diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index 36fa46e953..687e169bbe 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -412,6 +412,13 @@ pub const CallOptions = struct { }; }; +/// This function type is used by the Zig language code generation and +/// therefore must be kept in sync with the compiler implementation. +pub const TestFn = struct { + name: []const u8, + func: fn()anyerror!void, +}; + /// This function type is used by the Zig language code generation and /// therefore must be kept in sync with the compiler implementation. pub const PanicFn = fn ([]const u8, ?*StackTrace) noreturn; @@ -424,6 +431,10 @@ pub const panic: PanicFn = if (@hasDecl(root, "panic")) root.panic else default_ /// therefore must be kept in sync with the compiler implementation. pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace) noreturn { @setCold(true); + if (@hasDecl(root, "os") and @hasDecl(root.os, "panic")) { + root.os.panic(msg, error_return_trace); + unreachable; + } switch (os) { .freestanding => { while (true) { diff --git a/lib/std/os.zig b/lib/std/os.zig index 04de59d6e1..6d49bcd38e 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -187,19 +187,23 @@ pub fn abort() noreturn { } windows.kernel32.ExitProcess(3); } - if (builtin.link_libc) { - system.abort(); + if (!builtin.link_libc and builtin.os == .linux) { + raise(SIGABRT) catch {}; + + // TODO the rest of the implementation of abort() from musl libc here + + raise(SIGKILL) catch {}; + exit(127); } if (builtin.os == .uefi) { exit(0); // TODO choose appropriate exit code } + if (builtin.os == .wasi) { + @breakpoint(); + exit(1); + } - raise(SIGABRT) catch {}; - - // TODO the rest of the implementation of abort() from musl libc here - - raise(SIGKILL) catch {}; - exit(127); + system.abort(); } pub const RaiseError = UnexpectedError; diff --git a/lib/std/special/c.zig b/lib/std/special/c.zig index 4c2eb2a958..0895b1e6f9 100644 --- a/lib/std/special/c.zig +++ b/lib/std/special/c.zig @@ -83,7 +83,7 @@ pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn @setCold(true); std.debug.panic("{}", msg); } - if (builtin.os != .freestanding) { + if (builtin.os != .freestanding and builtin.os != .other) { std.os.abort(); } while (true) {} diff --git a/lib/std/special/test_runner.zig b/lib/std/special/test_runner.zig index 7bb53774d3..0335c8562d 100644 --- a/lib/std/special/test_runner.zig +++ b/lib/std/special/test_runner.zig @@ -1,9 +1,9 @@ const std = @import("std"); const io = std.io; const builtin = @import("builtin"); -const test_fn_list = builtin.test_functions; pub fn main() anyerror!void { + const test_fn_list = builtin.test_functions; var ok_count: usize = 0; var skip_count: usize = 0; var progress = std.Progress{}; @@ -16,7 +16,9 @@ pub fn main() anyerror!void { var test_node = root_node.start(test_fn.name, null); test_node.activate(); progress.refresh(); - if (progress.terminal == null) std.debug.warn("{}/{} {}...", .{ i + 1, test_fn_list.len, test_fn.name }); + if (progress.terminal == null) { + std.debug.warn("{}/{} {}...", .{ i + 1, test_fn_list.len, test_fn.name }); + } if (test_fn.func()) |_| { ok_count += 1; test_node.end(); diff --git a/lib/std/special/start.zig b/lib/std/start.zig similarity index 95% rename from lib/std/special/start.zig rename to lib/std/start.zig index 60745dab7f..3c46449949 100644 --- a/lib/std/special/start.zig +++ b/lib/std/start.zig @@ -1,8 +1,8 @@ // This file is included in the compilation unit when exporting an executable. const root = @import("root"); -const std = @import("std"); -const builtin = @import("builtin"); +const std = @import("std.zig"); +const builtin = std.builtin; const assert = std.debug.assert; const uefi = std.os.uefi; @@ -17,6 +17,7 @@ const is_mips = switch (builtin.arch) { .mips, .mipsel, .mips64, .mips64el => true, else => false, }; +const start_sym_name = if (is_mips) "__start" else "_start"; comptime { if (builtin.output_mode == .Lib and builtin.link_mode == .Dynamic) { @@ -34,14 +35,10 @@ comptime { } } else if (builtin.os == .uefi) { if (!@hasDecl(root, "EfiMain")) @export("EfiMain", EfiMain, .Strong); - } else if (builtin.os != .freestanding) { - if (is_mips) { - if (!@hasDecl(root, "__start")) @export("__start", _start, .Strong); - } else { - if (!@hasDecl(root, "_start")) @export("_start", _start, .Strong); - } - } else if (is_wasm) { - if (!@hasDecl(root, "_start")) @export("_start", wasm_freestanding_start, .Strong); + } else if (is_wasm and builtin.os == .freestanding) { + if (!@hasDecl(root, start_sym_name)) @export(start_sym_name, wasm_freestanding_start, .Strong); + } else if (builtin.os != .other and builtin.os != .freestanding) { + if (!@hasDecl(root, start_sym_name)) @export(start_sym_name, _start, .Strong); } } } @@ -247,7 +244,7 @@ async fn callMainAsync(loop: *std.event.Loop) u8 { // This is not marked inline because it is called with @asyncCall when // there is an event loop. -fn callMain() u8 { +pub fn callMain() u8 { switch (@typeInfo(@TypeOf(root.main).ReturnType)) { .NoReturn => { root.main(); diff --git a/lib/std/special/start_windows_tls.zig b/lib/std/start_windows_tls.zig similarity index 98% rename from lib/std/special/start_windows_tls.zig rename to lib/std/start_windows_tls.zig index bfd0e44122..f6dd2bc132 100644 --- a/lib/std/special/start_windows_tls.zig +++ b/lib/std/start_windows_tls.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const builtin = @import("builtin"); +const builtin = std.builtin; export var _tls_index: u32 = std.os.windows.TLS_OUT_OF_INDEXES; export var _tls_start: u8 linksection(".tls") = 0; diff --git a/lib/std/std.zig b/lib/std/std.zig index 09db489604..dd4d968efb 100644 --- a/lib/std/std.zig +++ b/lib/std/std.zig @@ -65,6 +65,13 @@ pub const time = @import("time.zig"); pub const unicode = @import("unicode.zig"); pub const valgrind = @import("valgrind.zig"); pub const zig = @import("zig.zig"); +pub const start = @import("start.zig"); + +// This forces the start.zig file to be imported, and the comptime logic inside that +// file decides whether to export any appropriate start symbols. +comptime { + _ = start; +} test "" { meta.refAllDecls(@This()); diff --git a/src/all_types.hpp b/src/all_types.hpp index 747655987c..5f0211df74 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -2003,10 +2003,11 @@ struct CodeGen { ZigPackage *std_package; ZigPackage *test_runner_package; ZigPackage *compile_var_package; + ZigPackage *root_pkg; // @import("root") + ZigPackage *main_pkg; // usually same as root_pkg, except for `zig test` ZigType *compile_var_import; ZigType *root_import; ZigType *start_import; - ZigType *test_runner_import; struct { ZigType *entry_bool; @@ -2179,7 +2180,6 @@ struct CodeGen { Buf *root_out_name; Buf *test_filter; Buf *test_name_prefix; - ZigPackage *root_package; Buf *zig_lib_dir; Buf *zig_std_dir; Buf *dynamic_linker_path; diff --git a/src/analyze.cpp b/src/analyze.cpp index f46c4fc07c..35a4bd7d4a 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -3536,7 +3536,7 @@ static void preview_test_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_scope return; ZigType *import = get_scope_import(&decls_scope->base); - if (import->data.structure.root_struct->package != g->root_package) + if (import->data.structure.root_struct->package != g->main_pkg) return; Buf *decl_name_buf = node->data.test_decl.name; @@ -3577,7 +3577,7 @@ void update_compile_var(CodeGen *g, Buf *name, ZigValue *value) { resolve_top_level_decl(g, tld, tld->source_node, false); assert(tld->id == TldIdVar); TldVar *tld_var = (TldVar *)tld; - tld_var->var->const_value = value; + copy_const_val(tld_var->var->const_value, value); tld_var->var->var_type = value->type; tld_var->var->align_bytes = get_abi_alignment(g, value->type); } @@ -9178,3 +9178,42 @@ bool is_anon_container(ZigType *ty) { ty->data.structure.special == StructSpecialInferredTuple || ty->data.structure.special == StructSpecialInferredStruct); } + +bool is_opt_err_set(ZigType *ty) { + return ty->id == ZigTypeIdErrorSet || + (ty->id == ZigTypeIdOptional && ty->data.maybe.child_type->id == ZigTypeIdErrorSet); +} + +// Returns whether the x_optional field of ZigValue is active. +bool type_has_optional_repr(ZigType *ty) { + if (ty->id != ZigTypeIdOptional) { + return false; + } else if (get_codegen_ptr_type(ty) != nullptr) { + return false; + } else if (is_opt_err_set(ty)) { + return false; + } else { + return true; + } +} + +void copy_const_val(ZigValue *dest, ZigValue *src) { + memcpy(dest, src, sizeof(ZigValue)); + if (src->special != ConstValSpecialStatic) + return; + dest->parent.id = ConstParentIdNone; + if (dest->type->id == ZigTypeIdStruct) { + dest->data.x_struct.fields = alloc_const_vals_ptrs(dest->type->data.structure.src_field_count); + for (size_t i = 0; i < dest->type->data.structure.src_field_count; i += 1) { + copy_const_val(dest->data.x_struct.fields[i], src->data.x_struct.fields[i]); + dest->data.x_struct.fields[i]->parent.id = ConstParentIdStruct; + dest->data.x_struct.fields[i]->parent.data.p_struct.struct_val = dest; + dest->data.x_struct.fields[i]->parent.data.p_struct.field_index = i; + } + } else if (type_has_optional_repr(dest->type) && dest->data.x_optional != nullptr) { + dest->data.x_optional = create_const_vals(1); + copy_const_val(dest->data.x_optional, src->data.x_optional); + dest->data.x_optional->parent.id = ConstParentIdOptionalPayload; + dest->data.x_optional->parent.data.p_optional_payload.optional_val = dest; + } +} diff --git a/src/analyze.hpp b/src/analyze.hpp index 8f07434203..0accff8e5b 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -276,4 +276,7 @@ Error analyze_import(CodeGen *codegen, ZigType *source_import, Buf *import_targe ZigType **out_import, Buf **out_import_target_path, Buf *out_full_path); ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry); bool is_anon_container(ZigType *ty); +void copy_const_val(ZigValue *dest, ZigValue *src); +bool type_has_optional_repr(ZigType *ty); +bool is_opt_err_set(ZigType *ty); #endif diff --git a/src/codegen.cpp b/src/codegen.cpp index 5b0899544d..a3f3eb622f 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8440,11 +8440,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { if (g->is_test_build) { buf_appendf(contents, - "const TestFn = struct {\n" - "name: []const u8,\n" - "func: fn()anyerror!void,\n" - "};\n" - "pub const test_functions = {}; // overwritten later\n" + "pub var test_functions: []TestFn = undefined; // overwritten later\n" ); } @@ -8535,23 +8531,23 @@ static Error define_builtin_compile_vars(CodeGen *g) { } } - assert(g->root_package); + assert(g->main_pkg); assert(g->std_package); g->compile_var_package = new_package(buf_ptr(this_dir), builtin_zig_basename, "builtin"); - g->compile_var_package->package_table.put(buf_create_from_str("std"), g->std_package); - g->root_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package); - g->std_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package); - g->std_package->package_table.put(buf_create_from_str("std"), g->std_package); - ZigPackage *root_pkg; if (g->is_test_build) { if (g->test_runner_package == nullptr) { g->test_runner_package = create_test_runner_pkg(g); } - root_pkg = g->test_runner_package; + g->root_pkg = g->test_runner_package; } else { - root_pkg = g->root_package; + g->root_pkg = g->main_pkg; } - g->std_package->package_table.put(buf_create_from_str("root"), root_pkg); + g->compile_var_package->package_table.put(buf_create_from_str("std"), g->std_package); + g->main_pkg->package_table.put(buf_create_from_str("builtin"), g->compile_var_package); + g->main_pkg->package_table.put(buf_create_from_str("root"), g->root_pkg); + g->std_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package); + g->std_package->package_table.put(buf_create_from_str("std"), g->std_package); + g->std_package->package_table.put(buf_create_from_str("root"), g->root_pkg); g->compile_var_import = add_source_file(g, g->compile_var_package, builtin_zig_path, contents, SourceKindPkgMain); @@ -8670,7 +8666,7 @@ static void init(CodeGen *g) { // no longer reference DW_AT_comp_dir, for the purpose of being able to support the // common practice of stripping all but the line number sections from an executable. const char *compile_unit_dir = target_os_is_darwin(g->zig_target->os) ? "." : - buf_ptr(&g->root_package->root_src_dir); + buf_ptr(&g->main_pkg->root_src_dir); ZigLLVMDIFile *compile_unit_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(g->root_out_name), compile_unit_dir); @@ -9083,30 +9079,7 @@ void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_us } } -static ZigType *add_special_code(CodeGen *g, ZigPackage *package, const char *basename) { - Buf *code_basename = buf_create_from_str(basename); - Buf path_to_code_src = BUF_INIT; - os_path_join(g->zig_std_special_dir, code_basename, &path_to_code_src); - - Buf *resolve_paths[] = {&path_to_code_src}; - Buf *resolved_path = buf_alloc(); - *resolved_path = os_path_resolve(resolve_paths, 1); - Buf *import_code = buf_alloc(); - Error err; - if ((err = file_fetch(g, resolved_path, import_code))) { - zig_panic("unable to open '%s': %s\n", buf_ptr(&path_to_code_src), err_str(err)); - } - - return add_source_file(g, package, resolved_path, import_code, SourceKindPkgMain); -} - -static ZigPackage *create_start_pkg(CodeGen *g, ZigPackage *pkg_with_main) { - ZigPackage *package = codegen_create_package(g, buf_ptr(g->zig_std_special_dir), "start.zig", "std.special"); - package->package_table.put(buf_create_from_str("root"), pkg_with_main); - return package; -} - -static void create_test_compile_var_and_add_test_runner(CodeGen *g) { +static void update_test_functions_builtin_decl(CodeGen *g) { Error err; assert(g->is_test_build); @@ -9166,16 +9139,15 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) { update_compile_var(g, buf_create_from_str("test_functions"), test_fn_slice); assert(g->test_runner_package != nullptr); - g->test_runner_import = add_special_code(g, g->test_runner_package, "test_runner.zig"); } static Buf *get_resolved_root_src_path(CodeGen *g) { // TODO memoize - if (buf_len(&g->root_package->root_src_path) == 0) + if (buf_len(&g->main_pkg->root_src_path) == 0) return nullptr; Buf rel_full_path = BUF_INIT; - os_path_join(&g->root_package->root_src_dir, &g->root_package->root_src_path, &rel_full_path); + os_path_join(&g->main_pkg->root_src_dir, &g->main_pkg->root_src_path, &rel_full_path); Buf *resolved_path = buf_alloc(); Buf *resolve_paths[] = {&rel_full_path}; @@ -9198,7 +9170,7 @@ static void gen_root_source(CodeGen *g) { exit(1); } - ZigType *root_import_alias = add_source_file(g, g->root_package, resolved_path, source_code, SourceKindRoot); + ZigType *root_import_alias = add_source_file(g, g->main_pkg, resolved_path, source_code, SourceKindRoot); assert(root_import_alias == g->root_import); assert(g->root_out_name); @@ -9250,16 +9222,8 @@ static void gen_root_source(CodeGen *g) { } report_errors_and_maybe_exit(g); - if (!g->is_test_build) { - g->start_import = add_special_code(g, create_start_pkg(g, g->root_package), "start.zig"); - } - if (!g->error_during_imports) { - semantic_analyze(g); - } if (g->is_test_build) { - create_test_compile_var_and_add_test_runner(g); - g->start_import = add_special_code(g, create_start_pkg(g, g->test_runner_package), "start.zig"); - + update_test_functions_builtin_decl(g); if (!g->error_during_imports) { semantic_analyze(g); } @@ -10058,7 +10022,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { CacheHash *ch = &g->cache_hash; cache_init(ch, manifest_dir); - add_cache_pkg(g, ch, g->root_package); + add_cache_pkg(g, ch, g->main_pkg); if (g->linker_script != nullptr) { cache_file(ch, buf_create_from_str(g->linker_script)); } @@ -10141,7 +10105,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { } static bool need_llvm_module(CodeGen *g) { - return buf_len(&g->root_package->root_src_path) != 0; + return buf_len(&g->main_pkg->root_src_path) != 0; } static void resolve_out_paths(CodeGen *g) { @@ -10388,8 +10352,7 @@ ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const c assert(g->compile_var_package != nullptr); pkg->package_table.put(buf_create_from_str("std"), g->std_package); - ZigPackage *main_pkg = g->is_test_build ? g->test_runner_package : g->root_package; - pkg->package_table.put(buf_create_from_str("root"), main_pkg); + pkg->package_table.put(buf_create_from_str("root"), g->root_pkg); pkg->package_table.put(buf_create_from_str("builtin"), g->compile_var_package); } @@ -10516,15 +10479,13 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget buf_len(&resolved_root_src_path) - buf_len(&resolved_main_pkg_path) - 1); } - g->root_package = new_package(buf_ptr(root_pkg_path), buf_ptr(rel_root_src_path), ""); + g->main_pkg = new_package(buf_ptr(root_pkg_path), buf_ptr(rel_root_src_path), ""); g->std_package = new_package(buf_ptr(g->zig_std_dir), "std.zig", "std"); - g->root_package->package_table.put(buf_create_from_str("std"), g->std_package); + g->main_pkg->package_table.put(buf_create_from_str("std"), g->std_package); } else { - g->root_package = new_package(".", "", ""); + g->main_pkg = new_package(".", "", ""); } - g->root_package->package_table.put(buf_create_from_str("root"), g->root_package); - g->zig_std_special_dir = buf_alloc(); os_path_join(g->zig_std_dir, buf_sprintf("special"), g->zig_std_special_dir); diff --git a/src/dump_analysis.cpp b/src/dump_analysis.cpp index 2b7d7a8bd9..c31438b658 100644 --- a/src/dump_analysis.cpp +++ b/src/dump_analysis.cpp @@ -1216,7 +1216,7 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const jw_end_object(jw); jw_object_field(jw, "rootPkg"); - anal_dump_pkg_ref(&ctx, g->root_package); + anal_dump_pkg_ref(&ctx, g->main_pkg); // Poke the functions for (size_t i = 0; i < g->fn_defs.length; i += 1) { diff --git a/src/ir.cpp b/src/ir.cpp index 8b588b5dee..bdf8c33bc2 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -232,7 +232,6 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr, ZigType *dest_type, IrInstruction *dest_type_src, bool safety_check_on); static ZigValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed); -static void copy_const_val(ZigValue *dest, ZigValue *src); static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align); static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target, ZigType *ptr_type); @@ -718,11 +717,6 @@ static ZigValue *const_ptr_pointee_unchecked(CodeGen *g, ZigValue *const_val) { return result; } -static bool is_opt_err_set(ZigType *ty) { - return ty->id == ZigTypeIdErrorSet || - (ty->id == ZigTypeIdOptional && ty->data.maybe.child_type->id == ZigTypeIdErrorSet); -} - static bool is_tuple(ZigType *type) { return type->id == ZigTypeIdStruct && type->data.structure.special == StructSpecialInferredTuple; } @@ -11451,40 +11445,6 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT } } -// Returns whether the x_optional field of ZigValue is active. -static bool type_has_optional_repr(ZigType *ty) { - if (ty->id != ZigTypeIdOptional) { - return false; - } else if (get_codegen_ptr_type(ty) != nullptr) { - return false; - } else if (is_opt_err_set(ty)) { - return false; - } else { - return true; - } -} - -static void copy_const_val(ZigValue *dest, ZigValue *src) { - memcpy(dest, src, sizeof(ZigValue)); - if (src->special != ConstValSpecialStatic) - return; - dest->parent.id = ConstParentIdNone; - if (dest->type->id == ZigTypeIdStruct) { - dest->data.x_struct.fields = alloc_const_vals_ptrs(dest->type->data.structure.src_field_count); - for (size_t i = 0; i < dest->type->data.structure.src_field_count; i += 1) { - copy_const_val(dest->data.x_struct.fields[i], src->data.x_struct.fields[i]); - dest->data.x_struct.fields[i]->parent.id = ConstParentIdStruct; - dest->data.x_struct.fields[i]->parent.data.p_struct.struct_val = dest; - dest->data.x_struct.fields[i]->parent.data.p_struct.field_index = i; - } - } else if (type_has_optional_repr(dest->type) && dest->data.x_optional != nullptr) { - dest->data.x_optional = create_const_vals(1); - copy_const_val(dest->data.x_optional, src->data.x_optional); - dest->data.x_optional->parent.id = ConstParentIdOptionalPayload; - dest->data.x_optional->parent.data.p_optional_payload.optional_val = dest; - } -} - static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_instr, CastOp cast_op, ZigValue *other_val, ZigType *other_type, diff --git a/src/main.cpp b/src/main.cpp index 5739f68df4..a6b26893b9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -623,7 +623,7 @@ int main(int argc, char **argv) { ZigPackage *build_pkg = codegen_create_package(g, buf_ptr(&build_file_dirname), buf_ptr(&build_file_basename), "std.special"); - g->root_package->package_table.put(buf_create_from_str("@build"), build_pkg); + g->main_pkg->package_table.put(buf_create_from_str("@build"), build_pkg); g->enable_cache = get_cache_opt(enable_cache, true); codegen_build_and_link(g); if (root_progress_node != nullptr) { @@ -1269,7 +1269,7 @@ int main(int argc, char **argv) { codegen_set_test_name_prefix(g, buf_create_from_str(test_name_prefix)); } - add_package(g, cur_pkg, g->root_package); + add_package(g, cur_pkg, g->main_pkg); if (cmd == CmdBuild || cmd == CmdRun || cmd == CmdTest) { g->c_source_files = c_source_files;