From ad214c7aa00fc82b243eb38061f41588a0c58867 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 2 Dec 2019 15:02:17 -0500 Subject: [PATCH] bring your own OS layer in the std lib closes #3784 --- lib/std/debug.zig | 6 ++++-- lib/std/event/loop.zig | 2 +- lib/std/heap.zig | 3 +++ lib/std/os.zig | 11 +++++++++-- lib/std/os/bits.zig | 9 +++++++-- lib/std/thread.zig | 4 ++-- src/ir.cpp | 41 +++++++++++++++++++++++++++++------------ 7 files changed, 55 insertions(+), 21 deletions(-) diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 711f728fa..e31f847d7 100644 --- a/lib/std/debug.zig +++ b/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 { diff --git a/lib/std/event/loop.zig b/lib/std/event/loop.zig index 03478f65d..3a6cced79 100644 --- a/lib/std/event/loop.zig +++ b/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 { diff --git a/lib/std/heap.zig b/lib/std/heap.zig index 997f1fa06..c421909a2 100644 --- a/lib/std/heap.zig +++ b/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; diff --git a/lib/std/os.zig b/lib/std/os.zig index 66a5522ac..5d3bb705a 100644 --- a/lib/std/os.zig +++ b/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, diff --git a/lib/std/os/bits.zig b/lib/std/os/bits.zig index 7dd968e47..bab9ad0ae 100644 --- a/lib/std/os/bits.zig +++ b/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, diff --git a/lib/std/thread.zig b/lib/std/thread.zig index 571773dca..e24104e1b 100644 --- a/lib/std/thread.zig +++ b/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. diff --git a/src/ir.cpp b/src/ir.cpp index d9fccb21e..a40836c9e 100644 --- a/src/ir.cpp +++ b/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;