Commit c6295fe9ab

Andrew Kelley <superjoe30@gmail.com>
2017-10-01 00:58:41
remove zigrt
adds test case for #394 partially reverts a32b5929ccf8cbf79396d8924097a1a911985dac
1 parent 6db589f
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;
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<FnTypeParamInfo>(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<TldFn>(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,
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);
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) {
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);
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;
 
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);
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);
 
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);
+    }
+}
std/special/zigrt.zig
@@ -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]);
-    }
-}
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);
+}
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");
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