Commit 968d1ecf17

Jacob G-W <jacoblevgw@gmail.com>
2021-07-11 02:56:30
stage2 plan9: add aarch64 support
1 parent 4076465
Changed files (4)
lib
src
test
stage2
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"),
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}),
     };
 }
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;
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 x64", x64);
+        case.addCompareOutput("pub fn main() void {}", "");
+    }
     {
-        var case = ctx.exe("plan9: exiting correctly", target);
+        var case = ctx.exe("plan9: exiting correctly arm", aarch64);
         case.addCompareOutput("pub fn main() void {}", "");
     }
     {
-        var case = ctx.exe("plan9: hello world", target);
+        var case = ctx.exe("plan9: hello world", x64);
         case.addCompareOutput(
             \\pub fn main() void {
             \\    const str = "Hello World!\n";