Commit ad214c7aa0

Andrew Kelley <andrew@ziglang.org>
2019-12-02 21:02:17
bring your own OS layer in the std lib
closes #3784
1 parent dcbd5ad
Changed files (7)
lib/std/event/loop.zig
@@ -61,7 +61,7 @@ pub const Loop = struct {
                 base: ResumeNode,
                 completion_key: usize,
             },
-            else => @compileError("unsupported OS"),
+            else => struct {},
         };
 
         const KEventFd = struct {
lib/std/os/bits.zig
@@ -1,7 +1,10 @@
-// Platform-dependent types and values that are used along with OS-specific APIs.
-// These are imported into `std.c`, `std.os`, and `std.os.linux`.
+//! Platform-dependent types and values that are used along with OS-specific APIs.
+//! These are imported into `std.c`, `std.os`, and `std.os.linux`.
+//! Root source files can define `os.bits` and these will additionally be added
+//! to the namespace.
 
 const builtin = @import("builtin");
+const root = @import("root");
 
 pub usingnamespace switch (builtin.os) {
     .macosx, .ios, .tvos, .watchos => @import("bits/darwin.zig"),
@@ -14,6 +17,8 @@ pub usingnamespace switch (builtin.os) {
     else => struct {},
 };
 
+pub usingnamespace if (@hasDecl(root, "os") and @hasDecl(root.os, "bits")) root.os.bits else struct {};
+
 pub const iovec = extern struct {
     iov_base: [*]u8,
     iov_len: usize,
lib/std/debug.zig
@@ -796,6 +796,9 @@ pub const OpenSelfDebugInfoError = error{
 pub fn openSelfDebugInfo(allocator: *mem.Allocator) !DebugInfo {
     if (builtin.strip_debug_info)
         return error.MissingDebugInfo;
+    if (@hasDecl(root, "os") and @hasDecl(root.os, "debug") and @hasDecl(root.os.debug, "openSelfDebugInfo")) {
+        return noasync root.os.debug.openSelfDebugInfo(allocator);
+    }
     if (builtin.os == .windows) {
         return noasync openSelfDebugInfoWindows(allocator);
     }
@@ -1722,8 +1725,7 @@ pub const DebugInfo = switch (builtin.os) {
         sect_contribs: []pdb.SectionContribEntry,
         modules: []Module,
     },
-    .linux, .freebsd, .netbsd, .dragonfly => DwarfInfo,
-    else => @compileError("Unsupported OS"),
+    else => DwarfInfo,
 };
 
 const PcRange = struct {
lib/std/heap.zig
@@ -1,4 +1,5 @@
 const std = @import("std.zig");
+const root = @import("root");
 const debug = std.debug;
 const assert = debug.assert;
 const testing = std.testing;
@@ -35,6 +36,8 @@ fn cShrink(self: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new
 /// Thread-safe and lock-free.
 pub const page_allocator = if (std.Target.current.isWasm())
     &wasm_page_allocator_state
+else if (std.Target.current.getOs() == .freestanding)
+    root.os.heap.page_allocator
 else
     &page_allocator_state;
 
lib/std/os.zig
@@ -14,6 +14,7 @@
 // Note: The Zig standard library does not support POSIX thread cancellation, and
 // in general EINTR is handled by trying again.
 
+const root = @import("root");
 const std = @import("std.zig");
 const builtin = @import("builtin");
 const assert = std.debug.assert;
@@ -48,8 +49,14 @@ test "" {
     _ = @import("os/test.zig");
 }
 
-/// When linking libc, this is the C API. Otherwise, it is the OS-specific system interface.
-pub const system = if (builtin.link_libc) std.c else switch (builtin.os) {
+/// Applications can override the `system` API layer in their root source file.
+/// Otherwise, when linking libc, this is the C API.
+/// When not linking libc, it is the OS-specific system interface.
+pub const system = if (@hasDecl(root, "os") and root.os != @This())
+    root.os.system
+else if (builtin.link_libc)
+    std.c
+else switch (builtin.os) {
     .macosx, .ios, .watchos, .tvos => darwin,
     .freebsd => freebsd,
     .linux => linux,
lib/std/thread.zig
@@ -19,7 +19,7 @@ pub const Thread = struct {
     else switch (builtin.os) {
         .linux => i32,
         .windows => windows.HANDLE,
-        else => @compileError("Unsupported OS"),
+        else => void,
     };
 
     /// Represents a unique ID per thread.
@@ -45,7 +45,7 @@ pub const Thread = struct {
             alloc_start: *c_void,
             heap_handle: windows.HANDLE,
         },
-        else => @compileError("Unsupported OS"),
+        else => struct {},
     };
 
     /// Returns the ID of the calling thread.
src/ir.cpp
@@ -9015,7 +9015,6 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *sc
         if (irb->exec->first_err_trace_msg == nullptr) {
             irb->exec->first_err_trace_msg = irb->codegen->trace_err;
         }
-        src_assert(irb->exec->first_err_trace_msg != nullptr, node);
     }
     return result;
 }
@@ -10709,10 +10708,12 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
                 if (type_is_global_error_set(err_set_type)) {
                     continue;
                 }
-                if (!resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->source_node)) {
+                bool allow_infer = cur_type->data.error_set.infer_fn != nullptr &&
+                        cur_type->data.error_set.infer_fn == ira->new_irb.exec->fn_entry;
+                if (!allow_infer && !resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->source_node)) {
                     return ira->codegen->builtin_types.entry_invalid;
                 }
-                if (type_is_global_error_set(cur_type)) {
+                if (!allow_infer && type_is_global_error_set(cur_type)) {
                     err_set_type = ira->codegen->builtin_types.entry_global_error_set;
                     prev_inst = cur_inst;
                     continue;
@@ -10830,10 +10831,12 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
         }
 
         if (cur_type->id == ZigTypeIdErrorSet) {
-            if (!resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->source_node)) {
+            bool allow_infer = cur_type->data.error_set.infer_fn != nullptr &&
+                    cur_type->data.error_set.infer_fn == ira->new_irb.exec->fn_entry;
+            if (!allow_infer && !resolve_inferred_error_set(ira->codegen, cur_type, cur_inst->source_node)) {
                 return ira->codegen->builtin_types.entry_invalid;
             }
-            if (type_is_global_error_set(cur_type)) {
+            if (!allow_infer && type_is_global_error_set(cur_type)) {
                 err_set_type = ira->codegen->builtin_types.entry_global_error_set;
                 continue;
             }
@@ -10844,17 +10847,20 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
             update_errors_helper(ira->codegen, &errors, &errors_count);
 
             if (err_set_type == nullptr) {
+                bool allow_infer = false;
                 if (prev_type->id == ZigTypeIdErrorUnion) {
                     err_set_type = prev_type->data.error_union.err_set_type;
+                    allow_infer = err_set_type->data.error_set.infer_fn != nullptr &&
+                        err_set_type->data.error_set.infer_fn == ira->new_irb.exec->fn_entry;
                 } else {
                     err_set_type = cur_type;
                 }
 
-                if (!resolve_inferred_error_set(ira->codegen, err_set_type, cur_inst->source_node)) {
+                if (!allow_infer && !resolve_inferred_error_set(ira->codegen, err_set_type, cur_inst->source_node)) {
                     return ira->codegen->builtin_types.entry_invalid;
                 }
 
-                if (type_is_global_error_set(err_set_type)) {
+                if (!allow_infer && type_is_global_error_set(err_set_type)) {
                     err_set_type = ira->codegen->builtin_types.entry_global_error_set;
                     continue;
                 }
@@ -10908,15 +10914,22 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
                 if (prev_err_set_type == cur_err_set_type)
                     continue;
 
-                if (!resolve_inferred_error_set(ira->codegen, prev_err_set_type, cur_inst->source_node)) {
+                bool allow_infer_prev = prev_err_set_type->data.error_set.infer_fn != nullptr &&
+                        prev_err_set_type->data.error_set.infer_fn == ira->new_irb.exec->fn_entry;
+                bool allow_infer_cur = cur_err_set_type->data.error_set.infer_fn != nullptr &&
+                        cur_err_set_type->data.error_set.infer_fn == ira->new_irb.exec->fn_entry;
+
+                if (!allow_infer_prev && !resolve_inferred_error_set(ira->codegen, prev_err_set_type, cur_inst->source_node)) {
                     return ira->codegen->builtin_types.entry_invalid;
                 }
 
-                if (!resolve_inferred_error_set(ira->codegen, cur_err_set_type, cur_inst->source_node)) {
+                if (!allow_infer_cur && !resolve_inferred_error_set(ira->codegen, cur_err_set_type, cur_inst->source_node)) {
                     return ira->codegen->builtin_types.entry_invalid;
                 }
 
-                if (type_is_global_error_set(prev_err_set_type) || type_is_global_error_set(cur_err_set_type)) {
+                if ((!allow_infer_prev && type_is_global_error_set(prev_err_set_type)) ||
+                    (!allow_infer_cur && type_is_global_error_set(cur_err_set_type)))
+                {
                     err_set_type = ira->codegen->builtin_types.entry_global_error_set;
                     continue;
                 }
@@ -11085,10 +11098,14 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
         {
             if (err_set_type != nullptr) {
                 ZigType *cur_err_set_type = cur_type->data.error_union.err_set_type;
-                if (!resolve_inferred_error_set(ira->codegen, cur_err_set_type, cur_inst->source_node)) {
+                bool allow_infer = cur_err_set_type->data.error_set.infer_fn != nullptr &&
+                    cur_err_set_type->data.error_set.infer_fn == ira->new_irb.exec->fn_entry;
+                if (!allow_infer && !resolve_inferred_error_set(ira->codegen, cur_err_set_type, cur_inst->source_node)) {
                     return ira->codegen->builtin_types.entry_invalid;
                 }
-                if (type_is_global_error_set(cur_err_set_type) || type_is_global_error_set(err_set_type)) {
+                if ((!allow_infer && type_is_global_error_set(cur_err_set_type)) ||
+                    type_is_global_error_set(err_set_type))
+                {
                     err_set_type = ira->codegen->builtin_types.entry_global_error_set;
                     prev_inst = cur_inst;
                     continue;