| author | |
| committer | |
| log | 968d1ecf17c0a0774d43965332d00d4ad39743b9 |
| tree | b76eadf8b7d8c27fbff9ed1c48efdd218659854d |
| parent | 40764650afd47f2ca2d191ed4d910f680702e014 |
4 files changed, 77 insertions(+), 5 deletions(-)
lib/std/start.zig+9| ... | ... | @@ -135,6 +135,15 @@ fn exit2(code: usize) noreturn { |
| 135 | 135 | : "rcx", "r11", "memory" |
| 136 | 136 | ); |
| 137 | 137 | }, |
| 138 | // TODO once we get stack setting with assembly on | |
| 139 | // arm, exit with 0 instead of stack garbage | |
| 140 | .aarch64 => { | |
| 141 | asm volatile ("svc #0" | |
| 142 | : | |
| 143 | : [exit] "{x0}" (0x08) | |
| 144 | : "memory", "cc" | |
| 145 | ); | |
| 146 | }, | |
| 138 | 147 | else => @compileError("TODO"), |
| 139 | 148 | }, |
| 140 | 149 | else => @compileError("TODO"), |
src/codegen.zig+50| ... | ... | @@ -2607,6 +2607,56 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 2607 | 2607 | return self.fail(inst.base.src, "TODO implement calling runtime known function pointer", .{}); |
| 2608 | 2608 | } |
| 2609 | 2609 | }, |
| 2610 | .aarch64 => { | |
| 2611 | for (info.args) |mc_arg, arg_i| { | |
| 2612 | const arg = inst.args[arg_i]; | |
| 2613 | const arg_mcv = try self.resolveInst(inst.args[arg_i]); | |
| 2614 | ||
| 2615 | switch (mc_arg) { | |
| 2616 | .none => continue, | |
| 2617 | .undef => unreachable, | |
| 2618 | .immediate => unreachable, | |
| 2619 | .unreach => unreachable, | |
| 2620 | .dead => unreachable, | |
| 2621 | .embedded_in_code => unreachable, | |
| 2622 | .memory => unreachable, | |
| 2623 | .compare_flags_signed => unreachable, | |
| 2624 | .compare_flags_unsigned => unreachable, | |
| 2625 | .register => |reg| { | |
| 2626 | try self.register_manager.getReg(reg, null); | |
| 2627 | try self.genSetReg(arg.src, arg.ty, reg, arg_mcv); | |
| 2628 | }, | |
| 2629 | .stack_offset => { | |
| 2630 | return self.fail(inst.base.src, "TODO implement calling with parameters in memory", .{}); | |
| 2631 | }, | |
| 2632 | .ptr_stack_offset => { | |
| 2633 | return self.fail(inst.base.src, "TODO implement calling with MCValue.ptr_stack_offset arg", .{}); | |
| 2634 | }, | |
| 2635 | .ptr_embedded_in_code => { | |
| 2636 | return self.fail(inst.base.src, "TODO implement calling with MCValue.ptr_embedded_in_code arg", .{}); | |
| 2637 | }, | |
| 2638 | } | |
| 2639 | } | |
| 2640 | if (inst.func.value()) |func_value| { | |
| 2641 | if (func_value.castTag(.function)) |func_payload| { | |
| 2642 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); | |
| 2643 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); | |
| 2644 | const got_addr = p9.bases.data; | |
| 2645 | const got_index = func_payload.data.owner_decl.link.plan9.got_index.?; | |
| 2646 | const fn_got_addr = got_addr + got_index * ptr_bytes; | |
| 2647 | ||
| 2648 | try self.genSetReg(inst.base.src, Type.initTag(.usize), .x30, .{ .memory = fn_got_addr }); | |
| 2649 | ||
| 2650 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.blr(.x30).toU32()); | |
| 2651 | } else if (func_value.castTag(.extern_fn)) |_| { | |
| 2652 | return self.fail(inst.base.src, "TODO implement calling extern functions", .{}); | |
| 2653 | } else { | |
| 2654 | return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{}); | |
| 2655 | } | |
| 2656 | } else { | |
| 2657 | return self.fail(inst.base.src, "TODO implement calling runtime known function pointer", .{}); | |
| 2658 | } | |
| 2659 | }, | |
| 2610 | 2660 | else => return self.fail(inst.base.src, "TODO implement call on plan9 for {}", .{self.target.cpu.arch}), |
| 2611 | 2661 | } |
| 2612 | 2662 | } else unreachable; |
src/link/Plan9.zig+7-2| ... | ... | @@ -78,15 +78,20 @@ pub const DeclBlock = struct { |
| 78 | 78 | pub fn defaultBaseAddrs(arch: std.Target.Cpu.Arch) Bases { |
| 79 | 79 | return switch (arch) { |
| 80 | 80 | .x86_64 => .{ |
| 81 | // 0x28 => 40 == header size | |
| 81 | // header size => 40 => 0x28 | |
| 82 | 82 | .text = 0x200028, |
| 83 | 83 | .data = 0x400000, |
| 84 | 84 | }, |
| 85 | 85 | .i386 => .{ |
| 86 | // 0x20 => 32 == header size | |
| 86 | // header size => 32 => 0x20 | |
| 87 | 87 | .text = 0x200020, |
| 88 | 88 | .data = 0x400000, |
| 89 | 89 | }, |
| 90 | .aarch64 => .{ | |
| 91 | // header size => 40 => 0x28 | |
| 92 | .text = 0x10028, | |
| 93 | .data = 0x20000, | |
| 94 | }, | |
| 90 | 95 | else => std.debug.panic("find default base address for {}", .{arch}), |
| 91 | 96 | }; |
| 92 | 97 | } |
test/stage2/plan9.zig+11-3| ... | ... | @@ -2,16 +2,24 @@ const std = @import("std"); |
| 2 | 2 | const TestContext = @import("../../src/test.zig").TestContext; |
| 3 | 3 | |
| 4 | 4 | pub fn addCases(ctx: *TestContext) !void { |
| 5 | const target: std.zig.CrossTarget = .{ | |
| 5 | const x64: std.zig.CrossTarget = .{ | |
| 6 | 6 | .cpu_arch = .x86_64, |
| 7 | 7 | .os_tag = .plan9, |
| 8 | 8 | }; |
| 9 | const aarch64: std.zig.CrossTarget = .{ | |
| 10 | .cpu_arch = .aarch64, | |
| 11 | .os_tag = .plan9, | |
| 12 | }; | |
| 13 | { | |
| 14 | var case = ctx.exe("plan9: exiting correctly x64", x64); | |
| 15 | case.addCompareOutput("pub fn main() void {}", ""); | |
| 16 | } | |
| 9 | 17 | { |
| 10 | var case = ctx.exe("plan9: exiting correctly", target); | |
| 18 | var case = ctx.exe("plan9: exiting correctly arm", aarch64); | |
| 11 | 19 | case.addCompareOutput("pub fn main() void {}", ""); |
| 12 | 20 | } |
| 13 | 21 | { |
| 14 | var case = ctx.exe("plan9: hello world", target); | |
| 22 | var case = ctx.exe("plan9: hello world", x64); | |
| 15 | 23 | case.addCompareOutput( |
| 16 | 24 | \\pub fn main() void { |
| 17 | 25 | \\ const str = "Hello World!\n"; |