| author | |
| committer | |
| log | 19e56638694dddf1b9137a352abf31df7952c5eb |
| tree | a896c6c4a1f6090d3f02ca09a473b2cf12dee227 |
| parent | 53523ef5d0413459bd2eb9d84d2338f2bc49d417 |
| parent | bfb88b2d0dc9ca9663a2346d707ff4f0034739ba |
| signature |
add plan9 support to std6 files changed, 187 insertions(+), 16 deletions(-)
lib/std/os.zig+1| ... | @@ -33,6 +33,7 @@ pub const netbsd = std.c; | ... | @@ -33,6 +33,7 @@ pub const netbsd = std.c; |
| 33 | pub const openbsd = std.c; | 33 | pub const openbsd = std.c; |
| 34 | pub const solaris = std.c; | 34 | pub const solaris = std.c; |
| 35 | pub const linux = @import("os/linux.zig"); | 35 | pub const linux = @import("os/linux.zig"); |
| 36 | pub const plan9 = @import("os/plan9.zig"); | ||
| 36 | pub const uefi = @import("os/uefi.zig"); | 37 | pub const uefi = @import("os/uefi.zig"); |
| 37 | pub const wasi = @import("os/wasi.zig"); | 38 | pub const wasi = @import("os/wasi.zig"); |
| 38 | pub const windows = @import("os/windows.zig"); | 39 | pub const windows = @import("os/windows.zig"); |
lib/std/os/plan9.zig created+91| ... | @@ -0,0 +1,91 @@ | ||
| 1 | const std = @import("../std.zig"); | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | |||
| 4 | pub const syscall_bits = switch (builtin.stage2_arch) { | ||
| 5 | .x86_64 => @import("plan9/x86_64.zig"), | ||
| 6 | else => @compileError("more plan9 syscall implementations (needs more inline asm in stage2"), | ||
| 7 | }; | ||
| 8 | pub const SYS = enum(usize) { | ||
| 9 | SYSR1 = 0, | ||
| 10 | _ERRSTR = 1, | ||
| 11 | BIND = 2, | ||
| 12 | CHDIR = 3, | ||
| 13 | CLOSE = 4, | ||
| 14 | DUP = 5, | ||
| 15 | ALARM = 6, | ||
| 16 | EXEC = 7, | ||
| 17 | EXITS = 8, | ||
| 18 | _FSESSION = 9, | ||
| 19 | FAUTH = 10, | ||
| 20 | _FSTAT = 11, | ||
| 21 | SEGBRK = 12, | ||
| 22 | _MOUNT = 13, | ||
| 23 | OPEN = 14, | ||
| 24 | _READ = 15, | ||
| 25 | OSEEK = 16, | ||
| 26 | SLEEP = 17, | ||
| 27 | _STAT = 18, | ||
| 28 | RFORK = 19, | ||
| 29 | _WRITE = 20, | ||
| 30 | PIPE = 21, | ||
| 31 | CREATE = 22, | ||
| 32 | FD2PATH = 23, | ||
| 33 | BRK_ = 24, | ||
| 34 | REMOVE = 25, | ||
| 35 | _WSTAT = 26, | ||
| 36 | _FWSTAT = 27, | ||
| 37 | NOTIFY = 28, | ||
| 38 | NOTED = 29, | ||
| 39 | SEGATTACH = 30, | ||
| 40 | SEGDETACH = 31, | ||
| 41 | SEGFREE = 32, | ||
| 42 | SEGFLUSH = 33, | ||
| 43 | RENDEZVOUS = 34, | ||
| 44 | UNMOUNT = 35, | ||
| 45 | _WAIT = 36, | ||
| 46 | SEMACQUIRE = 37, | ||
| 47 | SEMRELEASE = 38, | ||
| 48 | SEEK = 39, | ||
| 49 | FVERSION = 40, | ||
| 50 | ERRSTR = 41, | ||
| 51 | STAT = 42, | ||
| 52 | FSTAT = 43, | ||
| 53 | WSTAT = 44, | ||
| 54 | FWSTAT = 45, | ||
| 55 | MOUNT = 46, | ||
| 56 | AWAIT = 47, | ||
| 57 | PREAD = 50, | ||
| 58 | PWRITE = 51, | ||
| 59 | TSEMACQUIRE = 52, | ||
| 60 | _NSEC = 53, | ||
| 61 | }; | ||
| 62 | |||
| 63 | pub fn pwrite(fd: usize, buf: [*]const u8, count: usize, offset: usize) usize { | ||
| 64 | return syscall_bits.syscall4(.PWRITE, fd, @ptrToInt(buf), count, offset); | ||
| 65 | } | ||
| 66 | |||
| 67 | pub fn open(path: [*:0]const u8, omode: OpenMode) usize { | ||
| 68 | return syscall_bits.syscall2(.OPEN, @ptrToInt(path), @enumToInt(omode)); | ||
| 69 | } | ||
| 70 | |||
| 71 | pub fn create(path: [*:0]const u8, omode: OpenMode, perms: usize) usize { | ||
| 72 | return syscall_bits.syscall3(.CREATE, @ptrToInt(path), @enumToInt(omode), perms); | ||
| 73 | } | ||
| 74 | |||
| 75 | pub fn exits(status: ?[*:0]const u8) void { | ||
| 76 | _ = syscall_bits.syscall1(.EXITS, if (status) |s| @ptrToInt(s) else 0); | ||
| 77 | } | ||
| 78 | |||
| 79 | pub fn close(fd: usize) usize { | ||
| 80 | return syscall_bits.syscall1(.CLOSE, fd); | ||
| 81 | } | ||
| 82 | pub const OpenMode = enum(usize) { | ||
| 83 | OREAD = 0, //* open for read | ||
| 84 | OWRITE = 1, //* write | ||
| 85 | ORDWR = 2, //* read and write | ||
| 86 | OEXEC = 3, //* execute, == read but check execute permission | ||
| 87 | OTRUNC = 16, //* or'ed in (except for exec), truncate file first | ||
| 88 | OCEXEC = 32, //* or'ed in (per file descriptor), close on exec | ||
| 89 | ORCLOSE = 64, //* or'ed in, remove on close | ||
| 90 | OEXCL = 0x1000, //* or'ed in, exclusive create | ||
| 91 | }; | ||
lib/std/os/plan9/x86_64.zig created+73| ... | @@ -0,0 +1,73 @@ | ||
| 1 | const plan9 = @import("../plan9.zig"); | ||
| 2 | // TODO better inline asm | ||
| 3 | |||
| 4 | pub fn syscall1(sys: plan9.SYS, arg0: usize) usize { | ||
| 5 | return asm volatile ( | ||
| 6 | \\push %%r8 | ||
| 7 | \\push $0 | ||
| 8 | \\syscall | ||
| 9 | \\pop %%r11 | ||
| 10 | \\pop %%r11 | ||
| 11 | : [ret] "={rax}" (-> usize), | ||
| 12 | : [syscall_number] "{rbp}" (@enumToInt(sys)), | ||
| 13 | [arg0] "{r8}" (arg0), | ||
| 14 | : "rcx", "rax", "rbp", "r11", "memory" | ||
| 15 | ); | ||
| 16 | } | ||
| 17 | pub fn syscall2(sys: plan9.SYS, arg0: usize, arg1: usize) usize { | ||
| 18 | return asm volatile ( | ||
| 19 | \\push %%r9 | ||
| 20 | \\push %%r8 | ||
| 21 | \\push $0 | ||
| 22 | \\syscall | ||
| 23 | \\pop %%r11 | ||
| 24 | \\pop %%r11 | ||
| 25 | \\pop %%r11 | ||
| 26 | : [ret] "={rax}" (-> usize), | ||
| 27 | : [arg0] "{r8}" (arg0), | ||
| 28 | [arg1] "{r9}" (arg1), | ||
| 29 | [syscall_number] "{rbp}" (@enumToInt(sys)), | ||
| 30 | : "rcx", "rax", "rbp", "r11", "memory" | ||
| 31 | ); | ||
| 32 | } | ||
| 33 | pub fn syscall3(sys: plan9.SYS, arg0: usize, arg1: usize, arg2: usize) usize { | ||
| 34 | return asm volatile ( | ||
| 35 | \\push %%r10 | ||
| 36 | \\push %%r9 | ||
| 37 | \\push %%r8 | ||
| 38 | \\push $0 | ||
| 39 | \\syscall | ||
| 40 | \\pop %%r11 | ||
| 41 | \\pop %%r11 | ||
| 42 | \\pop %%r11 | ||
| 43 | \\pop %%r11 | ||
| 44 | : [ret] "={rax}" (-> usize), | ||
| 45 | : [arg0] "{r8}" (arg0), | ||
| 46 | [arg1] "{r9}" (arg1), | ||
| 47 | [arg2] "{r10}" (arg2), | ||
| 48 | [syscall_number] "{rbp}" (@enumToInt(sys)), | ||
| 49 | : "rcx", "rax", "rbp", "r11", "memory" | ||
| 50 | ); | ||
| 51 | } | ||
| 52 | pub fn syscall4(sys: plan9.SYS, arg0: usize, arg1: usize, arg2: usize, arg3: usize) usize { | ||
| 53 | return asm volatile ( | ||
| 54 | \\push %%r11 | ||
| 55 | \\push %%r10 | ||
| 56 | \\push %%r9 | ||
| 57 | \\push %%r8 | ||
| 58 | \\push $0 | ||
| 59 | \\syscall | ||
| 60 | \\pop %%r11 | ||
| 61 | \\pop %%r11 | ||
| 62 | \\pop %%r11 | ||
| 63 | \\pop %%r11 | ||
| 64 | \\pop %%r11 | ||
| 65 | : [ret] "={rax}" (-> usize), | ||
| 66 | : [arg0] "{r8}" (arg0), | ||
| 67 | [arg1] "{r9}" (arg1), | ||
| 68 | [arg2] "{r10}" (arg2), | ||
| 69 | [arg2] "{r11}" (arg3), | ||
| 70 | [syscall_number] "{rbp}" (@enumToInt(sys)), | ||
| 71 | : "rcx", "rax", "rbp", "r11", "memory" | ||
| 72 | ); | ||
| 73 | } | ||
src/Sema.zig+3| ... | @@ -9002,6 +9002,9 @@ fn zirIsNonNullPtr( | ... | @@ -9002,6 +9002,9 @@ fn zirIsNonNullPtr( |
| 9002 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 9002 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 9003 | const src = inst_data.src(); | 9003 | const src = inst_data.src(); |
| 9004 | const ptr = sema.resolveInst(inst_data.operand); | 9004 | const ptr = sema.resolveInst(inst_data.operand); |
| 9005 | if ((try sema.resolveMaybeUndefVal(block, src, ptr)) == null) { | ||
| 9006 | return block.addUnOp(.is_non_null_ptr, ptr); | ||
| 9007 | } | ||
| 9005 | const loaded = try sema.analyzeLoad(block, src, ptr, src); | 9008 | const loaded = try sema.analyzeLoad(block, src, ptr, src); |
| 9006 | return sema.analyzeIsNull(block, src, loaded, true); | 9009 | return sema.analyzeIsNull(block, src, loaded, true); |
| 9007 | } | 9010 | } |
src/arch/x86_64/CodeGen.zig+11-15| ... | @@ -1836,10 +1836,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1836,10 +1836,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void { |
| 1836 | try self.register_manager.getReg(reg, null); | 1836 | try self.register_manager.getReg(reg, null); |
| 1837 | try self.genSetReg(arg_ty, reg, arg_mcv); | 1837 | try self.genSetReg(arg_ty, reg, arg_mcv); |
| 1838 | }, | 1838 | }, |
| 1839 | .stack_offset => { | 1839 | .stack_offset => |off| { |
| 1840 | // Here we need to emit instructions like this: | 1840 | // Here we need to emit instructions like this: |
| 1841 | // mov qword ptr [rsp + stack_offset], x | 1841 | // mov qword ptr [rsp + stack_offset], x |
| 1842 | return self.fail("TODO implement calling with parameters in memory", .{}); | 1842 | try self.genSetStack(arg_ty, off, arg_mcv); |
| 1843 | }, | 1843 | }, |
| 1844 | .ptr_stack_offset => { | 1844 | .ptr_stack_offset => { |
| 1845 | return self.fail("TODO implement calling with MCValue.ptr_stack_offset arg", .{}); | 1845 | return self.fail("TODO implement calling with MCValue.ptr_stack_offset arg", .{}); |
| ... | @@ -1997,9 +1997,10 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1997,9 +1997,10 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void { |
| 1997 | fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { | 1997 | fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 1998 | const un_op = self.air.instructions.items(.data)[inst].un_op; | 1998 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 1999 | const ptr = try self.resolveInst(un_op); | 1999 | const ptr = try self.resolveInst(un_op); |
| 2000 | _ = ptr; | 2000 | // we can reuse self.ret_mcv because it just gets returned |
| 2001 | return self.fail("TODO implement airRetLoad for {}", .{self.target.cpu.arch}); | 2001 | try self.load(self.ret_mcv, ptr, self.air.typeOf(un_op)); |
| 2002 | //return self.finishAir(inst, .dead, .{ un_op, .none, .none }); | 2002 | try self.ret(self.ret_mcv); |
| 2003 | return self.finishAir(inst, .dead, .{ un_op, .none, .none }); | ||
| 2003 | } | 2004 | } |
| 2004 | 2005 | ||
| 2005 | fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { | 2006 | fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| ... | @@ -2497,8 +2498,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2497,8 +2498,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 2497 | const clobbers_len = @truncate(u5, extended.small >> 10); | 2498 | const clobbers_len = @truncate(u5, extended.small >> 10); |
| 2498 | _ = clobbers_len; // TODO honor these | 2499 | _ = clobbers_len; // TODO honor these |
| 2499 | const is_volatile = @truncate(u1, extended.small >> 15) != 0; | 2500 | const is_volatile = @truncate(u1, extended.small >> 15) != 0; |
| 2500 | const outputs = @bitCast([]const Air.Inst.Ref, self.air.extra[air_extra.end..][0..outputs_len]); | 2501 | const args = @bitCast([]const Air.Inst.Ref, self.air.extra[air_extra.end..][0..args_len]); |
| 2501 | const args = @bitCast([]const Air.Inst.Ref, self.air.extra[air_extra.end + outputs.len ..][0..args_len]); | ||
| 2502 | 2502 | ||
| 2503 | if (outputs_len > 1) { | 2503 | if (outputs_len > 1) { |
| 2504 | return self.fail("TODO implement codegen for asm with more than 1 output", .{}); | 2504 | return self.fail("TODO implement codegen for asm with more than 1 output", .{}); |
| ... | @@ -2601,16 +2601,12 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2601,16 +2601,12 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 2601 | break :result MCValue{ .none = {} }; | 2601 | break :result MCValue{ .none = {} }; |
| 2602 | } | 2602 | } |
| 2603 | }; | 2603 | }; |
| 2604 | if (outputs.len + args.len <= Liveness.bpi - 1) { | 2604 | if (args.len <= Liveness.bpi - 1) { |
| 2605 | var buf = [1]Air.Inst.Ref{.none} ** (Liveness.bpi - 1); | 2605 | var buf = [1]Air.Inst.Ref{.none} ** (Liveness.bpi - 1); |
| 2606 | std.mem.copy(Air.Inst.Ref, &buf, outputs); | 2606 | std.mem.copy(Air.Inst.Ref, &buf, args); |
| 2607 | std.mem.copy(Air.Inst.Ref, buf[outputs.len..], args); | ||
| 2608 | return self.finishAir(inst, result, buf); | 2607 | return self.finishAir(inst, result, buf); |
| 2609 | } | 2608 | } |
| 2610 | var bt = try self.iterateBigTomb(inst, outputs.len + args.len); | 2609 | var bt = try self.iterateBigTomb(inst, args.len); |
| 2611 | for (outputs) |output| { | ||
| 2612 | bt.feed(output); | ||
| 2613 | } | ||
| 2614 | for (args) |arg| { | 2610 | for (args) |arg| { |
| 2615 | bt.feed(arg); | 2611 | bt.feed(arg); |
| 2616 | } | 2612 | } |
| ... | @@ -3310,7 +3306,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -3310,7 +3306,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 3310 | const param_size = @intCast(u32, ty.abiSize(self.target.*)); | 3306 | const param_size = @intCast(u32, ty.abiSize(self.target.*)); |
| 3311 | const pass_in_reg = switch (ty.zigTypeTag()) { | 3307 | const pass_in_reg = switch (ty.zigTypeTag()) { |
| 3312 | .Bool => true, | 3308 | .Bool => true, |
| 3313 | .Int => param_size <= 8, | 3309 | .Int, .Enum => param_size <= 8, |
| 3314 | .Pointer => ty.ptrSize() != .Slice, | 3310 | .Pointer => ty.ptrSize() != .Slice, |
| 3315 | .Optional => ty.isPtrLikeOptional(), | 3311 | .Optional => ty.isPtrLikeOptional(), |
| 3316 | else => false, | 3312 | else => false, |
test/stage2/plan9.zig+8-1| ... | @@ -43,6 +43,13 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -43,6 +43,13 @@ pub fn addCases(ctx: *TestContext) !void { |
| 43 | \\ : "rcx", "rbp", "r11", "memory" | 43 | \\ : "rcx", "rbp", "r11", "memory" |
| 44 | \\ ); | 44 | \\ ); |
| 45 | \\} | 45 | \\} |
| 46 | , ""); | 46 | , "Hello World\n"); |
| 47 | case.addCompareOutput( | ||
| 48 | \\const std = @import("std"); | ||
| 49 | \\pub fn main() void { | ||
| 50 | \\ const str = "Hello World!\n"; | ||
| 51 | \\ _ = std.os.plan9.pwrite(1, str, str.len, 0); | ||
| 52 | \\} | ||
| 53 | , "Hello World\n"); | ||
| 47 | } | 54 | } |
| 48 | } | 55 | } |