Commit 09992f8acc

Jacob G-W <jacoblevgw@gmail.com>
2021-10-12 00:10:12
add initial plan9 support to std
1 parent 4d75382
Changed files (5)
lib
src
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"
+    );
+}
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);
+}
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");
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,
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);
 }