authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-03-26 21:07:07-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-03-26 21:07:07-04:00
loga32b5929ccf8cbf79396d8924097a1a911985dac
treec45c7413d1fb6eab9ba102f3a0b7d48df1738164
parent8aeea72654b2efbd068abe207b42170c4d27ee03

add stack protector safety when linking libc

* introduce zigrt file. it contains only weak symbols so that multiple instances can be merged. it contains __zig_panic so that multiple .o files can call the same panic function. * remove `@setFnVisible` builtin and add @setGlobalLinkage builtin which is more powerful * add `@panic` builtin function. * fix collision of symbols with extern prototypes and internal function names * add stack protector safety when linking against libc. To add the safety mechanism without libc requires implementing Thread Local Storage. See #276

19 files changed, 437 insertions(+), 185 deletions(-)

CMakeLists.txt+1-1
......@@ -233,8 +233,8 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/sort.zig" DESTINATION "${ZIG_STD_DEST}")
233233install(FILES "${CMAKE_SOURCE_DIR}/std/special/bootstrap.zig" DESTINATION "${ZIG_STD_DEST}/special")
234234install(FILES "${CMAKE_SOURCE_DIR}/std/special/builtin.zig" DESTINATION "${ZIG_STD_DEST}/special")
235235install(FILES "${CMAKE_SOURCE_DIR}/std/special/compiler_rt.zig" DESTINATION "${ZIG_STD_DEST}/special")
236install(FILES "${CMAKE_SOURCE_DIR}/std/special/panic.zig" DESTINATION "${ZIG_STD_DEST}/special")
237236install(FILES "${CMAKE_SOURCE_DIR}/std/special/test_runner.zig" DESTINATION "${ZIG_STD_DEST}/special")
237install(FILES "${CMAKE_SOURCE_DIR}/std/special/zigrt.zig" DESTINATION "${ZIG_STD_DEST}/special")
238238install(FILES "${CMAKE_SOURCE_DIR}/std/target.zig" DESTINATION "${ZIG_STD_DEST}")
239239
240240add_executable(run_tests ${TEST_SOURCES})
doc/emacs/zig-mode.el+1-1
......@@ -1,5 +1,5 @@
11(setq zig
2 '(("\\b\\(@sizeOf\\|@alignOf\\|@maxValue\\|@minValue\\|@memberCount\\|@typeOf\\|@addWithOverflow\\|@subWithOverflow\\|@mulWithOverflow\\|@shlWithOverflow\\|@cInclude\\|@cDefine\\|@cUndef\\|@compileVar\\|@generatedCode\\|@ctz\\|@clz\\|@import\\|@cImport\\|@errorName\\|@typeName\\|@isInteger\\|@isFloat\\|@canImplicitCast\\|@embedFile\\|@cmpxchg\\|@fence\\|@divExact\\|@truncate\\|@compileError\\|@compileLog\\|@intType\\|@unreachable\\|@setFnTest\\|@setFnVisible\\|@setDebugSafety\\|@alloca\\|@setGlobalAlign\\|@setGlobalSection\\)" . font-lock-builtin-face)
2 '(("\\b\\(@sizeOf\\|@alignOf\\|@maxValue\\|@minValue\\|@memberCount\\|@typeOf\\|@addWithOverflow\\|@subWithOverflow\\|@mulWithOverflow\\|@shlWithOverflow\\|@cInclude\\|@cDefine\\|@cUndef\\|@compileVar\\|@generatedCode\\|@ctz\\|@clz\\|@import\\|@cImport\\|@errorName\\|@typeName\\|@isInteger\\|@isFloat\\|@canImplicitCast\\|@embedFile\\|@cmpxchg\\|@fence\\|@divExact\\|@truncate\\|@compileError\\|@compileLog\\|@intType\\|@unreachable\\|@setDebugSafety\\|@alloca\\|@setGlobalAlign\\|@setGlobalLinkage\\|@setGlobalSection\\)" . font-lock-builtin-face)
33
44("\\b\\(fn\\|use\\|while\\|for\\|break\\|continue\\|goto\\|if\\|else\\|switch\\|try\\|return\\|defer\\|asm\\|unreachable\\|const\\|var\\|extern\\|packed\\|export\\|pub\\|noalias\\|inline\\|comptime\\|nakedcc\\|coldcc\\|volatile\\|struct\\|enum\\|union\\)\\b" . font-lock-keyword-face)
55
doc/langref.md+7
......@@ -626,3 +626,10 @@ Sets the alignment property of a global variable.
626626### @setGlobalSection(global_variable_name, section_name: []u8) -> bool
627627
628628Puts the global variable in the specified section.
629
630### @panic(message: []const u8) -> noreturn
631
632Invokes the panic handler function. By default the panic handler function
633calls the public `panic` function exposed in the root source file, or
634if there is not one specified, invokes the one provided in
635`std/special/panic.zig`.
src/all_types.hpp+35-15
......@@ -237,6 +237,13 @@ enum VisibMod {
237237 VisibModExport,
238238};
239239
240enum GlobalLinkageId {
241 GlobalLinkageIdInternal,
242 GlobalLinkageIdStrong,
243 GlobalLinkageIdWeak,
244 GlobalLinkageIdLinkOnce,
245};
246
240247enum TldId {
241248 TldIdVar,
242249 TldIdFn,
......@@ -273,6 +280,8 @@ struct TldVar {
273280 uint64_t alignment;
274281 AstNode *set_global_section_node;
275282 Buf *section_name;
283 AstNode *set_global_linkage_node;
284 GlobalLinkageId linkage;
276285};
277286
278287struct TldFn {
......@@ -1116,8 +1125,6 @@ struct FnTableEntry {
11161125 Buf symbol_name;
11171126 TypeTableEntry *type_entry; // function type
11181127 TypeTableEntry *implicit_return_type;
1119 bool internal_linkage;
1120 bool disable_export;
11211128 bool is_test;
11221129 FnInline fn_inline;
11231130 FnAnalState anal_state;
......@@ -1128,7 +1135,6 @@ struct FnTableEntry {
11281135 Buf **param_names;
11291136
11301137 AstNode *fn_no_inline_set_node;
1131 AstNode *fn_export_set_node;
11321138 AstNode *fn_static_eval_set_node;
11331139
11341140 ZigList<IrInstruction *> alloca_list;
......@@ -1138,6 +1144,8 @@ struct FnTableEntry {
11381144 uint64_t alignment;
11391145 AstNode *set_global_section_node;
11401146 Buf *section_name;
1147 AstNode *set_global_linkage_node;
1148 GlobalLinkageId linkage;
11411149};
11421150
11431151uint32_t fn_table_entry_hash(FnTableEntry*);
......@@ -1178,7 +1186,6 @@ enum BuiltinFnId {
11781186 BuiltinFnIdDivExact,
11791187 BuiltinFnIdTruncate,
11801188 BuiltinFnIdIntType,
1181 BuiltinFnIdSetFnVisible,
11821189 BuiltinFnIdSetDebugSafety,
11831190 BuiltinFnIdAlloca,
11841191 BuiltinFnIdTypeName,
......@@ -1187,6 +1194,8 @@ enum BuiltinFnId {
11871194 BuiltinFnIdCanImplicitCast,
11881195 BuiltinFnIdSetGlobalAlign,
11891196 BuiltinFnIdSetGlobalSection,
1197 BuiltinFnIdSetGlobalLinkage,
1198 BuiltinFnIdPanic,
11901199};
11911200
11921201struct BuiltinFnEntry {
......@@ -1300,7 +1309,8 @@ struct CodeGen {
13001309 HashMap<Scope *, IrInstruction *, fn_eval_hash, fn_eval_eql> memoized_fn_eval_table;
13011310 HashMap<ZigLLVMFnKey, LLVMValueRef, zig_llvm_fn_key_hash, zig_llvm_fn_key_eql> llvm_fn_table;
13021311 HashMap<Buf *, ConstExprValue *, buf_hash, buf_eql_buf> compile_vars;
1303 HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_symbol_names;
1312 HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> exported_symbol_names;
1313 HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes;
13041314
13051315 ZigList<ImportTableEntry *> import_queue;
13061316 size_t import_queue_index;
......@@ -1346,6 +1356,7 @@ struct CodeGen {
13461356 TypeTableEntry *entry_environ_enum;
13471357 TypeTableEntry *entry_oformat_enum;
13481358 TypeTableEntry *entry_atomic_order_enum;
1359 TypeTableEntry *entry_global_linkage_enum;
13491360 TypeTableEntry *entry_arg_tuple;
13501361 } builtin_types;
13511362
......@@ -1378,7 +1389,7 @@ struct CodeGen {
13781389 bool is_native_target;
13791390 PackageTableEntry *root_package;
13801391 PackageTableEntry *std_package;
1381 PackageTableEntry *panic_package;
1392 PackageTableEntry *zigrt_package;
13821393 Buf *root_out_name;
13831394 bool windows_subsystem_windows;
13841395 bool windows_subsystem_console;
......@@ -1388,6 +1399,7 @@ struct CodeGen {
13881399 Buf *mios_version_min;
13891400 bool linker_rdynamic;
13901401 const char *linker_script;
1402 bool omit_zigrt;
13911403
13921404 // The function definitions this module includes. There must be a corresponding
13931405 // fn_protos entry.
......@@ -1401,7 +1413,8 @@ struct CodeGen {
14011413 OutType out_type;
14021414 FnTableEntry *cur_fn;
14031415 FnTableEntry *main_fn;
1404 FnTableEntry *panic_fn;
1416 FnTableEntry *user_panic_fn;
1417 FnTableEntry *extern_panic_fn;
14051418 LLVMValueRef cur_ret_ptr;
14061419 LLVMValueRef cur_fn_val;
14071420 ZigList<LLVMBasicBlockRef> break_block_stack;
......@@ -1656,7 +1669,6 @@ enum IrInstructionId {
16561669 IrInstructionIdTypeOf,
16571670 IrInstructionIdToPtrType,
16581671 IrInstructionIdPtrTypeChild,
1659 IrInstructionIdSetFnVisible,
16601672 IrInstructionIdSetDebugSafety,
16611673 IrInstructionIdArrayType,
16621674 IrInstructionIdSliceType,
......@@ -1718,7 +1730,9 @@ enum IrInstructionId {
17181730 IrInstructionIdCanImplicitCast,
17191731 IrInstructionIdSetGlobalAlign,
17201732 IrInstructionIdSetGlobalSection,
1733 IrInstructionIdSetGlobalLinkage,
17211734 IrInstructionIdDeclRef,
1735 IrInstructionIdPanic,
17221736};
17231737
17241738struct IrInstruction {
......@@ -1999,13 +2013,6 @@ struct IrInstructionPtrTypeChild {
19992013 IrInstruction *value;
20002014};
20012015
2002struct IrInstructionSetFnVisible {
2003 IrInstruction base;
2004
2005 IrInstruction *fn_value;
2006 IrInstruction *is_visible;
2007};
2008
20092016struct IrInstructionSetDebugSafety {
20102017 IrInstruction base;
20112018
......@@ -2439,6 +2446,13 @@ struct IrInstructionSetGlobalSection {
24392446 IrInstruction *value;
24402447};
24412448
2449struct IrInstructionSetGlobalLinkage {
2450 IrInstruction base;
2451
2452 Tld *tld;
2453 IrInstruction *value;
2454};
2455
24422456struct IrInstructionDeclRef {
24432457 IrInstruction base;
24442458
......@@ -2446,6 +2460,12 @@ struct IrInstructionDeclRef {
24462460 LVal lval;
24472461};
24482462
2463struct IrInstructionPanic {
2464 IrInstruction base;
2465
2466 IrInstruction *msg;
2467};
2468
24492469static const size_t slice_ptr_index = 0;
24502470static const size_t slice_len_index = 1;
24512471
src/analyze.cpp+59-22
......@@ -1762,7 +1762,7 @@ static void get_fully_qualified_decl_name(Buf *buf, Tld *tld, uint8_t sep) {
17621762 buf_append_buf(buf, tld->name);
17631763}
17641764
1765FnTableEntry *create_fn_raw(FnInline inline_value, bool internal_linkage) {
1765FnTableEntry *create_fn_raw(FnInline inline_value, GlobalLinkageId linkage) {
17661766 FnTableEntry *fn_entry = allocate<FnTableEntry>(1);
17671767
17681768 fn_entry->analyzed_executable.backward_branch_count = &fn_entry->prealloc_bbc;
......@@ -1770,7 +1770,7 @@ FnTableEntry *create_fn_raw(FnInline inline_value, bool internal_linkage) {
17701770 fn_entry->analyzed_executable.fn_entry = fn_entry;
17711771 fn_entry->ir_executable.fn_entry = fn_entry;
17721772 fn_entry->fn_inline = inline_value;
1773 fn_entry->internal_linkage = internal_linkage;
1773 fn_entry->linkage = linkage;
17741774
17751775 return fn_entry;
17761776}
......@@ -1780,8 +1780,9 @@ FnTableEntry *create_fn(AstNode *proto_node) {
17801780 AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
17811781
17821782 FnInline inline_value = fn_proto->is_inline ? FnInlineAlways : FnInlineAuto;
1783 bool internal_linkage = (fn_proto->visib_mod != VisibModExport && !proto_node->data.fn_proto.is_extern);
1784 FnTableEntry *fn_entry = create_fn_raw(inline_value, internal_linkage);
1783 GlobalLinkageId linkage = (fn_proto->visib_mod == VisibModExport || proto_node->data.fn_proto.is_extern) ?
1784 GlobalLinkageIdStrong : GlobalLinkageIdInternal;
1785 FnTableEntry *fn_entry = create_fn_raw(inline_value, linkage);
17851786
17861787 fn_entry->proto_node = proto_node;
17871788 fn_entry->body_node = (proto_node->data.fn_proto.fn_def_node == nullptr) ? nullptr :
......@@ -1807,12 +1808,10 @@ static void wrong_panic_prototype(CodeGen *g, AstNode *proto_node, TypeTableEntr
18071808 buf_ptr(&fn_type->name)));
18081809}
18091810
1810static void typecheck_panic_fn(CodeGen *g) {
1811 assert(g->panic_fn);
1812
1813 AstNode *proto_node = g->panic_fn->proto_node;
1811static void typecheck_panic_fn(CodeGen *g, FnTableEntry *panic_fn) {
1812 AstNode *proto_node = panic_fn->proto_node;
18141813 assert(proto_node->type == NodeTypeFnProto);
1815 TypeTableEntry *fn_type = g->panic_fn->type_entry;
1814 TypeTableEntry *fn_type = panic_fn->type_entry;
18161815 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
18171816 if (fn_type_id->param_count != 1) {
18181817 return wrong_panic_prototype(g, proto_node, fn_type);
......@@ -1862,6 +1861,8 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
18621861 add_node_error(g, param_node, buf_sprintf("missing parameter name"));
18631862 }
18641863 }
1864 } else if (fn_table_entry->linkage != GlobalLinkageIdInternal) {
1865 g->external_prototypes.put_unique(tld_fn->base.name, &tld_fn->base);
18651866 }
18661867
18671868 Scope *child_scope = fn_table_entry->fndef_scope ? &fn_table_entry->fndef_scope->base : tld_fn->base.parent_scope;
......@@ -1892,18 +1893,16 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
18921893 }
18931894 }
18941895 } else if (buf_eql_str(&fn_table_entry->symbol_name, "panic")) {
1895 g->panic_fn = fn_table_entry;
1896 typecheck_panic_fn(g);
1896 typecheck_panic_fn(g, fn_table_entry);
18971897 }
1898 } else if (import->package == g->panic_package && scope_is_root_decls(tld_fn->base.parent_scope)) {
1899 if (buf_eql_str(&fn_table_entry->symbol_name, "panic")) {
1900 g->panic_fn = fn_table_entry;
1901 typecheck_panic_fn(g);
1898 } else if (import->package == g->zigrt_package && scope_is_root_decls(tld_fn->base.parent_scope)) {
1899 if (buf_eql_str(&fn_table_entry->symbol_name, "__zig_panic")) {
1900 g->extern_panic_fn = fn_table_entry;
19021901 }
19031902 }
19041903 }
19051904 } else if (source_node->type == NodeTypeTestDecl) {
1906 FnTableEntry *fn_table_entry = create_fn_raw(FnInlineAuto, false);
1905 FnTableEntry *fn_table_entry = create_fn_raw(FnInlineAuto, GlobalLinkageIdStrong);
19071906
19081907 get_fully_qualified_decl_name(&fn_table_entry->symbol_name, &tld_fn->base, '_');
19091908
......@@ -1931,16 +1930,12 @@ static void resolve_decl_comptime(CodeGen *g, TldCompTime *tld_comptime) {
19311930}
19321931
19331932static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) {
1934 if (tld->visib_mod == VisibModExport ||
1935 (buf_eql_str(tld->name, "panic") &&
1936 (decls_scope->import->package == g->panic_package || decls_scope->import == g->root_import)) ||
1937 (tld->id == TldIdVar && g->is_test_build))
1938 {
1933 if (tld->visib_mod == VisibModExport || (tld->id == TldIdVar && g->is_test_build)) {
19391934 g->resolve_queue.append(tld);
19401935 }
19411936
19421937 if (tld->visib_mod == VisibModExport) {
1943 auto entry = g->external_symbol_names.put_unique(tld->name, tld);
1938 auto entry = g->exported_symbol_names.put_unique(tld->name, tld);
19441939 if (entry) {
19451940 Tld *other_tld = entry->value;
19461941 ErrorMsg *msg = add_node_error(g, tld->source_node,
......@@ -2060,6 +2055,15 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
20602055 TldFn *tld_fn = allocate<TldFn>(1);
20612056 init_tld(&tld_fn->base, TldIdFn, fn_name, visib_mod, node, &decls_scope->base);
20622057 add_top_level_decl(g, decls_scope, &tld_fn->base);
2058
2059 ImportTableEntry *import = get_scope_import(&decls_scope->base);
2060 if (import == g->root_import && scope_is_root_decls(&decls_scope->base) &&
2061 buf_eql_str(fn_name, "panic"))
2062 {
2063 g->compile_vars.put(buf_create_from_str("panic_implementation_provided"),
2064 create_const_bool(g, true));
2065 }
2066
20632067 break;
20642068 }
20652069 case NodeTypeUse:
......@@ -4206,3 +4210,36 @@ ConstParent *get_const_val_parent(ConstExprValue *value) {
42064210 }
42074211 return nullptr;
42084212}
4213
4214FnTableEntry *get_extern_panic_fn(CodeGen *g) {
4215 if (g->extern_panic_fn)
4216 return g->extern_panic_fn;
4217
4218 FnTypeId fn_type_id = {0};
4219 fn_type_id.is_extern = true;
4220 fn_type_id.is_cold = true;
4221 fn_type_id.param_count = 2;
4222 fn_type_id.param_info = allocate<FnTypeParamInfo>(2);
4223 fn_type_id.next_param_index = 0;
4224 fn_type_id.param_info[0].type = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
4225 fn_type_id.param_info[1].type = g->builtin_types.entry_usize;
4226 fn_type_id.return_type = g->builtin_types.entry_unreachable;
4227
4228 TypeTableEntry *fn_type = get_fn_type(g, &fn_type_id);
4229 assert(!type_is_invalid(fn_type));
4230
4231 FnTableEntry *fn_entry = create_fn_raw(FnInlineAuto, GlobalLinkageIdStrong);
4232 buf_init_from_str(&fn_entry->symbol_name, "__zig_panic");
4233
4234 TldFn *tld_fn = allocate<TldFn>(1);
4235 init_tld(&tld_fn->base, TldIdFn, &fn_entry->symbol_name, VisibModPrivate, nullptr, nullptr);
4236 tld_fn->fn_entry = fn_entry;
4237
4238 g->external_prototypes.put_unique(tld_fn->base.name, &tld_fn->base);
4239
4240 fn_entry->type_entry = fn_type;
4241
4242 g->extern_panic_fn = fn_entry;
4243 return g->extern_panic_fn;
4244}
4245
src/analyze.hpp+2-1
......@@ -72,7 +72,7 @@ VariableTableEntry *add_variable(CodeGen *g, AstNode *source_node, Scope *parent
7272 bool is_const, ConstExprValue *init_value, Tld *src_tld);
7373TypeTableEntry *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node);
7474FnTableEntry *create_fn(AstNode *proto_node);
75FnTableEntry *create_fn_raw(FnInline inline_value, bool internal_linkage);
75FnTableEntry *create_fn_raw(FnInline inline_value, GlobalLinkageId linkage);
7676void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_count_alloc);
7777AstNode *get_param_decl_node(FnTableEntry *fn_entry, size_t index);
7878FnTableEntry *scope_get_fn_if_root(Scope *scope);
......@@ -148,5 +148,6 @@ void init_const_undefined(CodeGen *g, ConstExprValue *const_val);
148148
149149TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, size_t size_in_bits);
150150ConstParent *get_const_val_parent(ConstExprValue *value);
151FnTableEntry *get_extern_panic_fn(CodeGen *g);
151152
152153#endif
src/codegen.cpp+127-21
......@@ -67,7 +67,8 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {
6767 g->llvm_fn_table.init(16);
6868 g->memoized_fn_eval_table.init(16);
6969 g->compile_vars.init(16);
70 g->external_symbol_names.init(8);
70 g->exported_symbol_names.init(8);
71 g->external_prototypes.init(8);
7172 g->is_release_build = false;
7273 g->is_test_build = false;
7374 g->want_h_file = true;
......@@ -140,6 +141,10 @@ void codegen_set_is_release(CodeGen *g, bool is_release_build) {
140141 g->is_release_build = is_release_build;
141142}
142143
144void codegen_set_omit_zigrt(CodeGen *g, bool omit_zigrt) {
145 g->omit_zigrt = omit_zigrt;
146}
147
143148void codegen_set_is_test(CodeGen *g, bool is_test_build) {
144149 g->is_test_build = is_test_build;
145150}
......@@ -256,10 +261,22 @@ static void addLLVMAttr(LLVMValueRef val, LLVMAttributeIndex attr_index, const c
256261 LLVMAddAttributeAtIndex(val, attr_index, llvm_attr);
257262}
258263
264static void addLLVMAttrStr(LLVMValueRef val, LLVMAttributeIndex attr_index,
265 const char *attr_name, const char *attr_val)
266{
267 LLVMAttributeRef llvm_attr = LLVMCreateStringAttribute(LLVMGetGlobalContext(),
268 attr_name, strlen(attr_name), attr_val, strlen(attr_val));
269 LLVMAddAttributeAtIndex(val, attr_index, llvm_attr);
270}
271
259272static void addLLVMFnAttr(LLVMValueRef fn_val, const char *attr_name) {
260273 return addLLVMAttr(fn_val, -1, attr_name);
261274}
262275
276static void addLLVMFnAttrStr(LLVMValueRef fn_val, const char *attr_name, const char *attr_val) {
277 return addLLVMAttrStr(fn_val, -1, attr_name, attr_val);
278}
279
263280static void addLLVMArgAttr(LLVMValueRef arg_val, unsigned param_index, const char *attr_name) {
264281 return addLLVMAttr(arg_val, param_index + 1, attr_name);
265282}
......@@ -271,15 +288,19 @@ static void addLLVMCallsiteAttr(LLVMValueRef call_instr, unsigned param_index, c
271288 LLVMAddCallSiteAttribute(call_instr, param_index + 1, llvm_attr);
272289}
273290
291static bool is_symbol_available(CodeGen *g, Buf *name) {
292 return g->exported_symbol_names.maybe_get(name) == nullptr && g->external_prototypes.maybe_get(name) == nullptr;
293}
294
274295static Buf *get_mangled_name(CodeGen *g, Buf *original_name, bool external_linkage) {
275 if (external_linkage || g->external_symbol_names.maybe_get(original_name) == nullptr) {
296 if (external_linkage || is_symbol_available(g, original_name)) {
276297 return original_name;
277298 }
278299
279300 int n = 0;
280301 for (;; n += 1) {
281302 Buf *new_name = buf_sprintf("%s.%d", buf_ptr(original_name), n);
282 if (g->external_symbol_names.maybe_get(new_name) == nullptr) {
303 if (is_symbol_available(g, new_name)) {
283304 return new_name;
284305 }
285306 }
......@@ -289,11 +310,12 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
289310 if (fn_table_entry->llvm_value)
290311 return fn_table_entry->llvm_value;
291312
292 Buf *symbol_name = get_mangled_name(g, &fn_table_entry->symbol_name, !fn_table_entry->internal_linkage);
313 bool external_linkage = (fn_table_entry->linkage != GlobalLinkageIdInternal);
314 Buf *symbol_name = get_mangled_name(g, &fn_table_entry->symbol_name, external_linkage);
293315
294316 TypeTableEntry *fn_type = fn_table_entry->type_entry;
295317 LLVMTypeRef fn_llvm_type = fn_type->data.fn.raw_type_ref;
296 if (!fn_table_entry->internal_linkage && fn_table_entry->body_node == nullptr) {
318 if (external_linkage && fn_table_entry->body_node == nullptr) {
297319 LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, buf_ptr(symbol_name));
298320 if (existing_llvm_fn) {
299321 fn_table_entry->llvm_value = LLVMConstBitCast(existing_llvm_fn, LLVMPointerType(fn_llvm_type, 0));
......@@ -318,12 +340,35 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
318340 addLLVMFnAttr(fn_table_entry->llvm_value, "naked");
319341 }
320342
321 LLVMSetLinkage(fn_table_entry->llvm_value, fn_table_entry->internal_linkage ?
322 LLVMInternalLinkage : LLVMExternalLinkage);
343 switch (fn_table_entry->linkage) {
344 case GlobalLinkageIdInternal:
345 LLVMSetLinkage(fn_table_entry->llvm_value, LLVMInternalLinkage);
346 break;
347 case GlobalLinkageIdStrong:
348 LLVMSetLinkage(fn_table_entry->llvm_value, LLVMExternalLinkage);
349 break;
350 case GlobalLinkageIdWeak:
351 LLVMSetLinkage(fn_table_entry->llvm_value, LLVMWeakODRLinkage);
352 break;
353 case GlobalLinkageIdLinkOnce:
354 LLVMSetLinkage(fn_table_entry->llvm_value, LLVMLinkOnceODRLinkage);
355 break;
356 }
323357
324358 if (fn_type->data.fn.fn_type_id.return_type->id == TypeTableEntryIdUnreachable) {
325359 addLLVMFnAttr(fn_table_entry->llvm_value, "noreturn");
326360 }
361
362 if (fn_table_entry->body_node != nullptr) {
363 bool want_fn_safety = !g->is_release_build && !fn_table_entry->def_scope->safety_off;
364 if (want_fn_safety) {
365 if (g->link_libc) {
366 addLLVMFnAttr(fn_table_entry->llvm_value, "sspstrong");
367 addLLVMFnAttrStr(fn_table_entry->llvm_value, "stack-protector-buffer-size", "4");
368 }
369 }
370 }
371
327372 LLVMSetFunctionCallConv(fn_table_entry->llvm_value, fn_type->data.fn.calling_convention);
328373 if (fn_type->data.fn.fn_type_id.is_cold) {
329374 ZigLLVMAddFunctionAttrCold(fn_table_entry->llvm_value);
......@@ -363,10 +408,11 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
363408 bool is_definition = fn_table_entry->body_node != nullptr;
364409 unsigned flags = 0;
365410 bool is_optimized = g->is_release_build;
411 bool is_internal_linkage = (fn_table_entry->linkage == GlobalLinkageIdInternal);
366412 ZigLLVMDISubprogram *subprogram = ZigLLVMCreateFunction(g->dbuilder,
367413 get_di_scope(g, scope->parent), buf_ptr(&fn_table_entry->symbol_name), "",
368414 import->di_file, line_number,
369 fn_table_entry->type_entry->di_type, fn_table_entry->internal_linkage,
415 fn_table_entry->type_entry->di_type, is_internal_linkage,
370416 is_definition, scope_line, flags, is_optimized, nullptr);
371417
372418 scope->di_scope = ZigLLVMSubprogramToScope(subprogram);
......@@ -544,13 +590,28 @@ static LLVMValueRef get_panic_msg_ptr_val(CodeGen *g, PanicMsgId msg_id) {
544590 return val->llvm_global;
545591}
546592
547static void gen_debug_safety_crash(CodeGen *g, PanicMsgId msg_id) {
548 LLVMValueRef fn_val = fn_llvm_value(g, g->panic_fn);
549 LLVMValueRef msg_arg = get_panic_msg_ptr_val(g, msg_id);
550 ZigLLVMBuildCall(g->builder, fn_val, &msg_arg, 1, g->panic_fn->type_entry->data.fn.calling_convention, "");
593static void gen_panic(CodeGen *g, LLVMValueRef msg_arg) {
594 FnTableEntry *panic_fn = get_extern_panic_fn(g);
595 LLVMValueRef fn_val = fn_llvm_value(g, panic_fn);
596
597 TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true);
598 size_t ptr_index = str_type->data.structure.fields[slice_ptr_index].gen_index;
599 size_t len_index = str_type->data.structure.fields[slice_len_index].gen_index;
600 LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, msg_arg, ptr_index, "");
601 LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, msg_arg, len_index, "");
602
603 LLVMValueRef args[] = {
604 LLVMBuildLoad(g->builder, ptr_ptr, ""),
605 LLVMBuildLoad(g->builder, len_ptr, ""),
606 };
607 ZigLLVMBuildCall(g->builder, fn_val, args, 2, panic_fn->type_entry->data.fn.calling_convention, "");
551608 LLVMBuildUnreachable(g->builder);
552609}
553610
611static void gen_debug_safety_crash(CodeGen *g, PanicMsgId msg_id) {
612 gen_panic(g, get_panic_msg_ptr_val(g, msg_id));
613}
614
554615static void add_bounds_check(CodeGen *g, LLVMValueRef target_val,
555616 LLVMIntPredicate lower_pred, LLVMValueRef lower_value,
556617 LLVMIntPredicate upper_pred, LLVMValueRef upper_value)
......@@ -2564,6 +2625,11 @@ static LLVMValueRef ir_render_container_init_list(CodeGen *g, IrExecutable *exec
25642625 return tmp_array_ptr;
25652626}
25662627
2628static LLVMValueRef ir_render_panic(CodeGen *g, IrExecutable *executable, IrInstructionPanic *instruction) {
2629 gen_panic(g, ir_llvm_value(g, instruction->msg));
2630 return nullptr;
2631}
2632
25672633static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
25682634 AstNode *source_node = instruction->source_node;
25692635 Scope *scope = instruction->scope;
......@@ -2584,7 +2650,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
25842650 case IrInstructionIdToPtrType:
25852651 case IrInstructionIdPtrTypeChild:
25862652 case IrInstructionIdFieldPtr:
2587 case IrInstructionIdSetFnVisible:
25882653 case IrInstructionIdSetDebugSafety:
25892654 case IrInstructionIdArrayType:
25902655 case IrInstructionIdSliceType:
......@@ -2615,7 +2680,9 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
26152680 case IrInstructionIdCanImplicitCast:
26162681 case IrInstructionIdSetGlobalAlign:
26172682 case IrInstructionIdSetGlobalSection:
2683 case IrInstructionIdSetGlobalLinkage:
26182684 case IrInstructionIdDeclRef:
2685 case IrInstructionIdSwitchVar:
26192686 zig_unreachable();
26202687 case IrInstructionIdReturn:
26212688 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
......@@ -2721,8 +2788,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
27212788 return ir_render_int_to_enum(g, executable, (IrInstructionIntToEnum *)instruction);
27222789 case IrInstructionIdContainerInitList:
27232790 return ir_render_container_init_list(g, executable, (IrInstructionContainerInitList *)instruction);
2724 case IrInstructionIdSwitchVar:
2725 zig_panic("TODO render switch var instruction to LLVM");
2791 case IrInstructionIdPanic:
2792 return ir_render_panic(g, executable, (IrInstructionPanic *)instruction);
27262793 }
27272794 zig_unreachable();
27282795}
......@@ -3659,6 +3726,18 @@ static const CIntTypeInfo c_int_type_infos[] = {
36593726
36603727static const bool is_signed_list[] = { false, true, };
36613728
3729struct GlobalLinkageValue {
3730 GlobalLinkageId id;
3731 const char *name;
3732};
3733
3734static const GlobalLinkageValue global_linkage_values[] = {
3735 {GlobalLinkageIdInternal, "Internal"},
3736 {GlobalLinkageIdStrong, "Strong"},
3737 {GlobalLinkageIdWeak, "Weak"},
3738 {GlobalLinkageIdLinkOnce, "LinkOnce"},
3739};
3740
36623741static void define_builtin_types(CodeGen *g) {
36633742 {
36643743 // if this type is anywhere in the AST, we should never hit codegen.
......@@ -3995,6 +4074,30 @@ static void define_builtin_types(CodeGen *g) {
39954074 g->primitive_type_table.put(&entry->name, entry);
39964075 }
39974076
4077 {
4078 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnum);
4079 entry->zero_bits = true; // only allowed at compile time
4080 buf_init_from_str(&entry->name, "GlobalLinkage");
4081 uint32_t field_count = array_length(global_linkage_values);
4082 entry->data.enumeration.src_field_count = field_count;
4083 entry->data.enumeration.fields = allocate<TypeEnumField>(field_count);
4084 for (uint32_t i = 0; i < field_count; i += 1) {
4085 TypeEnumField *type_enum_field = &entry->data.enumeration.fields[i];
4086 const GlobalLinkageValue *value = &global_linkage_values[i];
4087 type_enum_field->name = buf_create_from_str(value->name);
4088 type_enum_field->value = i;
4089 type_enum_field->type_entry = g->builtin_types.entry_void;
4090 }
4091 entry->data.enumeration.complete = true;
4092 entry->data.enumeration.zero_bits_known = true;
4093
4094 TypeTableEntry *tag_type_entry = get_smallest_unsigned_int_type(g, field_count);
4095 entry->data.enumeration.tag_type = tag_type_entry;
4096
4097 g->builtin_types.entry_global_linkage_enum = entry;
4098 g->primitive_type_table.put(&entry->name, entry);
4099 }
4100
39984101 {
39994102 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnum);
40004103 entry->zero_bits = true; // only allowed at compile time
......@@ -4145,11 +4248,12 @@ static void define_builtin_fns(CodeGen *g) {
41454248 create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1);
41464249 create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);
41474250 create_builtin_fn(g, BuiltinFnIdIntType, "intType", 2);
4148 create_builtin_fn(g, BuiltinFnIdSetFnVisible, "setFnVisible", 2);
41494251 create_builtin_fn(g, BuiltinFnIdSetDebugSafety, "setDebugSafety", 2);
41504252 create_builtin_fn(g, BuiltinFnIdAlloca, "alloca", 2);
41514253 create_builtin_fn(g, BuiltinFnIdSetGlobalAlign, "setGlobalAlign", 2);
41524254 create_builtin_fn(g, BuiltinFnIdSetGlobalSection, "setGlobalSection", 2);
4255 create_builtin_fn(g, BuiltinFnIdSetGlobalLinkage, "setGlobalLinkage", 2);
4256 create_builtin_fn(g, BuiltinFnIdPanic, "panic", 1);
41534257}
41544258
41554259static void add_compile_var(CodeGen *g, const char *name, ConstExprValue *value) {
......@@ -4180,6 +4284,7 @@ static void define_builtin_compile_vars(CodeGen *g) {
41804284
41814285 add_compile_var(g, "link_libs", const_val);
41824286 }
4287 add_compile_var(g, "panic_implementation_provided", create_const_bool(g, false));
41834288}
41844289
41854290static void init(CodeGen *g, Buf *source_path) {
......@@ -4309,9 +4414,10 @@ static PackageTableEntry *create_bootstrap_pkg(CodeGen *g) {
43094414 return package;
43104415}
43114416
4312static PackageTableEntry *create_panic_pkg(CodeGen *g) {
4417static PackageTableEntry *create_zigrt_pkg(CodeGen *g) {
43134418 PackageTableEntry *package = new_package(buf_ptr(g->zig_std_special_dir), "");
43144419 package->package_table.put(buf_create_from_str("std"), g->std_package);
4420 package->package_table.put(buf_create_from_str("@root"), g->root_package);
43154421 return package;
43164422}
43174423
......@@ -4337,9 +4443,9 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou
43374443 if (!g->is_test_build && g->have_pub_main && (g->out_type == OutTypeObj || g->out_type == OutTypeExe)) {
43384444 g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g), "bootstrap.zig");
43394445 }
4340 if (!g->have_pub_panic) {
4341 g->panic_package = create_panic_pkg(g);
4342 add_special_code(g, g->panic_package, "panic.zig");
4446 if (!g->omit_zigrt) {
4447 g->zigrt_package = create_zigrt_pkg(g);
4448 add_special_code(g, g->zigrt_package, "zigrt.zig");
43434449 }
43444450
43454451 if (g->verbose) {
......@@ -4509,7 +4615,7 @@ void codegen_generate_h_file(CodeGen *g) {
45094615 for (size_t fn_def_i = 0; fn_def_i < g->fn_defs.length; fn_def_i += 1) {
45104616 FnTableEntry *fn_table_entry = g->fn_defs.at(fn_def_i);
45114617
4512 if (fn_table_entry->internal_linkage)
4618 if (fn_table_entry->linkage == GlobalLinkageIdInternal)
45134619 continue;
45144620
45154621 FnTypeId *fn_type_id = &fn_table_entry->type_entry->data.fn.fn_type_id;
src/codegen.hpp+1
......@@ -43,6 +43,7 @@ void codegen_set_rdynamic(CodeGen *g, bool rdynamic);
4343void codegen_set_mmacosx_version_min(CodeGen *g, Buf *mmacosx_version_min);
4444void codegen_set_mios_version_min(CodeGen *g, Buf *mios_version_min);
4545void codegen_set_linker_script(CodeGen *g, const char *linker_script);
46void codegen_set_omit_zigrt(CodeGen *g, bool omit_zigrt);
4647
4748void codegen_add_root_code(CodeGen *g, Buf *source_dir, Buf *source_basename, Buf *source_code);
4849
src/ir.cpp+148-82
......@@ -276,10 +276,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrTypeChild *)
276276 return IrInstructionIdPtrTypeChild;
277277}
278278
279static constexpr IrInstructionId ir_instruction_id(IrInstructionSetFnVisible *) {
280 return IrInstructionIdSetFnVisible;
281}
282
283279static constexpr IrInstructionId ir_instruction_id(IrInstructionSetDebugSafety *) {
284280 return IrInstructionIdSetDebugSafety;
285281}
......@@ -528,10 +524,18 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSetGlobalSection
528524 return IrInstructionIdSetGlobalSection;
529525}
530526
527static constexpr IrInstructionId ir_instruction_id(IrInstructionSetGlobalLinkage *) {
528 return IrInstructionIdSetGlobalLinkage;
529}
530
531531static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclRef *) {
532532 return IrInstructionIdDeclRef;
533533}
534534
535static constexpr IrInstructionId ir_instruction_id(IrInstructionPanic *) {
536 return IrInstructionIdPanic;
537}
538
535539template<typename T>
536540static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
537541 T *special_instruction = allocate<T>(1);
......@@ -1147,19 +1151,6 @@ static IrInstruction *ir_build_ptr_type_child(IrBuilder *irb, Scope *scope, AstN
11471151 return &instruction->base;
11481152}
11491153
1150static IrInstruction *ir_build_set_fn_visible(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *fn_value,
1151 IrInstruction *is_visible)
1152{
1153 IrInstructionSetFnVisible *instruction = ir_build_instruction<IrInstructionSetFnVisible>(irb, scope, source_node);
1154 instruction->fn_value = fn_value;
1155 instruction->is_visible = is_visible;
1156
1157 ir_ref_instruction(fn_value, irb->current_basic_block);
1158 ir_ref_instruction(is_visible, irb->current_basic_block);
1159
1160 return &instruction->base;
1161}
1162
11631154static IrInstruction *ir_build_set_debug_safety(IrBuilder *irb, Scope *scope, AstNode *source_node,
11641155 IrInstruction *scope_value, IrInstruction *debug_safety_on)
11651156{
......@@ -2092,6 +2083,19 @@ static IrInstruction *ir_build_set_global_section(IrBuilder *irb, Scope *scope,
20922083 return &instruction->base;
20932084}
20942085
2086static IrInstruction *ir_build_set_global_linkage(IrBuilder *irb, Scope *scope, AstNode *source_node,
2087 Tld *tld, IrInstruction *value)
2088{
2089 IrInstructionSetGlobalLinkage *instruction = ir_build_instruction<IrInstructionSetGlobalLinkage>(
2090 irb, scope, source_node);
2091 instruction->tld = tld;
2092 instruction->value = value;
2093
2094 ir_ref_instruction(value, irb->current_basic_block);
2095
2096 return &instruction->base;
2097}
2098
20952099static IrInstruction *ir_build_decl_ref(IrBuilder *irb, Scope *scope, AstNode *source_node,
20962100 Tld *tld, LVal lval)
20972101{
......@@ -2103,6 +2107,17 @@ static IrInstruction *ir_build_decl_ref(IrBuilder *irb, Scope *scope, AstNode *s
21032107 return &instruction->base;
21042108}
21052109
2110static IrInstruction *ir_build_panic(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *msg) {
2111 IrInstructionPanic *instruction = ir_build_instruction<IrInstructionPanic>(irb, scope, source_node);
2112 instruction->base.value.special = ConstValSpecialStatic;
2113 instruction->base.value.type = irb->codegen->builtin_types.entry_unreachable;
2114 instruction->msg = msg;
2115
2116 ir_ref_instruction(msg, irb->current_basic_block);
2117
2118 return &instruction->base;
2119}
2120
21062121static IrInstruction *ir_instruction_br_get_dep(IrInstructionBr *instruction, size_t index) {
21072122 return nullptr;
21082123}
......@@ -2287,14 +2302,6 @@ static IrInstruction *ir_instruction_ptrtypechild_get_dep(IrInstructionPtrTypeCh
22872302 }
22882303}
22892304
2290static IrInstruction *ir_instruction_setfnvisible_get_dep(IrInstructionSetFnVisible *instruction, size_t index) {
2291 switch (index) {
2292 case 0: return instruction->fn_value;
2293 case 1: return instruction->is_visible;
2294 default: return nullptr;
2295 }
2296}
2297
22982305static IrInstruction *ir_instruction_setdebugsafety_get_dep(IrInstructionSetDebugSafety *instruction, size_t index) {
22992306 switch (index) {
23002307 case 0: return instruction->scope_value;
......@@ -2742,10 +2749,24 @@ static IrInstruction *ir_instruction_setglobalsection_get_dep(IrInstructionSetGl
27422749 }
27432750}
27442751
2752static IrInstruction *ir_instruction_setgloballinkage_get_dep(IrInstructionSetGlobalLinkage *instruction, size_t index) {
2753 switch (index) {
2754 case 0: return instruction->value;
2755 default: return nullptr;
2756 }
2757}
2758
27452759static IrInstruction *ir_instruction_declref_get_dep(IrInstructionDeclRef *instruction, size_t index) {
27462760 return nullptr;
27472761}
27482762
2763static IrInstruction *ir_instruction_panic_get_dep(IrInstructionPanic *instruction, size_t index) {
2764 switch (index) {
2765 case 0: return instruction->msg;
2766 default: return nullptr;
2767 }
2768}
2769
27492770static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t index) {
27502771 switch (instruction->id) {
27512772 case IrInstructionIdInvalid:
......@@ -2804,8 +2825,6 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t
28042825 return ir_instruction_toptrtype_get_dep((IrInstructionToPtrType *) instruction, index);
28052826 case IrInstructionIdPtrTypeChild:
28062827 return ir_instruction_ptrtypechild_get_dep((IrInstructionPtrTypeChild *) instruction, index);
2807 case IrInstructionIdSetFnVisible:
2808 return ir_instruction_setfnvisible_get_dep((IrInstructionSetFnVisible *) instruction, index);
28092828 case IrInstructionIdSetDebugSafety:
28102829 return ir_instruction_setdebugsafety_get_dep((IrInstructionSetDebugSafety *) instruction, index);
28112830 case IrInstructionIdArrayType:
......@@ -2928,8 +2947,12 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t
29282947 return ir_instruction_setglobalalign_get_dep((IrInstructionSetGlobalAlign *) instruction, index);
29292948 case IrInstructionIdSetGlobalSection:
29302949 return ir_instruction_setglobalsection_get_dep((IrInstructionSetGlobalSection *) instruction, index);
2950 case IrInstructionIdSetGlobalLinkage:
2951 return ir_instruction_setgloballinkage_get_dep((IrInstructionSetGlobalLinkage *) instruction, index);
29312952 case IrInstructionIdDeclRef:
29322953 return ir_instruction_declref_get_dep((IrInstructionDeclRef *) instruction, index);
2954 case IrInstructionIdPanic:
2955 return ir_instruction_panic_get_dep((IrInstructionPanic *) instruction, index);
29332956 }
29342957 zig_unreachable();
29352958}
......@@ -3759,20 +3782,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
37593782 return arg;
37603783 return ir_build_typeof(irb, scope, node, arg);
37613784 }
3762 case BuiltinFnIdSetFnVisible:
3763 {
3764 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
3765 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
3766 if (arg0_value == irb->codegen->invalid_instruction)
3767 return arg0_value;
3768
3769 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
3770 IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
3771 if (arg1_value == irb->codegen->invalid_instruction)
3772 return arg1_value;
3773
3774 return ir_build_set_fn_visible(irb, scope, node, arg0_value, arg1_value);
3775 }
37763785 case BuiltinFnIdSetDebugSafety:
37773786 {
37783787 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
......@@ -4145,6 +4154,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
41454154 }
41464155 case BuiltinFnIdSetGlobalAlign:
41474156 case BuiltinFnIdSetGlobalSection:
4157 case BuiltinFnIdSetGlobalLinkage:
41484158 {
41494159 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
41504160 if (arg0_node->type != NodeTypeSymbol) {
......@@ -4170,10 +4180,23 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
41704180
41714181 if (builtin_fn->id == BuiltinFnIdSetGlobalAlign) {
41724182 return ir_build_set_global_align(irb, scope, node, tld, arg1_value);
4173 } else {
4183 } else if (builtin_fn->id == BuiltinFnIdSetGlobalSection) {
41744184 return ir_build_set_global_section(irb, scope, node, tld, arg1_value);
4185 } else if (builtin_fn->id == BuiltinFnIdSetGlobalLinkage) {
4186 return ir_build_set_global_linkage(irb, scope, node, tld, arg1_value);
4187 } else {
4188 zig_unreachable();
41754189 }
41764190 }
4191 case BuiltinFnIdPanic:
4192 {
4193 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4194 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
4195 if (arg0_value == irb->codegen->invalid_instruction)
4196 return arg0_value;
4197
4198 return ir_build_panic(irb, scope, node, arg0_value);
4199 }
41774200 }
41784201 zig_unreachable();
41794202}
......@@ -4624,6 +4647,10 @@ static IrInstruction *ir_gen_this_literal(IrBuilder *irb, Scope *scope, AstNode
46244647 if (fn_entry)
46254648 return ir_build_const_fn(irb, scope, node, fn_entry);
46264649
4650 while (scope->id != ScopeIdBlock && scope->id != ScopeIdDecls) {
4651 scope = scope->parent;
4652 }
4653
46274654 if (scope->id == ScopeIdDecls) {
46284655 ScopeDecls *decls_scope = (ScopeDecls *)scope;
46294656 TypeTableEntry *container_type = decls_scope->container_type;
......@@ -7096,6 +7123,23 @@ static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, Atomic
70967123 return true;
70977124}
70987125
7126static bool ir_resolve_global_linkage(IrAnalyze *ira, IrInstruction *value, GlobalLinkageId *out) {
7127 if (type_is_invalid(value->value.type))
7128 return false;
7129
7130 IrInstruction *casted_value = ir_implicit_cast(ira, value, ira->codegen->builtin_types.entry_global_linkage_enum);
7131 if (type_is_invalid(casted_value->value.type))
7132 return false;
7133
7134 ConstExprValue *const_val = ir_resolve_const(ira, casted_value, UndefBad);
7135 if (!const_val)
7136 return false;
7137
7138 *out = (GlobalLinkageId)const_val->data.x_enum.tag;
7139 return true;
7140}
7141
7142
70997143static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) {
71007144 if (type_is_invalid(value->value.type))
71017145 return nullptr;
......@@ -9557,42 +9601,6 @@ static TypeTableEntry *ir_analyze_instruction_ptr_type_child(IrAnalyze *ira,
95579601 return ira->codegen->builtin_types.entry_type;
95589602}
95599603
9560static TypeTableEntry *ir_analyze_instruction_set_fn_visible(IrAnalyze *ira,
9561 IrInstructionSetFnVisible *set_fn_visible_instruction)
9562{
9563 IrInstruction *fn_value = set_fn_visible_instruction->fn_value->other;
9564 IrInstruction *is_visible_value = set_fn_visible_instruction->is_visible->other;
9565
9566 FnTableEntry *fn_entry = ir_resolve_fn(ira, fn_value);
9567 if (!fn_entry)
9568 return ira->codegen->builtin_types.entry_invalid;
9569
9570 bool want_export;
9571 if (!ir_resolve_bool(ira, is_visible_value, &want_export))
9572 return ira->codegen->builtin_types.entry_invalid;
9573
9574 AstNode *source_node = set_fn_visible_instruction->base.source_node;
9575 if (fn_entry->fn_export_set_node) {
9576 ErrorMsg *msg = ir_add_error_node(ira, source_node,
9577 buf_sprintf("function visibility set twice"));
9578 add_error_note(ira->codegen, msg, fn_entry->fn_export_set_node, buf_sprintf("first set here"));
9579 return ira->codegen->builtin_types.entry_invalid;
9580 }
9581 fn_entry->fn_export_set_node = source_node;
9582
9583 AstNodeFnProto *fn_proto = &fn_entry->proto_node->data.fn_proto;
9584 if (fn_proto->visib_mod != VisibModExport) {
9585 ErrorMsg *msg = ir_add_error_node(ira, source_node,
9586 buf_sprintf("function must be marked export to set function visibility"));
9587 add_error_note(ira->codegen, msg, fn_entry->proto_node, buf_sprintf("function declared here"));
9588 return ira->codegen->builtin_types.entry_invalid;
9589 }
9590 fn_entry->internal_linkage = !want_export;
9591
9592 ir_build_const_from(ira, &set_fn_visible_instruction->base);
9593 return ira->codegen->builtin_types.entry_void;
9594}
9595
95969604static TypeTableEntry *ir_analyze_instruction_set_global_align(IrAnalyze *ira,
95979605 IrInstructionSetGlobalAlign *instruction)
95989606{
......@@ -9677,6 +9685,45 @@ static TypeTableEntry *ir_analyze_instruction_set_global_section(IrAnalyze *ira,
96779685 return ira->codegen->builtin_types.entry_void;
96789686}
96799687
9688static TypeTableEntry *ir_analyze_instruction_set_global_linkage(IrAnalyze *ira,
9689 IrInstructionSetGlobalLinkage *instruction)
9690{
9691 Tld *tld = instruction->tld;
9692 IrInstruction *linkage_value = instruction->value->other;
9693
9694 GlobalLinkageId linkage_scalar;
9695 if (!ir_resolve_global_linkage(ira, linkage_value, &linkage_scalar))
9696 return ira->codegen->builtin_types.entry_invalid;
9697
9698 AstNode **set_global_linkage_node;
9699 GlobalLinkageId *dest_linkage_ptr;
9700 if (tld->id == TldIdVar) {
9701 TldVar *tld_var = (TldVar *)tld;
9702 set_global_linkage_node = &tld_var->set_global_linkage_node;
9703 dest_linkage_ptr = &tld_var->linkage;
9704 } else if (tld->id == TldIdFn) {
9705 TldFn *tld_fn = (TldFn *)tld;
9706 FnTableEntry *fn_entry = tld_fn->fn_entry;
9707 set_global_linkage_node = &fn_entry->set_global_linkage_node;
9708 dest_linkage_ptr = &fn_entry->linkage;
9709 } else {
9710 // error is caught in pass1 IR gen
9711 zig_unreachable();
9712 }
9713
9714 AstNode *source_node = instruction->base.source_node;
9715 if (*set_global_linkage_node) {
9716 ErrorMsg *msg = ir_add_error_node(ira, source_node, buf_sprintf("linkage set twice"));
9717 add_error_note(ira->codegen, msg, *set_global_linkage_node, buf_sprintf("first set here"));
9718 return ira->codegen->builtin_types.entry_invalid;
9719 }
9720 *set_global_linkage_node = source_node;
9721 *dest_linkage_ptr = linkage_scalar;
9722
9723 ir_build_const_from(ira, &instruction->base);
9724 return ira->codegen->builtin_types.entry_void;
9725}
9726
96809727static TypeTableEntry *ir_analyze_instruction_set_debug_safety(IrAnalyze *ira,
96819728 IrInstructionSetDebugSafety *set_debug_safety_instruction)
96829729{
......@@ -12147,6 +12194,22 @@ static TypeTableEntry *ir_analyze_instruction_can_implicit_cast(IrAnalyze *ira,
1214712194 return ira->codegen->builtin_types.entry_bool;
1214812195}
1214912196
12197static TypeTableEntry *ir_analyze_instruction_panic(IrAnalyze *ira, IrInstructionPanic *instruction) {
12198 IrInstruction *msg = instruction->msg->other;
12199 if (type_is_invalid(msg->value.type))
12200 return ira->codegen->builtin_types.entry_invalid;
12201
12202 TypeTableEntry *str_type = get_slice_type(ira->codegen, ira->codegen->builtin_types.entry_u8, true);
12203 IrInstruction *casted_msg = ir_implicit_cast(ira, msg, str_type);
12204 if (type_is_invalid(casted_msg->value.type))
12205 return ira->codegen->builtin_types.entry_invalid;
12206
12207 IrInstruction *new_instruction = ir_build_panic(&ira->new_irb, instruction->base.scope,
12208 instruction->base.source_node, casted_msg);
12209 ir_link_new_instruction(new_instruction, &instruction->base);
12210 return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable);
12211}
12212
1215012213static TypeTableEntry *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
1215112214 IrInstructionDeclRef *instruction)
1215212215{
......@@ -12266,12 +12329,12 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
1226612329 return ir_analyze_instruction_to_ptr_type(ira, (IrInstructionToPtrType *)instruction);
1226712330 case IrInstructionIdPtrTypeChild:
1226812331 return ir_analyze_instruction_ptr_type_child(ira, (IrInstructionPtrTypeChild *)instruction);
12269 case IrInstructionIdSetFnVisible:
12270 return ir_analyze_instruction_set_fn_visible(ira, (IrInstructionSetFnVisible *)instruction);
1227112332 case IrInstructionIdSetGlobalAlign:
1227212333 return ir_analyze_instruction_set_global_align(ira, (IrInstructionSetGlobalAlign *)instruction);
1227312334 case IrInstructionIdSetGlobalSection:
1227412335 return ir_analyze_instruction_set_global_section(ira, (IrInstructionSetGlobalSection *)instruction);
12336 case IrInstructionIdSetGlobalLinkage:
12337 return ir_analyze_instruction_set_global_linkage(ira, (IrInstructionSetGlobalLinkage *)instruction);
1227512338 case IrInstructionIdSetDebugSafety:
1227612339 return ir_analyze_instruction_set_debug_safety(ira, (IrInstructionSetDebugSafety *)instruction);
1227712340 case IrInstructionIdSliceType:
......@@ -12384,6 +12447,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
1238412447 return ir_analyze_instruction_can_implicit_cast(ira, (IrInstructionCanImplicitCast *)instruction);
1238512448 case IrInstructionIdDeclRef:
1238612449 return ir_analyze_instruction_decl_ref(ira, (IrInstructionDeclRef *)instruction);
12450 case IrInstructionIdPanic:
12451 return ir_analyze_instruction_panic(ira, (IrInstructionPanic *)instruction);
1238712452 case IrInstructionIdMaybeWrap:
1238812453 case IrInstructionIdErrWrapCode:
1238912454 case IrInstructionIdErrWrapPayload:
......@@ -12482,7 +12547,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
1248212547 case IrInstructionIdCall:
1248312548 case IrInstructionIdReturn:
1248412549 case IrInstructionIdUnreachable:
12485 case IrInstructionIdSetFnVisible:
1248612550 case IrInstructionIdSetDebugSafety:
1248712551 case IrInstructionIdImport:
1248812552 case IrInstructionIdCompileErr:
......@@ -12500,6 +12564,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
1250012564 case IrInstructionIdCheckSwitchProngs:
1250112565 case IrInstructionIdSetGlobalAlign:
1250212566 case IrInstructionIdSetGlobalSection:
12567 case IrInstructionIdSetGlobalLinkage:
12568 case IrInstructionIdPanic:
1250312569 return true;
1250412570 case IrInstructionIdPhi:
1250512571 case IrInstructionIdUnOp:
......@@ -12580,7 +12646,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
1258012646}
1258112647
1258212648FnTableEntry *ir_create_inline_fn(CodeGen *codegen, Buf *fn_name, VariableTableEntry *var, Scope *parent_scope) {
12583 FnTableEntry *fn_entry = create_fn_raw(FnInlineAuto, true);
12649 FnTableEntry *fn_entry = create_fn_raw(FnInlineAuto, GlobalLinkageIdInternal);
1258412650 buf_init_from_buf(&fn_entry->symbol_name, fn_name);
1258512651
1258612652 fn_entry->fndef_scope = create_fndef_scope(nullptr, parent_scope, fn_entry);
src/ir_print.cpp+20-11
......@@ -339,14 +339,6 @@ static void ir_print_enum_field_ptr(IrPrint *irp, IrInstructionEnumFieldPtr *ins
339339 fprintf(irp->f, ")");
340340}
341341
342static void ir_print_set_fn_visible(IrPrint *irp, IrInstructionSetFnVisible *instruction) {
343 fprintf(irp->f, "@setFnVisible(");
344 ir_print_other_instruction(irp, instruction->fn_value);
345 fprintf(irp->f, ", ");
346 ir_print_other_instruction(irp, instruction->is_visible);
347 fprintf(irp->f, ")");
348}
349
350342static void ir_print_set_debug_safety(IrPrint *irp, IrInstructionSetDebugSafety *instruction) {
351343 fprintf(irp->f, "@setDebugSafety(");
352344 ir_print_other_instruction(irp, instruction->scope_value);
......@@ -849,6 +841,13 @@ static void ir_print_set_global_section(IrPrint *irp, IrInstructionSetGlobalSect
849841 fprintf(irp->f, ")");
850842}
851843
844static void ir_print_set_global_linkage(IrPrint *irp, IrInstructionSetGlobalLinkage *instruction) {
845 fprintf(irp->f, "@setGlobalLinkage(%s,", buf_ptr(instruction->tld->name));
846 ir_print_other_instruction(irp, instruction->value);
847 fprintf(irp->f, ")");
848}
849
850
852851static void ir_print_decl_ref(IrPrint *irp, IrInstructionDeclRef *instruction) {
853852 const char *ptr_str = instruction->lval.is_ptr ? "ptr " : "";
854853 const char *const_str = instruction->lval.is_const ? "const " : "";
......@@ -856,6 +855,13 @@ static void ir_print_decl_ref(IrPrint *irp, IrInstructionDeclRef *instruction) {
856855 fprintf(irp->f, "declref %s%s%s%s", const_str, volatile_str, ptr_str, buf_ptr(instruction->tld->name));
857856}
858857
858static void ir_print_panic(IrPrint *irp, IrInstructionPanic *instruction) {
859 fprintf(irp->f, "@panic(");
860 ir_print_other_instruction(irp, instruction->msg);
861 fprintf(irp->f, ")");
862}
863
864
859865static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
860866 ir_print_prefix(irp, instruction);
861867 switch (instruction->id) {
......@@ -933,9 +939,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
933939 case IrInstructionIdEnumFieldPtr:
934940 ir_print_enum_field_ptr(irp, (IrInstructionEnumFieldPtr *)instruction);
935941 break;
936 case IrInstructionIdSetFnVisible:
937 ir_print_set_fn_visible(irp, (IrInstructionSetFnVisible *)instruction);
938 break;
939942 case IrInstructionIdSetDebugSafety:
940943 ir_print_set_debug_safety(irp, (IrInstructionSetDebugSafety *)instruction);
941944 break;
......@@ -1128,9 +1131,15 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
11281131 case IrInstructionIdSetGlobalSection:
11291132 ir_print_set_global_section(irp, (IrInstructionSetGlobalSection *)instruction);
11301133 break;
1134 case IrInstructionIdSetGlobalLinkage:
1135 ir_print_set_global_linkage(irp, (IrInstructionSetGlobalLinkage *)instruction);
1136 break;
11311137 case IrInstructionIdDeclRef:
11321138 ir_print_decl_ref(irp, (IrInstructionDeclRef *)instruction);
11331139 break;
1140 case IrInstructionIdPanic:
1141 ir_print_panic(irp, (IrInstructionPanic *)instruction);
1142 break;
11341143 }
11351144 fprintf(irp->f, "\n");
11361145}
src/link.cpp+1
......@@ -52,6 +52,7 @@ static Buf *build_o(CodeGen *parent_gen, const char *oname) {
5252 child_gen->link_libs.items[i] = parent_gen->link_libs.items[i];
5353 }
5454
55 codegen_set_omit_zigrt(child_gen, true);
5556 child_gen->want_h_file = false;
5657
5758 codegen_set_is_release(child_gen, parent_gen->is_release_build);
src/parseh.cpp+1-2
......@@ -635,8 +635,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
635635 }
636636 assert(fn_type->id == TypeTableEntryIdFn);
637637
638 bool internal_linkage = false;
639 FnTableEntry *fn_entry = create_fn_raw(FnInlineAuto, internal_linkage);
638 FnTableEntry *fn_entry = create_fn_raw(FnInlineAuto, GlobalLinkageIdStrong);
640639 buf_init_from_buf(&fn_entry->symbol_name, fn_name);
641640 fn_entry->type_entry = fn_type;
642641
std/special/bootstrap.zig+2-2
......@@ -13,7 +13,7 @@ var argc: usize = undefined;
1313var argv: &&u8 = undefined;
1414
1515export nakedcc fn _start() -> noreturn {
16 @setFnVisible(this, want_start_symbol);
16 @setGlobalLinkage(_start, if (want_start_symbol) GlobalLinkage.Strong else GlobalLinkage.Internal);
1717 if (!want_start_symbol) {
1818 unreachable;
1919 }
......@@ -47,7 +47,7 @@ fn callMainAndExit() -> noreturn {
4747}
4848
4949export fn main(c_argc: i32, c_argv: &&u8) -> i32 {
50 @setFnVisible(this, want_main_symbol);
50 @setGlobalLinkage(main, if (want_main_symbol) GlobalLinkage.Strong else GlobalLinkage.Internal);
5151 if (!want_main_symbol) {
5252 unreachable;
5353 }
std/special/builtin.zig+2-3
......@@ -30,7 +30,6 @@ export fn memcpy(noalias dest: ?&u8, noalias src: ?&const u8, n: usize) {
3030 d[index] = s[index];
3131}
3232
33// Avoid dragging in the debug safety mechanisms into this .o file.
34pub fn panic(message: []const u8) -> noreturn {
35 unreachable;
33export fn __stack_chk_fail() {
34 @panic("stack smashing detected");
3635}
std/special/compiler_rt.zig+1-11
......@@ -1,13 +1,3 @@
1// Avoid dragging in the debug safety mechanisms into this .o file,
2// unless we're trying to test this file.
3pub fn panic(message: []const u8) -> noreturn {
4 if (@compileVar("is_test")) {
5 @import("std").debug.panic(message);
6 } else {
7 unreachable;
8 }
9}
10
111const CHAR_BIT = 8;
122const du_int = u64;
133const di_int = i64;
......@@ -262,7 +252,7 @@ export nakedcc fn __aeabi_uidivmod() {
262252 unreachable;
263253 }
264254
265 @setFnVisible(this, false);
255 @setGlobalLinkage(__aeabi_uidivmod, GlobalLinkage.Internal);
266256}
267257
268258export fn __udivmodsi4(a: su_int, b: su_int, rem: &su_int) -> su_int {
std/special/panic.zig deleted-12
......@@ -1,12 +0,0 @@
1// This file is included if and only if the user's main source file does not
2// include a public panic function.
3// If this file wants to import other files *by name*, support for that would
4// have to be added in the compiler.
5
6pub coldcc fn panic(message: []const u8) -> noreturn {
7 if (@compileVar("os") == Os.freestanding) {
8 while (true) {}
9 } else {
10 @import("std").debug.panic(message);
11 }
12}
std/special/zigrt.zig created+16
......@@ -0,0 +1,16 @@
1// This file contains functions that zig depends on to coordinate between
2// multiple .o files. The symbols are defined LinkOnce so that multiple
3// instances of zig_rt.zig do not conflict with each other.
4
5export coldcc fn __zig_panic(message_ptr: &const u8, message_len: usize) -> noreturn {
6 @setGlobalLinkage(__zig_panic, GlobalLinkage.Weak);
7 @setDebugSafety(this, false);
8
9 if (@compileVar("panic_implementation_provided")) {
10 @import("@root").panic(message_ptr[0...message_len]);
11 } else if (@compileVar("os") == Os.freestanding) {
12 while (true) {}
13 } else {
14 @import("std").debug.panic(message_ptr[0...message_len]);
15 }
16}
test/cases/misc.zig+1-1
......@@ -12,7 +12,7 @@ test "emptyFunctionWithComments" {
1212}
1313
1414export fn disabledExternFn() {
15 @setFnVisible(this, false);
15 @setGlobalLinkage(disabledExternFn, GlobalLinkage.Internal);
1616}
1717
1818test "callDisabledExternFn" {
test/run_tests.cpp+12
......@@ -1828,6 +1828,18 @@ export fn entry() {
18281828//////////////////////////////////////////////////////////////////////////////
18291829
18301830static void add_debug_safety_test_cases(void) {
1831 add_debug_safety_case("calling panic", R"SOURCE(
1832pub fn panic(message: []const u8) -> noreturn {
1833 @breakpoint();
1834 while (true) {}
1835}
1836pub fn main(args: [][]u8) -> %void {
1837 if (!@compileVar("is_release")) {
1838 @panic("oh no");
1839 }
1840}
1841 )SOURCE");
1842
18311843 add_debug_safety_case("out of bounds slice access", R"SOURCE(
18321844pub fn panic(message: []const u8) -> noreturn {
18331845 @breakpoint();