| ... | ... | @@ -157,40 +157,6 @@ const MCValue = union(enum) { |
| 157 | 157 | condition_flags: Condition, |
| 158 | 158 | /// The value is a function argument passed via the stack. |
| 159 | 159 | stack_argument_offset: u32, |
| 160 | | |
| 161 | | fn isMemory(mcv: MCValue) bool { |
| 162 | | return switch (mcv) { |
| 163 | | .memory, .stack_offset, .stack_argument_offset => true, |
| 164 | | else => false, |
| 165 | | }; |
| 166 | | } |
| 167 | | |
| 168 | | fn isImmediate(mcv: MCValue) bool { |
| 169 | | return switch (mcv) { |
| 170 | | .immediate => true, |
| 171 | | else => false, |
| 172 | | }; |
| 173 | | } |
| 174 | | |
| 175 | | fn isMutable(mcv: MCValue) bool { |
| 176 | | return switch (mcv) { |
| 177 | | .none => unreachable, |
| 178 | | .unreach => unreachable, |
| 179 | | .dead => unreachable, |
| 180 | | |
| 181 | | .immediate, |
| 182 | | .memory, |
| 183 | | .condition_flags, |
| 184 | | .ptr_stack_offset, |
| 185 | | .undef, |
| 186 | | .stack_argument_offset, |
| 187 | | => false, |
| 188 | | |
| 189 | | .register, |
| 190 | | .stack_offset, |
| 191 | | => true, |
| 192 | | }; |
| 193 | | } |
| 194 | 160 | }; |
| 195 | 161 | |
| 196 | 162 | const Branch = struct { |
| ... | ... | @@ -416,9 +382,7 @@ fn gen(self: *Self) !void { |
| 416 | 382 | const ptr_bytes = @divExact(ptr_bits, 8); |
| 417 | 383 | const ret_ptr_reg = self.registerAlias(.x0, Type.usize); |
| 418 | 384 | |
| 419 | | const stack_offset = mem.alignForwardGeneric(u32, self.next_stack_offset, ptr_bytes) + ptr_bytes; |
| 420 | | self.next_stack_offset = stack_offset; |
| 421 | | self.max_end_stack = @max(self.max_end_stack, self.next_stack_offset); |
| 385 | const stack_offset = try self.allocMem(ptr_bytes, ptr_bytes, null); |
| 422 | 386 | |
| 423 | 387 | try self.genSetStack(Type.usize, stack_offset, MCValue{ .register = ret_ptr_reg }); |
| 424 | 388 | self.ret_mcv = MCValue{ .stack_offset = stack_offset }; |
| ... | ... | @@ -879,17 +843,30 @@ fn addDbgInfoTypeReloc(self: *Self, ty: Type) !void { |
| 879 | 843 | } |
| 880 | 844 | } |
| 881 | 845 | |
| 882 | | fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: u32) !u32 { |
| 846 | fn allocMem( |
| 847 | self: *Self, |
| 848 | abi_size: u32, |
| 849 | abi_align: u32, |
| 850 | maybe_inst: ?Air.Inst.Index, |
| 851 | ) !u32 { |
| 852 | assert(abi_size > 0); |
| 853 | assert(abi_align > 0); |
| 854 | |
| 883 | 855 | if (abi_align > self.stack_align) |
| 884 | 856 | self.stack_align = abi_align; |
| 857 | |
| 885 | 858 | // TODO find a free slot instead of always appending |
| 886 | 859 | const offset = mem.alignForwardGeneric(u32, self.next_stack_offset, abi_align) + abi_size; |
| 887 | 860 | self.next_stack_offset = offset; |
| 888 | 861 | self.max_end_stack = @max(self.max_end_stack, self.next_stack_offset); |
| 889 | | try self.stack.putNoClobber(self.gpa, offset, .{ |
| 890 | | .inst = inst, |
| 891 | | .size = abi_size, |
| 892 | | }); |
| 862 | |
| 863 | if (maybe_inst) |inst| { |
| 864 | try self.stack.putNoClobber(self.gpa, offset, .{ |
| 865 | .inst = inst, |
| 866 | .size = abi_size, |
| 867 | }); |
| 868 | } |
| 869 | |
| 893 | 870 | return offset; |
| 894 | 871 | } |
| 895 | 872 | |
| ... | ... | @@ -910,40 +887,41 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { |
| 910 | 887 | }; |
| 911 | 888 | // TODO swap this for inst.ty.ptrAlign |
| 912 | 889 | const abi_align = elem_ty.abiAlignment(self.target.*); |
| 913 | | return self.allocMem(inst, abi_size, abi_align); |
| 890 | |
| 891 | return self.allocMem(abi_size, abi_align, inst); |
| 914 | 892 | } |
| 915 | 893 | |
| 916 | | fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { |
| 917 | | const elem_ty = self.air.typeOfIndex(inst); |
| 894 | fn allocRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool, maybe_inst: ?Air.Inst.Index) !MCValue { |
| 918 | 895 | const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) orelse { |
| 919 | 896 | const mod = self.bin_file.options.module.?; |
| 920 | 897 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); |
| 921 | 898 | }; |
| 922 | 899 | const abi_align = elem_ty.abiAlignment(self.target.*); |
| 923 | | if (abi_align > self.stack_align) |
| 924 | | self.stack_align = abi_align; |
| 925 | 900 | |
| 926 | 901 | if (reg_ok) { |
| 927 | 902 | // Make sure the type can fit in a register before we try to allocate one. |
| 928 | 903 | if (abi_size <= 8) { |
| 929 | | if (self.register_manager.tryAllocReg(inst, gp)) |reg| { |
| 904 | if (self.register_manager.tryAllocReg(maybe_inst, gp)) |reg| { |
| 930 | 905 | return MCValue{ .register = self.registerAlias(reg, elem_ty) }; |
| 931 | 906 | } |
| 932 | 907 | } |
| 933 | 908 | } |
| 934 | | const stack_offset = try self.allocMem(inst, abi_size, abi_align); |
| 909 | |
| 910 | const stack_offset = try self.allocMem(abi_size, abi_align, maybe_inst); |
| 935 | 911 | return MCValue{ .stack_offset = stack_offset }; |
| 936 | 912 | } |
| 937 | 913 | |
| 938 | 914 | pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void { |
| 939 | | const stack_mcv = try self.allocRegOrMem(inst, false); |
| 915 | const stack_mcv = try self.allocRegOrMem(self.air.typeOfIndex(inst), false, inst); |
| 940 | 916 | log.debug("spilling {d} to stack mcv {any}", .{ inst, stack_mcv }); |
| 917 | |
| 941 | 918 | const reg_mcv = self.getResolvedInstValue(inst); |
| 942 | 919 | switch (reg_mcv) { |
| 943 | 920 | .register => |r| assert(reg.id() == r.id()), |
| 944 | 921 | .register_with_overflow => |rwo| assert(rwo.reg.id() == reg.id()), |
| 945 | 922 | else => unreachable, // not a register |
| 946 | 923 | } |
| 924 | |
| 947 | 925 | const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; |
| 948 | 926 | try branch.inst_table.put(self.gpa, inst, stack_mcv); |
| 949 | 927 | try self.genSetStack(self.air.typeOfIndex(inst), stack_mcv.stack_offset, reg_mcv); |
| ... | ... | @@ -953,10 +931,11 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void |
| 953 | 931 | /// occupied |
| 954 | 932 | fn spillCompareFlagsIfOccupied(self: *Self) !void { |
| 955 | 933 | if (self.condition_flags_inst) |inst_to_save| { |
| 934 | const ty = self.air.typeOfIndex(inst_to_save); |
| 956 | 935 | const mcv = self.getResolvedInstValue(inst_to_save); |
| 957 | 936 | const new_mcv = switch (mcv) { |
| 958 | | .condition_flags => try self.allocRegOrMem(inst_to_save, true), |
| 959 | | .register_with_overflow => try self.allocRegOrMem(inst_to_save, false), |
| 937 | .condition_flags => try self.allocRegOrMem(ty, true, inst_to_save), |
| 938 | .register_with_overflow => try self.allocRegOrMem(ty, false, inst_to_save), |
| 960 | 939 | else => unreachable, // mcv doesn't occupy the compare flags |
| 961 | 940 | }; |
| 962 | 941 | |
| ... | ... | @@ -1046,14 +1025,14 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { |
| 1046 | 1025 | }; |
| 1047 | 1026 | |
| 1048 | 1027 | if (dest_info.bits > operand_info.bits) { |
| 1049 | | const dest_mcv = try self.allocRegOrMem(inst, true); |
| 1028 | const dest_mcv = try self.allocRegOrMem(dest_ty, true, inst); |
| 1050 | 1029 | try self.setRegOrMem(self.air.typeOfIndex(inst), dest_mcv, truncated); |
| 1051 | 1030 | break :result dest_mcv; |
| 1052 | 1031 | } else { |
| 1053 | 1032 | if (self.reuseOperand(inst, operand, 0, truncated)) { |
| 1054 | 1033 | break :result truncated; |
| 1055 | 1034 | } else { |
| 1056 | | const dest_mcv = try self.allocRegOrMem(inst, true); |
| 1035 | const dest_mcv = try self.allocRegOrMem(dest_ty, true, inst); |
| 1057 | 1036 | try self.setRegOrMem(self.air.typeOfIndex(inst), dest_mcv, truncated); |
| 1058 | 1037 | break :result dest_mcv; |
| 1059 | 1038 | } |
| ... | ... | @@ -1278,7 +1257,7 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 1278 | 1257 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 1279 | 1258 | const ptr_bytes = @divExact(ptr_bits, 8); |
| 1280 | 1259 | |
| 1281 | | const stack_offset = try self.allocMem(inst, ptr_bytes * 2, ptr_bytes * 2); |
| 1260 | const stack_offset = try self.allocMem(ptr_bytes * 2, ptr_bytes * 2, inst); |
| 1282 | 1261 | try self.genSetStack(ptr_ty, stack_offset, ptr); |
| 1283 | 1262 | try self.genSetStack(len_ty, stack_offset - ptr_bytes, len); |
| 1284 | 1263 | break :result MCValue{ .stack_offset = stack_offset }; |
| ... | ... | @@ -2049,7 +2028,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2049 | 2028 | const int_info = lhs_ty.intInfo(self.target.*); |
| 2050 | 2029 | switch (int_info.bits) { |
| 2051 | 2030 | 1...31, 33...63 => { |
| 2052 | | const stack_offset = try self.allocMem(inst, tuple_size, tuple_align); |
| 2031 | const stack_offset = try self.allocMem(tuple_size, tuple_align, inst); |
| 2053 | 2032 | |
| 2054 | 2033 | try self.spillCompareFlagsIfOccupied(); |
| 2055 | 2034 | self.condition_flags_inst = null; |
| ... | ... | @@ -2164,7 +2143,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2164 | 2143 | const int_info = lhs_ty.intInfo(self.target.*); |
| 2165 | 2144 | |
| 2166 | 2145 | if (int_info.bits <= 32) { |
| 2167 | | const stack_offset = try self.allocMem(inst, tuple_size, tuple_align); |
| 2146 | const stack_offset = try self.allocMem(tuple_size, tuple_align, inst); |
| 2168 | 2147 | |
| 2169 | 2148 | try self.spillCompareFlagsIfOccupied(); |
| 2170 | 2149 | self.condition_flags_inst = null; |
| ... | ... | @@ -2220,7 +2199,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2220 | 2199 | |
| 2221 | 2200 | break :result MCValue{ .stack_offset = stack_offset }; |
| 2222 | 2201 | } else if (int_info.bits <= 64) { |
| 2223 | | const stack_offset = try self.allocMem(inst, tuple_size, tuple_align); |
| 2202 | const stack_offset = try self.allocMem(tuple_size, tuple_align, inst); |
| 2224 | 2203 | |
| 2225 | 2204 | try self.spillCompareFlagsIfOccupied(); |
| 2226 | 2205 | self.condition_flags_inst = null; |
| ... | ... | @@ -2424,7 +2403,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2424 | 2403 | .Int => { |
| 2425 | 2404 | const int_info = lhs_ty.intInfo(self.target.*); |
| 2426 | 2405 | if (int_info.bits <= 64) { |
| 2427 | | const stack_offset = try self.allocMem(inst, tuple_size, tuple_align); |
| 2406 | const stack_offset = try self.allocMem(tuple_size, tuple_align, inst); |
| 2428 | 2407 | |
| 2429 | 2408 | const lhs_lock: ?RegisterLock = if (lhs == .register) |
| 2430 | 2409 | self.register_manager.lockRegAssumeUnused(lhs.register) |
| ... | ... | @@ -2745,7 +2724,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2745 | 2724 | const base_reg_lock = self.register_manager.lockRegAssumeUnused(base_reg); |
| 2746 | 2725 | defer self.register_manager.unlockReg(base_reg_lock); |
| 2747 | 2726 | |
| 2748 | | const dest = try self.allocRegOrMem(inst, true); |
| 2727 | const dest = try self.allocRegOrMem(elem_ty, true, inst); |
| 2749 | 2728 | const addr = try self.binOp(.ptr_add, base_mcv, index_mcv, slice_ptr_field_type, Type.usize, null); |
| 2750 | 2729 | try self.load(dest, addr, slice_ptr_field_type); |
| 2751 | 2730 | |
| ... | ... | @@ -3058,7 +3037,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 3058 | 3037 | else => ptr, |
| 3059 | 3038 | }; |
| 3060 | 3039 | } else { |
| 3061 | | break :blk try self.allocRegOrMem(inst, true); |
| 3040 | break :blk try self.allocRegOrMem(elem_ty, true, inst); |
| 3062 | 3041 | } |
| 3063 | 3042 | }; |
| 3064 | 3043 | try self.load(dst_mcv, ptr, self.air.typeOf(ty_op.operand)); |
| ... | ... | @@ -3334,7 +3313,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 3334 | 3313 | return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(mod)}); |
| 3335 | 3314 | }; |
| 3336 | 3315 | const abi_align = ty.abiAlignment(self.target.*); |
| 3337 | | const stack_offset = try self.allocMem(inst, abi_size, abi_align); |
| 3316 | const stack_offset = try self.allocMem(abi_size, abi_align, inst); |
| 3338 | 3317 | try self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); |
| 3339 | 3318 | |
| 3340 | 3319 | break :blk MCValue{ .stack_offset = stack_offset }; |
| ... | ... | @@ -3412,7 +3391,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 3412 | 3391 | const ret_ty = fn_ty.fnReturnType(); |
| 3413 | 3392 | const ret_abi_size = @intCast(u32, ret_ty.abiSize(self.target.*)); |
| 3414 | 3393 | const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(self.target.*)); |
| 3415 | | const stack_offset = try self.allocMem(inst, ret_abi_size, ret_abi_align); |
| 3394 | const stack_offset = try self.allocMem(ret_abi_size, ret_abi_align, inst); |
| 3416 | 3395 | |
| 3417 | 3396 | const ret_ptr_reg = self.registerAlias(.x0, Type.usize); |
| 3418 | 3397 | |
| ... | ... | @@ -3638,14 +3617,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 3638 | 3617 | const abi_size = @intCast(u32, ret_ty.abiSize(self.target.*)); |
| 3639 | 3618 | const abi_align = ret_ty.abiAlignment(self.target.*); |
| 3640 | 3619 | |
| 3641 | | // This is essentially allocMem without the |
| 3642 | | // instruction tracking |
| 3643 | | if (abi_align > self.stack_align) |
| 3644 | | self.stack_align = abi_align; |
| 3645 | | // TODO find a free slot instead of always appending |
| 3646 | | const offset = mem.alignForwardGeneric(u32, self.next_stack_offset, abi_align) + abi_size; |
| 3647 | | self.next_stack_offset = offset; |
| 3648 | | self.max_end_stack = @max(self.max_end_stack, self.next_stack_offset); |
| 3620 | const offset = try self.allocMem(abi_size, abi_align, null); |
| 3649 | 3621 | |
| 3650 | 3622 | const tmp_mcv = MCValue{ .stack_offset = offset }; |
| 3651 | 3623 | try self.load(tmp_mcv, ptr, ptr_ty); |
| ... | ... | @@ -3993,15 +3965,12 @@ fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 3993 | 3965 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 3994 | 3966 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 3995 | 3967 | const operand_ptr = try self.resolveInst(un_op); |
| 3996 | | const operand: MCValue = blk: { |
| 3997 | | if (self.reuseOperand(inst, un_op, 0, operand_ptr)) { |
| 3998 | | // The MCValue that holds the pointer can be re-used as the value. |
| 3999 | | break :blk operand_ptr; |
| 4000 | | } else { |
| 4001 | | break :blk try self.allocRegOrMem(inst, true); |
| 4002 | | } |
| 4003 | | }; |
| 4004 | | try self.load(operand, operand_ptr, self.air.typeOf(un_op)); |
| 3968 | const ptr_ty = self.air.typeOf(un_op); |
| 3969 | const elem_ty = ptr_ty.elemType(); |
| 3970 | |
| 3971 | const operand = try self.allocRegOrMem(elem_ty, true, null); |
| 3972 | try self.load(operand, operand_ptr, ptr_ty); |
| 3973 | |
| 4005 | 3974 | break :result try self.isNull(operand); |
| 4006 | 3975 | }; |
| 4007 | 3976 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| ... | ... | @@ -4020,15 +3989,12 @@ fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 4020 | 3989 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 4021 | 3990 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 4022 | 3991 | const operand_ptr = try self.resolveInst(un_op); |
| 4023 | | const operand: MCValue = blk: { |
| 4024 | | if (self.reuseOperand(inst, un_op, 0, operand_ptr)) { |
| 4025 | | // The MCValue that holds the pointer can be re-used as the value. |
| 4026 | | break :blk operand_ptr; |
| 4027 | | } else { |
| 4028 | | break :blk try self.allocRegOrMem(inst, true); |
| 4029 | | } |
| 4030 | | }; |
| 4031 | | try self.load(operand, operand_ptr, self.air.typeOf(un_op)); |
| 3992 | const ptr_ty = self.air.typeOf(un_op); |
| 3993 | const elem_ty = ptr_ty.elemType(); |
| 3994 | |
| 3995 | const operand = try self.allocRegOrMem(elem_ty, true, null); |
| 3996 | try self.load(operand, operand_ptr, ptr_ty); |
| 3997 | |
| 4032 | 3998 | break :result try self.isNonNull(operand); |
| 4033 | 3999 | }; |
| 4034 | 4000 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| ... | ... | @@ -4049,16 +4015,12 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 4049 | 4015 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 4050 | 4016 | const operand_ptr = try self.resolveInst(un_op); |
| 4051 | 4017 | const ptr_ty = self.air.typeOf(un_op); |
| 4052 | | const operand: MCValue = blk: { |
| 4053 | | if (self.reuseOperand(inst, un_op, 0, operand_ptr)) { |
| 4054 | | // The MCValue that holds the pointer can be re-used as the value. |
| 4055 | | break :blk operand_ptr; |
| 4056 | | } else { |
| 4057 | | break :blk try self.allocRegOrMem(inst, true); |
| 4058 | | } |
| 4059 | | }; |
| 4060 | | try self.load(operand, operand_ptr, self.air.typeOf(un_op)); |
| 4061 | | break :result try self.isErr(ptr_ty.elemType(), operand); |
| 4018 | const elem_ty = ptr_ty.elemType(); |
| 4019 | |
| 4020 | const operand = try self.allocRegOrMem(elem_ty, true, null); |
| 4021 | try self.load(operand, operand_ptr, ptr_ty); |
| 4022 | |
| 4023 | break :result try self.isErr(elem_ty, operand); |
| 4062 | 4024 | }; |
| 4063 | 4025 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| 4064 | 4026 | } |
| ... | ... | @@ -4078,16 +4040,12 @@ fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 4078 | 4040 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 4079 | 4041 | const operand_ptr = try self.resolveInst(un_op); |
| 4080 | 4042 | const ptr_ty = self.air.typeOf(un_op); |
| 4081 | | const operand: MCValue = blk: { |
| 4082 | | if (self.reuseOperand(inst, un_op, 0, operand_ptr)) { |
| 4083 | | // The MCValue that holds the pointer can be re-used as the value. |
| 4084 | | break :blk operand_ptr; |
| 4085 | | } else { |
| 4086 | | break :blk try self.allocRegOrMem(inst, true); |
| 4087 | | } |
| 4088 | | }; |
| 4089 | | try self.load(operand, operand_ptr, self.air.typeOf(un_op)); |
| 4090 | | break :result try self.isNonErr(ptr_ty.elemType(), operand); |
| 4043 | const elem_ty = ptr_ty.elemType(); |
| 4044 | |
| 4045 | const operand = try self.allocRegOrMem(elem_ty, true, null); |
| 4046 | try self.load(operand, operand_ptr, ptr_ty); |
| 4047 | |
| 4048 | break :result try self.isNonErr(elem_ty, operand); |
| 4091 | 4049 | }; |
| 4092 | 4050 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| 4093 | 4051 | } |
| ... | ... | @@ -4180,7 +4138,7 @@ fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void { |
| 4180 | 4138 | .none, .dead, .unreach => unreachable, |
| 4181 | 4139 | .register, .stack_offset, .memory => operand_mcv, |
| 4182 | 4140 | .immediate, .stack_argument_offset, .condition_flags => blk: { |
| 4183 | | const new_mcv = try self.allocRegOrMem(block, true); |
| 4141 | const new_mcv = try self.allocRegOrMem(self.air.typeOfIndex(block), true, block); |
| 4184 | 4142 | try self.setRegOrMem(self.air.typeOfIndex(block), new_mcv, operand_mcv); |
| 4185 | 4143 | break :blk new_mcv; |
| 4186 | 4144 | }, |
| ... | ... | @@ -4837,7 +4795,7 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 4837 | 4795 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 4838 | 4796 | const ptr_bytes = @divExact(ptr_bits, 8); |
| 4839 | 4797 | |
| 4840 | | const stack_offset = try self.allocMem(inst, ptr_bytes * 2, ptr_bytes * 2); |
| 4798 | const stack_offset = try self.allocMem(ptr_bytes * 2, ptr_bytes * 2, inst); |
| 4841 | 4799 | try self.genSetStack(ptr_ty, stack_offset, ptr); |
| 4842 | 4800 | try self.genSetStack(Type.initTag(.usize), stack_offset - ptr_bytes, .{ .immediate = array_len }); |
| 4843 | 4801 | break :result MCValue{ .stack_offset = stack_offset }; |