| author | |
| committer | |
| log | 2a8160e80fc0a03700b83ac9a715f97d1d637f02 |
| tree | ddaac9739e20717789574db9c200151dfb32a96c |
| parent | 3f658879740e3f7aee05be33532b5ba9aaa316bf |
| parent | 9d9201c3b48873e432dc6824d42b5ca96b236daa |
introduces the `@export` builtin function which can be used
in a comptime block to conditionally export a function.
it also allows creation of aliases.
previous export syntax is still allowed.
closes #462
closes #42039 files changed, 1032 insertions(+), 933 deletions(-)
doc/langref.html.in+15-9| ... | ... | @@ -136,6 +136,7 @@ |
| 136 | 136 | <li><a href="#builtin-divFloor">@divFloor</a></li> |
| 137 | 137 | <li><a href="#builtin-divTrunc">@divTrunc</a></li> |
| 138 | 138 | <li><a href="#builtin-embedFile">@embedFile</a></li> |
| 139 | <li><a href="#builtin-export">@export</a></li> | |
| 139 | 140 | <li><a href="#builtin-tagName">@tagName</a></li> |
| 140 | 141 | <li><a href="#builtin-EnumTagType">@EnumTagType</a></li> |
| 141 | 142 | <li><a href="#builtin-errorName">@errorName</a></li> |
| ... | ... | @@ -4368,6 +4369,11 @@ test.zig:6:2: error: found compile log statement |
| 4368 | 4369 | <ul> |
| 4369 | 4370 | <li><a href="#builtin-import">@import</a></li> |
| 4370 | 4371 | </ul> |
| 4372 | <h3 id="builtin-export">@export</h3> | |
| 4373 | <pre><code class="zig">@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) -&gt; []const u8</code></pre> | |
| 4374 | <p> | |
| 4375 | Creates a symbol in the output object file. | |
| 4376 | </p> | |
| 4371 | 4377 | <h3 id="builtin-tagName">@tagName</h3> |
| 4372 | 4378 | <pre><code class="zig">@tagName(value: var) -&gt; []const u8</code></pre> |
| 4373 | 4379 | <p> |
| ... | ... | @@ -5815,13 +5821,15 @@ TopLevelItem = ErrorValueDecl | CompTimeExpression(Block) | TopLevelDecl | TestD |
| 5815 | 5821 | |
| 5816 | 5822 | TestDecl = "test" String Block |
| 5817 | 5823 | |
| 5818 | TopLevelDecl = option(VisibleMod) (FnDef | ExternDecl | GlobalVarDecl | UseDecl) | |
| 5824 | TopLevelDecl = option("pub") (FnDef | ExternDecl | GlobalVarDecl | UseDecl) | |
| 5819 | 5825 | |
| 5820 | 5826 | ErrorValueDecl = "error" Symbol ";" |
| 5821 | 5827 | |
| 5822 | GlobalVarDecl = VariableDeclaration ";" | |
| 5828 | GlobalVarDecl = option("export") VariableDeclaration ";" | |
| 5823 | 5829 | |
| 5824 | VariableDeclaration = option("comptime") ("var" | "const") Symbol option(":" TypeExpr) option("align" "(" Expression ")") "=" Expression | |
| 5830 | LocalVarDecl = option("comptime") VariableDeclaration | |
| 5831 | ||
| 5832 | VariableDeclaration = ("var" | "const") Symbol option(":" TypeExpr) option("align" "(" Expression ")") option("section" "(" Expression ")") "=" Expression | |
| 5825 | 5833 | |
| 5826 | 5834 | ContainerMember = (ContainerField | FnDef | GlobalVarDecl) |
| 5827 | 5835 | |
| ... | ... | @@ -5831,11 +5839,9 @@ UseDecl = "use" Expression ";" |
| 5831 | 5839 | |
| 5832 | 5840 | ExternDecl = "extern" option(String) (FnProto | VariableDeclaration) ";" |
| 5833 | 5841 | |
| 5834 | FnProto = option("coldcc" | "nakedcc" | "stdcallcc") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("-&gt;" TypeExpr) | |
| 5835 | ||
| 5836 | VisibleMod = "pub" | "export" | |
| 5842 | FnProto = option("coldcc" | "nakedcc" | "stdcallcc" | "extern") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("-&gt;" TypeExpr) | |
| 5837 | 5843 | |
| 5838 | FnDef = option("inline" | "extern") FnProto Block | |
| 5844 | FnDef = option("inline" | "export") FnProto Block | |
| 5839 | 5845 | |
| 5840 | 5846 | ParamDeclList = "(" list(ParamDecl, ",") ")" |
| 5841 | 5847 | |
| ... | ... | @@ -5843,7 +5849,7 @@ ParamDecl = option("noalias" | "comptime") option(Symbol ":") (TypeExpr | "...") |
| 5843 | 5849 | |
| 5844 | 5850 | Block = "{" many(Statement) option(Expression) "}" |
| 5845 | 5851 | |
| 5846 | Statement = Label | VariableDeclaration ";" | Defer(Block) | Defer(Expression) ";" | BlockExpression(Block) | Expression ";" | ";" | |
| 5852 | Statement = Label | LocalVarDecl ";" | Defer(Block) | Defer(Expression) ";" | BlockExpression(Block) | Expression ";" | ";" | |
| 5847 | 5853 | |
| 5848 | 5854 | Label = Symbol ":" |
| 5849 | 5855 | |
| ... | ... | @@ -5949,7 +5955,7 @@ StructLiteralField = "." Symbol "=" Expression |
| 5949 | 5955 | |
| 5950 | 5956 | PrefixOp = "!" | "-" | "~" | "*" | ("&amp;" option("align" "(" Expression option(":" Integer ":" Integer) ")" ) option("const") option("volatile")) | "?" | "%" | "%%" | "??" | "-%" |
| 5951 | 5957 | |
| 5952 | PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl | |
| 5958 | PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ("error" "." Symbol) | ContainerDecl | |
| 5953 | 5959 | |
| 5954 | 5960 | ArrayType : "[" option(Expression) "]" option("align" "(" Expression option(":" Integer ":" Integer) ")")) option("const") option("volatile") TypeExpr |
| 5955 | 5961 |
src/all_types.hpp+28-29| ... | ... | @@ -37,6 +37,7 @@ struct IrBasicBlock; |
| 37 | 37 | struct ScopeDecls; |
| 38 | 38 | struct ZigWindowsSDK; |
| 39 | 39 | struct Tld; |
| 40 | struct TldExport; | |
| 40 | 41 | |
| 41 | 42 | struct IrGotoItem { |
| 42 | 43 | AstNode *source_node; |
| ... | ... | @@ -272,7 +273,6 @@ enum ReturnKnowledge { |
| 272 | 273 | enum VisibMod { |
| 273 | 274 | VisibModPrivate, |
| 274 | 275 | VisibModPub, |
| 275 | VisibModExport, | |
| 276 | 276 | }; |
| 277 | 277 | |
| 278 | 278 | enum GlobalLinkageId { |
| ... | ... | @@ -313,11 +313,8 @@ struct TldVar { |
| 313 | 313 | Tld base; |
| 314 | 314 | |
| 315 | 315 | VariableTableEntry *var; |
| 316 | AstNode *set_global_section_node; | |
| 317 | Buf *section_name; | |
| 318 | AstNode *set_global_linkage_node; | |
| 319 | GlobalLinkageId linkage; | |
| 320 | 316 | Buf *extern_lib_name; |
| 317 | Buf *section_name; | |
| 321 | 318 | }; |
| 322 | 319 | |
| 323 | 320 | struct TldFn { |
| ... | ... | @@ -425,6 +422,7 @@ struct AstNodeFnProto { |
| 425 | 422 | AstNode *return_type; |
| 426 | 423 | bool is_var_args; |
| 427 | 424 | bool is_extern; |
| 425 | bool is_export; | |
| 428 | 426 | bool is_inline; |
| 429 | 427 | CallingConvention cc; |
| 430 | 428 | AstNode *fn_def_node; |
| ... | ... | @@ -432,6 +430,8 @@ struct AstNodeFnProto { |
| 432 | 430 | Buf *lib_name; |
| 433 | 431 | // populated if the "align A" is present |
| 434 | 432 | AstNode *align_expr; |
| 433 | // populated if the "section(S)" is present | |
| 434 | AstNode *section_expr; | |
| 435 | 435 | }; |
| 436 | 436 | |
| 437 | 437 | struct AstNodeFnDef { |
| ... | ... | @@ -480,15 +480,18 @@ struct AstNodeVariableDeclaration { |
| 480 | 480 | VisibMod visib_mod; |
| 481 | 481 | Buf *symbol; |
| 482 | 482 | bool is_const; |
| 483 | bool is_inline; | |
| 483 | bool is_comptime; | |
| 484 | bool is_export; | |
| 484 | 485 | bool is_extern; |
| 485 | 486 | // one or both of type and expr will be non null |
| 486 | 487 | AstNode *type; |
| 487 | 488 | AstNode *expr; |
| 488 | 489 | // populated if this is an extern declaration |
| 489 | 490 | Buf *lib_name; |
| 490 | // populated if the "align A" is present | |
| 491 | // populated if the "align(A)" is present | |
| 491 | 492 | AstNode *align_expr; |
| 493 | // populated if the "section(S)" is present | |
| 494 | AstNode *section_expr; | |
| 492 | 495 | }; |
| 493 | 496 | |
| 494 | 497 | struct AstNodeErrorValueDecl { |
| ... | ... | @@ -1177,6 +1180,11 @@ enum FnInline { |
| 1177 | 1180 | FnInlineNever, |
| 1178 | 1181 | }; |
| 1179 | 1182 | |
| 1183 | struct FnExport { | |
| 1184 | Buf name; | |
| 1185 | GlobalLinkageId linkage; | |
| 1186 | }; | |
| 1187 | ||
| 1180 | 1188 | struct FnTableEntry { |
| 1181 | 1189 | LLVMValueRef llvm_value; |
| 1182 | 1190 | const char *llvm_name; |
| ... | ... | @@ -1204,12 +1212,11 @@ struct FnTableEntry { |
| 1204 | 1212 | ZigList<IrInstruction *> alloca_list; |
| 1205 | 1213 | ZigList<VariableTableEntry *> variable_list; |
| 1206 | 1214 | |
| 1207 | AstNode *set_global_section_node; | |
| 1208 | 1215 | Buf *section_name; |
| 1209 | AstNode *set_global_linkage_node; | |
| 1210 | GlobalLinkageId linkage; | |
| 1211 | 1216 | AstNode *set_alignstack_node; |
| 1212 | 1217 | uint32_t alignstack_value; |
| 1218 | ||
| 1219 | ZigList<FnExport> export_list; | |
| 1213 | 1220 | }; |
| 1214 | 1221 | |
| 1215 | 1222 | uint32_t fn_table_entry_hash(FnTableEntry*); |
| ... | ... | @@ -1258,8 +1265,6 @@ enum BuiltinFnId { |
| 1258 | 1265 | BuiltinFnIdSetFloatMode, |
| 1259 | 1266 | BuiltinFnIdTypeName, |
| 1260 | 1267 | BuiltinFnIdCanImplicitCast, |
| 1261 | BuiltinFnIdSetGlobalSection, | |
| 1262 | BuiltinFnIdSetGlobalLinkage, | |
| 1263 | 1268 | BuiltinFnIdPanic, |
| 1264 | 1269 | BuiltinFnIdPtrCast, |
| 1265 | 1270 | BuiltinFnIdBitCast, |
| ... | ... | @@ -1279,6 +1284,7 @@ enum BuiltinFnId { |
| 1279 | 1284 | BuiltinFnIdOpaqueType, |
| 1280 | 1285 | BuiltinFnIdSetAlignStack, |
| 1281 | 1286 | BuiltinFnIdArgType, |
| 1287 | BuiltinFnIdExport, | |
| 1282 | 1288 | }; |
| 1283 | 1289 | |
| 1284 | 1290 | struct BuiltinFnEntry { |
| ... | ... | @@ -1425,7 +1431,7 @@ struct CodeGen { |
| 1425 | 1431 | HashMap<GenericFnTypeId *, FnTableEntry *, generic_fn_type_id_hash, generic_fn_type_id_eql> generic_table; |
| 1426 | 1432 | HashMap<Scope *, IrInstruction *, fn_eval_hash, fn_eval_eql> memoized_fn_eval_table; |
| 1427 | 1433 | HashMap<ZigLLVMFnKey, LLVMValueRef, zig_llvm_fn_key_hash, zig_llvm_fn_key_eql> llvm_fn_table; |
| 1428 | HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> exported_symbol_names; | |
| 1434 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> exported_symbol_names; | |
| 1429 | 1435 | HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes; |
| 1430 | 1436 | |
| 1431 | 1437 | |
| ... | ... | @@ -1886,8 +1892,6 @@ enum IrInstructionId { |
| 1886 | 1892 | IrInstructionIdCheckStatementIsVoid, |
| 1887 | 1893 | IrInstructionIdTypeName, |
| 1888 | 1894 | IrInstructionIdCanImplicitCast, |
| 1889 | IrInstructionIdSetGlobalSection, | |
| 1890 | IrInstructionIdSetGlobalLinkage, | |
| 1891 | 1895 | IrInstructionIdDeclRef, |
| 1892 | 1896 | IrInstructionIdPanic, |
| 1893 | 1897 | IrInstructionIdTagName, |
| ... | ... | @@ -1901,6 +1905,7 @@ enum IrInstructionId { |
| 1901 | 1905 | IrInstructionIdOpaqueType, |
| 1902 | 1906 | IrInstructionIdSetAlignStack, |
| 1903 | 1907 | IrInstructionIdArgType, |
| 1908 | IrInstructionIdExport, | |
| 1904 | 1909 | }; |
| 1905 | 1910 | |
| 1906 | 1911 | struct IrInstruction { |
| ... | ... | @@ -2626,20 +2631,6 @@ struct IrInstructionCanImplicitCast { |
| 2626 | 2631 | IrInstruction *target_value; |
| 2627 | 2632 | }; |
| 2628 | 2633 | |
| 2629 | struct IrInstructionSetGlobalSection { | |
| 2630 | IrInstruction base; | |
| 2631 | ||
| 2632 | Tld *tld; | |
| 2633 | IrInstruction *value; | |
| 2634 | }; | |
| 2635 | ||
| 2636 | struct IrInstructionSetGlobalLinkage { | |
| 2637 | IrInstruction base; | |
| 2638 | ||
| 2639 | Tld *tld; | |
| 2640 | IrInstruction *value; | |
| 2641 | }; | |
| 2642 | ||
| 2643 | 2634 | struct IrInstructionDeclRef { |
| 2644 | 2635 | IrInstruction base; |
| 2645 | 2636 | |
| ... | ... | @@ -2728,6 +2719,14 @@ struct IrInstructionArgType { |
| 2728 | 2719 | IrInstruction *arg_index; |
| 2729 | 2720 | }; |
| 2730 | 2721 | |
| 2722 | struct IrInstructionExport { | |
| 2723 | IrInstruction base; | |
| 2724 | ||
| 2725 | IrInstruction *name; | |
| 2726 | IrInstruction *linkage; | |
| 2727 | IrInstruction *target; | |
| 2728 | }; | |
| 2729 | ||
| 2731 | 2730 | static const size_t slice_ptr_index = 0; |
| 2732 | 2731 | static const size_t slice_len_index = 1; |
| 2733 | 2732 |
src/analyze.cpp+112-51| ... | ... | @@ -1062,7 +1062,7 @@ void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_cou |
| 1062 | 1062 | AstNodeFnProto *fn_proto = &proto_node->data.fn_proto; |
| 1063 | 1063 | |
| 1064 | 1064 | if (fn_proto->cc == CallingConventionUnspecified) { |
| 1065 | bool extern_abi = fn_proto->is_extern || (fn_proto->visib_mod == VisibModExport); | |
| 1065 | bool extern_abi = fn_proto->is_extern || fn_proto->is_export; | |
| 1066 | 1066 | fn_type_id->cc = extern_abi ? CallingConventionC : CallingConventionUnspecified; |
| 1067 | 1067 | } else { |
| 1068 | 1068 | fn_type_id->cc = fn_proto->cc; |
| ... | ... | @@ -1093,6 +1093,38 @@ static bool analyze_const_align(CodeGen *g, Scope *scope, AstNode *node, uint32_ |
| 1093 | 1093 | return true; |
| 1094 | 1094 | } |
| 1095 | 1095 | |
| 1096 | static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **out_buffer) { | |
| 1097 | TypeTableEntry *ptr_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true); | |
| 1098 | TypeTableEntry *str_type = get_slice_type(g, ptr_type); | |
| 1099 | IrInstruction *instr = analyze_const_value(g, scope, node, str_type, nullptr); | |
| 1100 | if (type_is_invalid(instr->value.type)) | |
| 1101 | return false; | |
| 1102 | ||
| 1103 | ConstExprValue *ptr_field = &instr->value.data.x_struct.fields[slice_ptr_index]; | |
| 1104 | ConstExprValue *len_field = &instr->value.data.x_struct.fields[slice_len_index]; | |
| 1105 | ||
| 1106 | assert(ptr_field->data.x_ptr.special == ConstPtrSpecialBaseArray); | |
| 1107 | ConstExprValue *array_val = ptr_field->data.x_ptr.data.base_array.array_val; | |
| 1108 | expand_undef_array(g, array_val); | |
| 1109 | size_t len = bigint_as_unsigned(&len_field->data.x_bigint); | |
| 1110 | Buf *result = buf_alloc(); | |
| 1111 | buf_resize(result, len); | |
| 1112 | for (size_t i = 0; i < len; i += 1) { | |
| 1113 | size_t new_index = ptr_field->data.x_ptr.data.base_array.elem_index + i; | |
| 1114 | ConstExprValue *char_val = &array_val->data.x_array.s_none.elements[new_index]; | |
| 1115 | if (char_val->special == ConstValSpecialUndef) { | |
| 1116 | add_node_error(g, node, buf_sprintf("use of undefined value")); | |
| 1117 | return false; | |
| 1118 | } | |
| 1119 | uint64_t big_c = bigint_as_unsigned(&char_val->data.x_bigint); | |
| 1120 | assert(big_c <= UINT8_MAX); | |
| 1121 | uint8_t c = (uint8_t)big_c; | |
| 1122 | buf_ptr(result)[i] = c; | |
| 1123 | } | |
| 1124 | *out_buffer = result; | |
| 1125 | return true; | |
| 1126 | } | |
| 1127 | ||
| 1096 | 1128 | static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_scope) { |
| 1097 | 1129 | assert(proto_node->type == NodeTypeFnProto); |
| 1098 | 1130 | AstNodeFnProto *fn_proto = &proto_node->data.fn_proto; |
| ... | ... | @@ -2472,7 +2504,7 @@ static void get_fully_qualified_decl_name(Buf *buf, Tld *tld, uint8_t sep) { |
| 2472 | 2504 | buf_append_buf(buf, tld->name); |
| 2473 | 2505 | } |
| 2474 | 2506 | |
| 2475 | FnTableEntry *create_fn_raw(FnInline inline_value, GlobalLinkageId linkage) { | |
| 2507 | FnTableEntry *create_fn_raw(FnInline inline_value) { | |
| 2476 | 2508 | FnTableEntry *fn_entry = allocate<FnTableEntry>(1); |
| 2477 | 2509 | |
| 2478 | 2510 | fn_entry->analyzed_executable.backward_branch_count = &fn_entry->prealloc_bbc; |
| ... | ... | @@ -2480,7 +2512,6 @@ FnTableEntry *create_fn_raw(FnInline inline_value, GlobalLinkageId linkage) { |
| 2480 | 2512 | fn_entry->analyzed_executable.fn_entry = fn_entry; |
| 2481 | 2513 | fn_entry->ir_executable.fn_entry = fn_entry; |
| 2482 | 2514 | fn_entry->fn_inline = inline_value; |
| 2483 | fn_entry->linkage = linkage; | |
| 2484 | 2515 | |
| 2485 | 2516 | return fn_entry; |
| 2486 | 2517 | } |
| ... | ... | @@ -2490,9 +2521,7 @@ FnTableEntry *create_fn(AstNode *proto_node) { |
| 2490 | 2521 | AstNodeFnProto *fn_proto = &proto_node->data.fn_proto; |
| 2491 | 2522 | |
| 2492 | 2523 | FnInline inline_value = fn_proto->is_inline ? FnInlineAlways : FnInlineAuto; |
| 2493 | GlobalLinkageId linkage = (fn_proto->visib_mod == VisibModExport || proto_node->data.fn_proto.is_extern) ? | |
| 2494 | GlobalLinkageIdStrong : GlobalLinkageIdInternal; | |
| 2495 | FnTableEntry *fn_entry = create_fn_raw(inline_value, linkage); | |
| 2524 | FnTableEntry *fn_entry = create_fn_raw(inline_value); | |
| 2496 | 2525 | |
| 2497 | 2526 | fn_entry->proto_node = proto_node; |
| 2498 | 2527 | fn_entry->body_node = (proto_node->data.fn_proto.fn_def_node == nullptr) ? nullptr : |
| ... | ... | @@ -2548,6 +2577,34 @@ TypeTableEntry *get_test_fn_type(CodeGen *g) { |
| 2548 | 2577 | return g->test_fn_type; |
| 2549 | 2578 | } |
| 2550 | 2579 | |
| 2580 | void add_fn_export(CodeGen *g, FnTableEntry *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage, bool ccc) { | |
| 2581 | if (ccc) { | |
| 2582 | if (buf_eql_str(symbol_name, "main") && g->libc_link_lib != nullptr) { | |
| 2583 | g->have_c_main = true; | |
| 2584 | g->windows_subsystem_windows = false; | |
| 2585 | g->windows_subsystem_console = true; | |
| 2586 | } else if (buf_eql_str(symbol_name, "WinMain") && | |
| 2587 | g->zig_target.os == ZigLLVM_Win32) | |
| 2588 | { | |
| 2589 | g->have_winmain = true; | |
| 2590 | g->windows_subsystem_windows = true; | |
| 2591 | g->windows_subsystem_console = false; | |
| 2592 | } else if (buf_eql_str(symbol_name, "WinMainCRTStartup") && | |
| 2593 | g->zig_target.os == ZigLLVM_Win32) | |
| 2594 | { | |
| 2595 | g->have_winmain_crt_startup = true; | |
| 2596 | } else if (buf_eql_str(symbol_name, "DllMainCRTStartup") && | |
| 2597 | g->zig_target.os == ZigLLVM_Win32) | |
| 2598 | { | |
| 2599 | g->have_dllmain_crt_startup = true; | |
| 2600 | } | |
| 2601 | } | |
| 2602 | FnExport *fn_export = fn_table_entry->export_list.add_one(); | |
| 2603 | memset(fn_export, 0, sizeof(FnExport)); | |
| 2604 | buf_init_from_buf(&fn_export->name, symbol_name); | |
| 2605 | fn_export->linkage = linkage; | |
| 2606 | } | |
| 2607 | ||
| 2551 | 2608 | static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { |
| 2552 | 2609 | ImportTableEntry *import = tld_fn->base.import; |
| 2553 | 2610 | AstNode *source_node = tld_fn->base.source_node; |
| ... | ... | @@ -2559,6 +2616,11 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { |
| 2559 | 2616 | FnTableEntry *fn_table_entry = create_fn(source_node); |
| 2560 | 2617 | get_fully_qualified_decl_name(&fn_table_entry->symbol_name, &tld_fn->base, '_'); |
| 2561 | 2618 | |
| 2619 | if (fn_proto->is_export) { | |
| 2620 | bool ccc = (fn_proto->cc == CallingConventionUnspecified || fn_proto->cc == CallingConventionC); | |
| 2621 | add_fn_export(g, fn_table_entry, &fn_table_entry->symbol_name, GlobalLinkageIdStrong, ccc); | |
| 2622 | } | |
| 2623 | ||
| 2562 | 2624 | tld_fn->fn_entry = fn_table_entry; |
| 2563 | 2625 | |
| 2564 | 2626 | if (fn_table_entry->body_node) { |
| ... | ... | @@ -2572,7 +2634,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { |
| 2572 | 2634 | add_node_error(g, param_node, buf_sprintf("missing parameter name")); |
| 2573 | 2635 | } |
| 2574 | 2636 | } |
| 2575 | } else if (fn_table_entry->linkage != GlobalLinkageIdInternal) { | |
| 2637 | } else { | |
| 2576 | 2638 | g->external_prototypes.put_unique(tld_fn->base.name, &tld_fn->base); |
| 2577 | 2639 | } |
| 2578 | 2640 | |
| ... | ... | @@ -2580,6 +2642,15 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { |
| 2580 | 2642 | |
| 2581 | 2643 | fn_table_entry->type_entry = analyze_fn_type(g, source_node, child_scope); |
| 2582 | 2644 | |
| 2645 | if (fn_proto->section_expr != nullptr) { | |
| 2646 | if (fn_table_entry->body_node == nullptr) { | |
| 2647 | add_node_error(g, fn_proto->section_expr, | |
| 2648 | buf_sprintf("cannot set section of external function '%s'", buf_ptr(&fn_table_entry->symbol_name))); | |
| 2649 | } else { | |
| 2650 | analyze_const_string(g, child_scope, fn_proto->section_expr, &fn_table_entry->section_name); | |
| 2651 | } | |
| 2652 | } | |
| 2653 | ||
| 2583 | 2654 | if (fn_table_entry->type_entry->id == TypeTableEntryIdInvalid) { |
| 2584 | 2655 | tld_fn->base.resolution = TldResolutionInvalid; |
| 2585 | 2656 | return; |
| ... | ... | @@ -2594,15 +2665,12 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { |
| 2594 | 2665 | { |
| 2595 | 2666 | if (g->have_pub_main && buf_eql_str(&fn_table_entry->symbol_name, "main")) { |
| 2596 | 2667 | g->main_fn = fn_table_entry; |
| 2597 | ||
| 2598 | if (tld_fn->base.visib_mod != VisibModExport) { | |
| 2599 | TypeTableEntry *err_void = get_error_type(g, g->builtin_types.entry_void); | |
| 2600 | TypeTableEntry *actual_return_type = fn_table_entry->type_entry->data.fn.fn_type_id.return_type; | |
| 2601 | if (actual_return_type != err_void) { | |
| 2602 | add_node_error(g, fn_proto->return_type, | |
| 2603 | buf_sprintf("expected return type of main to be '%%void', instead is '%s'", | |
| 2604 | buf_ptr(&actual_return_type->name))); | |
| 2605 | } | |
| 2668 | TypeTableEntry *err_void = get_error_type(g, g->builtin_types.entry_void); | |
| 2669 | TypeTableEntry *actual_return_type = fn_table_entry->type_entry->data.fn.fn_type_id.return_type; | |
| 2670 | if (actual_return_type != err_void) { | |
| 2671 | add_node_error(g, fn_proto->return_type, | |
| 2672 | buf_sprintf("expected return type of main to be '%%void', instead is '%s'", | |
| 2673 | buf_ptr(&actual_return_type->name))); | |
| 2606 | 2674 | } |
| 2607 | 2675 | } else if ((import->package == g->panic_package || g->have_pub_panic) && |
| 2608 | 2676 | buf_eql_str(&fn_table_entry->symbol_name, "panic")) |
| ... | ... | @@ -2613,7 +2681,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { |
| 2613 | 2681 | } |
| 2614 | 2682 | } |
| 2615 | 2683 | } else if (source_node->type == NodeTypeTestDecl) { |
| 2616 | FnTableEntry *fn_table_entry = create_fn_raw(FnInlineAuto, GlobalLinkageIdStrong); | |
| 2684 | FnTableEntry *fn_table_entry = create_fn_raw(FnInlineAuto); | |
| 2617 | 2685 | |
| 2618 | 2686 | get_fully_qualified_decl_name(&fn_table_entry->symbol_name, &tld_fn->base, '_'); |
| 2619 | 2687 | |
| ... | ... | @@ -2640,17 +2708,23 @@ static void resolve_decl_comptime(CodeGen *g, TldCompTime *tld_comptime) { |
| 2640 | 2708 | } |
| 2641 | 2709 | |
| 2642 | 2710 | static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) { |
| 2643 | if (tld->visib_mod == VisibModExport) { | |
| 2644 | g->resolve_queue.append(tld); | |
| 2711 | bool is_export = false; | |
| 2712 | if (tld->id == TldIdVar) { | |
| 2713 | assert(tld->source_node->type == NodeTypeVariableDeclaration); | |
| 2714 | is_export = tld->source_node->data.variable_declaration.is_export; | |
| 2715 | } else if (tld->id == TldIdFn) { | |
| 2716 | assert(tld->source_node->type == NodeTypeFnProto); | |
| 2717 | is_export = tld->source_node->data.fn_proto.is_export; | |
| 2645 | 2718 | } |
| 2719 | if (is_export) { | |
| 2720 | g->resolve_queue.append(tld); | |
| 2646 | 2721 | |
| 2647 | if (tld->visib_mod == VisibModExport) { | |
| 2648 | auto entry = g->exported_symbol_names.put_unique(tld->name, tld); | |
| 2722 | auto entry = g->exported_symbol_names.put_unique(tld->name, tld->source_node); | |
| 2649 | 2723 | if (entry) { |
| 2650 | Tld *other_tld = entry->value; | |
| 2724 | AstNode *other_source_node = entry->value; | |
| 2651 | 2725 | ErrorMsg *msg = add_node_error(g, tld->source_node, |
| 2652 | 2726 | buf_sprintf("exported symbol collision: '%s'", buf_ptr(tld->name))); |
| 2653 | add_error_note(g, msg, other_tld->source_node, buf_sprintf("other symbol is here")); | |
| 2727 | add_error_note(g, msg, other_source_node, buf_sprintf("other symbol here")); | |
| 2654 | 2728 | } |
| 2655 | 2729 | } |
| 2656 | 2730 | |
| ... | ... | @@ -2729,7 +2803,6 @@ static void preview_comptime_decl(CodeGen *g, AstNode *node, ScopeDecls *decls_s |
| 2729 | 2803 | g->resolve_queue.append(&tld_comptime->base); |
| 2730 | 2804 | } |
| 2731 | 2805 | |
| 2732 | ||
| 2733 | 2806 | void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source_node, |
| 2734 | 2807 | Scope *parent_scope) |
| 2735 | 2808 | { |
| ... | ... | @@ -2985,8 +3058,8 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { |
| 2985 | 3058 | AstNodeVariableDeclaration *var_decl = &source_node->data.variable_declaration; |
| 2986 | 3059 | |
| 2987 | 3060 | bool is_const = var_decl->is_const; |
| 2988 | bool is_export = (tld_var->base.visib_mod == VisibModExport); | |
| 2989 | 3061 | bool is_extern = var_decl->is_extern; |
| 3062 | bool is_export = var_decl->is_export; | |
| 2990 | 3063 | |
| 2991 | 3064 | TypeTableEntry *explicit_type = nullptr; |
| 2992 | 3065 | if (var_decl->type) { |
| ... | ... | @@ -2994,9 +3067,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { |
| 2994 | 3067 | explicit_type = validate_var_type(g, var_decl->type, proposed_type); |
| 2995 | 3068 | } |
| 2996 | 3069 | |
| 2997 | if (is_export && is_extern) { | |
| 2998 | add_node_error(g, source_node, buf_sprintf("variable is both export and extern")); | |
| 2999 | } | |
| 3070 | assert(!is_export || !is_extern); | |
| 3000 | 3071 | |
| 3001 | 3072 | VarLinkage linkage; |
| 3002 | 3073 | if (is_export) { |
| ... | ... | @@ -3007,7 +3078,6 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { |
| 3007 | 3078 | linkage = VarLinkageInternal; |
| 3008 | 3079 | } |
| 3009 | 3080 | |
| 3010 | ||
| 3011 | 3081 | IrInstruction *init_value = nullptr; |
| 3012 | 3082 | |
| 3013 | 3083 | // TODO more validation for types that can't be used for export/extern variables |
| ... | ... | @@ -3056,6 +3126,15 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { |
| 3056 | 3126 | } |
| 3057 | 3127 | } |
| 3058 | 3128 | |
| 3129 | if (var_decl->section_expr != nullptr) { | |
| 3130 | if (var_decl->is_extern) { | |
| 3131 | add_node_error(g, var_decl->section_expr, | |
| 3132 | buf_sprintf("cannot set section of external variable '%s'", buf_ptr(var_decl->symbol))); | |
| 3133 | } else if (!analyze_const_string(g, tld_var->base.parent_scope, var_decl->section_expr, &tld_var->section_name)) { | |
| 3134 | tld_var->section_name = nullptr; | |
| 3135 | } | |
| 3136 | } | |
| 3137 | ||
| 3059 | 3138 | g->global_vars.append(tld_var); |
| 3060 | 3139 | } |
| 3061 | 3140 | |
| ... | ... | @@ -3724,8 +3803,10 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *a |
| 3724 | 3803 | Buf *proto_name = proto_node->data.fn_proto.name; |
| 3725 | 3804 | |
| 3726 | 3805 | bool is_pub = (proto_node->data.fn_proto.visib_mod == VisibModPub); |
| 3806 | bool ok_cc = (proto_node->data.fn_proto.cc == CallingConventionUnspecified || | |
| 3807 | proto_node->data.fn_proto.cc == CallingConventionCold); | |
| 3727 | 3808 | |
| 3728 | if (is_pub) { | |
| 3809 | if (is_pub && ok_cc) { | |
| 3729 | 3810 | if (buf_eql_str(proto_name, "main")) { |
| 3730 | 3811 | g->have_pub_main = true; |
| 3731 | 3812 | g->windows_subsystem_windows = false; |
| ... | ... | @@ -3733,28 +3814,7 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *a |
| 3733 | 3814 | } else if (buf_eql_str(proto_name, "panic")) { |
| 3734 | 3815 | g->have_pub_panic = true; |
| 3735 | 3816 | } |
| 3736 | } else if (proto_node->data.fn_proto.visib_mod == VisibModExport && buf_eql_str(proto_name, "main") && | |
| 3737 | g->libc_link_lib != nullptr) | |
| 3738 | { | |
| 3739 | g->have_c_main = true; | |
| 3740 | g->windows_subsystem_windows = false; | |
| 3741 | g->windows_subsystem_console = true; | |
| 3742 | } else if (proto_node->data.fn_proto.visib_mod == VisibModExport && buf_eql_str(proto_name, "WinMain") && | |
| 3743 | g->zig_target.os == ZigLLVM_Win32) | |
| 3744 | { | |
| 3745 | g->have_winmain = true; | |
| 3746 | g->windows_subsystem_windows = true; | |
| 3747 | g->windows_subsystem_console = false; | |
| 3748 | } else if (proto_node->data.fn_proto.visib_mod == VisibModExport && | |
| 3749 | buf_eql_str(proto_name, "WinMainCRTStartup") && g->zig_target.os == ZigLLVM_Win32) | |
| 3750 | { | |
| 3751 | g->have_winmain_crt_startup = true; | |
| 3752 | } else if (proto_node->data.fn_proto.visib_mod == VisibModExport && | |
| 3753 | buf_eql_str(proto_name, "DllMainCRTStartup") && g->zig_target.os == ZigLLVM_Win32) | |
| 3754 | { | |
| 3755 | g->have_dllmain_crt_startup = true; | |
| 3756 | 3817 | } |
| 3757 | ||
| 3758 | 3818 | } |
| 3759 | 3819 | } |
| 3760 | 3820 | |
| ... | ... | @@ -5445,3 +5505,4 @@ uint32_t type_ptr_hash(const TypeTableEntry *ptr) { |
| 5445 | 5505 | bool type_ptr_eql(const TypeTableEntry *a, const TypeTableEntry *b) { |
| 5446 | 5506 | return a == b; |
| 5447 | 5507 | } |
| 5508 |
src/analyze.hpp+3| ... | ... | @@ -182,4 +182,7 @@ uint32_t get_abi_alignment(CodeGen *g, TypeTableEntry *type_entry); |
| 182 | 182 | TypeTableEntry *get_align_amt_type(CodeGen *g); |
| 183 | 183 | PackageTableEntry *new_anonymous_package(void); |
| 184 | 184 | |
| 185 | Buf *const_value_to_buffer(ConstExprValue *const_val); | |
| 186 | void add_fn_export(CodeGen *g, FnTableEntry *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage, bool ccc); | |
| 187 | ||
| 185 | 188 | #endif |
src/ast_render.cpp+26-2| ... | ... | @@ -78,7 +78,6 @@ static const char *visib_mod_string(VisibMod mod) { |
| 78 | 78 | switch (mod) { |
| 79 | 79 | case VisibModPub: return "pub "; |
| 80 | 80 | case VisibModPrivate: return ""; |
| 81 | case VisibModExport: return "export "; | |
| 82 | 81 | } |
| 83 | 82 | zig_unreachable(); |
| 84 | 83 | } |
| ... | ... | @@ -112,6 +111,10 @@ static const char *extern_string(bool is_extern) { |
| 112 | 111 | return is_extern ? "extern " : ""; |
| 113 | 112 | } |
| 114 | 113 | |
| 114 | static const char *export_string(bool is_export) { | |
| 115 | return is_export ? "export " : ""; | |
| 116 | } | |
| 117 | ||
| 115 | 118 | //static const char *calling_convention_string(CallingConvention cc) { |
| 116 | 119 | // switch (cc) { |
| 117 | 120 | // case CallingConventionUnspecified: return ""; |
| ... | ... | @@ -411,8 +414,9 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 411 | 414 | { |
| 412 | 415 | const char *pub_str = visib_mod_string(node->data.fn_proto.visib_mod); |
| 413 | 416 | const char *extern_str = extern_string(node->data.fn_proto.is_extern); |
| 417 | const char *export_str = export_string(node->data.fn_proto.is_export); | |
| 414 | 418 | const char *inline_str = inline_string(node->data.fn_proto.is_inline); |
| 415 | fprintf(ar->f, "%s%s%sfn", pub_str, inline_str, extern_str); | |
| 419 | fprintf(ar->f, "%s%s%s%sfn", pub_str, inline_str, export_str, extern_str); | |
| 416 | 420 | if (node->data.fn_proto.name != nullptr) { |
| 417 | 421 | fprintf(ar->f, " "); |
| 418 | 422 | print_symbol(ar, node->data.fn_proto.name); |
| ... | ... | @@ -440,6 +444,16 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 440 | 444 | } |
| 441 | 445 | } |
| 442 | 446 | fprintf(ar->f, ")"); |
| 447 | if (node->data.fn_proto.align_expr) { | |
| 448 | fprintf(ar->f, " align("); | |
| 449 | render_node_grouped(ar, node->data.fn_proto.align_expr); | |
| 450 | fprintf(ar->f, ")"); | |
| 451 | } | |
| 452 | if (node->data.fn_proto.section_expr) { | |
| 453 | fprintf(ar->f, " section("); | |
| 454 | render_node_grouped(ar, node->data.fn_proto.section_expr); | |
| 455 | fprintf(ar->f, ")"); | |
| 456 | } | |
| 443 | 457 | |
| 444 | 458 | AstNode *return_type_node = node->data.fn_proto.return_type; |
| 445 | 459 | if (return_type_node != nullptr) { |
| ... | ... | @@ -526,6 +540,16 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { |
| 526 | 540 | fprintf(ar->f, ": "); |
| 527 | 541 | render_node_grouped(ar, node->data.variable_declaration.type); |
| 528 | 542 | } |
| 543 | if (node->data.variable_declaration.align_expr) { | |
| 544 | fprintf(ar->f, "align("); | |
| 545 | render_node_grouped(ar, node->data.variable_declaration.align_expr); | |
| 546 | fprintf(ar->f, ") "); | |
| 547 | } | |
| 548 | if (node->data.variable_declaration.section_expr) { | |
| 549 | fprintf(ar->f, "section("); | |
| 550 | render_node_grouped(ar, node->data.variable_declaration.section_expr); | |
| 551 | fprintf(ar->f, ") "); | |
| 552 | } | |
| 529 | 553 | if (node->data.variable_declaration.expr) { |
| 530 | 554 | fprintf(ar->f, " = "); |
| 531 | 555 | render_node_grouped(ar, node->data.variable_declaration.expr); |
src/codegen.cpp+67-38| ... | ... | @@ -391,24 +391,51 @@ static void add_uwtable_attr(CodeGen *g, LLVMValueRef fn_val) { |
| 391 | 391 | } |
| 392 | 392 | } |
| 393 | 393 | |
| 394 | static LLVMLinkage to_llvm_linkage(GlobalLinkageId id) { | |
| 395 | switch (id) { | |
| 396 | case GlobalLinkageIdInternal: | |
| 397 | return LLVMInternalLinkage; | |
| 398 | case GlobalLinkageIdStrong: | |
| 399 | return LLVMExternalLinkage; | |
| 400 | case GlobalLinkageIdWeak: | |
| 401 | return LLVMWeakODRLinkage; | |
| 402 | case GlobalLinkageIdLinkOnce: | |
| 403 | return LLVMLinkOnceODRLinkage; | |
| 404 | } | |
| 405 | zig_unreachable(); | |
| 406 | } | |
| 407 | ||
| 394 | 408 | static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { |
| 395 | 409 | if (fn_table_entry->llvm_value) |
| 396 | 410 | return fn_table_entry->llvm_value; |
| 397 | 411 | |
| 398 | bool external_linkage = (fn_table_entry->linkage != GlobalLinkageIdInternal); | |
| 399 | Buf *symbol_name = get_mangled_name(g, &fn_table_entry->symbol_name, external_linkage); | |
| 412 | Buf *unmangled_name = &fn_table_entry->symbol_name; | |
| 413 | Buf *symbol_name; | |
| 414 | GlobalLinkageId linkage; | |
| 415 | if (fn_table_entry->body_node == nullptr) { | |
| 416 | symbol_name = unmangled_name; | |
| 417 | linkage = GlobalLinkageIdStrong; | |
| 418 | } else if (fn_table_entry->export_list.length == 0) { | |
| 419 | symbol_name = get_mangled_name(g, unmangled_name, false); | |
| 420 | linkage = GlobalLinkageIdInternal; | |
| 421 | } else { | |
| 422 | FnExport *fn_export = &fn_table_entry->export_list.items[0]; | |
| 423 | symbol_name = &fn_export->name; | |
| 424 | linkage = fn_export->linkage; | |
| 425 | } | |
| 400 | 426 | |
| 427 | bool external_linkage = linkage != GlobalLinkageIdInternal; | |
| 401 | 428 | if (fn_table_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionStdcall && external_linkage && |
| 402 | 429 | g->zig_target.arch.arch == ZigLLVM_x86) |
| 403 | 430 | { |
| 404 | // prevent name mangling | |
| 431 | // prevent llvm name mangling | |
| 405 | 432 | symbol_name = buf_sprintf("\x01_%s", buf_ptr(symbol_name)); |
| 406 | 433 | } |
| 407 | 434 | |
| 408 | 435 | |
| 409 | 436 | TypeTableEntry *fn_type = fn_table_entry->type_entry; |
| 410 | 437 | LLVMTypeRef fn_llvm_type = fn_type->data.fn.raw_type_ref; |
| 411 | if (external_linkage && fn_table_entry->body_node == nullptr) { | |
| 438 | if (fn_table_entry->body_node == nullptr) { | |
| 412 | 439 | LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, buf_ptr(symbol_name)); |
| 413 | 440 | if (existing_llvm_fn) { |
| 414 | 441 | fn_table_entry->llvm_value = LLVMConstBitCast(existing_llvm_fn, LLVMPointerType(fn_llvm_type, 0)); |
| ... | ... | @@ -418,6 +445,12 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { |
| 418 | 445 | } |
| 419 | 446 | } else { |
| 420 | 447 | fn_table_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name), fn_llvm_type); |
| 448 | ||
| 449 | for (size_t i = 1; i < fn_table_entry->export_list.length; i += 1) { | |
| 450 | FnExport *fn_export = &fn_table_entry->export_list.items[i]; | |
| 451 | LLVMAddAlias(g->module, LLVMTypeOf(fn_table_entry->llvm_value), | |
| 452 | fn_table_entry->llvm_value, buf_ptr(&fn_export->name)); | |
| 453 | } | |
| 421 | 454 | } |
| 422 | 455 | fn_table_entry->llvm_name = LLVMGetValueName(fn_table_entry->llvm_value); |
| 423 | 456 | |
| ... | ... | @@ -445,20 +478,10 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { |
| 445 | 478 | } |
| 446 | 479 | } |
| 447 | 480 | |
| 448 | switch (fn_table_entry->linkage) { | |
| 449 | case GlobalLinkageIdInternal: | |
| 450 | LLVMSetLinkage(fn_table_entry->llvm_value, LLVMInternalLinkage); | |
| 451 | LLVMSetUnnamedAddr(fn_table_entry->llvm_value, true); | |
| 452 | break; | |
| 453 | case GlobalLinkageIdStrong: | |
| 454 | LLVMSetLinkage(fn_table_entry->llvm_value, LLVMExternalLinkage); | |
| 455 | break; | |
| 456 | case GlobalLinkageIdWeak: | |
| 457 | LLVMSetLinkage(fn_table_entry->llvm_value, LLVMWeakODRLinkage); | |
| 458 | break; | |
| 459 | case GlobalLinkageIdLinkOnce: | |
| 460 | LLVMSetLinkage(fn_table_entry->llvm_value, LLVMLinkOnceODRLinkage); | |
| 461 | break; | |
| 481 | LLVMSetLinkage(fn_table_entry->llvm_value, to_llvm_linkage(linkage)); | |
| 482 | ||
| 483 | if (linkage == GlobalLinkageIdInternal) { | |
| 484 | LLVMSetUnnamedAddr(fn_table_entry->llvm_value, true); | |
| 462 | 485 | } |
| 463 | 486 | |
| 464 | 487 | if (fn_type->data.fn.fn_type_id.return_type->id == TypeTableEntryIdUnreachable) { |
| ... | ... | @@ -565,7 +588,8 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) { |
| 565 | 588 | bool is_definition = fn_table_entry->body_node != nullptr; |
| 566 | 589 | unsigned flags = 0; |
| 567 | 590 | bool is_optimized = g->build_mode != BuildModeDebug; |
| 568 | bool is_internal_linkage = (fn_table_entry->linkage == GlobalLinkageIdInternal); | |
| 591 | bool is_internal_linkage = (fn_table_entry->body_node != nullptr && | |
| 592 | fn_table_entry->export_list.length == 0); | |
| 569 | 593 | ZigLLVMDISubprogram *subprogram = ZigLLVMCreateFunction(g->dbuilder, |
| 570 | 594 | get_di_scope(g, scope->parent), buf_ptr(&fn_table_entry->symbol_name), "", |
| 571 | 595 | import->di_file, line_number, |
| ... | ... | @@ -3487,8 +3511,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 3487 | 3511 | case IrInstructionIdCheckStatementIsVoid: |
| 3488 | 3512 | case IrInstructionIdTypeName: |
| 3489 | 3513 | case IrInstructionIdCanImplicitCast: |
| 3490 | case IrInstructionIdSetGlobalSection: | |
| 3491 | case IrInstructionIdSetGlobalLinkage: | |
| 3492 | 3514 | case IrInstructionIdDeclRef: |
| 3493 | 3515 | case IrInstructionIdSwitchVar: |
| 3494 | 3516 | case IrInstructionIdOffsetOf: |
| ... | ... | @@ -3499,6 +3521,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 3499 | 3521 | case IrInstructionIdSetAlignStack: |
| 3500 | 3522 | case IrInstructionIdArgType: |
| 3501 | 3523 | case IrInstructionIdTagType: |
| 3524 | case IrInstructionIdExport: | |
| 3502 | 3525 | zig_unreachable(); |
| 3503 | 3526 | case IrInstructionIdReturn: |
| 3504 | 3527 | return ir_render_return(g, executable, (IrInstructionReturn *)instruction); |
| ... | ... | @@ -4969,8 +4992,6 @@ static void define_builtin_fns(CodeGen *g) { |
| 4969 | 4992 | create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int |
| 4970 | 4993 | create_builtin_fn(g, BuiltinFnIdSetDebugSafety, "setDebugSafety", 2); |
| 4971 | 4994 | create_builtin_fn(g, BuiltinFnIdSetFloatMode, "setFloatMode", 2); |
| 4972 | create_builtin_fn(g, BuiltinFnIdSetGlobalSection, "setGlobalSection", 2); | |
| 4973 | create_builtin_fn(g, BuiltinFnIdSetGlobalLinkage, "setGlobalLinkage", 2); | |
| 4974 | 4995 | create_builtin_fn(g, BuiltinFnIdPanic, "panic", 1); |
| 4975 | 4996 | create_builtin_fn(g, BuiltinFnIdPtrCast, "ptrCast", 2); |
| 4976 | 4997 | create_builtin_fn(g, BuiltinFnIdBitCast, "bitCast", 2); |
| ... | ... | @@ -4995,6 +5016,7 @@ static void define_builtin_fns(CodeGen *g) { |
| 4995 | 5016 | create_builtin_fn(g, BuiltinFnIdOpaqueType, "OpaqueType", 0); |
| 4996 | 5017 | create_builtin_fn(g, BuiltinFnIdSetAlignStack, "setAlignStack", 1); |
| 4997 | 5018 | create_builtin_fn(g, BuiltinFnIdArgType, "ArgType", 2); |
| 5019 | create_builtin_fn(g, BuiltinFnIdExport, "export", 3); | |
| 4998 | 5020 | } |
| 4999 | 5021 | |
| 5000 | 5022 | static const char *bool_to_str(bool b) { |
| ... | ... | @@ -5433,6 +5455,27 @@ static void gen_root_source(CodeGen *g) { |
| 5433 | 5455 | assert(g->root_out_name); |
| 5434 | 5456 | assert(g->out_type != OutTypeUnknown); |
| 5435 | 5457 | |
| 5458 | { | |
| 5459 | // Zig has lazy top level definitions. Here we semantically analyze the panic function. | |
| 5460 | ImportTableEntry *import_with_panic; | |
| 5461 | if (g->have_pub_panic) { | |
| 5462 | import_with_panic = g->root_import; | |
| 5463 | } else { | |
| 5464 | g->panic_package = create_panic_pkg(g); | |
| 5465 | import_with_panic = add_special_code(g, g->panic_package, "panic.zig"); | |
| 5466 | } | |
| 5467 | scan_import(g, import_with_panic); | |
| 5468 | Tld *panic_tld = find_decl(g, &import_with_panic->decls_scope->base, buf_create_from_str("panic")); | |
| 5469 | assert(panic_tld != nullptr); | |
| 5470 | resolve_top_level_decl(g, panic_tld, false, nullptr); | |
| 5471 | } | |
| 5472 | ||
| 5473 | ||
| 5474 | if (!g->error_during_imports) { | |
| 5475 | semantic_analyze(g); | |
| 5476 | } | |
| 5477 | report_errors_and_maybe_exit(g); | |
| 5478 | ||
| 5436 | 5479 | if (!g->is_test_build && g->zig_target.os != ZigLLVM_UnknownOS && |
| 5437 | 5480 | !g->have_c_main && !g->have_winmain && !g->have_winmain_crt_startup && |
| 5438 | 5481 | ((g->have_pub_main && g->out_type == OutTypeObj) || g->out_type == OutTypeExe)) |
| ... | ... | @@ -5442,20 +5485,6 @@ static void gen_root_source(CodeGen *g) { |
| 5442 | 5485 | if (g->zig_target.os == ZigLLVM_Win32 && !g->have_dllmain_crt_startup && g->out_type == OutTypeLib) { |
| 5443 | 5486 | g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->root_package), "bootstrap_lib.zig"); |
| 5444 | 5487 | } |
| 5445 | ImportTableEntry *import_with_panic; | |
| 5446 | if (g->have_pub_panic) { | |
| 5447 | import_with_panic = g->root_import; | |
| 5448 | } else { | |
| 5449 | g->panic_package = create_panic_pkg(g); | |
| 5450 | import_with_panic = add_special_code(g, g->panic_package, "panic.zig"); | |
| 5451 | } | |
| 5452 | // Zig has lazy top level definitions. Here we semantically analyze the panic function. | |
| 5453 | { | |
| 5454 | scan_import(g, import_with_panic); | |
| 5455 | Tld *panic_tld = find_decl(g, &import_with_panic->decls_scope->base, buf_create_from_str("panic")); | |
| 5456 | assert(panic_tld != nullptr); | |
| 5457 | resolve_top_level_decl(g, panic_tld, false, nullptr); | |
| 5458 | } | |
| 5459 | 5488 | |
| 5460 | 5489 | if (!g->error_during_imports) { |
| 5461 | 5490 | semantic_analyze(g); |
| ... | ... | @@ -5682,7 +5711,7 @@ static void gen_h_file(CodeGen *g) { |
| 5682 | 5711 | for (size_t fn_def_i = 0; fn_def_i < g->fn_defs.length; fn_def_i += 1) { |
| 5683 | 5712 | FnTableEntry *fn_table_entry = g->fn_defs.at(fn_def_i); |
| 5684 | 5713 | |
| 5685 | if (fn_table_entry->linkage == GlobalLinkageIdInternal) | |
| 5714 | if (fn_table_entry->export_list.length == 0) | |
| 5686 | 5715 | continue; |
| 5687 | 5716 | |
| 5688 | 5717 | FnTypeId *fn_type_id = &fn_table_entry->type_entry->data.fn.fn_type_id; |
src/ir.cpp+235-196| ... | ... | @@ -207,6 +207,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclVar *) { |
| 207 | 207 | return IrInstructionIdDeclVar; |
| 208 | 208 | } |
| 209 | 209 | |
| 210 | static constexpr IrInstructionId ir_instruction_id(IrInstructionExport *) { | |
| 211 | return IrInstructionIdExport; | |
| 212 | } | |
| 213 | ||
| 210 | 214 | static constexpr IrInstructionId ir_instruction_id(IrInstructionLoadPtr *) { |
| 211 | 215 | return IrInstructionIdLoadPtr; |
| 212 | 216 | } |
| ... | ... | @@ -523,14 +527,6 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCanImplicitCast |
| 523 | 527 | return IrInstructionIdCanImplicitCast; |
| 524 | 528 | } |
| 525 | 529 | |
| 526 | static constexpr IrInstructionId ir_instruction_id(IrInstructionSetGlobalSection *) { | |
| 527 | return IrInstructionIdSetGlobalSection; | |
| 528 | } | |
| 529 | ||
| 530 | static constexpr IrInstructionId ir_instruction_id(IrInstructionSetGlobalLinkage *) { | |
| 531 | return IrInstructionIdSetGlobalLinkage; | |
| 532 | } | |
| 533 | ||
| 534 | 530 | static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclRef *) { |
| 535 | 531 | return IrInstructionIdDeclRef; |
| 536 | 532 | } |
| ... | ... | @@ -1205,6 +1201,24 @@ static IrInstruction *ir_build_var_decl_from(IrBuilder *irb, IrInstruction *old_ |
| 1205 | 1201 | return new_instruction; |
| 1206 | 1202 | } |
| 1207 | 1203 | |
| 1204 | static IrInstruction *ir_build_export(IrBuilder *irb, Scope *scope, AstNode *source_node, | |
| 1205 | IrInstruction *name, IrInstruction *target, IrInstruction *linkage) | |
| 1206 | { | |
| 1207 | IrInstructionExport *export_instruction = ir_build_instruction<IrInstructionExport>( | |
| 1208 | irb, scope, source_node); | |
| 1209 | export_instruction->base.value.special = ConstValSpecialStatic; | |
| 1210 | export_instruction->base.value.type = irb->codegen->builtin_types.entry_void; | |
| 1211 | export_instruction->name = name; | |
| 1212 | export_instruction->target = target; | |
| 1213 | export_instruction->linkage = linkage; | |
| 1214 | ||
| 1215 | ir_ref_instruction(name, irb->current_basic_block); | |
| 1216 | ir_ref_instruction(target, irb->current_basic_block); | |
| 1217 | if (linkage) ir_ref_instruction(linkage, irb->current_basic_block); | |
| 1218 | ||
| 1219 | return &export_instruction->base; | |
| 1220 | } | |
| 1221 | ||
| 1208 | 1222 | static IrInstruction *ir_build_load_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *ptr) { |
| 1209 | 1223 | IrInstructionLoadPtr *instruction = ir_build_instruction<IrInstructionLoadPtr>(irb, scope, source_node); |
| 1210 | 1224 | instruction->ptr = ptr; |
| ... | ... | @@ -2159,32 +2173,6 @@ static IrInstruction *ir_build_can_implicit_cast(IrBuilder *irb, Scope *scope, A |
| 2159 | 2173 | return &instruction->base; |
| 2160 | 2174 | } |
| 2161 | 2175 | |
| 2162 | static IrInstruction *ir_build_set_global_section(IrBuilder *irb, Scope *scope, AstNode *source_node, | |
| 2163 | Tld *tld, IrInstruction *value) | |
| 2164 | { | |
| 2165 | IrInstructionSetGlobalSection *instruction = ir_build_instruction<IrInstructionSetGlobalSection>( | |
| 2166 | irb, scope, source_node); | |
| 2167 | instruction->tld = tld; | |
| 2168 | instruction->value = value; | |
| 2169 | ||
| 2170 | ir_ref_instruction(value, irb->current_basic_block); | |
| 2171 | ||
| 2172 | return &instruction->base; | |
| 2173 | } | |
| 2174 | ||
| 2175 | static IrInstruction *ir_build_set_global_linkage(IrBuilder *irb, Scope *scope, AstNode *source_node, | |
| 2176 | Tld *tld, IrInstruction *value) | |
| 2177 | { | |
| 2178 | IrInstructionSetGlobalLinkage *instruction = ir_build_instruction<IrInstructionSetGlobalLinkage>( | |
| 2179 | irb, scope, source_node); | |
| 2180 | instruction->tld = tld; | |
| 2181 | instruction->value = value; | |
| 2182 | ||
| 2183 | ir_ref_instruction(value, irb->current_basic_block); | |
| 2184 | ||
| 2185 | return &instruction->base; | |
| 2186 | } | |
| 2187 | ||
| 2188 | 2176 | static IrInstruction *ir_build_decl_ref(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 2189 | 2177 | Tld *tld, LVal lval) |
| 2190 | 2178 | { |
| ... | ... | @@ -2396,6 +2384,21 @@ static IrInstruction *ir_instruction_declvar_get_dep(IrInstructionDeclVar *instr |
| 2396 | 2384 | return nullptr; |
| 2397 | 2385 | } |
| 2398 | 2386 | |
| 2387 | static IrInstruction *ir_instruction_export_get_dep(IrInstructionExport *instruction, size_t index) { | |
| 2388 | if (index < 1) return instruction->name; | |
| 2389 | index -= 1; | |
| 2390 | ||
| 2391 | if (index < 1) return instruction->target; | |
| 2392 | index -= 1; | |
| 2393 | ||
| 2394 | if (instruction->linkage != nullptr) { | |
| 2395 | if (index < 1) return instruction->linkage; | |
| 2396 | index -= 1; | |
| 2397 | } | |
| 2398 | ||
| 2399 | return nullptr; | |
| 2400 | } | |
| 2401 | ||
| 2399 | 2402 | static IrInstruction *ir_instruction_loadptr_get_dep(IrInstructionLoadPtr *instruction, size_t index) { |
| 2400 | 2403 | switch (index) { |
| 2401 | 2404 | case 0: return instruction->ptr; |
| ... | ... | @@ -2979,20 +2982,6 @@ static IrInstruction *ir_instruction_canimplicitcast_get_dep(IrInstructionCanImp |
| 2979 | 2982 | } |
| 2980 | 2983 | } |
| 2981 | 2984 | |
| 2982 | static IrInstruction *ir_instruction_setglobalsection_get_dep(IrInstructionSetGlobalSection *instruction, size_t index) { | |
| 2983 | switch (index) { | |
| 2984 | case 0: return instruction->value; | |
| 2985 | default: return nullptr; | |
| 2986 | } | |
| 2987 | } | |
| 2988 | ||
| 2989 | static IrInstruction *ir_instruction_setgloballinkage_get_dep(IrInstructionSetGlobalLinkage *instruction, size_t index) { | |
| 2990 | switch (index) { | |
| 2991 | case 0: return instruction->value; | |
| 2992 | default: return nullptr; | |
| 2993 | } | |
| 2994 | } | |
| 2995 | ||
| 2996 | 2985 | static IrInstruction *ir_instruction_declref_get_dep(IrInstructionDeclRef *instruction, size_t index) { |
| 2997 | 2986 | return nullptr; |
| 2998 | 2987 | } |
| ... | ... | @@ -3106,6 +3095,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t |
| 3106 | 3095 | return ir_instruction_binop_get_dep((IrInstructionBinOp *) instruction, index); |
| 3107 | 3096 | case IrInstructionIdDeclVar: |
| 3108 | 3097 | return ir_instruction_declvar_get_dep((IrInstructionDeclVar *) instruction, index); |
| 3098 | case IrInstructionIdExport: | |
| 3099 | return ir_instruction_export_get_dep((IrInstructionExport *) instruction, index); | |
| 3109 | 3100 | case IrInstructionIdLoadPtr: |
| 3110 | 3101 | return ir_instruction_loadptr_get_dep((IrInstructionLoadPtr *) instruction, index); |
| 3111 | 3102 | case IrInstructionIdStorePtr: |
| ... | ... | @@ -3264,10 +3255,6 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t |
| 3264 | 3255 | return ir_instruction_typename_get_dep((IrInstructionTypeName *) instruction, index); |
| 3265 | 3256 | case IrInstructionIdCanImplicitCast: |
| 3266 | 3257 | return ir_instruction_canimplicitcast_get_dep((IrInstructionCanImplicitCast *) instruction, index); |
| 3267 | case IrInstructionIdSetGlobalSection: | |
| 3268 | return ir_instruction_setglobalsection_get_dep((IrInstructionSetGlobalSection *) instruction, index); | |
| 3269 | case IrInstructionIdSetGlobalLinkage: | |
| 3270 | return ir_instruction_setgloballinkage_get_dep((IrInstructionSetGlobalLinkage *) instruction, index); | |
| 3271 | 3258 | case IrInstructionIdDeclRef: |
| 3272 | 3259 | return ir_instruction_declref_get_dep((IrInstructionDeclRef *) instruction, index); |
| 3273 | 3260 | case IrInstructionIdPanic: |
| ... | ... | @@ -4528,39 +4515,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4528 | 4515 | |
| 4529 | 4516 | return ir_build_can_implicit_cast(irb, scope, node, arg0_value, arg1_value); |
| 4530 | 4517 | } |
| 4531 | case BuiltinFnIdSetGlobalSection: | |
| 4532 | case BuiltinFnIdSetGlobalLinkage: | |
| 4533 | { | |
| 4534 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | |
| 4535 | if (arg0_node->type != NodeTypeSymbol) { | |
| 4536 | add_node_error(irb->codegen, arg0_node, buf_sprintf("expected identifier")); | |
| 4537 | return irb->codegen->invalid_instruction; | |
| 4538 | } | |
| 4539 | Buf *variable_name = arg0_node->data.symbol_expr.symbol; | |
| 4540 | Tld *tld = find_decl(irb->codegen, scope, variable_name); | |
| 4541 | if (!tld) { | |
| 4542 | add_node_error(irb->codegen, node, buf_sprintf("use of undeclared identifier '%s'", | |
| 4543 | buf_ptr(variable_name))); | |
| 4544 | return irb->codegen->invalid_instruction; | |
| 4545 | } | |
| 4546 | if (tld->id != TldIdVar && tld->id != TldIdFn) { | |
| 4547 | add_node_error(irb->codegen, node, buf_sprintf("'%s' must be global variable or function", | |
| 4548 | buf_ptr(variable_name))); | |
| 4549 | return irb->codegen->invalid_instruction; | |
| 4550 | } | |
| 4551 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | |
| 4552 | IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); | |
| 4553 | if (arg1_value == irb->codegen->invalid_instruction) | |
| 4554 | return arg1_value; | |
| 4555 | ||
| 4556 | if (builtin_fn->id == BuiltinFnIdSetGlobalSection) { | |
| 4557 | return ir_build_set_global_section(irb, scope, node, tld, arg1_value); | |
| 4558 | } else if (builtin_fn->id == BuiltinFnIdSetGlobalLinkage) { | |
| 4559 | return ir_build_set_global_linkage(irb, scope, node, tld, arg1_value); | |
| 4560 | } else { | |
| 4561 | zig_unreachable(); | |
| 4562 | } | |
| 4563 | } | |
| 4564 | 4518 | case BuiltinFnIdPanic: |
| 4565 | 4519 | { |
| 4566 | 4520 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); |
| ... | ... | @@ -4784,6 +4738,25 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4784 | 4738 | |
| 4785 | 4739 | return ir_build_arg_type(irb, scope, node, arg0_value, arg1_value); |
| 4786 | 4740 | } |
| 4741 | case BuiltinFnIdExport: | |
| 4742 | { | |
| 4743 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); | |
| 4744 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); | |
| 4745 | if (arg0_value == irb->codegen->invalid_instruction) | |
| 4746 | return arg0_value; | |
| 4747 | ||
| 4748 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); | |
| 4749 | IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); | |
| 4750 | if (arg1_value == irb->codegen->invalid_instruction) | |
| 4751 | return arg1_value; | |
| 4752 | ||
| 4753 | AstNode *arg2_node = node->data.fn_call_expr.params.at(2); | |
| 4754 | IrInstruction *arg2_value = ir_gen_node(irb, arg2_node, scope); | |
| 4755 | if (arg2_value == irb->codegen->invalid_instruction) | |
| 4756 | return arg2_value; | |
| 4757 | ||
| 4758 | return ir_build_export(irb, scope, node, arg0_value, arg1_value, arg2_value); | |
| 4759 | } | |
| 4787 | 4760 | } |
| 4788 | 4761 | zig_unreachable(); |
| 4789 | 4762 | } |
| ... | ... | @@ -5087,7 +5060,7 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod |
| 5087 | 5060 | bool is_const = variable_declaration->is_const; |
| 5088 | 5061 | bool is_extern = variable_declaration->is_extern; |
| 5089 | 5062 | IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node, |
| 5090 | ir_should_inline(irb->exec, scope) || variable_declaration->is_inline); | |
| 5063 | ir_should_inline(irb->exec, scope) || variable_declaration->is_comptime); | |
| 5091 | 5064 | VariableTableEntry *var = ir_create_var(irb, node, scope, variable_declaration->symbol, |
| 5092 | 5065 | is_const, is_const, is_shadowable, is_comptime); |
| 5093 | 5066 | // we detect IrInstructionIdDeclVar in gen_block to make sure the next node |
| ... | ... | @@ -5106,6 +5079,11 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod |
| 5106 | 5079 | return align_value; |
| 5107 | 5080 | } |
| 5108 | 5081 | |
| 5082 | if (variable_declaration->section_expr != nullptr) { | |
| 5083 | add_node_error(irb->codegen, variable_declaration->section_expr, | |
| 5084 | buf_sprintf("cannot set section of local variable '%s'", buf_ptr(variable_declaration->symbol))); | |
| 5085 | } | |
| 5086 | ||
| 5109 | 5087 | IrInstruction *init_value = ir_gen_node(irb, variable_declaration->expr, scope); |
| 5110 | 5088 | if (init_value == irb->codegen->invalid_instruction) |
| 5111 | 5089 | return init_value; |
| ... | ... | @@ -6355,6 +6333,10 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop |
| 6355 | 6333 | case NodeTypeSwitchRange: |
| 6356 | 6334 | case NodeTypeStructField: |
| 6357 | 6335 | case NodeTypeLabel: |
| 6336 | case NodeTypeFnDef: | |
| 6337 | case NodeTypeFnDecl: | |
| 6338 | case NodeTypeErrorValueDecl: | |
| 6339 | case NodeTypeTestDecl: | |
| 6358 | 6340 | zig_unreachable(); |
| 6359 | 6341 | case NodeTypeBlock: |
| 6360 | 6342 | return ir_lval_wrap(irb, scope, ir_gen_block(irb, scope, node), lval); |
| ... | ... | @@ -6436,14 +6418,6 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop |
| 6436 | 6418 | return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval); |
| 6437 | 6419 | case NodeTypeFnProto: |
| 6438 | 6420 | return ir_lval_wrap(irb, scope, ir_gen_fn_proto(irb, scope, node), lval); |
| 6439 | case NodeTypeFnDef: | |
| 6440 | zig_panic("TODO IR gen NodeTypeFnDef"); | |
| 6441 | case NodeTypeFnDecl: | |
| 6442 | zig_panic("TODO IR gen NodeTypeFnDecl"); | |
| 6443 | case NodeTypeErrorValueDecl: | |
| 6444 | zig_panic("TODO IR gen NodeTypeErrorValueDecl"); | |
| 6445 | case NodeTypeTestDecl: | |
| 6446 | zig_panic("TODO IR gen NodeTypeTestDecl"); | |
| 6447 | 6421 | } |
| 6448 | 6422 | zig_unreachable(); |
| 6449 | 6423 | } |
| ... | ... | @@ -10481,6 +10455,170 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc |
| 10481 | 10455 | return ira->codegen->builtin_types.entry_void; |
| 10482 | 10456 | } |
| 10483 | 10457 | |
| 10458 | static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) { | |
| 10459 | IrInstruction *name = instruction->name->other; | |
| 10460 | Buf *symbol_name = ir_resolve_str(ira, name); | |
| 10461 | if (symbol_name == nullptr) { | |
| 10462 | return ira->codegen->builtin_types.entry_invalid; | |
| 10463 | } | |
| 10464 | ||
| 10465 | IrInstruction *target = instruction->target->other; | |
| 10466 | if (type_is_invalid(target->value.type)) { | |
| 10467 | return ira->codegen->builtin_types.entry_invalid; | |
| 10468 | } | |
| 10469 | ||
| 10470 | GlobalLinkageId global_linkage_id = GlobalLinkageIdStrong; | |
| 10471 | if (instruction->linkage != nullptr) { | |
| 10472 | IrInstruction *linkage_value = instruction->linkage->other; | |
| 10473 | if (!ir_resolve_global_linkage(ira, linkage_value, &global_linkage_id)) { | |
| 10474 | return ira->codegen->builtin_types.entry_invalid; | |
| 10475 | } | |
| 10476 | } | |
| 10477 | ||
| 10478 | auto entry = ira->codegen->exported_symbol_names.put_unique(symbol_name, instruction->base.source_node); | |
| 10479 | if (entry) { | |
| 10480 | AstNode *other_export_node = entry->value; | |
| 10481 | ErrorMsg *msg = ir_add_error(ira, &instruction->base, | |
| 10482 | buf_sprintf("exported symbol collision: '%s'", buf_ptr(symbol_name))); | |
| 10483 | add_error_note(ira->codegen, msg, other_export_node, buf_sprintf("other symbol is here")); | |
| 10484 | } | |
| 10485 | ||
| 10486 | switch (target->value.type->id) { | |
| 10487 | case TypeTableEntryIdInvalid: | |
| 10488 | case TypeTableEntryIdVar: | |
| 10489 | case TypeTableEntryIdUnreachable: | |
| 10490 | zig_unreachable(); | |
| 10491 | case TypeTableEntryIdFn: { | |
| 10492 | FnTableEntry *fn_entry = target->value.data.x_fn.fn_entry; | |
| 10493 | CallingConvention cc = fn_entry->type_entry->data.fn.fn_type_id.cc; | |
| 10494 | switch (cc) { | |
| 10495 | case CallingConventionUnspecified: { | |
| 10496 | ErrorMsg *msg = ir_add_error(ira, target, | |
| 10497 | buf_sprintf("exported function must specify calling convention")); | |
| 10498 | add_error_note(ira->codegen, msg, fn_entry->proto_node, buf_sprintf("declared here")); | |
| 10499 | } break; | |
| 10500 | case CallingConventionC: | |
| 10501 | case CallingConventionNaked: | |
| 10502 | case CallingConventionCold: | |
| 10503 | case CallingConventionStdcall: | |
| 10504 | add_fn_export(ira->codegen, fn_entry, symbol_name, global_linkage_id, cc == CallingConventionC); | |
| 10505 | break; | |
| 10506 | } | |
| 10507 | } break; | |
| 10508 | case TypeTableEntryIdStruct: | |
| 10509 | if (is_slice(target->value.type)) { | |
| 10510 | ir_add_error(ira, target, | |
| 10511 | buf_sprintf("unable to export value of type '%s'", buf_ptr(&target->value.type->name))); | |
| 10512 | } else if (target->value.type->data.structure.layout != ContainerLayoutExtern) { | |
| 10513 | ErrorMsg *msg = ir_add_error(ira, target, | |
| 10514 | buf_sprintf("exported struct value must be declared extern")); | |
| 10515 | add_error_note(ira->codegen, msg, target->value.type->data.structure.decl_node, buf_sprintf("declared here")); | |
| 10516 | } | |
| 10517 | break; | |
| 10518 | case TypeTableEntryIdUnion: | |
| 10519 | if (target->value.type->data.unionation.layout != ContainerLayoutExtern) { | |
| 10520 | ErrorMsg *msg = ir_add_error(ira, target, | |
| 10521 | buf_sprintf("exported union value must be declared extern")); | |
| 10522 | add_error_note(ira->codegen, msg, target->value.type->data.unionation.decl_node, buf_sprintf("declared here")); | |
| 10523 | } | |
| 10524 | break; | |
| 10525 | case TypeTableEntryIdEnum: | |
| 10526 | if (target->value.type->data.enumeration.layout != ContainerLayoutExtern) { | |
| 10527 | ErrorMsg *msg = ir_add_error(ira, target, | |
| 10528 | buf_sprintf("exported enum value must be declared extern")); | |
| 10529 | add_error_note(ira->codegen, msg, target->value.type->data.enumeration.decl_node, buf_sprintf("declared here")); | |
| 10530 | } | |
| 10531 | break; | |
| 10532 | case TypeTableEntryIdMetaType: { | |
| 10533 | TypeTableEntry *type_value = target->value.data.x_type; | |
| 10534 | switch (type_value->id) { | |
| 10535 | case TypeTableEntryIdInvalid: | |
| 10536 | case TypeTableEntryIdVar: | |
| 10537 | zig_unreachable(); | |
| 10538 | case TypeTableEntryIdStruct: | |
| 10539 | if (is_slice(type_value)) { | |
| 10540 | ir_add_error(ira, target, | |
| 10541 | buf_sprintf("unable to export type '%s'", buf_ptr(&type_value->name))); | |
| 10542 | } else if (type_value->data.structure.layout != ContainerLayoutExtern) { | |
| 10543 | ErrorMsg *msg = ir_add_error(ira, target, | |
| 10544 | buf_sprintf("exported struct must be declared extern")); | |
| 10545 | add_error_note(ira->codegen, msg, type_value->data.structure.decl_node, buf_sprintf("declared here")); | |
| 10546 | } | |
| 10547 | break; | |
| 10548 | case TypeTableEntryIdUnion: | |
| 10549 | if (type_value->data.unionation.layout != ContainerLayoutExtern) { | |
| 10550 | ErrorMsg *msg = ir_add_error(ira, target, | |
| 10551 | buf_sprintf("exported union must be declared extern")); | |
| 10552 | add_error_note(ira->codegen, msg, type_value->data.unionation.decl_node, buf_sprintf("declared here")); | |
| 10553 | } | |
| 10554 | break; | |
| 10555 | case TypeTableEntryIdEnum: | |
| 10556 | if (type_value->data.enumeration.layout != ContainerLayoutExtern) { | |
| 10557 | ErrorMsg *msg = ir_add_error(ira, target, | |
| 10558 | buf_sprintf("exported enum must be declared extern")); | |
| 10559 | add_error_note(ira->codegen, msg, type_value->data.enumeration.decl_node, buf_sprintf("declared here")); | |
| 10560 | } | |
| 10561 | break; | |
| 10562 | case TypeTableEntryIdFn: { | |
| 10563 | if (type_value->data.fn.fn_type_id.cc == CallingConventionUnspecified) { | |
| 10564 | ir_add_error(ira, target, | |
| 10565 | buf_sprintf("exported function type must specify calling convention")); | |
| 10566 | } | |
| 10567 | } break; | |
| 10568 | case TypeTableEntryIdInt: | |
| 10569 | case TypeTableEntryIdFloat: | |
| 10570 | case TypeTableEntryIdPointer: | |
| 10571 | case TypeTableEntryIdArray: | |
| 10572 | case TypeTableEntryIdBool: | |
| 10573 | break; | |
| 10574 | case TypeTableEntryIdMetaType: | |
| 10575 | case TypeTableEntryIdVoid: | |
| 10576 | case TypeTableEntryIdUnreachable: | |
| 10577 | case TypeTableEntryIdNumLitFloat: | |
| 10578 | case TypeTableEntryIdNumLitInt: | |
| 10579 | case TypeTableEntryIdUndefLit: | |
| 10580 | case TypeTableEntryIdNullLit: | |
| 10581 | case TypeTableEntryIdMaybe: | |
| 10582 | case TypeTableEntryIdErrorUnion: | |
| 10583 | case TypeTableEntryIdPureError: | |
| 10584 | case TypeTableEntryIdNamespace: | |
| 10585 | case TypeTableEntryIdBlock: | |
| 10586 | case TypeTableEntryIdBoundFn: | |
| 10587 | case TypeTableEntryIdArgTuple: | |
| 10588 | case TypeTableEntryIdOpaque: | |
| 10589 | ir_add_error(ira, target, | |
| 10590 | buf_sprintf("invalid export target '%s'", buf_ptr(&type_value->name))); | |
| 10591 | break; | |
| 10592 | } | |
| 10593 | } break; | |
| 10594 | case TypeTableEntryIdVoid: | |
| 10595 | case TypeTableEntryIdBool: | |
| 10596 | case TypeTableEntryIdInt: | |
| 10597 | case TypeTableEntryIdFloat: | |
| 10598 | case TypeTableEntryIdPointer: | |
| 10599 | case TypeTableEntryIdArray: | |
| 10600 | case TypeTableEntryIdNumLitFloat: | |
| 10601 | case TypeTableEntryIdNumLitInt: | |
| 10602 | case TypeTableEntryIdUndefLit: | |
| 10603 | case TypeTableEntryIdNullLit: | |
| 10604 | case TypeTableEntryIdMaybe: | |
| 10605 | case TypeTableEntryIdErrorUnion: | |
| 10606 | case TypeTableEntryIdPureError: | |
| 10607 | zig_panic("TODO export const value of type %s", buf_ptr(&target->value.type->name)); | |
| 10608 | case TypeTableEntryIdNamespace: | |
| 10609 | case TypeTableEntryIdBlock: | |
| 10610 | case TypeTableEntryIdBoundFn: | |
| 10611 | case TypeTableEntryIdArgTuple: | |
| 10612 | case TypeTableEntryIdOpaque: | |
| 10613 | ir_add_error(ira, target, | |
| 10614 | buf_sprintf("invalid export target type '%s'", buf_ptr(&target->value.type->name))); | |
| 10615 | break; | |
| 10616 | } | |
| 10617 | ||
| 10618 | ir_build_const_from(ira, &instruction->base); | |
| 10619 | return ira->codegen->builtin_types.entry_void; | |
| 10620 | } | |
| 10621 | ||
| 10484 | 10622 | static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node, |
| 10485 | 10623 | IrInstruction *arg, Scope **exec_scope, size_t *next_proto_i) |
| 10486 | 10624 | { |
| ... | ... | @@ -12399,102 +12537,6 @@ static TypeTableEntry *ir_analyze_instruction_ptr_type_child(IrAnalyze *ira, |
| 12399 | 12537 | return ira->codegen->builtin_types.entry_type; |
| 12400 | 12538 | } |
| 12401 | 12539 | |
| 12402 | static TypeTableEntry *ir_analyze_instruction_set_global_section(IrAnalyze *ira, | |
| 12403 | IrInstructionSetGlobalSection *instruction) | |
| 12404 | { | |
| 12405 | Tld *tld = instruction->tld; | |
| 12406 | IrInstruction *section_value = instruction->value->other; | |
| 12407 | ||
| 12408 | resolve_top_level_decl(ira->codegen, tld, true, instruction->base.source_node); | |
| 12409 | if (tld->resolution == TldResolutionInvalid) | |
| 12410 | return ira->codegen->builtin_types.entry_invalid; | |
| 12411 | ||
| 12412 | Buf *section_name = ir_resolve_str(ira, section_value); | |
| 12413 | if (!section_name) | |
| 12414 | return ira->codegen->builtin_types.entry_invalid; | |
| 12415 | ||
| 12416 | AstNode **set_global_section_node; | |
| 12417 | Buf **section_name_ptr; | |
| 12418 | if (tld->id == TldIdVar) { | |
| 12419 | TldVar *tld_var = (TldVar *)tld; | |
| 12420 | set_global_section_node = &tld_var->set_global_section_node; | |
| 12421 | section_name_ptr = &tld_var->section_name; | |
| 12422 | ||
| 12423 | if (tld_var->var->linkage == VarLinkageExternal) { | |
| 12424 | ErrorMsg *msg = ir_add_error(ira, &instruction->base, | |
| 12425 | buf_sprintf("cannot set section of external variable '%s'", buf_ptr(&tld_var->var->name))); | |
| 12426 | add_error_note(ira->codegen, msg, tld->source_node, buf_sprintf("declared here")); | |
| 12427 | return ira->codegen->builtin_types.entry_invalid; | |
| 12428 | } | |
| 12429 | } else if (tld->id == TldIdFn) { | |
| 12430 | TldFn *tld_fn = (TldFn *)tld; | |
| 12431 | FnTableEntry *fn_entry = tld_fn->fn_entry; | |
| 12432 | set_global_section_node = &fn_entry->set_global_section_node; | |
| 12433 | section_name_ptr = &fn_entry->section_name; | |
| 12434 | ||
| 12435 | if (fn_entry->def_scope == nullptr) { | |
| 12436 | ErrorMsg *msg = ir_add_error(ira, &instruction->base, | |
| 12437 | buf_sprintf("cannot set section of external function '%s'", buf_ptr(&fn_entry->symbol_name))); | |
| 12438 | add_error_note(ira->codegen, msg, tld->source_node, buf_sprintf("declared here")); | |
| 12439 | return ira->codegen->builtin_types.entry_invalid; | |
| 12440 | } | |
| 12441 | } else { | |
| 12442 | // error is caught in pass1 IR gen | |
| 12443 | zig_unreachable(); | |
| 12444 | } | |
| 12445 | ||
| 12446 | AstNode *source_node = instruction->base.source_node; | |
| 12447 | if (*set_global_section_node) { | |
| 12448 | ErrorMsg *msg = ir_add_error_node(ira, source_node, buf_sprintf("section set twice")); | |
| 12449 | add_error_note(ira->codegen, msg, *set_global_section_node, buf_sprintf("first set here")); | |
| 12450 | return ira->codegen->builtin_types.entry_invalid; | |
| 12451 | } | |
| 12452 | *set_global_section_node = source_node; | |
| 12453 | *section_name_ptr = section_name; | |
| 12454 | ||
| 12455 | ir_build_const_from(ira, &instruction->base); | |
| 12456 | return ira->codegen->builtin_types.entry_void; | |
| 12457 | } | |
| 12458 | ||
| 12459 | static TypeTableEntry *ir_analyze_instruction_set_global_linkage(IrAnalyze *ira, | |
| 12460 | IrInstructionSetGlobalLinkage *instruction) | |
| 12461 | { | |
| 12462 | Tld *tld = instruction->tld; | |
| 12463 | IrInstruction *linkage_value = instruction->value->other; | |
| 12464 | ||
| 12465 | GlobalLinkageId linkage_scalar; | |
| 12466 | if (!ir_resolve_global_linkage(ira, linkage_value, &linkage_scalar)) | |
| 12467 | return ira->codegen->builtin_types.entry_invalid; | |
| 12468 | ||
| 12469 | AstNode **set_global_linkage_node; | |
| 12470 | GlobalLinkageId *dest_linkage_ptr; | |
| 12471 | if (tld->id == TldIdVar) { | |
| 12472 | TldVar *tld_var = (TldVar *)tld; | |
| 12473 | set_global_linkage_node = &tld_var->set_global_linkage_node; | |
| 12474 | dest_linkage_ptr = &tld_var->linkage; | |
| 12475 | } else if (tld->id == TldIdFn) { | |
| 12476 | TldFn *tld_fn = (TldFn *)tld; | |
| 12477 | FnTableEntry *fn_entry = tld_fn->fn_entry; | |
| 12478 | set_global_linkage_node = &fn_entry->set_global_linkage_node; | |
| 12479 | dest_linkage_ptr = &fn_entry->linkage; | |
| 12480 | } else { | |
| 12481 | // error is caught in pass1 IR gen | |
| 12482 | zig_unreachable(); | |
| 12483 | } | |
| 12484 | ||
| 12485 | AstNode *source_node = instruction->base.source_node; | |
| 12486 | if (*set_global_linkage_node) { | |
| 12487 | ErrorMsg *msg = ir_add_error_node(ira, source_node, buf_sprintf("linkage set twice")); | |
| 12488 | add_error_note(ira->codegen, msg, *set_global_linkage_node, buf_sprintf("first set here")); | |
| 12489 | return ira->codegen->builtin_types.entry_invalid; | |
| 12490 | } | |
| 12491 | *set_global_linkage_node = source_node; | |
| 12492 | *dest_linkage_ptr = linkage_scalar; | |
| 12493 | ||
| 12494 | ir_build_const_from(ira, &instruction->base); | |
| 12495 | return ira->codegen->builtin_types.entry_void; | |
| 12496 | } | |
| 12497 | ||
| 12498 | 12540 | static TypeTableEntry *ir_analyze_instruction_set_debug_safety(IrAnalyze *ira, |
| 12499 | 12541 | IrInstructionSetDebugSafety *set_debug_safety_instruction) |
| 12500 | 12542 | { |
| ... | ... | @@ -16165,10 +16207,6 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 16165 | 16207 | return ir_analyze_instruction_to_ptr_type(ira, (IrInstructionToPtrType *)instruction); |
| 16166 | 16208 | case IrInstructionIdPtrTypeChild: |
| 16167 | 16209 | return ir_analyze_instruction_ptr_type_child(ira, (IrInstructionPtrTypeChild *)instruction); |
| 16168 | case IrInstructionIdSetGlobalSection: | |
| 16169 | return ir_analyze_instruction_set_global_section(ira, (IrInstructionSetGlobalSection *)instruction); | |
| 16170 | case IrInstructionIdSetGlobalLinkage: | |
| 16171 | return ir_analyze_instruction_set_global_linkage(ira, (IrInstructionSetGlobalLinkage *)instruction); | |
| 16172 | 16210 | case IrInstructionIdSetDebugSafety: |
| 16173 | 16211 | return ir_analyze_instruction_set_debug_safety(ira, (IrInstructionSetDebugSafety *)instruction); |
| 16174 | 16212 | case IrInstructionIdSetFloatMode: |
| ... | ... | @@ -16311,6 +16349,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 16311 | 16349 | return ir_analyze_instruction_arg_type(ira, (IrInstructionArgType *)instruction); |
| 16312 | 16350 | case IrInstructionIdTagType: |
| 16313 | 16351 | return ir_analyze_instruction_tag_type(ira, (IrInstructionTagType *)instruction); |
| 16352 | case IrInstructionIdExport: | |
| 16353 | return ir_analyze_instruction_export(ira, (IrInstructionExport *)instruction); | |
| 16314 | 16354 | } |
| 16315 | 16355 | zig_unreachable(); |
| 16316 | 16356 | } |
| ... | ... | @@ -16418,12 +16458,11 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 16418 | 16458 | case IrInstructionIdOverflowOp: // TODO when we support multiple returns this can be side effect free |
| 16419 | 16459 | case IrInstructionIdCheckSwitchProngs: |
| 16420 | 16460 | case IrInstructionIdCheckStatementIsVoid: |
| 16421 | case IrInstructionIdSetGlobalSection: | |
| 16422 | case IrInstructionIdSetGlobalLinkage: | |
| 16423 | 16461 | case IrInstructionIdPanic: |
| 16424 | 16462 | case IrInstructionIdSetEvalBranchQuota: |
| 16425 | 16463 | case IrInstructionIdPtrTypeOf: |
| 16426 | 16464 | case IrInstructionIdSetAlignStack: |
| 16465 | case IrInstructionIdExport: | |
| 16427 | 16466 | return true; |
| 16428 | 16467 | case IrInstructionIdPhi: |
| 16429 | 16468 | case IrInstructionIdUnOp: |
src/ir_print.cpp+21-19| ... | ... | @@ -899,19 +899,6 @@ static void ir_print_ptr_type_of(IrPrint *irp, IrInstructionPtrTypeOf *instructi |
| 899 | 899 | ir_print_other_instruction(irp, instruction->child_type); |
| 900 | 900 | } |
| 901 | 901 | |
| 902 | static void ir_print_set_global_section(IrPrint *irp, IrInstructionSetGlobalSection *instruction) { | |
| 903 | fprintf(irp->f, "@setGlobalSection(%s,", buf_ptr(instruction->tld->name)); | |
| 904 | ir_print_other_instruction(irp, instruction->value); | |
| 905 | fprintf(irp->f, ")"); | |
| 906 | } | |
| 907 | ||
| 908 | static void ir_print_set_global_linkage(IrPrint *irp, IrInstructionSetGlobalLinkage *instruction) { | |
| 909 | fprintf(irp->f, "@setGlobalLinkage(%s,", buf_ptr(instruction->tld->name)); | |
| 910 | ir_print_other_instruction(irp, instruction->value); | |
| 911 | fprintf(irp->f, ")"); | |
| 912 | } | |
| 913 | ||
| 914 | ||
| 915 | 902 | static void ir_print_decl_ref(IrPrint *irp, IrInstructionDeclRef *instruction) { |
| 916 | 903 | const char *ptr_str = instruction->lval.is_ptr ? "ptr " : ""; |
| 917 | 904 | const char *const_str = instruction->lval.is_const ? "const " : ""; |
| ... | ... | @@ -991,6 +978,24 @@ static void ir_print_enum_tag_type(IrPrint *irp, IrInstructionTagType *instructi |
| 991 | 978 | fprintf(irp->f, ")"); |
| 992 | 979 | } |
| 993 | 980 | |
| 981 | static void ir_print_export(IrPrint *irp, IrInstructionExport *instruction) { | |
| 982 | if (instruction->linkage == nullptr) { | |
| 983 | fprintf(irp->f, "@export("); | |
| 984 | ir_print_other_instruction(irp, instruction->name); | |
| 985 | fprintf(irp->f, ","); | |
| 986 | ir_print_other_instruction(irp, instruction->target); | |
| 987 | fprintf(irp->f, ")"); | |
| 988 | } else { | |
| 989 | fprintf(irp->f, "@exportWithLinkage("); | |
| 990 | ir_print_other_instruction(irp, instruction->name); | |
| 991 | fprintf(irp->f, ","); | |
| 992 | ir_print_other_instruction(irp, instruction->target); | |
| 993 | fprintf(irp->f, ","); | |
| 994 | ir_print_other_instruction(irp, instruction->linkage); | |
| 995 | fprintf(irp->f, ")"); | |
| 996 | } | |
| 997 | } | |
| 998 | ||
| 994 | 999 | |
| 995 | 1000 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 996 | 1001 | ir_print_prefix(irp, instruction); |
| ... | ... | @@ -1267,12 +1272,6 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1267 | 1272 | case IrInstructionIdPtrTypeOf: |
| 1268 | 1273 | ir_print_ptr_type_of(irp, (IrInstructionPtrTypeOf *)instruction); |
| 1269 | 1274 | break; |
| 1270 | case IrInstructionIdSetGlobalSection: | |
| 1271 | ir_print_set_global_section(irp, (IrInstructionSetGlobalSection *)instruction); | |
| 1272 | break; | |
| 1273 | case IrInstructionIdSetGlobalLinkage: | |
| 1274 | ir_print_set_global_linkage(irp, (IrInstructionSetGlobalLinkage *)instruction); | |
| 1275 | break; | |
| 1276 | 1275 | case IrInstructionIdDeclRef: |
| 1277 | 1276 | ir_print_decl_ref(irp, (IrInstructionDeclRef *)instruction); |
| 1278 | 1277 | break; |
| ... | ... | @@ -1306,6 +1305,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1306 | 1305 | case IrInstructionIdTagType: |
| 1307 | 1306 | ir_print_enum_tag_type(irp, (IrInstructionTagType *)instruction); |
| 1308 | 1307 | break; |
| 1308 | case IrInstructionIdExport: | |
| 1309 | ir_print_export(irp, (IrInstructionExport *)instruction); | |
| 1310 | break; | |
| 1309 | 1311 | } |
| 1310 | 1312 | fprintf(irp->f, "\n"); |
| 1311 | 1313 | } |
src/parser.cpp+114-53| ... | ... | @@ -676,7 +676,7 @@ static AstNode *ast_parse_comptime_expr(ParseContext *pc, size_t *token_index, b |
| 676 | 676 | } |
| 677 | 677 | |
| 678 | 678 | /* |
| 679 | PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl | |
| 679 | PrimaryExpression = Integer | Float | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression(BlockOrExpression) | Symbol | ("@" Symbol FnCallExpression) | ArrayType | FnProto | AsmExpression | ("error" "." Symbol) | ContainerDecl | |
| 680 | 680 | KeywordLiteral = "true" | "false" | "null" | "continue" | "undefined" | "error" | "this" | "unreachable" |
| 681 | 681 | */ |
| 682 | 682 | static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory) { |
| ... | ... | @@ -740,9 +740,21 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo |
| 740 | 740 | return node; |
| 741 | 741 | } else if (token->id == TokenIdAtSign) { |
| 742 | 742 | *token_index += 1; |
| 743 | Token *name_tok = ast_eat_token(pc, token_index, TokenIdSymbol); | |
| 743 | Token *name_tok = &pc->tokens->at(*token_index); | |
| 744 | Buf *name_buf; | |
| 745 | if (name_tok->id == TokenIdKeywordExport) { | |
| 746 | name_buf = buf_create_from_str("export"); | |
| 747 | *token_index += 1; | |
| 748 | } else if (name_tok->id == TokenIdSymbol) { | |
| 749 | name_buf = token_buf(name_tok); | |
| 750 | *token_index += 1; | |
| 751 | } else { | |
| 752 | ast_expect_token(pc, name_tok, TokenIdSymbol); | |
| 753 | zig_unreachable(); | |
| 754 | } | |
| 755 | ||
| 744 | 756 | AstNode *name_node = ast_create_node(pc, NodeTypeSymbol, name_tok); |
| 745 | name_node->data.symbol_expr.symbol = token_buf(name_tok); | |
| 757 | name_node->data.symbol_expr.symbol = name_buf; | |
| 746 | 758 | |
| 747 | 759 | AstNode *node = ast_create_node(pc, NodeTypeFnCallExpr, token); |
| 748 | 760 | node->data.fn_call_expr.fn_ref_expr = name_node; |
| ... | ... | @@ -791,13 +803,6 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo |
| 791 | 803 | if (container_decl) |
| 792 | 804 | return container_decl; |
| 793 | 805 | |
| 794 | if (token->id == TokenIdKeywordExtern) { | |
| 795 | *token_index += 1; | |
| 796 | AstNode *node = ast_parse_fn_proto(pc, token_index, true, VisibModPrivate); | |
| 797 | node->data.fn_proto.is_extern = true; | |
| 798 | return node; | |
| 799 | } | |
| 800 | ||
| 801 | 806 | if (!mandatory) |
| 802 | 807 | return nullptr; |
| 803 | 808 | |
| ... | ... | @@ -1534,38 +1539,20 @@ static AstNode *ast_parse_defer_expr(ParseContext *pc, size_t *token_index) { |
| 1534 | 1539 | } |
| 1535 | 1540 | |
| 1536 | 1541 | /* |
| 1537 | VariableDeclaration = option("comptime") ("var" | "const") Symbol option(":" TypeExpr) option("align" "(" Expression ")") "=" Expression | |
| 1542 | VariableDeclaration = ("var" | "const") Symbol option(":" TypeExpr) option("align" "(" Expression ")") "=" Expression | |
| 1538 | 1543 | */ |
| 1539 | 1544 | static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *token_index, bool mandatory, |
| 1540 | VisibMod visib_mod) | |
| 1545 | VisibMod visib_mod, bool is_comptime, bool is_export) | |
| 1541 | 1546 | { |
| 1542 | 1547 | Token *first_token = &pc->tokens->at(*token_index); |
| 1543 | 1548 | Token *var_token; |
| 1544 | 1549 | |
| 1545 | 1550 | bool is_const; |
| 1546 | bool is_comptime; | |
| 1547 | if (first_token->id == TokenIdKeywordCompTime) { | |
| 1548 | is_comptime = true; | |
| 1549 | var_token = &pc->tokens->at(*token_index + 1); | |
| 1550 | ||
| 1551 | if (var_token->id == TokenIdKeywordVar) { | |
| 1552 | is_const = false; | |
| 1553 | } else if (var_token->id == TokenIdKeywordConst) { | |
| 1554 | is_const = true; | |
| 1555 | } else if (mandatory) { | |
| 1556 | ast_invalid_token_error(pc, var_token); | |
| 1557 | } else { | |
| 1558 | return nullptr; | |
| 1559 | } | |
| 1560 | ||
| 1561 | *token_index += 2; | |
| 1562 | } else if (first_token->id == TokenIdKeywordVar) { | |
| 1563 | is_comptime = false; | |
| 1551 | if (first_token->id == TokenIdKeywordVar) { | |
| 1564 | 1552 | is_const = false; |
| 1565 | 1553 | var_token = first_token; |
| 1566 | 1554 | *token_index += 1; |
| 1567 | 1555 | } else if (first_token->id == TokenIdKeywordConst) { |
| 1568 | is_comptime = false; | |
| 1569 | 1556 | is_const = true; |
| 1570 | 1557 | var_token = first_token; |
| 1571 | 1558 | *token_index += 1; |
| ... | ... | @@ -1577,7 +1564,8 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *to |
| 1577 | 1564 | |
| 1578 | 1565 | AstNode *node = ast_create_node(pc, NodeTypeVariableDeclaration, var_token); |
| 1579 | 1566 | |
| 1580 | node->data.variable_declaration.is_inline = is_comptime; | |
| 1567 | node->data.variable_declaration.is_comptime = is_comptime; | |
| 1568 | node->data.variable_declaration.is_export = is_export; | |
| 1581 | 1569 | node->data.variable_declaration.is_const = is_const; |
| 1582 | 1570 | node->data.variable_declaration.visib_mod = visib_mod; |
| 1583 | 1571 | |
| ... | ... | @@ -1600,6 +1588,14 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *to |
| 1600 | 1588 | next_token = &pc->tokens->at(*token_index); |
| 1601 | 1589 | } |
| 1602 | 1590 | |
| 1591 | if (next_token->id == TokenIdKeywordSection) { | |
| 1592 | *token_index += 1; | |
| 1593 | ast_eat_token(pc, token_index, TokenIdLParen); | |
| 1594 | node->data.variable_declaration.section_expr = ast_parse_expression(pc, token_index, true); | |
| 1595 | ast_eat_token(pc, token_index, TokenIdRParen); | |
| 1596 | next_token = &pc->tokens->at(*token_index); | |
| 1597 | } | |
| 1598 | ||
| 1603 | 1599 | if (next_token->id == TokenIdEq) { |
| 1604 | 1600 | *token_index += 1; |
| 1605 | 1601 | node->data.variable_declaration.expr = ast_parse_expression(pc, token_index, true); |
| ... | ... | @@ -1612,6 +1608,50 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, size_t *to |
| 1612 | 1608 | return node; |
| 1613 | 1609 | } |
| 1614 | 1610 | |
| 1611 | /* | |
| 1612 | GlobalVarDecl = option("export") VariableDeclaration ";" | |
| 1613 | */ | |
| 1614 | static AstNode *ast_parse_global_var_decl(ParseContext *pc, size_t *token_index, VisibMod visib_mod) { | |
| 1615 | Token *first_token = &pc->tokens->at(*token_index); | |
| 1616 | ||
| 1617 | bool is_export = false;; | |
| 1618 | if (first_token->id == TokenIdKeywordExport) { | |
| 1619 | *token_index += 1; | |
| 1620 | is_export = true; | |
| 1621 | } | |
| 1622 | ||
| 1623 | AstNode *node = ast_parse_variable_declaration_expr(pc, token_index, false, visib_mod, false, is_export); | |
| 1624 | if (node == nullptr) { | |
| 1625 | if (is_export) { | |
| 1626 | *token_index -= 1; | |
| 1627 | } | |
| 1628 | return nullptr; | |
| 1629 | } | |
| 1630 | return node; | |
| 1631 | } | |
| 1632 | ||
| 1633 | /* | |
| 1634 | LocalVarDecl = option("comptime") VariableDeclaration | |
| 1635 | */ | |
| 1636 | static AstNode *ast_parse_local_var_decl(ParseContext *pc, size_t *token_index) { | |
| 1637 | Token *first_token = &pc->tokens->at(*token_index); | |
| 1638 | ||
| 1639 | bool is_comptime = false;; | |
| 1640 | if (first_token->id == TokenIdKeywordCompTime) { | |
| 1641 | *token_index += 1; | |
| 1642 | is_comptime = true; | |
| 1643 | } | |
| 1644 | ||
| 1645 | AstNode *node = ast_parse_variable_declaration_expr(pc, token_index, false, VisibModPrivate, is_comptime, false); | |
| 1646 | if (node == nullptr) { | |
| 1647 | if (is_comptime) { | |
| 1648 | *token_index -= 1; | |
| 1649 | } | |
| 1650 | return nullptr; | |
| 1651 | } | |
| 1652 | return node; | |
| 1653 | } | |
| 1654 | ||
| 1615 | 1655 | /* |
| 1616 | 1656 | BoolOrExpression = BoolAndExpression "or" BoolOrExpression | BoolAndExpression |
| 1617 | 1657 | */ |
| ... | ... | @@ -2144,7 +2184,7 @@ static bool statement_terminates_without_semicolon(AstNode *node) { |
| 2144 | 2184 | |
| 2145 | 2185 | /* |
| 2146 | 2186 | Block = "{" many(Statement) option(Expression) "}" |
| 2147 | Statement = Label | VariableDeclaration ";" | Defer(Block) | Defer(Expression) ";" | BlockExpression(Block) | Expression ";" | ";" | |
| 2187 | Statement = Label | VariableDeclaration ";" | Defer(Block) | Defer(Expression) ";" | BlockExpression(Block) | Expression ";" | ";" | ExportDecl | |
| 2148 | 2188 | */ |
| 2149 | 2189 | static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mandatory) { |
| 2150 | 2190 | Token *last_token = &pc->tokens->at(*token_index); |
| ... | ... | @@ -2163,7 +2203,7 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand |
| 2163 | 2203 | for (;;) { |
| 2164 | 2204 | AstNode *statement_node = ast_parse_label(pc, token_index, false); |
| 2165 | 2205 | if (!statement_node) |
| 2166 | statement_node = ast_parse_variable_declaration_expr(pc, token_index, false, VisibModPrivate); | |
| 2206 | statement_node = ast_parse_local_var_decl(pc, token_index); | |
| 2167 | 2207 | if (!statement_node) |
| 2168 | 2208 | statement_node = ast_parse_defer_expr(pc, token_index); |
| 2169 | 2209 | if (!statement_node) |
| ... | ... | @@ -2205,13 +2245,14 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand |
| 2205 | 2245 | } |
| 2206 | 2246 | |
| 2207 | 2247 | /* |
| 2208 | FnProto = option("coldcc" | "nakedcc" | "stdcallcc") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("->" TypeExpr) | |
| 2248 | FnProto = option("coldcc" | "nakedcc" | "stdcallcc" | "extern") "fn" option(Symbol) ParamDeclList option("align" "(" Expression ")") option("section" "(" Expression ")") option("-&gt;" TypeExpr) | |
| 2209 | 2249 | */ |
| 2210 | 2250 | static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) { |
| 2211 | 2251 | Token *first_token = &pc->tokens->at(*token_index); |
| 2212 | 2252 | Token *fn_token; |
| 2213 | 2253 | |
| 2214 | 2254 | CallingConvention cc; |
| 2255 | bool is_extern = false; | |
| 2215 | 2256 | if (first_token->id == TokenIdKeywordColdCC) { |
| 2216 | 2257 | *token_index += 1; |
| 2217 | 2258 | fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn); |
| ... | ... | @@ -2224,6 +2265,21 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m |
| 2224 | 2265 | *token_index += 1; |
| 2225 | 2266 | fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn); |
| 2226 | 2267 | cc = CallingConventionStdcall; |
| 2268 | } else if (first_token->id == TokenIdKeywordExtern) { | |
| 2269 | is_extern = true; | |
| 2270 | *token_index += 1; | |
| 2271 | Token *next_token = &pc->tokens->at(*token_index); | |
| 2272 | if (next_token->id == TokenIdKeywordFn) { | |
| 2273 | fn_token = next_token; | |
| 2274 | *token_index += 1; | |
| 2275 | } else if (mandatory) { | |
| 2276 | ast_expect_token(pc, next_token, TokenIdKeywordFn); | |
| 2277 | zig_unreachable(); | |
| 2278 | } else { | |
| 2279 | *token_index -= 1; | |
| 2280 | return nullptr; | |
| 2281 | } | |
| 2282 | cc = CallingConventionC; | |
| 2227 | 2283 | } else if (first_token->id == TokenIdKeywordFn) { |
| 2228 | 2284 | fn_token = first_token; |
| 2229 | 2285 | *token_index += 1; |
| ... | ... | @@ -2238,6 +2294,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m |
| 2238 | 2294 | AstNode *node = ast_create_node(pc, NodeTypeFnProto, fn_token); |
| 2239 | 2295 | node->data.fn_proto.visib_mod = visib_mod; |
| 2240 | 2296 | node->data.fn_proto.cc = cc; |
| 2297 | node->data.fn_proto.is_extern = is_extern; | |
| 2241 | 2298 | |
| 2242 | 2299 | Token *fn_name = &pc->tokens->at(*token_index); |
| 2243 | 2300 | |
| ... | ... | @@ -2259,6 +2316,14 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m |
| 2259 | 2316 | ast_eat_token(pc, token_index, TokenIdRParen); |
| 2260 | 2317 | next_token = &pc->tokens->at(*token_index); |
| 2261 | 2318 | } |
| 2319 | if (next_token->id == TokenIdKeywordSection) { | |
| 2320 | *token_index += 1; | |
| 2321 | ast_eat_token(pc, token_index, TokenIdLParen); | |
| 2322 | ||
| 2323 | node->data.fn_proto.section_expr = ast_parse_expression(pc, token_index, true); | |
| 2324 | ast_eat_token(pc, token_index, TokenIdRParen); | |
| 2325 | next_token = &pc->tokens->at(*token_index); | |
| 2326 | } | |
| 2262 | 2327 | if (next_token->id == TokenIdArrow) { |
| 2263 | 2328 | *token_index += 1; |
| 2264 | 2329 | node->data.fn_proto.return_type = ast_parse_type_expr(pc, token_index, false); |
| ... | ... | @@ -2270,35 +2335,35 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m |
| 2270 | 2335 | } |
| 2271 | 2336 | |
| 2272 | 2337 | /* |
| 2273 | FnDef = option("inline" | "extern") FnProto Block | |
| 2338 | FnDef = option("inline" | "export") FnProto Block | |
| 2274 | 2339 | */ |
| 2275 | 2340 | static AstNode *ast_parse_fn_def(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) { |
| 2276 | 2341 | Token *first_token = &pc->tokens->at(*token_index); |
| 2277 | 2342 | bool is_inline; |
| 2278 | bool is_extern; | |
| 2343 | bool is_export; | |
| 2279 | 2344 | if (first_token->id == TokenIdKeywordInline) { |
| 2280 | 2345 | *token_index += 1; |
| 2281 | 2346 | is_inline = true; |
| 2282 | is_extern = false; | |
| 2283 | } else if (first_token->id == TokenIdKeywordExtern) { | |
| 2347 | is_export = false; | |
| 2348 | } else if (first_token->id == TokenIdKeywordExport) { | |
| 2284 | 2349 | *token_index += 1; |
| 2285 | is_extern = true; | |
| 2350 | is_export = true; | |
| 2286 | 2351 | is_inline = false; |
| 2287 | 2352 | } else { |
| 2288 | 2353 | is_inline = false; |
| 2289 | is_extern = false; | |
| 2354 | is_export = false; | |
| 2290 | 2355 | } |
| 2291 | 2356 | |
| 2292 | 2357 | AstNode *fn_proto = ast_parse_fn_proto(pc, token_index, mandatory, visib_mod); |
| 2293 | 2358 | if (!fn_proto) { |
| 2294 | if (is_inline || is_extern) { | |
| 2359 | if (is_inline || is_export) { | |
| 2295 | 2360 | *token_index -= 1; |
| 2296 | 2361 | } |
| 2297 | 2362 | return nullptr; |
| 2298 | 2363 | } |
| 2299 | 2364 | |
| 2300 | 2365 | fn_proto->data.fn_proto.is_inline = is_inline; |
| 2301 | fn_proto->data.fn_proto.is_extern = is_extern; | |
| 2366 | fn_proto->data.fn_proto.is_export = is_export; | |
| 2302 | 2367 | |
| 2303 | 2368 | Token *semi_token = &pc->tokens->at(*token_index); |
| 2304 | 2369 | if (semi_token->id == TokenIdSemicolon) { |
| ... | ... | @@ -2344,7 +2409,7 @@ static AstNode *ast_parse_extern_decl(ParseContext *pc, size_t *token_index, boo |
| 2344 | 2409 | return fn_proto_node; |
| 2345 | 2410 | } |
| 2346 | 2411 | |
| 2347 | AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, visib_mod); | |
| 2412 | AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, visib_mod, false, false); | |
| 2348 | 2413 | if (var_decl_node) { |
| 2349 | 2414 | ast_eat_token(pc, token_index, TokenIdSemicolon); |
| 2350 | 2415 | |
| ... | ... | @@ -2447,9 +2512,6 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, |
| 2447 | 2512 | if (visib_tok->id == TokenIdKeywordPub) { |
| 2448 | 2513 | *token_index += 1; |
| 2449 | 2514 | visib_mod = VisibModPub; |
| 2450 | } else if (visib_tok->id == TokenIdKeywordExport) { | |
| 2451 | *token_index += 1; | |
| 2452 | visib_mod = VisibModExport; | |
| 2453 | 2515 | } else { |
| 2454 | 2516 | visib_mod = VisibModPrivate; |
| 2455 | 2517 | } |
| ... | ... | @@ -2460,7 +2522,7 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, |
| 2460 | 2522 | continue; |
| 2461 | 2523 | } |
| 2462 | 2524 | |
| 2463 | AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, visib_mod); | |
| 2525 | AstNode *var_decl_node = ast_parse_global_var_decl(pc, token_index, visib_mod); | |
| 2464 | 2526 | if (var_decl_node) { |
| 2465 | 2527 | ast_eat_token(pc, token_index, TokenIdSemicolon); |
| 2466 | 2528 | node->data.container_decl.decls.append(var_decl_node); |
| ... | ... | @@ -2553,7 +2615,7 @@ static AstNode *ast_parse_test_decl_node(ParseContext *pc, size_t *token_index) |
| 2553 | 2615 | |
| 2554 | 2616 | /* |
| 2555 | 2617 | TopLevelItem = ErrorValueDecl | CompTimeExpression(Block) | TopLevelDecl | TestDecl |
| 2556 | TopLevelDecl = option(VisibleMod) (FnDef | ExternDecl | GlobalVarDecl | UseDecl) | |
| 2618 | TopLevelDecl = option("pub") (FnDef | ExternDecl | GlobalVarDecl | UseDecl) | |
| 2557 | 2619 | */ |
| 2558 | 2620 | static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, ZigList<AstNode *> *top_level_decls) { |
| 2559 | 2621 | for (;;) { |
| ... | ... | @@ -2580,9 +2642,6 @@ static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, Zig |
| 2580 | 2642 | if (visib_tok->id == TokenIdKeywordPub) { |
| 2581 | 2643 | *token_index += 1; |
| 2582 | 2644 | visib_mod = VisibModPub; |
| 2583 | } else if (visib_tok->id == TokenIdKeywordExport) { | |
| 2584 | *token_index += 1; | |
| 2585 | visib_mod = VisibModExport; | |
| 2586 | 2645 | } else { |
| 2587 | 2646 | visib_mod = VisibModPrivate; |
| 2588 | 2647 | } |
| ... | ... | @@ -2605,7 +2664,7 @@ static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, Zig |
| 2605 | 2664 | continue; |
| 2606 | 2665 | } |
| 2607 | 2666 | |
| 2608 | AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, visib_mod); | |
| 2667 | AstNode *var_decl_node = ast_parse_global_var_decl(pc, token_index, visib_mod); | |
| 2609 | 2668 | if (var_decl_node) { |
| 2610 | 2669 | ast_eat_token(pc, token_index, TokenIdSemicolon); |
| 2611 | 2670 | top_level_decls->append(var_decl_node); |
| ... | ... | @@ -2669,6 +2728,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont |
| 2669 | 2728 | visit_field(&node->data.fn_proto.return_type, visit, context); |
| 2670 | 2729 | visit_node_list(&node->data.fn_proto.params, visit, context); |
| 2671 | 2730 | visit_field(&node->data.fn_proto.align_expr, visit, context); |
| 2731 | visit_field(&node->data.fn_proto.section_expr, visit, context); | |
| 2672 | 2732 | break; |
| 2673 | 2733 | case NodeTypeFnDef: |
| 2674 | 2734 | visit_field(&node->data.fn_def.fn_proto, visit, context); |
| ... | ... | @@ -2696,6 +2756,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont |
| 2696 | 2756 | visit_field(&node->data.variable_declaration.type, visit, context); |
| 2697 | 2757 | visit_field(&node->data.variable_declaration.expr, visit, context); |
| 2698 | 2758 | visit_field(&node->data.variable_declaration.align_expr, visit, context); |
| 2759 | visit_field(&node->data.variable_declaration.section_expr, visit, context); | |
| 2699 | 2760 | break; |
| 2700 | 2761 | case NodeTypeErrorValueDecl: |
| 2701 | 2762 | // none |
src/tokenizer.cpp+2| ... | ... | @@ -134,6 +134,7 @@ static const struct ZigKeyword zig_keywords[] = { |
| 134 | 134 | {"packed", TokenIdKeywordPacked}, |
| 135 | 135 | {"pub", TokenIdKeywordPub}, |
| 136 | 136 | {"return", TokenIdKeywordReturn}, |
| 137 | {"section", TokenIdKeywordSection}, | |
| 137 | 138 | {"stdcallcc", TokenIdKeywordStdcallCC}, |
| 138 | 139 | {"struct", TokenIdKeywordStruct}, |
| 139 | 140 | {"switch", TokenIdKeywordSwitch}, |
| ... | ... | @@ -1533,6 +1534,7 @@ const char * token_name(TokenId id) { |
| 1533 | 1534 | case TokenIdKeywordPacked: return "packed"; |
| 1534 | 1535 | case TokenIdKeywordPub: return "pub"; |
| 1535 | 1536 | case TokenIdKeywordReturn: return "return"; |
| 1537 | case TokenIdKeywordSection: return "section"; | |
| 1536 | 1538 | case TokenIdKeywordStdcallCC: return "stdcallcc"; |
| 1537 | 1539 | case TokenIdKeywordStruct: return "struct"; |
| 1538 | 1540 | case TokenIdKeywordSwitch: return "switch"; |
src/tokenizer.hpp+1| ... | ... | @@ -47,6 +47,7 @@ enum TokenId { |
| 47 | 47 | TokenIdFloatLiteral, |
| 48 | 48 | TokenIdIntLiteral, |
| 49 | 49 | TokenIdKeywordAlign, |
| 50 | TokenIdKeywordSection, | |
| 50 | 51 | TokenIdKeywordAnd, |
| 51 | 52 | TokenIdKeywordAsm, |
| 52 | 53 | TokenIdKeywordBreak, |
src/translate_c.cpp+5-4| ... | ... | @@ -73,7 +73,7 @@ struct Context { |
| 73 | 73 | ImportTableEntry *import; |
| 74 | 74 | ZigList<ErrorMsg *> *errors; |
| 75 | 75 | VisibMod visib_mod; |
| 76 | VisibMod export_visib_mod; | |
| 76 | bool want_export; | |
| 77 | 77 | AstNode *root; |
| 78 | 78 | HashMap<const void *, AstNode *, ptr_hash, ptr_eq> decl_table; |
| 79 | 79 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table; |
| ... | ... | @@ -3251,7 +3251,8 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { |
| 3251 | 3251 | |
| 3252 | 3252 | StorageClass sc = fn_decl->getStorageClass(); |
| 3253 | 3253 | if (sc == SC_None) { |
| 3254 | proto_node->data.fn_proto.visib_mod = fn_decl->hasBody() ? c->export_visib_mod : c->visib_mod; | |
| 3254 | proto_node->data.fn_proto.visib_mod = c->visib_mod; | |
| 3255 | proto_node->data.fn_proto.is_export = fn_decl->hasBody() ? c->want_export : false; | |
| 3255 | 3256 | } else if (sc == SC_Extern || sc == SC_Static) { |
| 3256 | 3257 | proto_node->data.fn_proto.visib_mod = c->visib_mod; |
| 3257 | 3258 | } else if (sc == SC_PrivateExtern) { |
| ... | ... | @@ -4274,10 +4275,10 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch |
| 4274 | 4275 | c->errors = errors; |
| 4275 | 4276 | if (buf_ends_with_str(buf_create_from_str(target_file), ".h")) { |
| 4276 | 4277 | c->visib_mod = VisibModPub; |
| 4277 | c->export_visib_mod = VisibModPub; | |
| 4278 | c->want_export = false; | |
| 4278 | 4279 | } else { |
| 4279 | 4280 | c->visib_mod = VisibModPub; |
| 4280 | c->export_visib_mod = VisibModExport; | |
| 4281 | c->want_export = true; | |
| 4281 | 4282 | } |
| 4282 | 4283 | c->decl_table.init(8); |
| 4283 | 4284 | c->macro_table.init(8); |
std/debug.zig-2| ... | ... | @@ -96,8 +96,6 @@ const WHITE = "\x1b[37;1m"; |
| 96 | 96 | const DIM = "\x1b[2m"; |
| 97 | 97 | const RESET = "\x1b[0m"; |
| 98 | 98 | |
| 99 | pub var user_main_fn: ?fn() -> %void = null; | |
| 100 | ||
| 101 | 99 | error PathNotFound; |
| 102 | 100 | error InvalidDebugInfo; |
| 103 | 101 |
std/elf.zig+31-31| ... | ... | @@ -188,39 +188,39 @@ pub const Elf = struct { |
| 188 | 188 | if (elf.is_64) { |
| 189 | 189 | if (sh_entry_size != 64) return error.InvalidFormat; |
| 190 | 190 | |
| 191 | for (elf.section_headers) |*section| { | |
| 192 | section.name = %return in.readInt(elf.endian, u32); | |
| 193 | section.sh_type = %return in.readInt(elf.endian, u32); | |
| 194 | section.flags = %return in.readInt(elf.endian, u64); | |
| 195 | section.addr = %return in.readInt(elf.endian, u64); | |
| 196 | section.offset = %return in.readInt(elf.endian, u64); | |
| 197 | section.size = %return in.readInt(elf.endian, u64); | |
| 198 | section.link = %return in.readInt(elf.endian, u32); | |
| 199 | section.info = %return in.readInt(elf.endian, u32); | |
| 200 | section.addr_align = %return in.readInt(elf.endian, u64); | |
| 201 | section.ent_size = %return in.readInt(elf.endian, u64); | |
| 191 | for (elf.section_headers) |*elf_section| { | |
| 192 | elf_section.name = %return in.readInt(elf.endian, u32); | |
| 193 | elf_section.sh_type = %return in.readInt(elf.endian, u32); | |
| 194 | elf_section.flags = %return in.readInt(elf.endian, u64); | |
| 195 | elf_section.addr = %return in.readInt(elf.endian, u64); | |
| 196 | elf_section.offset = %return in.readInt(elf.endian, u64); | |
| 197 | elf_section.size = %return in.readInt(elf.endian, u64); | |
| 198 | elf_section.link = %return in.readInt(elf.endian, u32); | |
| 199 | elf_section.info = %return in.readInt(elf.endian, u32); | |
| 200 | elf_section.addr_align = %return in.readInt(elf.endian, u64); | |
| 201 | elf_section.ent_size = %return in.readInt(elf.endian, u64); | |
| 202 | 202 | } |
| 203 | 203 | } else { |
| 204 | 204 | if (sh_entry_size != 40) return error.InvalidFormat; |
| 205 | 205 | |
| 206 | for (elf.section_headers) |*section| { | |
| 206 | for (elf.section_headers) |*elf_section| { | |
| 207 | 207 | // TODO (multiple occurences) allow implicit cast from %u32 -> %u64 ? |
| 208 | section.name = %return in.readInt(elf.endian, u32); | |
| 209 | section.sh_type = %return in.readInt(elf.endian, u32); | |
| 210 | section.flags = u64(%return in.readInt(elf.endian, u32)); | |
| 211 | section.addr = u64(%return in.readInt(elf.endian, u32)); | |
| 212 | section.offset = u64(%return in.readInt(elf.endian, u32)); | |
| 213 | section.size = u64(%return in.readInt(elf.endian, u32)); | |
| 214 | section.link = %return in.readInt(elf.endian, u32); | |
| 215 | section.info = %return in.readInt(elf.endian, u32); | |
| 216 | section.addr_align = u64(%return in.readInt(elf.endian, u32)); | |
| 217 | section.ent_size = u64(%return in.readInt(elf.endian, u32)); | |
| 208 | elf_section.name = %return in.readInt(elf.endian, u32); | |
| 209 | elf_section.sh_type = %return in.readInt(elf.endian, u32); | |
| 210 | elf_section.flags = u64(%return in.readInt(elf.endian, u32)); | |
| 211 | elf_section.addr = u64(%return in.readInt(elf.endian, u32)); | |
| 212 | elf_section.offset = u64(%return in.readInt(elf.endian, u32)); | |
| 213 | elf_section.size = u64(%return in.readInt(elf.endian, u32)); | |
| 214 | elf_section.link = %return in.readInt(elf.endian, u32); | |
| 215 | elf_section.info = %return in.readInt(elf.endian, u32); | |
| 216 | elf_section.addr_align = u64(%return in.readInt(elf.endian, u32)); | |
| 217 | elf_section.ent_size = u64(%return in.readInt(elf.endian, u32)); | |
| 218 | 218 | } |
| 219 | 219 | } |
| 220 | 220 | |
| 221 | for (elf.section_headers) |*section| { | |
| 222 | if (section.sh_type != SHT_NOBITS) { | |
| 223 | const file_end_offset = %return math.add(u64, section.offset, section.size); | |
| 221 | for (elf.section_headers) |*elf_section| { | |
| 222 | if (elf_section.sh_type != SHT_NOBITS) { | |
| 223 | const file_end_offset = %return math.add(u64, elf_section.offset, elf_section.size); | |
| 224 | 224 | if (stream_end < file_end_offset) return error.InvalidFormat; |
| 225 | 225 | } |
| 226 | 226 | } |
| ... | ... | @@ -243,10 +243,10 @@ pub const Elf = struct { |
| 243 | 243 | var file_stream = io.FileInStream.init(elf.in_file); |
| 244 | 244 | const in = &file_stream.stream; |
| 245 | 245 | |
| 246 | for (elf.section_headers) |*section| { | |
| 247 | if (section.sh_type == SHT_NULL) continue; | |
| 246 | for (elf.section_headers) |*elf_section| { | |
| 247 | if (elf_section.sh_type == SHT_NULL) continue; | |
| 248 | 248 | |
| 249 | const name_offset = elf.string_section.offset + section.name; | |
| 249 | const name_offset = elf.string_section.offset + elf_section.name; | |
| 250 | 250 | %return elf.in_file.seekTo(name_offset); |
| 251 | 251 | |
| 252 | 252 | for (name) |expected_c| { |
| ... | ... | @@ -256,7 +256,7 @@ pub const Elf = struct { |
| 256 | 256 | |
| 257 | 257 | { |
| 258 | 258 | const null_byte = %return in.readByte(); |
| 259 | if (null_byte == 0) return section; | |
| 259 | if (null_byte == 0) return elf_section; | |
| 260 | 260 | } |
| 261 | 261 | |
| 262 | 262 | next_section: |
| ... | ... | @@ -265,7 +265,7 @@ pub const Elf = struct { |
| 265 | 265 | return null; |
| 266 | 266 | } |
| 267 | 267 | |
| 268 | pub fn seekToSection(elf: &Elf, section: &SectionHeader) -> %void { | |
| 269 | %return elf.in_file.seekTo(section.offset); | |
| 268 | pub fn seekToSection(elf: &Elf, elf_section: &SectionHeader) -> %void { | |
| 269 | %return elf.in_file.seekTo(elf_section.offset); | |
| 270 | 270 | } |
| 271 | 271 | }; |
std/os/linux.zig-22| ... | ... | @@ -651,28 +651,6 @@ pub const iovec = extern struct { |
| 651 | 651 | iov_len: usize, |
| 652 | 652 | }; |
| 653 | 653 | |
| 654 | // | |
| 655 | //const IF_NAMESIZE = 16; | |
| 656 | // | |
| 657 | //export struct ifreq { | |
| 658 | // ifrn_name: [IF_NAMESIZE]u8, | |
| 659 | // union { | |
| 660 | // ifru_addr: sockaddr, | |
| 661 | // ifru_dstaddr: sockaddr, | |
| 662 | // ifru_broadaddr: sockaddr, | |
| 663 | // ifru_netmask: sockaddr, | |
| 664 | // ifru_hwaddr: sockaddr, | |
| 665 | // ifru_flags: i16, | |
| 666 | // ifru_ivalue: i32, | |
| 667 | // ifru_mtu: i32, | |
| 668 | // ifru_map: ifmap, | |
| 669 | // ifru_slave: [IF_NAMESIZE]u8, | |
| 670 | // ifru_newname: [IF_NAMESIZE]u8, | |
| 671 | // ifru_data: &u8, | |
| 672 | // } ifr_ifru; | |
| 673 | //} | |
| 674 | // | |
| 675 | ||
| 676 | 654 | pub fn getsockname(fd: i32, noalias addr: &sockaddr, noalias len: &socklen_t) -> usize { |
| 677 | 655 | arch.syscall3(arch.SYS_getsockname, usize(fd), @ptrToInt(addr), @ptrToInt(len)) |
| 678 | 656 | } |
std/os/linux_i386.zig-10| ... | ... | @@ -502,13 +502,3 @@ pub nakedcc fn restore_rt() { |
| 502 | 502 | : [number] "{eax}" (usize(SYS_rt_sigreturn)) |
| 503 | 503 | : "rcx", "r11") |
| 504 | 504 | } |
| 505 | ||
| 506 | export struct msghdr { | |
| 507 | msg_name: &u8, | |
| 508 | msg_namelen: socklen_t, | |
| 509 | msg_iov: &iovec, | |
| 510 | msg_iovlen: i32, | |
| 511 | msg_control: &u8, | |
| 512 | msg_controllen: socklen_t, | |
| 513 | msg_flags: i32, | |
| 514 | } |
std/special/bootstrap.zig+12-24| ... | ... | @@ -5,20 +5,20 @@ const root = @import("@root"); |
| 5 | 5 | const std = @import("std"); |
| 6 | 6 | const builtin = @import("builtin"); |
| 7 | 7 | |
| 8 | const is_windows = builtin.os == builtin.Os.windows; | |
| 9 | const want_main_symbol = builtin.link_libc; | |
| 10 | const want_start_symbol = !want_main_symbol and !is_windows; | |
| 11 | const want_WinMainCRTStartup = is_windows and !builtin.link_libc; | |
| 12 | ||
| 13 | 8 | var argc_ptr: &usize = undefined; |
| 14 | 9 | |
| 15 | ||
| 16 | export nakedcc fn _start() -> noreturn { | |
| 17 | if (!want_start_symbol) { | |
| 18 | @setGlobalLinkage(_start, builtin.GlobalLinkage.Internal); | |
| 19 | unreachable; | |
| 10 | comptime { | |
| 11 | const strong_linkage = builtin.GlobalLinkage.Strong; | |
| 12 | if (builtin.link_libc) { | |
| 13 | @export("main", main, strong_linkage); | |
| 14 | } else if (builtin.os == builtin.Os.windows) { | |
| 15 | @export("WinMainCRTStartup", WinMainCRTStartup, strong_linkage); | |
| 16 | } else { | |
| 17 | @export("_start", _start, strong_linkage); | |
| 20 | 18 | } |
| 19 | } | |
| 21 | 20 | |
| 21 | nakedcc fn _start() -> noreturn { | |
| 22 | 22 | switch (builtin.arch) { |
| 23 | 23 | builtin.Arch.x86_64 => { |
| 24 | 24 | argc_ptr = asm("lea (%%rsp), %[argc]": [argc] "=r" (-> &usize)); |
| ... | ... | @@ -33,14 +33,9 @@ export nakedcc fn _start() -> noreturn { |
| 33 | 33 | @noInlineCall(posixCallMainAndExit); |
| 34 | 34 | } |
| 35 | 35 | |
| 36 | export fn WinMainCRTStartup() -> noreturn { | |
| 37 | if (!want_WinMainCRTStartup) { | |
| 38 | @setGlobalLinkage(WinMainCRTStartup, builtin.GlobalLinkage.Internal); | |
| 39 | unreachable; | |
| 40 | } | |
| 36 | extern fn WinMainCRTStartup() -> noreturn { | |
| 41 | 37 | @setAlignStack(16); |
| 42 | 38 | |
| 43 | std.debug.user_main_fn = root.main; | |
| 44 | 39 | root.main() %% std.os.windows.ExitProcess(1); |
| 45 | 40 | std.os.windows.ExitProcess(0); |
| 46 | 41 | } |
| ... | ... | @@ -60,17 +55,10 @@ fn callMain(argc: usize, argv: &&u8, envp: &?&u8) -> %void { |
| 60 | 55 | while (envp[env_count] != null) : (env_count += 1) {} |
| 61 | 56 | std.os.posix_environ_raw = @ptrCast(&&u8, envp)[0..env_count]; |
| 62 | 57 | |
| 63 | std.debug.user_main_fn = root.main; | |
| 64 | ||
| 65 | 58 | return root.main(); |
| 66 | 59 | } |
| 67 | 60 | |
| 68 | export fn main(c_argc: i32, c_argv: &&u8, c_envp: &?&u8) -> i32 { | |
| 69 | if (!want_main_symbol) { | |
| 70 | @setGlobalLinkage(main, builtin.GlobalLinkage.Internal); | |
| 71 | unreachable; | |
| 72 | } | |
| 73 | ||
| 61 | extern fn main(c_argc: i32, c_argv: &&u8, c_envp: &?&u8) -> i32 { | |
| 74 | 62 | callMain(usize(c_argc), c_argv, c_envp) %% return 1; |
| 75 | 63 | return 0; |
| 76 | 64 | } |
std/special/bootstrap_lib.zig+5-1| ... | ... | @@ -2,7 +2,11 @@ |
| 2 | 2 | |
| 3 | 3 | const std = @import("std"); |
| 4 | 4 | |
| 5 | export stdcallcc fn _DllMainCRTStartup(hinstDLL: std.os.windows.HINSTANCE, fdwReason: std.os.windows.DWORD, | |
| 5 | comptime { | |
| 6 | @export("_DllMainCRTStartup", _DllMainCRTStartup); | |
| 7 | } | |
| 8 | ||
| 9 | stdcallcc fn _DllMainCRTStartup(hinstDLL: std.os.windows.HINSTANCE, fdwReason: std.os.windows.DWORD, | |
| 6 | 10 | lpReserved: std.os.windows.LPVOID) -> std.os.windows.BOOL |
| 7 | 11 | { |
| 8 | 12 | return std.os.windows.TRUE; |
std/special/builtin.zig+5-4| ... | ... | @@ -35,11 +35,12 @@ export fn memcpy(noalias dest: ?&u8, noalias src: ?&const u8, n: usize) { |
| 35 | 35 | (??dest)[index] = (??src)[index]; |
| 36 | 36 | } |
| 37 | 37 | |
| 38 | export fn __stack_chk_fail() -> noreturn { | |
| 39 | if (builtin.mode == builtin.Mode.ReleaseFast or builtin.os == builtin.Os.windows) { | |
| 40 | @setGlobalLinkage(__stack_chk_fail, builtin.GlobalLinkage.Internal); | |
| 41 | unreachable; | |
| 38 | comptime { | |
| 39 | if (builtin.mode != builtin.Mode.ReleaseFast and builtin.os != builtin.Os.windows) { | |
| 40 | @export("__stack_chk_fail", __stack_chk_fail, builtin.GlobalLinkage.Strong); | |
| 42 | 41 | } |
| 42 | } | |
| 43 | extern fn __stack_chk_fail() -> noreturn { | |
| 43 | 44 | @panic("stack smashing detected"); |
| 44 | 45 | } |
| 45 | 46 |
std/special/compiler_rt/aulldiv.zig+54-65| ... | ... | @@ -1,66 +1,55 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const linkage = if (builtin.is_test) builtin.GlobalLinkage.Internal else builtin.GlobalLinkage.Strong; | |
| 3 | const is_win32 = builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386; | |
| 4 | ||
| 5 | export nakedcc fn _aulldiv() { | |
| 6 | if (is_win32) { | |
| 7 | @setDebugSafety(this, false); | |
| 8 | @setGlobalLinkage(_aulldiv, linkage); | |
| 9 | asm volatile ( | |
| 10 | \\.intel_syntax noprefix | |
| 11 | \\ | |
| 12 | \\ push ebx | |
| 13 | \\ push esi | |
| 14 | \\ mov eax,dword ptr [esp+18h] | |
| 15 | \\ or eax,eax | |
| 16 | \\ jne L1 | |
| 17 | \\ mov ecx,dword ptr [esp+14h] | |
| 18 | \\ mov eax,dword ptr [esp+10h] | |
| 19 | \\ xor edx,edx | |
| 20 | \\ div ecx | |
| 21 | \\ mov ebx,eax | |
| 22 | \\ mov eax,dword ptr [esp+0Ch] | |
| 23 | \\ div ecx | |
| 24 | \\ mov edx,ebx | |
| 25 | \\ jmp L2 | |
| 26 | \\ L1: | |
| 27 | \\ mov ecx,eax | |
| 28 | \\ mov ebx,dword ptr [esp+14h] | |
| 29 | \\ mov edx,dword ptr [esp+10h] | |
| 30 | \\ mov eax,dword ptr [esp+0Ch] | |
| 31 | \\ L3: | |
| 32 | \\ shr ecx,1 | |
| 33 | \\ rcr ebx,1 | |
| 34 | \\ shr edx,1 | |
| 35 | \\ rcr eax,1 | |
| 36 | \\ or ecx,ecx | |
| 37 | \\ jne L3 | |
| 38 | \\ div ebx | |
| 39 | \\ mov esi,eax | |
| 40 | \\ mul dword ptr [esp+18h] | |
| 41 | \\ mov ecx,eax | |
| 42 | \\ mov eax,dword ptr [esp+14h] | |
| 43 | \\ mul esi | |
| 44 | \\ add edx,ecx | |
| 45 | \\ jb L4 | |
| 46 | \\ cmp edx,dword ptr [esp+10h] | |
| 47 | \\ ja L4 | |
| 48 | \\ jb L5 | |
| 49 | \\ cmp eax,dword ptr [esp+0Ch] | |
| 50 | \\ jbe L5 | |
| 51 | \\ L4: | |
| 52 | \\ dec esi | |
| 53 | \\ L5: | |
| 54 | \\ xor edx,edx | |
| 55 | \\ mov eax,esi | |
| 56 | \\ L2: | |
| 57 | \\ pop esi | |
| 58 | \\ pop ebx | |
| 59 | \\ ret 10h | |
| 60 | ); | |
| 61 | unreachable; | |
| 62 | } | |
| 63 | ||
| 64 | @setGlobalLinkage(_aulldiv, builtin.GlobalLinkage.Internal); | |
| 65 | unreachable; | |
| 1 | pub nakedcc fn _aulldiv() { | |
| 2 | @setDebugSafety(this, false); | |
| 3 | asm volatile ( | |
| 4 | \\.intel_syntax noprefix | |
| 5 | \\ | |
| 6 | \\ push ebx | |
| 7 | \\ push esi | |
| 8 | \\ mov eax,dword ptr [esp+18h] | |
| 9 | \\ or eax,eax | |
| 10 | \\ jne L1 | |
| 11 | \\ mov ecx,dword ptr [esp+14h] | |
| 12 | \\ mov eax,dword ptr [esp+10h] | |
| 13 | \\ xor edx,edx | |
| 14 | \\ div ecx | |
| 15 | \\ mov ebx,eax | |
| 16 | \\ mov eax,dword ptr [esp+0Ch] | |
| 17 | \\ div ecx | |
| 18 | \\ mov edx,ebx | |
| 19 | \\ jmp L2 | |
| 20 | \\ L1: | |
| 21 | \\ mov ecx,eax | |
| 22 | \\ mov ebx,dword ptr [esp+14h] | |
| 23 | \\ mov edx,dword ptr [esp+10h] | |
| 24 | \\ mov eax,dword ptr [esp+0Ch] | |
| 25 | \\ L3: | |
| 26 | \\ shr ecx,1 | |
| 27 | \\ rcr ebx,1 | |
| 28 | \\ shr edx,1 | |
| 29 | \\ rcr eax,1 | |
| 30 | \\ or ecx,ecx | |
| 31 | \\ jne L3 | |
| 32 | \\ div ebx | |
| 33 | \\ mov esi,eax | |
| 34 | \\ mul dword ptr [esp+18h] | |
| 35 | \\ mov ecx,eax | |
| 36 | \\ mov eax,dword ptr [esp+14h] | |
| 37 | \\ mul esi | |
| 38 | \\ add edx,ecx | |
| 39 | \\ jb L4 | |
| 40 | \\ cmp edx,dword ptr [esp+10h] | |
| 41 | \\ ja L4 | |
| 42 | \\ jb L5 | |
| 43 | \\ cmp eax,dword ptr [esp+0Ch] | |
| 44 | \\ jbe L5 | |
| 45 | \\ L4: | |
| 46 | \\ dec esi | |
| 47 | \\ L5: | |
| 48 | \\ xor edx,edx | |
| 49 | \\ mov eax,esi | |
| 50 | \\ L2: | |
| 51 | \\ pop esi | |
| 52 | \\ pop ebx | |
| 53 | \\ ret 10h | |
| 54 | ); | |
| 66 | 55 | } |
std/special/compiler_rt/aullrem.zig+55-66| ... | ... | @@ -1,67 +1,56 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const linkage = if (builtin.is_test) builtin.GlobalLinkage.Internal else builtin.GlobalLinkage.Strong; | |
| 3 | const is_win32 = builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386; | |
| 4 | ||
| 5 | export nakedcc fn _aullrem() { | |
| 6 | if (is_win32) { | |
| 7 | @setDebugSafety(this, false); | |
| 8 | @setGlobalLinkage(_aullrem, linkage); | |
| 9 | asm volatile ( | |
| 10 | \\.intel_syntax noprefix | |
| 11 | \\ | |
| 12 | \\ push ebx | |
| 13 | \\ mov eax,dword ptr [esp+14h] | |
| 14 | \\ or eax,eax | |
| 15 | \\ jne L1a | |
| 16 | \\ mov ecx,dword ptr [esp+10h] | |
| 17 | \\ mov eax,dword ptr [esp+0Ch] | |
| 18 | \\ xor edx,edx | |
| 19 | \\ div ecx | |
| 20 | \\ mov eax,dword ptr [esp+8] | |
| 21 | \\ div ecx | |
| 22 | \\ mov eax,edx | |
| 23 | \\ xor edx,edx | |
| 24 | \\ jmp L2a | |
| 25 | \\ L1a: | |
| 26 | \\ mov ecx,eax | |
| 27 | \\ mov ebx,dword ptr [esp+10h] | |
| 28 | \\ mov edx,dword ptr [esp+0Ch] | |
| 29 | \\ mov eax,dword ptr [esp+8] | |
| 30 | \\ L3a: | |
| 31 | \\ shr ecx,1 | |
| 32 | \\ rcr ebx,1 | |
| 33 | \\ shr edx,1 | |
| 34 | \\ rcr eax,1 | |
| 35 | \\ or ecx,ecx | |
| 36 | \\ jne L3a | |
| 37 | \\ div ebx | |
| 38 | \\ mov ecx,eax | |
| 39 | \\ mul dword ptr [esp+14h] | |
| 40 | \\ xchg eax,ecx | |
| 41 | \\ mul dword ptr [esp+10h] | |
| 42 | \\ add edx,ecx | |
| 43 | \\ jb L4a | |
| 44 | \\ cmp edx,dword ptr [esp+0Ch] | |
| 45 | \\ ja L4a | |
| 46 | \\ jb L5a | |
| 47 | \\ cmp eax,dword ptr [esp+8] | |
| 48 | \\ jbe L5a | |
| 49 | \\ L4a: | |
| 50 | \\ sub eax,dword ptr [esp+10h] | |
| 51 | \\ sbb edx,dword ptr [esp+14h] | |
| 52 | \\ L5a: | |
| 53 | \\ sub eax,dword ptr [esp+8] | |
| 54 | \\ sbb edx,dword ptr [esp+0Ch] | |
| 55 | \\ neg edx | |
| 56 | \\ neg eax | |
| 57 | \\ sbb edx,0 | |
| 58 | \\ L2a: | |
| 59 | \\ pop ebx | |
| 60 | \\ ret 10h | |
| 61 | ); | |
| 62 | unreachable; | |
| 63 | } | |
| 64 | ||
| 65 | @setGlobalLinkage(_aullrem, builtin.GlobalLinkage.Internal); | |
| 66 | unreachable; | |
| 1 | pub nakedcc fn _aullrem() { | |
| 2 | @setDebugSafety(this, false); | |
| 3 | asm volatile ( | |
| 4 | \\.intel_syntax noprefix | |
| 5 | \\ | |
| 6 | \\ push ebx | |
| 7 | \\ mov eax,dword ptr [esp+14h] | |
| 8 | \\ or eax,eax | |
| 9 | \\ jne L1a | |
| 10 | \\ mov ecx,dword ptr [esp+10h] | |
| 11 | \\ mov eax,dword ptr [esp+0Ch] | |
| 12 | \\ xor edx,edx | |
| 13 | \\ div ecx | |
| 14 | \\ mov eax,dword ptr [esp+8] | |
| 15 | \\ div ecx | |
| 16 | \\ mov eax,edx | |
| 17 | \\ xor edx,edx | |
| 18 | \\ jmp L2a | |
| 19 | \\ L1a: | |
| 20 | \\ mov ecx,eax | |
| 21 | \\ mov ebx,dword ptr [esp+10h] | |
| 22 | \\ mov edx,dword ptr [esp+0Ch] | |
| 23 | \\ mov eax,dword ptr [esp+8] | |
| 24 | \\ L3a: | |
| 25 | \\ shr ecx,1 | |
| 26 | \\ rcr ebx,1 | |
| 27 | \\ shr edx,1 | |
| 28 | \\ rcr eax,1 | |
| 29 | \\ or ecx,ecx | |
| 30 | \\ jne L3a | |
| 31 | \\ div ebx | |
| 32 | \\ mov ecx,eax | |
| 33 | \\ mul dword ptr [esp+14h] | |
| 34 | \\ xchg eax,ecx | |
| 35 | \\ mul dword ptr [esp+10h] | |
| 36 | \\ add edx,ecx | |
| 37 | \\ jb L4a | |
| 38 | \\ cmp edx,dword ptr [esp+0Ch] | |
| 39 | \\ ja L4a | |
| 40 | \\ jb L5a | |
| 41 | \\ cmp eax,dword ptr [esp+8] | |
| 42 | \\ jbe L5a | |
| 43 | \\ L4a: | |
| 44 | \\ sub eax,dword ptr [esp+10h] | |
| 45 | \\ sbb edx,dword ptr [esp+14h] | |
| 46 | \\ L5a: | |
| 47 | \\ sub eax,dword ptr [esp+8] | |
| 48 | \\ sbb edx,dword ptr [esp+0Ch] | |
| 49 | \\ neg edx | |
| 50 | \\ neg eax | |
| 51 | \\ sbb edx,0 | |
| 52 | \\ L2a: | |
| 53 | \\ pop ebx | |
| 54 | \\ ret 10h | |
| 55 | ); | |
| 67 | 56 | } |
std/special/compiler_rt/comparetf2.zig+3-42| ... | ... | @@ -20,11 +20,9 @@ const infRep = exponentMask; |
| 20 | 20 | |
| 21 | 21 | const builtin = @import("builtin"); |
| 22 | 22 | const is_test = builtin.is_test; |
| 23 | const linkage = @import("index.zig").linkage; | |
| 24 | 23 | |
| 25 | export fn __letf2(a: f128, b: f128) -> c_int { | |
| 24 | pub extern fn __letf2(a: f128, b: f128) -> c_int { | |
| 26 | 25 | @setDebugSafety(this, is_test); |
| 27 | @setGlobalLinkage(__letf2, linkage); | |
| 28 | 26 | |
| 29 | 27 | const aInt = @bitCast(rep_t, a); |
| 30 | 28 | const bInt = @bitCast(rep_t, b); |
| ... | ... | @@ -63,14 +61,6 @@ export fn __letf2(a: f128, b: f128) -> c_int { |
| 63 | 61 | }; |
| 64 | 62 | } |
| 65 | 63 | |
| 66 | // Alias for libgcc compatibility | |
| 67 | // TODO https://github.com/zig-lang/zig/issues/420 | |
| 68 | export fn __cmptf2(a: f128, b: f128) -> c_int { | |
| 69 | @setGlobalLinkage(__cmptf2, linkage); | |
| 70 | @setDebugSafety(this, is_test); | |
| 71 | return __letf2(a, b); | |
| 72 | } | |
| 73 | ||
| 74 | 64 | // TODO https://github.com/zig-lang/zig/issues/305 |
| 75 | 65 | // and then make the return types of some of these functions the enum instead of c_int |
| 76 | 66 | const GE_LESS = c_int(-1); |
| ... | ... | @@ -78,8 +68,7 @@ const GE_EQUAL = c_int(0); |
| 78 | 68 | const GE_GREATER = c_int(1); |
| 79 | 69 | const GE_UNORDERED = c_int(-1); // Note: different from LE_UNORDERED |
| 80 | 70 | |
| 81 | export fn __getf2(a: f128, b: f128) -> c_int { | |
| 82 | @setGlobalLinkage(__getf2, linkage); | |
| 71 | pub extern fn __getf2(a: f128, b: f128) -> c_int { | |
| 83 | 72 | @setDebugSafety(this, is_test); |
| 84 | 73 | |
| 85 | 74 | const aInt = @bitCast(srep_t, a); |
| ... | ... | @@ -108,38 +97,10 @@ export fn __getf2(a: f128, b: f128) -> c_int { |
| 108 | 97 | }; |
| 109 | 98 | } |
| 110 | 99 | |
| 111 | export fn __unordtf2(a: f128, b: f128) -> c_int { | |
| 112 | @setGlobalLinkage(__unordtf2, linkage); | |
| 100 | pub extern fn __unordtf2(a: f128, b: f128) -> c_int { | |
| 113 | 101 | @setDebugSafety(this, is_test); |
| 114 | 102 | |
| 115 | 103 | const aAbs = @bitCast(rep_t, a) & absMask; |
| 116 | 104 | const bAbs = @bitCast(rep_t, b) & absMask; |
| 117 | 105 | return c_int(aAbs > infRep or bAbs > infRep); |
| 118 | 106 | } |
| 119 | ||
| 120 | // The following are alternative names for the preceding routines. | |
| 121 | // TODO use aliases https://github.com/zig-lang/zig/issues/462 | |
| 122 | ||
| 123 | export fn __eqtf2(a: f128, b: f128) -> c_int { | |
| 124 | @setGlobalLinkage(__eqtf2, linkage); | |
| 125 | @setDebugSafety(this, is_test); | |
| 126 | return __letf2(a, b); | |
| 127 | } | |
| 128 | ||
| 129 | export fn __lttf2(a: f128, b: f128) -> c_int { | |
| 130 | @setGlobalLinkage(__lttf2, linkage); | |
| 131 | @setDebugSafety(this, is_test); | |
| 132 | return __letf2(a, b); | |
| 133 | } | |
| 134 | ||
| 135 | export fn __netf2(a: f128, b: f128) -> c_int { | |
| 136 | @setGlobalLinkage(__netf2, linkage); | |
| 137 | @setDebugSafety(this, is_test); | |
| 138 | return __letf2(a, b); | |
| 139 | } | |
| 140 | ||
| 141 | export fn __gttf2(a: f128, b: f128) -> c_int { | |
| 142 | @setGlobalLinkage(__gttf2, linkage); | |
| 143 | @setDebugSafety(this, is_test); | |
| 144 | return __getf2(a, b); | |
| 145 | } |
std/special/compiler_rt/fixunsdfdi.zig+1-3| ... | ... | @@ -1,10 +1,8 @@ |
| 1 | 1 | const fixuint = @import("fixuint.zig").fixuint; |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | const linkage = @import("index.zig").linkage; | |
| 4 | 3 | |
| 5 | export fn __fixunsdfdi(a: f64) -> u64 { | |
| 4 | pub extern fn __fixunsdfdi(a: f64) -> u64 { | |
| 6 | 5 | @setDebugSafety(this, builtin.is_test); |
| 7 | @setGlobalLinkage(__fixunsdfdi, linkage); | |
| 8 | 6 | return fixuint(f64, u64, a); |
| 9 | 7 | } |
| 10 | 8 |
std/special/compiler_rt/fixunsdfsi.zig+1-3| ... | ... | @@ -1,10 +1,8 @@ |
| 1 | 1 | const fixuint = @import("fixuint.zig").fixuint; |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | const linkage = @import("index.zig").linkage; | |
| 4 | 3 | |
| 5 | export fn __fixunsdfsi(a: f64) -> u32 { | |
| 4 | pub extern fn __fixunsdfsi(a: f64) -> u32 { | |
| 6 | 5 | @setDebugSafety(this, builtin.is_test); |
| 7 | @setGlobalLinkage(__fixunsdfsi, linkage); | |
| 8 | 6 | return fixuint(f64, u32, a); |
| 9 | 7 | } |
| 10 | 8 |
std/special/compiler_rt/fixunsdfti.zig+1-3| ... | ... | @@ -1,10 +1,8 @@ |
| 1 | 1 | const fixuint = @import("fixuint.zig").fixuint; |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | const linkage = @import("index.zig").linkage; | |
| 4 | 3 | |
| 5 | export fn __fixunsdfti(a: f64) -> u128 { | |
| 4 | pub extern fn __fixunsdfti(a: f64) -> u128 { | |
| 6 | 5 | @setDebugSafety(this, builtin.is_test); |
| 7 | @setGlobalLinkage(__fixunsdfti, linkage); | |
| 8 | 6 | return fixuint(f64, u128, a); |
| 9 | 7 | } |
| 10 | 8 |
std/special/compiler_rt/fixunssfdi.zig+1-3| ... | ... | @@ -1,10 +1,8 @@ |
| 1 | 1 | const fixuint = @import("fixuint.zig").fixuint; |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | const linkage = @import("index.zig").linkage; | |
| 4 | 3 | |
| 5 | export fn __fixunssfdi(a: f32) -> u64 { | |
| 4 | pub extern fn __fixunssfdi(a: f32) -> u64 { | |
| 6 | 5 | @setDebugSafety(this, builtin.is_test); |
| 7 | @setGlobalLinkage(__fixunssfdi, linkage); | |
| 8 | 6 | return fixuint(f32, u64, a); |
| 9 | 7 | } |
| 10 | 8 |
std/special/compiler_rt/fixunssfsi.zig+1-3| ... | ... | @@ -1,10 +1,8 @@ |
| 1 | 1 | const fixuint = @import("fixuint.zig").fixuint; |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | const linkage = @import("index.zig").linkage; | |
| 4 | 3 | |
| 5 | export fn __fixunssfsi(a: f32) -> u32 { | |
| 4 | pub extern fn __fixunssfsi(a: f32) -> u32 { | |
| 6 | 5 | @setDebugSafety(this, builtin.is_test); |
| 7 | @setGlobalLinkage(__fixunssfsi, linkage); | |
| 8 | 6 | return fixuint(f32, u32, a); |
| 9 | 7 | } |
| 10 | 8 |
std/special/compiler_rt/fixunssfti.zig+1-3| ... | ... | @@ -1,10 +1,8 @@ |
| 1 | 1 | const fixuint = @import("fixuint.zig").fixuint; |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | const linkage = @import("index.zig").linkage; | |
| 4 | 3 | |
| 5 | export fn __fixunssfti(a: f32) -> u128 { | |
| 4 | pub extern fn __fixunssfti(a: f32) -> u128 { | |
| 6 | 5 | @setDebugSafety(this, builtin.is_test); |
| 7 | @setGlobalLinkage(__fixunssfti, linkage); | |
| 8 | 6 | return fixuint(f32, u128, a); |
| 9 | 7 | } |
| 10 | 8 |
std/special/compiler_rt/fixunstfdi.zig+1-3| ... | ... | @@ -1,10 +1,8 @@ |
| 1 | 1 | const fixuint = @import("fixuint.zig").fixuint; |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | const linkage = @import("index.zig").linkage; | |
| 4 | 3 | |
| 5 | export fn __fixunstfdi(a: f128) -> u64 { | |
| 4 | pub extern fn __fixunstfdi(a: f128) -> u64 { | |
| 6 | 5 | @setDebugSafety(this, builtin.is_test); |
| 7 | @setGlobalLinkage(__fixunstfdi, linkage); | |
| 8 | 6 | return fixuint(f128, u64, a); |
| 9 | 7 | } |
| 10 | 8 |
std/special/compiler_rt/fixunstfsi.zig+1-3| ... | ... | @@ -1,10 +1,8 @@ |
| 1 | 1 | const fixuint = @import("fixuint.zig").fixuint; |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | const linkage = @import("index.zig").linkage; | |
| 4 | 3 | |
| 5 | export fn __fixunstfsi(a: f128) -> u32 { | |
| 4 | pub extern fn __fixunstfsi(a: f128) -> u32 { | |
| 6 | 5 | @setDebugSafety(this, builtin.is_test); |
| 7 | @setGlobalLinkage(__fixunstfsi, linkage); | |
| 8 | 6 | return fixuint(f128, u32, a); |
| 9 | 7 | } |
| 10 | 8 |
std/special/compiler_rt/fixunstfti.zig+1-3| ... | ... | @@ -1,10 +1,8 @@ |
| 1 | 1 | const fixuint = @import("fixuint.zig").fixuint; |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | const linkage = @import("index.zig").linkage; | |
| 4 | 3 | |
| 5 | export fn __fixunstfti(a: f128) -> u128 { | |
| 4 | pub extern fn __fixunstfti(a: f128) -> u128 { | |
| 6 | 5 | @setDebugSafety(this, builtin.is_test); |
| 7 | @setGlobalLinkage(__fixunstfti, linkage); | |
| 8 | 6 | return fixuint(f128, u128, a); |
| 9 | 7 | } |
| 10 | 8 |
std/special/compiler_rt/index.zig+165-176| ... | ... | @@ -1,33 +1,74 @@ |
| 1 | comptime { | |
| 2 | _ = @import("comparetf2.zig"); | |
| 3 | _ = @import("fixunsdfdi.zig"); | |
| 4 | _ = @import("fixunsdfsi.zig"); | |
| 5 | _ = @import("fixunsdfti.zig"); | |
| 6 | _ = @import("fixunssfdi.zig"); | |
| 7 | _ = @import("fixunssfsi.zig"); | |
| 8 | _ = @import("fixunssfti.zig"); | |
| 9 | _ = @import("fixunstfdi.zig"); | |
| 10 | _ = @import("fixunstfsi.zig"); | |
| 11 | _ = @import("fixunstfti.zig"); | |
| 12 | _ = @import("udivmoddi4.zig"); | |
| 13 | _ = @import("udivmodti4.zig"); | |
| 14 | _ = @import("udivti3.zig"); | |
| 15 | _ = @import("umodti3.zig"); | |
| 16 | _ = @import("aulldiv.zig"); | |
| 17 | _ = @import("aullrem.zig"); | |
| 18 | } | |
| 19 | ||
| 20 | 1 | const builtin = @import("builtin"); |
| 21 | 2 | const is_test = builtin.is_test; |
| 22 | const assert = @import("../../debug.zig").assert; | |
| 23 | 3 | |
| 4 | comptime { | |
| 5 | const linkage = if (is_test) builtin.GlobalLinkage.Internal else builtin.GlobalLinkage.Weak; | |
| 6 | const strong_linkage = if (is_test) builtin.GlobalLinkage.Internal else builtin.GlobalLinkage.Strong; | |
| 7 | ||
| 8 | @export("__letf2", @import("comparetf2.zig").__letf2, linkage); | |
| 9 | @export("__getf2", @import("comparetf2.zig").__getf2, linkage); | |
| 10 | ||
| 11 | if (!is_test) { | |
| 12 | // only create these aliases when not testing | |
| 13 | @export("__cmptf2", @import("comparetf2.zig").__letf2, linkage); | |
| 14 | @export("__eqtf2", @import("comparetf2.zig").__letf2, linkage); | |
| 15 | @export("__lttf2", @import("comparetf2.zig").__letf2, linkage); | |
| 16 | @export("__netf2", @import("comparetf2.zig").__letf2, linkage); | |
| 17 | @export("__gttf2", @import("comparetf2.zig").__getf2, linkage); | |
| 18 | } | |
| 19 | ||
| 20 | @export("__unordtf2", @import("comparetf2.zig").__unordtf2, linkage); | |
| 21 | ||
| 22 | @export("__fixunssfsi", @import("fixunssfsi.zig").__fixunssfsi, linkage); | |
| 23 | @export("__fixunssfdi", @import("fixunssfdi.zig").__fixunssfdi, linkage); | |
| 24 | @export("__fixunssfti", @import("fixunssfti.zig").__fixunssfti, linkage); | |
| 25 | ||
| 26 | @export("__fixunsdfsi", @import("fixunsdfsi.zig").__fixunsdfsi, linkage); | |
| 27 | @export("__fixunsdfdi", @import("fixunsdfdi.zig").__fixunsdfdi, linkage); | |
| 28 | @export("__fixunsdfti", @import("fixunsdfti.zig").__fixunsdfti, linkage); | |
| 29 | ||
| 30 | @export("__fixunstfsi", @import("fixunstfsi.zig").__fixunstfsi, linkage); | |
| 31 | @export("__fixunstfdi", @import("fixunstfdi.zig").__fixunstfdi, linkage); | |
| 32 | @export("__fixunstfti", @import("fixunstfti.zig").__fixunstfti, linkage); | |
| 33 | ||
| 34 | @export("__udivmoddi4", @import("udivmoddi4.zig").__udivmoddi4, linkage); | |
| 35 | @export("__udivmodti4", @import("udivmodti4.zig").__udivmodti4, linkage); | |
| 24 | 36 | |
| 25 | const win32 = builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386; | |
| 26 | const win64 = builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.x86_64; | |
| 27 | const win32_nocrt = win32 and !builtin.link_libc; | |
| 28 | const win64_nocrt = win64 and !builtin.link_libc; | |
| 29 | pub const linkage = if (builtin.is_test) builtin.GlobalLinkage.Internal else builtin.GlobalLinkage.Weak; | |
| 30 | const strong_linkage = if (builtin.is_test) builtin.GlobalLinkage.Internal else builtin.GlobalLinkage.Strong; | |
| 37 | @export("__udivti3", @import("udivti3.zig").__udivti3, linkage); | |
| 38 | @export("__umodti3", @import("umodti3.zig").__umodti3, linkage); | |
| 39 | ||
| 40 | @export("__udivsi3", __udivsi3, linkage); | |
| 41 | @export("__udivdi3", __udivdi3, linkage); | |
| 42 | @export("__umoddi3", __umoddi3, linkage); | |
| 43 | @export("__udivmodsi4", __udivmodsi4, linkage); | |
| 44 | ||
| 45 | if (isArmArch()) { | |
| 46 | @export("__aeabi_uldivmod", __aeabi_uldivmod, linkage); | |
| 47 | @export("__aeabi_uidivmod", __aeabi_uidivmod, linkage); | |
| 48 | @export("__aeabi_uidiv", __udivsi3, linkage); | |
| 49 | } | |
| 50 | if (builtin.os == builtin.Os.windows) { | |
| 51 | switch (builtin.arch) { | |
| 52 | builtin.Arch.i386 => { | |
| 53 | if (!builtin.link_libc) { | |
| 54 | @export("_chkstk", _chkstk, strong_linkage); | |
| 55 | @export("__chkstk_ms", __chkstk_ms, linkage); | |
| 56 | } | |
| 57 | @export("_aulldiv", @import("aulldiv.zig")._aulldiv, strong_linkage); | |
| 58 | @export("_aullrem", @import("aullrem.zig")._aullrem, strong_linkage); | |
| 59 | }, | |
| 60 | builtin.Arch.x86_64 => { | |
| 61 | if (!builtin.link_libc) { | |
| 62 | @export("__chkstk", __chkstk, strong_linkage); | |
| 63 | @export("___chkstk_ms", ___chkstk_ms, linkage); | |
| 64 | } | |
| 65 | }, | |
| 66 | else => {}, | |
| 67 | } | |
| 68 | } | |
| 69 | } | |
| 70 | ||
| 71 | const assert = @import("../../debug.zig").assert; | |
| 31 | 72 | |
| 32 | 73 | const __udivmoddi4 = @import("udivmoddi4.zig").__udivmoddi4; |
| 33 | 74 | |
| ... | ... | @@ -41,15 +82,13 @@ pub coldcc fn panic(msg: []const u8) -> noreturn { |
| 41 | 82 | } |
| 42 | 83 | } |
| 43 | 84 | |
| 44 | export fn __udivdi3(a: u64, b: u64) -> u64 { | |
| 85 | extern fn __udivdi3(a: u64, b: u64) -> u64 { | |
| 45 | 86 | @setDebugSafety(this, is_test); |
| 46 | @setGlobalLinkage(__udivdi3, linkage); | |
| 47 | 87 | return __udivmoddi4(a, b, null); |
| 48 | 88 | } |
| 49 | 89 | |
| 50 | export fn __umoddi3(a: u64, b: u64) -> u64 { | |
| 90 | extern fn __umoddi3(a: u64, b: u64) -> u64 { | |
| 51 | 91 | @setDebugSafety(this, is_test); |
| 52 | @setGlobalLinkage(__umoddi3, linkage); | |
| 53 | 92 | |
| 54 | 93 | var r: u64 = undefined; |
| 55 | 94 | _ = __udivmoddi4(a, b, &r); |
| ... | ... | @@ -60,17 +99,11 @@ const AeabiUlDivModResult = extern struct { |
| 60 | 99 | quot: u64, |
| 61 | 100 | rem: u64, |
| 62 | 101 | }; |
| 63 | export fn __aeabi_uldivmod(numerator: u64, denominator: u64) -> AeabiUlDivModResult { | |
| 102 | extern fn __aeabi_uldivmod(numerator: u64, denominator: u64) -> AeabiUlDivModResult { | |
| 64 | 103 | @setDebugSafety(this, is_test); |
| 65 | if (comptime isArmArch()) { | |
| 66 | @setGlobalLinkage(__aeabi_uldivmod, linkage); | |
| 67 | var result: AeabiUlDivModResult = undefined; | |
| 68 | result.quot = __udivmoddi4(numerator, denominator, &result.rem); | |
| 69 | return result; | |
| 70 | } | |
| 71 | ||
| 72 | @setGlobalLinkage(__aeabi_uldivmod, builtin.GlobalLinkage.Internal); | |
| 73 | unreachable; | |
| 104 | var result: AeabiUlDivModResult = undefined; | |
| 105 | result.quot = __udivmoddi4(numerator, denominator, &result.rem); | |
| 106 | return result; | |
| 74 | 107 | } |
| 75 | 108 | |
| 76 | 109 | fn isArmArch() -> bool { |
| ... | ... | @@ -98,156 +131,124 @@ fn isArmArch() -> bool { |
| 98 | 131 | }; |
| 99 | 132 | } |
| 100 | 133 | |
| 101 | export nakedcc fn __aeabi_uidivmod() { | |
| 134 | nakedcc fn __aeabi_uidivmod() { | |
| 102 | 135 | @setDebugSafety(this, false); |
| 103 | ||
| 104 | if (comptime isArmArch()) { | |
| 105 | @setGlobalLinkage(__aeabi_uidivmod, linkage); | |
| 106 | asm volatile ( | |
| 107 | \\ push { lr } | |
| 108 | \\ sub sp, sp, #4 | |
| 109 | \\ mov r2, sp | |
| 110 | \\ bl __udivmodsi4 | |
| 111 | \\ ldr r1, [sp] | |
| 112 | \\ add sp, sp, #4 | |
| 113 | \\ pop { pc } | |
| 114 | ::: "r2", "r1"); | |
| 115 | unreachable; | |
| 116 | } | |
| 117 | ||
| 118 | @setGlobalLinkage(__aeabi_uidivmod, builtin.GlobalLinkage.Internal); | |
| 136 | asm volatile ( | |
| 137 | \\ push { lr } | |
| 138 | \\ sub sp, sp, #4 | |
| 139 | \\ mov r2, sp | |
| 140 | \\ bl __udivmodsi4 | |
| 141 | \\ ldr r1, [sp] | |
| 142 | \\ add sp, sp, #4 | |
| 143 | \\ pop { pc } | |
| 144 | ::: "r2", "r1"); | |
| 119 | 145 | } |
| 120 | 146 | |
| 121 | 147 | // _chkstk (_alloca) routine - probe stack between %esp and (%esp-%eax) in 4k increments, |
| 122 | 148 | // then decrement %esp by %eax. Preserves all registers except %esp and flags. |
| 123 | 149 | // This routine is windows specific |
| 124 | 150 | // http://msdn.microsoft.com/en-us/library/ms648426.aspx |
| 125 | export nakedcc fn _chkstk() align(4) { | |
| 151 | nakedcc fn _chkstk() align(4) { | |
| 126 | 152 | @setDebugSafety(this, false); |
| 127 | 153 | |
| 128 | if (win32_nocrt) { | |
| 129 | @setGlobalLinkage(_chkstk, strong_linkage); | |
| 130 | asm volatile ( | |
| 131 | \\ push %%ecx | |
| 132 | \\ push %%eax | |
| 133 | \\ cmp $0x1000,%%eax | |
| 134 | \\ lea 12(%%esp),%%ecx | |
| 135 | \\ jb 1f | |
| 136 | \\ 2: | |
| 137 | \\ sub $0x1000,%%ecx | |
| 138 | \\ test %%ecx,(%%ecx) | |
| 139 | \\ sub $0x1000,%%eax | |
| 140 | \\ cmp $0x1000,%%eax | |
| 141 | \\ ja 2b | |
| 142 | \\ 1: | |
| 143 | \\ sub %%eax,%%ecx | |
| 144 | \\ test %%ecx,(%%ecx) | |
| 145 | \\ pop %%eax | |
| 146 | \\ pop %%ecx | |
| 147 | \\ ret | |
| 148 | ); | |
| 149 | unreachable; | |
| 150 | } | |
| 151 | ||
| 152 | @setGlobalLinkage(_chkstk, builtin.GlobalLinkage.Internal); | |
| 154 | asm volatile ( | |
| 155 | \\ push %%ecx | |
| 156 | \\ push %%eax | |
| 157 | \\ cmp $0x1000,%%eax | |
| 158 | \\ lea 12(%%esp),%%ecx | |
| 159 | \\ jb 1f | |
| 160 | \\ 2: | |
| 161 | \\ sub $0x1000,%%ecx | |
| 162 | \\ test %%ecx,(%%ecx) | |
| 163 | \\ sub $0x1000,%%eax | |
| 164 | \\ cmp $0x1000,%%eax | |
| 165 | \\ ja 2b | |
| 166 | \\ 1: | |
| 167 | \\ sub %%eax,%%ecx | |
| 168 | \\ test %%ecx,(%%ecx) | |
| 169 | \\ pop %%eax | |
| 170 | \\ pop %%ecx | |
| 171 | \\ ret | |
| 172 | ); | |
| 153 | 173 | } |
| 154 | 174 | |
| 155 | export nakedcc fn __chkstk() align(4) { | |
| 175 | nakedcc fn __chkstk() align(4) { | |
| 156 | 176 | @setDebugSafety(this, false); |
| 157 | 177 | |
| 158 | if (win64_nocrt) { | |
| 159 | @setGlobalLinkage(__chkstk, strong_linkage); | |
| 160 | asm volatile ( | |
| 161 | \\ push %%rcx | |
| 162 | \\ push %%rax | |
| 163 | \\ cmp $0x1000,%%rax | |
| 164 | \\ lea 24(%%rsp),%%rcx | |
| 165 | \\ jb 1f | |
| 166 | \\2: | |
| 167 | \\ sub $0x1000,%%rcx | |
| 168 | \\ test %%rcx,(%%rcx) | |
| 169 | \\ sub $0x1000,%%rax | |
| 170 | \\ cmp $0x1000,%%rax | |
| 171 | \\ ja 2b | |
| 172 | \\1: | |
| 173 | \\ sub %%rax,%%rcx | |
| 174 | \\ test %%rcx,(%%rcx) | |
| 175 | \\ pop %%rax | |
| 176 | \\ pop %%rcx | |
| 177 | \\ ret | |
| 178 | ); | |
| 179 | unreachable; | |
| 180 | } | |
| 181 | ||
| 182 | @setGlobalLinkage(__chkstk, builtin.GlobalLinkage.Internal); | |
| 178 | asm volatile ( | |
| 179 | \\ push %%rcx | |
| 180 | \\ push %%rax | |
| 181 | \\ cmp $0x1000,%%rax | |
| 182 | \\ lea 24(%%rsp),%%rcx | |
| 183 | \\ jb 1f | |
| 184 | \\2: | |
| 185 | \\ sub $0x1000,%%rcx | |
| 186 | \\ test %%rcx,(%%rcx) | |
| 187 | \\ sub $0x1000,%%rax | |
| 188 | \\ cmp $0x1000,%%rax | |
| 189 | \\ ja 2b | |
| 190 | \\1: | |
| 191 | \\ sub %%rax,%%rcx | |
| 192 | \\ test %%rcx,(%%rcx) | |
| 193 | \\ pop %%rax | |
| 194 | \\ pop %%rcx | |
| 195 | \\ ret | |
| 196 | ); | |
| 183 | 197 | } |
| 184 | 198 | |
| 185 | 199 | // _chkstk routine |
| 186 | 200 | // This routine is windows specific |
| 187 | 201 | // http://msdn.microsoft.com/en-us/library/ms648426.aspx |
| 188 | export nakedcc fn __chkstk_ms() align(4) { | |
| 202 | nakedcc fn __chkstk_ms() align(4) { | |
| 189 | 203 | @setDebugSafety(this, false); |
| 190 | 204 | |
| 191 | if (win32_nocrt) { | |
| 192 | @setGlobalLinkage(__chkstk_ms, linkage); | |
| 193 | asm volatile ( | |
| 194 | \\ push %%ecx | |
| 195 | \\ push %%eax | |
| 196 | \\ cmp $0x1000,%%eax | |
| 197 | \\ lea 12(%%esp),%%ecx | |
| 198 | \\ jb 1f | |
| 199 | \\ 2: | |
| 200 | \\ sub $0x1000,%%ecx | |
| 201 | \\ test %%ecx,(%%ecx) | |
| 202 | \\ sub $0x1000,%%eax | |
| 203 | \\ cmp $0x1000,%%eax | |
| 204 | \\ ja 2b | |
| 205 | \\ 1: | |
| 206 | \\ sub %%eax,%%ecx | |
| 207 | \\ test %%ecx,(%%ecx) | |
| 208 | \\ pop %%eax | |
| 209 | \\ pop %%ecx | |
| 210 | \\ ret | |
| 211 | ); | |
| 212 | unreachable; | |
| 213 | } | |
| 214 | ||
| 215 | @setGlobalLinkage(__chkstk_ms, builtin.GlobalLinkage.Internal); | |
| 205 | asm volatile ( | |
| 206 | \\ push %%ecx | |
| 207 | \\ push %%eax | |
| 208 | \\ cmp $0x1000,%%eax | |
| 209 | \\ lea 12(%%esp),%%ecx | |
| 210 | \\ jb 1f | |
| 211 | \\ 2: | |
| 212 | \\ sub $0x1000,%%ecx | |
| 213 | \\ test %%ecx,(%%ecx) | |
| 214 | \\ sub $0x1000,%%eax | |
| 215 | \\ cmp $0x1000,%%eax | |
| 216 | \\ ja 2b | |
| 217 | \\ 1: | |
| 218 | \\ sub %%eax,%%ecx | |
| 219 | \\ test %%ecx,(%%ecx) | |
| 220 | \\ pop %%eax | |
| 221 | \\ pop %%ecx | |
| 222 | \\ ret | |
| 223 | ); | |
| 216 | 224 | } |
| 217 | 225 | |
| 218 | export nakedcc fn ___chkstk_ms() align(4) { | |
| 226 | nakedcc fn ___chkstk_ms() align(4) { | |
| 219 | 227 | @setDebugSafety(this, false); |
| 220 | 228 | |
| 221 | if (win64_nocrt) { | |
| 222 | @setGlobalLinkage(___chkstk_ms, linkage); | |
| 223 | asm volatile ( | |
| 224 | \\ push %%rcx | |
| 225 | \\ push %%rax | |
| 226 | \\ cmp $0x1000,%%rax | |
| 227 | \\ lea 24(%%rsp),%%rcx | |
| 228 | \\ jb 1f | |
| 229 | \\2: | |
| 230 | \\ sub $0x1000,%%rcx | |
| 231 | \\ test %%rcx,(%%rcx) | |
| 232 | \\ sub $0x1000,%%rax | |
| 233 | \\ cmp $0x1000,%%rax | |
| 234 | \\ ja 2b | |
| 235 | \\1: | |
| 236 | \\ sub %%rax,%%rcx | |
| 237 | \\ test %%rcx,(%%rcx) | |
| 238 | \\ pop %%rax | |
| 239 | \\ pop %%rcx | |
| 240 | \\ ret | |
| 241 | ); | |
| 242 | unreachable; | |
| 243 | } | |
| 244 | ||
| 245 | @setGlobalLinkage(___chkstk_ms, builtin.GlobalLinkage.Internal); | |
| 229 | asm volatile ( | |
| 230 | \\ push %%rcx | |
| 231 | \\ push %%rax | |
| 232 | \\ cmp $0x1000,%%rax | |
| 233 | \\ lea 24(%%rsp),%%rcx | |
| 234 | \\ jb 1f | |
| 235 | \\2: | |
| 236 | \\ sub $0x1000,%%rcx | |
| 237 | \\ test %%rcx,(%%rcx) | |
| 238 | \\ sub $0x1000,%%rax | |
| 239 | \\ cmp $0x1000,%%rax | |
| 240 | \\ ja 2b | |
| 241 | \\1: | |
| 242 | \\ sub %%rax,%%rcx | |
| 243 | \\ test %%rcx,(%%rcx) | |
| 244 | \\ pop %%rax | |
| 245 | \\ pop %%rcx | |
| 246 | \\ ret | |
| 247 | ); | |
| 246 | 248 | } |
| 247 | 249 | |
| 248 | export fn __udivmodsi4(a: u32, b: u32, rem: &u32) -> u32 { | |
| 250 | extern fn __udivmodsi4(a: u32, b: u32, rem: &u32) -> u32 { | |
| 249 | 251 | @setDebugSafety(this, is_test); |
| 250 | @setGlobalLinkage(__udivmodsi4, linkage); | |
| 251 | 252 | |
| 252 | 253 | const d = __udivsi3(a, b); |
| 253 | 254 | *rem = u32(i32(a) -% (i32(d) * i32(b))); |
| ... | ... | @@ -255,19 +256,8 @@ export fn __udivmodsi4(a: u32, b: u32, rem: &u32) -> u32 { |
| 255 | 256 | } |
| 256 | 257 | |
| 257 | 258 | |
| 258 | // TODO make this an alias instead of an extra function call | |
| 259 | // https://github.com/andrewrk/zig/issues/256 | |
| 260 | ||
| 261 | export fn __aeabi_uidiv(n: u32, d: u32) -> u32 { | |
| 259 | extern fn __udivsi3(n: u32, d: u32) -> u32 { | |
| 262 | 260 | @setDebugSafety(this, is_test); |
| 263 | @setGlobalLinkage(__aeabi_uidiv, linkage); | |
| 264 | ||
| 265 | return __udivsi3(n, d); | |
| 266 | } | |
| 267 | ||
| 268 | export fn __udivsi3(n: u32, d: u32) -> u32 { | |
| 269 | @setDebugSafety(this, is_test); | |
| 270 | @setGlobalLinkage(__udivsi3, linkage); | |
| 271 | 261 | |
| 272 | 262 | const n_uword_bits: c_uint = u32.bit_count; |
| 273 | 263 | // special cases |
| ... | ... | @@ -463,4 +453,3 @@ fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) { |
| 463 | 453 | const q: u32 = __udivsi3(a, b); |
| 464 | 454 | assert(q == expected_q); |
| 465 | 455 | } |
| 466 |
std/special/compiler_rt/udivmoddi4.zig+1-3| ... | ... | @@ -1,10 +1,8 @@ |
| 1 | 1 | const udivmod = @import("udivmod.zig").udivmod; |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | const linkage = @import("index.zig").linkage; | |
| 4 | 3 | |
| 5 | export fn __udivmoddi4(a: u64, b: u64, maybe_rem: ?&u64) -> u64 { | |
| 4 | pub extern fn __udivmoddi4(a: u64, b: u64, maybe_rem: ?&u64) -> u64 { | |
| 6 | 5 | @setDebugSafety(this, builtin.is_test); |
| 7 | @setGlobalLinkage(__udivmoddi4, linkage); | |
| 8 | 6 | return udivmod(u64, a, b, maybe_rem); |
| 9 | 7 | } |
| 10 | 8 |
std/special/compiler_rt/udivmodti4.zig+1-3| ... | ... | @@ -1,10 +1,8 @@ |
| 1 | 1 | const udivmod = @import("udivmod.zig").udivmod; |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | const linkage = @import("index.zig").linkage; | |
| 4 | 3 | |
| 5 | export fn __udivmodti4(a: u128, b: u128, maybe_rem: ?&u128) -> u128 { | |
| 4 | pub extern fn __udivmodti4(a: u128, b: u128, maybe_rem: ?&u128) -> u128 { | |
| 6 | 5 | @setDebugSafety(this, builtin.is_test); |
| 7 | @setGlobalLinkage(__udivmodti4, linkage); | |
| 8 | 6 | return udivmod(u128, a, b, maybe_rem); |
| 9 | 7 | } |
| 10 | 8 |
std/special/compiler_rt/udivti3.zig+1-3| ... | ... | @@ -1,9 +1,7 @@ |
| 1 | 1 | const __udivmodti4 = @import("udivmodti4.zig").__udivmodti4; |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | const linkage = @import("index.zig").linkage; | |
| 4 | 3 | |
| 5 | export fn __udivti3(a: u128, b: u128) -> u128 { | |
| 4 | pub extern fn __udivti3(a: u128, b: u128) -> u128 { | |
| 6 | 5 | @setDebugSafety(this, builtin.is_test); |
| 7 | @setGlobalLinkage(__udivti3, linkage); | |
| 8 | 6 | return __udivmodti4(a, b, null); |
| 9 | 7 | } |
std/special/compiler_rt/umodti3.zig+1-3| ... | ... | @@ -1,10 +1,8 @@ |
| 1 | 1 | const __udivmodti4 = @import("udivmodti4.zig").__udivmodti4; |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | const linkage = @import("index.zig").linkage; | |
| 4 | 3 | |
| 5 | export fn __umodti3(a: u128, b: u128) -> u128 { | |
| 4 | pub extern fn __umodti3(a: u128, b: u128) -> u128 { | |
| 6 | 5 | @setDebugSafety(this, builtin.is_test); |
| 7 | @setGlobalLinkage(__umodti3, linkage); | |
| 8 | 6 | var r: u128 = undefined; |
| 9 | 7 | _ = __udivmodti4(a, b, &r); |
| 10 | 8 | return r; |
test/cases/misc.zig+5-2| ... | ... | @@ -12,8 +12,11 @@ test "empty function with comments" { |
| 12 | 12 | emptyFunctionWithComments(); |
| 13 | 13 | } |
| 14 | 14 | |
| 15 | export fn disabledExternFn() { | |
| 16 | @setGlobalLinkage(disabledExternFn, builtin.GlobalLinkage.Internal); | |
| 15 | comptime { | |
| 16 | @export("disabledExternFn", disabledExternFn, builtin.GlobalLinkage.Internal); | |
| 17 | } | |
| 18 | ||
| 19 | extern fn disabledExternFn() { | |
| 17 | 20 | } |
| 18 | 21 | |
| 19 | 22 | test "call disabled extern fn" { |
test/compile_errors.zig+24-17| ... | ... | @@ -1468,7 +1468,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1468 | 1468 | \\} |
| 1469 | 1469 | , |
| 1470 | 1470 | "foo.zig:1:8: error: exported symbol collision: 'bar'", |
| 1471 | ".tmp_source.zig:3:8: note: other symbol is here"); | |
| 1471 | ".tmp_source.zig:3:8: note: other symbol here"); | |
| 1472 | 1472 | |
| 1473 | 1473 | tc.addSourceFile("foo.zig", |
| 1474 | 1474 | \\export fn bar() {} |
| ... | ... | @@ -1611,23 +1611,29 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1611 | 1611 | "error: 'main' is private", |
| 1612 | 1612 | ".tmp_source.zig:1:1: note: declared here"); |
| 1613 | 1613 | |
| 1614 | cases.add("@setGlobalSection extern variable", | |
| 1615 | \\extern var foo: i32; | |
| 1616 | \\comptime { | |
| 1617 | \\ @setGlobalSection(foo, ".text2"); | |
| 1614 | cases.add("setting a section on an extern variable", | |
| 1615 | \\extern var foo: i32 section(".text2"); | |
| 1616 | \\export fn entry() -> i32 { | |
| 1617 | \\ return foo; | |
| 1618 | 1618 | \\} |
| 1619 | 1619 | , |
| 1620 | ".tmp_source.zig:3:5: error: cannot set section of external variable 'foo'", | |
| 1621 | ".tmp_source.zig:1:8: note: declared here"); | |
| 1620 | ".tmp_source.zig:1:29: error: cannot set section of external variable 'foo'"); | |
| 1622 | 1621 | |
| 1623 | cases.add("@setGlobalSection extern fn", | |
| 1624 | \\extern fn foo(); | |
| 1625 | \\comptime { | |
| 1626 | \\ @setGlobalSection(foo, ".text2"); | |
| 1622 | cases.add("setting a section on a local variable", | |
| 1623 | \\export fn entry() -> i32 { | |
| 1624 | \\ var foo: i32 section(".text2") = 1234; | |
| 1625 | \\ return foo; | |
| 1627 | 1626 | \\} |
| 1628 | 1627 | , |
| 1629 | ".tmp_source.zig:3:5: error: cannot set section of external function 'foo'", | |
| 1630 | ".tmp_source.zig:1:8: note: declared here"); | |
| 1628 | ".tmp_source.zig:2:26: error: cannot set section of local variable 'foo'"); | |
| 1629 | ||
| 1630 | cases.add("setting a section on an extern fn", | |
| 1631 | \\extern fn foo() section(".text2"); | |
| 1632 | \\export fn entry() { | |
| 1633 | \\ foo(); | |
| 1634 | \\} | |
| 1635 | , | |
| 1636 | ".tmp_source.zig:1:25: error: cannot set section of external function 'foo'"); | |
| 1631 | 1637 | |
| 1632 | 1638 | cases.add("returning address of local variable - simple", |
| 1633 | 1639 | \\export fn foo() -> &i32 { |
| ... | ... | @@ -2120,12 +2126,13 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 2120 | 2126 | , |
| 2121 | 2127 | ".tmp_source.zig:3:41: error: expected type 'AtomicOrder', found 'u32'"); |
| 2122 | 2128 | |
| 2123 | cases.add("wrong types given to setGlobalLinkage", | |
| 2124 | \\export fn entry() { | |
| 2125 | \\ @setGlobalLinkage(entry, u32(1234)); | |
| 2129 | cases.add("wrong types given to @export", | |
| 2130 | \\extern fn entry() { } | |
| 2131 | \\comptime { | |
| 2132 | \\ @export("entry", entry, u32(1234)); | |
| 2126 | 2133 | \\} |
| 2127 | 2134 | , |
| 2128 | ".tmp_source.zig:2:33: error: expected type 'GlobalLinkage', found 'u32'"); | |
| 2135 | ".tmp_source.zig:3:32: error: expected type 'GlobalLinkage', found 'u32'"); | |
| 2129 | 2136 | |
| 2130 | 2137 | cases.add("struct with invalid field", |
| 2131 | 2138 | \\const std = @import("std"); |
test/translate_c.zig+31-31| ... | ... | @@ -325,12 +325,12 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 325 | 325 | \\ return a; |
| 326 | 326 | \\} |
| 327 | 327 | , |
| 328 | \\export fn foo1(_arg_a: c_uint) -> c_uint { | |
| 328 | \\pub export fn foo1(_arg_a: c_uint) -> c_uint { | |
| 329 | 329 | \\ var a = _arg_a; |
| 330 | 330 | \\ a +%= 1; |
| 331 | 331 | \\ return a; |
| 332 | 332 | \\} |
| 333 | \\export fn foo2(_arg_a: c_int) -> c_int { | |
| 333 | \\pub export fn foo2(_arg_a: c_int) -> c_int { | |
| 334 | 334 | \\ var a = _arg_a; |
| 335 | 335 | \\ a += 1; |
| 336 | 336 | \\ return a; |
| ... | ... | @@ -346,7 +346,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 346 | 346 | \\ return i; |
| 347 | 347 | \\} |
| 348 | 348 | , |
| 349 | \\export fn log2(_arg_a: c_uint) -> c_int { | |
| 349 | \\pub export fn log2(_arg_a: c_uint) -> c_int { | |
| 350 | 350 | \\ var a = _arg_a; |
| 351 | 351 | \\ var i: c_int = 0; |
| 352 | 352 | \\ while (a > c_uint(0)) { |
| ... | ... | @@ -367,7 +367,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 367 | 367 | \\ return a; |
| 368 | 368 | \\} |
| 369 | 369 | , |
| 370 | \\export fn max(a: c_int, b: c_int) -> c_int { | |
| 370 | \\pub export fn max(a: c_int, b: c_int) -> c_int { | |
| 371 | 371 | \\ if (a < b) return b; |
| 372 | 372 | \\ if (a < b) return b else return a; |
| 373 | 373 | \\} |
| ... | ... | @@ -382,7 +382,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 382 | 382 | \\ return a; |
| 383 | 383 | \\} |
| 384 | 384 | , |
| 385 | \\export fn max(a: c_int, b: c_int) -> c_int { | |
| 385 | \\pub export fn max(a: c_int, b: c_int) -> c_int { | |
| 386 | 386 | \\ if (a == b) return a; |
| 387 | 387 | \\ if (a != b) return b; |
| 388 | 388 | \\ return a; |
| ... | ... | @@ -407,7 +407,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 407 | 407 | \\ c = a % b; |
| 408 | 408 | \\} |
| 409 | 409 | , |
| 410 | \\export fn s(a: c_int, b: c_int) -> c_int { | |
| 410 | \\pub export fn s(a: c_int, b: c_int) -> c_int { | |
| 411 | 411 | \\ var c: c_int; |
| 412 | 412 | \\ c = (a + b); |
| 413 | 413 | \\ c = (a - b); |
| ... | ... | @@ -415,7 +415,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 415 | 415 | \\ c = @divTrunc(a, b); |
| 416 | 416 | \\ c = @rem(a, b); |
| 417 | 417 | \\} |
| 418 | \\export fn u(a: c_uint, b: c_uint) -> c_uint { | |
| 418 | \\pub export fn u(a: c_uint, b: c_uint) -> c_uint { | |
| 419 | 419 | \\ var c: c_uint; |
| 420 | 420 | \\ c = (a +% b); |
| 421 | 421 | \\ c = (a -% b); |
| ... | ... | @@ -430,7 +430,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 430 | 430 | \\ return (a & b) ^ (a | b); |
| 431 | 431 | \\} |
| 432 | 432 | , |
| 433 | \\export fn max(a: c_int, b: c_int) -> c_int { | |
| 433 | \\pub export fn max(a: c_int, b: c_int) -> c_int { | |
| 434 | 434 | \\ return (a & b) ^ (a | b); |
| 435 | 435 | \\} |
| 436 | 436 | ); |
| ... | ... | @@ -444,7 +444,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 444 | 444 | \\ return a; |
| 445 | 445 | \\} |
| 446 | 446 | , |
| 447 | \\export fn max(a: c_int, b: c_int) -> c_int { | |
| 447 | \\pub export fn max(a: c_int, b: c_int) -> c_int { | |
| 448 | 448 | \\ if ((a < b) or (a == b)) return b; |
| 449 | 449 | \\ if ((a >= b) and (a == b)) return a; |
| 450 | 450 | \\ return a; |
| ... | ... | @@ -458,7 +458,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 458 | 458 | \\ a = tmp; |
| 459 | 459 | \\} |
| 460 | 460 | , |
| 461 | \\export fn max(_arg_a: c_int) -> c_int { | |
| 461 | \\pub export fn max(_arg_a: c_int) -> c_int { | |
| 462 | 462 | \\ var a = _arg_a; |
| 463 | 463 | \\ var tmp: c_int; |
| 464 | 464 | \\ tmp = a; |
| ... | ... | @@ -472,7 +472,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 472 | 472 | \\ c = b = a; |
| 473 | 473 | \\} |
| 474 | 474 | , |
| 475 | \\export fn max(a: c_int) { | |
| 475 | \\pub export fn max(a: c_int) { | |
| 476 | 476 | \\ var b: c_int; |
| 477 | 477 | \\ var c: c_int; |
| 478 | 478 | \\ c = { |
| ... | ... | @@ -493,7 +493,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 493 | 493 | \\ return i; |
| 494 | 494 | \\} |
| 495 | 495 | , |
| 496 | \\export fn log2(_arg_a: u32) -> c_int { | |
| 496 | \\pub export fn log2(_arg_a: u32) -> c_int { | |
| 497 | 497 | \\ var a = _arg_a; |
| 498 | 498 | \\ var i: c_int = 0; |
| 499 | 499 | \\ while (a > c_uint(0)) { |
| ... | ... | @@ -518,7 +518,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 518 | 518 | \\void foo(void) { bar(); } |
| 519 | 519 | , |
| 520 | 520 | \\pub fn bar() {} |
| 521 | \\export fn foo() { | |
| 521 | \\pub export fn foo() { | |
| 522 | 522 | \\ bar(); |
| 523 | 523 | \\} |
| 524 | 524 | ); |
| ... | ... | @@ -534,7 +534,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 534 | 534 | \\pub const struct_Foo = extern struct { |
| 535 | 535 | \\ field: c_int, |
| 536 | 536 | \\}; |
| 537 | \\export fn read_field(foo: ?&struct_Foo) -> c_int { | |
| 537 | \\pub export fn read_field(foo: ?&struct_Foo) -> c_int { | |
| 538 | 538 | \\ return (??foo).field; |
| 539 | 539 | \\} |
| 540 | 540 | ); |
| ... | ... | @@ -544,7 +544,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 544 | 544 | \\ ;;;;; |
| 545 | 545 | \\} |
| 546 | 546 | , |
| 547 | \\export fn foo() {} | |
| 547 | \\pub export fn foo() {} | |
| 548 | 548 | ); |
| 549 | 549 | |
| 550 | 550 | cases.add("undefined array global", |
| ... | ... | @@ -560,7 +560,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 560 | 560 | \\} |
| 561 | 561 | , |
| 562 | 562 | \\pub var array: [100]c_int = undefined; |
| 563 | \\export fn foo(index: c_int) -> c_int { | |
| 563 | \\pub export fn foo(index: c_int) -> c_int { | |
| 564 | 564 | \\ return array[index]; |
| 565 | 565 | \\} |
| 566 | 566 | ); |
| ... | ... | @@ -571,7 +571,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 571 | 571 | \\ return (int)a; |
| 572 | 572 | \\} |
| 573 | 573 | , |
| 574 | \\export fn float_to_int(a: f32) -> c_int { | |
| 574 | \\pub export fn float_to_int(a: f32) -> c_int { | |
| 575 | 575 | \\ return c_int(a); |
| 576 | 576 | \\} |
| 577 | 577 | ); |
| ... | ... | @@ -581,7 +581,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 581 | 581 | \\ return x; |
| 582 | 582 | \\} |
| 583 | 583 | , |
| 584 | \\export fn foo(x: ?&c_ushort) -> ?&c_void { | |
| 584 | \\pub export fn foo(x: ?&c_ushort) -> ?&c_void { | |
| 585 | 585 | \\ return @ptrCast(?&c_void, x); |
| 586 | 586 | \\} |
| 587 | 587 | ); |
| ... | ... | @@ -592,7 +592,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 592 | 592 | \\ return sizeof(int); |
| 593 | 593 | \\} |
| 594 | 594 | , |
| 595 | \\export fn size_of() -> usize { | |
| 595 | \\pub export fn size_of() -> usize { | |
| 596 | 596 | \\ return @sizeOf(c_int); |
| 597 | 597 | \\} |
| 598 | 598 | ); |
| ... | ... | @@ -602,7 +602,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 602 | 602 | \\ return 0; |
| 603 | 603 | \\} |
| 604 | 604 | , |
| 605 | \\export fn foo() -> ?&c_int { | |
| 605 | \\pub export fn foo() -> ?&c_int { | |
| 606 | 606 | \\ return null; |
| 607 | 607 | \\} |
| 608 | 608 | ); |
| ... | ... | @@ -612,7 +612,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 612 | 612 | \\ return 1, 2; |
| 613 | 613 | \\} |
| 614 | 614 | , |
| 615 | \\export fn foo() -> c_int { | |
| 615 | \\pub export fn foo() -> c_int { | |
| 616 | 616 | \\ return { |
| 617 | 617 | \\ _ = 1; |
| 618 | 618 | \\ 2 |
| ... | ... | @@ -625,7 +625,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 625 | 625 | \\ return (1 << 2) >> 1; |
| 626 | 626 | \\} |
| 627 | 627 | , |
| 628 | \\export fn foo() -> c_int { | |
| 628 | \\pub export fn foo() -> c_int { | |
| 629 | 629 | \\ return (1 << @import("std").math.Log2Int(c_int)(2)) >> @import("std").math.Log2Int(c_int)(1); |
| 630 | 630 | \\} |
| 631 | 631 | ); |
| ... | ... | @@ -643,7 +643,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 643 | 643 | \\ a <<= (a <<= 1); |
| 644 | 644 | \\} |
| 645 | 645 | , |
| 646 | \\export fn foo() { | |
| 646 | \\pub export fn foo() { | |
| 647 | 647 | \\ var a: c_int = 0; |
| 648 | 648 | \\ a += { |
| 649 | 649 | \\ const _ref = &a; |
| ... | ... | @@ -701,7 +701,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 701 | 701 | \\ a <<= (a <<= 1); |
| 702 | 702 | \\} |
| 703 | 703 | , |
| 704 | \\export fn foo() { | |
| 704 | \\pub export fn foo() { | |
| 705 | 705 | \\ var a: c_uint = c_uint(0); |
| 706 | 706 | \\ a +%= { |
| 707 | 707 | \\ const _ref = &a; |
| ... | ... | @@ -771,7 +771,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 771 | 771 | \\ u = u--; |
| 772 | 772 | \\} |
| 773 | 773 | , |
| 774 | \\export fn foo() { | |
| 774 | \\pub export fn foo() { | |
| 775 | 775 | \\ var i: c_int = 0; |
| 776 | 776 | \\ var u: c_uint = c_uint(0); |
| 777 | 777 | \\ i += 1; |
| ... | ... | @@ -819,7 +819,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 819 | 819 | \\ u = --u; |
| 820 | 820 | \\} |
| 821 | 821 | , |
| 822 | \\export fn foo() { | |
| 822 | \\pub export fn foo() { | |
| 823 | 823 | \\ var i: c_int = 0; |
| 824 | 824 | \\ var u: c_uint = c_uint(0); |
| 825 | 825 | \\ i += 1; |
| ... | ... | @@ -862,7 +862,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 862 | 862 | \\ while (b != 0); |
| 863 | 863 | \\} |
| 864 | 864 | , |
| 865 | \\export fn foo() { | |
| 865 | \\pub export fn foo() { | |
| 866 | 866 | \\ var a: c_int = 2; |
| 867 | 867 | \\ while (true) { |
| 868 | 868 | \\ a -= 1; |
| ... | ... | @@ -886,9 +886,9 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 886 | 886 | \\ baz(); |
| 887 | 887 | \\} |
| 888 | 888 | , |
| 889 | \\export fn foo() {} | |
| 890 | \\export fn baz() {} | |
| 891 | \\export fn bar() { | |
| 889 | \\pub export fn foo() {} | |
| 890 | \\pub export fn baz() {} | |
| 891 | \\pub export fn bar() { | |
| 892 | 892 | \\ var f: ?extern fn() = foo; |
| 893 | 893 | \\ (??f)(); |
| 894 | 894 | \\ (??f)(); |
| ... | ... | @@ -901,7 +901,7 @@ pub fn addCases(cases: &tests.TranslateCContext) { |
| 901 | 901 | \\ *x = 1; |
| 902 | 902 | \\} |
| 903 | 903 | , |
| 904 | \\export fn foo(x: ?&c_int) { | |
| 904 | \\pub export fn foo(x: ?&c_int) { | |
| 905 | 905 | \\ (*??x) = 1; |
| 906 | 906 | \\} |
| 907 | 907 | ); |