| 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 | 33 | pub const openbsd = std.c; |
| 34 | 34 | pub const solaris = std.c; |
| 35 | 35 | pub const linux = @import("os/linux.zig"); |
| 36 | pub const plan9 = @import("os/plan9.zig"); | |
| 36 | 37 | pub const uefi = @import("os/uefi.zig"); |
| 37 | 38 | pub const wasi = @import("os/wasi.zig"); |
| 38 | 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 | 9002 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 9003 | 9003 | const src = inst_data.src(); |
| 9004 | 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 | 9008 | const loaded = try sema.analyzeLoad(block, src, ptr, src); |
| 9006 | 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 | 1836 | try self.register_manager.getReg(reg, null); |
| 1837 | 1837 | try self.genSetReg(arg_ty, reg, arg_mcv); |
| 1838 | 1838 | }, |
| 1839 | .stack_offset => { | |
| 1839 | .stack_offset => |off| { | |
| 1840 | 1840 | // Here we need to emit instructions like this: |
| 1841 | 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 | 1844 | .ptr_stack_offset => { |
| 1845 | 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 | 1997 | fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 1998 | 1998 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 1999 | 1999 | const ptr = try self.resolveInst(un_op); |
| 2000 | _ = ptr; | |
| 2001 | return self.fail("TODO implement airRetLoad for {}", .{self.target.cpu.arch}); | |
| 2002 | //return self.finishAir(inst, .dead, .{ un_op, .none, .none }); | |
| 2000 | // we can reuse self.ret_mcv because it just gets returned | |
| 2001 | try self.load(self.ret_mcv, ptr, self.air.typeOf(un_op)); | |
| 2002 | try self.ret(self.ret_mcv); | |
| 2003 | return self.finishAir(inst, .dead, .{ un_op, .none, .none }); | |
| 2003 | 2004 | } |
| 2004 | 2005 | |
| 2005 | 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 | 2498 | const clobbers_len = @truncate(u5, extended.small >> 10); |
| 2498 | 2499 | _ = clobbers_len; // TODO honor these |
| 2499 | 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 + outputs.len ..][0..args_len]); | |
| 2501 | const args = @bitCast([]const Air.Inst.Ref, self.air.extra[air_extra.end..][0..args_len]); | |
| 2502 | 2502 | |
| 2503 | 2503 | if (outputs_len > 1) { |
| 2504 | 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 | 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 | 2605 | var buf = [1]Air.Inst.Ref{.none} ** (Liveness.bpi - 1); |
| 2606 | std.mem.copy(Air.Inst.Ref, &buf, outputs); | |
| 2607 | std.mem.copy(Air.Inst.Ref, buf[outputs.len..], args); | |
| 2606 | std.mem.copy(Air.Inst.Ref, &buf, args); | |
| 2608 | 2607 | return self.finishAir(inst, result, buf); |
| 2609 | 2608 | } |
| 2610 | var bt = try self.iterateBigTomb(inst, outputs.len + args.len); | |
| 2611 | for (outputs) |output| { | |
| 2612 | bt.feed(output); | |
| 2613 | } | |
| 2609 | var bt = try self.iterateBigTomb(inst, args.len); | |
| 2614 | 2610 | for (args) |arg| { |
| 2615 | 2611 | bt.feed(arg); |
| 2616 | 2612 | } |
| ... | ... | @@ -3310,7 +3306,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 3310 | 3306 | const param_size = @intCast(u32, ty.abiSize(self.target.*)); |
| 3311 | 3307 | const pass_in_reg = switch (ty.zigTypeTag()) { |
| 3312 | 3308 | .Bool => true, |
| 3313 | .Int => param_size <= 8, | |
| 3309 | .Int, .Enum => param_size <= 8, | |
| 3314 | 3310 | .Pointer => ty.ptrSize() != .Slice, |
| 3315 | 3311 | .Optional => ty.isPtrLikeOptional(), |
| 3316 | 3312 | else => false, |
test/stage2/plan9.zig+8-1| ... | ... | @@ -43,6 +43,13 @@ pub fn addCases(ctx: *TestContext) !void { |
| 43 | 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 | } |