mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 16:54:52 +00:00
stage2 AArch64: simplify allocMem
This commit is contained in:
parent
151e15e444
commit
230bafa1ab
@ -157,40 +157,6 @@ const MCValue = union(enum) {
|
|||||||
condition_flags: Condition,
|
condition_flags: Condition,
|
||||||
/// The value is a function argument passed via the stack.
|
/// The value is a function argument passed via the stack.
|
||||||
stack_argument_offset: u32,
|
stack_argument_offset: u32,
|
||||||
|
|
||||||
fn isMemory(mcv: MCValue) bool {
|
|
||||||
return switch (mcv) {
|
|
||||||
.memory, .stack_offset, .stack_argument_offset => true,
|
|
||||||
else => false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn isImmediate(mcv: MCValue) bool {
|
|
||||||
return switch (mcv) {
|
|
||||||
.immediate => true,
|
|
||||||
else => false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn isMutable(mcv: MCValue) bool {
|
|
||||||
return switch (mcv) {
|
|
||||||
.none => unreachable,
|
|
||||||
.unreach => unreachable,
|
|
||||||
.dead => unreachable,
|
|
||||||
|
|
||||||
.immediate,
|
|
||||||
.memory,
|
|
||||||
.condition_flags,
|
|
||||||
.ptr_stack_offset,
|
|
||||||
.undef,
|
|
||||||
.stack_argument_offset,
|
|
||||||
=> false,
|
|
||||||
|
|
||||||
.register,
|
|
||||||
.stack_offset,
|
|
||||||
=> true,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const Branch = struct {
|
const Branch = struct {
|
||||||
@ -416,9 +382,7 @@ fn gen(self: *Self) !void {
|
|||||||
const ptr_bytes = @divExact(ptr_bits, 8);
|
const ptr_bytes = @divExact(ptr_bits, 8);
|
||||||
const ret_ptr_reg = self.registerAlias(.x0, Type.usize);
|
const ret_ptr_reg = self.registerAlias(.x0, Type.usize);
|
||||||
|
|
||||||
const stack_offset = mem.alignForwardGeneric(u32, self.next_stack_offset, ptr_bytes) + ptr_bytes;
|
const stack_offset = try self.allocMem(ptr_bytes, ptr_bytes, null);
|
||||||
self.next_stack_offset = stack_offset;
|
|
||||||
self.max_end_stack = @max(self.max_end_stack, self.next_stack_offset);
|
|
||||||
|
|
||||||
try self.genSetStack(Type.usize, stack_offset, MCValue{ .register = ret_ptr_reg });
|
try self.genSetStack(Type.usize, stack_offset, MCValue{ .register = ret_ptr_reg });
|
||||||
self.ret_mcv = MCValue{ .stack_offset = stack_offset };
|
self.ret_mcv = MCValue{ .stack_offset = stack_offset };
|
||||||
@ -879,17 +843,30 @@ fn addDbgInfoTypeReloc(self: *Self, ty: Type) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: u32) !u32 {
|
fn allocMem(
|
||||||
|
self: *Self,
|
||||||
|
abi_size: u32,
|
||||||
|
abi_align: u32,
|
||||||
|
maybe_inst: ?Air.Inst.Index,
|
||||||
|
) !u32 {
|
||||||
|
assert(abi_size > 0);
|
||||||
|
assert(abi_align > 0);
|
||||||
|
|
||||||
if (abi_align > self.stack_align)
|
if (abi_align > self.stack_align)
|
||||||
self.stack_align = abi_align;
|
self.stack_align = abi_align;
|
||||||
|
|
||||||
// TODO find a free slot instead of always appending
|
// TODO find a free slot instead of always appending
|
||||||
const offset = mem.alignForwardGeneric(u32, self.next_stack_offset, abi_align) + abi_size;
|
const offset = mem.alignForwardGeneric(u32, self.next_stack_offset, abi_align) + abi_size;
|
||||||
self.next_stack_offset = offset;
|
self.next_stack_offset = offset;
|
||||||
self.max_end_stack = @max(self.max_end_stack, self.next_stack_offset);
|
self.max_end_stack = @max(self.max_end_stack, self.next_stack_offset);
|
||||||
try self.stack.putNoClobber(self.gpa, offset, .{
|
|
||||||
.inst = inst,
|
if (maybe_inst) |inst| {
|
||||||
.size = abi_size,
|
try self.stack.putNoClobber(self.gpa, offset, .{
|
||||||
});
|
.inst = inst,
|
||||||
|
.size = abi_size,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -910,40 +887,41 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {
|
|||||||
};
|
};
|
||||||
// TODO swap this for inst.ty.ptrAlign
|
// TODO swap this for inst.ty.ptrAlign
|
||||||
const abi_align = elem_ty.abiAlignment(self.target.*);
|
const abi_align = elem_ty.abiAlignment(self.target.*);
|
||||||
return self.allocMem(inst, abi_size, abi_align);
|
|
||||||
|
return self.allocMem(abi_size, abi_align, inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
|
fn allocRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool, maybe_inst: ?Air.Inst.Index) !MCValue {
|
||||||
const elem_ty = self.air.typeOfIndex(inst);
|
|
||||||
const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) orelse {
|
const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) orelse {
|
||||||
const mod = self.bin_file.options.module.?;
|
const mod = self.bin_file.options.module.?;
|
||||||
return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)});
|
return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)});
|
||||||
};
|
};
|
||||||
const abi_align = elem_ty.abiAlignment(self.target.*);
|
const abi_align = elem_ty.abiAlignment(self.target.*);
|
||||||
if (abi_align > self.stack_align)
|
|
||||||
self.stack_align = abi_align;
|
|
||||||
|
|
||||||
if (reg_ok) {
|
if (reg_ok) {
|
||||||
// Make sure the type can fit in a register before we try to allocate one.
|
// Make sure the type can fit in a register before we try to allocate one.
|
||||||
if (abi_size <= 8) {
|
if (abi_size <= 8) {
|
||||||
if (self.register_manager.tryAllocReg(inst, gp)) |reg| {
|
if (self.register_manager.tryAllocReg(maybe_inst, gp)) |reg| {
|
||||||
return MCValue{ .register = self.registerAlias(reg, elem_ty) };
|
return MCValue{ .register = self.registerAlias(reg, elem_ty) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const stack_offset = try self.allocMem(inst, abi_size, abi_align);
|
|
||||||
|
const stack_offset = try self.allocMem(abi_size, abi_align, maybe_inst);
|
||||||
return MCValue{ .stack_offset = stack_offset };
|
return MCValue{ .stack_offset = stack_offset };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void {
|
pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void {
|
||||||
const stack_mcv = try self.allocRegOrMem(inst, false);
|
const stack_mcv = try self.allocRegOrMem(self.air.typeOfIndex(inst), false, inst);
|
||||||
log.debug("spilling {d} to stack mcv {any}", .{ inst, stack_mcv });
|
log.debug("spilling {d} to stack mcv {any}", .{ inst, stack_mcv });
|
||||||
|
|
||||||
const reg_mcv = self.getResolvedInstValue(inst);
|
const reg_mcv = self.getResolvedInstValue(inst);
|
||||||
switch (reg_mcv) {
|
switch (reg_mcv) {
|
||||||
.register => |r| assert(reg.id() == r.id()),
|
.register => |r| assert(reg.id() == r.id()),
|
||||||
.register_with_overflow => |rwo| assert(rwo.reg.id() == reg.id()),
|
.register_with_overflow => |rwo| assert(rwo.reg.id() == reg.id()),
|
||||||
else => unreachable, // not a register
|
else => unreachable, // not a register
|
||||||
}
|
}
|
||||||
|
|
||||||
const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
|
const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
|
||||||
try branch.inst_table.put(self.gpa, inst, stack_mcv);
|
try branch.inst_table.put(self.gpa, inst, stack_mcv);
|
||||||
try self.genSetStack(self.air.typeOfIndex(inst), stack_mcv.stack_offset, reg_mcv);
|
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
|
|||||||
/// occupied
|
/// occupied
|
||||||
fn spillCompareFlagsIfOccupied(self: *Self) !void {
|
fn spillCompareFlagsIfOccupied(self: *Self) !void {
|
||||||
if (self.condition_flags_inst) |inst_to_save| {
|
if (self.condition_flags_inst) |inst_to_save| {
|
||||||
|
const ty = self.air.typeOfIndex(inst_to_save);
|
||||||
const mcv = self.getResolvedInstValue(inst_to_save);
|
const mcv = self.getResolvedInstValue(inst_to_save);
|
||||||
const new_mcv = switch (mcv) {
|
const new_mcv = switch (mcv) {
|
||||||
.condition_flags => try self.allocRegOrMem(inst_to_save, true),
|
.condition_flags => try self.allocRegOrMem(ty, true, inst_to_save),
|
||||||
.register_with_overflow => try self.allocRegOrMem(inst_to_save, false),
|
.register_with_overflow => try self.allocRegOrMem(ty, false, inst_to_save),
|
||||||
else => unreachable, // mcv doesn't occupy the compare flags
|
else => unreachable, // mcv doesn't occupy the compare flags
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1046,14 +1025,14 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (dest_info.bits > operand_info.bits) {
|
if (dest_info.bits > operand_info.bits) {
|
||||||
const dest_mcv = try self.allocRegOrMem(inst, true);
|
const dest_mcv = try self.allocRegOrMem(dest_ty, true, inst);
|
||||||
try self.setRegOrMem(self.air.typeOfIndex(inst), dest_mcv, truncated);
|
try self.setRegOrMem(self.air.typeOfIndex(inst), dest_mcv, truncated);
|
||||||
break :result dest_mcv;
|
break :result dest_mcv;
|
||||||
} else {
|
} else {
|
||||||
if (self.reuseOperand(inst, operand, 0, truncated)) {
|
if (self.reuseOperand(inst, operand, 0, truncated)) {
|
||||||
break :result truncated;
|
break :result truncated;
|
||||||
} else {
|
} else {
|
||||||
const dest_mcv = try self.allocRegOrMem(inst, true);
|
const dest_mcv = try self.allocRegOrMem(dest_ty, true, inst);
|
||||||
try self.setRegOrMem(self.air.typeOfIndex(inst), dest_mcv, truncated);
|
try self.setRegOrMem(self.air.typeOfIndex(inst), dest_mcv, truncated);
|
||||||
break :result dest_mcv;
|
break :result dest_mcv;
|
||||||
}
|
}
|
||||||
@ -1278,7 +1257,7 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
|
|||||||
const ptr_bits = self.target.cpu.arch.ptrBitWidth();
|
const ptr_bits = self.target.cpu.arch.ptrBitWidth();
|
||||||
const ptr_bytes = @divExact(ptr_bits, 8);
|
const ptr_bytes = @divExact(ptr_bits, 8);
|
||||||
|
|
||||||
const stack_offset = try self.allocMem(inst, ptr_bytes * 2, ptr_bytes * 2);
|
const stack_offset = try self.allocMem(ptr_bytes * 2, ptr_bytes * 2, inst);
|
||||||
try self.genSetStack(ptr_ty, stack_offset, ptr);
|
try self.genSetStack(ptr_ty, stack_offset, ptr);
|
||||||
try self.genSetStack(len_ty, stack_offset - ptr_bytes, len);
|
try self.genSetStack(len_ty, stack_offset - ptr_bytes, len);
|
||||||
break :result MCValue{ .stack_offset = stack_offset };
|
break :result MCValue{ .stack_offset = stack_offset };
|
||||||
@ -2049,7 +2028,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
|
|||||||
const int_info = lhs_ty.intInfo(self.target.*);
|
const int_info = lhs_ty.intInfo(self.target.*);
|
||||||
switch (int_info.bits) {
|
switch (int_info.bits) {
|
||||||
1...31, 33...63 => {
|
1...31, 33...63 => {
|
||||||
const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);
|
const stack_offset = try self.allocMem(tuple_size, tuple_align, inst);
|
||||||
|
|
||||||
try self.spillCompareFlagsIfOccupied();
|
try self.spillCompareFlagsIfOccupied();
|
||||||
self.condition_flags_inst = null;
|
self.condition_flags_inst = null;
|
||||||
@ -2164,7 +2143,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
|
|||||||
const int_info = lhs_ty.intInfo(self.target.*);
|
const int_info = lhs_ty.intInfo(self.target.*);
|
||||||
|
|
||||||
if (int_info.bits <= 32) {
|
if (int_info.bits <= 32) {
|
||||||
const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);
|
const stack_offset = try self.allocMem(tuple_size, tuple_align, inst);
|
||||||
|
|
||||||
try self.spillCompareFlagsIfOccupied();
|
try self.spillCompareFlagsIfOccupied();
|
||||||
self.condition_flags_inst = null;
|
self.condition_flags_inst = null;
|
||||||
@ -2220,7 +2199,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
|
|||||||
|
|
||||||
break :result MCValue{ .stack_offset = stack_offset };
|
break :result MCValue{ .stack_offset = stack_offset };
|
||||||
} else if (int_info.bits <= 64) {
|
} else if (int_info.bits <= 64) {
|
||||||
const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);
|
const stack_offset = try self.allocMem(tuple_size, tuple_align, inst);
|
||||||
|
|
||||||
try self.spillCompareFlagsIfOccupied();
|
try self.spillCompareFlagsIfOccupied();
|
||||||
self.condition_flags_inst = null;
|
self.condition_flags_inst = null;
|
||||||
@ -2424,7 +2403,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
|
|||||||
.Int => {
|
.Int => {
|
||||||
const int_info = lhs_ty.intInfo(self.target.*);
|
const int_info = lhs_ty.intInfo(self.target.*);
|
||||||
if (int_info.bits <= 64) {
|
if (int_info.bits <= 64) {
|
||||||
const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);
|
const stack_offset = try self.allocMem(tuple_size, tuple_align, inst);
|
||||||
|
|
||||||
const lhs_lock: ?RegisterLock = if (lhs == .register)
|
const lhs_lock: ?RegisterLock = if (lhs == .register)
|
||||||
self.register_manager.lockRegAssumeUnused(lhs.register)
|
self.register_manager.lockRegAssumeUnused(lhs.register)
|
||||||
@ -2745,7 +2724,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
|
|||||||
const base_reg_lock = self.register_manager.lockRegAssumeUnused(base_reg);
|
const base_reg_lock = self.register_manager.lockRegAssumeUnused(base_reg);
|
||||||
defer self.register_manager.unlockReg(base_reg_lock);
|
defer self.register_manager.unlockReg(base_reg_lock);
|
||||||
|
|
||||||
const dest = try self.allocRegOrMem(inst, true);
|
const dest = try self.allocRegOrMem(elem_ty, true, inst);
|
||||||
const addr = try self.binOp(.ptr_add, base_mcv, index_mcv, slice_ptr_field_type, Type.usize, null);
|
const addr = try self.binOp(.ptr_add, base_mcv, index_mcv, slice_ptr_field_type, Type.usize, null);
|
||||||
try self.load(dest, addr, slice_ptr_field_type);
|
try self.load(dest, addr, slice_ptr_field_type);
|
||||||
|
|
||||||
@ -3058,7 +3037,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
|
|||||||
else => ptr,
|
else => ptr,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
break :blk try self.allocRegOrMem(inst, true);
|
break :blk try self.allocRegOrMem(elem_ty, true, inst);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
try self.load(dst_mcv, ptr, self.air.typeOf(ty_op.operand));
|
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 {
|
|||||||
return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(mod)});
|
return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(mod)});
|
||||||
};
|
};
|
||||||
const abi_align = ty.abiAlignment(self.target.*);
|
const abi_align = ty.abiAlignment(self.target.*);
|
||||||
const stack_offset = try self.allocMem(inst, abi_size, abi_align);
|
const stack_offset = try self.allocMem(abi_size, abi_align, inst);
|
||||||
try self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
|
try self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
|
||||||
|
|
||||||
break :blk MCValue{ .stack_offset = stack_offset };
|
break :blk MCValue{ .stack_offset = stack_offset };
|
||||||
@ -3412,7 +3391,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
|
|||||||
const ret_ty = fn_ty.fnReturnType();
|
const ret_ty = fn_ty.fnReturnType();
|
||||||
const ret_abi_size = @intCast(u32, ret_ty.abiSize(self.target.*));
|
const ret_abi_size = @intCast(u32, ret_ty.abiSize(self.target.*));
|
||||||
const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(self.target.*));
|
const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(self.target.*));
|
||||||
const stack_offset = try self.allocMem(inst, ret_abi_size, ret_abi_align);
|
const stack_offset = try self.allocMem(ret_abi_size, ret_abi_align, inst);
|
||||||
|
|
||||||
const ret_ptr_reg = self.registerAlias(.x0, Type.usize);
|
const ret_ptr_reg = self.registerAlias(.x0, Type.usize);
|
||||||
|
|
||||||
@ -3638,14 +3617,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
|
|||||||
const abi_size = @intCast(u32, ret_ty.abiSize(self.target.*));
|
const abi_size = @intCast(u32, ret_ty.abiSize(self.target.*));
|
||||||
const abi_align = ret_ty.abiAlignment(self.target.*);
|
const abi_align = ret_ty.abiAlignment(self.target.*);
|
||||||
|
|
||||||
// This is essentially allocMem without the
|
const offset = try self.allocMem(abi_size, abi_align, null);
|
||||||
// instruction tracking
|
|
||||||
if (abi_align > self.stack_align)
|
|
||||||
self.stack_align = abi_align;
|
|
||||||
// TODO find a free slot instead of always appending
|
|
||||||
const offset = mem.alignForwardGeneric(u32, self.next_stack_offset, abi_align) + abi_size;
|
|
||||||
self.next_stack_offset = offset;
|
|
||||||
self.max_end_stack = @max(self.max_end_stack, self.next_stack_offset);
|
|
||||||
|
|
||||||
const tmp_mcv = MCValue{ .stack_offset = offset };
|
const tmp_mcv = MCValue{ .stack_offset = offset };
|
||||||
try self.load(tmp_mcv, ptr, ptr_ty);
|
try self.load(tmp_mcv, ptr, ptr_ty);
|
||||||
@ -3993,15 +3965,12 @@ fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void {
|
|||||||
const un_op = self.air.instructions.items(.data)[inst].un_op;
|
const un_op = self.air.instructions.items(.data)[inst].un_op;
|
||||||
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
|
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
|
||||||
const operand_ptr = try self.resolveInst(un_op);
|
const operand_ptr = try self.resolveInst(un_op);
|
||||||
const operand: MCValue = blk: {
|
const ptr_ty = self.air.typeOf(un_op);
|
||||||
if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {
|
const elem_ty = ptr_ty.elemType();
|
||||||
// The MCValue that holds the pointer can be re-used as the value.
|
|
||||||
break :blk operand_ptr;
|
const operand = try self.allocRegOrMem(elem_ty, true, null);
|
||||||
} else {
|
try self.load(operand, operand_ptr, ptr_ty);
|
||||||
break :blk try self.allocRegOrMem(inst, true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
try self.load(operand, operand_ptr, self.air.typeOf(un_op));
|
|
||||||
break :result try self.isNull(operand);
|
break :result try self.isNull(operand);
|
||||||
};
|
};
|
||||||
return self.finishAir(inst, result, .{ un_op, .none, .none });
|
return self.finishAir(inst, result, .{ un_op, .none, .none });
|
||||||
@ -4020,15 +3989,12 @@ fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {
|
|||||||
const un_op = self.air.instructions.items(.data)[inst].un_op;
|
const un_op = self.air.instructions.items(.data)[inst].un_op;
|
||||||
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
|
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
|
||||||
const operand_ptr = try self.resolveInst(un_op);
|
const operand_ptr = try self.resolveInst(un_op);
|
||||||
const operand: MCValue = blk: {
|
const ptr_ty = self.air.typeOf(un_op);
|
||||||
if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {
|
const elem_ty = ptr_ty.elemType();
|
||||||
// The MCValue that holds the pointer can be re-used as the value.
|
|
||||||
break :blk operand_ptr;
|
const operand = try self.allocRegOrMem(elem_ty, true, null);
|
||||||
} else {
|
try self.load(operand, operand_ptr, ptr_ty);
|
||||||
break :blk try self.allocRegOrMem(inst, true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
try self.load(operand, operand_ptr, self.air.typeOf(un_op));
|
|
||||||
break :result try self.isNonNull(operand);
|
break :result try self.isNonNull(operand);
|
||||||
};
|
};
|
||||||
return self.finishAir(inst, result, .{ un_op, .none, .none });
|
return self.finishAir(inst, result, .{ un_op, .none, .none });
|
||||||
@ -4049,16 +4015,12 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {
|
|||||||
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
|
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
|
||||||
const operand_ptr = try self.resolveInst(un_op);
|
const operand_ptr = try self.resolveInst(un_op);
|
||||||
const ptr_ty = self.air.typeOf(un_op);
|
const ptr_ty = self.air.typeOf(un_op);
|
||||||
const operand: MCValue = blk: {
|
const elem_ty = ptr_ty.elemType();
|
||||||
if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {
|
|
||||||
// The MCValue that holds the pointer can be re-used as the value.
|
const operand = try self.allocRegOrMem(elem_ty, true, null);
|
||||||
break :blk operand_ptr;
|
try self.load(operand, operand_ptr, ptr_ty);
|
||||||
} else {
|
|
||||||
break :blk try self.allocRegOrMem(inst, true);
|
break :result try self.isErr(elem_ty, operand);
|
||||||
}
|
|
||||||
};
|
|
||||||
try self.load(operand, operand_ptr, self.air.typeOf(un_op));
|
|
||||||
break :result try self.isErr(ptr_ty.elemType(), operand);
|
|
||||||
};
|
};
|
||||||
return self.finishAir(inst, result, .{ un_op, .none, .none });
|
return self.finishAir(inst, result, .{ un_op, .none, .none });
|
||||||
}
|
}
|
||||||
@ -4078,16 +4040,12 @@ fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {
|
|||||||
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
|
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
|
||||||
const operand_ptr = try self.resolveInst(un_op);
|
const operand_ptr = try self.resolveInst(un_op);
|
||||||
const ptr_ty = self.air.typeOf(un_op);
|
const ptr_ty = self.air.typeOf(un_op);
|
||||||
const operand: MCValue = blk: {
|
const elem_ty = ptr_ty.elemType();
|
||||||
if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {
|
|
||||||
// The MCValue that holds the pointer can be re-used as the value.
|
const operand = try self.allocRegOrMem(elem_ty, true, null);
|
||||||
break :blk operand_ptr;
|
try self.load(operand, operand_ptr, ptr_ty);
|
||||||
} else {
|
|
||||||
break :blk try self.allocRegOrMem(inst, true);
|
break :result try self.isNonErr(elem_ty, operand);
|
||||||
}
|
|
||||||
};
|
|
||||||
try self.load(operand, operand_ptr, self.air.typeOf(un_op));
|
|
||||||
break :result try self.isNonErr(ptr_ty.elemType(), operand);
|
|
||||||
};
|
};
|
||||||
return self.finishAir(inst, result, .{ un_op, .none, .none });
|
return self.finishAir(inst, result, .{ un_op, .none, .none });
|
||||||
}
|
}
|
||||||
@ -4180,7 +4138,7 @@ fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
|
|||||||
.none, .dead, .unreach => unreachable,
|
.none, .dead, .unreach => unreachable,
|
||||||
.register, .stack_offset, .memory => operand_mcv,
|
.register, .stack_offset, .memory => operand_mcv,
|
||||||
.immediate, .stack_argument_offset, .condition_flags => blk: {
|
.immediate, .stack_argument_offset, .condition_flags => blk: {
|
||||||
const new_mcv = try self.allocRegOrMem(block, true);
|
const new_mcv = try self.allocRegOrMem(self.air.typeOfIndex(block), true, block);
|
||||||
try self.setRegOrMem(self.air.typeOfIndex(block), new_mcv, operand_mcv);
|
try self.setRegOrMem(self.air.typeOfIndex(block), new_mcv, operand_mcv);
|
||||||
break :blk new_mcv;
|
break :blk new_mcv;
|
||||||
},
|
},
|
||||||
@ -4837,7 +4795,7 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {
|
|||||||
const ptr_bits = self.target.cpu.arch.ptrBitWidth();
|
const ptr_bits = self.target.cpu.arch.ptrBitWidth();
|
||||||
const ptr_bytes = @divExact(ptr_bits, 8);
|
const ptr_bytes = @divExact(ptr_bits, 8);
|
||||||
|
|
||||||
const stack_offset = try self.allocMem(inst, ptr_bytes * 2, ptr_bytes * 2);
|
const stack_offset = try self.allocMem(ptr_bytes * 2, ptr_bytes * 2, inst);
|
||||||
try self.genSetStack(ptr_ty, stack_offset, ptr);
|
try self.genSetStack(ptr_ty, stack_offset, ptr);
|
||||||
try self.genSetStack(Type.initTag(.usize), stack_offset - ptr_bytes, .{ .immediate = array_len });
|
try self.genSetStack(Type.initTag(.usize), stack_offset - ptr_bytes, .{ .immediate = array_len });
|
||||||
break :result MCValue{ .stack_offset = stack_offset };
|
break :result MCValue{ .stack_offset = stack_offset };
|
||||||
|
|||||||
@ -432,7 +432,7 @@ pub const Inst = struct {
|
|||||||
rn: Register,
|
rn: Register,
|
||||||
offset: bits.Instruction.LoadStoreOffsetRegister,
|
offset: bits.Instruction.LoadStoreOffsetRegister,
|
||||||
},
|
},
|
||||||
/// A registers and a stack offset
|
/// A register and a stack offset
|
||||||
///
|
///
|
||||||
/// Used by e.g. str_stack
|
/// Used by e.g. str_stack
|
||||||
load_store_stack: struct {
|
load_store_stack: struct {
|
||||||
@ -464,10 +464,6 @@ pub const Inst = struct {
|
|||||||
line: u32,
|
line: u32,
|
||||||
column: u32,
|
column: u32,
|
||||||
},
|
},
|
||||||
load_memory: struct {
|
|
||||||
register: u32,
|
|
||||||
addr: u32,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Make sure we don't accidentally make instructions bigger than expected.
|
// Make sure we don't accidentally make instructions bigger than expected.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user