From 968d1ecf17c0a0774d43965332d00d4ad39743b9 Mon Sep 17 00:00:00 2001 From: Jacob G-W Date: Sat, 10 Jul 2021 20:56:30 -0400 Subject: [PATCH] stage2 plan9: add aarch64 support --- lib/std/start.zig | 9 ++++++++ src/codegen.zig | 50 +++++++++++++++++++++++++++++++++++++++++++ src/link/Plan9.zig | 9 ++++++-- test/stage2/plan9.zig | 14 +++++++++--- 4 files changed, 77 insertions(+), 5 deletions(-) diff --git a/lib/std/start.zig b/lib/std/start.zig index dbbab433d0..1a290a90db 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -135,6 +135,15 @@ fn exit2(code: usize) noreturn { : "rcx", "r11", "memory" ); }, + // TODO once we get stack setting with assembly on + // arm, exit with 0 instead of stack garbage + .aarch64 => { + asm volatile ("svc #0" + : + : [exit] "{x0}" (0x08) + : "memory", "cc" + ); + }, else => @compileError("TODO"), }, else => @compileError("TODO"), diff --git a/src/codegen.zig b/src/codegen.zig index 96a24195ee..6050fe0ed8 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -2607,6 +2607,56 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { return self.fail(inst.base.src, "TODO implement calling runtime known function pointer", .{}); } }, + .aarch64 => { + for (info.args) |mc_arg, arg_i| { + const arg = inst.args[arg_i]; + const arg_mcv = try self.resolveInst(inst.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.src, arg.ty, reg, arg_mcv); + }, + .stack_offset => { + return self.fail(inst.base.src, "TODO implement calling with parameters in memory", .{}); + }, + .ptr_stack_offset => { + return self.fail(inst.base.src, "TODO implement calling with MCValue.ptr_stack_offset arg", .{}); + }, + .ptr_embedded_in_code => { + return self.fail(inst.base.src, "TODO implement calling with MCValue.ptr_embedded_in_code arg", .{}); + }, + } + } + if (inst.func.value()) |func_value| { + if (func_value.castTag(.function)) |func_payload| { + 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(inst.base.src, 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(inst.base.src, "TODO implement calling extern functions", .{}); + } else { + return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{}); + } + } else { + return self.fail(inst.base.src, "TODO implement calling runtime known function pointer", .{}); + } + }, else => return self.fail(inst.base.src, "TODO implement call on plan9 for {}", .{self.target.cpu.arch}), } } else unreachable; diff --git a/src/link/Plan9.zig b/src/link/Plan9.zig index f880b40d85..80a92f9cdb 100644 --- a/src/link/Plan9.zig +++ b/src/link/Plan9.zig @@ -78,15 +78,20 @@ pub const DeclBlock = struct { pub fn defaultBaseAddrs(arch: std.Target.Cpu.Arch) Bases { return switch (arch) { .x86_64 => .{ - // 0x28 => 40 == header size + // header size => 40 => 0x28 .text = 0x200028, .data = 0x400000, }, .i386 => .{ - // 0x20 => 32 == header size + // header size => 32 => 0x20 .text = 0x200020, .data = 0x400000, }, + .aarch64 => .{ + // header size => 40 => 0x28 + .text = 0x10028, + .data = 0x20000, + }, else => std.debug.panic("find default base address for {}", .{arch}), }; } diff --git a/test/stage2/plan9.zig b/test/stage2/plan9.zig index 22fa8253dc..09affac763 100644 --- a/test/stage2/plan9.zig +++ b/test/stage2/plan9.zig @@ -2,16 +2,24 @@ const std = @import("std"); const TestContext = @import("../../src/test.zig").TestContext; pub fn addCases(ctx: *TestContext) !void { - const target: std.zig.CrossTarget = .{ + const x64: std.zig.CrossTarget = .{ .cpu_arch = .x86_64, .os_tag = .plan9, }; + const aarch64: std.zig.CrossTarget = .{ + .cpu_arch = .aarch64, + .os_tag = .plan9, + }; { - var case = ctx.exe("plan9: exiting correctly", target); + var case = ctx.exe("plan9: exiting correctly x64", x64); case.addCompareOutput("pub fn main() void {}", ""); } { - var case = ctx.exe("plan9: hello world", target); + var case = ctx.exe("plan9: exiting correctly arm", aarch64); + case.addCompareOutput("pub fn main() void {}", ""); + } + { + var case = ctx.exe("plan9: hello world", x64); case.addCompareOutput( \\pub fn main() void { \\ const str = "Hello World!\n";