From 09992f8acc2432080409c3c3b32cab52bc8a3d91 Mon Sep 17 00:00:00 2001 From: Jacob G-W Date: Mon, 11 Oct 2021 18:10:12 -0400 Subject: [PATCH] add initial plan9 support to std --- lib/std/os.zig | 1 + lib/std/os/plan9.zig | 69 +++++++++++++++++++++++++++++++++++++ lib/std/os/plan9/x86_64.zig | 40 +++++++++++++++++++++ src/Sema.zig | 3 ++ src/arch/x86_64/CodeGen.zig | 26 ++++++-------- 5 files changed, 124 insertions(+), 15 deletions(-) create mode 100644 lib/std/os/plan9.zig create mode 100644 lib/std/os/plan9/x86_64.zig diff --git a/lib/std/os.zig b/lib/std/os.zig index f167e47e2a..9f2cf556de 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -33,6 +33,7 @@ pub const netbsd = std.c; pub const openbsd = std.c; pub const solaris = std.c; pub const linux = @import("os/linux.zig"); +pub const plan9 = @import("os/plan9.zig"); pub const uefi = @import("os/uefi.zig"); pub const wasi = @import("os/wasi.zig"); pub const windows = @import("os/windows.zig"); diff --git a/lib/std/os/plan9.zig b/lib/std/os/plan9.zig new file mode 100644 index 0000000000..7e047c728c --- /dev/null +++ b/lib/std/os/plan9.zig @@ -0,0 +1,69 @@ +const std = @import("../std.zig"); +const builtin = @import("builtin"); + +pub const syscall_bits = switch (builtin.stage2_arch) { + .x86_64 => @import("plan9/x86_64.zig"), + else => @compileError("more plan9 syscall implementations (needs more inline asm in stage2"), +}; +pub const SYS = enum(usize) { + SYSR1 = 0, + _ERRSTR = 1, + BIND = 2, + CHDIR = 3, + CLOSE = 4, + DUP = 5, + ALARM = 6, + EXEC = 7, + EXITS = 8, + _FSESSION = 9, + FAUTH = 10, + _FSTAT = 11, + SEGBRK = 12, + _MOUNT = 13, + OPEN = 14, + _READ = 15, + OSEEK = 16, + SLEEP = 17, + _STAT = 18, + RFORK = 19, + _WRITE = 20, + PIPE = 21, + CREATE = 22, + FD2PATH = 23, + BRK_ = 24, + REMOVE = 25, + _WSTAT = 26, + _FWSTAT = 27, + NOTIFY = 28, + NOTED = 29, + SEGATTACH = 30, + SEGDETACH = 31, + SEGFREE = 32, + SEGFLUSH = 33, + RENDEZVOUS = 34, + UNMOUNT = 35, + _WAIT = 36, + SEMACQUIRE = 37, + SEMRELEASE = 38, + SEEK = 39, + FVERSION = 40, + ERRSTR = 41, + STAT = 42, + FSTAT = 43, + WSTAT = 44, + FWSTAT = 45, + MOUNT = 46, + AWAIT = 47, + PREAD = 50, + PWRITE = 51, + TSEMACQUIRE = 52, + _NSEC = 53, +}; + +pub fn pwrite(fd: usize, buf: [*]const u8, count: usize, offset: usize) void { + syscall_bits.syscall4(.PWRITE, fd, @ptrToInt(buf), count, offset); +} + +pub fn exits(status: ?[*:0]const u8) void { + syscall_bits.syscall1(.EXITS, if (status) |s| @ptrToInt(s) else 0); +} diff --git a/lib/std/os/plan9/x86_64.zig b/lib/std/os/plan9/x86_64.zig new file mode 100644 index 0000000000..d24b29d0a8 --- /dev/null +++ b/lib/std/os/plan9/x86_64.zig @@ -0,0 +1,40 @@ +const plan9 = @import("../plan9.zig"); +// TODO get ret from inline asm +// TODO better inline asm + +pub fn syscall4(sys: plan9.SYS, arg0: usize, arg1: usize, arg2: usize, arg3: usize) void { + asm volatile ( + \\push %%r11 + \\push %%r10 + \\push %%r9 + \\push %%r8 + \\push $0 + \\syscall + \\pop %%r11 + \\pop %%r11 + \\pop %%r11 + \\pop %%r11 + \\pop %%r11 + : + : [arg0] "{r8}" (arg0), + [arg1] "{r9}" (arg1), + [arg2] "{r10}" (arg2), + [arg2] "{r11}" (arg3), + [syscall_number] "{rbp}" (@enumToInt(sys)), + : "rcx", "rbp", "r11", "memory" + ); +} +pub fn syscall1(sys: plan9.SYS, arg0: usize) void { + _ = sys; + asm volatile ( + \\push %%r8 + \\push $0 + \\syscall + \\pop %%r11 + \\pop %%r11 + : + : [syscall_number] "{rbp}" (@enumToInt(sys)), + [arg0] "{r8}" (arg0), + : "rcx", "rbp", "r11", "memory" + ); +} diff --git a/src/Sema.zig b/src/Sema.zig index 300d319167..0de048121a 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -8919,6 +8919,9 @@ fn zirIsNonNullPtr( const inst_data = sema.code.instructions.items(.data)[inst].un_node; const src = inst_data.src(); const ptr = sema.resolveInst(inst_data.operand); + if ((try sema.resolveMaybeUndefVal(block, src, ptr)) == null) { + return block.addUnOp(.is_non_null_ptr, ptr); + } const loaded = try sema.analyzeLoad(block, src, ptr, src); return sema.analyzeIsNull(block, src, loaded, true); } diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 4089a2edd8..54dfa2bcf8 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -1826,10 +1826,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void { try self.register_manager.getReg(reg, null); try self.genSetReg(arg_ty, reg, arg_mcv); }, - .stack_offset => { + .stack_offset => |off| { // Here we need to emit instructions like this: // mov qword ptr [rsp + stack_offset], x - return self.fail("TODO implement calling with parameters in memory", .{}); + try self.genSetStack(arg_ty, off, arg_mcv); }, .ptr_stack_offset => { return self.fail("TODO implement calling with MCValue.ptr_stack_offset arg", .{}); @@ -1987,9 +1987,10 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void { fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { const un_op = self.air.instructions.items(.data)[inst].un_op; const ptr = try self.resolveInst(un_op); - _ = ptr; - return self.fail("TODO implement airRetLoad for {}", .{self.target.cpu.arch}); - //return self.finishAir(inst, .dead, .{ un_op, .none, .none }); + // we can reuse self.ret_mcv because it just gets returned + try self.load(self.ret_mcv, ptr, self.air.typeOf(un_op)); + try self.ret(self.ret_mcv); + return self.finishAir(inst, .dead, .{ un_op, .none, .none }); } fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { @@ -2487,8 +2488,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { const clobbers_len = @truncate(u5, extended.small >> 10); _ = clobbers_len; // TODO honor these const is_volatile = @truncate(u1, extended.small >> 15) != 0; - const outputs = @bitCast([]const Air.Inst.Ref, self.air.extra[air_extra.end..][0..outputs_len]); - const args = @bitCast([]const Air.Inst.Ref, self.air.extra[air_extra.end + outputs.len ..][0..args_len]); + const args = @bitCast([]const Air.Inst.Ref, self.air.extra[air_extra.end..][0..args_len]); if (outputs_len > 1) { return self.fail("TODO implement codegen for asm with more than 1 output", .{}); @@ -2591,16 +2591,12 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { break :result MCValue{ .none = {} }; } }; - if (outputs.len + args.len <= Liveness.bpi - 1) { + if (args.len <= Liveness.bpi - 1) { var buf = [1]Air.Inst.Ref{.none} ** (Liveness.bpi - 1); - std.mem.copy(Air.Inst.Ref, &buf, outputs); - std.mem.copy(Air.Inst.Ref, buf[outputs.len..], args); + std.mem.copy(Air.Inst.Ref, &buf, args); return self.finishAir(inst, result, buf); } - var bt = try self.iterateBigTomb(inst, outputs.len + args.len); - for (outputs) |output| { - bt.feed(output); - } + var bt = try self.iterateBigTomb(inst, args.len); for (args) |arg| { bt.feed(arg); } @@ -3297,7 +3293,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { const param_size = @intCast(u32, ty.abiSize(self.target.*)); const pass_in_reg = switch (ty.zigTypeTag()) { .Bool => true, - .Int => param_size <= 8, + .Int, .Enum => param_size <= 8, .Pointer => ty.ptrSize() != .Slice, .Optional => ty.isPtrLikeOptional(), else => false,