From f47245865eea35fa0b08cb2a87e3620fa904dd88 Mon Sep 17 00:00:00 2001 From: joachimschmidt557 Date: Tue, 8 Feb 2022 19:57:01 +0100 Subject: [PATCH] stage2 AArch64: minor refactors in Mir + Emit --- src/arch/aarch64/CodeGen.zig | 79 ++++++++++++++---------------------- src/arch/aarch64/Emit.zig | 73 +++++++++++++++------------------ src/arch/aarch64/Mir.zig | 24 +++++++---- 3 files changed, 78 insertions(+), 98 deletions(-) diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index bd6b875550..4e14760286 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/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(); } diff --git a/src/arch/aarch64/Emit.zig b/src/arch/aarch64/Emit.zig index 140d0664b5..786fa4b3f3 100644 --- a/src/arch/aarch64/Emit.zig +++ b/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, } } diff --git a/src/arch/aarch64/Mir.zig b/src/arch/aarch64/Mir.zig index 4f653ff072..6bb681acb8 100644 --- a/src/arch/aarch64/Mir.zig +++ b/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