authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-06-14 00:04:34-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-06-14 00:04:34-04:00
log6a93dda3e1c0ff5f400da25a5d14c907fc9a6fdf
tree08260222b967ccf73f237ae97824c054c023c9b8
parent199bbb6292896330ced71dec2e5c58a49af5907e

progress toward windows hello world working


28 files changed, 515 insertions(+), 235 deletions(-)

CMakeLists.txt-1
......@@ -244,7 +244,6 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/special/builtin.zig" DESTINATION "${ZIG_S
244244install(FILES "${CMAKE_SOURCE_DIR}/std/special/compiler_rt.zig" DESTINATION "${ZIG_STD_DEST}/special")
245245install(FILES "${CMAKE_SOURCE_DIR}/std/special/test_runner.zig" DESTINATION "${ZIG_STD_DEST}/special")
246246install(FILES "${CMAKE_SOURCE_DIR}/std/special/zigrt.zig" DESTINATION "${ZIG_STD_DEST}/special")
247install(FILES "${CMAKE_SOURCE_DIR}/std/target.zig" DESTINATION "${ZIG_STD_DEST}")
248247
249248if (ZIG_TEST_COVERAGE)
250249 add_custom_target(coverage
doc/langref.md+2-2
......@@ -23,9 +23,9 @@ ContainerField = Symbol option(":" Expression) ","
2323
2424UseDecl = "use" Expression ";"
2525
26ExternDecl = "extern" (FnProto | VariableDeclaration) ";"
26ExternDecl = "extern" option(String) (FnProto | VariableDeclaration) ";"
2727
28FnProto = option("coldcc" | "nakedcc") "fn" option(Symbol) ParamDeclList option("->" TypeExpr)
28FnProto = option("coldcc" | "nakedcc" | "stdcallcc") "fn" option(Symbol) ParamDeclList option("->" TypeExpr)
2929
3030VisibleMod = "pub" | "export"
3131
src/all_types.hpp+27-8
......@@ -304,12 +304,14 @@ struct TldVar {
304304 Buf *section_name;
305305 AstNode *set_global_linkage_node;
306306 GlobalLinkageId linkage;
307 Buf *extern_lib_name;
307308};
308309
309310struct TldFn {
310311 Tld base;
311312
312313 FnTableEntry *fn_entry;
314 Buf *extern_lib_name;
313315};
314316
315317struct TldContainer {
......@@ -387,6 +389,14 @@ struct AstNodeRoot {
387389 ZigList<AstNode *> top_level_decls;
388390};
389391
392enum CallingConvention {
393 CallingConventionUnspecified,
394 CallingConventionC,
395 CallingConventionCold,
396 CallingConventionNaked,
397 CallingConventionStdcall,
398};
399
390400struct AstNodeFnProto {
391401 VisibMod visib_mod;
392402 Buf *name;
......@@ -395,9 +405,10 @@ struct AstNodeFnProto {
395405 bool is_var_args;
396406 bool is_extern;
397407 bool is_inline;
398 bool is_coldcc;
399 bool is_nakedcc;
408 CallingConvention cc;
400409 AstNode *fn_def_node;
410 // populated if this is an extern declaration
411 Buf *lib_name;
401412};
402413
403414struct AstNodeFnDef {
......@@ -451,6 +462,8 @@ struct AstNodeVariableDeclaration {
451462 // one or both of type and expr will be non null
452463 AstNode *type;
453464 AstNode *expr;
465 // populated if this is an extern declaration
466 Buf *lib_name;
454467};
455468
456469struct AstNodeErrorValueDecl {
......@@ -879,9 +892,7 @@ struct FnTypeId {
879892 size_t param_count;
880893 size_t next_param_index;
881894 bool is_var_args;
882 bool is_naked;
883 bool is_cold;
884 bool is_extern;
895 CallingConvention cc;
885896};
886897
887898uint32_t fn_type_id_hash(FnTypeId*);
......@@ -1013,7 +1024,6 @@ struct TypeTableEntryFn {
10131024 FnGenParamInfo *gen_param_info;
10141025
10151026 LLVMTypeRef raw_type_ref;
1016 LLVMCallConv calling_convention;
10171027
10181028 TypeTableEntry *bound_fn_parent;
10191029};
......@@ -1316,6 +1326,13 @@ enum BuildMode {
13161326 BuildModeSafeRelease,
13171327};
13181328
1329struct LinkLib {
1330 Buf *name;
1331 Buf *path;
1332 ZigList<Buf *> symbols; // the list of symbols that we depend on from this lib
1333 bool provided_explicitly;
1334};
1335
13191336struct CodeGen {
13201337 LLVMModuleRef module;
13211338 ZigList<ErrorMsg*> errors;
......@@ -1324,7 +1341,9 @@ struct CodeGen {
13241341 ZigLLVMDICompileUnit *compile_unit;
13251342 ZigLLVMDIFile *compile_unit_file;
13261343
1327 ZigList<Buf *> link_libs; // non-libc link libs
1344 ZigList<LinkLib *> link_libs_list;
1345 LinkLib *libc_link_lib;
1346
13281347 // add -framework [name] args to linker
13291348 ZigList<Buf *> darwin_frameworks;
13301349 // add -rpath [name] args to linker
......@@ -1344,6 +1363,7 @@ struct CodeGen {
13441363 HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> exported_symbol_names;
13451364 HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes;
13461365
1366
13471367 ZigList<ImportTableEntry *> import_queue;
13481368 size_t import_queue_index;
13491369 ZigList<Tld *> resolve_queue;
......@@ -1402,7 +1422,6 @@ struct CodeGen {
14021422 bool have_pub_main;
14031423 bool have_c_main;
14041424 bool have_pub_panic;
1405 bool link_libc;
14061425 Buf *libc_lib_dir;
14071426 Buf *libc_static_lib_dir;
14081427 Buf *libc_include_dir;
src/analyze.cpp+108-62
......@@ -802,6 +802,21 @@ TypeTableEntry *get_bound_fn_type(CodeGen *g, FnTableEntry *fn_entry) {
802802 return bound_fn_type;
803803}
804804
805bool calling_convention_does_first_arg_return(CallingConvention cc) {
806 return cc == CallingConventionUnspecified;
807}
808
809static const char *calling_convention_name(CallingConvention cc) {
810 switch (cc) {
811 case CallingConventionUnspecified: return "undefined";
812 case CallingConventionC: return "ccc";
813 case CallingConventionCold: return "coldcc";
814 case CallingConventionNaked: return "nakedcc";
815 case CallingConventionStdcall: return "stdcallcc";
816 default: zig_unreachable();
817 }
818}
819
805820TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
806821 auto table_entry = g->fn_type_table.maybe_get(fn_type_id);
807822 if (table_entry) {
......@@ -813,30 +828,29 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
813828 fn_type->is_copyable = true;
814829 fn_type->data.fn.fn_type_id = *fn_type_id;
815830
816 if (fn_type_id->is_cold) {
817 // cold calling convention only works on x86.
818 // but we can add the cold attribute later.
819 if (g->zig_target.arch.arch == ZigLLVM_x86 ||
820 g->zig_target.arch.arch == ZigLLVM_x86_64)
821 {
822 fn_type->data.fn.calling_convention = LLVMColdCallConv;
823 } else {
824 fn_type->data.fn.calling_convention = LLVMFastCallConv;
825 }
826 } else if (fn_type_id->is_extern) {
827 fn_type->data.fn.calling_convention = LLVMCCallConv;
828 } else {
829 fn_type->data.fn.calling_convention = LLVMFastCallConv;
830 }
831
832831 bool skip_debug_info = false;
833832
834833 // populate the name of the type
835834 buf_resize(&fn_type->name, 0);
836 const char *extern_str = fn_type_id->is_extern ? "extern " : "";
837 const char *naked_str = fn_type_id->is_naked ? "nakedcc " : "";
838 const char *cold_str = fn_type_id->is_cold ? "coldcc " : "";
839 buf_appendf(&fn_type->name, "%s%s%sfn(", extern_str, naked_str, cold_str);
835 const char *cc_str;
836 switch (fn_type->data.fn.fn_type_id.cc) {
837 case CallingConventionUnspecified:
838 cc_str = "";
839 break;
840 case CallingConventionC:
841 cc_str = "extern ";
842 break;
843 case CallingConventionCold:
844 cc_str = "coldcc ";
845 break;
846 case CallingConventionNaked:
847 cc_str = "nakedcc ";
848 break;
849 case CallingConventionStdcall:
850 cc_str = "stdcallcc ";
851 break;
852 }
853 buf_appendf(&fn_type->name, "%sfn(", cc_str);
840854 for (size_t i = 0; i < fn_type_id->param_count; i += 1) {
841855 FnTypeParamInfo *param_info = &fn_type_id->param_info[i];
842856
......@@ -861,7 +875,8 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
861875 // next, loop over the parameters again and compute debug information
862876 // and codegen information
863877 if (!skip_debug_info) {
864 bool first_arg_return = !fn_type_id->is_extern && handle_is_ptr(fn_type_id->return_type);
878 bool first_arg_return = calling_convention_does_first_arg_return(fn_type_id->cc) &&
879 handle_is_ptr(fn_type_id->return_type);
865880 // +1 for maybe making the first argument the return value
866881 LLVMTypeRef *gen_param_types = allocate<LLVMTypeRef>(1 + fn_type_id->param_count);
867882 // +1 because 0 is the return type and +1 for maybe making first arg ret val
......@@ -1013,9 +1028,13 @@ void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, size_t param_cou
10131028 assert(proto_node->type == NodeTypeFnProto);
10141029 AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
10151030
1016 fn_type_id->is_extern = fn_proto->is_extern || (fn_proto->visib_mod == VisibModExport);
1017 fn_type_id->is_naked = fn_proto->is_nakedcc;
1018 fn_type_id->is_cold = fn_proto->is_coldcc;
1031 if (fn_proto->cc == CallingConventionUnspecified) {
1032 bool extern_abi = fn_proto->is_extern || (fn_proto->visib_mod == VisibModExport);
1033 fn_type_id->cc = extern_abi ? CallingConventionC : CallingConventionUnspecified;
1034 } else {
1035 fn_type_id->cc = fn_proto->cc;
1036 }
1037
10191038 fn_type_id->param_count = fn_proto->params.length;
10201039 fn_type_id->param_info = allocate_nonzero<FnTypeParamInfo>(param_count_alloc);
10211040 fn_type_id->next_param_index = 0;
......@@ -1037,18 +1056,24 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
10371056 bool param_is_var_args = param_node->data.param_decl.is_var_args;
10381057
10391058 if (param_is_comptime) {
1040 if (fn_type_id.is_extern) {
1059 if (fn_type_id.cc != CallingConventionUnspecified) {
10411060 add_node_error(g, param_node,
1042 buf_sprintf("comptime parameter not allowed in extern function"));
1061 buf_sprintf("comptime parameter not allowed in function with calling convention '%s'",
1062 calling_convention_name(fn_type_id.cc)));
10431063 return g->builtin_types.entry_invalid;
10441064 }
10451065 return get_generic_fn_type(g, &fn_type_id);
10461066 } else if (param_is_var_args) {
1047 if (fn_type_id.is_extern) {
1067 if (fn_type_id.cc == CallingConventionC) {
10481068 fn_type_id.param_count = fn_type_id.next_param_index;
10491069 continue;
1050 } else {
1070 } else if (fn_type_id.cc == CallingConventionUnspecified) {
10511071 return get_generic_fn_type(g, &fn_type_id);
1072 } else {
1073 add_node_error(g, param_node,
1074 buf_sprintf("var args not allowed in function with calling convention '%s'",
1075 calling_convention_name(fn_type_id.cc)));
1076 return g->builtin_types.entry_invalid;
10521077 }
10531078 }
10541079
......@@ -1066,9 +1091,10 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
10661091 buf_sprintf("parameter of type '%s' not allowed", buf_ptr(&type_entry->name)));
10671092 return g->builtin_types.entry_invalid;
10681093 case TypeTableEntryIdVar:
1069 if (fn_type_id.is_extern) {
1094 if (fn_type_id.cc != CallingConventionUnspecified) {
10701095 add_node_error(g, param_node->data.param_decl.type,
1071 buf_sprintf("parameter of type 'var' not allowed in extern function"));
1096 buf_sprintf("parameter of type 'var' not allowed in function with calling convention '%s'",
1097 calling_convention_name(fn_type_id.cc)));
10721098 return g->builtin_types.entry_invalid;
10731099 }
10741100 return get_generic_fn_type(g, &fn_type_id);
......@@ -1097,7 +1123,7 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
10971123 case TypeTableEntryIdFn:
10981124 case TypeTableEntryIdEnumTag:
10991125 ensure_complete_type(g, type_entry);
1100 if (!fn_type_id.is_extern && !type_is_copyable(g, type_entry)) {
1126 if (fn_type_id.cc == CallingConventionUnspecified && !type_is_copyable(g, type_entry)) {
11011127 add_node_error(g, param_node->data.param_decl.type,
11021128 buf_sprintf("type '%s' is not copyable; cannot pass by value", buf_ptr(&type_entry->name)));
11031129 return g->builtin_types.entry_invalid;
......@@ -1130,10 +1156,11 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
11301156 case TypeTableEntryIdBoundFn:
11311157 case TypeTableEntryIdVar:
11321158 case TypeTableEntryIdMetaType:
1133 if (fn_type_id.is_extern) {
1159 if (fn_type_id.cc != CallingConventionUnspecified) {
11341160 add_node_error(g, fn_proto->return_type,
1135 buf_sprintf("return type '%s' not allowed in extern function",
1136 buf_ptr(&fn_type_id.return_type->name)));
1161 buf_sprintf("return type '%s' not allowed in function with calling convention '%s'",
1162 buf_ptr(&fn_type_id.return_type->name),
1163 calling_convention_name(fn_type_id.cc)));
11371164 return g->builtin_types.entry_invalid;
11381165 }
11391166 return get_generic_fn_type(g, &fn_type_id);
......@@ -1947,7 +1974,7 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
19471974 if (buf_eql_str(&fn_table_entry->symbol_name, "main")) {
19481975 g->main_fn = fn_table_entry;
19491976
1950 if (!g->link_libc && tld_fn->base.visib_mod != VisibModExport) {
1977 if (g->libc_link_lib == nullptr && tld_fn->base.visib_mod != VisibModExport) {
19511978 TypeTableEntry *err_void = get_error_type(g, g->builtin_types.entry_void);
19521979 TypeTableEntry *actual_return_type = fn_table_entry->type_entry->data.fn.fn_type_id.return_type;
19531980 if (actual_return_type != err_void) {
......@@ -2109,6 +2136,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
21092136 VisibMod visib_mod = node->data.variable_declaration.visib_mod;
21102137 TldVar *tld_var = allocate<TldVar>(1);
21112138 init_tld(&tld_var->base, TldIdVar, name, visib_mod, node, &decls_scope->base);
2139 tld_var->extern_lib_name = node->data.variable_declaration.lib_name;
21122140 add_top_level_decl(g, decls_scope, &tld_var->base);
21132141 break;
21142142 }
......@@ -2124,6 +2152,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
21242152 VisibMod visib_mod = node->data.fn_proto.visib_mod;
21252153 TldFn *tld_fn = allocate<TldFn>(1);
21262154 init_tld(&tld_fn->base, TldIdFn, fn_name, visib_mod, node, &decls_scope->base);
2155 tld_fn->extern_lib_name = node->data.fn_proto.lib_name;
21272156 add_top_level_decl(g, decls_scope, &tld_fn->base);
21282157
21292158 ImportTableEntry *import = get_scope_import(&decls_scope->base);
......@@ -2497,13 +2526,7 @@ bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *
24972526 if (expected_type->id == TypeTableEntryIdFn &&
24982527 actual_type->id == TypeTableEntryIdFn)
24992528 {
2500 if (expected_type->data.fn.fn_type_id.is_extern != actual_type->data.fn.fn_type_id.is_extern) {
2501 return false;
2502 }
2503 if (expected_type->data.fn.fn_type_id.is_naked != actual_type->data.fn.fn_type_id.is_naked) {
2504 return false;
2505 }
2506 if (expected_type->data.fn.fn_type_id.is_cold != actual_type->data.fn.fn_type_id.is_cold) {
2529 if (expected_type->data.fn.fn_type_id.cc != actual_type->data.fn.fn_type_id.cc) {
25072530 return false;
25082531 }
25092532 if (expected_type->data.fn.fn_type_id.is_var_args != actual_type->data.fn.fn_type_id.is_var_args) {
......@@ -2780,11 +2803,6 @@ void define_local_param_variables(CodeGen *g, FnTableEntry *fn_table_entry, Vari
27802803 add_node_error(g, param_decl_node, buf_sprintf("noalias on non-pointer parameter"));
27812804 }
27822805
2783 if (fn_type_id->is_extern && handle_is_ptr(param_type)) {
2784 add_node_error(g, param_decl_node,
2785 buf_sprintf("byvalue types not yet supported on extern function parameters"));
2786 }
2787
27882806 VariableTableEntry *var = add_variable(g, param_decl_node, fn_table_entry->child_scope,
27892807 param_name, true, create_const_runtime(param_type), nullptr);
27902808 var->src_arg_index = i;
......@@ -2849,12 +2867,6 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {
28492867
28502868 TypeTableEntry *fn_type = fn_table_entry->type_entry;
28512869 assert(!fn_type->data.fn.is_generic);
2852 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
2853
2854 if (fn_type_id->is_extern && handle_is_ptr(fn_type_id->return_type)) {
2855 add_node_error(g, return_type_node,
2856 buf_sprintf("byvalue types not yet supported on extern function return values"));
2857 }
28582870
28592871 ir_gen_fn(g, fn_table_entry);
28602872 if (fn_table_entry->ir_executable.invalid) {
......@@ -3018,7 +3030,7 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *a
30183030 g->have_pub_panic = true;
30193031 }
30203032 } else if (proto_node->data.fn_proto.visib_mod == VisibModExport && buf_eql_str(proto_name, "main") &&
3021 g->link_libc)
3033 g->libc_link_lib != nullptr)
30223034 {
30233035 g->have_c_main = true;
30243036 }
......@@ -3189,9 +3201,7 @@ bool fn_table_entry_eql(FnTableEntry *a, FnTableEntry *b) {
31893201
31903202uint32_t fn_type_id_hash(FnTypeId *id) {
31913203 uint32_t result = 0;
3192 result += id->is_extern ? (uint32_t)3349388391 : 0;
3193 result += id->is_naked ? (uint32_t)608688877 : 0;
3194 result += id->is_cold ? (uint32_t)3605523458 : 0;
3204 result += ((uint32_t)(id->cc)) * (uint32_t)3349388391;
31953205 result += id->is_var_args ? (uint32_t)1931444534 : 0;
31963206 result += hash_ptr(id->return_type);
31973207 for (size_t i = 0; i < id->param_count; i += 1) {
......@@ -3203,9 +3213,7 @@ uint32_t fn_type_id_hash(FnTypeId *id) {
32033213}
32043214
32053215bool fn_type_id_eql(FnTypeId *a, FnTypeId *b) {
3206 if (a->is_extern != b->is_extern ||
3207 a->is_naked != b->is_naked ||
3208 a->is_cold != b->is_cold ||
3216 if (a->cc != b->cc ||
32093217 a->return_type != b->return_type ||
32103218 a->is_var_args != b->is_var_args ||
32113219 a->param_count != b->param_count)
......@@ -4344,8 +4352,7 @@ FnTableEntry *get_extern_panic_fn(CodeGen *g) {
43444352 return g->extern_panic_fn;
43454353
43464354 FnTypeId fn_type_id = {0};
4347 fn_type_id.is_extern = true;
4348 fn_type_id.is_cold = true;
4355 fn_type_id.cc = CallingConventionCold;
43494356 fn_type_id.param_count = 2;
43504357 fn_type_id.param_info = allocate<FnTypeParamInfo>(2);
43514358 fn_type_id.next_param_index = 0;
......@@ -4525,3 +4532,42 @@ const char *type_id_name(TypeTableEntryId id) {
45254532 }
45264533 zig_unreachable();
45274534}
4535
4536LinkLib *create_link_lib(Buf *name) {
4537 LinkLib *link_lib = allocate<LinkLib>(1);
4538 link_lib->name = name;
4539 return link_lib;
4540}
4541
4542LinkLib *add_link_lib(CodeGen *g, Buf *name) {
4543 bool is_libc = buf_eql_str(name, "c");
4544
4545 if (is_libc && g->libc_link_lib != nullptr)
4546 return g->libc_link_lib;
4547
4548 for (size_t i = 0; i < g->link_libs_list.length; i += 1) {
4549 LinkLib *existing_lib = g->link_libs_list.at(i);
4550 if (buf_eql_buf(existing_lib->name, name)) {
4551 return existing_lib;
4552 }
4553 }
4554
4555 LinkLib *link_lib = create_link_lib(name);
4556 g->link_libs_list.append(link_lib);
4557
4558 if (is_libc)
4559 g->libc_link_lib = link_lib;
4560
4561 return link_lib;
4562}
4563
4564void add_link_lib_symbol(CodeGen *g, Buf *lib_name, Buf *symbol_name) {
4565 LinkLib *link_lib = add_link_lib(g, lib_name);
4566 for (size_t i = 0; i < link_lib->symbols.length; i += 1) {
4567 Buf *existing_symbol_name = link_lib->symbols.at(i);
4568 if (buf_eql_buf(existing_symbol_name, symbol_name)) {
4569 return;
4570 }
4571 }
4572 link_lib->symbols.append(symbol_name);
4573}
src/analyze.hpp+4
......@@ -168,5 +168,9 @@ size_t type_id_len();
168168size_t type_id_index(TypeTableEntryId id);
169169TypeTableEntry *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id);
170170bool type_is_copyable(CodeGen *g, TypeTableEntry *type_entry);
171LinkLib *create_link_lib(Buf *name);
172bool calling_convention_does_first_arg_return(CallingConvention cc);
173LinkLib *add_link_lib(CodeGen *codegen, Buf *lib);
174void add_link_lib_symbol(CodeGen *g, Buf *lib_name, Buf *symbol_name);
171175
172176#endif
src/ast_render.cpp+13-4
......@@ -118,6 +118,17 @@ static const char *extern_string(bool is_extern) {
118118 return is_extern ? "extern " : "";
119119}
120120
121static const char *calling_convention_string(CallingConvention cc) {
122 switch (cc) {
123 case CallingConventionUnspecified: return "";
124 case CallingConventionC: return "extern ";
125 case CallingConventionCold: return "coldcc ";
126 case CallingConventionNaked: return "nakedcc ";
127 case CallingConventionStdcall: return "stdcallcc ";
128 }
129 zig_unreachable();
130}
131
121132static const char *inline_string(bool is_inline) {
122133 return is_inline ? "inline " : "";
123134}
......@@ -951,10 +962,8 @@ static void ast_render_tld_fn(AstRender *ar, Buf *name, TldFn *tld_fn) {
951962 FnTableEntry *fn_entry = tld_fn->fn_entry;
952963 FnTypeId *fn_type_id = &fn_entry->type_entry->data.fn.fn_type_id;
953964 const char *visib_mod_str = visib_mod_string(tld_fn->base.visib_mod);
954 const char *extern_str = extern_string(fn_type_id->is_extern);
955 const char *coldcc_str = fn_type_id->is_cold ? "coldcc " : "";
956 const char *nakedcc_str = fn_type_id->is_naked ? "nakedcc " : "";
957 fprintf(ar->f, "%s%s%s%sfn %s(", visib_mod_str, extern_str, coldcc_str, nakedcc_str, buf_ptr(&fn_entry->symbol_name));
965 const char *cc_str = calling_convention_string(fn_type_id->cc);
966 fprintf(ar->f, "%s%sfn %s(", visib_mod_str, cc_str, buf_ptr(&fn_entry->symbol_name));
958967 for (size_t i = 0; i < fn_type_id->param_count; i += 1) {
959968 FnTypeParamInfo *param_info = &fn_type_id->param_info[i];
960969 if (i != 0) {
src/codegen.cpp+58-33
......@@ -138,8 +138,7 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
138138 g->zig_target.os == ZigLLVM_MacOSX ||
139139 g->zig_target.os == ZigLLVM_IOS)
140140 {
141 g->link_libc = true;
142 g->link_libs.append(buf_create_from_str("c"));
141 g->libc_link_lib = create_link_lib(buf_create_from_str("c"));
143142 }
144143
145144 return g;
......@@ -234,13 +233,8 @@ void codegen_add_rpath(CodeGen *g, const char *name) {
234233 g->rpath_list.append(buf_create_from_str(name));
235234}
236235
237void codegen_add_link_lib(CodeGen *g, const char *lib) {
238 if (strcmp(lib, "c") == 0) {
239 if (g->link_libc)
240 return;
241 g->link_libc = true;
242 }
243 g->link_libs.append(buf_create_from_str(lib));
236LinkLib *codegen_add_link_lib(CodeGen *g, Buf *name) {
237 return add_link_lib(g, name);
244238}
245239
246240void codegen_add_framework(CodeGen *g, const char *framework) {
......@@ -334,6 +328,33 @@ static Buf *get_mangled_name(CodeGen *g, Buf *original_name, bool external_linka
334328 }
335329}
336330
331static LLVMCallConv get_llvm_cc(CodeGen *g, CallingConvention cc) {
332 switch (cc) {
333 case CallingConventionUnspecified: return LLVMFastCallConv;
334 case CallingConventionC: return LLVMCCallConv;
335 case CallingConventionCold:
336 // cold calling convention only works on x86.
337 if (g->zig_target.arch.arch == ZigLLVM_x86 ||
338 g->zig_target.arch.arch == ZigLLVM_x86_64)
339 {
340 return LLVMColdCallConv;
341 } else {
342 return LLVMCCallConv;
343 }
344 break;
345 case CallingConventionNaked:
346 zig_unreachable();
347 case CallingConventionStdcall:
348 // stdcall calling convention only works on x86.
349 if (g->zig_target.arch.arch == ZigLLVM_x86) {
350 return LLVMX86StdcallCallConv;
351 } else {
352 return LLVMCCallConv;
353 }
354 }
355 zig_unreachable();
356}
357
337358static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
338359 if (fn_table_entry->llvm_value)
339360 return fn_table_entry->llvm_value;
......@@ -355,6 +376,16 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
355376 }
356377 fn_table_entry->llvm_name = LLVMGetValueName(fn_table_entry->llvm_value);
357378
379 //if (buf_eql_str(&fn_table_entry->symbol_name, "ExitProcess") ||
380 // buf_eql_str(&fn_table_entry->symbol_name, "GetConsoleMode") ||
381 // buf_eql_str(&fn_table_entry->symbol_name, "GetStdHandle") ||
382 // buf_eql_str(&fn_table_entry->symbol_name, "GetFileInformationByHandleEx") ||
383 // buf_eql_str(&fn_table_entry->symbol_name, "GetLastError") ||
384 // buf_eql_str(&fn_table_entry->symbol_name, "WriteFile"))
385 //{
386 // LLVMSetDLLStorageClass(fn_table_entry->llvm_value, LLVMDLLImportStorageClass);
387 //}
388
358389 switch (fn_table_entry->fn_inline) {
359390 case FnInlineAlways:
360391 addLLVMFnAttr(fn_table_entry->llvm_value, "alwaysinline");
......@@ -366,8 +397,14 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
366397 case FnInlineAuto:
367398 break;
368399 }
369 if (fn_type->data.fn.fn_type_id.is_naked) {
400
401 if (fn_type->data.fn.fn_type_id.cc == CallingConventionNaked) {
370402 addLLVMFnAttr(fn_table_entry->llvm_value, "naked");
403 } else {
404 LLVMSetFunctionCallConv(fn_table_entry->llvm_value, get_llvm_cc(g, fn_type->data.fn.fn_type_id.cc));
405 if (fn_type->data.fn.fn_type_id.cc == CallingConventionCold) {
406 ZigLLVMAddFunctionAttrCold(fn_table_entry->llvm_value);
407 }
371408 }
372409
373410 switch (fn_table_entry->linkage) {
......@@ -393,17 +430,13 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
393430 if (fn_table_entry->body_node != nullptr) {
394431 bool want_fn_safety = g->build_mode != BuildModeFastRelease && !fn_table_entry->def_scope->safety_off;
395432 if (want_fn_safety) {
396 if (g->link_libc) {
433 if (g->libc_link_lib != nullptr) {
397434 addLLVMFnAttr(fn_table_entry->llvm_value, "sspstrong");
398435 addLLVMFnAttrStr(fn_table_entry->llvm_value, "stack-protector-buffer-size", "4");
399436 }
400437 }
401438 }
402439
403 LLVMSetFunctionCallConv(fn_table_entry->llvm_value, fn_type->data.fn.calling_convention);
404 if (fn_type->data.fn.fn_type_id.is_cold) {
405 ZigLLVMAddFunctionAttrCold(fn_table_entry->llvm_value);
406 }
407440 addLLVMFnAttr(fn_table_entry->llvm_value, "nounwind");
408441 if (g->build_mode == BuildModeDebug && fn_table_entry->fn_inline != FnInlineAlways) {
409442 ZigLLVMAddFunctionAttr(fn_table_entry->llvm_value, "no-frame-pointer-elim", "true");
......@@ -700,7 +733,8 @@ static void gen_panic_raw(CodeGen *g, LLVMValueRef msg_ptr, LLVMValueRef msg_len
700733 FnTableEntry *panic_fn = get_extern_panic_fn(g);
701734 LLVMValueRef fn_val = fn_llvm_value(g, panic_fn);
702735 LLVMValueRef args[] = { msg_ptr, msg_len };
703 ZigLLVMBuildCall(g->builder, fn_val, args, 2, panic_fn->type_entry->data.fn.calling_convention, false, "");
736 LLVMCallConv llvm_cc = get_llvm_cc(g, panic_fn->type_entry->data.fn.fn_type_id.cc);
737 ZigLLVMBuildCall(g->builder, fn_val, args, 2, llvm_cc, false, "");
704738 LLVMBuildUnreachable(g->builder);
705739}
706740
......@@ -1100,15 +1134,14 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {
11001134static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *return_instruction) {
11011135 LLVMValueRef value = ir_llvm_value(g, return_instruction->value);
11021136 TypeTableEntry *return_type = return_instruction->value->value.type;
1103 bool is_extern = g->cur_fn->type_entry->data.fn.fn_type_id.is_extern;
11041137 if (handle_is_ptr(return_type)) {
1105 if (is_extern) {
1106 LLVMValueRef by_val_value = LLVMBuildLoad(g->builder, value, "");
1107 LLVMBuildRet(g->builder, by_val_value);
1108 } else {
1138 if (calling_convention_does_first_arg_return(g->cur_fn->type_entry->data.fn.fn_type_id.cc)) {
11091139 assert(g->cur_ret_ptr);
11101140 gen_assign_raw(g, g->cur_ret_ptr, get_pointer_to_type(g, return_type, false), value);
11111141 LLVMBuildRetVoid(g->builder);
1142 } else {
1143 LLVMValueRef by_val_value = LLVMBuildLoad(g->builder, value, "");
1144 LLVMBuildRet(g->builder, by_val_value);
11121145 }
11131146 } else {
11141147 LLVMBuildRet(g->builder, value);
......@@ -2059,9 +2092,9 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
20592092 bool want_always_inline = (instruction->fn_entry != nullptr &&
20602093 instruction->fn_entry->fn_inline == FnInlineAlways) || instruction->is_inline;
20612094
2095 LLVMCallConv llvm_cc = get_llvm_cc(g, fn_type->data.fn.fn_type_id.cc);
20622096 LLVMValueRef result = ZigLLVMBuildCall(g->builder, fn_val,
2063 gen_param_values, (unsigned)gen_param_index, fn_type->data.fn.calling_convention,
2064 want_always_inline, "");
2097 gen_param_values, (unsigned)gen_param_index, llvm_cc, want_always_inline, "");
20652098
20662099 for (size_t param_i = 0; param_i < fn_type_id->param_count; param_i += 1) {
20672100 FnGenParamInfo *gen_info = &fn_type->data.fn.gen_param_info[param_i];
......@@ -3893,7 +3926,7 @@ static void do_code_gen(CodeGen *g) {
38933926 {
38943927 addLLVMAttr(fn_val, 0, "nonnull");
38953928 } else if (handle_is_ptr(fn_type->data.fn.fn_type_id.return_type) &&
3896 !fn_type->data.fn.fn_type_id.is_extern)
3929 calling_convention_does_first_arg_return(fn_type->data.fn.fn_type_id.cc))
38973930 {
38983931 addLLVMArgAttr(fn_val, 0, "sret");
38993932 addLLVMArgAttr(fn_val, 0, "nonnull");
......@@ -4648,15 +4681,7 @@ static void define_builtin_compile_vars(CodeGen *g) {
46484681 buf_appendf(contents, "pub const environ = Environ.%s;\n", cur_environ);
46494682 buf_appendf(contents, "pub const object_format = ObjectFormat.%s;\n", cur_obj_fmt);
46504683 buf_appendf(contents, "pub const mode = %s;\n", build_mode_to_str(g->build_mode));
4651
4652 {
4653 buf_appendf(contents, "pub const link_libs = [][]const u8 {\n");
4654 for (size_t i = 0; i < g->link_libs.length; i += 1) {
4655 Buf *link_lib_buf = g->link_libs.at(i);
4656 buf_appendf(contents, " \"%s\",\n", buf_ptr(link_lib_buf));
4657 }
4658 buf_appendf(contents, "};\n");
4659 }
4684 buf_appendf(contents, "pub const link_libc = %s;\n", bool_to_str(g->libc_link_lib != nullptr));
46604685
46614686 buf_appendf(contents, "pub const __zig_panic_implementation_provided = %s; // overwritten later\n",
46624687 bool_to_str(false));
src/codegen.hpp+1-1
......@@ -33,7 +33,7 @@ void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker);
3333void codegen_set_windows_subsystem(CodeGen *g, bool mwindows, bool mconsole);
3434void codegen_set_windows_unicode(CodeGen *g, bool municode);
3535void codegen_add_lib_dir(CodeGen *codegen, const char *dir);
36void codegen_add_link_lib(CodeGen *codegen, const char *lib);
36LinkLib *codegen_add_link_lib(CodeGen *codegen, Buf *lib);
3737void codegen_add_framework(CodeGen *codegen, const char *name);
3838void codegen_add_rpath(CodeGen *codegen, const char *name);
3939void codegen_set_mlinker_version(CodeGen *g, Buf *darwin_linker_version);
src/ir.cpp+22-4
......@@ -9044,7 +9044,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
90449044
90459045 if (comptime_fn_call) {
90469046 // No special handling is needed for compile time evaluation of generic functions.
9047 if (!fn_entry || fn_entry->type_entry->data.fn.fn_type_id.is_extern) {
9047 if (!fn_entry || fn_entry->body_node == nullptr) {
90489048 ir_add_error(ira, fn_ref, buf_sprintf("unable to evaluate constant expression"));
90499049 return ira->codegen->builtin_types.entry_invalid;
90509050 }
......@@ -10129,6 +10129,10 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source
1012910129 {
1013010130 TldVar *tld_var = (TldVar *)tld;
1013110131 VariableTableEntry *var = tld_var->var;
10132 if (tld_var->extern_lib_name != nullptr) {
10133 add_link_lib_symbol(ira->codegen, tld_var->extern_lib_name, &var->name);
10134 }
10135
1013210136 return ir_analyze_var_ptr(ira, source_instruction, var, false, false);
1013310137 }
1013410138 case TldIdFn:
......@@ -10147,6 +10151,10 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source
1014710151 const_val->type = fn_entry->type_entry;
1014810152 const_val->data.x_fn.fn_entry = fn_entry;
1014910153
10154 if (tld_fn->extern_lib_name != nullptr) {
10155 add_link_lib_symbol(ira->codegen, tld_fn->extern_lib_name, &fn_entry->symbol_name);
10156 }
10157
1015010158 bool ptr_is_const = true;
1015110159 bool ptr_is_volatile = false;
1015210160 return ir_analyze_const_ptr(ira, source_instruction, const_val, fn_entry->type_entry,
......@@ -13167,13 +13175,15 @@ static TypeTableEntry *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruc
1316713175
1316813176 bool param_is_var_args = param_node->data.param_decl.is_var_args;
1316913177 if (param_is_var_args) {
13170 if (fn_type_id.is_extern) {
13178 if (fn_type_id.cc == CallingConventionC) {
1317113179 fn_type_id.param_count = fn_type_id.next_param_index;
1317213180 continue;
13173 } else {
13181 } else if (fn_type_id.cc == CallingConventionUnspecified) {
1317413182 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
1317513183 out_val->data.x_type = get_generic_fn_type(ira->codegen, &fn_type_id);
1317613184 return ira->codegen->builtin_types.entry_type;
13185 } else {
13186 zig_unreachable();
1317713187 }
1317813188 }
1317913189 IrInstruction *param_type_value = instruction->param_types[fn_type_id.next_param_index]->other;
......@@ -13484,6 +13494,10 @@ static TypeTableEntry *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
1348413494 if (type_is_invalid(var_ptr->value.type))
1348513495 return ira->codegen->builtin_types.entry_invalid;
1348613496
13497 if (tld_var->extern_lib_name != nullptr) {
13498 add_link_lib_symbol(ira->codegen, tld_var->extern_lib_name, &var->name);
13499 }
13500
1348713501 if (lval.is_ptr) {
1348813502 ir_link_new_instruction(var_ptr, &instruction->base);
1348913503 return var_ptr->value.type;
......@@ -13499,6 +13513,10 @@ static TypeTableEntry *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
1349913513 FnTableEntry *fn_entry = tld_fn->fn_entry;
1350013514 assert(fn_entry->type_entry);
1350113515
13516 if (tld_fn->extern_lib_name != nullptr) {
13517 add_link_lib_symbol(ira->codegen, tld_fn->extern_lib_name, &fn_entry->symbol_name);
13518 }
13519
1350213520 IrInstruction *ref_instruction = ir_create_const_fn(&ira->new_irb, instruction->base.scope,
1350313521 instruction->base.source_node, fn_entry);
1350413522 if (lval.is_ptr) {
......@@ -13896,7 +13914,7 @@ FnTableEntry *ir_create_inline_fn(CodeGen *codegen, Buf *fn_name, VariableTableE
1389613914 assert(src_fn_type->id == TypeTableEntryIdFn);
1389713915
1389813916 FnTypeId new_fn_type = src_fn_type->data.fn.fn_type_id;
13899 new_fn_type.is_extern = false;
13917 new_fn_type.cc = CallingConventionUnspecified;
1390013918
1390113919 fn_entry->type_entry = get_fn_type(codegen, &new_fn_type);
1390213920
src/link.cpp+46-34
......@@ -38,12 +38,6 @@ static Buf *build_o(CodeGen *parent_gen, const char *oname) {
3838
3939 ZigTarget *child_target = parent_gen->is_native_target ? nullptr : &parent_gen->zig_target;
4040 CodeGen *child_gen = codegen_create(full_path, child_target, OutTypeObj, parent_gen->build_mode);
41 child_gen->link_libc = parent_gen->link_libc;
42
43 child_gen->link_libs.resize(parent_gen->link_libs.length);
44 for (size_t i = 0; i < parent_gen->link_libs.length; i += 1) {
45 child_gen->link_libs.items[i] = parent_gen->link_libs.items[i];
46 }
4741
4842 codegen_set_omit_zigrt(child_gen, true);
4943 child_gen->want_h_file = false;
......@@ -215,13 +209,13 @@ static void construct_linker_job_elf(LinkJob *lj) {
215209 if (g->each_lib_rpath) {
216210 for (size_t i = 0; i < g->lib_dirs.length; i += 1) {
217211 const char *lib_dir = g->lib_dirs.at(i);
218 for (size_t i = 0; i < g->link_libs.length; i += 1) {
219 Buf *link_lib = g->link_libs.at(i);
220 if (buf_eql_str(link_lib, "c")) {
212 for (size_t i = 0; i < g->link_libs_list.length; i += 1) {
213 LinkLib *link_lib = g->link_libs_list.at(i);
214 if (buf_eql_str(link_lib->name, "c")) {
221215 continue;
222216 }
223217 bool does_exist;
224 Buf *test_path = buf_sprintf("%s/lib%s.so", lib_dir, buf_ptr(link_lib));
218 Buf *test_path = buf_sprintf("%s/lib%s.so", lib_dir, buf_ptr(link_lib->name));
225219 if (os_file_exists(test_path, &does_exist) != ErrorNone) {
226220 zig_panic("link: unable to check if file exists: %s", buf_ptr(test_path));
227221 }
......@@ -239,7 +233,7 @@ static void construct_linker_job_elf(LinkJob *lj) {
239233 lj->args.append(lib_dir);
240234 }
241235
242 if (g->link_libc) {
236 if (g->libc_link_lib != nullptr) {
243237 lj->args.append("-L");
244238 lj->args.append(buf_ptr(g->libc_lib_dir));
245239
......@@ -265,7 +259,7 @@ static void construct_linker_job_elf(LinkJob *lj) {
265259 lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));
266260 }
267261
268 if (!g->link_libc && (g->out_type == OutTypeExe || g->out_type == OutTypeLib)) {
262 if (g->libc_link_lib == nullptr && (g->out_type == OutTypeExe || g->out_type == OutTypeLib)) {
269263 Buf *builtin_o_path = build_o(g, "builtin");
270264 lj->args.append(buf_ptr(builtin_o_path));
271265
......@@ -273,25 +267,25 @@ static void construct_linker_job_elf(LinkJob *lj) {
273267 lj->args.append(buf_ptr(compiler_rt_o_path));
274268 }
275269
276 for (size_t i = 0; i < g->link_libs.length; i += 1) {
277 Buf *link_lib = g->link_libs.at(i);
278 if (buf_eql_str(link_lib, "c")) {
270 for (size_t i = 0; i < g->link_libs_list.length; i += 1) {
271 LinkLib *link_lib = g->link_libs_list.at(i);
272 if (buf_eql_str(link_lib->name, "c")) {
279273 continue;
280274 }
281275 Buf *arg;
282 if (buf_starts_with_str(link_lib, "/") || buf_ends_with_str(link_lib, ".a") ||
283 buf_ends_with_str(link_lib, ".so"))
276 if (buf_starts_with_str(link_lib->name, "/") || buf_ends_with_str(link_lib->name, ".a") ||
277 buf_ends_with_str(link_lib->name, ".so"))
284278 {
285 arg = link_lib;
279 arg = link_lib->name;
286280 } else {
287 arg = buf_sprintf("-l%s", buf_ptr(link_lib));
281 arg = buf_sprintf("-l%s", buf_ptr(link_lib->name));
288282 }
289283 lj->args.append(buf_ptr(arg));
290284 }
291285
292286
293287 // libc dep
294 if (g->link_libc) {
288 if (g->libc_link_lib != nullptr) {
295289 if (g->is_static) {
296290 lj->args.append("--start-group");
297291 lj->args.append("-lgcc");
......@@ -394,7 +388,7 @@ static void construct_linker_job_coff(LinkJob *lj) {
394388 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", lib_dir)));
395389 }
396390
397 if (g->link_libc) {
391 if (g->libc_link_lib != nullptr) {
398392 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_lib_dir))));
399393 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_static_lib_dir))));
400394 }
......@@ -403,7 +397,7 @@ static void construct_linker_job_coff(LinkJob *lj) {
403397 lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));
404398 }
405399
406 if (!g->link_libc && (g->out_type == OutTypeExe || g->out_type == OutTypeLib)) {
400 if (g->libc_link_lib == nullptr && (g->out_type == OutTypeExe || g->out_type == OutTypeLib)) {
407401 Buf *builtin_o_path = build_o(g, "builtin");
408402 lj->args.append(buf_ptr(builtin_o_path));
409403
......@@ -411,17 +405,35 @@ static void construct_linker_job_coff(LinkJob *lj) {
411405 lj->args.append(buf_ptr(compiler_rt_o_path));
412406 }
413407
414
415 for (size_t i = 0; i < g->link_libs.length; i += 1) {
416 Buf *link_lib = g->link_libs.at(i);
417 if (buf_eql_str(link_lib, "c")) {
408 Buf *def_contents = buf_alloc();
409 for (size_t lib_i = 0; lib_i < g->link_libs_list.length; lib_i += 1) {
410 LinkLib *link_lib = g->link_libs_list.at(lib_i);
411 if (buf_eql_str(link_lib->name, "c")) {
418412 continue;
419413 }
420 Buf *arg = buf_sprintf("-l%s", buf_ptr(link_lib));
421 lj->args.append(buf_ptr(arg));
414 if (link_lib->provided_explicitly) {
415 Buf *arg = buf_sprintf("-l%s", buf_ptr(link_lib->name));
416 lj->args.append(buf_ptr(arg));
417 } else {
418 buf_appendf(def_contents, "LIBRARY %s\nEXPORTS\n", buf_ptr(link_lib->name));
419 for (size_t exp_i = 0; exp_i < link_lib->symbols.length; exp_i += 1) {
420 Buf *symbol_name = link_lib->symbols.at(exp_i);
421 buf_appendf(def_contents, "%s\n", buf_ptr(symbol_name));
422 }
423 buf_appendf(def_contents, "\n");
424 }
425 }
426 if (buf_len(def_contents) != 0) {
427 Buf *dll_path = buf_alloc();
428 os_path_join(g->cache_dir, buf_create_from_str("all.dll"), dll_path);
429 ZigLLDDefToLib(def_contents, dll_path);
430
431 Buf *all_lib_path = buf_alloc();
432 os_path_join(g->cache_dir, buf_create_from_str("all.lib"), all_lib_path);
433 lj->args.append(buf_ptr(all_lib_path));
422434 }
423435
424 if (g->link_libc) {
436 if (g->libc_link_lib != nullptr) {
425437 if (g->is_static) {
426438 lj->args.append("--start-group");
427439 }
......@@ -664,12 +676,12 @@ static void construct_linker_job_macho(LinkJob *lj) {
664676 lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));
665677 }
666678
667 for (size_t i = 0; i < g->link_libs.length; i += 1) {
668 Buf *link_lib = g->link_libs.at(i);
669 if (buf_eql_str(link_lib, "c")) {
679 for (size_t i = 0; i < g->link_libs_list.length; i += 1) {
680 LinkLib *link_lib = g->link_libs_list.at(i);
681 if (buf_eql_str(link_lib->name, "c")) {
670682 continue;
671683 }
672 Buf *arg = buf_sprintf("-l%s", buf_ptr(link_lib));
684 Buf *arg = buf_sprintf("-l%s", buf_ptr(link_lib->name));
673685 lj->args.append(buf_ptr(arg));
674686 }
675687
......@@ -771,7 +783,7 @@ void codegen_link(CodeGen *g, const char *out_file) {
771783 return;
772784 }
773785
774 lj.link_in_crt = (g->link_libc && g->out_type == OutTypeExe);
786 lj.link_in_crt = (g->libc_link_lib != nullptr && g->out_type == OutTypeExe);
775787
776788 construct_linker_job(&lj);
777789
src/main.cpp+2-1
......@@ -601,7 +601,8 @@ int main(int argc, char **argv) {
601601 codegen_add_lib_dir(g, lib_dirs.at(i));
602602 }
603603 for (size_t i = 0; i < link_libs.length; i += 1) {
604 codegen_add_link_lib(g, link_libs.at(i));
604 LinkLib *link_lib = codegen_add_link_lib(g, buf_create_from_str(link_libs.at(i)));
605 link_lib->provided_explicitly = true;
605606 }
606607 for (size_t i = 0; i < frameworks.length; i += 1) {
607608 codegen_add_framework(g, frameworks.at(i));
src/parseh.cpp+2-3
......@@ -477,8 +477,7 @@ static TypeTableEntry *resolve_type_with_table(Context *c, const Type *ty, const
477477 }
478478
479479 FnTypeId fn_type_id = {0};
480 fn_type_id.is_naked = false;
481 fn_type_id.is_extern = true;
480 fn_type_id.cc = CallingConventionC;
482481 fn_type_id.is_var_args = fn_proto_ty->isVariadic();
483482 fn_type_id.param_count = fn_proto_ty->getNumParams();
484483
......@@ -619,7 +618,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
619618 buf_init_from_buf(&fn_entry->symbol_name, fn_name);
620619 fn_entry->type_entry = fn_type;
621620
622 assert(!fn_type->data.fn.fn_type_id.is_naked);
621 assert(fn_type->data.fn.fn_type_id.cc != CallingConventionNaked);
623622
624623 size_t arg_count = fn_type->data.fn.fn_type_id.param_count;
625624 fn_entry->param_names = allocate<Buf *>(arg_count);
src/parser.cpp+20-8
......@@ -2123,25 +2123,29 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand
21232123}
21242124
21252125/*
2126FnProto = option("coldcc" | "nakedcc") "fn" option(Symbol) ParamDeclList option("->" TypeExpr)
2126FnProto = option("coldcc" | "nakedcc" | "stdcallcc") "fn" option(Symbol) ParamDeclList option("->" TypeExpr)
21272127*/
21282128static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) {
21292129 Token *first_token = &pc->tokens->at(*token_index);
21302130 Token *fn_token;
21312131
2132 bool is_coldcc = false;
2133 bool is_nakedcc = false;
2132 CallingConvention cc;
21342133 if (first_token->id == TokenIdKeywordColdCC) {
21352134 *token_index += 1;
21362135 fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn);
2137 is_coldcc = true;
2136 cc = CallingConventionCold;
21382137 } else if (first_token->id == TokenIdKeywordNakedCC) {
21392138 *token_index += 1;
21402139 fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn);
2141 is_nakedcc = true;
2140 cc = CallingConventionNaked;
2141 } else if (first_token->id == TokenIdKeywordStdcallCC) {
2142 *token_index += 1;
2143 fn_token = ast_eat_token(pc, token_index, TokenIdKeywordFn);
2144 cc = CallingConventionStdcall;
21422145 } else if (first_token->id == TokenIdKeywordFn) {
21432146 fn_token = first_token;
21442147 *token_index += 1;
2148 cc = CallingConventionUnspecified;
21452149 } else if (mandatory) {
21462150 ast_expect_token(pc, first_token, TokenIdKeywordFn);
21472151 zig_unreachable();
......@@ -2151,8 +2155,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool m
21512155
21522156 AstNode *node = ast_create_node(pc, NodeTypeFnProto, fn_token);
21532157 node->data.fn_proto.visib_mod = visib_mod;
2154 node->data.fn_proto.is_coldcc = is_coldcc;
2155 node->data.fn_proto.is_nakedcc = is_nakedcc;
2158 node->data.fn_proto.cc = cc;
21562159
21572160 Token *fn_name = &pc->tokens->at(*token_index);
21582161 if (fn_name->id == TokenIdSymbol) {
......@@ -2220,7 +2223,7 @@ static AstNode *ast_parse_fn_def(ParseContext *pc, size_t *token_index, bool man
22202223}
22212224
22222225/*
2223ExternDecl = "extern" (FnProto | VariableDeclaration) ";"
2226ExternDecl = "extern" option(String) (FnProto | VariableDeclaration) ";"
22242227*/
22252228static AstNode *ast_parse_extern_decl(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod) {
22262229 Token *extern_kw = &pc->tokens->at(*token_index);
......@@ -2233,11 +2236,19 @@ static AstNode *ast_parse_extern_decl(ParseContext *pc, size_t *token_index, boo
22332236 }
22342237 *token_index += 1;
22352238
2239 Token *lib_name_tok = &pc->tokens->at(*token_index);
2240 Buf *lib_name = nullptr;
2241 if (lib_name_tok->id == TokenIdStringLiteral) {
2242 lib_name = token_buf(lib_name_tok);
2243 *token_index += 1;
2244 }
2245
22362246 AstNode *fn_proto_node = ast_parse_fn_proto(pc, token_index, false, visib_mod);
22372247 if (fn_proto_node) {
22382248 ast_eat_token(pc, token_index, TokenIdSemicolon);
22392249
22402250 fn_proto_node->data.fn_proto.is_extern = true;
2251 fn_proto_node->data.fn_proto.lib_name = lib_name;
22412252
22422253 return fn_proto_node;
22432254 }
......@@ -2247,6 +2258,7 @@ static AstNode *ast_parse_extern_decl(ParseContext *pc, size_t *token_index, boo
22472258 ast_eat_token(pc, token_index, TokenIdSemicolon);
22482259
22492260 var_decl_node->data.variable_declaration.is_extern = true;
2261 var_decl_node->data.variable_declaration.lib_name = lib_name;
22502262
22512263 return var_decl_node;
22522264 }
src/tokenizer.cpp+2
......@@ -133,6 +133,7 @@ static const struct ZigKeyword zig_keywords[] = {
133133 {"packed", TokenIdKeywordPacked},
134134 {"pub", TokenIdKeywordPub},
135135 {"return", TokenIdKeywordReturn},
136 {"stdcallcc", TokenIdKeywordStdcallCC},
136137 {"struct", TokenIdKeywordStruct},
137138 {"switch", TokenIdKeywordSwitch},
138139 {"test", TokenIdKeywordTest},
......@@ -1471,6 +1472,7 @@ const char * token_name(TokenId id) {
14711472 case TokenIdKeywordPacked: return "packed";
14721473 case TokenIdKeywordPub: return "pub";
14731474 case TokenIdKeywordReturn: return "return";
1475 case TokenIdKeywordStdcallCC: return "stdcallcc";
14741476 case TokenIdKeywordStruct: return "struct";
14751477 case TokenIdKeywordSwitch: return "switch";
14761478 case TokenIdKeywordTest: return "test";
src/tokenizer.hpp+1
......@@ -71,6 +71,7 @@ enum TokenId {
7171 TokenIdKeywordPacked,
7272 TokenIdKeywordPub,
7373 TokenIdKeywordReturn,
74 TokenIdKeywordStdcallCC,
7475 TokenIdKeywordStruct,
7576 TokenIdKeywordSwitch,
7677 TokenIdKeywordTest,
src/zig_llvm.cpp+149
......@@ -38,6 +38,7 @@
3838#include <llvm/Support/FileSystem.h>
3939#include <llvm/Support/TargetParser.h>
4040#include <llvm/Support/raw_ostream.h>
41#include <llvm/Support/COFF.h>
4142#include <llvm/Target/TargetMachine.h>
4243#include <llvm/Transforms/IPO.h>
4344#include <llvm/Transforms/IPO/PassManagerBuilder.h>
......@@ -791,3 +792,151 @@ bool ZigLLDLink(ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_
791792 }
792793 zig_unreachable();
793794}
795
796// workaround for LLD not exposing ability to convert .def to .lib
797
798#include <set>
799
800namespace lld {
801namespace coff {
802
803class SymbolBody;
804class StringChunk;
805struct Symbol;
806
807struct Export {
808 StringRef Name; // N in /export:N or /export:E=N
809 StringRef ExtName; // E in /export:E=N
810 SymbolBody *Sym = nullptr;
811 uint16_t Ordinal = 0;
812 bool Noname = false;
813 bool Data = false;
814 bool Private = false;
815
816 // If an export is a form of /export:foo=dllname.bar, that means
817 // that foo should be exported as an alias to bar in the DLL.
818 // ForwardTo is set to "dllname.bar" part. Usually empty.
819 StringRef ForwardTo;
820 StringChunk *ForwardChunk = nullptr;
821
822 // True if this /export option was in .drectves section.
823 bool Directives = false;
824 StringRef SymbolName;
825 StringRef ExportName; // Name in DLL
826
827 bool operator==(const Export &E) {
828 return (Name == E.Name && ExtName == E.ExtName &&
829 Ordinal == E.Ordinal && Noname == E.Noname &&
830 Data == E.Data && Private == E.Private);
831 }
832};
833
834enum class DebugType {
835 None = 0x0,
836 CV = 0x1, /// CodeView
837 PData = 0x2, /// Procedure Data
838 Fixup = 0x4, /// Relocation Table
839};
840
841struct Configuration {
842 enum ManifestKind { SideBySide, Embed, No };
843 llvm::COFF::MachineTypes Machine = llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN;
844 bool Verbose = false;
845 llvm::COFF::WindowsSubsystem Subsystem = llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN;
846 SymbolBody *Entry = nullptr;
847 bool NoEntry = false;
848 std::string OutputFile;
849 bool DoGC = true;
850 bool DoICF = true;
851 bool Relocatable = true;
852 bool Force = false;
853 bool Debug = false;
854 bool WriteSymtab = true;
855 unsigned DebugTypes = static_cast<unsigned>(DebugType::None);
856 StringRef PDBPath;
857
858 // Symbols in this set are considered as live by the garbage collector.
859 std::set<SymbolBody *> GCRoot;
860
861 std::set<StringRef> NoDefaultLibs;
862 bool NoDefaultLibAll = false;
863
864 // True if we are creating a DLL.
865 bool DLL = false;
866 StringRef Implib;
867 std::vector<Export> Exports;
868 std::set<std::string> DelayLoads;
869 std::map<std::string, int> DLLOrder;
870 SymbolBody *DelayLoadHelper = nullptr;
871
872 // Used for SafeSEH.
873 Symbol *SEHTable = nullptr;
874 Symbol *SEHCount = nullptr;
875
876 // Used for /opt:lldlto=N
877 unsigned LTOOptLevel = 2;
878
879 // Used for /opt:lldltojobs=N
880 unsigned LTOJobs = 1;
881
882 // Used for /merge:from=to (e.g. /merge:.rdata=.text)
883 std::map<StringRef, StringRef> Merge;
884
885 // Used for /section=.name,{DEKPRSW} to set section attributes.
886 std::map<StringRef, uint32_t> Section;
887
888 // Options for manifest files.
889 ManifestKind Manifest = SideBySide;
890 int ManifestID = 1;
891 StringRef ManifestDependency;
892 bool ManifestUAC = true;
893 std::vector<std::string> ManifestInput;
894 StringRef ManifestLevel = "'asInvoker'";
895 StringRef ManifestUIAccess = "'false'";
896 StringRef ManifestFile;
897
898 // Used for /failifmismatch.
899 std::map<StringRef, StringRef> MustMatch;
900
901 // Used for /alternatename.
902 std::map<StringRef, StringRef> AlternateNames;
903
904 uint64_t ImageBase = -1;
905 uint64_t StackReserve = 1024 * 1024;
906 uint64_t StackCommit = 4096;
907 uint64_t HeapReserve = 1024 * 1024;
908 uint64_t HeapCommit = 4096;
909 uint32_t MajorImageVersion = 0;
910 uint32_t MinorImageVersion = 0;
911 uint32_t MajorOSVersion = 6;
912 uint32_t MinorOSVersion = 0;
913 bool DynamicBase = true;
914 bool AllowBind = true;
915 bool NxCompat = true;
916 bool AllowIsolation = true;
917 bool TerminalServerAware = true;
918 bool LargeAddressAware = false;
919 bool HighEntropyVA = false;
920
921 // This is for debugging.
922 bool DebugPdb = false;
923 bool DumpPdb = false;
924};
925
926extern Configuration *Config;
927
928void writeImportLibrary();
929void parseModuleDefs(MemoryBufferRef MB);
930
931} // namespace coff
932} // namespace lld
933
934// writes the output to dll_path with .dll replaced with .lib
935void ZigLLDDefToLib(Buf *def_contents, Buf *dll_path) {
936 lld::coff::Config = new lld::coff::Configuration;
937 auto mem_buf = MemoryBuffer::getMemBuffer(buf_ptr(def_contents));
938 MemoryBufferRef mbref(*mem_buf);
939 lld::coff::parseModuleDefs(mbref);
940 lld::coff::Config->OutputFile = buf_ptr(dll_path);
941 lld::coff::writeImportLibrary();
942}
src/zig_llvm.hpp+1
......@@ -359,5 +359,6 @@ void ZigLLVMGetNativeTarget(ZigLLVM_ArchType *arch_type, ZigLLVM_SubArchType *su
359359 ZigLLVM_VendorType *vendor_type, ZigLLVM_OSType *os_type, ZigLLVM_EnvironmentType *environ_type,
360360 ZigLLVM_ObjectFormatType *oformat);
361361
362void ZigLLDDefToLib(Buf *def_contents, Buf *dll_path);
362363
363364#endif
std/c/darwin.zig+2-2
......@@ -1,4 +1,4 @@
1pub extern fn getrandom(buf_ptr: &u8, buf_len: usize) -> c_int;
1pub extern "c" fn getrandom(buf_ptr: &u8, buf_len: usize) -> c_int;
2fn extern "c" __error() -> &c_int;
23
3extern fn __error() -> &c_int;
44pub const _errno = __error;
std/c/index.zig+1-2
......@@ -9,7 +9,6 @@ pub use switch(builtin.os) {
99 else => empty_import,
1010};
1111
12pub extern fn abort() -> noreturn;
13
12pub extern "c" fn abort() -> noreturn;
1413
1514const empty_import = @import("../empty.zig");
std/c/linux.zig+2-3
......@@ -1,4 +1,3 @@
1pub extern fn getrandom(buf_ptr: &u8, buf_len: usize, flags: c_uint) -> c_int;
2
3extern fn __errno_location() -> &c_int;
1pub extern "c" fn getrandom(buf_ptr: &u8, buf_len: usize, flags: c_uint) -> c_int;
2extern "c" fn __errno_location() -> &c_int;
43pub const _errno = __errno_location;
std/c/windows.zig+1-1
......@@ -1 +1 @@
1pub extern fn _errno() -> &c_int;
1pub extern "c" fn _errno() -> &c_int;
std/debug.zig+3-1
......@@ -16,7 +16,9 @@ pub fn assert(ok: bool) {
1616
1717var panicking = false;
1818/// This is the default panic implementation.
19pub coldcc fn panic(comptime format: []const u8, args: ...) -> noreturn {
19pub fn panic(comptime format: []const u8, args: ...) -> noreturn {
20 // TODO an intrinsic that labels this as unlikely to be reached
21
2022 // TODO
2123 // if (@atomicRmw(AtomicOp.XChg, &panicking, true, AtomicOrder.SeqCst)) { }
2224 if (panicking) {
std/index.zig-2
......@@ -22,7 +22,6 @@ pub const net = @import("net.zig");
2222pub const os = @import("os/index.zig");
2323pub const rand = @import("rand.zig");
2424pub const sort = @import("sort.zig");
25pub const target = @import("target.zig");
2625
2726test "std" {
2827 // run tests from these
......@@ -50,5 +49,4 @@ test "std" {
5049 _ = @import("os/index.zig");
5150 _ = @import("rand.zig");
5251 _ = @import("sort.zig");
53 _ = @import("target.zig");
5452}
std/os/index.zig+3-4
......@@ -24,7 +24,6 @@ const debug = @import("../debug.zig");
2424const assert = debug.assert;
2525
2626const errno = @import("errno.zig");
27const linking_libc = @import("../target.zig").linking_libc;
2827const c = @import("../c/index.zig");
2928
3029const mem = @import("../mem.zig");
......@@ -60,14 +59,14 @@ pub fn getRandomBytes(buf: []u8) -> %void {
6059 while (true) {
6160 const err = switch (builtin.os) {
6261 Os.linux => {
63 if (linking_libc) {
62 if (builtin.link_libc) {
6463 if (c.getrandom(buf.ptr, buf.len, 0) == -1) *c._errno() else 0
6564 } else {
6665 posix.getErrno(posix.getrandom(buf.ptr, buf.len, 0))
6766 }
6867 },
6968 Os.darwin, Os.macosx, Os.ios => {
70 if (linking_libc) {
69 if (builtin.link_libc) {
7170 if (posix.getrandom(buf.ptr, buf.len) == -1) *c._errno() else 0
7271 } else {
7372 posix.getErrno(posix.getrandom(buf.ptr, buf.len))
......@@ -103,7 +102,7 @@ pub fn getRandomBytes(buf: []u8) -> %void {
103102/// If linking against libc, this calls the abort() libc function. Otherwise
104103/// it uses the zig standard library implementation.
105104pub coldcc fn abort() -> noreturn {
106 if (linking_libc) {
105 if (builtin.link_libc) {
107106 c.abort();
108107 }
109108 switch (builtin.os) {
std/os/windows/index.zig+26-14
......@@ -1,39 +1,50 @@
11pub const ERROR = @import("error.zig");
22
3pub extern fn CryptAcquireContext(phProv: &HCRYPTPROV, pszContainer: LPCTSTR,
3pub extern "kernel32" stdcallcc fn CryptAcquireContext(phProv: &HCRYPTPROV, pszContainer: LPCTSTR,
44 pszProvider: LPCTSTR, dwProvType: DWORD, dwFlags: DWORD) -> bool;
55
6pub extern fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> bool;
6pub extern "kernel32" stdcallcc fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> bool;
77
8pub extern fn CryptGenRandom(hProv: HCRYPTPROV, dwLen: DWORD, pbBuffer: &BYTE) -> bool;
8pub extern "kernel32" stdcallcc fn CryptGenRandom(hProv: HCRYPTPROV, dwLen: DWORD, pbBuffer: &BYTE) -> bool;
99
10pub extern fn ExitProcess(exit_code: UINT) -> noreturn;
10pub extern "kernel32" fn ExitProcess(exit_code: UINT) -> noreturn;
1111
12pub extern fn GetConsoleMode(in_hConsoleHandle: HANDLE, out_lpMode: &DWORD) -> bool;
12pub extern "kernel32" stdcallcc fn GetCommandLine() -> LPTSTR;
13
14pub extern "kernel32" stdcallcc fn GetConsoleMode(in_hConsoleHandle: HANDLE, out_lpMode: &DWORD) -> bool;
1315
1416/// Retrieves the calling thread's last-error code value. The last-error code is maintained on a per-thread basis.
1517/// Multiple threads do not overwrite each other's last-error code.
16pub extern fn GetLastError() -> DWORD;
18pub extern "kernel32" stdcallcc fn GetLastError() -> DWORD;
1719
1820/// Retrieves file information for the specified file.
19pub extern fn GetFileInformationByHandleEx(in_hFile: HANDLE, in_FileInformationClass: FILE_INFO_BY_HANDLE_CLASS,
20 out_lpFileInformation: &c_void, in_dwBufferSize: DWORD) -> bool;
21pub extern "kernel32" stdcallcc fn GetFileInformationByHandleEx(in_hFile: HANDLE,
22 in_FileInformationClass: FILE_INFO_BY_HANDLE_CLASS, out_lpFileInformation: &c_void,
23 in_dwBufferSize: DWORD) -> bool;
2124
2225/// Retrieves a handle to the specified standard device (standard input, standard output, or standard error).
23pub extern fn GetStdHandle(in_nStdHandle: DWORD) -> ?HANDLE;
26pub extern "kernel32" stdcallcc fn GetStdHandle(in_nStdHandle: DWORD) -> ?HANDLE;
2427
2528/// Reads data from the specified file or input/output (I/O) device. Reads occur at the position specified by the file pointer if supported by the device.
2629/// This function is designed for both synchronous and asynchronous operations. For a similar function designed solely for asynchronous operation, see ReadFileEx.
27pub extern fn ReadFile(in_hFile: HANDLE, out_lpBuffer: LPVOID, in_nNumberOfBytesToRead: DWORD,
28 out_lpNumberOfBytesRead: &DWORD, in_out_lpOverlapped: ?&OVERLAPPED) -> BOOL;
30pub extern "kernel32" stdcallcc fn ReadFile(in_hFile: HANDLE, out_lpBuffer: LPVOID,
31 in_nNumberOfBytesToRead: DWORD, out_lpNumberOfBytesRead: &DWORD,
32 in_out_lpOverlapped: ?&OVERLAPPED) -> BOOL;
2933
3034/// Writes data to the specified file or input/output (I/O) device.
3135/// This function is designed for both synchronous and asynchronous operation. For a similar function designed solely for asynchronous operation, see WriteFileEx.
32pub extern fn WriteFile(in_hFile: HANDLE, in_lpBuffer: &const c_void, in_nNumberOfBytesToWrite: DWORD,
33 out_lpNumberOfBytesWritten: ?&DWORD, in_out_lpOverlapped: ?&OVERLAPPED) -> BOOL;
36pub extern "kernel32" stdcallcc fn WriteFile(in_hFile: HANDLE, in_lpBuffer: &const c_void,
37 in_nNumberOfBytesToWrite: DWORD, out_lpNumberOfBytesWritten: ?&DWORD,
38 in_out_lpOverlapped: ?&OVERLAPPED) -> BOOL;
3439
3540pub const PROV_RSA_FULL = 1;
3641
42pub const UNICODE = false;
43pub const LPTSTR = if (unicode) LPWSTR else LPSTR;
44pub const LPWSTR = &WCHAR;
45pub const LPSTR = &CHAR;
46pub const CHAR = u8;
47
3748
3849pub const BOOL = bool;
3950pub const BYTE = u8;
......@@ -45,12 +56,13 @@ pub const LPCTSTR = &const TCHAR;
4556pub const LPDWORD = &DWORD;
4657pub const LPVOID = &c_void;
4758pub const PVOID = &c_void;
48pub const TCHAR = u8; // TODO something about unicode WCHAR vs char
59pub const TCHAR = if (UNICODE) WCHAR else u8;
4960pub const UINT = c_uint;
5061pub const ULONG_PTR = usize;
5162pub const WCHAR = u16;
5263pub const LPCVOID = &const c_void;
5364
65
5466/// The standard input device. Initially, this is the console input buffer, CONIN$.
5567pub const STD_INPUT_HANDLE = @maxValue(DWORD) - 10 + 1;
5668
std/special/bootstrap.zig+17-15
......@@ -5,19 +5,23 @@ const root = @import("@root");
55const std = @import("std");
66const builtin = @import("builtin");
77
8const want_main_symbol = std.target.linking_libc;
8const want_main_symbol = builtin.link_libc;
99const want_start_symbol = !want_main_symbol;
1010
11const posix_exit = std.os.posix.exit;
12
1311var argc_ptr: &usize = undefined;
1412
13const is_windows = builtin.os == builtin.Os.windows;
14
1515export nakedcc fn _start() -> noreturn {
1616 if (!want_start_symbol) {
1717 @setGlobalLinkage(_start, builtin.GlobalLinkage.Internal);
1818 unreachable;
1919 }
2020
21 if (is_windows) {
22 windowsCallMainAndExit()
23 }
24
2125 switch (builtin.arch) {
2226 builtin.Arch.x86_64 => {
2327 argc_ptr = asm("lea (%%rsp), %[argc]": [argc] "=r" (-> &usize));
......@@ -27,23 +31,21 @@ export nakedcc fn _start() -> noreturn {
2731 },
2832 else => @compileError("unsupported arch"),
2933 }
30 callMainAndExit()
34 posixCallMainAndExit()
35}
36
37fn windowsCallMainAndExit() -> noreturn {
38 std.debug.user_main_fn = root.main;
39 root.main() %% std.os.windows.ExitProcess(1);
40 std.os.windows.ExitProcess(0);
3141}
3242
33fn callMainAndExit() -> noreturn {
43fn posixCallMainAndExit() -> noreturn {
3444 const argc = *argc_ptr;
3545 const argv = @ptrCast(&&u8, &argc_ptr[1]);
3646 const envp = @ptrCast(&?&u8, &argv[argc + 1]);
37 callMain(argc, argv, envp) %% exit(true);
38 exit(false);
39}
40
41fn exit(failure: bool) -> noreturn {
42 if (builtin.os == builtin.Os.windows) {
43 std.os.windows.ExitProcess(c_uint(failure));
44 } else {
45 posix_exit(i32(failure));
46 }
47 callMain(argc, argv, envp) %% std.os.posix.exit(1);
48 std.os.posix.exit(0);
4749}
4850
4951fn callMain(argc: usize, argv: &&u8, envp: &?&u8) -> %void {
std/target.zig deleted-16
......@@ -1,16 +0,0 @@
1const mem = @import("mem.zig");
2const builtin = @import("builtin");
3
4pub const linking_libc = linkingLibrary("c");
5
6pub fn linkingLibrary(lib_name: []const u8) -> bool {
7 // TODO shouldn't need this if
8 if (builtin.link_libs.len != 0) {
9 for (builtin.link_libs) |link_lib| {
10 if (mem.eql(u8, link_lib, lib_name)) {
11 return true;
12 }
13 }
14 }
15 return false;
16}
test/compile_errors.zig+2-14
......@@ -409,18 +409,6 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
409409 ".tmp_source.zig:2:1: error: redefinition of 'a'",
410410 ".tmp_source.zig:1:1: note: previous definition is here");
411411
412 cases.add("byvalue struct parameter in exported function",
413 \\const A = struct { x : i32, };
414 \\export fn f(a : A) {}
415 , ".tmp_source.zig:2:13: error: byvalue types not yet supported on extern function parameters");
416
417 cases.add("byvalue struct return value in exported function",
418 \\const A = struct { x: i32, };
419 \\export fn f() -> A {
420 \\ A {.x = 1234 }
421 \\}
422 , ".tmp_source.zig:2:18: error: byvalue types not yet supported on extern function return values");
423
424412 cases.add("duplicate field in struct value expression",
425413 \\const A = struct {
426414 \\ x : i32,
......@@ -1070,7 +1058,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
10701058 \\export fn foo(comptime x: i32, y: i32) -> i32{
10711059 \\ x + y
10721060 \\}
1073 , ".tmp_source.zig:1:15: error: comptime parameter not allowed in extern function");
1061 , ".tmp_source.zig:1:15: error: comptime parameter not allowed in function with calling convention 'ccc'");
10741062
10751063 cases.add("extern function with comptime parameter",
10761064 \\extern fn foo(comptime x: i32, y: i32) -> i32;
......@@ -1078,7 +1066,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
10781066 \\ foo(1, 2)
10791067 \\}
10801068 \\export fn entry() -> usize { @sizeOf(@typeOf(f)) }
1081 , ".tmp_source.zig:1:15: error: comptime parameter not allowed in extern function");
1069 , ".tmp_source.zig:1:15: error: comptime parameter not allowed in function with calling convention 'ccc'");
10821070
10831071 cases.add("convert fixed size array to slice with invalid size",
10841072 \\export fn f() {