Commit f47245865e

joachimschmidt557 <joachim.schmidt557@outlook.com>
2022-02-08 19:57:01
stage2 AArch64: minor refactors in Mir + Emit
1 parent f598d2a
Changed files (3)
src/arch/aarch64/CodeGen.zig
@@ -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();
 }
src/arch/aarch64/Emit.zig
@@ -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,
     }
 }
src/arch/aarch64/Mir.zig
@@ -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