| ... | ... | @@ -936,35 +936,34 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { |
| 936 | 936 | }; |
| 937 | 937 | // TODO swap this for inst.ty.ptrAlign |
| 938 | 938 | const abi_align = elem_ty.abiAlignment(self.target.*); |
| 939 | |
| 939 | 940 | return self.allocMem(abi_size, abi_align, inst); |
| 940 | 941 | } |
| 941 | 942 | |
| 942 | | fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { |
| 943 | | const elem_ty = self.air.typeOfIndex(inst); |
| 943 | fn allocRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool, maybe_inst: ?Air.Inst.Index) !MCValue { |
| 944 | 944 | const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) orelse { |
| 945 | 945 | const mod = self.bin_file.options.module.?; |
| 946 | 946 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); |
| 947 | 947 | }; |
| 948 | 948 | const abi_align = elem_ty.abiAlignment(self.target.*); |
| 949 | | if (abi_align > self.stack_align) |
| 950 | | self.stack_align = abi_align; |
| 951 | 949 | |
| 952 | 950 | if (reg_ok) { |
| 953 | 951 | // Make sure the type can fit in a register before we try to allocate one. |
| 954 | 952 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 955 | 953 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 956 | 954 | if (abi_size <= ptr_bytes) { |
| 957 | | if (self.register_manager.tryAllocReg(inst, gp)) |reg| { |
| 955 | if (self.register_manager.tryAllocReg(maybe_inst, gp)) |reg| { |
| 958 | 956 | return MCValue{ .register = reg }; |
| 959 | 957 | } |
| 960 | 958 | } |
| 961 | 959 | } |
| 962 | | const stack_offset = try self.allocMem(abi_size, abi_align, inst); |
| 960 | |
| 961 | const stack_offset = try self.allocMem(abi_size, abi_align, maybe_inst); |
| 963 | 962 | return MCValue{ .stack_offset = stack_offset }; |
| 964 | 963 | } |
| 965 | 964 | |
| 966 | 965 | pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void { |
| 967 | | const stack_mcv = try self.allocRegOrMem(inst, false); |
| 966 | const stack_mcv = try self.allocRegOrMem(self.air.typeOfIndex(inst), false, inst); |
| 968 | 967 | log.debug("spilling {} (%{d}) to stack mcv {any}", .{ reg, inst, stack_mcv }); |
| 969 | 968 | |
| 970 | 969 | const reg_mcv = self.getResolvedInstValue(inst); |
| ... | ... | @@ -985,12 +984,13 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void |
| 985 | 984 | /// occupied |
| 986 | 985 | fn spillCompareFlagsIfOccupied(self: *Self) !void { |
| 987 | 986 | if (self.cpsr_flags_inst) |inst_to_save| { |
| 987 | const ty = self.air.typeOfIndex(inst_to_save); |
| 988 | 988 | const mcv = self.getResolvedInstValue(inst_to_save); |
| 989 | 989 | const new_mcv = switch (mcv) { |
| 990 | | .cpsr_flags => try self.allocRegOrMem(inst_to_save, true), |
| 990 | .cpsr_flags => try self.allocRegOrMem(ty, true, inst_to_save), |
| 991 | 991 | .register_c_flag, |
| 992 | 992 | .register_v_flag, |
| 993 | | => try self.allocRegOrMem(inst_to_save, false), |
| 993 | => try self.allocRegOrMem(ty, false, inst_to_save), |
| 994 | 994 | else => unreachable, // mcv doesn't occupy the compare flags |
| 995 | 995 | }; |
| 996 | 996 | |
| ... | ... | @@ -1121,10 +1121,11 @@ fn truncRegister( |
| 1121 | 1121 | }); |
| 1122 | 1122 | } |
| 1123 | 1123 | |
| 1124 | /// Asserts that both operand_ty and dest_ty are integer types |
| 1124 | 1125 | fn trunc( |
| 1125 | 1126 | self: *Self, |
| 1126 | 1127 | maybe_inst: ?Air.Inst.Index, |
| 1127 | | operand: MCValue, |
| 1128 | operand_bind: ReadArg.Bind, |
| 1128 | 1129 | operand_ty: Type, |
| 1129 | 1130 | dest_ty: Type, |
| 1130 | 1131 | ) !MCValue { |
| ... | ... | @@ -1132,39 +1133,38 @@ fn trunc( |
| 1132 | 1133 | const info_b = dest_ty.intInfo(self.target.*); |
| 1133 | 1134 | |
| 1134 | 1135 | if (info_b.bits <= 32) { |
| 1135 | | const operand_reg = switch (operand) { |
| 1136 | | .register => |r| r, |
| 1137 | | else => operand_reg: { |
| 1138 | | if (info_a.bits <= 32) { |
| 1139 | | break :operand_reg try self.copyToTmpRegister(operand_ty, operand); |
| 1140 | | } else { |
| 1141 | | return self.fail("TODO load least significant word into register", .{}); |
| 1142 | | } |
| 1143 | | }, |
| 1144 | | }; |
| 1145 | | const operand_reg_lock = self.register_manager.lockReg(operand_reg); |
| 1146 | | defer if (operand_reg_lock) |reg| self.register_manager.unlockReg(reg); |
| 1136 | if (info_a.bits > 32) { |
| 1137 | return self.fail("TODO load least significant word into register", .{}); |
| 1138 | } |
| 1147 | 1139 | |
| 1148 | | const dest_reg = if (maybe_inst) |inst| blk: { |
| 1149 | | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1140 | var operand_reg: Register = undefined; |
| 1141 | var dest_reg: Register = undefined; |
| 1150 | 1142 | |
| 1151 | | if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) { |
| 1152 | | break :blk operand_reg; |
| 1153 | | } else { |
| 1154 | | break :blk try self.register_manager.allocReg(inst, gp); |
| 1155 | | } |
| 1156 | | } else try self.register_manager.allocReg(null, gp); |
| 1143 | const read_args = [_]ReadArg{ |
| 1144 | .{ .ty = operand_ty, .bind = operand_bind, .class = gp, .reg = &operand_reg }, |
| 1145 | }; |
| 1146 | const write_args = [_]WriteArg{ |
| 1147 | .{ .ty = dest_ty, .bind = .none, .class = gp, .reg = &dest_reg }, |
| 1148 | }; |
| 1149 | try self.allocRegs( |
| 1150 | &read_args, |
| 1151 | &write_args, |
| 1152 | if (maybe_inst) |inst| .{ |
| 1153 | .corresponding_inst = inst, |
| 1154 | .operand_mapping = &.{0}, |
| 1155 | } else null, |
| 1156 | ); |
| 1157 | 1157 | |
| 1158 | 1158 | switch (info_b.bits) { |
| 1159 | 1159 | 32 => { |
| 1160 | 1160 | try self.genSetReg(operand_ty, dest_reg, .{ .register = operand_reg }); |
| 1161 | | return MCValue{ .register = dest_reg }; |
| 1162 | 1161 | }, |
| 1163 | 1162 | else => { |
| 1164 | 1163 | try self.truncRegister(operand_reg, dest_reg, info_b.signedness, info_b.bits); |
| 1165 | | return MCValue{ .register = dest_reg }; |
| 1166 | 1164 | }, |
| 1167 | 1165 | } |
| 1166 | |
| 1167 | return MCValue{ .register = dest_reg }; |
| 1168 | 1168 | } else { |
| 1169 | 1169 | return self.fail("TODO: truncate to ints > 32 bits", .{}); |
| 1170 | 1170 | } |
| ... | ... | @@ -1172,12 +1172,12 @@ fn trunc( |
| 1172 | 1172 | |
| 1173 | 1173 | fn airTrunc(self: *Self, inst: Air.Inst.Index) !void { |
| 1174 | 1174 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1175 | | const operand = try self.resolveInst(ty_op.operand); |
| 1175 | const operand_bind: ReadArg.Bind = .{ .inst = ty_op.operand }; |
| 1176 | 1176 | const operand_ty = self.air.typeOf(ty_op.operand); |
| 1177 | 1177 | const dest_ty = self.air.typeOfIndex(inst); |
| 1178 | 1178 | |
| 1179 | 1179 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else blk: { |
| 1180 | | break :blk try self.trunc(inst, operand, operand_ty, dest_ty); |
| 1180 | break :blk try self.trunc(inst, operand_bind, operand_ty, dest_ty); |
| 1181 | 1181 | }; |
| 1182 | 1182 | |
| 1183 | 1183 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| ... | ... | @@ -2334,7 +2334,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2334 | 2334 | break :result dst_mcv; |
| 2335 | 2335 | }, |
| 2336 | 2336 | else => { |
| 2337 | | const dest = try self.allocRegOrMem(inst, true); |
| 2337 | const dest = try self.allocRegOrMem(self.air.typeOfIndex(inst), true, inst); |
| 2338 | 2338 | |
| 2339 | 2339 | const base_bind: ReadArg.Bind = .{ .mcv = base_mcv }; |
| 2340 | 2340 | const index_bind: ReadArg.Bind = .{ .mcv = index_mcv }; |
| ... | ... | @@ -2583,16 +2583,18 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 2583 | 2583 | if (self.liveness.isUnused(inst) and !is_volatile) |
| 2584 | 2584 | break :result MCValue.dead; |
| 2585 | 2585 | |
| 2586 | | const dst_mcv: MCValue = blk: { |
| 2587 | | if (self.reuseOperand(inst, ty_op.operand, 0, ptr)) { |
| 2586 | const dest_mcv: MCValue = blk: { |
| 2587 | const ptr_fits_dest = elem_ty.abiSize(self.target.*) <= 4; |
| 2588 | if (ptr_fits_dest and self.reuseOperand(inst, ty_op.operand, 0, ptr)) { |
| 2588 | 2589 | // The MCValue that holds the pointer can be re-used as the value. |
| 2589 | 2590 | break :blk ptr; |
| 2590 | 2591 | } else { |
| 2591 | | break :blk try self.allocRegOrMem(inst, true); |
| 2592 | break :blk try self.allocRegOrMem(elem_ty, true, inst); |
| 2592 | 2593 | } |
| 2593 | 2594 | }; |
| 2594 | | try self.load(dst_mcv, ptr, self.air.typeOf(ty_op.operand)); |
| 2595 | | break :result dst_mcv; |
| 2595 | try self.load(dest_mcv, ptr, self.air.typeOf(ty_op.operand)); |
| 2596 | |
| 2597 | break :result dest_mcv; |
| 2596 | 2598 | }; |
| 2597 | 2599 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 2598 | 2600 | } |
| ... | ... | @@ -4615,81 +4617,39 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { |
| 4615 | 4617 | return self.finishAir(inst, .unreach, .{ .none, .none, .none }); |
| 4616 | 4618 | } |
| 4617 | 4619 | |
| 4618 | | fn isNull(self: *Self, ty: Type, operand: MCValue) !MCValue { |
| 4619 | | if (ty.isPtrLikeOptional()) { |
| 4620 | | assert(ty.abiSize(self.target.*) == 4); |
| 4621 | | |
| 4622 | | const reg_mcv: MCValue = switch (operand) { |
| 4623 | | .register => operand, |
| 4624 | | else => .{ .register = try self.copyToTmpRegister(ty, operand) }, |
| 4625 | | }; |
| 4626 | | |
| 4627 | | _ = try self.addInst(.{ |
| 4628 | | .tag = .cmp, |
| 4629 | | .data = .{ .r_op_cmp = .{ |
| 4630 | | .rn = reg_mcv.register, |
| 4631 | | .op = Instruction.Operand.fromU32(0).?, |
| 4632 | | } }, |
| 4633 | | }); |
| 4620 | fn isNull( |
| 4621 | self: *Self, |
| 4622 | operand_bind: ReadArg.Bind, |
| 4623 | operand_ty: Type, |
| 4624 | ) !MCValue { |
| 4625 | if (operand_ty.isPtrLikeOptional()) { |
| 4626 | assert(operand_ty.abiSize(self.target.*) == 4); |
| 4634 | 4627 | |
| 4635 | | return MCValue{ .cpsr_flags = .eq }; |
| 4628 | const imm_bind: ReadArg.Bind = .{ .mcv = .{ .immediate = 0 } }; |
| 4629 | return self.cmp(operand_bind, imm_bind, Type.usize, .eq); |
| 4636 | 4630 | } else { |
| 4637 | 4631 | return self.fail("TODO implement non-pointer optionals", .{}); |
| 4638 | 4632 | } |
| 4639 | 4633 | } |
| 4640 | 4634 | |
| 4641 | | fn isNonNull(self: *Self, ty: Type, operand: MCValue) !MCValue { |
| 4642 | | const is_null_result = try self.isNull(ty, operand); |
| 4643 | | assert(is_null_result.cpsr_flags == .eq); |
| 4644 | | |
| 4645 | | return MCValue{ .cpsr_flags = .ne }; |
| 4646 | | } |
| 4647 | | |
| 4648 | | fn isErr( |
| 4635 | fn isNonNull( |
| 4649 | 4636 | self: *Self, |
| 4650 | | error_union_bind: ReadArg.Bind, |
| 4651 | | error_union_ty: Type, |
| 4637 | operand_bind: ReadArg.Bind, |
| 4638 | operand_ty: Type, |
| 4652 | 4639 | ) !MCValue { |
| 4653 | | const error_type = error_union_ty.errorUnionSet(); |
| 4654 | | |
| 4655 | | if (error_type.errorSetIsEmpty()) { |
| 4656 | | return MCValue{ .immediate = 0 }; // always false |
| 4657 | | } |
| 4658 | | |
| 4659 | | const error_mcv = try self.errUnionErr(error_union_bind, error_union_ty, null); |
| 4660 | | _ = try self.cmp(.{ .mcv = error_mcv }, .{ .mcv = .{ .immediate = 0 } }, error_type, .neq); |
| 4661 | | return MCValue{ .cpsr_flags = .hi }; |
| 4662 | | } |
| 4640 | const is_null_result = try self.isNull(operand_bind, operand_ty); |
| 4641 | assert(is_null_result.cpsr_flags == .eq); |
| 4663 | 4642 | |
| 4664 | | fn isNonErr( |
| 4665 | | self: *Self, |
| 4666 | | error_union_bind: ReadArg.Bind, |
| 4667 | | error_union_ty: Type, |
| 4668 | | ) !MCValue { |
| 4669 | | const is_err_result = try self.isErr(error_union_bind, error_union_ty); |
| 4670 | | switch (is_err_result) { |
| 4671 | | .cpsr_flags => |cond| { |
| 4672 | | assert(cond == .hi); |
| 4673 | | return MCValue{ .cpsr_flags = cond.negate() }; |
| 4674 | | }, |
| 4675 | | .immediate => |imm| { |
| 4676 | | assert(imm == 0); |
| 4677 | | return MCValue{ .immediate = 1 }; |
| 4678 | | }, |
| 4679 | | else => unreachable, |
| 4680 | | } |
| 4643 | return MCValue{ .cpsr_flags = .ne }; |
| 4681 | 4644 | } |
| 4682 | 4645 | |
| 4683 | 4646 | fn airIsNull(self: *Self, inst: Air.Inst.Index) !void { |
| 4684 | 4647 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 4685 | | |
| 4686 | | try self.spillCompareFlagsIfOccupied(); |
| 4687 | | self.cpsr_flags_inst = inst; |
| 4688 | | |
| 4689 | 4648 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 4690 | | const operand = try self.resolveInst(un_op); |
| 4691 | | const ty = self.air.typeOf(un_op); |
| 4692 | | break :result try self.isNull(ty, operand); |
| 4649 | const operand_bind: ReadArg.Bind = .{ .inst = un_op }; |
| 4650 | const operand_ty = self.air.typeOf(un_op); |
| 4651 | |
| 4652 | break :result try self.isNull(operand_bind, operand_ty); |
| 4693 | 4653 | }; |
| 4694 | 4654 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| 4695 | 4655 | } |
| ... | ... | @@ -4699,16 +4659,12 @@ fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 4699 | 4659 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 4700 | 4660 | const operand_ptr = try self.resolveInst(un_op); |
| 4701 | 4661 | const ptr_ty = self.air.typeOf(un_op); |
| 4702 | | const operand: MCValue = blk: { |
| 4703 | | if (self.reuseOperand(inst, un_op, 0, operand_ptr)) { |
| 4704 | | // The MCValue that holds the pointer can be re-used as the value. |
| 4705 | | break :blk operand_ptr; |
| 4706 | | } else { |
| 4707 | | break :blk try self.allocRegOrMem(inst, true); |
| 4708 | | } |
| 4709 | | }; |
| 4662 | const elem_ty = ptr_ty.elemType(); |
| 4663 | |
| 4664 | const operand = try self.allocRegOrMem(elem_ty, true, null); |
| 4710 | 4665 | try self.load(operand, operand_ptr, ptr_ty); |
| 4711 | | break :result try self.isNull(ptr_ty.elemType(), operand); |
| 4666 | |
| 4667 | break :result try self.isNull(.{ .mcv = operand }, elem_ty); |
| 4712 | 4668 | }; |
| 4713 | 4669 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| 4714 | 4670 | } |
| ... | ... | @@ -4716,9 +4672,10 @@ fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 4716 | 4672 | fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void { |
| 4717 | 4673 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 4718 | 4674 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 4719 | | const operand = try self.resolveInst(un_op); |
| 4720 | | const ty = self.air.typeOf(un_op); |
| 4721 | | break :result try self.isNonNull(ty, operand); |
| 4675 | const operand_bind: ReadArg.Bind = .{ .inst = un_op }; |
| 4676 | const operand_ty = self.air.typeOf(un_op); |
| 4677 | |
| 4678 | break :result try self.isNonNull(operand_bind, operand_ty); |
| 4722 | 4679 | }; |
| 4723 | 4680 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| 4724 | 4681 | } |
| ... | ... | @@ -4728,20 +4685,50 @@ fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 4728 | 4685 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 4729 | 4686 | const operand_ptr = try self.resolveInst(un_op); |
| 4730 | 4687 | const ptr_ty = self.air.typeOf(un_op); |
| 4731 | | const operand: MCValue = blk: { |
| 4732 | | if (self.reuseOperand(inst, un_op, 0, operand_ptr)) { |
| 4733 | | // The MCValue that holds the pointer can be re-used as the value. |
| 4734 | | break :blk operand_ptr; |
| 4735 | | } else { |
| 4736 | | break :blk try self.allocRegOrMem(inst, true); |
| 4737 | | } |
| 4738 | | }; |
| 4688 | const elem_ty = ptr_ty.elemType(); |
| 4689 | |
| 4690 | const operand = try self.allocRegOrMem(elem_ty, true, null); |
| 4739 | 4691 | try self.load(operand, operand_ptr, ptr_ty); |
| 4740 | | break :result try self.isNonNull(ptr_ty.elemType(), operand); |
| 4692 | |
| 4693 | break :result try self.isNonNull(.{ .mcv = operand }, elem_ty); |
| 4741 | 4694 | }; |
| 4742 | 4695 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| 4743 | 4696 | } |
| 4744 | 4697 | |
| 4698 | fn isErr( |
| 4699 | self: *Self, |
| 4700 | error_union_bind: ReadArg.Bind, |
| 4701 | error_union_ty: Type, |
| 4702 | ) !MCValue { |
| 4703 | const error_type = error_union_ty.errorUnionSet(); |
| 4704 | |
| 4705 | if (error_type.errorSetIsEmpty()) { |
| 4706 | return MCValue{ .immediate = 0 }; // always false |
| 4707 | } |
| 4708 | |
| 4709 | const error_mcv = try self.errUnionErr(error_union_bind, error_union_ty, null); |
| 4710 | return try self.cmp(.{ .mcv = error_mcv }, .{ .mcv = .{ .immediate = 0 } }, error_type, .gt); |
| 4711 | } |
| 4712 | |
| 4713 | fn isNonErr( |
| 4714 | self: *Self, |
| 4715 | error_union_bind: ReadArg.Bind, |
| 4716 | error_union_ty: Type, |
| 4717 | ) !MCValue { |
| 4718 | const is_err_result = try self.isErr(error_union_bind, error_union_ty); |
| 4719 | switch (is_err_result) { |
| 4720 | .cpsr_flags => |cond| { |
| 4721 | assert(cond == .hi); |
| 4722 | return MCValue{ .cpsr_flags = cond.negate() }; |
| 4723 | }, |
| 4724 | .immediate => |imm| { |
| 4725 | assert(imm == 0); |
| 4726 | return MCValue{ .immediate = 1 }; |
| 4727 | }, |
| 4728 | else => unreachable, |
| 4729 | } |
| 4730 | } |
| 4731 | |
| 4745 | 4732 | fn airIsErr(self: *Self, inst: Air.Inst.Index) !void { |
| 4746 | 4733 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 4747 | 4734 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| ... | ... | @@ -4758,16 +4745,12 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 4758 | 4745 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 4759 | 4746 | const operand_ptr = try self.resolveInst(un_op); |
| 4760 | 4747 | const ptr_ty = self.air.typeOf(un_op); |
| 4761 | | const operand: MCValue = blk: { |
| 4762 | | if (self.reuseOperand(inst, un_op, 0, operand_ptr)) { |
| 4763 | | // The MCValue that holds the pointer can be re-used as the value. |
| 4764 | | break :blk operand_ptr; |
| 4765 | | } else { |
| 4766 | | break :blk try self.allocRegOrMem(inst, true); |
| 4767 | | } |
| 4768 | | }; |
| 4748 | const elem_ty = ptr_ty.elemType(); |
| 4749 | |
| 4750 | const operand = try self.allocRegOrMem(elem_ty, true, null); |
| 4769 | 4751 | try self.load(operand, operand_ptr, ptr_ty); |
| 4770 | | break :result try self.isErr(.{ .mcv = operand }, ptr_ty.elemType()); |
| 4752 | |
| 4753 | break :result try self.isErr(.{ .mcv = operand }, elem_ty); |
| 4771 | 4754 | }; |
| 4772 | 4755 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| 4773 | 4756 | } |
| ... | ... | @@ -4788,16 +4771,12 @@ fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 4788 | 4771 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 4789 | 4772 | const operand_ptr = try self.resolveInst(un_op); |
| 4790 | 4773 | const ptr_ty = self.air.typeOf(un_op); |
| 4791 | | const operand: MCValue = blk: { |
| 4792 | | if (self.reuseOperand(inst, un_op, 0, operand_ptr)) { |
| 4793 | | // The MCValue that holds the pointer can be re-used as the value. |
| 4794 | | break :blk operand_ptr; |
| 4795 | | } else { |
| 4796 | | break :blk try self.allocRegOrMem(inst, true); |
| 4797 | | } |
| 4798 | | }; |
| 4774 | const elem_ty = ptr_ty.elemType(); |
| 4775 | |
| 4776 | const operand = try self.allocRegOrMem(elem_ty, true, null); |
| 4799 | 4777 | try self.load(operand, operand_ptr, ptr_ty); |
| 4800 | | break :result try self.isNonErr(.{ .mcv = operand }, ptr_ty.elemType()); |
| 4778 | |
| 4779 | break :result try self.isNonErr(.{ .mcv = operand }, elem_ty); |
| 4801 | 4780 | }; |
| 4802 | 4781 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| 4803 | 4782 | } |
| ... | ... | @@ -5010,7 +4989,7 @@ fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void { |
| 5010 | 4989 | .none, .dead, .unreach => unreachable, |
| 5011 | 4990 | .register, .stack_offset, .memory => operand_mcv, |
| 5012 | 4991 | .immediate, .stack_argument_offset, .cpsr_flags => blk: { |
| 5013 | | const new_mcv = try self.allocRegOrMem(block, true); |
| 4992 | const new_mcv = try self.allocRegOrMem(self.air.typeOfIndex(block), true, block); |
| 5014 | 4993 | try self.setRegOrMem(self.air.typeOfIndex(block), new_mcv, operand_mcv); |
| 5015 | 4994 | break :blk new_mcv; |
| 5016 | 4995 | }, |