| author | |
| committer | |
| log | a32b5929ccf8cbf79396d8924097a1a911985dac |
| tree | c45c7413d1fb6eab9ba102f3a0b7d48df1738164 |
| parent | 8aeea72654b2efbd068abe207b42170c4d27ee03 |
* 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 #27619 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}") |
| 233 | 233 | install(FILES "${CMAKE_SOURCE_DIR}/std/special/bootstrap.zig" DESTINATION "${ZIG_STD_DEST}/special") |
| 234 | 234 | install(FILES "${CMAKE_SOURCE_DIR}/std/special/builtin.zig" DESTINATION "${ZIG_STD_DEST}/special") |
| 235 | 235 | install(FILES "${CMAKE_SOURCE_DIR}/std/special/compiler_rt.zig" DESTINATION "${ZIG_STD_DEST}/special") |
| 236 | install(FILES "${CMAKE_SOURCE_DIR}/std/special/panic.zig" DESTINATION "${ZIG_STD_DEST}/special") | |
| 237 | 236 | install(FILES "${CMAKE_SOURCE_DIR}/std/special/test_runner.zig" DESTINATION "${ZIG_STD_DEST}/special") |
| 237 | install(FILES "${CMAKE_SOURCE_DIR}/std/special/zigrt.zig" DESTINATION "${ZIG_STD_DEST}/special") | |
| 238 | 238 | install(FILES "${CMAKE_SOURCE_DIR}/std/target.zig" DESTINATION "${ZIG_STD_DEST}") |
| 239 | 239 | |
| 240 | 240 | add_executable(run_tests ${TEST_SOURCES}) |
doc/emacs/zig-mode.el+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | (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) | |
| 3 | 3 | |
| 4 | 4 | ("\\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) |
| 5 | 5 |
doc/langref.md+7| ... | ... | @@ -626,3 +626,10 @@ Sets the alignment property of a global variable. |
| 626 | 626 | ### @setGlobalSection(global_variable_name, section_name: []u8) -> bool |
| 627 | 627 | |
| 628 | 628 | Puts the global variable in the specified section. |
| 629 | ||
| 630 | ### @panic(message: []const u8) -> noreturn | |
| 631 | ||
| 632 | Invokes the panic handler function. By default the panic handler function | |
| 633 | calls the public `panic` function exposed in the root source file, or | |
| 634 | if 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 { |
| 237 | 237 | VisibModExport, |
| 238 | 238 | }; |
| 239 | 239 | |
| 240 | enum GlobalLinkageId { | |
| 241 | GlobalLinkageIdInternal, | |
| 242 | GlobalLinkageIdStrong, | |
| 243 | GlobalLinkageIdWeak, | |
| 244 | GlobalLinkageIdLinkOnce, | |
| 245 | }; | |
| 246 | ||
| 240 | 247 | enum TldId { |
| 241 | 248 | TldIdVar, |
| 242 | 249 | TldIdFn, |
| ... | ... | @@ -273,6 +280,8 @@ struct TldVar { |
| 273 | 280 | uint64_t alignment; |
| 274 | 281 | AstNode *set_global_section_node; |
| 275 | 282 | Buf *section_name; |
| 283 | AstNode *set_global_linkage_node; | |
| 284 | GlobalLinkageId linkage; | |
| 276 | 285 | }; |
| 277 | 286 | |
| 278 | 287 | struct TldFn { |
| ... | ... | @@ -1116,8 +1125,6 @@ struct FnTableEntry { |
| 1116 | 1125 | Buf symbol_name; |
| 1117 | 1126 | TypeTableEntry *type_entry; // function type |
| 1118 | 1127 | TypeTableEntry *implicit_return_type; |
| 1119 | bool internal_linkage; | |
| 1120 | bool disable_export; | |
| 1121 | 1128 | bool is_test; |
| 1122 | 1129 | FnInline fn_inline; |
| 1123 | 1130 | FnAnalState anal_state; |
| ... | ... | @@ -1128,7 +1135,6 @@ struct FnTableEntry { |
| 1128 | 1135 | Buf **param_names; |
| 1129 | 1136 | |
| 1130 | 1137 | AstNode *fn_no_inline_set_node; |
| 1131 | AstNode *fn_export_set_node; | |
| 1132 | 1138 | AstNode *fn_static_eval_set_node; |
| 1133 | 1139 | |
| 1134 | 1140 | ZigList<IrInstruction *> alloca_list; |
| ... | ... | @@ -1138,6 +1144,8 @@ struct FnTableEntry { |
| 1138 | 1144 | uint64_t alignment; |
| 1139 | 1145 | AstNode *set_global_section_node; |
| 1140 | 1146 | Buf *section_name; |
| 1147 | AstNode *set_global_linkage_node; | |
| 1148 | GlobalLinkageId linkage; | |
| 1141 | 1149 | }; |
| 1142 | 1150 | |
| 1143 | 1151 | uint32_t fn_table_entry_hash(FnTableEntry*); |
| ... | ... | @@ -1178,7 +1186,6 @@ enum BuiltinFnId { |
| 1178 | 1186 | BuiltinFnIdDivExact, |
| 1179 | 1187 | BuiltinFnIdTruncate, |
| 1180 | 1188 | BuiltinFnIdIntType, |
| 1181 | BuiltinFnIdSetFnVisible, | |
| 1182 | 1189 | BuiltinFnIdSetDebugSafety, |
| 1183 | 1190 | BuiltinFnIdAlloca, |
| 1184 | 1191 | BuiltinFnIdTypeName, |
| ... | ... | @@ -1187,6 +1194,8 @@ enum BuiltinFnId { |
| 1187 | 1194 | BuiltinFnIdCanImplicitCast, |
| 1188 | 1195 | BuiltinFnIdSetGlobalAlign, |
| 1189 | 1196 | BuiltinFnIdSetGlobalSection, |
| 1197 | BuiltinFnIdSetGlobalLinkage, | |
| 1198 | BuiltinFnIdPanic, | |
| 1190 | 1199 | }; |
| 1191 | 1200 | |
| 1192 | 1201 | struct BuiltinFnEntry { |
| ... | ... | @@ -1300,7 +1309,8 @@ struct CodeGen { |
| 1300 | 1309 | HashMap<Scope *, IrInstruction *, fn_eval_hash, fn_eval_eql> memoized_fn_eval_table; |
| 1301 | 1310 | HashMap<ZigLLVMFnKey, LLVMValueRef, zig_llvm_fn_key_hash, zig_llvm_fn_key_eql> llvm_fn_table; |
| 1302 | 1311 | 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; | |
| 1304 | 1314 | |
| 1305 | 1315 | ZigList<ImportTableEntry *> import_queue; |
| 1306 | 1316 | size_t import_queue_index; |
| ... | ... | @@ -1346,6 +1356,7 @@ struct CodeGen { |
| 1346 | 1356 | TypeTableEntry *entry_environ_enum; |
| 1347 | 1357 | TypeTableEntry *entry_oformat_enum; |
| 1348 | 1358 | TypeTableEntry *entry_atomic_order_enum; |
| 1359 | TypeTableEntry *entry_global_linkage_enum; | |
| 1349 | 1360 | TypeTableEntry *entry_arg_tuple; |
| 1350 | 1361 | } builtin_types; |
| 1351 | 1362 | |
| ... | ... | @@ -1378,7 +1389,7 @@ struct CodeGen { |
| 1378 | 1389 | bool is_native_target; |
| 1379 | 1390 | PackageTableEntry *root_package; |
| 1380 | 1391 | PackageTableEntry *std_package; |
| 1381 | PackageTableEntry *panic_package; | |
| 1392 | PackageTableEntry *zigrt_package; | |
| 1382 | 1393 | Buf *root_out_name; |
| 1383 | 1394 | bool windows_subsystem_windows; |
| 1384 | 1395 | bool windows_subsystem_console; |
| ... | ... | @@ -1388,6 +1399,7 @@ struct CodeGen { |
| 1388 | 1399 | Buf *mios_version_min; |
| 1389 | 1400 | bool linker_rdynamic; |
| 1390 | 1401 | const char *linker_script; |
| 1402 | bool omit_zigrt; | |
| 1391 | 1403 | |
| 1392 | 1404 | // The function definitions this module includes. There must be a corresponding |
| 1393 | 1405 | // fn_protos entry. |
| ... | ... | @@ -1401,7 +1413,8 @@ struct CodeGen { |
| 1401 | 1413 | OutType out_type; |
| 1402 | 1414 | FnTableEntry *cur_fn; |
| 1403 | 1415 | FnTableEntry *main_fn; |
| 1404 | FnTableEntry *panic_fn; | |
| 1416 | FnTableEntry *user_panic_fn; | |
| 1417 | FnTableEntry *extern_panic_fn; | |
| 1405 | 1418 | LLVMValueRef cur_ret_ptr; |
| 1406 | 1419 | LLVMValueRef cur_fn_val; |
| 1407 | 1420 | ZigList<LLVMBasicBlockRef> break_block_stack; |
| ... | ... | @@ -1656,7 +1669,6 @@ enum IrInstructionId { |
| 1656 | 1669 | IrInstructionIdTypeOf, |
| 1657 | 1670 | IrInstructionIdToPtrType, |
| 1658 | 1671 | IrInstructionIdPtrTypeChild, |
| 1659 | IrInstructionIdSetFnVisible, | |
| 1660 | 1672 | IrInstructionIdSetDebugSafety, |
| 1661 | 1673 | IrInstructionIdArrayType, |
| 1662 | 1674 | IrInstructionIdSliceType, |
| ... | ... | @@ -1718,7 +1730,9 @@ enum IrInstructionId { |
| 1718 | 1730 | IrInstructionIdCanImplicitCast, |
| 1719 | 1731 | IrInstructionIdSetGlobalAlign, |
| 1720 | 1732 | IrInstructionIdSetGlobalSection, |
| 1733 | IrInstructionIdSetGlobalLinkage, | |
| 1721 | 1734 | IrInstructionIdDeclRef, |
| 1735 | IrInstructionIdPanic, | |
| 1722 | 1736 | }; |
| 1723 | 1737 | |
| 1724 | 1738 | struct IrInstruction { |
| ... | ... | @@ -1999,13 +2013,6 @@ struct IrInstructionPtrTypeChild { |
| 1999 | 2013 | IrInstruction *value; |
| 2000 | 2014 | }; |
| 2001 | 2015 | |
| 2002 | struct IrInstructionSetFnVisible { | |
| 2003 | IrInstruction base; | |
| 2004 | ||
| 2005 | IrInstruction *fn_value; | |
| 2006 | IrInstruction *is_visible; | |
| 2007 | }; | |
| 2008 | ||
| 2009 | 2016 | struct IrInstructionSetDebugSafety { |
| 2010 | 2017 | IrInstruction base; |
| 2011 | 2018 | |
| ... | ... | @@ -2439,6 +2446,13 @@ struct IrInstructionSetGlobalSection { |
| 2439 | 2446 | IrInstruction *value; |
| 2440 | 2447 | }; |
| 2441 | 2448 | |
| 2449 | struct IrInstructionSetGlobalLinkage { | |
| 2450 | IrInstruction base; | |
| 2451 | ||
| 2452 | Tld *tld; | |
| 2453 | IrInstruction *value; | |
| 2454 | }; | |
| 2455 | ||
| 2442 | 2456 | struct IrInstructionDeclRef { |
| 2443 | 2457 | IrInstruction base; |
| 2444 | 2458 | |
| ... | ... | @@ -2446,6 +2460,12 @@ struct IrInstructionDeclRef { |
| 2446 | 2460 | LVal lval; |
| 2447 | 2461 | }; |
| 2448 | 2462 | |
| 2463 | struct IrInstructionPanic { | |
| 2464 | IrInstruction base; | |
| 2465 | ||
| 2466 | IrInstruction *msg; | |
| 2467 | }; | |
| 2468 | ||
| 2449 | 2469 | static const size_t slice_ptr_index = 0; |
| 2450 | 2470 | static const size_t slice_len_index = 1; |
| 2451 | 2471 |
src/analyze.cpp+59-22| ... | ... | @@ -1762,7 +1762,7 @@ static void get_fully_qualified_decl_name(Buf *buf, Tld *tld, uint8_t sep) { |
| 1762 | 1762 | buf_append_buf(buf, tld->name); |
| 1763 | 1763 | } |
| 1764 | 1764 | |
| 1765 | FnTableEntry *create_fn_raw(FnInline inline_value, bool internal_linkage) { | |
| 1765 | FnTableEntry *create_fn_raw(FnInline inline_value, GlobalLinkageId linkage) { | |
| 1766 | 1766 | FnTableEntry *fn_entry = allocate<FnTableEntry>(1); |
| 1767 | 1767 | |
| 1768 | 1768 | 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) { |
| 1770 | 1770 | fn_entry->analyzed_executable.fn_entry = fn_entry; |
| 1771 | 1771 | fn_entry->ir_executable.fn_entry = fn_entry; |
| 1772 | 1772 | fn_entry->fn_inline = inline_value; |
| 1773 | fn_entry->internal_linkage = internal_linkage; | |
| 1773 | fn_entry->linkage = linkage; | |
| 1774 | 1774 | |
| 1775 | 1775 | return fn_entry; |
| 1776 | 1776 | } |
| ... | ... | @@ -1780,8 +1780,9 @@ FnTableEntry *create_fn(AstNode *proto_node) { |
| 1780 | 1780 | AstNodeFnProto *fn_proto = &proto_node->data.fn_proto; |
| 1781 | 1781 | |
| 1782 | 1782 | 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); | |
| 1785 | 1786 | |
| 1786 | 1787 | fn_entry->proto_node = proto_node; |
| 1787 | 1788 | 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 |
| 1807 | 1808 | buf_ptr(&fn_type->name))); |
| 1808 | 1809 | } |
| 1809 | 1810 | |
| 1810 | static void typecheck_panic_fn(CodeGen *g) { | |
| 1811 | assert(g->panic_fn); | |
| 1812 | ||
| 1813 | AstNode *proto_node = g->panic_fn->proto_node; | |
| 1811 | static void typecheck_panic_fn(CodeGen *g, FnTableEntry *panic_fn) { | |
| 1812 | AstNode *proto_node = panic_fn->proto_node; | |
| 1814 | 1813 | assert(proto_node->type == NodeTypeFnProto); |
| 1815 | TypeTableEntry *fn_type = g->panic_fn->type_entry; | |
| 1814 | TypeTableEntry *fn_type = panic_fn->type_entry; | |
| 1816 | 1815 | FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; |
| 1817 | 1816 | if (fn_type_id->param_count != 1) { |
| 1818 | 1817 | return wrong_panic_prototype(g, proto_node, fn_type); |
| ... | ... | @@ -1862,6 +1861,8 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { |
| 1862 | 1861 | add_node_error(g, param_node, buf_sprintf("missing parameter name")); |
| 1863 | 1862 | } |
| 1864 | 1863 | } |
| 1864 | } else if (fn_table_entry->linkage != GlobalLinkageIdInternal) { | |
| 1865 | g->external_prototypes.put_unique(tld_fn->base.name, &tld_fn->base); | |
| 1865 | 1866 | } |
| 1866 | 1867 | |
| 1867 | 1868 | 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) { |
| 1892 | 1893 | } |
| 1893 | 1894 | } |
| 1894 | 1895 | } 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); | |
| 1897 | 1897 | } |
| 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; | |
| 1902 | 1901 | } |
| 1903 | 1902 | } |
| 1904 | 1903 | } |
| 1905 | 1904 | } 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); | |
| 1907 | 1906 | |
| 1908 | 1907 | get_fully_qualified_decl_name(&fn_table_entry->symbol_name, &tld_fn->base, '_'); |
| 1909 | 1908 | |
| ... | ... | @@ -1931,16 +1930,12 @@ static void resolve_decl_comptime(CodeGen *g, TldCompTime *tld_comptime) { |
| 1931 | 1930 | } |
| 1932 | 1931 | |
| 1933 | 1932 | static 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)) { | |
| 1939 | 1934 | g->resolve_queue.append(tld); |
| 1940 | 1935 | } |
| 1941 | 1936 | |
| 1942 | 1937 | 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); | |
| 1944 | 1939 | if (entry) { |
| 1945 | 1940 | Tld *other_tld = entry->value; |
| 1946 | 1941 | ErrorMsg *msg = add_node_error(g, tld->source_node, |
| ... | ... | @@ -2060,6 +2055,15 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { |
| 2060 | 2055 | TldFn *tld_fn = allocate<TldFn>(1); |
| 2061 | 2056 | init_tld(&tld_fn->base, TldIdFn, fn_name, visib_mod, node, &decls_scope->base); |
| 2062 | 2057 | 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 | ||
| 2063 | 2067 | break; |
| 2064 | 2068 | } |
| 2065 | 2069 | case NodeTypeUse: |
| ... | ... | @@ -4206,3 +4210,36 @@ ConstParent *get_const_val_parent(ConstExprValue *value) { |
| 4206 | 4210 | } |
| 4207 | 4211 | return nullptr; |
| 4208 | 4212 | } |
| 4213 | ||
| 4214 | FnTableEntry *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 |
| 72 | 72 | bool is_const, ConstExprValue *init_value, Tld *src_tld); |
| 73 | 73 | TypeTableEntry *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node); |
| 74 | 74 | FnTableEntry *create_fn(AstNode *proto_node); |
| 75 | FnTableEntry *create_fn_raw(FnInline inline_value, bool internal_linkage); | |
| 75 | FnTableEntry *create_fn_raw(FnInline inline_value, GlobalLinkageId linkage); | |
| 76 | 76 | void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_count_alloc); |
| 77 | 77 | AstNode *get_param_decl_node(FnTableEntry *fn_entry, size_t index); |
| 78 | 78 | FnTableEntry *scope_get_fn_if_root(Scope *scope); |
| ... | ... | @@ -148,5 +148,6 @@ void init_const_undefined(CodeGen *g, ConstExprValue *const_val); |
| 148 | 148 | |
| 149 | 149 | TypeTableEntry *make_int_type(CodeGen *g, bool is_signed, size_t size_in_bits); |
| 150 | 150 | ConstParent *get_const_val_parent(ConstExprValue *value); |
| 151 | FnTableEntry *get_extern_panic_fn(CodeGen *g); | |
| 151 | 152 | |
| 152 | 153 | #endif |
src/codegen.cpp+127-21| ... | ... | @@ -67,7 +67,8 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) { |
| 67 | 67 | g->llvm_fn_table.init(16); |
| 68 | 68 | g->memoized_fn_eval_table.init(16); |
| 69 | 69 | 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); | |
| 71 | 72 | g->is_release_build = false; |
| 72 | 73 | g->is_test_build = false; |
| 73 | 74 | g->want_h_file = true; |
| ... | ... | @@ -140,6 +141,10 @@ void codegen_set_is_release(CodeGen *g, bool is_release_build) { |
| 140 | 141 | g->is_release_build = is_release_build; |
| 141 | 142 | } |
| 142 | 143 | |
| 144 | void codegen_set_omit_zigrt(CodeGen *g, bool omit_zigrt) { | |
| 145 | g->omit_zigrt = omit_zigrt; | |
| 146 | } | |
| 147 | ||
| 143 | 148 | void codegen_set_is_test(CodeGen *g, bool is_test_build) { |
| 144 | 149 | g->is_test_build = is_test_build; |
| 145 | 150 | } |
| ... | ... | @@ -256,10 +261,22 @@ static void addLLVMAttr(LLVMValueRef val, LLVMAttributeIndex attr_index, const c |
| 256 | 261 | LLVMAddAttributeAtIndex(val, attr_index, llvm_attr); |
| 257 | 262 | } |
| 258 | 263 | |
| 264 | static 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 | ||
| 259 | 272 | static void addLLVMFnAttr(LLVMValueRef fn_val, const char *attr_name) { |
| 260 | 273 | return addLLVMAttr(fn_val, -1, attr_name); |
| 261 | 274 | } |
| 262 | 275 | |
| 276 | static 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 | ||
| 263 | 280 | static void addLLVMArgAttr(LLVMValueRef arg_val, unsigned param_index, const char *attr_name) { |
| 264 | 281 | return addLLVMAttr(arg_val, param_index + 1, attr_name); |
| 265 | 282 | } |
| ... | ... | @@ -271,15 +288,19 @@ static void addLLVMCallsiteAttr(LLVMValueRef call_instr, unsigned param_index, c |
| 271 | 288 | LLVMAddCallSiteAttribute(call_instr, param_index + 1, llvm_attr); |
| 272 | 289 | } |
| 273 | 290 | |
| 291 | static 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 | ||
| 274 | 295 | static 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)) { | |
| 276 | 297 | return original_name; |
| 277 | 298 | } |
| 278 | 299 | |
| 279 | 300 | int n = 0; |
| 280 | 301 | for (;; n += 1) { |
| 281 | 302 | 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)) { | |
| 283 | 304 | return new_name; |
| 284 | 305 | } |
| 285 | 306 | } |
| ... | ... | @@ -289,11 +310,12 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { |
| 289 | 310 | if (fn_table_entry->llvm_value) |
| 290 | 311 | return fn_table_entry->llvm_value; |
| 291 | 312 | |
| 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); | |
| 293 | 315 | |
| 294 | 316 | TypeTableEntry *fn_type = fn_table_entry->type_entry; |
| 295 | 317 | 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) { | |
| 297 | 319 | LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, buf_ptr(symbol_name)); |
| 298 | 320 | if (existing_llvm_fn) { |
| 299 | 321 | 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) { |
| 318 | 340 | addLLVMFnAttr(fn_table_entry->llvm_value, "naked"); |
| 319 | 341 | } |
| 320 | 342 | |
| 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 | } | |
| 323 | 357 | |
| 324 | 358 | if (fn_type->data.fn.fn_type_id.return_type->id == TypeTableEntryIdUnreachable) { |
| 325 | 359 | addLLVMFnAttr(fn_table_entry->llvm_value, "noreturn"); |
| 326 | 360 | } |
| 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 | ||
| 327 | 372 | LLVMSetFunctionCallConv(fn_table_entry->llvm_value, fn_type->data.fn.calling_convention); |
| 328 | 373 | if (fn_type->data.fn.fn_type_id.is_cold) { |
| 329 | 374 | ZigLLVMAddFunctionAttrCold(fn_table_entry->llvm_value); |
| ... | ... | @@ -363,10 +408,11 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) { |
| 363 | 408 | bool is_definition = fn_table_entry->body_node != nullptr; |
| 364 | 409 | unsigned flags = 0; |
| 365 | 410 | bool is_optimized = g->is_release_build; |
| 411 | bool is_internal_linkage = (fn_table_entry->linkage == GlobalLinkageIdInternal); | |
| 366 | 412 | ZigLLVMDISubprogram *subprogram = ZigLLVMCreateFunction(g->dbuilder, |
| 367 | 413 | get_di_scope(g, scope->parent), buf_ptr(&fn_table_entry->symbol_name), "", |
| 368 | 414 | 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, | |
| 370 | 416 | is_definition, scope_line, flags, is_optimized, nullptr); |
| 371 | 417 | |
| 372 | 418 | scope->di_scope = ZigLLVMSubprogramToScope(subprogram); |
| ... | ... | @@ -544,13 +590,28 @@ static LLVMValueRef get_panic_msg_ptr_val(CodeGen *g, PanicMsgId msg_id) { |
| 544 | 590 | return val->llvm_global; |
| 545 | 591 | } |
| 546 | 592 | |
| 547 | static 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, ""); | |
| 593 | static 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, ""); | |
| 551 | 608 | LLVMBuildUnreachable(g->builder); |
| 552 | 609 | } |
| 553 | 610 | |
| 611 | static void gen_debug_safety_crash(CodeGen *g, PanicMsgId msg_id) { | |
| 612 | gen_panic(g, get_panic_msg_ptr_val(g, msg_id)); | |
| 613 | } | |
| 614 | ||
| 554 | 615 | static void add_bounds_check(CodeGen *g, LLVMValueRef target_val, |
| 555 | 616 | LLVMIntPredicate lower_pred, LLVMValueRef lower_value, |
| 556 | 617 | LLVMIntPredicate upper_pred, LLVMValueRef upper_value) |
| ... | ... | @@ -2564,6 +2625,11 @@ static LLVMValueRef ir_render_container_init_list(CodeGen *g, IrExecutable *exec |
| 2564 | 2625 | return tmp_array_ptr; |
| 2565 | 2626 | } |
| 2566 | 2627 | |
| 2628 | static 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 | ||
| 2567 | 2633 | static void set_debug_location(CodeGen *g, IrInstruction *instruction) { |
| 2568 | 2634 | AstNode *source_node = instruction->source_node; |
| 2569 | 2635 | Scope *scope = instruction->scope; |
| ... | ... | @@ -2584,7 +2650,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 2584 | 2650 | case IrInstructionIdToPtrType: |
| 2585 | 2651 | case IrInstructionIdPtrTypeChild: |
| 2586 | 2652 | case IrInstructionIdFieldPtr: |
| 2587 | case IrInstructionIdSetFnVisible: | |
| 2588 | 2653 | case IrInstructionIdSetDebugSafety: |
| 2589 | 2654 | case IrInstructionIdArrayType: |
| 2590 | 2655 | case IrInstructionIdSliceType: |
| ... | ... | @@ -2615,7 +2680,9 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 2615 | 2680 | case IrInstructionIdCanImplicitCast: |
| 2616 | 2681 | case IrInstructionIdSetGlobalAlign: |
| 2617 | 2682 | case IrInstructionIdSetGlobalSection: |
| 2683 | case IrInstructionIdSetGlobalLinkage: | |
| 2618 | 2684 | case IrInstructionIdDeclRef: |
| 2685 | case IrInstructionIdSwitchVar: | |
| 2619 | 2686 | zig_unreachable(); |
| 2620 | 2687 | case IrInstructionIdReturn: |
| 2621 | 2688 | return ir_render_return(g, executable, (IrInstructionReturn *)instruction); |
| ... | ... | @@ -2721,8 +2788,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 2721 | 2788 | return ir_render_int_to_enum(g, executable, (IrInstructionIntToEnum *)instruction); |
| 2722 | 2789 | case IrInstructionIdContainerInitList: |
| 2723 | 2790 | 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); | |
| 2726 | 2793 | } |
| 2727 | 2794 | zig_unreachable(); |
| 2728 | 2795 | } |
| ... | ... | @@ -3659,6 +3726,18 @@ static const CIntTypeInfo c_int_type_infos[] = { |
| 3659 | 3726 | |
| 3660 | 3727 | static const bool is_signed_list[] = { false, true, }; |
| 3661 | 3728 | |
| 3729 | struct GlobalLinkageValue { | |
| 3730 | GlobalLinkageId id; | |
| 3731 | const char *name; | |
| 3732 | }; | |
| 3733 | ||
| 3734 | static const GlobalLinkageValue global_linkage_values[] = { | |
| 3735 | {GlobalLinkageIdInternal, "Internal"}, | |
| 3736 | {GlobalLinkageIdStrong, "Strong"}, | |
| 3737 | {GlobalLinkageIdWeak, "Weak"}, | |
| 3738 | {GlobalLinkageIdLinkOnce, "LinkOnce"}, | |
| 3739 | }; | |
| 3740 | ||
| 3662 | 3741 | static void define_builtin_types(CodeGen *g) { |
| 3663 | 3742 | { |
| 3664 | 3743 | // if this type is anywhere in the AST, we should never hit codegen. |
| ... | ... | @@ -3995,6 +4074,30 @@ static void define_builtin_types(CodeGen *g) { |
| 3995 | 4074 | g->primitive_type_table.put(&entry->name, entry); |
| 3996 | 4075 | } |
| 3997 | 4076 | |
| 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 | ||
| 3998 | 4101 | { |
| 3999 | 4102 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnum); |
| 4000 | 4103 | entry->zero_bits = true; // only allowed at compile time |
| ... | ... | @@ -4145,11 +4248,12 @@ static void define_builtin_fns(CodeGen *g) { |
| 4145 | 4248 | create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1); |
| 4146 | 4249 | create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX); |
| 4147 | 4250 | create_builtin_fn(g, BuiltinFnIdIntType, "intType", 2); |
| 4148 | create_builtin_fn(g, BuiltinFnIdSetFnVisible, "setFnVisible", 2); | |
| 4149 | 4251 | create_builtin_fn(g, BuiltinFnIdSetDebugSafety, "setDebugSafety", 2); |
| 4150 | 4252 | create_builtin_fn(g, BuiltinFnIdAlloca, "alloca", 2); |
| 4151 | 4253 | create_builtin_fn(g, BuiltinFnIdSetGlobalAlign, "setGlobalAlign", 2); |
| 4152 | 4254 | create_builtin_fn(g, BuiltinFnIdSetGlobalSection, "setGlobalSection", 2); |
| 4255 | create_builtin_fn(g, BuiltinFnIdSetGlobalLinkage, "setGlobalLinkage", 2); | |
| 4256 | create_builtin_fn(g, BuiltinFnIdPanic, "panic", 1); | |
| 4153 | 4257 | } |
| 4154 | 4258 | |
| 4155 | 4259 | static void add_compile_var(CodeGen *g, const char *name, ConstExprValue *value) { |
| ... | ... | @@ -4180,6 +4284,7 @@ static void define_builtin_compile_vars(CodeGen *g) { |
| 4180 | 4284 | |
| 4181 | 4285 | add_compile_var(g, "link_libs", const_val); |
| 4182 | 4286 | } |
| 4287 | add_compile_var(g, "panic_implementation_provided", create_const_bool(g, false)); | |
| 4183 | 4288 | } |
| 4184 | 4289 | |
| 4185 | 4290 | static void init(CodeGen *g, Buf *source_path) { |
| ... | ... | @@ -4309,9 +4414,10 @@ static PackageTableEntry *create_bootstrap_pkg(CodeGen *g) { |
| 4309 | 4414 | return package; |
| 4310 | 4415 | } |
| 4311 | 4416 | |
| 4312 | static PackageTableEntry *create_panic_pkg(CodeGen *g) { | |
| 4417 | static PackageTableEntry *create_zigrt_pkg(CodeGen *g) { | |
| 4313 | 4418 | PackageTableEntry *package = new_package(buf_ptr(g->zig_std_special_dir), ""); |
| 4314 | 4419 | 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); | |
| 4315 | 4421 | return package; |
| 4316 | 4422 | } |
| 4317 | 4423 | |
| ... | ... | @@ -4337,9 +4443,9 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou |
| 4337 | 4443 | if (!g->is_test_build && g->have_pub_main && (g->out_type == OutTypeObj || g->out_type == OutTypeExe)) { |
| 4338 | 4444 | g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g), "bootstrap.zig"); |
| 4339 | 4445 | } |
| 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"); | |
| 4343 | 4449 | } |
| 4344 | 4450 | |
| 4345 | 4451 | if (g->verbose) { |
| ... | ... | @@ -4509,7 +4615,7 @@ void codegen_generate_h_file(CodeGen *g) { |
| 4509 | 4615 | for (size_t fn_def_i = 0; fn_def_i < g->fn_defs.length; fn_def_i += 1) { |
| 4510 | 4616 | FnTableEntry *fn_table_entry = g->fn_defs.at(fn_def_i); |
| 4511 | 4617 | |
| 4512 | if (fn_table_entry->internal_linkage) | |
| 4618 | if (fn_table_entry->linkage == GlobalLinkageIdInternal) | |
| 4513 | 4619 | continue; |
| 4514 | 4620 | |
| 4515 | 4621 | 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); |
| 43 | 43 | void codegen_set_mmacosx_version_min(CodeGen *g, Buf *mmacosx_version_min); |
| 44 | 44 | void codegen_set_mios_version_min(CodeGen *g, Buf *mios_version_min); |
| 45 | 45 | void codegen_set_linker_script(CodeGen *g, const char *linker_script); |
| 46 | void codegen_set_omit_zigrt(CodeGen *g, bool omit_zigrt); | |
| 46 | 47 | |
| 47 | 48 | void codegen_add_root_code(CodeGen *g, Buf *source_dir, Buf *source_basename, Buf *source_code); |
| 48 | 49 |
src/ir.cpp+148-82| ... | ... | @@ -276,10 +276,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrTypeChild *) |
| 276 | 276 | return IrInstructionIdPtrTypeChild; |
| 277 | 277 | } |
| 278 | 278 | |
| 279 | static constexpr IrInstructionId ir_instruction_id(IrInstructionSetFnVisible *) { | |
| 280 | return IrInstructionIdSetFnVisible; | |
| 281 | } | |
| 282 | ||
| 283 | 279 | static constexpr IrInstructionId ir_instruction_id(IrInstructionSetDebugSafety *) { |
| 284 | 280 | return IrInstructionIdSetDebugSafety; |
| 285 | 281 | } |
| ... | ... | @@ -528,10 +524,18 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSetGlobalSection |
| 528 | 524 | return IrInstructionIdSetGlobalSection; |
| 529 | 525 | } |
| 530 | 526 | |
| 527 | static constexpr IrInstructionId ir_instruction_id(IrInstructionSetGlobalLinkage *) { | |
| 528 | return IrInstructionIdSetGlobalLinkage; | |
| 529 | } | |
| 530 | ||
| 531 | 531 | static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclRef *) { |
| 532 | 532 | return IrInstructionIdDeclRef; |
| 533 | 533 | } |
| 534 | 534 | |
| 535 | static constexpr IrInstructionId ir_instruction_id(IrInstructionPanic *) { | |
| 536 | return IrInstructionIdPanic; | |
| 537 | } | |
| 538 | ||
| 535 | 539 | template<typename T> |
| 536 | 540 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 537 | 541 | T *special_instruction = allocate<T>(1); |
| ... | ... | @@ -1147,19 +1151,6 @@ static IrInstruction *ir_build_ptr_type_child(IrBuilder *irb, Scope *scope, AstN |
| 1147 | 1151 | return &instruction->base; |
| 1148 | 1152 | } |
| 1149 | 1153 | |
| 1150 | static 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 | ||
| 1163 | 1154 | static IrInstruction *ir_build_set_debug_safety(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 1164 | 1155 | IrInstruction *scope_value, IrInstruction *debug_safety_on) |
| 1165 | 1156 | { |
| ... | ... | @@ -2092,6 +2083,19 @@ static IrInstruction *ir_build_set_global_section(IrBuilder *irb, Scope *scope, |
| 2092 | 2083 | return &instruction->base; |
| 2093 | 2084 | } |
| 2094 | 2085 | |
| 2086 | static 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 | ||
| 2095 | 2099 | static IrInstruction *ir_build_decl_ref(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 2096 | 2100 | Tld *tld, LVal lval) |
| 2097 | 2101 | { |
| ... | ... | @@ -2103,6 +2107,17 @@ static IrInstruction *ir_build_decl_ref(IrBuilder *irb, Scope *scope, AstNode *s |
| 2103 | 2107 | return &instruction->base; |
| 2104 | 2108 | } |
| 2105 | 2109 | |
| 2110 | static 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 | ||
| 2106 | 2121 | static IrInstruction *ir_instruction_br_get_dep(IrInstructionBr *instruction, size_t index) { |
| 2107 | 2122 | return nullptr; |
| 2108 | 2123 | } |
| ... | ... | @@ -2287,14 +2302,6 @@ static IrInstruction *ir_instruction_ptrtypechild_get_dep(IrInstructionPtrTypeCh |
| 2287 | 2302 | } |
| 2288 | 2303 | } |
| 2289 | 2304 | |
| 2290 | static 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 | ||
| 2298 | 2305 | static IrInstruction *ir_instruction_setdebugsafety_get_dep(IrInstructionSetDebugSafety *instruction, size_t index) { |
| 2299 | 2306 | switch (index) { |
| 2300 | 2307 | case 0: return instruction->scope_value; |
| ... | ... | @@ -2742,10 +2749,24 @@ static IrInstruction *ir_instruction_setglobalsection_get_dep(IrInstructionSetGl |
| 2742 | 2749 | } |
| 2743 | 2750 | } |
| 2744 | 2751 | |
| 2752 | static 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 | ||
| 2745 | 2759 | static IrInstruction *ir_instruction_declref_get_dep(IrInstructionDeclRef *instruction, size_t index) { |
| 2746 | 2760 | return nullptr; |
| 2747 | 2761 | } |
| 2748 | 2762 | |
| 2763 | static 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 | ||
| 2749 | 2770 | static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t index) { |
| 2750 | 2771 | switch (instruction->id) { |
| 2751 | 2772 | case IrInstructionIdInvalid: |
| ... | ... | @@ -2804,8 +2825,6 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t |
| 2804 | 2825 | return ir_instruction_toptrtype_get_dep((IrInstructionToPtrType *) instruction, index); |
| 2805 | 2826 | case IrInstructionIdPtrTypeChild: |
| 2806 | 2827 | return ir_instruction_ptrtypechild_get_dep((IrInstructionPtrTypeChild *) instruction, index); |
| 2807 | case IrInstructionIdSetFnVisible: | |
| 2808 | return ir_instruction_setfnvisible_get_dep((IrInstructionSetFnVisible *) instruction, index); | |
| 2809 | 2828 | case IrInstructionIdSetDebugSafety: |
| 2810 | 2829 | return ir_instruction_setdebugsafety_get_dep((IrInstructionSetDebugSafety *) instruction, index); |
| 2811 | 2830 | case IrInstructionIdArrayType: |
| ... | ... | @@ -2928,8 +2947,12 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t |
| 2928 | 2947 | return ir_instruction_setglobalalign_get_dep((IrInstructionSetGlobalAlign *) instruction, index); |
| 2929 | 2948 | case IrInstructionIdSetGlobalSection: |
| 2930 | 2949 | return ir_instruction_setglobalsection_get_dep((IrInstructionSetGlobalSection *) instruction, index); |
| 2950 | case IrInstructionIdSetGlobalLinkage: | |
| 2951 | return ir_instruction_setgloballinkage_get_dep((IrInstructionSetGlobalLinkage *) instruction, index); | |
| 2931 | 2952 | case IrInstructionIdDeclRef: |
| 2932 | 2953 | return ir_instruction_declref_get_dep((IrInstructionDeclRef *) instruction, index); |
| 2954 | case IrInstructionIdPanic: | |
| 2955 | return ir_instruction_panic_get_dep((IrInstructionPanic *) instruction, index); | |
| 2933 | 2956 | } |
| 2934 | 2957 | zig_unreachable(); |
| 2935 | 2958 | } |
| ... | ... | @@ -3759,20 +3782,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 3759 | 3782 | return arg; |
| 3760 | 3783 | return ir_build_typeof(irb, scope, node, arg); |
| 3761 | 3784 | } |
| 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 | } | |
| 3776 | 3785 | case BuiltinFnIdSetDebugSafety: |
| 3777 | 3786 | { |
| 3778 | 3787 | 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 |
| 4145 | 4154 | } |
| 4146 | 4155 | case BuiltinFnIdSetGlobalAlign: |
| 4147 | 4156 | case BuiltinFnIdSetGlobalSection: |
| 4157 | case BuiltinFnIdSetGlobalLinkage: | |
| 4148 | 4158 | { |
| 4149 | 4159 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); |
| 4150 | 4160 | if (arg0_node->type != NodeTypeSymbol) { |
| ... | ... | @@ -4170,10 +4180,23 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4170 | 4180 | |
| 4171 | 4181 | if (builtin_fn->id == BuiltinFnIdSetGlobalAlign) { |
| 4172 | 4182 | return ir_build_set_global_align(irb, scope, node, tld, arg1_value); |
| 4173 | } else { | |
| 4183 | } else if (builtin_fn->id == BuiltinFnIdSetGlobalSection) { | |
| 4174 | 4184 | 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(); | |
| 4175 | 4189 | } |
| 4176 | 4190 | } |
| 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 | } | |
| 4177 | 4200 | } |
| 4178 | 4201 | zig_unreachable(); |
| 4179 | 4202 | } |
| ... | ... | @@ -4624,6 +4647,10 @@ static IrInstruction *ir_gen_this_literal(IrBuilder *irb, Scope *scope, AstNode |
| 4624 | 4647 | if (fn_entry) |
| 4625 | 4648 | return ir_build_const_fn(irb, scope, node, fn_entry); |
| 4626 | 4649 | |
| 4650 | while (scope->id != ScopeIdBlock && scope->id != ScopeIdDecls) { | |
| 4651 | scope = scope->parent; | |
| 4652 | } | |
| 4653 | ||
| 4627 | 4654 | if (scope->id == ScopeIdDecls) { |
| 4628 | 4655 | ScopeDecls *decls_scope = (ScopeDecls *)scope; |
| 4629 | 4656 | TypeTableEntry *container_type = decls_scope->container_type; |
| ... | ... | @@ -7096,6 +7123,23 @@ static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, Atomic |
| 7096 | 7123 | return true; |
| 7097 | 7124 | } |
| 7098 | 7125 | |
| 7126 | static 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 | ||
| 7099 | 7143 | static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) { |
| 7100 | 7144 | if (type_is_invalid(value->value.type)) |
| 7101 | 7145 | return nullptr; |
| ... | ... | @@ -9557,42 +9601,6 @@ static TypeTableEntry *ir_analyze_instruction_ptr_type_child(IrAnalyze *ira, |
| 9557 | 9601 | return ira->codegen->builtin_types.entry_type; |
| 9558 | 9602 | } |
| 9559 | 9603 | |
| 9560 | static 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 | ||
| 9596 | 9604 | static TypeTableEntry *ir_analyze_instruction_set_global_align(IrAnalyze *ira, |
| 9597 | 9605 | IrInstructionSetGlobalAlign *instruction) |
| 9598 | 9606 | { |
| ... | ... | @@ -9677,6 +9685,45 @@ static TypeTableEntry *ir_analyze_instruction_set_global_section(IrAnalyze *ira, |
| 9677 | 9685 | return ira->codegen->builtin_types.entry_void; |
| 9678 | 9686 | } |
| 9679 | 9687 | |
| 9688 | static 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 | ||
| 9680 | 9727 | static TypeTableEntry *ir_analyze_instruction_set_debug_safety(IrAnalyze *ira, |
| 9681 | 9728 | IrInstructionSetDebugSafety *set_debug_safety_instruction) |
| 9682 | 9729 | { |
| ... | ... | @@ -12147,6 +12194,22 @@ static TypeTableEntry *ir_analyze_instruction_can_implicit_cast(IrAnalyze *ira, |
| 12147 | 12194 | return ira->codegen->builtin_types.entry_bool; |
| 12148 | 12195 | } |
| 12149 | 12196 | |
| 12197 | static 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 | ||
| 12150 | 12213 | static TypeTableEntry *ir_analyze_instruction_decl_ref(IrAnalyze *ira, |
| 12151 | 12214 | IrInstructionDeclRef *instruction) |
| 12152 | 12215 | { |
| ... | ... | @@ -12266,12 +12329,12 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 12266 | 12329 | return ir_analyze_instruction_to_ptr_type(ira, (IrInstructionToPtrType *)instruction); |
| 12267 | 12330 | case IrInstructionIdPtrTypeChild: |
| 12268 | 12331 | return ir_analyze_instruction_ptr_type_child(ira, (IrInstructionPtrTypeChild *)instruction); |
| 12269 | case IrInstructionIdSetFnVisible: | |
| 12270 | return ir_analyze_instruction_set_fn_visible(ira, (IrInstructionSetFnVisible *)instruction); | |
| 12271 | 12332 | case IrInstructionIdSetGlobalAlign: |
| 12272 | 12333 | return ir_analyze_instruction_set_global_align(ira, (IrInstructionSetGlobalAlign *)instruction); |
| 12273 | 12334 | case IrInstructionIdSetGlobalSection: |
| 12274 | 12335 | return ir_analyze_instruction_set_global_section(ira, (IrInstructionSetGlobalSection *)instruction); |
| 12336 | case IrInstructionIdSetGlobalLinkage: | |
| 12337 | return ir_analyze_instruction_set_global_linkage(ira, (IrInstructionSetGlobalLinkage *)instruction); | |
| 12275 | 12338 | case IrInstructionIdSetDebugSafety: |
| 12276 | 12339 | return ir_analyze_instruction_set_debug_safety(ira, (IrInstructionSetDebugSafety *)instruction); |
| 12277 | 12340 | case IrInstructionIdSliceType: |
| ... | ... | @@ -12384,6 +12447,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 12384 | 12447 | return ir_analyze_instruction_can_implicit_cast(ira, (IrInstructionCanImplicitCast *)instruction); |
| 12385 | 12448 | case IrInstructionIdDeclRef: |
| 12386 | 12449 | return ir_analyze_instruction_decl_ref(ira, (IrInstructionDeclRef *)instruction); |
| 12450 | case IrInstructionIdPanic: | |
| 12451 | return ir_analyze_instruction_panic(ira, (IrInstructionPanic *)instruction); | |
| 12387 | 12452 | case IrInstructionIdMaybeWrap: |
| 12388 | 12453 | case IrInstructionIdErrWrapCode: |
| 12389 | 12454 | case IrInstructionIdErrWrapPayload: |
| ... | ... | @@ -12482,7 +12547,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 12482 | 12547 | case IrInstructionIdCall: |
| 12483 | 12548 | case IrInstructionIdReturn: |
| 12484 | 12549 | case IrInstructionIdUnreachable: |
| 12485 | case IrInstructionIdSetFnVisible: | |
| 12486 | 12550 | case IrInstructionIdSetDebugSafety: |
| 12487 | 12551 | case IrInstructionIdImport: |
| 12488 | 12552 | case IrInstructionIdCompileErr: |
| ... | ... | @@ -12500,6 +12564,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 12500 | 12564 | case IrInstructionIdCheckSwitchProngs: |
| 12501 | 12565 | case IrInstructionIdSetGlobalAlign: |
| 12502 | 12566 | case IrInstructionIdSetGlobalSection: |
| 12567 | case IrInstructionIdSetGlobalLinkage: | |
| 12568 | case IrInstructionIdPanic: | |
| 12503 | 12569 | return true; |
| 12504 | 12570 | case IrInstructionIdPhi: |
| 12505 | 12571 | case IrInstructionIdUnOp: |
| ... | ... | @@ -12580,7 +12646,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 12580 | 12646 | } |
| 12581 | 12647 | |
| 12582 | 12648 | FnTableEntry *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); | |
| 12584 | 12650 | buf_init_from_buf(&fn_entry->symbol_name, fn_name); |
| 12585 | 12651 | |
| 12586 | 12652 | 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 |
| 339 | 339 | fprintf(irp->f, ")"); |
| 340 | 340 | } |
| 341 | 341 | |
| 342 | static 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 | ||
| 350 | 342 | static void ir_print_set_debug_safety(IrPrint *irp, IrInstructionSetDebugSafety *instruction) { |
| 351 | 343 | fprintf(irp->f, "@setDebugSafety("); |
| 352 | 344 | ir_print_other_instruction(irp, instruction->scope_value); |
| ... | ... | @@ -849,6 +841,13 @@ static void ir_print_set_global_section(IrPrint *irp, IrInstructionSetGlobalSect |
| 849 | 841 | fprintf(irp->f, ")"); |
| 850 | 842 | } |
| 851 | 843 | |
| 844 | static 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 | ||
| 852 | 851 | static void ir_print_decl_ref(IrPrint *irp, IrInstructionDeclRef *instruction) { |
| 853 | 852 | const char *ptr_str = instruction->lval.is_ptr ? "ptr " : ""; |
| 854 | 853 | const char *const_str = instruction->lval.is_const ? "const " : ""; |
| ... | ... | @@ -856,6 +855,13 @@ static void ir_print_decl_ref(IrPrint *irp, IrInstructionDeclRef *instruction) { |
| 856 | 855 | fprintf(irp->f, "declref %s%s%s%s", const_str, volatile_str, ptr_str, buf_ptr(instruction->tld->name)); |
| 857 | 856 | } |
| 858 | 857 | |
| 858 | static 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 | ||
| 859 | 865 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 860 | 866 | ir_print_prefix(irp, instruction); |
| 861 | 867 | switch (instruction->id) { |
| ... | ... | @@ -933,9 +939,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 933 | 939 | case IrInstructionIdEnumFieldPtr: |
| 934 | 940 | ir_print_enum_field_ptr(irp, (IrInstructionEnumFieldPtr *)instruction); |
| 935 | 941 | break; |
| 936 | case IrInstructionIdSetFnVisible: | |
| 937 | ir_print_set_fn_visible(irp, (IrInstructionSetFnVisible *)instruction); | |
| 938 | break; | |
| 939 | 942 | case IrInstructionIdSetDebugSafety: |
| 940 | 943 | ir_print_set_debug_safety(irp, (IrInstructionSetDebugSafety *)instruction); |
| 941 | 944 | break; |
| ... | ... | @@ -1128,9 +1131,15 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1128 | 1131 | case IrInstructionIdSetGlobalSection: |
| 1129 | 1132 | ir_print_set_global_section(irp, (IrInstructionSetGlobalSection *)instruction); |
| 1130 | 1133 | break; |
| 1134 | case IrInstructionIdSetGlobalLinkage: | |
| 1135 | ir_print_set_global_linkage(irp, (IrInstructionSetGlobalLinkage *)instruction); | |
| 1136 | break; | |
| 1131 | 1137 | case IrInstructionIdDeclRef: |
| 1132 | 1138 | ir_print_decl_ref(irp, (IrInstructionDeclRef *)instruction); |
| 1133 | 1139 | break; |
| 1140 | case IrInstructionIdPanic: | |
| 1141 | ir_print_panic(irp, (IrInstructionPanic *)instruction); | |
| 1142 | break; | |
| 1134 | 1143 | } |
| 1135 | 1144 | fprintf(irp->f, "\n"); |
| 1136 | 1145 | } |
src/link.cpp+1| ... | ... | @@ -52,6 +52,7 @@ static Buf *build_o(CodeGen *parent_gen, const char *oname) { |
| 52 | 52 | child_gen->link_libs.items[i] = parent_gen->link_libs.items[i]; |
| 53 | 53 | } |
| 54 | 54 | |
| 55 | codegen_set_omit_zigrt(child_gen, true); | |
| 55 | 56 | child_gen->want_h_file = false; |
| 56 | 57 | |
| 57 | 58 | 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) { |
| 635 | 635 | } |
| 636 | 636 | assert(fn_type->id == TypeTableEntryIdFn); |
| 637 | 637 | |
| 638 | bool internal_linkage = false; | |
| 639 | FnTableEntry *fn_entry = create_fn_raw(FnInlineAuto, internal_linkage); | |
| 638 | FnTableEntry *fn_entry = create_fn_raw(FnInlineAuto, GlobalLinkageIdStrong); | |
| 640 | 639 | buf_init_from_buf(&fn_entry->symbol_name, fn_name); |
| 641 | 640 | fn_entry->type_entry = fn_type; |
| 642 | 641 |
std/special/bootstrap.zig+2-2| ... | ... | @@ -13,7 +13,7 @@ var argc: usize = undefined; |
| 13 | 13 | var argv: &&u8 = undefined; |
| 14 | 14 | |
| 15 | 15 | export nakedcc fn _start() -> noreturn { |
| 16 | @setFnVisible(this, want_start_symbol); | |
| 16 | @setGlobalLinkage(_start, if (want_start_symbol) GlobalLinkage.Strong else GlobalLinkage.Internal); | |
| 17 | 17 | if (!want_start_symbol) { |
| 18 | 18 | unreachable; |
| 19 | 19 | } |
| ... | ... | @@ -47,7 +47,7 @@ fn callMainAndExit() -> noreturn { |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | 49 | export 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); | |
| 51 | 51 | if (!want_main_symbol) { |
| 52 | 52 | unreachable; |
| 53 | 53 | } |
std/special/builtin.zig+2-3| ... | ... | @@ -30,7 +30,6 @@ export fn memcpy(noalias dest: ?&u8, noalias src: ?&const u8, n: usize) { |
| 30 | 30 | d[index] = s[index]; |
| 31 | 31 | } |
| 32 | 32 | |
| 33 | // Avoid dragging in the debug safety mechanisms into this .o file. | |
| 34 | pub fn panic(message: []const u8) -> noreturn { | |
| 35 | unreachable; | |
| 33 | export fn __stack_chk_fail() { | |
| 34 | @panic("stack smashing detected"); | |
| 36 | 35 | } |
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. | |
| 3 | pub fn panic(message: []const u8) -> noreturn { | |
| 4 | if (@compileVar("is_test")) { | |
| 5 | @import("std").debug.panic(message); | |
| 6 | } else { | |
| 7 | unreachable; | |
| 8 | } | |
| 9 | } | |
| 10 | ||
| 11 | 1 | const CHAR_BIT = 8; |
| 12 | 2 | const du_int = u64; |
| 13 | 3 | const di_int = i64; |
| ... | ... | @@ -262,7 +252,7 @@ export nakedcc fn __aeabi_uidivmod() { |
| 262 | 252 | unreachable; |
| 263 | 253 | } |
| 264 | 254 | |
| 265 | @setFnVisible(this, false); | |
| 255 | @setGlobalLinkage(__aeabi_uidivmod, GlobalLinkage.Internal); | |
| 266 | 256 | } |
| 267 | 257 | |
| 268 | 258 | export 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 | ||
| 6 | pub 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 | ||
| 5 | export 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" { |
| 12 | 12 | } |
| 13 | 13 | |
| 14 | 14 | export fn disabledExternFn() { |
| 15 | @setFnVisible(this, false); | |
| 15 | @setGlobalLinkage(disabledExternFn, GlobalLinkage.Internal); | |
| 16 | 16 | } |
| 17 | 17 | |
| 18 | 18 | test "callDisabledExternFn" { |
test/run_tests.cpp+12| ... | ... | @@ -1828,6 +1828,18 @@ export fn entry() { |
| 1828 | 1828 | ////////////////////////////////////////////////////////////////////////////// |
| 1829 | 1829 | |
| 1830 | 1830 | static void add_debug_safety_test_cases(void) { |
| 1831 | add_debug_safety_case("calling panic", R"SOURCE( | |
| 1832 | pub fn panic(message: []const u8) -> noreturn { | |
| 1833 | @breakpoint(); | |
| 1834 | while (true) {} | |
| 1835 | } | |
| 1836 | pub fn main(args: [][]u8) -> %void { | |
| 1837 | if (!@compileVar("is_release")) { | |
| 1838 | @panic("oh no"); | |
| 1839 | } | |
| 1840 | } | |
| 1841 | )SOURCE"); | |
| 1842 | ||
| 1831 | 1843 | add_debug_safety_case("out of bounds slice access", R"SOURCE( |
| 1832 | 1844 | pub fn panic(message: []const u8) -> noreturn { |
| 1833 | 1845 | @breakpoint(); |