| ... | @@ -157,40 +157,6 @@ const MCValue = union(enum) { | ... | @@ -157,40 +157,6 @@ const MCValue = union(enum) { |
| 157 | condition_flags: Condition, | 157 | condition_flags: Condition, |
| 158 | /// The value is a function argument passed via the stack. | 158 | /// The value is a function argument passed via the stack. |
| 159 | stack_argument_offset: u32, | 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 | const Branch = struct { | 162 | const Branch = struct { |
| ... | @@ -416,9 +382,7 @@ fn gen(self: *Self) !void { | ... | @@ -416,9 +382,7 @@ fn gen(self: *Self) !void { |
| 416 | const ptr_bytes = @divExact(ptr_bits, 8); | 382 | const ptr_bytes = @divExact(ptr_bits, 8); |
| 417 | const ret_ptr_reg = self.registerAlias(.x0, Type.usize); | 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; | 385 | const stack_offset = try self.allocMem(ptr_bytes, ptr_bytes, null); |
| 420 | self.next_stack_offset = stack_offset; | | |
| 421 | self.max_end_stack = @max(self.max_end_stack, self.next_stack_offset); | | |
| 422 | | 386 | |
| 423 | try self.genSetStack(Type.usize, stack_offset, MCValue{ .register = ret_ptr_reg }); | 387 | try self.genSetStack(Type.usize, stack_offset, MCValue{ .register = ret_ptr_reg }); |
| 424 | self.ret_mcv = MCValue{ .stack_offset = stack_offset }; | 388 | self.ret_mcv = MCValue{ .stack_offset = stack_offset }; |
| ... | @@ -879,17 +843,30 @@ fn addDbgInfoTypeReloc(self: *Self, ty: Type) !void { | ... | @@ -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 | if (abi_align > self.stack_align) | 855 | if (abi_align > self.stack_align) |
| 884 | self.stack_align = abi_align; | 856 | self.stack_align = abi_align; |
| | 857 | |
| 885 | // TODO find a free slot instead of always appending | 858 | // TODO find a free slot instead of always appending |
| 886 | const offset = mem.alignForwardGeneric(u32, self.next_stack_offset, abi_align) + abi_size; | 859 | const offset = mem.alignForwardGeneric(u32, self.next_stack_offset, abi_align) + abi_size; |
| 887 | self.next_stack_offset = offset; | 860 | self.next_stack_offset = offset; |
| 888 | self.max_end_stack = @max(self.max_end_stack, self.next_stack_offset); | 861 | self.max_end_stack = @max(self.max_end_stack, self.next_stack_offset); |
| 889 | try self.stack.putNoClobber(self.gpa, offset, .{ | 862 | |
| 890 | .inst = inst, | 863 | if (maybe_inst) |inst| { |
| 891 | .size = abi_size, | 864 | try self.stack.putNoClobber(self.gpa, offset, .{ |
| 892 | }); | 865 | .inst = inst, |
| | 866 | .size = abi_size, |
| | 867 | }); |
| | 868 | } |
| | 869 | |
| 893 | return offset; | 870 | return offset; |
| 894 | } | 871 | } |
| 895 | | 872 | |
| ... | @@ -910,40 +887,41 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { | ... | @@ -910,40 +887,41 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { |
| 910 | }; | 887 | }; |
| 911 | // TODO swap this for inst.ty.ptrAlign | 888 | // TODO swap this for inst.ty.ptrAlign |
| 912 | const abi_align = elem_ty.abiAlignment(self.target.*); | 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 { | 894 | fn allocRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool, maybe_inst: ?Air.Inst.Index) !MCValue { |
| 917 | const elem_ty = self.air.typeOfIndex(inst); | | |
| 918 | const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) orelse { | 895 | const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) orelse { |
| 919 | const mod = self.bin_file.options.module.?; | 896 | const mod = self.bin_file.options.module.?; |
| 920 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); | 897 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); |
| 921 | }; | 898 | }; |
| 922 | const abi_align = elem_ty.abiAlignment(self.target.*); | 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 | if (reg_ok) { | 901 | if (reg_ok) { |
| 927 | // Make sure the type can fit in a register before we try to allocate one. | 902 | // Make sure the type can fit in a register before we try to allocate one. |
| 928 | if (abi_size <= 8) { | 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 | return MCValue{ .register = self.registerAlias(reg, elem_ty) }; | 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 | return MCValue{ .stack_offset = stack_offset }; | 911 | return MCValue{ .stack_offset = stack_offset }; |
| 936 | } | 912 | } |
| 937 | | 913 | |
| 938 | pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void { | 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 | log.debug("spilling {d} to stack mcv {any}", .{ inst, stack_mcv }); | 916 | log.debug("spilling {d} to stack mcv {any}", .{ inst, stack_mcv }); |
| | 917 | |
| 941 | const reg_mcv = self.getResolvedInstValue(inst); | 918 | const reg_mcv = self.getResolvedInstValue(inst); |
| 942 | switch (reg_mcv) { | 919 | switch (reg_mcv) { |
| 943 | .register => |r| assert(reg.id() == r.id()), | 920 | .register => |r| assert(reg.id() == r.id()), |
| 944 | .register_with_overflow => |rwo| assert(rwo.reg.id() == reg.id()), | 921 | .register_with_overflow => |rwo| assert(rwo.reg.id() == reg.id()), |
| 945 | else => unreachable, // not a register | 922 | else => unreachable, // not a register |
| 946 | } | 923 | } |
| | 924 | |
| 947 | const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; | 925 | const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; |
| 948 | try branch.inst_table.put(self.gpa, inst, stack_mcv); | 926 | try branch.inst_table.put(self.gpa, inst, stack_mcv); |
| 949 | try self.genSetStack(self.air.typeOfIndex(inst), stack_mcv.stack_offset, reg_mcv); | 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,10 +931,11 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void |
| 953 | /// occupied | 931 | /// occupied |
| 954 | fn spillCompareFlagsIfOccupied(self: *Self) !void { | 932 | fn spillCompareFlagsIfOccupied(self: *Self) !void { |
| 955 | if (self.condition_flags_inst) |inst_to_save| { | 933 | if (self.condition_flags_inst) |inst_to_save| { |
| | 934 | const ty = self.air.typeOfIndex(inst_to_save); |
| 956 | const mcv = self.getResolvedInstValue(inst_to_save); | 935 | const mcv = self.getResolvedInstValue(inst_to_save); |
| 957 | const new_mcv = switch (mcv) { | 936 | const new_mcv = switch (mcv) { |
| 958 | .condition_flags => try self.allocRegOrMem(inst_to_save, true), | 937 | .condition_flags => try self.allocRegOrMem(ty, true, inst_to_save), |
| 959 | .register_with_overflow => try self.allocRegOrMem(inst_to_save, false), | 938 | .register_with_overflow => try self.allocRegOrMem(ty, false, inst_to_save), |
| 960 | else => unreachable, // mcv doesn't occupy the compare flags | 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,14 +1025,14 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { |
| 1046 | }; | 1025 | }; |
| 1047 | | 1026 | |
| 1048 | if (dest_info.bits > operand_info.bits) { | 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 | try self.setRegOrMem(self.air.typeOfIndex(inst), dest_mcv, truncated); | 1029 | try self.setRegOrMem(self.air.typeOfIndex(inst), dest_mcv, truncated); |
| 1051 | break :result dest_mcv; | 1030 | break :result dest_mcv; |
| 1052 | } else { | 1031 | } else { |
| 1053 | if (self.reuseOperand(inst, operand, 0, truncated)) { | 1032 | if (self.reuseOperand(inst, operand, 0, truncated)) { |
| 1054 | break :result truncated; | 1033 | break :result truncated; |
| 1055 | } else { | 1034 | } else { |
| 1056 | const dest_mcv = try self.allocRegOrMem(inst, true); | 1035 | const dest_mcv = try self.allocRegOrMem(dest_ty, true, inst); |
| 1057 | try self.setRegOrMem(self.air.typeOfIndex(inst), dest_mcv, truncated); | 1036 | try self.setRegOrMem(self.air.typeOfIndex(inst), dest_mcv, truncated); |
| 1058 | break :result dest_mcv; | 1037 | break :result dest_mcv; |
| 1059 | } | 1038 | } |
| ... | @@ -1278,7 +1257,7 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1278,7 +1257,7 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 1278 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); | 1257 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 1279 | const ptr_bytes = @divExact(ptr_bits, 8); | 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 | try self.genSetStack(ptr_ty, stack_offset, ptr); | 1261 | try self.genSetStack(ptr_ty, stack_offset, ptr); |
| 1283 | try self.genSetStack(len_ty, stack_offset - ptr_bytes, len); | 1262 | try self.genSetStack(len_ty, stack_offset - ptr_bytes, len); |
| 1284 | break :result MCValue{ .stack_offset = stack_offset }; | 1263 | break :result MCValue{ .stack_offset = stack_offset }; |
| ... | @@ -2049,7 +2028,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2049,7 +2028,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2049 | const int_info = lhs_ty.intInfo(self.target.*); | 2028 | const int_info = lhs_ty.intInfo(self.target.*); |
| 2050 | switch (int_info.bits) { | 2029 | switch (int_info.bits) { |
| 2051 | 1...31, 33...63 => { | 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 | try self.spillCompareFlagsIfOccupied(); | 2033 | try self.spillCompareFlagsIfOccupied(); |
| 2055 | self.condition_flags_inst = null; | 2034 | self.condition_flags_inst = null; |
| ... | @@ -2164,7 +2143,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2164,7 +2143,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2164 | const int_info = lhs_ty.intInfo(self.target.*); | 2143 | const int_info = lhs_ty.intInfo(self.target.*); |
| 2165 | | 2144 | |
| 2166 | if (int_info.bits <= 32) { | 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 | try self.spillCompareFlagsIfOccupied(); | 2148 | try self.spillCompareFlagsIfOccupied(); |
| 2170 | self.condition_flags_inst = null; | 2149 | self.condition_flags_inst = null; |
| ... | @@ -2220,7 +2199,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2220,7 +2199,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2220 | | 2199 | |
| 2221 | break :result MCValue{ .stack_offset = stack_offset }; | 2200 | break :result MCValue{ .stack_offset = stack_offset }; |
| 2222 | } else if (int_info.bits <= 64) { | 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 | try self.spillCompareFlagsIfOccupied(); | 2204 | try self.spillCompareFlagsIfOccupied(); |
| 2226 | self.condition_flags_inst = null; | 2205 | self.condition_flags_inst = null; |
| ... | @@ -2424,7 +2403,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2424,7 +2403,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2424 | .Int => { | 2403 | .Int => { |
| 2425 | const int_info = lhs_ty.intInfo(self.target.*); | 2404 | const int_info = lhs_ty.intInfo(self.target.*); |
| 2426 | if (int_info.bits <= 64) { | 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 | const lhs_lock: ?RegisterLock = if (lhs == .register) | 2408 | const lhs_lock: ?RegisterLock = if (lhs == .register) |
| 2430 | self.register_manager.lockRegAssumeUnused(lhs.register) | 2409 | self.register_manager.lockRegAssumeUnused(lhs.register) |
| ... | @@ -2745,7 +2724,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2745,7 +2724,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2745 | const base_reg_lock = self.register_manager.lockRegAssumeUnused(base_reg); | 2724 | const base_reg_lock = self.register_manager.lockRegAssumeUnused(base_reg); |
| 2746 | defer self.register_manager.unlockReg(base_reg_lock); | 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 | const addr = try self.binOp(.ptr_add, base_mcv, index_mcv, slice_ptr_field_type, Type.usize, null); | 2728 | const addr = try self.binOp(.ptr_add, base_mcv, index_mcv, slice_ptr_field_type, Type.usize, null); |
| 2750 | try self.load(dest, addr, slice_ptr_field_type); | 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,7 +3037,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 3058 | else => ptr, | 3037 | else => ptr, |
| 3059 | }; | 3038 | }; |
| 3060 | } else { | 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 | try self.load(dst_mcv, ptr, self.air.typeOf(ty_op.operand)); | 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,7 +3313,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 3334 | return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(mod)}); | 3313 | return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(mod)}); |
| 3335 | }; | 3314 | }; |
| 3336 | const abi_align = ty.abiAlignment(self.target.*); | 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 | try self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); | 3317 | try self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); |
| 3339 | | 3318 | |
| 3340 | break :blk MCValue{ .stack_offset = stack_offset }; | 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,7 +3391,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 3412 | const ret_ty = fn_ty.fnReturnType(); | 3391 | const ret_ty = fn_ty.fnReturnType(); |
| 3413 | const ret_abi_size = @intCast(u32, ret_ty.abiSize(self.target.*)); | 3392 | const ret_abi_size = @intCast(u32, ret_ty.abiSize(self.target.*)); |
| 3414 | const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(self.target.*)); | 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 | const ret_ptr_reg = self.registerAlias(.x0, Type.usize); | 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,14 +3617,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 3638 | const abi_size = @intCast(u32, ret_ty.abiSize(self.target.*)); | 3617 | const abi_size = @intCast(u32, ret_ty.abiSize(self.target.*)); |
| 3639 | const abi_align = ret_ty.abiAlignment(self.target.*); | 3618 | const abi_align = ret_ty.abiAlignment(self.target.*); |
| 3640 | | 3619 | |
| 3641 | // This is essentially allocMem without the | 3620 | const offset = try self.allocMem(abi_size, abi_align, null); |
| 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); | | |
| 3649 | | 3621 | |
| 3650 | const tmp_mcv = MCValue{ .stack_offset = offset }; | 3622 | const tmp_mcv = MCValue{ .stack_offset = offset }; |
| 3651 | try self.load(tmp_mcv, ptr, ptr_ty); | 3623 | try self.load(tmp_mcv, ptr, ptr_ty); |
| ... | @@ -3993,15 +3965,12 @@ fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3993,15 +3965,12 @@ fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 3993 | const un_op = self.air.instructions.items(.data)[inst].un_op; | 3965 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 3994 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 3966 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 3995 | const operand_ptr = try self.resolveInst(un_op); | 3967 | const operand_ptr = try self.resolveInst(un_op); |
| 3996 | const operand: MCValue = blk: { | 3968 | const ptr_ty = self.air.typeOf(un_op); |
| 3997 | if (self.reuseOperand(inst, un_op, 0, operand_ptr)) { | 3969 | const elem_ty = ptr_ty.elemType(); |
| 3998 | // The MCValue that holds the pointer can be re-used as the value. | 3970 | |
| 3999 | break :blk operand_ptr; | 3971 | const operand = try self.allocRegOrMem(elem_ty, true, null); |
| 4000 | } else { | 3972 | try self.load(operand, operand_ptr, ptr_ty); |
| 4001 | break :blk try self.allocRegOrMem(inst, true); | 3973 | |
| 4002 | } | | |
| 4003 | }; | | |
| 4004 | try self.load(operand, operand_ptr, self.air.typeOf(un_op)); | | |
| 4005 | break :result try self.isNull(operand); | 3974 | break :result try self.isNull(operand); |
| 4006 | }; | 3975 | }; |
| 4007 | return self.finishAir(inst, result, .{ un_op, .none, .none }); | 3976 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| ... | @@ -4020,15 +3989,12 @@ fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4020,15 +3989,12 @@ fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 4020 | const un_op = self.air.instructions.items(.data)[inst].un_op; | 3989 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 4021 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 3990 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 4022 | const operand_ptr = try self.resolveInst(un_op); | 3991 | const operand_ptr = try self.resolveInst(un_op); |
| 4023 | const operand: MCValue = blk: { | 3992 | const ptr_ty = self.air.typeOf(un_op); |
| 4024 | if (self.reuseOperand(inst, un_op, 0, operand_ptr)) { | 3993 | const elem_ty = ptr_ty.elemType(); |
| 4025 | // The MCValue that holds the pointer can be re-used as the value. | 3994 | |
| 4026 | break :blk operand_ptr; | 3995 | const operand = try self.allocRegOrMem(elem_ty, true, null); |
| 4027 | } else { | 3996 | try self.load(operand, operand_ptr, ptr_ty); |
| 4028 | break :blk try self.allocRegOrMem(inst, true); | 3997 | |
| 4029 | } | | |
| 4030 | }; | | |
| 4031 | try self.load(operand, operand_ptr, self.air.typeOf(un_op)); | | |
| 4032 | break :result try self.isNonNull(operand); | 3998 | break :result try self.isNonNull(operand); |
| 4033 | }; | 3999 | }; |
| 4034 | return self.finishAir(inst, result, .{ un_op, .none, .none }); | 4000 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| ... | @@ -4049,16 +4015,12 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4049,16 +4015,12 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 4049 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 4015 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 4050 | const operand_ptr = try self.resolveInst(un_op); | 4016 | const operand_ptr = try self.resolveInst(un_op); |
| 4051 | const ptr_ty = self.air.typeOf(un_op); | 4017 | const ptr_ty = self.air.typeOf(un_op); |
| 4052 | const operand: MCValue = blk: { | 4018 | const elem_ty = ptr_ty.elemType(); |
| 4053 | if (self.reuseOperand(inst, un_op, 0, operand_ptr)) { | 4019 | |
| 4054 | // The MCValue that holds the pointer can be re-used as the value. | 4020 | const operand = try self.allocRegOrMem(elem_ty, true, null); |
| 4055 | break :blk operand_ptr; | 4021 | try self.load(operand, operand_ptr, ptr_ty); |
| 4056 | } else { | 4022 | |
| 4057 | break :blk try self.allocRegOrMem(inst, true); | 4023 | break :result try self.isErr(elem_ty, operand); |
| 4058 | } | | |
| 4059 | }; | | |
| 4060 | try self.load(operand, operand_ptr, self.air.typeOf(un_op)); | | |
| 4061 | break :result try self.isErr(ptr_ty.elemType(), operand); | | |
| 4062 | }; | 4024 | }; |
| 4063 | return self.finishAir(inst, result, .{ un_op, .none, .none }); | 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,16 +4040,12 @@ fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 4078 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 4040 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 4079 | const operand_ptr = try self.resolveInst(un_op); | 4041 | const operand_ptr = try self.resolveInst(un_op); |
| 4080 | const ptr_ty = self.air.typeOf(un_op); | 4042 | const ptr_ty = self.air.typeOf(un_op); |
| 4081 | const operand: MCValue = blk: { | 4043 | const elem_ty = ptr_ty.elemType(); |
| 4082 | if (self.reuseOperand(inst, un_op, 0, operand_ptr)) { | 4044 | |
| 4083 | // The MCValue that holds the pointer can be re-used as the value. | 4045 | const operand = try self.allocRegOrMem(elem_ty, true, null); |
| 4084 | break :blk operand_ptr; | 4046 | try self.load(operand, operand_ptr, ptr_ty); |
| 4085 | } else { | 4047 | |
| 4086 | break :blk try self.allocRegOrMem(inst, true); | 4048 | break :result try self.isNonErr(elem_ty, operand); |
| 4087 | } | | |
| 4088 | }; | | |
| 4089 | try self.load(operand, operand_ptr, self.air.typeOf(un_op)); | | |
| 4090 | break :result try self.isNonErr(ptr_ty.elemType(), operand); | | |
| 4091 | }; | 4049 | }; |
| 4092 | return self.finishAir(inst, result, .{ un_op, .none, .none }); | 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,7 +4138,7 @@ fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void { |
| 4180 | .none, .dead, .unreach => unreachable, | 4138 | .none, .dead, .unreach => unreachable, |
| 4181 | .register, .stack_offset, .memory => operand_mcv, | 4139 | .register, .stack_offset, .memory => operand_mcv, |
| 4182 | .immediate, .stack_argument_offset, .condition_flags => blk: { | 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 | try self.setRegOrMem(self.air.typeOfIndex(block), new_mcv, operand_mcv); | 4142 | try self.setRegOrMem(self.air.typeOfIndex(block), new_mcv, operand_mcv); |
| 4185 | break :blk new_mcv; | 4143 | break :blk new_mcv; |
| 4186 | }, | 4144 | }, |
| ... | @@ -4837,7 +4795,7 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4837,7 +4795,7 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 4837 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); | 4795 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 4838 | const ptr_bytes = @divExact(ptr_bits, 8); | 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 | try self.genSetStack(ptr_ty, stack_offset, ptr); | 4799 | try self.genSetStack(ptr_ty, stack_offset, ptr); |
| 4842 | try self.genSetStack(Type.initTag(.usize), stack_offset - ptr_bytes, .{ .immediate = array_len }); | 4800 | try self.genSetStack(Type.initTag(.usize), stack_offset - ptr_bytes, .{ .immediate = array_len }); |
| 4843 | break :result MCValue{ .stack_offset = stack_offset }; | 4801 | break :result MCValue{ .stack_offset = stack_offset }; |