Commit 1ab0ac3ea2

Andrew Kelley <andrew@ziglang.org>
2019-05-29 17:56:36
cleanups for windows subsystem in builtin.zig
1 parent b461e60
src/all_types.hpp
@@ -1857,7 +1857,7 @@ struct CodeGen {
     BuildMode build_mode;
     OutType out_type;
     const ZigTarget *zig_target;
-    TargetSubsystem subsystem;
+    TargetSubsystem subsystem; // careful using this directly; see detect_subsystem
     ValgrindSupport valgrind_support;
     bool strip_debug_symbols;
     bool is_test_build;
src/analyze.cpp
@@ -2722,12 +2722,10 @@ void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLi
     if (ccc) {
         if (buf_eql_str(symbol_name, "main") && g->libc_link_lib != nullptr) {
             g->have_c_main = true;
-            g->subsystem = g->subsystem == TargetSubsystemAuto ? TargetSubsystemConsole : g->subsystem;
         } else if (buf_eql_str(symbol_name, "WinMain") &&
             g->zig_target->os == OsWindows)
         {
             g->have_winmain = true;
-            g->subsystem = g->subsystem == TargetSubsystemAuto ? TargetSubsystemWindows : g->subsystem;
         } else if (buf_eql_str(symbol_name, "WinMainCRTStartup") &&
             g->zig_target->os == OsWindows)
         {
@@ -3966,7 +3964,6 @@ ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *resolved_path, Bu
                 if (is_pub) {
                     if (buf_eql_str(proto_name, "main")) {
                         g->have_pub_main = true;
-                        g->subsystem = g->subsystem == TargetSubsystemAuto ? TargetSubsystemConsole : g->subsystem;
                     } else if (buf_eql_str(proto_name, "panic")) {
                         g->have_pub_panic = true;
                     }
src/codegen.cpp
@@ -7417,6 +7417,21 @@ static const char *build_mode_to_str(BuildMode build_mode) {
     zig_unreachable();
 }
 
+static const char *subsystem_to_str(TargetSubsystem subsystem) {
+    switch (subsystem) {
+        case TargetSubsystemConsole: return "Console";
+        case TargetSubsystemWindows: return "Windows";
+        case TargetSubsystemPosix: return "Posix";
+        case TargetSubsystemNative: return "Native";
+        case TargetSubsystemEfiApplication: return "EfiApplication";
+        case TargetSubsystemEfiBootServiceDriver: return "EfiBootServiceDriver";
+        case TargetSubsystemEfiRom: return "EfiRom";
+        case TargetSubsystemEfiRuntimeDriver: return "EfiRuntimeDriver";
+        case TargetSubsystemAuto: zig_unreachable();
+    }
+    zig_unreachable();
+}
+
 static bool detect_dynamic_link(CodeGen *g) {
     if (g->is_dynamic)
         return true;
@@ -7462,6 +7477,23 @@ static bool detect_stack_probing(CodeGen *g) {
     zig_unreachable();
 }
 
+// Returns TargetSubsystemAuto to mean "no subsystem"
+TargetSubsystem detect_subsystem(CodeGen *g) {
+    if (g->subsystem != TargetSubsystemAuto)
+        return g->subsystem;
+    if (g->zig_target->os == OsWindows) {
+        if (g->have_dllmain_crt_startup || (g->out_type == OutTypeLib && g->is_dynamic))
+            return TargetSubsystemAuto;
+        if (g->have_c_main || g->have_pub_main || g->is_test_build)
+            return TargetSubsystemConsole;
+        if (g->have_winmain || g->have_winmain_crt_startup)
+            return TargetSubsystemWindows;
+    } else if (g->zig_target->os == OsUefi) {
+        return TargetSubsystemEfiApplication;
+    }
+    return TargetSubsystemAuto;
+}
+
 static bool detect_single_threaded(CodeGen *g) {
     if (g->want_single_threaded)
         return true;
@@ -7882,14 +7914,14 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
         "    EfiRuntimeDriver,\n"
         "};\n\n");
 
-        assert(TargetSubsystemConsole == 1);
-        assert(TargetSubsystemWindows == 2);
-        assert(TargetSubsystemPosix == 3);
-        assert(TargetSubsystemNative == 4);
-        assert(TargetSubsystemEfiApplication == 5);
-        assert(TargetSubsystemEfiBootServiceDriver == 6);
-        assert(TargetSubsystemEfiRom == 7);
-        assert(TargetSubsystemEfiRuntimeDriver == 8);
+        assert(TargetSubsystemConsole == 0);
+        assert(TargetSubsystemWindows == 1);
+        assert(TargetSubsystemPosix == 2);
+        assert(TargetSubsystemNative == 3);
+        assert(TargetSubsystemEfiApplication == 4);
+        assert(TargetSubsystemEfiBootServiceDriver == 5);
+        assert(TargetSubsystemEfiRom == 6);
+        assert(TargetSubsystemEfiRuntimeDriver == 7);
     }
     {
         const char *endian_str = g->is_big_endian ? "Endian.Big" : "Endian.Little";
@@ -7908,29 +7940,10 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
     buf_appendf(contents, "pub const position_independent_code = %s;\n", bool_to_str(g->have_pic));
 
     {
-        static const char* subsystem_strings[] = {
-            "Console",
-            "Windows",
-            "Posix",
-            "Native",
-            "EfiApplication",
-            "EfiBootServiceDriver",
-            "EfiRom",
-            "EfiRuntimeDriver",
-        };
-
-        if (g->zig_target->os != OsWindows || g->zig_target->os != OsUefi || g->have_dllmain_crt_startup || g->out_type == OutTypeLib) {
-                buf_appendf(contents, "pub const subsystem = null;\n");
-        } else if (g->subsystem == TargetSubsystemAuto) {
-            if (g->have_c_main || g->have_pub_main) {
-                buf_appendf(contents, "pub const subsystem = SubSystem.%s;\n", subsystem_strings[TargetSubsystemConsole - 1]);
-            } else if (g->have_winmain || g->have_winmain_crt_startup) {
-                buf_appendf(contents, "pub const subsystem = SubSystem.%s;\n", subsystem_strings[TargetSubsystemWindows - 1]);
-            }
-        } else {
-            buf_appendf(contents, "pub const subsystem = SubSystem.%s;\n", subsystem_strings[g->subsystem - 1]);
+        TargetSubsystem detected_subsystem = detect_subsystem(g);
+        if (detected_subsystem != TargetSubsystemAuto) {
+            buf_appendf(contents, "pub const subsystem = SubSystem.%s;\n", subsystem_to_str(detected_subsystem));
         }
-        
     }
 
     if (g->is_test_build) {
@@ -7976,7 +7989,7 @@ static Error define_builtin_compile_vars(CodeGen *g) {
     cache_bool(&cache_hash, g->have_err_ret_tracing);
     cache_bool(&cache_hash, g->libc_link_lib != nullptr);
     cache_bool(&cache_hash, g->valgrind_support);
-    cache_int(&cache_hash, g->subsystem - 1);
+    cache_int(&cache_hash, detect_subsystem(g));
 
     Buf digest = BUF_INIT;
     buf_resize(&digest, 0);
@@ -8044,10 +8057,6 @@ static void init(CodeGen *g) {
         g->is_single_threaded = true;
     }
 
-    if (g->is_test_build) {
-        g->subsystem = g->subsystem == TargetSubsystemAuto ? TargetSubsystemConsole : g->subsystem;
-    }
-
     assert(g->root_out_name);
     g->module = LLVMModuleCreateWithName(buf_ptr(g->root_out_name));
 
@@ -9401,7 +9410,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
     cache_int(ch, g->zig_target->vendor);
     cache_int(ch, g->zig_target->os);
     cache_int(ch, g->zig_target->abi);
-    cache_int(ch, g->subsystem);
+    cache_int(ch, detect_subsystem(g));
     cache_bool(ch, g->strip_debug_symbols);
     cache_bool(ch, g->is_test_build);
     if (g->is_test_build) {
src/codegen.hpp
@@ -56,4 +56,6 @@ void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_us
 
 Buf *codegen_generate_builtin_source(CodeGen *g);
 
+TargetSubsystem detect_subsystem(CodeGen *g);
+
 #endif
src/link.cpp
@@ -1225,7 +1225,7 @@ static void add_mingw_link_args(LinkJob *lj, bool is_library) {
     lj->args.append(get_libc_file(g->libc, "libmingwex.a"));
     lj->args.append(get_libc_file(g->libc, "libmsvcrt.a"));
 
-    if (g->subsystem == TargetSubsystemWindows) {
+    if (detect_subsystem(g) == TargetSubsystemWindows) {
         lj->args.append(get_libc_file(g->libc, "libgdi32.a"));
         lj->args.append(get_libc_file(g->libc, "libcomdlg32.a"));
     }
@@ -1307,7 +1307,7 @@ static void construct_linker_job_coff(LinkJob *lj) {
         lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));
     }
 
-    switch (g->subsystem) {
+    switch (detect_subsystem(g)) {
         case TargetSubsystemAuto:
             if (g->zig_target->os == OsUefi) {
                 add_uefi_link_args(lj);
src/target.hpp
@@ -62,7 +62,6 @@ enum SubArchList {
 };
 
 enum TargetSubsystem {
-    TargetSubsystemAuto, // Zig should infer the subsystem
     TargetSubsystemConsole,
     TargetSubsystemWindows,
     TargetSubsystemPosix,
@@ -71,6 +70,11 @@ enum TargetSubsystem {
     TargetSubsystemEfiBootServiceDriver,
     TargetSubsystemEfiRom,
     TargetSubsystemEfiRuntimeDriver,
+
+    // This means Zig should infer the subsystem.
+    // It's last so that the indexes of other items can line up
+    // with the enum in builtin.zig.
+    TargetSubsystemAuto
 };
 
 struct ZigTarget {