aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.zig
diff options
context:
space:
mode:
authorjoachimschmidt557 <joachim.schmidt557@outlook.com>2021-10-15 15:54:00 +0200
committerAndrew Kelley <andrew@ziglang.org>2021-10-15 13:58:14 -0400
commit01b390568872344e53862d61da091071e0ab1f3e (patch)
tree1aeaab0e2cf2147affed763d41eb0e4dd9aa328b /src/codegen.zig
parent6a9726e495650602638037c9ec022e264eadb586 (diff)
downloadzig-01b390568872344e53862d61da091071e0ab1f3e.tar.gz
zig-01b390568872344e53862d61da091071e0ab1f3e.zip
stage2 AArch64: move codegen to separate file
Diffstat (limited to 'src/codegen.zig')
-rw-r--r--src/codegen.zig536
1 files changed, 5 insertions, 531 deletions
diff --git a/src/codegen.zig b/src/codegen.zig
index 8745c1aa58..0371f32a8a 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -88,9 +88,9 @@ pub fn generateFunction(
.wasm64 => unreachable, // has its own code path
.arm => return Function(.arm).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
.armeb => return Function(.armeb).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
- .aarch64 => return Function(.aarch64).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
- .aarch64_be => return Function(.aarch64_be).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
- .aarch64_32 => return Function(.aarch64_32).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
+ .aarch64 => return @import("arch/aarch64/CodeGen.zig").generate(.aarch64, bin_file, src_loc, func, air, liveness, code, debug_output),
+ .aarch64_be => return @import("arch/aarch64/CodeGen.zig").generate(.aarch64_be, bin_file, src_loc, func, air, liveness, code, debug_output),
+ .aarch64_32 => return @import("arch/aarch64/CodeGen.zig").generate(.aarch64_32, bin_file, src_loc, func, air, liveness, code, debug_output),
//.arc => return Function(.arc).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
//.avr => return Function(.avr).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
//.bpfel => return Function(.bpfel).generate(bin_file, src_loc, func, air, liveness, code, debug_output),
@@ -730,82 +730,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
try self.dbgSetEpilogueBegin();
}
},
- .aarch64, .aarch64_be, .aarch64_32 => {
- const cc = self.fn_type.fnCallingConvention();
- if (cc != .Naked) {
- // TODO Finish function prologue and epilogue for aarch64.
-
- // stp fp, lr, [sp, #-16]!
- // mov fp, sp
- // sub sp, sp, #reloc
- writeInt(u32, try self.code.addManyAsArray(4), Instruction.stp(
- .x29,
- .x30,
- Register.sp,
- Instruction.LoadStorePairOffset.pre_index(-16),
- ).toU32());
- writeInt(u32, try self.code.addManyAsArray(4), Instruction.add(.x29, .xzr, 0, false).toU32());
- const backpatch_reloc = self.code.items.len;
- try self.code.resize(backpatch_reloc + 4);
-
- try self.dbgSetPrologueEnd();
-
- try self.genBody(self.air.getMainBody());
-
- // Backpatch stack offset
- const stack_end = self.max_end_stack;
- const aligned_stack_end = mem.alignForward(stack_end, self.stack_align);
- if (math.cast(u12, aligned_stack_end)) |size| {
- writeInt(u32, self.code.items[backpatch_reloc..][0..4], Instruction.sub(.xzr, .xzr, size, false).toU32());
- } else |_| {
- return self.failSymbol("TODO AArch64: allow larger stacks", .{});
- }
-
- try self.dbgSetEpilogueBegin();
-
- // exitlude jumps
- if (self.exitlude_jump_relocs.items.len == 1) {
- // There is only one relocation. Hence,
- // this relocation must be at the end of
- // the code. Therefore, we can just delete
- // the space initially reserved for the
- // jump
- self.code.items.len -= 4;
- } else for (self.exitlude_jump_relocs.items) |jmp_reloc| {
- const amt = @intCast(i32, self.code.items.len) - @intCast(i32, jmp_reloc + 8);
- if (amt == -4) {
- // This return is at the end of the
- // code block. We can't just delete
- // the space because there may be
- // other jumps we already relocated to
- // the address. Instead, insert a nop
- writeInt(u32, self.code.items[jmp_reloc..][0..4], Instruction.nop().toU32());
- } else {
- if (math.cast(i28, amt)) |offset| {
- writeInt(u32, self.code.items[jmp_reloc..][0..4], Instruction.b(offset).toU32());
- } else |_| {
- return self.failSymbol("exitlude jump is too large", .{});
- }
- }
- }
-
- // ldp fp, lr, [sp], #16
- writeInt(u32, try self.code.addManyAsArray(4), Instruction.ldp(
- .x29,
- .x30,
- Register.sp,
- Instruction.LoadStorePairOffset.post_index(16),
- ).toU32());
- // add sp, sp, #stack_size
- writeInt(u32, try self.code.addManyAsArray(4), Instruction.add(.xzr, .xzr, @intCast(u12, aligned_stack_end), false).toU32());
- // ret lr
- writeInt(u32, try self.code.addManyAsArray(4), Instruction.ret(null).toU32());
- } else {
- try self.dbgSetPrologueEnd();
- try self.genBody(self.air.getMainBody());
- try self.dbgSetEpilogueBegin();
- }
- },
else => {
try self.dbgSetPrologueEnd();
try self.genBody(self.air.getMainBody());
@@ -2690,7 +2614,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
const result = self.args[arg_index];
const mcv = switch (arch) {
// TODO support stack-only arguments on all target architectures
- .arm, .armeb, .aarch64, .aarch64_32, .aarch64_be => switch (result) {
+ .arm, .armeb => switch (result) {
// Copy registers to the stack
.register => |reg| blk: {
const abi_size = math.cast(u32, ty.abiSize(self.target.*)) catch {
@@ -2732,9 +2656,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
.arm, .armeb => {
writeInt(u32, try self.code.addManyAsArray(4), Instruction.bkpt(0).toU32());
},
- .aarch64 => {
- mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.brk(1).toU32());
- },
else => return self.fail("TODO implement @breakpoint() for {}", .{self.target.cpu.arch}),
}
return self.finishAirBookkeeping();
@@ -2913,63 +2834,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
return self.fail("TODO implement calling runtime known function pointer", .{});
}
},
- .aarch64 => {
- for (info.args) |mc_arg, arg_i| {
- const arg = args[arg_i];
- const arg_ty = self.air.typeOf(arg);
- const arg_mcv = try self.resolveInst(args[arg_i]);
-
- switch (mc_arg) {
- .none => continue,
- .undef => unreachable,
- .immediate => unreachable,
- .unreach => unreachable,
- .dead => unreachable,
- .embedded_in_code => unreachable,
- .memory => unreachable,
- .compare_flags_signed => unreachable,
- .compare_flags_unsigned => unreachable,
- .register => |reg| {
- try self.register_manager.getReg(reg, null);
- try self.genSetReg(arg_ty, reg, arg_mcv);
- },
- .stack_offset => {
- return self.fail("TODO implement calling with parameters in memory", .{});
- },
- .ptr_stack_offset => {
- return self.fail("TODO implement calling with MCValue.ptr_stack_offset arg", .{});
- },
- .ptr_embedded_in_code => {
- return self.fail("TODO implement calling with MCValue.ptr_embedded_in_code arg", .{});
- },
- }
- }
-
- if (self.air.value(callee)) |func_value| {
- if (func_value.castTag(.function)) |func_payload| {
- const func = func_payload.data;
- const ptr_bits = self.target.cpu.arch.ptrBitWidth();
- const ptr_bytes: u64 = @divExact(ptr_bits, 8);
- const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: {
- const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];
- break :blk @intCast(u32, got.p_vaddr + func.owner_decl.link.elf.offset_table_index * ptr_bytes);
- } else if (self.bin_file.cast(link.File.Coff)) |coff_file|
- coff_file.offset_table_virtual_address + func.owner_decl.link.coff.offset_table_index * ptr_bytes
- else
- unreachable;
-
- try self.genSetReg(Type.initTag(.usize), .x30, .{ .memory = got_addr });
-
- writeInt(u32, try self.code.addManyAsArray(4), Instruction.blr(.x30).toU32());
- } else if (func_value.castTag(.extern_fn)) |_| {
- return self.fail("TODO implement calling extern functions", .{});
- } else {
- return self.fail("TODO implement calling bitcasted functions", .{});
- }
- } else {
- return self.fail("TODO implement calling runtime known function pointer", .{});
- }
- },
else => return self.fail("TODO implement call for {}", .{self.target.cpu.arch}),
}
} else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
@@ -2984,7 +2848,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
.register => |reg| {
// TODO prevent this macho if block to be generated for all archs
switch (arch) {
- .x86_64, .aarch64 => try self.register_manager.getReg(reg, null),
+ .x86_64 => try self.register_manager.getReg(reg, null),
else => unreachable,
}
try self.genSetReg(arg_ty, reg, arg_mcv);
@@ -3025,13 +2889,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
try self.code.ensureUnusedCapacity(2);
self.code.appendSliceAssumeCapacity(&[2]u8{ 0xff, 0xd0 });
},
- .aarch64 => {
- try self.genSetReg(Type.initTag(.u64), .x30, .{
- .memory = func.owner_decl.link.macho.local_sym_index,
- });
- // blr x30
- writeInt(u32, try self.code.addManyAsArray(4), Instruction.blr(.x30).toU32());
- },
else => unreachable, // unsupported architecture on MachO
}
} else if (func_value.castTag(.extern_fn)) |func_payload| {
@@ -3045,12 +2902,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
self.code.appendSliceAssumeCapacity(&[5]u8{ 0xe8, 0x0, 0x0, 0x0, 0x0 });
break :blk @intCast(u32, self.code.items.len) - 4;
},
- .aarch64 => {
- const offset = @intCast(u32, self.code.items.len);
- // bl
- writeInt(u32, try self.code.addManyAsArray(4), Instruction.bl(0).toU32());
- break :blk offset;
- },
else => unreachable, // unsupported architecture on MachO
}
};
@@ -3063,7 +2914,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
.pcrel = true,
.length = 2,
.@"type" = switch (arch) {
- .aarch64 => @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_BRANCH26),
.x86_64 => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_BRANCH),
else => unreachable,
},
@@ -3127,58 +2977,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
return self.fail("TODO implement calling runtime known function pointer", .{});
}
},
- .aarch64 => {
- for (info.args) |mc_arg, arg_i| {
- const arg = args[arg_i];
- const arg_ty = self.air.typeOf(arg);
- const arg_mcv = try self.resolveInst(args[arg_i]);
-
- switch (mc_arg) {
- .none => continue,
- .undef => unreachable,
- .immediate => unreachable,
- .unreach => unreachable,
- .dead => unreachable,
- .embedded_in_code => unreachable,
- .memory => unreachable,
- .compare_flags_signed => unreachable,
- .compare_flags_unsigned => unreachable,
- .register => |reg| {
- try self.register_manager.getReg(reg, null);
- try self.genSetReg(arg_ty, reg, arg_mcv);
- },
- .stack_offset => {
- return self.fail("TODO implement calling with parameters in memory", .{});
- },
- .ptr_stack_offset => {
- return self.fail("TODO implement calling with MCValue.ptr_stack_offset arg", .{});
- },
- .ptr_embedded_in_code => {
- return self.fail("TODO implement calling with MCValue.ptr_embedded_in_code arg", .{});
- },
- }
- }
- if (self.air.value(callee)) |func_value| {
- if (func_value.castTag(.function)) |func_payload| {
- try p9.seeDecl(func_payload.data.owner_decl);
- const ptr_bits = self.target.cpu.arch.ptrBitWidth();
- const ptr_bytes: u64 = @divExact(ptr_bits, 8);
- const got_addr = p9.bases.data;
- const got_index = func_payload.data.owner_decl.link.plan9.got_index.?;
- const fn_got_addr = got_addr + got_index * ptr_bytes;
-
- try self.genSetReg(Type.initTag(.usize), .x30, .{ .memory = fn_got_addr });
-
- writeInt(u32, try self.code.addManyAsArray(4), Instruction.blr(.x30).toU32());
- } else if (func_value.castTag(.extern_fn)) |_| {
- return self.fail("TODO implement calling extern functions", .{});
- } else {
- return self.fail("TODO implement calling bitcasted functions", .{});
- }
- } else {
- return self.fail("TODO implement calling runtime known function pointer", .{});
- }
- },
else => return self.fail("TODO implement call on plan9 for {}", .{self.target.cpu.arch}),
}
} else unreachable;
@@ -3233,11 +3031,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
try self.code.resize(self.code.items.len + 4);
try self.exitlude_jump_relocs.append(self.gpa, self.code.items.len - 4);
},
- .aarch64 => {
- // Just add space for an instruction, patch this later
- try self.code.resize(self.code.items.len + 4);
- try self.exitlude_jump_relocs.append(self.gpa, self.code.items.len - 4);
- },
else => return self.fail("TODO implement return for {}", .{self.target.cpu.arch}),
}
}
@@ -3731,13 +3524,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
return self.fail("TODO: enable larger branch offset", .{});
}
},
- .aarch64, .aarch64_be, .aarch64_32 => {
- if (math.cast(i28, @intCast(i32, index) - @intCast(i32, self.code.items.len + 8))) |delta| {
- writeInt(u32, try self.code.addManyAsArray(4), Instruction.b(delta).toU32());
- } else |_| {
- return self.fail("TODO: enable larger branch offset", .{});
- }
- },
else => return self.fail("TODO implement jump for {}", .{self.target.cpu.arch}),
}
}
@@ -3944,44 +3730,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
break :result MCValue{ .none = {} };
}
},
- .aarch64 => result: {
- for (args) |arg| {
- const input = zir.extraData(Zir.Inst.Asm.Input, extra_i);
- extra_i = input.end;
- const constraint = zir.nullTerminatedString(input.data.constraint);
-
- if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') {
- return self.fail("unrecognized asm input constraint: '{s}'", .{constraint});
- }
- const reg_name = constraint[1 .. constraint.len - 1];
- const reg = parseRegName(reg_name) orelse
- return self.fail("unrecognized register: '{s}'", .{reg_name});
-
- const arg_mcv = try self.resolveInst(arg);
- try self.register_manager.getReg(reg, null);
- try self.genSetReg(self.air.typeOf(arg), reg, arg_mcv);
- }
-
- if (mem.eql(u8, asm_source, "svc #0")) {
- mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.svc(0x0).toU32());
- } else if (mem.eql(u8, asm_source, "svc #0x80")) {
- mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.svc(0x80).toU32());
- } else {
- return self.fail("TODO implement support for more aarch64 assembly instructions", .{});
- }
-
- if (output_constraint) |output| {
- if (output.len < 4 or output[0] != '=' or output[1] != '{' or output[output.len - 1] != '}') {
- return self.fail("unrecognized asm output constraint: '{s}'", .{output});
- }
- const reg_name = output[2 .. output.len - 1];
- const reg = parseRegName(reg_name) orelse
- return self.fail("unrecognized register: '{s}'", .{reg_name});
- break :result MCValue{ .register = reg };
- } else {
- break :result MCValue{ .none = {} };
- }
- },
.riscv64 => result: {
for (args) |arg| {
const input = zir.extraData(Zir.Inst.Asm.Input, extra_i);
@@ -4303,75 +4051,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
},
},
- .aarch64, .aarch64_be, .aarch64_32 => switch (mcv) {
- .dead => unreachable,
- .ptr_stack_offset => unreachable,
- .ptr_embedded_in_code => unreachable,
- .unreach, .none => return, // Nothing to do.
- .undef => {
- if (!self.wantSafety())
- return; // The already existing value will do just fine.
- // TODO Upgrade this to a memset call when we have that available.
- switch (ty.abiSize(self.target.*)) {
- 1 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaa }),
- 2 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaa }),
- 4 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }),
- 8 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaaaaaaaaaa }),
- else => return self.fail("TODO implement memset", .{}),
- }
- },
- .compare_flags_unsigned,
- .compare_flags_signed,
- .immediate,
- => {
- const reg = try self.copyToTmpRegister(ty, mcv);
- return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
- },
- .embedded_in_code => |code_offset| {
- _ = code_offset;
- return self.fail("TODO implement set stack variable from embedded_in_code", .{});
- },
- .register => |reg| {
- const abi_size = ty.abiSize(self.target.*);
- const adj_off = stack_offset + abi_size;
-
- switch (abi_size) {
- 1, 2, 4, 8 => {
- const offset = if (math.cast(i9, adj_off)) |imm|
- Instruction.LoadStoreOffset.imm_post_index(-imm)
- else |_|
- Instruction.LoadStoreOffset.reg(try self.copyToTmpRegister(Type.initTag(.u64), MCValue{ .immediate = adj_off }));
- const rn: Register = switch (arch) {
- .aarch64, .aarch64_be => .x29,
- .aarch64_32 => .w29,
- else => unreachable,
- };
- const str = switch (abi_size) {
- 1 => Instruction.strb,
- 2 => Instruction.strh,
- 4, 8 => Instruction.str,
- else => unreachable, // unexpected abi size
- };
-
- writeInt(u32, try self.code.addManyAsArray(4), str(reg, rn, .{
- .offset = offset,
- }).toU32());
- },
- else => return self.fail("TODO implement storing other types abi_size={}", .{abi_size}),
- }
- },
- .memory => |vaddr| {
- _ = vaddr;
- return self.fail("TODO implement set stack variable from memory vaddr", .{});
- },
- .stack_offset => |off| {
- if (stack_offset == off)
- return; // Copy stack variable to itself; nothing to do.
-
- const reg = try self.copyToTmpRegister(ty, mcv);
- return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
- },
- },
else => return self.fail("TODO implement getSetStack for {}", .{self.target.cpu.arch}),
}
}
@@ -4491,141 +4170,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
},
else => return self.fail("TODO implement getSetReg for arm {}", .{mcv}),
},
- .aarch64 => switch (mcv) {
- .dead => unreachable,
- .ptr_stack_offset => unreachable,
- .ptr_embedded_in_code => unreachable,
- .unreach, .none => return, // Nothing to do.
- .undef => {
- if (!self.wantSafety())
- return; // The already existing value will do just fine.
- // Write the debug undefined value.
- switch (reg.size()) {
- 32 => return self.genSetReg(ty, reg, .{ .immediate = 0xaaaaaaaa }),
- 64 => return self.genSetReg(ty, reg, .{ .immediate = 0xaaaaaaaaaaaaaaaa }),
- else => unreachable, // unexpected register size
- }
- },
- .immediate => |x| {
- if (x <= math.maxInt(u16)) {
- mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.movz(reg, @intCast(u16, x), 0).toU32());
- } else if (x <= math.maxInt(u32)) {
- mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.movz(reg, @truncate(u16, x), 0).toU32());
- mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.movk(reg, @intCast(u16, x >> 16), 16).toU32());
- } else if (x <= math.maxInt(u32)) {
- mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.movz(reg, @truncate(u16, x), 0).toU32());
- mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.movk(reg, @truncate(u16, x >> 16), 16).toU32());
- mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.movk(reg, @intCast(u16, x >> 32), 32).toU32());
- } else {
- mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.movz(reg, @truncate(u16, x), 0).toU32());
- mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.movk(reg, @truncate(u16, x >> 16), 16).toU32());
- mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.movk(reg, @truncate(u16, x >> 32), 32).toU32());
- mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.movk(reg, @intCast(u16, x >> 48), 48).toU32());
- }
- },
- .register => |src_reg| {
- // If the registers are the same, nothing to do.
- if (src_reg.id() == reg.id())
- return;
-
- // mov reg, src_reg
- writeInt(u32, try self.code.addManyAsArray(4), Instruction.orr(
- reg,
- .xzr,
- src_reg,
- Instruction.Shift.none,
- ).toU32());
- },
- .memory => |addr| {
- if (self.bin_file.options.pie) {
- // PC-relative displacement to the entry in the GOT table.
- // adrp
- const offset = @intCast(u32, self.code.items.len);
- mem.writeIntLittle(
- u32,
- try self.code.addManyAsArray(4),
- Instruction.adrp(reg, 0).toU32(),
- );
- // ldr reg, reg, offset
- mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.ldr(reg, .{
- .register = .{
- .rn = reg,
- .offset = Instruction.LoadStoreOffset.imm(0),
- },
- }).toU32());
-
- if (self.bin_file.cast(link.File.MachO)) |macho_file| {
- // TODO I think the reloc might be in the wrong place.
- const decl = macho_file.active_decl.?;
- // Page reloc for adrp instruction.
- try decl.link.macho.relocs.append(self.bin_file.allocator, .{
- .offset = offset,
- .target = .{ .local = @intCast(u32, addr) },
- .addend = 0,
- .subtractor = null,
- .pcrel = true,
- .length = 2,
- .@"type" = @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_GOT_LOAD_PAGE21),
- });
- // Pageoff reloc for adrp instruction.
- try decl.link.macho.relocs.append(self.bin_file.allocator, .{
- .offset = offset + 4,
- .target = .{ .local = @intCast(u32, addr) },
- .addend = 0,
- .subtractor = null,
- .pcrel = false,
- .length = 2,
- .@"type" = @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_GOT_LOAD_PAGEOFF12),
- });
- } else {
- return self.fail("TODO implement genSetReg for PIE GOT indirection on this platform", .{});
- }
- } else {
- // The value is in memory at a hard-coded address.
- // If the type is a pointer, it means the pointer address is at this memory location.
- try self.genSetReg(Type.initTag(.usize), reg, .{ .immediate = addr });
- mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.ldr(reg, .{ .register = .{ .rn = reg } }).toU32());
- }
- },
- .stack_offset => |unadjusted_off| {
- // TODO: maybe addressing from sp instead of fp
- const abi_size = ty.abiSize(self.target.*);
- const adj_off = unadjusted_off + abi_size;
-
- const rn: Register = switch (arch) {
- .aarch64, .aarch64_be => .x29,
- .aarch64_32 => .w29,
- else => unreachable,
- };
-
- const offset = if (math.cast(i9, adj_off)) |imm|
- Instruction.LoadStoreOffset.imm_post_index(-imm)
- else |_|
- Instruction.LoadStoreOffset.reg(try self.copyToTmpRegister(Type.initTag(.u64), MCValue{ .immediate = adj_off }));
-
- switch (abi_size) {
- 1, 2 => {
- const ldr = switch (abi_size) {
- 1 => Instruction.ldrb,
- 2 => Instruction.ldrh,
- else => unreachable, // unexpected abi size
- };
-
- writeInt(u32, try self.code.addManyAsArray(4), ldr(reg, rn, .{
- .offset = offset,
- }).toU32());
- },
- 4, 8 => {
- writeInt(u32, try self.code.addManyAsArray(4), Instruction.ldr(reg, .{ .register = .{
- .rn = rn,
- .offset = offset,
- } }).toU32());
- },
- else => return self.fail("TODO implement genSetReg other types abi_size={}", .{abi_size}),
- }
- },
- else => return self.fail("TODO implement genSetReg for aarch64 {}", .{mcv}),
- },
.riscv64 => switch (mcv) {
.dead => unreachable,
.ptr_stack_offset => unreachable,
@@ -5358,59 +4902,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
else => return self.fail("TODO implement function parameters for {} on arm", .{cc}),
}
},
- .aarch64 => {
- switch (cc) {
- .Naked => {
- assert(result.args.len == 0);
- result.return_value = .{ .unreach = {} };
- result.stack_byte_count = 0;
- result.stack_align = 1;
- return result;
- },
- .Unspecified, .C => {
- // ARM64 Procedure Call Standard
- var ncrn: usize = 0; // Next Core Register Number
- var nsaa: u32 = 0; // Next stacked argument address
-
- for (param_types) |ty, i| {
- // We round up NCRN only for non-Apple platforms which allow the 16-byte aligned
- // values to spread across odd-numbered registers.
- if (ty.abiAlignment(self.target.*) == 16 and !self.target.isDarwin()) {
- // Round up NCRN to the next even number
- ncrn += ncrn % 2;
- }
-
- const param_size = @intCast(u32, ty.abiSize(self.target.*));
- if (std.math.divCeil(u32, param_size, 8) catch unreachable <= 8 - ncrn) {
- if (param_size <= 8) {
- result.args[i] = .{ .register = c_abi_int_param_regs[ncrn] };
- ncrn += 1;
- } else {
- return self.fail("TODO MCValues with multiple registers", .{});
- }
- } else if (ncrn < 8 and nsaa == 0) {
- return self.fail("TODO MCValues split between registers and stack", .{});
- } else {
- ncrn = 8;
- // TODO Apple allows the arguments on the stack to be non-8-byte aligned provided
- // that the entire stack space consumed by the arguments is 8-byte aligned.
- if (ty.abiAlignment(self.target.*) == 8) {
- if (nsaa % 8 != 0) {
- nsaa += 8 - (nsaa % 8);
- }
- }
-
- result.args[i] = .{ .stack_offset = nsaa };
- nsaa += param_size;
- }
- }
-
- result.stack_byte_count = nsaa;
- result.stack_align = 16;
- },
- else => return self.fail("TODO implement function parameters for {} on aarch64", .{cc}),
- }
- },
else => if (param_types.len != 0)
return self.fail("TODO implement codegen parameters for {}", .{self.target.cpu.arch}),
}
@@ -5441,18 +4932,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
},
else => return self.fail("TODO implement function return values for {}", .{cc}),
},
- .aarch64 => switch (cc) {
- .Naked => unreachable,
- .Unspecified, .C => {
- const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*));
- if (ret_ty_size <= 8) {
- result.return_value = .{ .register = c_abi_int_return_regs[0] };
- } else {
- return self.fail("TODO support more return types for ARM backend", .{});
- }
- },
- else => return self.fail("TODO implement function return values for {}", .{cc}),
- },
else => return self.fail("TODO implement codegen return values for {}", .{self.target.cpu.arch}),
}
return result;
@@ -5487,7 +4966,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
.x86_64 => @import("arch/x86_64/bits.zig").Register,
.riscv64 => @import("arch/riscv64/bits.zig").Register,
.arm, .armeb => @import("arch/arm/bits.zig").Register,
- .aarch64, .aarch64_be, .aarch64_32 => @import("arch/aarch64/bits.zig").Register,
else => enum {
dummy,
@@ -5501,7 +4979,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
const Instruction = switch (arch) {
.riscv64 => @import("arch/riscv64/bits.zig").Instruction,
.arm, .armeb => @import("arch/arm/bits.zig").Instruction,
- .aarch64, .aarch64_be, .aarch64_32 => @import("arch/aarch64/bits.zig").Instruction,
else => void,
};
@@ -5515,7 +4992,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
.x86_64 => @import("arch/x86_64/bits.zig").callee_preserved_regs,
.riscv64 => @import("arch/riscv64/bits.zig").callee_preserved_regs,
.arm, .armeb => @import("arch/arm/bits.zig").callee_preserved_regs,
- .aarch64, .aarch64_be, .aarch64_32 => @import("arch/aarch64/bits.zig").callee_preserved_regs,
else => [_]Register{},
};
@@ -5523,7 +4999,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
.i386 => @import("arch/x86/bits.zig").c_abi_int_param_regs,
.x86_64 => @import("arch/x86_64/bits.zig").c_abi_int_param_regs,
.arm, .armeb => @import("arch/arm/bits.zig").c_abi_int_param_regs,
- .aarch64, .aarch64_be, .aarch64_32 => @import("arch/aarch64/bits.zig").c_abi_int_param_regs,
else => [_]Register{},
};
@@ -5531,7 +5006,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
.i386 => @import("arch/x86/bits.zig").c_abi_int_return_regs,
.x86_64 => @import("arch/x86_64/bits.zig").c_abi_int_return_regs,
.arm, .armeb => @import("arch/arm/bits.zig").c_abi_int_return_regs,
- .aarch64, .aarch64_be, .aarch64_32 => @import("arch/aarch64/bits.zig").c_abi_int_return_regs,
else => [_]Register{},
};