aboutsummaryrefslogtreecommitdiff
path: root/src/arch/arm/CodeGen.zig
diff options
context:
space:
mode:
authorJoachim Schmidt <joachim.schmidt557@outlook.com>2022-03-11 17:43:36 +0100
committerGitHub <noreply@github.com>2022-03-11 17:43:36 +0100
commit5fbae9cd6fe7a53d85ad6dd20cab75f7b835f0ad (patch)
treeba874ceb64ee6c2de89223dbf87d4b0e0018d78f /src/arch/arm/CodeGen.zig
parent078037ab9b410fa13a86eabdfc30918fc83cdcf3 (diff)
parent4590e980f77f406158258c8f44a76e28d53eff2f (diff)
downloadzig-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.zig58
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);