mirror of
https://github.com/ziglang/zig.git
synced 2025-12-24 15:13:08 +00:00
stage2 AArch64: minor refactors in Mir + Emit
This commit is contained in:
parent
f598d2ae05
commit
f47245865e
@ -2121,8 +2121,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
|
||||
.immediate => |imm| {
|
||||
_ = try self.addInst(.{
|
||||
.tag = .cmp_immediate,
|
||||
.data = .{ .rr_imm12_sh = .{
|
||||
.rd = .xzr,
|
||||
.data = .{ .r_imm12_sh = .{
|
||||
.rn = lhs_mcv.register,
|
||||
.imm12 = @intCast(u12, imm),
|
||||
} },
|
||||
@ -2334,8 +2333,7 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
|
||||
|
||||
_ = try self.addInst(.{
|
||||
.tag = .cmp_immediate,
|
||||
.data = .{ .rr_imm12_sh = .{
|
||||
.rd = .xzr,
|
||||
.data = .{ .r_imm12_sh = .{
|
||||
.rn = reg_mcv.register,
|
||||
.imm12 = 0,
|
||||
} },
|
||||
@ -2559,7 +2557,16 @@ fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
|
||||
const operand_mcv = try self.resolveInst(operand);
|
||||
const block_mcv = block_data.mcv;
|
||||
if (block_mcv == .none) {
|
||||
block_data.mcv = operand_mcv;
|
||||
block_data.mcv = switch (operand_mcv) {
|
||||
.none, .dead, .unreach => unreachable,
|
||||
.register, .stack_offset, .memory => operand_mcv,
|
||||
.immediate => blk: {
|
||||
const new_mcv = try self.allocRegOrMem(block, true);
|
||||
try self.setRegOrMem(self.air.typeOfIndex(block), new_mcv, operand_mcv);
|
||||
break :blk new_mcv;
|
||||
},
|
||||
else => return self.fail("TODO implement block_data.mcv = operand_mcv for {}", .{operand_mcv}),
|
||||
};
|
||||
} else {
|
||||
try self.setRegOrMem(self.air.typeOfIndex(block), block_mcv, operand_mcv);
|
||||
}
|
||||
@ -2845,10 +2852,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
|
||||
|
||||
_ = try self.addInst(.{
|
||||
.tag = .cset,
|
||||
.data = .{ .rrr_cond = .{
|
||||
.data = .{ .r_cond = .{
|
||||
.rd = reg,
|
||||
.rn = .xzr,
|
||||
.rm = .xzr,
|
||||
.cond = condition,
|
||||
} },
|
||||
});
|
||||
@ -2933,7 +2938,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
|
||||
} },
|
||||
});
|
||||
},
|
||||
3 => return self.fail("TODO implement genSetReg types size 3", .{}),
|
||||
3, 5, 6, 7 => return self.fail("TODO implement genSetReg types size {}", .{abi_size}),
|
||||
else => unreachable,
|
||||
}
|
||||
},
|
||||
@ -3114,27 +3119,6 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
|
||||
}
|
||||
}
|
||||
|
||||
/// If the MCValue is an immediate, and it does not fit within this type,
|
||||
/// we put it in a register.
|
||||
/// A potential opportunity for future optimization here would be keeping track
|
||||
/// of the fact that the instruction is available both as an immediate
|
||||
/// and as a register.
|
||||
fn limitImmediateType(self: *Self, operand: Air.Inst.Ref, comptime T: type) !MCValue {
|
||||
const mcv = try self.resolveInst(operand);
|
||||
const ti = @typeInfo(T).Int;
|
||||
switch (mcv) {
|
||||
.immediate => |imm| {
|
||||
// This immediate is unsigned.
|
||||
const U = std.meta.Int(.unsigned, ti.bits - @boolToInt(ti.signedness == .signed));
|
||||
if (imm >= math.maxInt(U)) {
|
||||
return MCValue{ .register = try self.copyToTmpRegister(Type.initTag(.usize), mcv) };
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
return mcv;
|
||||
}
|
||||
|
||||
fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCValue {
|
||||
const ptr_bits = self.target.cpu.arch.ptrBitWidth();
|
||||
const ptr_bytes: u64 = @divExact(ptr_bits, 8);
|
||||
@ -3248,19 +3232,11 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
|
||||
}
|
||||
},
|
||||
.ErrorSet => {
|
||||
switch (typed_value.val.tag()) {
|
||||
.@"error" => {
|
||||
const err_name = typed_value.val.castTag(.@"error").?.data.name;
|
||||
const module = self.bin_file.options.module.?;
|
||||
const global_error_set = module.global_error_set;
|
||||
const error_index = global_error_set.get(err_name).?;
|
||||
return MCValue{ .immediate = error_index };
|
||||
},
|
||||
else => {
|
||||
// In this case we are rendering an error union which has a 0 bits payload.
|
||||
return MCValue{ .immediate = 0 };
|
||||
},
|
||||
}
|
||||
const err_name = typed_value.val.castTag(.@"error").?.data.name;
|
||||
const module = self.bin_file.options.module.?;
|
||||
const global_error_set = module.global_error_set;
|
||||
const error_index = global_error_set.get(err_name).?;
|
||||
return MCValue{ .immediate = error_index };
|
||||
},
|
||||
.ErrorUnion => {
|
||||
const error_type = typed_value.ty.errorUnionSet();
|
||||
@ -3425,13 +3401,18 @@ fn parseRegName(name: []const u8) ?Register {
|
||||
}
|
||||
|
||||
fn registerAlias(reg: Register, size_bytes: u32) Register {
|
||||
_ = size_bytes;
|
||||
|
||||
return reg;
|
||||
if (size_bytes == 0) {
|
||||
unreachable; // should be comptime known
|
||||
} else if (size_bytes <= 4) {
|
||||
return reg.to32();
|
||||
} else if (size_bytes <= 8) {
|
||||
return reg.to64();
|
||||
} else {
|
||||
unreachable; // TODO handle floating-point registers
|
||||
}
|
||||
}
|
||||
|
||||
/// For most architectures this does nothing. For x86_64 it resolves any aliased registers
|
||||
/// to the 64-bit wide ones.
|
||||
/// Resolves any aliased registers to the 64-bit wide ones.
|
||||
fn toCanonicalReg(reg: Register) Register {
|
||||
return reg;
|
||||
return reg.to64();
|
||||
}
|
||||
|
||||
@ -423,27 +423,30 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void {
|
||||
|
||||
fn mirAddSubtractImmediate(emit: *Emit, inst: Mir.Inst.Index) !void {
|
||||
const tag = emit.mir.instructions.items(.tag)[inst];
|
||||
const rr_imm12_sh = emit.mir.instructions.items(.data)[inst].rr_imm12_sh;
|
||||
|
||||
switch (tag) {
|
||||
.add_immediate => try emit.writeInstruction(Instruction.add(
|
||||
rr_imm12_sh.rd,
|
||||
rr_imm12_sh.rn,
|
||||
rr_imm12_sh.imm12,
|
||||
rr_imm12_sh.sh == 1,
|
||||
)),
|
||||
.cmp_immediate => try emit.writeInstruction(Instruction.subs(
|
||||
rr_imm12_sh.rd,
|
||||
rr_imm12_sh.rn,
|
||||
rr_imm12_sh.imm12,
|
||||
rr_imm12_sh.sh == 1,
|
||||
)),
|
||||
.sub_immediate => try emit.writeInstruction(Instruction.sub(
|
||||
rr_imm12_sh.rd,
|
||||
rr_imm12_sh.rn,
|
||||
rr_imm12_sh.imm12,
|
||||
rr_imm12_sh.sh == 1,
|
||||
)),
|
||||
.add_immediate,
|
||||
.sub_immediate,
|
||||
=> {
|
||||
const rr_imm12_sh = emit.mir.instructions.items(.data)[inst].rr_imm12_sh;
|
||||
const rd = rr_imm12_sh.rd;
|
||||
const rn = rr_imm12_sh.rn;
|
||||
const imm12 = rr_imm12_sh.imm12;
|
||||
const sh = rr_imm12_sh.sh == 1;
|
||||
|
||||
switch (tag) {
|
||||
.add_immediate => try emit.writeInstruction(Instruction.add(rd, rn, imm12, sh)),
|
||||
.sub_immediate => try emit.writeInstruction(Instruction.sub(rd, rn, imm12, sh)),
|
||||
else => unreachable,
|
||||
}
|
||||
},
|
||||
.cmp_immediate => {
|
||||
const r_imm12_sh = emit.mir.instructions.items(.data)[inst].r_imm12_sh;
|
||||
const rn = r_imm12_sh.rn;
|
||||
const imm12 = r_imm12_sh.imm12;
|
||||
const sh = r_imm12_sh.sh == 1;
|
||||
|
||||
try emit.writeInstruction(Instruction.subs(.xzr, rn, imm12, sh));
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
@ -589,15 +592,11 @@ fn mirAddSubtractShiftedRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
|
||||
|
||||
fn mirConditionalSelect(emit: *Emit, inst: Mir.Inst.Index) !void {
|
||||
const tag = emit.mir.instructions.items(.tag)[inst];
|
||||
const rrr_cond = emit.mir.instructions.items(.data)[inst].rrr_cond;
|
||||
|
||||
switch (tag) {
|
||||
.cset => try emit.writeInstruction(Instruction.csinc(
|
||||
rrr_cond.rd,
|
||||
rrr_cond.rn,
|
||||
rrr_cond.rm,
|
||||
rrr_cond.cond,
|
||||
)),
|
||||
.cset => {
|
||||
const r_cond = emit.mir.instructions.items(.data)[inst].r_cond;
|
||||
try emit.writeInstruction(Instruction.csinc(r_cond.rd, .xzr, .xzr, r_cond.cond));
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
@ -662,20 +661,14 @@ fn mirLoadMemory(emit: *Emit, inst: Mir.Inst.Index) !void {
|
||||
fn mirLoadStoreRegisterPair(emit: *Emit, inst: Mir.Inst.Index) !void {
|
||||
const tag = emit.mir.instructions.items(.tag)[inst];
|
||||
const load_store_register_pair = emit.mir.instructions.items(.data)[inst].load_store_register_pair;
|
||||
const rt = load_store_register_pair.rt;
|
||||
const rt2 = load_store_register_pair.rt2;
|
||||
const rn = load_store_register_pair.rn;
|
||||
const offset = load_store_register_pair.offset;
|
||||
|
||||
switch (tag) {
|
||||
.stp => try emit.writeInstruction(Instruction.stp(
|
||||
load_store_register_pair.rt,
|
||||
load_store_register_pair.rt2,
|
||||
load_store_register_pair.rn,
|
||||
load_store_register_pair.offset,
|
||||
)),
|
||||
.ldp => try emit.writeInstruction(Instruction.ldp(
|
||||
load_store_register_pair.rt,
|
||||
load_store_register_pair.rt2,
|
||||
load_store_register_pair.rn,
|
||||
load_store_register_pair.offset,
|
||||
)),
|
||||
.stp => try emit.writeInstruction(Instruction.stp(rt, rt2, rn, offset)),
|
||||
.ldp => try emit.writeInstruction(Instruction.ldp(rt, rt2, rn, offset)),
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,6 +175,13 @@ pub const Inst = struct {
|
||||
imm16: u16,
|
||||
hw: u2 = 0,
|
||||
},
|
||||
/// A register and a condition
|
||||
///
|
||||
/// Used by e.g. cset
|
||||
r_cond: struct {
|
||||
rd: Register,
|
||||
cond: bits.Instruction.Condition,
|
||||
},
|
||||
/// Two registers
|
||||
///
|
||||
/// Used by e.g. mov_register
|
||||
@ -182,6 +189,14 @@ pub const Inst = struct {
|
||||
rd: Register,
|
||||
rn: Register,
|
||||
},
|
||||
/// A register, an unsigned 12-bit immediate, and an optional shift
|
||||
///
|
||||
/// Used by e.g. cmp_immediate
|
||||
r_imm12_sh: struct {
|
||||
rn: Register,
|
||||
imm12: u12,
|
||||
sh: u1 = 0,
|
||||
},
|
||||
/// Two registers, an unsigned 12-bit immediate, and an optional shift
|
||||
///
|
||||
/// Used by e.g. sub_immediate
|
||||
@ -209,15 +224,6 @@ pub const Inst = struct {
|
||||
imm6: u6,
|
||||
shift: bits.Instruction.AddSubtractShiftedRegisterShift,
|
||||
},
|
||||
/// Three registers and a condition
|
||||
///
|
||||
/// Used by e.g. cset
|
||||
rrr_cond: struct {
|
||||
rd: Register,
|
||||
rn: Register,
|
||||
rm: Register,
|
||||
cond: bits.Instruction.Condition,
|
||||
},
|
||||
/// Two registers and a LoadStoreOffsetImmediate
|
||||
///
|
||||
/// Used by e.g. str_immediate
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user