| ... | @@ -208,7 +208,7 @@ const Branch = struct { | ... | @@ -208,7 +208,7 @@ const Branch = struct { |
| 208 | }; | 208 | }; |
| 209 | | 209 | |
| 210 | const StackAllocation = struct { | 210 | const StackAllocation = struct { |
| 211 | inst: Air.Inst.Index, | 211 | inst: ?Air.Inst.Index, |
| 212 | /// TODO do we need size? should be determined by inst.ty.abiSize(self.target.*) | 212 | /// TODO do we need size? should be determined by inst.ty.abiSize(self.target.*) |
| 213 | size: u32, | 213 | size: u32, |
| 214 | }; | 214 | }; |
| ... | @@ -1109,7 +1109,7 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void { | ... | @@ -1109,7 +1109,7 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void { |
| 1109 | try table.ensureUnusedCapacity(self.gpa, additional_count); | 1109 | try table.ensureUnusedCapacity(self.gpa, additional_count); |
| 1110 | } | 1110 | } |
| 1111 | | 1111 | |
| 1112 | fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: u32) !u32 { | 1112 | fn allocMem(self: *Self, inst: ?Air.Inst.Index, abi_size: u32, abi_align: u32) !u32 { |
| 1113 | if (abi_align > self.stack_align) | 1113 | if (abi_align > self.stack_align) |
| 1114 | self.stack_align = abi_align; | 1114 | self.stack_align = abi_align; |
| 1115 | // TODO find a free slot instead of always appending | 1115 | // TODO find a free slot instead of always appending |
| ... | @@ -1142,7 +1142,14 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { | ... | @@ -1142,7 +1142,14 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { |
| 1142 | } | 1142 | } |
| 1143 | | 1143 | |
| 1144 | fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { | 1144 | fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { |
| 1145 | const elem_ty = self.air.typeOfIndex(inst); | 1145 | return self.allocRegOrMemAdvanced(self.air.typeOfIndex(inst), inst, reg_ok); |
| | 1146 | } |
| | 1147 | |
| | 1148 | fn allocTempRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool) !MCValue { |
| | 1149 | return self.allocRegOrMemAdvanced(elem_ty, null, reg_ok); |
| | 1150 | } |
| | 1151 | |
| | 1152 | fn allocRegOrMemAdvanced(self: *Self, elem_ty: Type, inst: ?Air.Inst.Index, reg_ok: bool) !MCValue { |
| 1146 | const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) orelse { | 1153 | const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) orelse { |
| 1147 | const mod = self.bin_file.options.module.?; | 1154 | const mod = self.bin_file.options.module.?; |
| 1148 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); | 1155 | return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)}); |
| ... | @@ -4571,18 +4578,16 @@ fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4571,18 +4578,16 @@ fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 4571 | }; | 4578 | }; |
| 4572 | defer if (operand_ptr_lock) |lock| self.register_manager.unlockReg(lock); | 4579 | defer if (operand_ptr_lock) |lock| self.register_manager.unlockReg(lock); |
| 4573 | | 4580 | |
| 4574 | const operand: MCValue = blk: { | | |
| 4575 | if (self.reuseOperand(inst, un_op, 0, operand_ptr)) { | | |
| 4576 | // The MCValue that holds the pointer can be re-used as the value. | | |
| 4577 | break :blk operand_ptr; | | |
| 4578 | } else { | | |
| 4579 | break :blk try self.allocRegOrMem(inst, true); | | |
| 4580 | } | | |
| 4581 | }; | | |
| 4582 | const ptr_ty = self.air.typeOf(un_op); | 4581 | const ptr_ty = self.air.typeOf(un_op); |
| | 4582 | const elem_ty = ptr_ty.childType(); |
| | 4583 | const operand = if (elem_ty.isPtrLikeOptional() and self.reuseOperand(inst, un_op, 0, operand_ptr)) |
| | 4584 | // The MCValue that holds the pointer can be re-used as the value. |
| | 4585 | operand_ptr |
| | 4586 | else |
| | 4587 | try self.allocTempRegOrMem(elem_ty, true); |
| 4583 | try self.load(operand, operand_ptr, ptr_ty); | 4588 | try self.load(operand, operand_ptr, ptr_ty); |
| 4584 | | 4589 | |
| 4585 | const result = try self.isNull(inst, ptr_ty.elemType(), operand); | 4590 | const result = try self.isNull(inst, elem_ty, operand); |
| 4586 | | 4591 | |
| 4587 | return self.finishAir(inst, result, .{ un_op, .none, .none }); | 4592 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| 4588 | } | 4593 | } |
| ... | @@ -4611,15 +4616,13 @@ fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4611,15 +4616,13 @@ fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 4611 | }; | 4616 | }; |
| 4612 | defer if (operand_ptr_lock) |lock| self.register_manager.unlockReg(lock); | 4617 | defer if (operand_ptr_lock) |lock| self.register_manager.unlockReg(lock); |
| 4613 | | 4618 | |
| 4614 | const operand: MCValue = blk: { | | |
| 4615 | if (self.reuseOperand(inst, un_op, 0, operand_ptr)) { | | |
| 4616 | // The MCValue that holds the pointer can be re-used as the value. | | |
| 4617 | break :blk operand_ptr; | | |
| 4618 | } else { | | |
| 4619 | break :blk try self.allocRegOrMem(inst, true); | | |
| 4620 | } | | |
| 4621 | }; | | |
| 4622 | const ptr_ty = self.air.typeOf(un_op); | 4619 | const ptr_ty = self.air.typeOf(un_op); |
| | 4620 | const elem_ty = ptr_ty.childType(); |
| | 4621 | const operand = if (elem_ty.isPtrLikeOptional() and self.reuseOperand(inst, un_op, 0, operand_ptr)) |
| | 4622 | // The MCValue that holds the pointer can be re-used as the value. |
| | 4623 | operand_ptr |
| | 4624 | else |
| | 4625 | try self.allocTempRegOrMem(elem_ty, true); |
| 4623 | try self.load(operand, operand_ptr, ptr_ty); | 4626 | try self.load(operand, operand_ptr, ptr_ty); |
| 4624 | | 4627 | |
| 4625 | const result = try self.isNonNull(inst, ptr_ty.elemType(), operand); | 4628 | const result = try self.isNonNull(inst, ptr_ty.elemType(), operand); |