authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-02-08 19:57:01+01:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-02-14 22:09:43+01:00
logf47245865eea35fa0b08cb2a87e3620fa904dd88
tree61995c5a806a91a2cc90cba8cd5eab40655d226b
parentf598d2ae056e72bda1efb3bc7d77e8183e95e191
signaturelock-open Commit is signed but in an unrecognized format.

stage2 AArch64: minor refactors in Mir + Emit


3 files changed, 78 insertions(+), 98 deletions(-)

src/arch/aarch64/CodeGen.zig+30-49
......@@ -2121,8 +2121,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
21212121 .immediate => |imm| {
21222122 _ = try self.addInst(.{
21232123 .tag = .cmp_immediate,
2124 .data = .{ .rr_imm12_sh = .{
2125 .rd = .xzr,
2124 .data = .{ .r_imm12_sh = .{
21262125 .rn = lhs_mcv.register,
21272126 .imm12 = @intCast(u12, imm),
21282127 } },
......@@ -2334,8 +2333,7 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
23342333
23352334 _ = try self.addInst(.{
23362335 .tag = .cmp_immediate,
2337 .data = .{ .rr_imm12_sh = .{
2338 .rd = .xzr,
2336 .data = .{ .r_imm12_sh = .{
23392337 .rn = reg_mcv.register,
23402338 .imm12 = 0,
23412339 } },
......@@ -2559,7 +2557,16 @@ fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
25592557 const operand_mcv = try self.resolveInst(operand);
25602558 const block_mcv = block_data.mcv;
25612559 if (block_mcv == .none) {
2562 block_data.mcv = operand_mcv;
2560 block_data.mcv = switch (operand_mcv) {
2561 .none, .dead, .unreach => unreachable,
2562 .register, .stack_offset, .memory => operand_mcv,
2563 .immediate => blk: {
2564 const new_mcv = try self.allocRegOrMem(block, true);
2565 try self.setRegOrMem(self.air.typeOfIndex(block), new_mcv, operand_mcv);
2566 break :blk new_mcv;
2567 },
2568 else => return self.fail("TODO implement block_data.mcv = operand_mcv for {}", .{operand_mcv}),
2569 };
25632570 } else {
25642571 try self.setRegOrMem(self.air.typeOfIndex(block), block_mcv, operand_mcv);
25652572 }
......@@ -2845,10 +2852,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
28452852
28462853 _ = try self.addInst(.{
28472854 .tag = .cset,
2848 .data = .{ .rrr_cond = .{
2855 .data = .{ .r_cond = .{
28492856 .rd = reg,
2850 .rn = .xzr,
2851 .rm = .xzr,
28522857 .cond = condition,
28532858 } },
28542859 });
......@@ -2933,7 +2938,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
29332938 } },
29342939 });
29352940 },
2936 3 => return self.fail("TODO implement genSetReg types size 3", .{}),
2941 3, 5, 6, 7 => return self.fail("TODO implement genSetReg types size {}", .{abi_size}),
29372942 else => unreachable,
29382943 }
29392944 },
......@@ -3114,27 +3119,6 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
31143119 }
31153120}
31163121
3117/// If the MCValue is an immediate, and it does not fit within this type,
3118/// we put it in a register.
3119/// A potential opportunity for future optimization here would be keeping track
3120/// of the fact that the instruction is available both as an immediate
3121/// and as a register.
3122fn limitImmediateType(self: *Self, operand: Air.Inst.Ref, comptime T: type) !MCValue {
3123 const mcv = try self.resolveInst(operand);
3124 const ti = @typeInfo(T).Int;
3125 switch (mcv) {
3126 .immediate => |imm| {
3127 // This immediate is unsigned.
3128 const U = std.meta.Int(.unsigned, ti.bits - @boolToInt(ti.signedness == .signed));
3129 if (imm >= math.maxInt(U)) {
3130 return MCValue{ .register = try self.copyToTmpRegister(Type.initTag(.usize), mcv) };
3131 }
3132 },
3133 else => {},
3134 }
3135 return mcv;
3136}
3137
31383122fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCValue {
31393123 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
31403124 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
......@@ -3248,19 +3232,11 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
32483232 }
32493233 },
32503234 .ErrorSet => {
3251 switch (typed_value.val.tag()) {
3252 .@"error" => {
3253 const err_name = typed_value.val.castTag(.@"error").?.data.name;
3254 const module = self.bin_file.options.module.?;
3255 const global_error_set = module.global_error_set;
3256 const error_index = global_error_set.get(err_name).?;
3257 return MCValue{ .immediate = error_index };
3258 },
3259 else => {
3260 // In this case we are rendering an error union which has a 0 bits payload.
3261 return MCValue{ .immediate = 0 };
3262 },
3263 }
3235 const err_name = typed_value.val.castTag(.@"error").?.data.name;
3236 const module = self.bin_file.options.module.?;
3237 const global_error_set = module.global_error_set;
3238 const error_index = global_error_set.get(err_name).?;
3239 return MCValue{ .immediate = error_index };
32643240 },
32653241 .ErrorUnion => {
32663242 const error_type = typed_value.ty.errorUnionSet();
......@@ -3425,13 +3401,18 @@ fn parseRegName(name: []const u8) ?Register {
34253401}
34263402
34273403fn registerAlias(reg: Register, size_bytes: u32) Register {
3428 _ = size_bytes;
3429
3430 return reg;
3404 if (size_bytes == 0) {
3405 unreachable; // should be comptime known
3406 } else if (size_bytes <= 4) {
3407 return reg.to32();
3408 } else if (size_bytes <= 8) {
3409 return reg.to64();
3410 } else {
3411 unreachable; // TODO handle floating-point registers
3412 }
34313413}
34323414
3433/// For most architectures this does nothing. For x86_64 it resolves any aliased registers
3434/// to the 64-bit wide ones.
3415/// Resolves any aliased registers to the 64-bit wide ones.
34353416fn toCanonicalReg(reg: Register) Register {
3436 return reg;
3417 return reg.to64();
34373418}
src/arch/aarch64/Emit.zig+33-40
......@@ -423,27 +423,30 @@ fn dbgAdvancePCAndLine(self: *Emit, line: u32, column: u32) !void {
423423
424424fn mirAddSubtractImmediate(emit: *Emit, inst: Mir.Inst.Index) !void {
425425 const tag = emit.mir.instructions.items(.tag)[inst];
426 const rr_imm12_sh = emit.mir.instructions.items(.data)[inst].rr_imm12_sh;
427
428426 switch (tag) {
429 .add_immediate => try emit.writeInstruction(Instruction.add(
430 rr_imm12_sh.rd,
431 rr_imm12_sh.rn,
432 rr_imm12_sh.imm12,
433 rr_imm12_sh.sh == 1,
434 )),
435 .cmp_immediate => try emit.writeInstruction(Instruction.subs(
436 rr_imm12_sh.rd,
437 rr_imm12_sh.rn,
438 rr_imm12_sh.imm12,
439 rr_imm12_sh.sh == 1,
440 )),
441 .sub_immediate => try emit.writeInstruction(Instruction.sub(
442 rr_imm12_sh.rd,
443 rr_imm12_sh.rn,
444 rr_imm12_sh.imm12,
445 rr_imm12_sh.sh == 1,
446 )),
427 .add_immediate,
428 .sub_immediate,
429 => {
430 const rr_imm12_sh = emit.mir.instructions.items(.data)[inst].rr_imm12_sh;
431 const rd = rr_imm12_sh.rd;
432 const rn = rr_imm12_sh.rn;
433 const imm12 = rr_imm12_sh.imm12;
434 const sh = rr_imm12_sh.sh == 1;
435
436 switch (tag) {
437 .add_immediate => try emit.writeInstruction(Instruction.add(rd, rn, imm12, sh)),
438 .sub_immediate => try emit.writeInstruction(Instruction.sub(rd, rn, imm12, sh)),
439 else => unreachable,
440 }
441 },
442 .cmp_immediate => {
443 const r_imm12_sh = emit.mir.instructions.items(.data)[inst].r_imm12_sh;
444 const rn = r_imm12_sh.rn;
445 const imm12 = r_imm12_sh.imm12;
446 const sh = r_imm12_sh.sh == 1;
447
448 try emit.writeInstruction(Instruction.subs(.xzr, rn, imm12, sh));
449 },
447450 else => unreachable,
448451 }
449452}
......@@ -589,15 +592,11 @@ fn mirAddSubtractShiftedRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
589592
590593fn mirConditionalSelect(emit: *Emit, inst: Mir.Inst.Index) !void {
591594 const tag = emit.mir.instructions.items(.tag)[inst];
592 const rrr_cond = emit.mir.instructions.items(.data)[inst].rrr_cond;
593
594595 switch (tag) {
595 .cset => try emit.writeInstruction(Instruction.csinc(
596 rrr_cond.rd,
597 rrr_cond.rn,
598 rrr_cond.rm,
599 rrr_cond.cond,
600 )),
596 .cset => {
597 const r_cond = emit.mir.instructions.items(.data)[inst].r_cond;
598 try emit.writeInstruction(Instruction.csinc(r_cond.rd, .xzr, .xzr, r_cond.cond));
599 },
601600 else => unreachable,
602601 }
603602}
......@@ -662,20 +661,14 @@ fn mirLoadMemory(emit: *Emit, inst: Mir.Inst.Index) !void {
662661fn mirLoadStoreRegisterPair(emit: *Emit, inst: Mir.Inst.Index) !void {
663662 const tag = emit.mir.instructions.items(.tag)[inst];
664663 const load_store_register_pair = emit.mir.instructions.items(.data)[inst].load_store_register_pair;
664 const rt = load_store_register_pair.rt;
665 const rt2 = load_store_register_pair.rt2;
666 const rn = load_store_register_pair.rn;
667 const offset = load_store_register_pair.offset;
665668
666669 switch (tag) {
667 .stp => try emit.writeInstruction(Instruction.stp(
668 load_store_register_pair.rt,
669 load_store_register_pair.rt2,
670 load_store_register_pair.rn,
671 load_store_register_pair.offset,
672 )),
673 .ldp => try emit.writeInstruction(Instruction.ldp(
674 load_store_register_pair.rt,
675 load_store_register_pair.rt2,
676 load_store_register_pair.rn,
677 load_store_register_pair.offset,
678 )),
670 .stp => try emit.writeInstruction(Instruction.stp(rt, rt2, rn, offset)),
671 .ldp => try emit.writeInstruction(Instruction.ldp(rt, rt2, rn, offset)),
679672 else => unreachable,
680673 }
681674}
src/arch/aarch64/Mir.zig+15-9
......@@ -175,6 +175,13 @@ pub const Inst = struct {
175175 imm16: u16,
176176 hw: u2 = 0,
177177 },
178 /// A register and a condition
179 ///
180 /// Used by e.g. cset
181 r_cond: struct {
182 rd: Register,
183 cond: bits.Instruction.Condition,
184 },
178185 /// Two registers
179186 ///
180187 /// Used by e.g. mov_register
......@@ -182,6 +189,14 @@ pub const Inst = struct {
182189 rd: Register,
183190 rn: Register,
184191 },
192 /// A register, an unsigned 12-bit immediate, and an optional shift
193 ///
194 /// Used by e.g. cmp_immediate
195 r_imm12_sh: struct {
196 rn: Register,
197 imm12: u12,
198 sh: u1 = 0,
199 },
185200 /// Two registers, an unsigned 12-bit immediate, and an optional shift
186201 ///
187202 /// Used by e.g. sub_immediate
......@@ -209,15 +224,6 @@ pub const Inst = struct {
209224 imm6: u6,
210225 shift: bits.Instruction.AddSubtractShiftedRegisterShift,
211226 },
212 /// Three registers and a condition
213 ///
214 /// Used by e.g. cset
215 rrr_cond: struct {
216 rd: Register,
217 rn: Register,
218 rm: Register,
219 cond: bits.Instruction.Condition,
220 },
221227 /// Two registers and a LoadStoreOffsetImmediate
222228 ///
223229 /// Used by e.g. str_immediate