diff options
| author | Joachim Schmidt <joachim.schmidt557@outlook.com> | 2022-03-11 17:43:36 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-03-11 17:43:36 +0100 |
| commit | 5fbae9cd6fe7a53d85ad6dd20cab75f7b835f0ad (patch) | |
| tree | ba874ceb64ee6c2de89223dbf87d4b0e0018d78f /src/arch/arm/CodeGen.zig | |
| parent | 078037ab9b410fa13a86eabdfc30918fc83cdcf3 (diff) | |
| parent | 4590e980f77f406158258c8f44a76e28d53eff2f (diff) | |
| download | zig-5fbae9cd6fe7a53d85ad6dd20cab75f7b835f0ad.tar.gz zig-5fbae9cd6fe7a53d85ad6dd20cab75f7b835f0ad.zip | |
Merge pull request #11121 from joachimschmidt557/stage2-arm
stage2 ARM: implement caller-preserved registers
Diffstat (limited to 'src/arch/arm/CodeGen.zig')
| -rw-r--r-- | src/arch/arm/CodeGen.zig | 58 |
1 files changed, 32 insertions, 26 deletions
diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig index 3a247c09f2..2248daf1d0 100644 --- a/src/arch/arm/CodeGen.zig +++ b/src/arch/arm/CodeGen.zig @@ -21,12 +21,24 @@ const DW = std.dwarf; const leb128 = std.leb; const log = std.log.scoped(.codegen); const build_options = @import("build_options"); -const RegisterManager = @import("../../register_manager.zig").RegisterManager; +const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager; +const RegisterManager = RegisterManagerFn(Self, Register, &allocatable_registers); const FnResult = @import("../../codegen.zig").FnResult; const GenerateSymbolError = @import("../../codegen.zig").GenerateSymbolError; const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput; +const bits = @import("bits.zig"); +const abi = @import("abi.zig"); +const Register = bits.Register; +const Instruction = bits.Instruction; +const Condition = bits.Condition; +const callee_preserved_regs = abi.callee_preserved_regs; +const caller_preserved_regs = abi.caller_preserved_regs; +const allocatable_registers = abi.allocatable_registers; +const c_abi_int_param_regs = abi.c_abi_int_param_regs; +const c_abi_int_return_regs = abi.c_abi_int_return_regs; + const InnerError = error{ OutOfMemory, CodegenFail, @@ -73,7 +85,7 @@ branch_stack: *std.ArrayList(Branch), // Key is the block instruction blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, BlockData) = .{}, -register_manager: RegisterManager(Self, Register, &callee_preserved_regs) = .{}, +register_manager: RegisterManager = .{}, /// Maps offset to what is stored there. stack: std.AutoHashMapUnmanaged(u32, StackAllocation) = .{}, /// Tracks the current instruction allocated to the compare flags @@ -778,10 +790,6 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { if (!elem_ty.hasRuntimeBits()) { // As this stack item will never be dereferenced at runtime, // return the current stack offset - try self.stack.putNoClobber(self.gpa, self.next_stack_offset, .{ - .inst = inst, - .size = 0, - }); return self.next_stack_offset; } @@ -1559,13 +1567,13 @@ fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_ind switch (mcv) { .register => |reg| { - // If it's in the registers table, need to associate the register with the - // new instruction. - if (reg.allocIndex()) |index| { - if (!self.register_manager.isRegFree(reg)) { - self.register_manager.registers[index] = inst; - } + // We assert that this register is allocatable by asking + // for its index + const index = RegisterManager.indexOfRegIntoTracked(reg).?; // see note above + if (!self.register_manager.isRegFree(reg)) { + self.register_manager.registers[index] = inst; } + log.debug("%{d} => {} (reused)", .{ inst, reg }); }, .stack_offset => |off| { @@ -2535,13 +2543,17 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. // Architecture, compare flags are not preserved across // calls. Therefore, if some value is currently stored there, we // need to save it. - // - // TODO once caller-saved registers are implemented, save them - // here too, but crucially *after* we save the compare flags as - // saving compare flags may require a new caller-saved register try self.spillCompareFlagsIfOccupied(); + // Save caller-saved registers, but crucially *after* we save the + // compare flags as saving compare flags may require a new + // caller-saved register + for (caller_preserved_regs) |reg| { + try self.register_manager.getReg(reg, null); + } + if (info.return_value == .stack_offset) { + log.debug("airCall: return by reference", .{}); const ret_ty = fn_ty.fnReturnType(); const ret_abi_size = @intCast(u32, ret_ty.abiSize(self.target.*)); const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(self.target.*)); @@ -2552,7 +2564,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. .data = ret_ty, }; const ptr_ty = Type.initPayload(&ptr_ty_payload.base); - try self.register_manager.getReg(.r0, inst); + try self.register_manager.getReg(.r0, null); try self.genSetReg(ptr_ty, .r0, .{ .ptr_stack_offset = stack_offset }); info.return_value = .{ .stack_offset = stack_offset }; @@ -2652,8 +2664,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. const result: MCValue = result: { switch (info.return_value) { .register => |reg| { - if (Register.allocIndex(reg) == null) { - // Save function return value in a callee saved register + if (RegisterManager.indexOfRegIntoTracked(reg) == null) { + // Save function return value into a tracked register + log.debug("airCall: copying {} as it is not tracked", .{reg}); break :result try self.copyToNewRegister(inst, info.return_value); } }, @@ -4495,13 +4508,6 @@ fn failSymbol(self: *Self, comptime format: []const u8, args: anytype) InnerErro return error.CodegenFail; } -const Register = @import("bits.zig").Register; -const Instruction = @import("bits.zig").Instruction; -const Condition = @import("bits.zig").Condition; -const callee_preserved_regs = @import("bits.zig").callee_preserved_regs; -const c_abi_int_param_regs = @import("bits.zig").c_abi_int_param_regs; -const c_abi_int_return_regs = @import("bits.zig").c_abi_int_return_regs; - fn parseRegName(name: []const u8) ?Register { if (@hasDecl(Register, "parseRegName")) { return Register.parseRegName(name); |
