From c6295fe9abf5508d522ab4000b577a6f30a98a88 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 30 Sep 2017 18:58:41 -0400 Subject: [PATCH] remove zigrt adds test case for #394 partially reverts a32b5929ccf8cbf79396d8924097a1a911985dac --- CMakeLists.txt | 2 +- src/all_types.hpp | 6 +- src/analyze.cpp | 55 +++--------------- src/analyze.hpp | 1 - src/codegen.cpp | 94 ++++++++++++++++--------------- src/codegen.hpp | 1 - src/link.cpp | 1 - std/special/builtin.zig | 19 ++++++- std/special/compiler_rt/index.zig | 10 ++++ std/special/panic.zig | 14 +++++ std/special/zigrt.zig | 18 ------ test/behavior.zig | 1 + test/cases/bugs/394.zig | 9 +++ 13 files changed, 109 insertions(+), 122 deletions(-) create mode 100644 std/special/panic.zig delete mode 100644 std/special/zigrt.zig create mode 100644 test/cases/bugs/394.zig diff --git a/CMakeLists.txt b/CMakeLists.txt index c5448f32bc..ee44029bdb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -585,8 +585,8 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/special/compiler_rt/udivmod.zig" DESTINAT install(FILES "${CMAKE_SOURCE_DIR}/std/special/compiler_rt/udivmoddi4.zig" DESTINATION "${ZIG_STD_DEST}/special/compiler_rt") install(FILES "${CMAKE_SOURCE_DIR}/std/special/compiler_rt/udivmodti4.zig" DESTINATION "${ZIG_STD_DEST}/special/compiler_rt") install(FILES "${CMAKE_SOURCE_DIR}/std/special/compiler_rt/umodti3.zig" DESTINATION "${ZIG_STD_DEST}/special/compiler_rt") +install(FILES "${CMAKE_SOURCE_DIR}/std/special/panic.zig" DESTINATION "${ZIG_STD_DEST}/special") install(FILES "${CMAKE_SOURCE_DIR}/std/special/test_runner.zig" DESTINATION "${ZIG_STD_DEST}/special") -install(FILES "${CMAKE_SOURCE_DIR}/std/special/zigrt.zig" DESTINATION "${ZIG_STD_DEST}/special") if (ZIG_TEST_COVERAGE) add_custom_target(coverage diff --git a/src/all_types.hpp b/src/all_types.hpp index 8628bf0071..aefaa736cf 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1472,7 +1472,7 @@ struct CodeGen { bool is_native_target; PackageTableEntry *root_package; PackageTableEntry *std_package; - PackageTableEntry *zigrt_package; + PackageTableEntry *panic_package; PackageTableEntry *test_runner_package; PackageTableEntry *compile_var_package; ImportTableEntry *compile_var_import; @@ -1484,7 +1484,6 @@ struct CodeGen { Buf *mios_version_min; bool linker_rdynamic; const char *linker_script; - bool omit_zigrt; // The function definitions this module includes. There must be a corresponding // fn_protos entry. @@ -1498,8 +1497,7 @@ struct CodeGen { OutType out_type; FnTableEntry *cur_fn; FnTableEntry *main_fn; - FnTableEntry *user_panic_fn; - FnTableEntry *extern_panic_fn; + FnTableEntry *panic_fn; LLVMValueRef cur_ret_ptr; LLVMValueRef cur_fn_val; bool c_want_stdint; diff --git a/src/analyze.cpp b/src/analyze.cpp index fbe96fb91f..1a39140e66 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -2072,11 +2072,10 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { if (fn_def_node) g->fn_defs.append(fn_table_entry); - if (g->have_pub_main && scope_is_root_decls(tld_fn->base.parent_scope) && - ((!g->is_test_build && import == g->root_import) || - (g->is_test_build && import == g->test_runner_import))) + if (scope_is_root_decls(tld_fn->base.parent_scope) && + (import == g->root_import || import->package == g->panic_package)) { - if (buf_eql_str(&fn_table_entry->symbol_name, "main")) { + if (g->have_pub_main && buf_eql_str(&fn_table_entry->symbol_name, "main")) { g->main_fn = fn_table_entry; if (tld_fn->base.visib_mod != VisibModExport) { @@ -2088,13 +2087,12 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { buf_ptr(&actual_return_type->name))); } } - } else if (buf_eql_str(&fn_table_entry->symbol_name, "panic")) { + } else if ((import->package == g->panic_package || g->have_pub_panic) && + buf_eql_str(&fn_table_entry->symbol_name, "panic")) + { + g->panic_fn = fn_table_entry; typecheck_panic_fn(g, fn_table_entry); } - } else if (import->package == g->zigrt_package && scope_is_root_decls(tld_fn->base.parent_scope)) { - if (buf_eql_str(&fn_table_entry->symbol_name, "__zig_panic")) { - g->extern_panic_fn = fn_table_entry; - } } } } else if (source_node->type == NodeTypeTestDecl) { @@ -2272,14 +2270,6 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { tld_fn->extern_lib_name = node->data.fn_proto.lib_name; add_top_level_decl(g, decls_scope, &tld_fn->base); - ImportTableEntry *import = get_scope_import(&decls_scope->base); - if (import == g->root_import && scope_is_root_decls(&decls_scope->base) && - buf_eql_str(fn_name, "panic")) - { - update_compile_var(g, buf_create_from_str("__zig_panic_implementation_provided"), - create_const_bool(g, true)); - } - break; } case NodeTypeUse: @@ -4606,37 +4596,6 @@ ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value) { return nullptr; } -FnTableEntry *get_extern_panic_fn(CodeGen *g) { - if (g->extern_panic_fn) - return g->extern_panic_fn; - - FnTypeId fn_type_id = {0}; - fn_type_id.cc = CallingConventionCold; - fn_type_id.param_count = 2; - fn_type_id.param_info = allocate(2); - fn_type_id.next_param_index = 0; - fn_type_id.param_info[0].type = get_pointer_to_type(g, g->builtin_types.entry_u8, true); - fn_type_id.param_info[1].type = g->builtin_types.entry_usize; - fn_type_id.return_type = g->builtin_types.entry_unreachable; - - TypeTableEntry *fn_type = get_fn_type(g, &fn_type_id); - assert(!type_is_invalid(fn_type)); - - FnTableEntry *fn_entry = create_fn_raw(FnInlineAuto, GlobalLinkageIdStrong); - buf_init_from_str(&fn_entry->symbol_name, "__zig_panic"); - - TldFn *tld_fn = allocate(1); - init_tld(&tld_fn->base, TldIdFn, &fn_entry->symbol_name, VisibModPrivate, nullptr, nullptr); - tld_fn->fn_entry = fn_entry; - - g->external_prototypes.put_unique(tld_fn->base.name, &tld_fn->base); - - fn_entry->type_entry = fn_type; - - g->extern_panic_fn = fn_entry; - return g->extern_panic_fn; -} - static const TypeTableEntryId all_type_ids[] = { TypeTableEntryIdMetaType, TypeTableEntryIdVoid, diff --git a/src/analyze.hpp b/src/analyze.hpp index 9e9e066126..4f56640592 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -157,7 +157,6 @@ ConstExprValue *create_const_vals(size_t count); TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits); ConstParent *get_const_val_parent(CodeGen *g, ConstExprValue *value); -FnTableEntry *get_extern_panic_fn(CodeGen *g); TypeTableEntry *create_enum_tag_type(CodeGen *g, TypeTableEntry *enum_type, TypeTableEntry *int_type); void expand_undef_array(CodeGen *g, ConstExprValue *const_val); void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value); diff --git a/src/codegen.cpp b/src/codegen.cpp index 623f946307..b9298f84cb 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -157,10 +157,6 @@ void codegen_set_llvm_argv(CodeGen *g, const char **args, size_t len) { g->llvm_argv_len = len; } -void codegen_set_omit_zigrt(CodeGen *g, bool omit_zigrt) { - g->omit_zigrt = omit_zigrt; -} - void codegen_set_test_filter(CodeGen *g, Buf *filter) { g->test_filter = filter; } @@ -751,26 +747,12 @@ static LLVMValueRef get_panic_msg_ptr_val(CodeGen *g, PanicMsgId msg_id) { return val->global_refs->llvm_global; } -static void gen_panic_raw(CodeGen *g, LLVMValueRef msg_ptr, LLVMValueRef msg_len) { - FnTableEntry *panic_fn = get_extern_panic_fn(g); - LLVMValueRef fn_val = fn_llvm_value(g, panic_fn); - LLVMValueRef args[] = { msg_ptr, msg_len }; - LLVMCallConv llvm_cc = get_llvm_cc(g, panic_fn->type_entry->data.fn.fn_type_id.cc); - ZigLLVMBuildCall(g->builder, fn_val, args, 2, llvm_cc, false, ""); - LLVMBuildUnreachable(g->builder); -} - static void gen_panic(CodeGen *g, LLVMValueRef msg_arg) { - TypeTableEntry *ptr_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true); - TypeTableEntry *str_type = get_slice_type(g, ptr_type); - size_t ptr_index = str_type->data.structure.fields[slice_ptr_index].gen_index; - size_t len_index = str_type->data.structure.fields[slice_len_index].gen_index; - LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, msg_arg, (unsigned)ptr_index, ""); - LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, msg_arg, (unsigned)len_index, ""); - - LLVMValueRef msg_ptr = gen_load_untyped(g, ptr_ptr, 0, false, ""); - LLVMValueRef msg_len = gen_load_untyped(g, len_ptr, 0, false, ""); - gen_panic_raw(g, msg_ptr, msg_len); + assert(g->panic_fn != nullptr); + LLVMValueRef fn_val = fn_llvm_value(g, g->panic_fn); + LLVMCallConv llvm_cc = get_llvm_cc(g, g->panic_fn->type_entry->data.fn.fn_type_id.cc); + ZigLLVMBuildCall(g->builder, fn_val, &msg_arg, 1, llvm_cc, false, ""); + LLVMBuildUnreachable(g->builder); } static void gen_debug_safety_crash(CodeGen *g, PanicMsgId msg_id) { @@ -818,26 +800,40 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { } uint32_t u8_align_bytes = get_abi_alignment(g, g->builtin_types.entry_u8); LLVMValueRef init_value = LLVMConstArray(LLVMInt8Type(), err_buf_vals, err_buf_len); - Buf *global_name = get_mangled_name(g, buf_create_from_str("__zig_panic_buf"), false); - LLVMValueRef global_value = LLVMAddGlobal(g->module, LLVMTypeOf(init_value), buf_ptr(global_name)); - LLVMSetInitializer(global_value, init_value); - LLVMSetLinkage(global_value, LLVMInternalLinkage); - LLVMSetGlobalConstant(global_value, false); - LLVMSetUnnamedAddr(global_value, true); - LLVMSetAlignment(global_value, u8_align_bytes); + LLVMValueRef global_array = LLVMAddGlobal(g->module, LLVMTypeOf(init_value), ""); + LLVMSetInitializer(global_array, init_value); + LLVMSetLinkage(global_array, LLVMInternalLinkage); + LLVMSetGlobalConstant(global_array, false); + LLVMSetUnnamedAddr(global_array, true); + LLVMSetAlignment(global_array, u8_align_bytes); TypeTableEntry *usize = g->builtin_types.entry_usize; LLVMValueRef full_buf_ptr_indices[] = { LLVMConstNull(usize->type_ref), LLVMConstNull(usize->type_ref), }; - LLVMValueRef full_buf_ptr = LLVMConstInBoundsGEP(global_value, full_buf_ptr_indices, 2); + LLVMValueRef full_buf_ptr = LLVMConstInBoundsGEP(global_array, full_buf_ptr_indices, 2); + + + TypeTableEntry *u8_ptr_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true); + TypeTableEntry *str_type = get_slice_type(g, u8_ptr_type); + LLVMValueRef global_slice_fields[] = { + full_buf_ptr, + LLVMConstNull(usize->type_ref), + }; + LLVMValueRef slice_init_value = LLVMConstNamedStruct(str_type->type_ref, global_slice_fields, 2); + LLVMValueRef global_slice = LLVMAddGlobal(g->module, LLVMTypeOf(slice_init_value), ""); + LLVMSetInitializer(global_slice, slice_init_value); + LLVMSetLinkage(global_slice, LLVMInternalLinkage); + LLVMSetGlobalConstant(global_slice, false); + LLVMSetUnnamedAddr(global_slice, true); + LLVMSetAlignment(global_slice, get_abi_alignment(g, str_type)); LLVMValueRef offset_ptr_indices[] = { LLVMConstNull(usize->type_ref), LLVMConstInt(usize->type_ref, unwrap_err_msg_text_len, false), }; - LLVMValueRef offset_buf_ptr = LLVMConstInBoundsGEP(global_value, offset_ptr_indices, 2); + LLVMValueRef offset_buf_ptr = LLVMConstInBoundsGEP(global_array, offset_ptr_indices, 2); Buf *fn_name = get_mangled_name(g, buf_create_from_str("__zig_fail_unwrap"), false); LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), &g->err_tag_type->type_ref, 1, false); @@ -888,7 +884,10 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { LLVMValueRef const_prefix_len = LLVMConstInt(LLVMTypeOf(err_name_len), strlen(unwrap_err_msg_text), false); LLVMValueRef full_buf_len = LLVMBuildNUWAdd(g->builder, const_prefix_len, err_name_len, ""); - gen_panic_raw(g, full_buf_ptr, full_buf_len); + LLVMValueRef global_slice_len_field_ptr = LLVMBuildStructGEP(g->builder, global_slice, slice_len_index, ""); + gen_store(g, full_buf_len, global_slice_len_field_ptr, u8_ptr_type); + + gen_panic(g, global_slice); LLVMPositionBuilderAtEnd(g->builder, prev_block); LLVMSetCurrentDebugLocation(g->builder, prev_debug_location); @@ -3744,8 +3743,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { fields[type_struct_field->gen_index] = gen_const_val(g, &const_val->data.x_struct.fields[i]); } } - return LLVMConstStruct(fields, type_entry->data.structure.gen_field_count, - type_entry->data.structure.layout == ContainerLayoutPacked); + return LLVMConstNamedStruct(type_entry->type_ref, fields, type_entry->data.structure.gen_field_count); } case TypeTableEntryIdUnion: { @@ -4103,7 +4101,7 @@ static void validate_inline_fns(CodeGen *g) { } static void do_code_gen(CodeGen *g) { - if (g->verbose || g->verbose_ir) { + if (g->verbose) { fprintf(stderr, "\nCode Generation:\n"); fprintf(stderr, "------------------\n"); } @@ -4918,8 +4916,6 @@ static void define_builtin_compile_vars(CodeGen *g) { buf_appendf(contents, "pub const mode = %s;\n", build_mode_to_str(g->build_mode)); buf_appendf(contents, "pub const link_libc = %s;\n", bool_to_str(g->libc_link_lib != nullptr)); - buf_appendf(contents, "pub const __zig_panic_implementation_provided = %s; // overwritten later\n", - bool_to_str(false)); buf_appendf(contents, "pub const __zig_test_fn_slice = {}; // overwritten later\n"); ensure_cache_dir(g); @@ -5105,10 +5101,8 @@ static PackageTableEntry *create_test_runner_pkg(CodeGen *g) { return codegen_create_package(g, buf_ptr(g->zig_std_special_dir), "test_runner.zig"); } -static PackageTableEntry *create_zigrt_pkg(CodeGen *g) { - PackageTableEntry *package = codegen_create_package(g, buf_ptr(g->zig_std_special_dir), "zigrt.zig"); - package->package_table.put(buf_create_from_str("@root"), g->root_package); - return package; +static PackageTableEntry *create_panic_pkg(CodeGen *g) { + return codegen_create_package(g, buf_ptr(g->zig_std_special_dir), "panic.zig"); } static void create_test_compile_var_and_add_test_runner(CodeGen *g) { @@ -5190,9 +5184,19 @@ static void gen_root_source(CodeGen *g) { { g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->root_package), "bootstrap.zig"); } - if (!g->omit_zigrt) { - g->zigrt_package = create_zigrt_pkg(g); - add_special_code(g, g->zigrt_package, "zigrt.zig"); + ImportTableEntry *import_with_panic; + if (g->have_pub_panic) { + import_with_panic = g->root_import; + } else { + g->panic_package = create_panic_pkg(g); + import_with_panic = add_special_code(g, g->panic_package, "panic.zig"); + } + // Zig has lazy top level definitions. Here we semantically analyze the panic function. + { + scan_import(g, import_with_panic); + Tld *panic_tld = find_decl(g, &import_with_panic->decls_scope->base, buf_create_from_str("panic")); + assert(panic_tld != nullptr); + resolve_top_level_decl(g, panic_tld, false, nullptr); } if (g->verbose) { diff --git a/src/codegen.hpp b/src/codegen.hpp index 03d51fce35..93975fd789 100644 --- a/src/codegen.hpp +++ b/src/codegen.hpp @@ -41,7 +41,6 @@ void codegen_set_rdynamic(CodeGen *g, bool rdynamic); void codegen_set_mmacosx_version_min(CodeGen *g, Buf *mmacosx_version_min); void codegen_set_mios_version_min(CodeGen *g, Buf *mios_version_min); void codegen_set_linker_script(CodeGen *g, const char *linker_script); -void codegen_set_omit_zigrt(CodeGen *g, bool omit_zigrt); void codegen_set_test_filter(CodeGen *g, Buf *filter); void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix); void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patch); diff --git a/src/link.cpp b/src/link.cpp index ecf980ab4a..359474204b 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -35,7 +35,6 @@ static Buf *build_o_raw(CodeGen *parent_gen, const char *oname, Buf *full_path) ZigTarget *child_target = parent_gen->is_native_target ? nullptr : &parent_gen->zig_target; CodeGen *child_gen = codegen_create(full_path, child_target, OutTypeObj, parent_gen->build_mode); - codegen_set_omit_zigrt(child_gen, true); child_gen->want_h_file = false; child_gen->verbose_link = parent_gen->verbose_link; diff --git a/std/special/builtin.zig b/std/special/builtin.zig index 17839a51d5..51e6646574 100644 --- a/std/special/builtin.zig +++ b/std/special/builtin.zig @@ -1,11 +1,21 @@ // These functions are provided when not linking against libc because LLVM // sometimes generates code that calls them. -// Note that these functions do not return `dest`, like the libc API. -// The semantics of these functions is dictated by the corresponding -// LLVM intrinsics, not by the libc API. const builtin = @import("builtin"); +// Avoid dragging in the debug safety mechanisms into this .o file, +// unless we're trying to test this file. +pub coldcc fn panic(msg: []const u8) -> noreturn { + if (builtin.is_test) { + @import("std").debug.panic("{}", msg); + } else { + unreachable; + } +} + +// Note that memset does not return `dest`, like the libc API. +// The semantics of memset is dictated by the corresponding +// LLVM intrinsics, not by the libc API. export fn memset(dest: ?&u8, c: u8, n: usize) { @setDebugSafety(this, false); @@ -14,6 +24,9 @@ export fn memset(dest: ?&u8, c: u8, n: usize) { (??dest)[index] = c; } +// Note that memcpy does not return `dest`, like the libc API. +// The semantics of memcpy is dictated by the corresponding +// LLVM intrinsics, not by the libc API. export fn memcpy(noalias dest: ?&u8, noalias src: ?&const u8, n: usize) { @setDebugSafety(this, false); diff --git a/std/special/compiler_rt/index.zig b/std/special/compiler_rt/index.zig index a19eac4c2c..d005c92ba1 100644 --- a/std/special/compiler_rt/index.zig +++ b/std/special/compiler_rt/index.zig @@ -23,6 +23,16 @@ const assert = @import("../../debug.zig").assert; const __udivmoddi4 = @import("udivmoddi4.zig").__udivmoddi4; +// Avoid dragging in the debug safety mechanisms into this .o file, +// unless we're trying to test this file. +pub coldcc fn panic(msg: []const u8) -> noreturn { + if (is_test) { + @import("std").debug.panic("{}", msg); + } else { + unreachable; + } +} + export fn __udivdi3(a: u64, b: u64) -> u64 { @setDebugSafety(this, is_test); @setGlobalLinkage(__udivdi3, builtin.GlobalLinkage.LinkOnce); diff --git a/std/special/panic.zig b/std/special/panic.zig new file mode 100644 index 0000000000..78117a5366 --- /dev/null +++ b/std/special/panic.zig @@ -0,0 +1,14 @@ +// This file is the default panic handler if the root source file does not +// have a `pub fn panic`. +// If this file wants to import other files *by name*, support for that would +// have to be added in the compiler. + +const builtin = @import("builtin"); + +pub coldcc fn panic(msg: []const u8) -> noreturn { + if (builtin.os == builtin.Os.freestanding) { + while (true) {} + } else { + @import("std").debug.panic("{}", msg); + } +} diff --git a/std/special/zigrt.zig b/std/special/zigrt.zig deleted file mode 100644 index 26d5a161c7..0000000000 --- a/std/special/zigrt.zig +++ /dev/null @@ -1,18 +0,0 @@ -// This file contains functions that zig depends on to coordinate between -// multiple .o files. The symbols are defined LinkOnce so that multiple -// instances of zig_rt.zig do not conflict with each other. - -const builtin = @import("builtin"); - -export coldcc fn __zig_panic(message_ptr: &const u8, message_len: usize) -> noreturn { - @setGlobalLinkage(__zig_panic, builtin.GlobalLinkage.LinkOnce); - @setDebugSafety(this, false); - - if (builtin.__zig_panic_implementation_provided) { - @import("@root").panic(message_ptr[0..message_len]); - } else if (builtin.os == builtin.Os.freestanding) { - while (true) {} - } else { - @import("std").debug.panic("{}", message_ptr[0..message_len]); - } -} diff --git a/test/behavior.zig b/test/behavior.zig index c9c1182d1c..54c954be3d 100644 --- a/test/behavior.zig +++ b/test/behavior.zig @@ -6,6 +6,7 @@ comptime { _ = @import("cases/atomics.zig"); _ = @import("cases/bitcast.zig"); _ = @import("cases/bool.zig"); + _ = @import("cases/bugs/394.zig"); _ = @import("cases/cast.zig"); _ = @import("cases/const_slice_child.zig"); _ = @import("cases/defer.zig"); diff --git a/test/cases/bugs/394.zig b/test/cases/bugs/394.zig new file mode 100644 index 0000000000..aaa7de6f88 --- /dev/null +++ b/test/cases/bugs/394.zig @@ -0,0 +1,9 @@ +const E = enum { A: [9]u8, B: u64, }; +const S = struct { x: u8, y: E, }; + +const assert = @import("std").debug.assert; + +test "bug 394 fixed" { + const x = S { .x = 3, .y = E.B {1} }; + assert(x.x == 3); +}