From fdea12b2d9deaea6a90c7b1451df425e84b98099 Mon Sep 17 00:00:00 2001
From: nebulaeonline
Date: Sun, 23 Dec 2018 22:44:02 -0500
Subject: msvc subsystem option handling; added uefi os type
---
src/main.cpp | 34 ++++++++++++++++++++++++++++++----
1 file changed, 30 insertions(+), 4 deletions(-)
(limited to 'src/main.cpp')
diff --git a/src/main.cpp b/src/main.cpp
index 078dfb25f9..469ec448e8 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -90,9 +90,7 @@ static int print_full_usage(const char *arg0) {
" -rdynamic add all symbols to the dynamic symbol table\n"
" -rpath [path] add directory to the runtime library search path\n"
" --no-rosegment compromise security to workaround valgrind bug\n"
- " -mconsole (windows) --subsystem console to the linker\n"
- " -mwindows (windows) --subsystem windows to the linker\n"
- " -framework [name] (darwin) link against framework\n"
+ " --msvc-subsystem [subsystem] (windows/uefi) /SUBSYSTEM: to the linker\n" " -framework [name] (darwin) link against framework\n"
" -mios-version-min [ver] (darwin) set iOS deployment target\n"
" -mmacosx-version-min [ver] (darwin) set Mac OS X deployment target\n"
" --ver-major [ver] dynamic library semver major version\n"
@@ -395,6 +393,7 @@ int main(int argc, char **argv) {
int runtime_args_start = -1;
bool no_rosegment_workaround = false;
bool system_linker_hack = false;
+ ZigLLVM_MSVCSubsystemType msvc_subsystem_type = ZigLLVM_MSVC_NONE;
if (argc >= 2 && strcmp(argv[1], "build") == 0) {
Buf zig_exe_path_buf = BUF_INIT;
@@ -540,6 +539,32 @@ int main(int argc, char **argv) {
verbose_llvm_ir = true;
} else if (strcmp(arg, "--verbose-cimport") == 0) {
verbose_cimport = true;
+ } else if (strcmp(arg, "--msvc-subsystem") == 0) {
+ if (i + 1 >= argc) {
+ fprintf(stderr, "Expected 1 argument after --msvc-subsystem\n");
+ return print_error_usage(arg0);
+ }
+ i += 1;
+ if (stricmp(argv[i], "CONSOLE") == 0) {
+ msvc_subsystem_type = ZigLLVM_MSVC_CONSOLE;
+ } else if (stricmp(argv[i], "WINDOWS") == 0) {
+ msvc_subsystem_type = ZigLLVM_MSVC_WINDOWS;
+ } else if (stricmp(argv[i], "POSIX") == 0) {
+ msvc_subsystem_type = ZigLLVM_MSVC_POSIX;
+ } else if (stricmp(argv[i], "NATIVE") == 0) {
+ msvc_subsystem_type = ZigLLVM_MSVC_NATIVE;
+ } else if (stricmp(argv[i], "EFI_APPLICATION") == 0) {
+ msvc_subsystem_type = ZigLLVM_MSVC_EFI_APPLICATION;
+ } else if (stricmp(argv[i], "EFI_BOOT_SERVICE_DRIVER") == 0) {
+ msvc_subsystem_type = ZigLLVM_MSVC_EFI_BOOT_SERVICE_DRIVER;
+ } else if (stricmp(argv[i], "EFI_ROM") == 0) {
+ msvc_subsystem_type = ZigLLVM_MSVC_EFI_ROM;
+ } else if (stricmp(argv[i], "EFI_RUNTIME_DRIVER") == 0) {
+ msvc_subsystem_type = ZigLLVM_MSVC_EFI_RUNTIME_DRIVER;
+ } else {
+ fprintf(stderr, "Unknown format %s for --msvc-subsystem argument\n", argv[i]);
+ return EXIT_FAILURE;
+ }
} else if (strcmp(arg, "-mwindows") == 0) {
mwindows = true;
} else if (strcmp(arg, "-mconsole") == 0) {
@@ -849,6 +874,8 @@ int main(int argc, char **argv) {
buf_out_name = buf_create_from_str("run");
}
CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode, get_zig_lib_dir());
+ g->msvc_subsystem = msvc_subsystem_type;
+
if (disable_pic) {
if (out_type != OutTypeLib || !is_static) {
fprintf(stderr, "--disable-pic only applies to static libraries");
@@ -909,7 +936,6 @@ int main(int argc, char **argv) {
codegen_add_rpath(g, rpath_list.at(i));
}
- codegen_set_windows_subsystem(g, mwindows, mconsole);
codegen_set_rdynamic(g, rdynamic);
g->no_rosegment_workaround = no_rosegment_workaround;
if (mmacosx_version_min && mios_version_min) {
--
cgit v1.2.3
From 7dcee99510fe4d69faae67f3aa41cfb47a43045e Mon Sep 17 00:00:00 2001
From: nebulaeonline
Date: Sun, 23 Dec 2018 23:59:59 -0500
Subject: fixed stricmp/strcasecmp between windows/posix
---
src/main.cpp | 23 +++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)
(limited to 'src/main.cpp')
diff --git a/src/main.cpp b/src/main.cpp
index 469ec448e8..303e48d750 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -16,6 +16,13 @@
#include
+#ifdef __GNUC__
+#include
+#define STRCASECMP strcasecmp
+#else
+#define STRCASECMP stricmp
+#endif
+
static int print_error_usage(const char *arg0) {
fprintf(stderr, "See `%s help` for detailed usage information\n", arg0);
return EXIT_FAILURE;
@@ -545,21 +552,21 @@ int main(int argc, char **argv) {
return print_error_usage(arg0);
}
i += 1;
- if (stricmp(argv[i], "CONSOLE") == 0) {
+ if (STRCASECMP(argv[i], "CONSOLE") == 0) {
msvc_subsystem_type = ZigLLVM_MSVC_CONSOLE;
- } else if (stricmp(argv[i], "WINDOWS") == 0) {
+ } else if (STRCASECMP(argv[i], "WINDOWS") == 0) {
msvc_subsystem_type = ZigLLVM_MSVC_WINDOWS;
- } else if (stricmp(argv[i], "POSIX") == 0) {
+ } else if (STRCASECMP(argv[i], "POSIX") == 0) {
msvc_subsystem_type = ZigLLVM_MSVC_POSIX;
- } else if (stricmp(argv[i], "NATIVE") == 0) {
+ } else if (STRCASECMP(argv[i], "NATIVE") == 0) {
msvc_subsystem_type = ZigLLVM_MSVC_NATIVE;
- } else if (stricmp(argv[i], "EFI_APPLICATION") == 0) {
+ } else if (STRCASECMP(argv[i], "EFI_APPLICATION") == 0) {
msvc_subsystem_type = ZigLLVM_MSVC_EFI_APPLICATION;
- } else if (stricmp(argv[i], "EFI_BOOT_SERVICE_DRIVER") == 0) {
+ } else if (STRCASECMP(argv[i], "EFI_BOOT_SERVICE_DRIVER") == 0) {
msvc_subsystem_type = ZigLLVM_MSVC_EFI_BOOT_SERVICE_DRIVER;
- } else if (stricmp(argv[i], "EFI_ROM") == 0) {
+ } else if (STRCASECMP(argv[i], "EFI_ROM") == 0) {
msvc_subsystem_type = ZigLLVM_MSVC_EFI_ROM;
- } else if (stricmp(argv[i], "EFI_RUNTIME_DRIVER") == 0) {
+ } else if (STRCASECMP(argv[i], "EFI_RUNTIME_DRIVER") == 0) {
msvc_subsystem_type = ZigLLVM_MSVC_EFI_RUNTIME_DRIVER;
} else {
fprintf(stderr, "Unknown format %s for --msvc-subsystem argument\n", argv[i]);
--
cgit v1.2.3
From 28cd337d1ffc547f296f574b82547d6b15253167 Mon Sep 17 00:00:00 2001
From: nebulaeonline
Date: Mon, 24 Dec 2018 07:49:15 -0500
Subject: fixed formatting in options display
---
src/main.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
(limited to 'src/main.cpp')
diff --git a/src/main.cpp b/src/main.cpp
index 303e48d750..faca9511dc 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -97,7 +97,8 @@ static int print_full_usage(const char *arg0) {
" -rdynamic add all symbols to the dynamic symbol table\n"
" -rpath [path] add directory to the runtime library search path\n"
" --no-rosegment compromise security to workaround valgrind bug\n"
- " --msvc-subsystem [subsystem] (windows/uefi) /SUBSYSTEM: to the linker\n" " -framework [name] (darwin) link against framework\n"
+ " --msvc-subsystem [subsystem] (windows/uefi) /SUBSYSTEM: to the linker\n"
+ " -framework [name] (darwin) link against framework\n"
" -mios-version-min [ver] (darwin) set iOS deployment target\n"
" -mmacosx-version-min [ver] (darwin) set Mac OS X deployment target\n"
" --ver-major [ver] dynamic library semver major version\n"
--
cgit v1.2.3
From a918ce26b81b8e51c061d85631aa432a025c1ee2 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Wed, 26 Dec 2018 15:25:54 -0500
Subject: fixups
---
CMakeLists.txt | 2 +-
README.md | 40 +++----
src/all_types.hpp | 2 +-
src/analyze.cpp | 8 +-
src/codegen.cpp | 6 +-
src/ir.cpp | 8 +-
src/link.cpp | 310 ++++++++++++++++++++++++++------------------------
src/main.cpp | 78 ++++++-------
src/target.cpp | 5 +-
src/target.hpp | 13 ++-
src/translate_c.cpp | 2 +-
src/zig_llvm.cpp | 7 +-
src/zig_llvm.h | 18 +--
std/os/index.zig | 5 +-
std/os/uefi.zig | 2 +
std/os/uefi/index.zig | 0
std/special/panic.zig | 6 +-
17 files changed, 253 insertions(+), 259 deletions(-)
create mode 100644 std/os/uefi.zig
delete mode 100644 std/os/uefi/index.zig
(limited to 'src/main.cpp')
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7b31f96562..807077476a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -590,7 +590,7 @@ set(ZIG_STD_FILES
"os/freebsd/x86_64.zig"
"os/path.zig"
"os/time.zig"
- "os/uefi/index.zig"
+ "os/uefi.zig"
"os/windows/advapi32.zig"
"os/windows/error.zig"
"os/windows/index.zig"
diff --git a/README.md b/README.md
index c1eec599e5..e9756b404d 100644
--- a/README.md
+++ b/README.md
@@ -87,26 +87,26 @@ clarity.
#### Support Table
-| | freestanding | linux | macosx | windows | freebsd | other |
-|--------|--------------|--------|--------|---------|---------|--------|
-|x86_64 | Tier 2 | Tier 1 | Tier 1 | Tier 1 | Tier 2 | Tier 3 |
-|i386 | Tier 2 | Tier 2 | Tier 2 | Tier 2 | Tier 3 | Tier 3 |
-|arm | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 |
-|arm64 | Tier 2 | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 |
-|bpf | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
-|hexagon | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
-|mips | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
-|powerpc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
-|r600 | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
-|amdgcn | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
-|sparc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
-|s390x | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
-|spir | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
-|lanai | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 |
-|wasm32 | Tier 4 | N/A | N/A | N/A | N/A | N/A |
-|wasm64 | Tier 4 | N/A | N/A | N/A | N/A | N/A |
-|riscv32 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 |
-|riscv64 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 |
+| | freestanding | linux | macosx | windows | freebsd | UEFI | other |
+|--------|--------------|--------|--------|---------|---------|--------|--------|
+|x86_64 | Tier 2 | Tier 1 | Tier 1 | Tier 1 | Tier 2 | Tier 2 | Tier 3 |
+|i386 | Tier 2 | Tier 2 | Tier 2 | Tier 2 | Tier 3 | Tier 3 | Tier 3 |
+|arm | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 |
+|arm64 | Tier 2 | Tier 2 | Tier 3 | Tier 3 | Tier 3 | Tier 3 | Tier 3 |
+|bpf | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
+|hexagon | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
+|mips | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
+|powerpc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
+|r600 | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
+|amdgcn | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
+|sparc | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
+|s390x | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
+|spir | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
+|lanai | Tier 3 | Tier 3 | N/A | N/A | Tier 3 | Tier 3 | Tier 3 |
+|wasm32 | Tier 4 | N/A | N/A | N/A | N/A | N/A | N/A |
+|wasm64 | Tier 4 | N/A | N/A | N/A | N/A | N/A | N/A |
+|riscv32 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | Tier 4 |
+|riscv64 | Tier 4 | Tier 4 | N/A | N/A | Tier 4 | Tier 4 | Tier 4 |
## Community
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 26e9edbab4..2b55f8ee2e 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -1750,11 +1750,11 @@ struct CodeGen {
BuildMode build_mode;
OutType out_type;
ZigTarget zig_target;
+ TargetSubsystem subsystem;
bool is_static;
bool strip_debug_symbols;
bool is_test_build;
bool is_native_target;
- ZigLLVM_MSVCSubsystemType msvc_subsystem;
bool linker_rdynamic;
bool no_rosegment_workaround;
bool each_lib_rpath;
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 48d473fb37..04d957b626 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -3203,22 +3203,20 @@ 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->msvc_subsystem = ZigLLVM_MSVC_CONSOLE;
+ g->subsystem = TargetSubsystemConsole;
} else if (buf_eql_str(symbol_name, "WinMain") &&
g->zig_target.os == OsWindows)
{
g->have_winmain = true;
- g->msvc_subsystem = ZigLLVM_MSVC_WINDOWS;
+ g->subsystem = TargetSubsystemWindows;
} else if (buf_eql_str(symbol_name, "WinMainCRTStartup") &&
g->zig_target.os == OsWindows)
{
g->have_winmain_crt_startup = true;
- g->msvc_subsystem = ZigLLVM_MSVC_WINDOWS;
} else if (buf_eql_str(symbol_name, "DllMainCRTStartup") &&
g->zig_target.os == OsWindows)
{
g->have_dllmain_crt_startup = true;
- g->msvc_subsystem = ZigLLVM_MSVC_WINDOWS;
}
}
@@ -4377,7 +4375,7 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *r
if (is_pub && ok_cc) {
if (buf_eql_str(proto_name, "main")) {
g->have_pub_main = true;
- g->msvc_subsystem = ZigLLVM_MSVC_CONSOLE;
+ g->subsystem = TargetSubsystemConsole;
} else if (buf_eql_str(proto_name, "panic")) {
g->have_pub_panic = true;
}
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 30a4f8c2a4..bbf8ffa340 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -7231,7 +7231,7 @@ static void init(CodeGen *g) {
}
if (g->is_test_build) {
- g->msvc_subsystem = ZigLLVM_MSVC_CONSOLE;
+ g->subsystem = TargetSubsystemConsole;
}
assert(g->root_out_name);
@@ -7513,7 +7513,7 @@ static void gen_root_source(CodeGen *g) {
report_errors_and_maybe_exit(g);
if (!g->is_test_build && g->zig_target.os != OsFreestanding &&
- g->zig_target.os != OsZen && g->zig_target.os != OsUefi &&
+ g->zig_target.os != OsUefi &&
!g->have_c_main && !g->have_winmain && !g->have_winmain_crt_startup &&
((g->have_pub_main && g->out_type == OutTypeObj) || g->out_type == OutTypeExe))
{
@@ -8070,11 +8070,11 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
cache_int(ch, g->zig_target.os);
cache_int(ch, g->zig_target.env_type);
cache_int(ch, g->zig_target.oformat);
+ cache_int(ch, g->subsystem);
cache_bool(ch, g->is_static);
cache_bool(ch, g->strip_debug_symbols);
cache_bool(ch, g->is_test_build);
cache_bool(ch, g->is_native_target);
- cache_int(ch, g->msvc_subsystem);
cache_bool(ch, g->linker_rdynamic);
cache_bool(ch, g->no_rosegment_workaround);
cache_bool(ch, g->each_lib_rpath);
diff --git a/src/ir.cpp b/src/ir.cpp
index a1432c7b11..83960f2eee 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -17872,13 +17872,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
if (type_is_invalid(cimport_result->value.type))
return ira->codegen->invalid_instruction;
- if (ira->codegen->msvc_subsystem != ZigLLVM_MSVC_EFI_APPLICATION &&
- ira->codegen->msvc_subsystem != ZigLLVM_MSVC_EFI_BOOT_SERVICE_DRIVER &&
- ira->codegen->msvc_subsystem != ZigLLVM_MSVC_EFI_ROM &&
- ira->codegen->msvc_subsystem != ZigLLVM_MSVC_EFI_RUNTIME_DRIVER) {
-
- find_libc_include_path(ira->codegen);
- }
+ find_libc_include_path(ira->codegen);
ImportTableEntry *child_import = allocate(1);
child_import->decls_scope = create_decls_scope(ira->codegen, node, nullptr, nullptr, child_import);
diff --git a/src/link.cpp b/src/link.cpp
index 52ca2f2cd9..593f7f309f 100644
--- a/src/link.cpp
+++ b/src/link.cpp
@@ -444,97 +444,20 @@ static bool zig_lld_link(ZigLLVM_ObjectFormatType oformat, const char **args, si
return ZigLLDLink(oformat, args, arg_count, link_diag_callback, diag);
}
-static void construct_linker_job_coff(LinkJob *lj) {
- CodeGen *g = lj->codegen;
-
- lj->args.append("/ERRORLIMIT:0");
-
- if (g->libc_link_lib != nullptr) {
- find_libc_lib_path(g);
- }
-
- lj->args.append("-NOLOGO");
-
- if (!g->strip_debug_symbols && g->zig_target.os != Os::OsUefi) {
- lj->args.append("-DEBUG");
- }
-
- if (g->out_type == OutTypeExe) {
- // TODO compile time stack upper bound detection
- lj->args.append("/STACK:16777216");
- }
-
- coff_append_machine_arg(g, &lj->args);
-
- // The commented out stuff is from when we linked with MinGW
- // Now that we're linking with LLD it remains to be determined
- // how to handle --target-environ gnu
- // These comments are a clue
-
- bool is_library = g->out_type == OutTypeLib;
- //bool dll = g->out_type == OutTypeLib;
- //bool shared = !g->is_static && dll;
- //if (g->is_static) {
- // lj->args.append("-Bstatic");
- //} else {
- // if (dll) {
- // lj->args.append("--dll");
- // } else if (shared) {
- // lj->args.append("--shared");
- // }
- // lj->args.append("-Bdynamic");
- // if (dll || shared) {
- // lj->args.append("-e");
- // if (g->zig_target.arch.arch == ZigLLVM_x86) {
- // lj->args.append("_DllMainCRTStartup@12");
- // } else {
- // lj->args.append("DllMainCRTStartup");
- // }
- // lj->args.append("--enable-auto-image-base");
- // }
- //}
-
-
- // These are n actual command lines from LINK.EXE UEFI builds (app & driver) to be used as guidance cleaning
- // up a bit for building the COFF linker args:
- // /OUT:"J:\coding\nebulae\k\x64\Release\k.efi" /LTCG:incremental /Driver /PDB:"J:\coding\nebulae\k\x64\Release\k.pdb" "UefiApplicationEntryPoint.lib" "UefiRuntimeLib.lib" "UefiHiiLib.lib" "UefiHiiServicesLib.lib" "UefiSortLib.lib" "UefiShellLib.lib" "GlueLib.lib" "BaseLib.lib" "BaseDebugPrintErrorLevelLib.lib" "BasePrintLib.lib" "UefiLib.lib" "UefiBootServicesTableLib.lib" "UefiRuntimeServicesTableLib.lib" "UefiDevicePathLibDevicePathProtocol.lib" "UefiDebugLibConOut.lib" "UefiMemoryLib.lib" "UefiMemoryAllocationLib.lib" "BaseSynchronizationLib.lib" "UefiFileHandleLib.lib" /IMPLIB:"J:\coding\nebulae\k\x64\Release\k.lib" /DEBUG:FASTLINK /BASE:"0" /MACHINE:X64 /ENTRY:"EfiMain" /OPT:REF /SAFESEH:NO /SUBSYSTEM:EFI_APPLICATION /MERGE:".rdata=.data" /NOLOGO /ALIGN:32 /NODEFAULTLIB /SECTION:".xdata,D"
- // /OUT:"J:\coding\VisualUefi\samples\x64\Release\UefiDriver.efi" /LTCG:incremental /Driver /PDB:"J:\coding\VisualUefi\samples\x64\Release\UefiDriver.pdb" "UefiDriverEntryPoint.lib" "UefiHiiLib.lib" "UefiHiiServicesLib.lib" "UefiSortLib.lib" "UefiShellLib.lib" "GlueLib.lib" "BaseLib.lib" "BaseDebugPrintErrorLevelLib.lib" "BasePrintLib.lib" "UefiLib.lib" "UefiBootServicesTableLib.lib" "UefiRuntimeServicesTableLib.lib" "UefiDevicePathLibDevicePathProtocol.lib" "UefiDebugLibConOut.lib" "UefiMemoryLib.lib" "UefiMemoryAllocationLib.lib" "BaseSynchronizationLib.lib" "UefiFileHandleLib.lib" /IMPLIB:"J:\coding\VisualUefi\samples\x64\Release\UefiDriver.lib" /DEBUG:FASTLINK /BASE:"0" /MACHINE:X64 /ENTRY:"EfiMain" /OPT:REF /SAFESEH:NO /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /MERGE:".rdata=.data" /NOLOGO /ALIGN:32 /NODEFAULTLIB /SECTION:".xdata,D"
-
- // Sorry for the goto(s) :)
- switch (g->msvc_subsystem) {
- case ZigLLVM_MSVC_CONSOLE:
- lj->args.append("/SUBSYSTEM:console");
- goto building_nt;
- case ZigLLVM_MSVC_EFI_APPLICATION:
- lj->args.append("/SUBSYSTEM:efi_application");
- goto building_uefi;
- case ZigLLVM_MSVC_EFI_BOOT_SERVICE_DRIVER:
- lj->args.append("/SUBSYSTEM:efi_boot_service_driver");
- goto building_uefi;
- case ZigLLVM_MSVC_EFI_ROM:
- lj->args.append("/SUBSYSTEM:efi_rom");
- goto building_uefi;
- case ZigLLVM_MSVC_EFI_RUNTIME_DRIVER:
- lj->args.append("/SUBSYSTEM:efi_runtime_driver");
- goto building_uefi;
- case ZigLLVM_MSVC_NATIVE:
- lj->args.append("/SUBSYSTEM:native");
- goto building_nt;
- case ZigLLVM_MSVC_POSIX:
- lj->args.append("/SUBSYSTEM:posix");
- goto building_nt;
- case ZigLLVM_MSVC_WINDOWS:
- lj->args.append("/SUBSYSTEM:windows");
- goto building_nt;
- case ZigLLVM_MSVC_NONE:
- goto continuing_build;
- }
+static void add_uefi_link_args(LinkJob *lj) {
+ lj->args.append("/BASE:0");
+ lj->args.append("/ENTRY:EfiMain");
+ lj->args.append("/OPT:REF");
+ lj->args.append("/SAFESEH:NO");
+ lj->args.append("/MERGE:.rdata=.data");
+ lj->args.append("/ALIGN:32");
+ lj->args.append("/NODEFAULTLIB");
+ lj->args.append("/SECTION:.xdata,D");
+}
-building_uefi:
- lj->args.append("/BASE:\"0\" /ENTRY:\"EfiMain\" /OPT:REF /SAFESEH:NO /MERGE:\".rdata=.data\" /ALIGN:32 /NODEFAULTLIB /SECTION:\".xdata,D\"");
- goto continuing_build;
+static void add_nt_link_args(LinkJob *lj, bool is_library) {
+ CodeGen *g = lj->codegen;
-building_nt:
if (lj->link_in_crt) {
const char *lib_str = g->is_static ? "lib" : "";
const char *d_str = (g->build_mode == BuildModeDebug) ? "d" : "";
@@ -557,17 +480,6 @@ building_nt:
//https://msdn.microsoft.com/en-us/library/bb531344.aspx
lj->args.append("legacy_stdio_definitions.lib");
- //if (shared || dll) {
- // lj->args.append(get_libc_file(g, "dllcrt2.o"));
- //} else {
- // if (g->windows_linker_unicode) {
- // lj->args.append(get_libc_file(g, "crt2u.o"));
- // } else {
- // lj->args.append(get_libc_file(g, "crt2.o"));
- // }
- //}
- //lj->args.append(get_libc_static_file(g, "crtbegin.o"));
-
// msvcrt depends on kernel32
lj->args.append("kernel32.lib");
} else {
@@ -580,8 +492,156 @@ building_nt:
}
}
}
+}
+
+// These are n actual command lines from LINK.EXE UEFI builds (app & driver) to be used as guidance cleaning
+// up a bit for building the COFF linker args:
+// /OUT:"J:\coding\nebulae\k\x64\Release\k.efi" /LTCG:incremental /Driver /PDB:"J:\coding\nebulae\k\x64\Release\k.pdb" "UefiApplicationEntryPoint.lib" "UefiRuntimeLib.lib" "UefiHiiLib.lib" "UefiHiiServicesLib.lib" "UefiSortLib.lib" "UefiShellLib.lib" "GlueLib.lib" "BaseLib.lib" "BaseDebugPrintErrorLevelLib.lib" "BasePrintLib.lib" "UefiLib.lib" "UefiBootServicesTableLib.lib" "UefiRuntimeServicesTableLib.lib" "UefiDevicePathLibDevicePathProtocol.lib" "UefiDebugLibConOut.lib" "UefiMemoryLib.lib" "UefiMemoryAllocationLib.lib" "BaseSynchronizationLib.lib" "UefiFileHandleLib.lib" /IMPLIB:"J:\coding\nebulae\k\x64\Release\k.lib" /DEBUG:FASTLINK /BASE:"0" /MACHINE:X64 /ENTRY:"EfiMain" /OPT:REF /SAFESEH:NO /SUBSYSTEM:EFI_APPLICATION /MERGE:".rdata=.data" /NOLOGO /ALIGN:32 /NODEFAULTLIB /SECTION:".xdata,D"
+// /OUT:"J:\coding\VisualUefi\samples\x64\Release\UefiDriver.efi" /LTCG:incremental /Driver /PDB:"J:\coding\VisualUefi\samples\x64\Release\UefiDriver.pdb" "UefiDriverEntryPoint.lib" "UefiHiiLib.lib" "UefiHiiServicesLib.lib" "UefiSortLib.lib" "UefiShellLib.lib" "GlueLib.lib" "BaseLib.lib" "BaseDebugPrintErrorLevelLib.lib" "BasePrintLib.lib" "UefiLib.lib" "UefiBootServicesTableLib.lib" "UefiRuntimeServicesTableLib.lib" "UefiDevicePathLibDevicePathProtocol.lib" "UefiDebugLibConOut.lib" "UefiMemoryLib.lib" "UefiMemoryAllocationLib.lib" "BaseSynchronizationLib.lib" "UefiFileHandleLib.lib" /IMPLIB:"J:\coding\VisualUefi\samples\x64\Release\UefiDriver.lib" /DEBUG:FASTLINK /BASE:"0" /MACHINE:X64 /ENTRY:"EfiMain" /OPT:REF /SAFESEH:NO /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /MERGE:".rdata=.data" /NOLOGO /ALIGN:32 /NODEFAULTLIB /SECTION:".xdata,D"
+// This commented out stuff is from when we linked with MinGW
+// Now that we're linking with LLD it remains to be determined
+// how to handle --target-environ gnu
+// These comments are a clue
+//bool dll = g->out_type == OutTypeLib;
+//bool shared = !g->is_static && dll;
+//if (g->is_static) {
+// lj->args.append("-Bstatic");
+//} else {
+// if (dll) {
+// lj->args.append("--dll");
+// } else if (shared) {
+// lj->args.append("--shared");
+// }
+// lj->args.append("-Bdynamic");
+// if (dll || shared) {
+// lj->args.append("-e");
+// if (g->zig_target.arch.arch == ZigLLVM_x86) {
+// lj->args.append("_DllMainCRTStartup@12");
+// } else {
+// lj->args.append("DllMainCRTStartup");
+// }
+// lj->args.append("--enable-auto-image-base");
+// }
+//}
+//if (shared || dll) {
+// lj->args.append(get_libc_file(g, "dllcrt2.o"));
+//} else {
+// if (g->windows_linker_unicode) {
+// lj->args.append(get_libc_file(g, "crt2u.o"));
+// } else {
+// lj->args.append(get_libc_file(g, "crt2.o"));
+// }
+//}
+//lj->args.append(get_libc_static_file(g, "crtbegin.o"));
+//if (g->libc_link_lib != nullptr) {
+//if (g->is_static) {
+// lj->args.append("--start-group");
+//}
+
+//lj->args.append("-lmingw32");
+
+//lj->args.append("-lgcc");
+//bool is_android = (g->zig_target.env_type == ZigLLVM_Android);
+//bool is_cyg_ming = is_target_cyg_mingw(&g->zig_target);
+//if (!g->is_static && !is_android) {
+// if (!is_cyg_ming) {
+// lj->args.append("--as-needed");
+// }
+// //lj->args.append("-lgcc_s");
+// if (!is_cyg_ming) {
+// lj->args.append("--no-as-needed");
+// }
+//}
+//if (g->is_static && !is_android) {
+// //lj->args.append("-lgcc_eh");
+//}
+//if (is_android && !g->is_static) {
+// lj->args.append("-ldl");
+//}
+
+//lj->args.append("-lmoldname");
+//lj->args.append("-lmingwex");
+//lj->args.append("-lmsvcrt");
+
+
+//if (g->windows_subsystem_windows) {
+// lj->args.append("-lgdi32");
+// lj->args.append("-lcomdlg32");
+//}
+//lj->args.append("-ladvapi32");
+//lj->args.append("-lshell32");
+//lj->args.append("-luser32");
+//lj->args.append("-lkernel32");
+
+//if (g->is_static) {
+// lj->args.append("--end-group");
+//}
+
+//if (lj->link_in_crt) {
+// lj->args.append(get_libc_static_file(g, "crtend.o"));
+//}
+//}
+
+
+static void construct_linker_job_coff(LinkJob *lj) {
+ CodeGen *g = lj->codegen;
+
+ lj->args.append("/ERRORLIMIT:0");
+
+ if (g->libc_link_lib != nullptr) {
+ find_libc_lib_path(g);
+ }
+
+ lj->args.append("/NOLOGO");
-continuing_build:
+ if (!g->strip_debug_symbols) {
+ lj->args.append("/DEBUG");
+ }
+
+ if (g->out_type == OutTypeExe) {
+ // TODO compile time stack upper bound detection
+ lj->args.append("/STACK:16777216");
+ }
+
+ coff_append_machine_arg(g, &lj->args);
+
+ bool is_library = g->out_type == OutTypeLib;
+ switch (g->subsystem) {
+ case TargetSubsystemAuto:
+ break;
+ case TargetSubsystemConsole:
+ lj->args.append("/SUBSYSTEM:console");
+ add_nt_link_args(lj, is_library);
+ break;
+ case TargetSubsystemEfiApplication:
+ lj->args.append("/SUBSYSTEM:efi_application");
+ add_uefi_link_args(lj);
+ break;
+ case TargetSubsystemEfiBootServiceDriver:
+ lj->args.append("/SUBSYSTEM:efi_boot_service_driver");
+ add_uefi_link_args(lj);
+ break;
+ case TargetSubsystemEfiRom:
+ lj->args.append("/SUBSYSTEM:efi_rom");
+ add_uefi_link_args(lj);
+ break;
+ case TargetSubsystemEfiRuntimeDriver:
+ lj->args.append("/SUBSYSTEM:efi_runtime_driver");
+ add_uefi_link_args(lj);
+ break;
+ case TargetSubsystemNative:
+ lj->args.append("/SUBSYSTEM:native");
+ add_nt_link_args(lj, is_library);
+ break;
+ case TargetSubsystemPosix:
+ lj->args.append("/SUBSYSTEM:posix");
+ add_nt_link_args(lj, is_library);
+ break;
+ case TargetSubsystemWindows:
+ lj->args.append("/SUBSYSTEM:windows");
+ add_nt_link_args(lj, is_library);
+ break;
+ }
lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path))));
@@ -665,54 +725,6 @@ continuing_build:
}
}
- //if (g->libc_link_lib != nullptr) {
- //if (g->is_static) {
- // lj->args.append("--start-group");
- //}
-
- //lj->args.append("-lmingw32");
-
- //lj->args.append("-lgcc");
- //bool is_android = (g->zig_target.env_type == ZigLLVM_Android);
- //bool is_cyg_ming = is_target_cyg_mingw(&g->zig_target);
- //if (!g->is_static && !is_android) {
- // if (!is_cyg_ming) {
- // lj->args.append("--as-needed");
- // }
- // //lj->args.append("-lgcc_s");
- // if (!is_cyg_ming) {
- // lj->args.append("--no-as-needed");
- // }
- //}
- //if (g->is_static && !is_android) {
- // //lj->args.append("-lgcc_eh");
- //}
- //if (is_android && !g->is_static) {
- // lj->args.append("-ldl");
- //}
-
- //lj->args.append("-lmoldname");
- //lj->args.append("-lmingwex");
- //lj->args.append("-lmsvcrt");
-
-
- //if (g->windows_subsystem_windows) {
- // lj->args.append("-lgdi32");
- // lj->args.append("-lcomdlg32");
- //}
- //lj->args.append("-ladvapi32");
- //lj->args.append("-lshell32");
- //lj->args.append("-luser32");
- //lj->args.append("-lkernel32");
-
- //if (g->is_static) {
- // lj->args.append("--end-group");
- //}
-
- //if (lj->link_in_crt) {
- // lj->args.append(get_libc_static_file(g, "crtend.o"));
- //}
- //}
}
diff --git a/src/main.cpp b/src/main.cpp
index faca9511dc..fd8e3db2fa 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -16,13 +16,6 @@
#include
-#ifdef __GNUC__
-#include
-#define STRCASECMP strcasecmp
-#else
-#define STRCASECMP stricmp
-#endif
-
static int print_error_usage(const char *arg0) {
fprintf(stderr, "See `%s help` for detailed usage information\n", arg0);
return EXIT_FAILURE;
@@ -97,8 +90,8 @@ static int print_full_usage(const char *arg0) {
" -rdynamic add all symbols to the dynamic symbol table\n"
" -rpath [path] add directory to the runtime library search path\n"
" --no-rosegment compromise security to workaround valgrind bug\n"
- " --msvc-subsystem [subsystem] (windows/uefi) /SUBSYSTEM: to the linker\n"
- " -framework [name] (darwin) link against framework\n"
+ " --subsystem [subsystem] (windows) /SUBSYSTEM: to the linker\n"
+ " -framework [name] (darwin) link against framework\n"
" -mios-version-min [ver] (darwin) set iOS deployment target\n"
" -mmacosx-version-min [ver] (darwin) set Mac OS X deployment target\n"
" --ver-major [ver] dynamic library semver major version\n"
@@ -377,8 +370,6 @@ int main(int argc, char **argv) {
const char *target_arch = nullptr;
const char *target_os = nullptr;
const char *target_environ = nullptr;
- bool mwindows = false;
- bool mconsole = false;
bool rdynamic = false;
const char *mmacosx_version_min = nullptr;
const char *mios_version_min = nullptr;
@@ -401,7 +392,7 @@ int main(int argc, char **argv) {
int runtime_args_start = -1;
bool no_rosegment_workaround = false;
bool system_linker_hack = false;
- ZigLLVM_MSVCSubsystemType msvc_subsystem_type = ZigLLVM_MSVC_NONE;
+ TargetSubsystem subsystem = TargetSubsystemAuto;
if (argc >= 2 && strcmp(argv[1], "build") == 0) {
Buf zig_exe_path_buf = BUF_INIT;
@@ -547,36 +538,6 @@ int main(int argc, char **argv) {
verbose_llvm_ir = true;
} else if (strcmp(arg, "--verbose-cimport") == 0) {
verbose_cimport = true;
- } else if (strcmp(arg, "--msvc-subsystem") == 0) {
- if (i + 1 >= argc) {
- fprintf(stderr, "Expected 1 argument after --msvc-subsystem\n");
- return print_error_usage(arg0);
- }
- i += 1;
- if (STRCASECMP(argv[i], "CONSOLE") == 0) {
- msvc_subsystem_type = ZigLLVM_MSVC_CONSOLE;
- } else if (STRCASECMP(argv[i], "WINDOWS") == 0) {
- msvc_subsystem_type = ZigLLVM_MSVC_WINDOWS;
- } else if (STRCASECMP(argv[i], "POSIX") == 0) {
- msvc_subsystem_type = ZigLLVM_MSVC_POSIX;
- } else if (STRCASECMP(argv[i], "NATIVE") == 0) {
- msvc_subsystem_type = ZigLLVM_MSVC_NATIVE;
- } else if (STRCASECMP(argv[i], "EFI_APPLICATION") == 0) {
- msvc_subsystem_type = ZigLLVM_MSVC_EFI_APPLICATION;
- } else if (STRCASECMP(argv[i], "EFI_BOOT_SERVICE_DRIVER") == 0) {
- msvc_subsystem_type = ZigLLVM_MSVC_EFI_BOOT_SERVICE_DRIVER;
- } else if (STRCASECMP(argv[i], "EFI_ROM") == 0) {
- msvc_subsystem_type = ZigLLVM_MSVC_EFI_ROM;
- } else if (STRCASECMP(argv[i], "EFI_RUNTIME_DRIVER") == 0) {
- msvc_subsystem_type = ZigLLVM_MSVC_EFI_RUNTIME_DRIVER;
- } else {
- fprintf(stderr, "Unknown format %s for --msvc-subsystem argument\n", argv[i]);
- return EXIT_FAILURE;
- }
- } else if (strcmp(arg, "-mwindows") == 0) {
- mwindows = true;
- } else if (strcmp(arg, "-mconsole") == 0) {
- mconsole = true;
} else if (strcmp(arg, "-rdynamic") == 0) {
rdynamic = true;
} else if (strcmp(arg, "--no-rosegment") == 0) {
@@ -720,6 +681,37 @@ int main(int argc, char **argv) {
ver_patch = atoi(argv[i]);
} else if (strcmp(arg, "--test-cmd") == 0) {
test_exec_args.append(argv[i]);
+ } else if (strcmp(arg, "--subsystem") == 0) {
+ if (strcmp(argv[i], "console") == 0) {
+ subsystem = TargetSubsystemConsole;
+ } else if (strcmp(argv[i], "windows") == 0) {
+ subsystem = TargetSubsystemWindows;
+ } else if (strcmp(argv[i], "posix") == 0) {
+ subsystem = TargetSubsystemPosix;
+ } else if (strcmp(argv[i], "native") == 0) {
+ subsystem = TargetSubsystemNative;
+ } else if (strcmp(argv[i], "efi_application") == 0) {
+ subsystem = TargetSubsystemEfiApplication;
+ } else if (strcmp(argv[i], "efi_boot_service_driver") == 0) {
+ subsystem = TargetSubsystemEfiBootServiceDriver;
+ } else if (strcmp(argv[i], "efi_rom") == 0) {
+ subsystem = TargetSubsystemEfiRom;
+ } else if (strcmp(argv[i], "efi_runtime_driver") == 0) {
+ subsystem = TargetSubsystemEfiRuntimeDriver;
+ } else {
+ fprintf(stderr, "invalid: --subsystem %s\n"
+ "Options are:\n"
+ " console\n"
+ " windows\n"
+ " posix\n"
+ " native\n"
+ " efi_application\n"
+ " efi_boot_service_driver\n"
+ " efi_rom\n"
+ " efi_runtime_driver\n"
+ , argv[i]);
+ return EXIT_FAILURE;
+ }
} else {
fprintf(stderr, "Invalid argument: %s\n", arg);
return print_error_usage(arg0);
@@ -882,7 +874,7 @@ int main(int argc, char **argv) {
buf_out_name = buf_create_from_str("run");
}
CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode, get_zig_lib_dir());
- g->msvc_subsystem = msvc_subsystem_type;
+ g->subsystem = subsystem;
if (disable_pic) {
if (out_type != OutTypeLib || !is_static) {
diff --git a/src/target.cpp b/src/target.cpp
index 61543c38d5..6fea79518c 100644
--- a/src/target.cpp
+++ b/src/target.cpp
@@ -283,6 +283,7 @@ ZigLLVM_OSType get_llvm_os_type(Os os_type) {
case OsSolaris:
return ZigLLVM_Solaris;
case OsWindows:
+ case OsUefi:
return ZigLLVM_Win32;
case OsHaiku:
return ZigLLVM_Haiku;
@@ -316,8 +317,6 @@ ZigLLVM_OSType get_llvm_os_type(Os os_type) {
return ZigLLVM_Contiki;
case OsAMDPAL:
return ZigLLVM_AMDPAL;
- case OsUefi:
- return ZigLLVM_Uefi;
}
zig_unreachable();
}
@@ -809,7 +808,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
}
const char *target_o_file_ext(ZigTarget *target) {
- if (target->env_type == ZigLLVM_MSVC || (target->os == OsWindows || target->os == OsUefi)) {
+ if (target->env_type == ZigLLVM_MSVC || target->os == OsWindows || target->os == OsUefi) {
return ".obj";
} else {
return ".o";
diff --git a/src/target.hpp b/src/target.hpp
index 62cc20711a..a87b12351a 100644
--- a/src/target.hpp
+++ b/src/target.hpp
@@ -54,13 +54,24 @@ enum Os {
OsUefi,
};
+enum TargetSubsystem {
+ TargetSubsystemAuto, // Zig should infer the subsystem
+ TargetSubsystemConsole,
+ TargetSubsystemWindows,
+ TargetSubsystemPosix,
+ TargetSubsystemNative,
+ TargetSubsystemEfiApplication,
+ TargetSubsystemEfiBootServiceDriver,
+ TargetSubsystemEfiRom,
+ TargetSubsystemEfiRuntimeDriver,
+};
+
struct ZigTarget {
ArchType arch;
ZigLLVM_VendorType vendor;
Os os;
ZigLLVM_EnvironmentType env_type;
ZigLLVM_ObjectFormatType oformat;
- ZigLLVM_MSVCSubsystemType msvc_subsystem = ZigLLVM_MSVC_NONE;
};
enum CIntType {
diff --git a/src/translate_c.cpp b/src/translate_c.cpp
index 0e56e29810..02fa3b24be 100644
--- a/src/translate_c.cpp
+++ b/src/translate_c.cpp
@@ -4749,7 +4749,7 @@ Error parse_h_file(ImportTableEntry *import, ZigList *errors, const
clang_argv.append("-isystem");
clang_argv.append(buf_ptr(codegen->zig_c_headers_dir));
- if (codegen->libc_include_dir) {
+ if (codegen->libc_include_dir != nullptr) {
clang_argv.append("-isystem");
clang_argv.append(buf_ptr(codegen->libc_include_dir));
}
diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp
index bd63b7cbe5..bda8fa0adc 100644
--- a/src/zig_llvm.cpp
+++ b/src/zig_llvm.cpp
@@ -690,12 +690,7 @@ const char *ZigLLVMGetVendorTypeName(ZigLLVM_VendorType vendor) {
}
const char *ZigLLVMGetOSTypeName(ZigLLVM_OSType os) {
- switch (os) {
- case ZigLLVM_Uefi:
- return "windows";
- default:
- return (const char*)Triple::getOSTypeName((Triple::OSType)os).bytes_begin();
- }
+ return (const char*)Triple::getOSTypeName((Triple::OSType)os).bytes_begin();
}
const char *ZigLLVMGetEnvironmentTypeName(ZigLLVM_EnvironmentType env_type) {
diff --git a/src/zig_llvm.h b/src/zig_llvm.h
index bb7cb5c5ff..551a4a7448 100644
--- a/src/zig_llvm.h
+++ b/src/zig_llvm.h
@@ -10,7 +10,6 @@
#include
#include
-#include
#include
#include
#include
@@ -358,8 +357,8 @@ enum ZigLLVM_OSType {
ZigLLVM_Mesa3D,
ZigLLVM_Contiki,
ZigLLVM_AMDPAL, // AMD PAL Runtime
- ZigLLVM_Uefi,
- ZigLLVM_LastOSType = ZigLLVM_Uefi
+
+ ZigLLVM_LastOSType = ZigLLVM_AMDPAL
};
// Synchronize with target.cpp::environ_list
@@ -398,19 +397,6 @@ enum ZigLLVM_ObjectFormatType {
ZigLLVM_Wasm,
};
-// For MSVC-supported subsystems
-enum ZigLLVM_MSVCSubsystemType {
- ZigLLVM_MSVC_NONE,
- ZigLLVM_MSVC_CONSOLE,
- ZigLLVM_MSVC_WINDOWS,
- ZigLLVM_MSVC_POSIX,
- ZigLLVM_MSVC_NATIVE,
- ZigLLVM_MSVC_EFI_APPLICATION,
- ZigLLVM_MSVC_EFI_BOOT_SERVICE_DRIVER,
- ZigLLVM_MSVC_EFI_ROM,
- ZigLLVM_MSVC_EFI_RUNTIME_DRIVER,
-};
-
ZIG_EXTERN_C const char *ZigLLVMGetArchTypeName(enum ZigLLVM_ArchType arch);
ZIG_EXTERN_C const char *ZigLLVMGetSubArchTypeName(enum ZigLLVM_SubArchType sub_arch);
ZIG_EXTERN_C const char *ZigLLVMGetVendorTypeName(enum ZigLLVM_VendorType vendor);
diff --git a/std/os/index.zig b/std/os/index.zig
index ce65667157..bb2eb76265 100644
--- a/std/os/index.zig
+++ b/std/os/index.zig
@@ -18,7 +18,7 @@ test "std.os" {
_ = @import("test.zig");
_ = @import("time.zig");
_ = @import("windows/index.zig");
- _ = @import("uefi/index.zig");
+ _ = @import("uefi.zig");
_ = @import("get_app_data_dir.zig");
}
@@ -27,7 +27,7 @@ pub const darwin = @import("darwin.zig");
pub const linux = @import("linux/index.zig");
pub const freebsd = @import("freebsd/index.zig");
pub const zen = @import("zen.zig");
-pub const uefi = @import("uefi/index.zig");
+pub const uefi = @import("uefi.zig");
pub const posix = switch (builtin.os) {
Os.linux => linux,
@@ -192,6 +192,7 @@ pub fn abort() noreturn {
windows.ExitProcess(3);
},
Os.uefi => {
+ // TODO there's gotta be a better thing to do here than loop forever
while (true) {}
},
else => @compileError("Unsupported OS"),
diff --git a/std/os/uefi.zig b/std/os/uefi.zig
new file mode 100644
index 0000000000..8ed60d9c9b
--- /dev/null
+++ b/std/os/uefi.zig
@@ -0,0 +1,2 @@
+// TODO this is where the extern declarations go. For example, see
+// inc/efilib.h in gnu-efi-code
diff --git a/std/os/uefi/index.zig b/std/os/uefi/index.zig
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/std/special/panic.zig b/std/special/panic.zig
index fe1e020604..bd3ad971e0 100644
--- a/std/special/panic.zig
+++ b/std/special/panic.zig
@@ -10,9 +10,13 @@ pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn
@setCold(true);
switch (builtin.os) {
// TODO: fix panic in zen.
- builtin.Os.freestanding, builtin.Os.zen, builtin.Os.uefi => {
+ builtin.Os.freestanding, builtin.Os.zen => {
while (true) {}
},
+ builtin.Os.uefi => {
+ // TODO look into using the debug info and logging helpful messages
+ std.os.abort();
+ },
else => {
const first_trace_addr = @ptrToInt(@returnAddress());
std.debug.panicExtra(error_return_trace, first_trace_addr, "{}", msg);
--
cgit v1.2.3
From 9b8e23934bc87f1fd6a42cdfdd551212994b6e58 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Fri, 1 Feb 2019 17:49:29 -0500
Subject: introduce --single-threaded build option
closes #1764
This adds another boolean to the test matrix; hopefully it does not
inflate the time too much.
std.event.Loop does not work with this option yet. See #1908
---
doc/langref.html.in | 19 +++++++++
src/all_types.hpp | 1 +
src/codegen.cpp | 4 ++
src/main.cpp | 6 +++
std/atomic/queue.zig | 42 ++++++++++++------
std/atomic/stack.zig | 82 ++++++++++++++++++++++++------------
std/event/channel.zig | 3 ++
std/event/future.zig | 3 ++
std/event/group.zig | 3 ++
std/event/lock.zig | 3 ++
std/event/loop.zig | 22 ++++++++++
std/event/net.zig | 3 ++
std/event/rwlock.zig | 3 ++
std/mutex.zig | 66 +++++++++++++++++++++--------
std/os/index.zig | 1 +
std/os/test.zig | 4 ++
std/statically_initialized_mutex.zig | 21 +++++----
test/tests.zig | 43 +++++++++++--------
18 files changed, 246 insertions(+), 83 deletions(-)
(limited to 'src/main.cpp')
diff --git a/doc/langref.html.in b/doc/langref.html.in
index e192dbbf76..144c8571c4 100644
--- a/doc/langref.html.in
+++ b/doc/langref.html.in
@@ -6714,6 +6714,25 @@ pub fn build(b: *Builder) void {
{#header_close#}
{#see_also|Compile Variables|Zig Build System|Undefined Behavior#}
{#header_close#}
+
+ {#header_open|Single Threaded Builds#}
+ Zig has a compile option --single-threaded which has the following effects:
+
+ - {#link|@atomicLoad#} is emitted as a normal load.
+ - {#link|@atomicRmw#} is emitted as a normal memory load, modify, store.
+ - {#link|@fence#} becomes a no-op.
+ - Variables which have Thread Local Storage instead become globals. TODO thread local variables
+ are not implemented yet.
+ - The overhead of {#link|Coroutines#} becomes equivalent to function call overhead.
+ TODO: please note this will not be implemented until the upcoming Coroutine Rewrite
+ - The {#syntax#}@import("builtin").single_threaded{#endsyntax#} becomes {#syntax#}true{#endsyntax#}
+ and therefore various userland APIs which read this variable become more efficient.
+ For example {#syntax#}std.Mutex{#endsyntax#} becomes
+ an empty data structure and all of its functions become no-ops.
+
+
+ {#header_close#}
+
{#header_open|Undefined Behavior#}
Zig has many instances of undefined behavior. If undefined behavior is
diff --git a/src/all_types.hpp b/src/all_types.hpp
index f6fe72891d..3fc6772b31 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -1808,6 +1808,7 @@ struct CodeGen {
bool is_static;
bool strip_debug_symbols;
bool is_test_build;
+ bool is_single_threaded;
bool is_native_target;
bool linker_rdynamic;
bool no_rosegment_workaround;
diff --git a/src/codegen.cpp b/src/codegen.cpp
index e2576f5335..b73fda59d1 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -118,6 +118,7 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
g->string_literals_table.init(16);
g->type_info_cache.init(32);
g->is_test_build = false;
+ g->is_single_threaded = false;
buf_resize(&g->global_asm, 0);
for (size_t i = 0; i < array_length(symbols_that_llvm_depends_on); i += 1) {
@@ -7377,6 +7378,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
buf_appendf(contents, "pub const endian = %s;\n", endian_str);
}
buf_appendf(contents, "pub const is_test = %s;\n", bool_to_str(g->is_test_build));
+ buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded));
buf_appendf(contents, "pub const os = Os.%s;\n", cur_os);
buf_appendf(contents, "pub const arch = Arch.%s;\n", cur_arch);
buf_appendf(contents, "pub const environ = Environ.%s;\n", cur_environ);
@@ -7411,6 +7413,7 @@ static Error define_builtin_compile_vars(CodeGen *g) {
cache_buf(&cache_hash, compiler_id);
cache_int(&cache_hash, g->build_mode);
cache_bool(&cache_hash, g->is_test_build);
+ cache_bool(&cache_hash, g->is_single_threaded);
cache_int(&cache_hash, g->zig_target.arch.arch);
cache_int(&cache_hash, g->zig_target.arch.sub_arch);
cache_int(&cache_hash, g->zig_target.vendor);
@@ -8329,6 +8332,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
cache_bool(ch, g->is_static);
cache_bool(ch, g->strip_debug_symbols);
cache_bool(ch, g->is_test_build);
+ cache_bool(ch, g->is_single_threaded);
cache_bool(ch, g->is_native_target);
cache_bool(ch, g->linker_rdynamic);
cache_bool(ch, g->no_rosegment_workaround);
diff --git a/src/main.cpp b/src/main.cpp
index fd8e3db2fa..81f49089be 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -59,6 +59,7 @@ static int print_full_usage(const char *arg0) {
" --release-fast build with optimizations on and safety off\n"
" --release-safe build with optimizations on and safety on\n"
" --release-small build with size optimizations on and safety off\n"
+ " --single-threaded source may assume it is only used single-threaded\n"
" --static output will be statically linked\n"
" --strip exclude debug symbols\n"
" --target-arch [name] specify target architecture\n"
@@ -393,6 +394,7 @@ int main(int argc, char **argv) {
bool no_rosegment_workaround = false;
bool system_linker_hack = false;
TargetSubsystem subsystem = TargetSubsystemAuto;
+ bool is_single_threaded = false;
if (argc >= 2 && strcmp(argv[1], "build") == 0) {
Buf zig_exe_path_buf = BUF_INIT;
@@ -550,6 +552,8 @@ int main(int argc, char **argv) {
disable_pic = true;
} else if (strcmp(arg, "--system-linker-hack") == 0) {
system_linker_hack = true;
+ } else if (strcmp(arg, "--single-threaded") == 0) {
+ is_single_threaded = true;
} else if (strcmp(arg, "--test-cmd-bin") == 0) {
test_exec_args.append(nullptr);
} else if (arg[1] == 'L' && arg[2] != 0) {
@@ -816,6 +820,7 @@ int main(int argc, char **argv) {
switch (cmd) {
case CmdBuiltin: {
CodeGen *g = codegen_create(nullptr, target, out_type, build_mode, get_zig_lib_dir());
+ g->is_single_threaded = is_single_threaded;
Buf *builtin_source = codegen_generate_builtin_source(g);
if (fwrite(buf_ptr(builtin_source), 1, buf_len(builtin_source), stdout) != buf_len(builtin_source)) {
fprintf(stderr, "unable to write to stdout: %s\n", strerror(ferror(stdout)));
@@ -889,6 +894,7 @@ int main(int argc, char **argv) {
codegen_set_out_name(g, buf_out_name);
codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);
codegen_set_is_test(g, cmd == CmdTest);
+ g->is_single_threaded = is_single_threaded;
codegen_set_linker_script(g, linker_script);
if (each_lib_rpath)
codegen_set_each_lib_rpath(g, each_lib_rpath);
diff --git a/std/atomic/queue.zig b/std/atomic/queue.zig
index 1aab4c32de..6c61bcc048 100644
--- a/std/atomic/queue.zig
+++ b/std/atomic/queue.zig
@@ -170,20 +170,36 @@ test "std.atomic.Queue" {
.get_count = 0,
};
- var putters: [put_thread_count]*std.os.Thread = undefined;
- for (putters) |*t| {
- t.* = try std.os.spawnThread(&context, startPuts);
- }
- var getters: [put_thread_count]*std.os.Thread = undefined;
- for (getters) |*t| {
- t.* = try std.os.spawnThread(&context, startGets);
- }
+ if (builtin.single_threaded) {
+ {
+ var i: usize = 0;
+ while (i < put_thread_count) : (i += 1) {
+ std.debug.assertOrPanic(startPuts(&context) == 0);
+ }
+ }
+ context.puts_done = 1;
+ {
+ var i: usize = 0;
+ while (i < put_thread_count) : (i += 1) {
+ std.debug.assertOrPanic(startGets(&context) == 0);
+ }
+ }
+ } else {
+ var putters: [put_thread_count]*std.os.Thread = undefined;
+ for (putters) |*t| {
+ t.* = try std.os.spawnThread(&context, startPuts);
+ }
+ var getters: [put_thread_count]*std.os.Thread = undefined;
+ for (getters) |*t| {
+ t.* = try std.os.spawnThread(&context, startGets);
+ }
- for (putters) |t|
- t.wait();
- _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);
- for (getters) |t|
- t.wait();
+ for (putters) |t|
+ t.wait();
+ _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);
+ for (getters) |t|
+ t.wait();
+ }
if (context.put_sum != context.get_sum) {
std.debug.panic("failure\nput_sum:{} != get_sum:{}", context.put_sum, context.get_sum);
diff --git a/std/atomic/stack.zig b/std/atomic/stack.zig
index b69a93733c..1e4981353b 100644
--- a/std/atomic/stack.zig
+++ b/std/atomic/stack.zig
@@ -4,10 +4,13 @@ const AtomicOrder = builtin.AtomicOrder;
/// Many reader, many writer, non-allocating, thread-safe
/// Uses a spinlock to protect push() and pop()
+/// When building in single threaded mode, this is a simple linked list.
pub fn Stack(comptime T: type) type {
return struct {
root: ?*Node,
- lock: u8,
+ lock: @typeOf(lock_init),
+
+ const lock_init = if (builtin.single_threaded) {} else u8(0);
pub const Self = @This();
@@ -19,7 +22,7 @@ pub fn Stack(comptime T: type) type {
pub fn init() Self {
return Self{
.root = null,
- .lock = 0,
+ .lock = lock_init,
};
}
@@ -31,20 +34,31 @@ pub fn Stack(comptime T: type) type {
}
pub fn push(self: *Self, node: *Node) void {
- while (@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) != 0) {}
- defer assert(@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst) == 1);
-
- node.next = self.root;
- self.root = node;
+ if (builtin.single_threaded) {
+ node.next = self.root;
+ self.root = node;
+ } else {
+ while (@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) != 0) {}
+ defer assert(@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst) == 1);
+
+ node.next = self.root;
+ self.root = node;
+ }
}
pub fn pop(self: *Self) ?*Node {
- while (@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) != 0) {}
- defer assert(@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst) == 1);
-
- const root = self.root orelse return null;
- self.root = root.next;
- return root;
+ if (builtin.single_threaded) {
+ const root = self.root orelse return null;
+ self.root = root.next;
+ return root;
+ } else {
+ while (@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst) != 0) {}
+ defer assert(@atomicRmw(u8, &self.lock, builtin.AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst) == 1);
+
+ const root = self.root orelse return null;
+ self.root = root.next;
+ return root;
+ }
}
pub fn isEmpty(self: *Self) bool {
@@ -90,20 +104,36 @@ test "std.atomic.stack" {
.get_count = 0,
};
- var putters: [put_thread_count]*std.os.Thread = undefined;
- for (putters) |*t| {
- t.* = try std.os.spawnThread(&context, startPuts);
- }
- var getters: [put_thread_count]*std.os.Thread = undefined;
- for (getters) |*t| {
- t.* = try std.os.spawnThread(&context, startGets);
- }
+ if (builtin.single_threaded) {
+ {
+ var i: usize = 0;
+ while (i < put_thread_count) : (i += 1) {
+ std.debug.assertOrPanic(startPuts(&context) == 0);
+ }
+ }
+ context.puts_done = 1;
+ {
+ var i: usize = 0;
+ while (i < put_thread_count) : (i += 1) {
+ std.debug.assertOrPanic(startGets(&context) == 0);
+ }
+ }
+ } else {
+ var putters: [put_thread_count]*std.os.Thread = undefined;
+ for (putters) |*t| {
+ t.* = try std.os.spawnThread(&context, startPuts);
+ }
+ var getters: [put_thread_count]*std.os.Thread = undefined;
+ for (getters) |*t| {
+ t.* = try std.os.spawnThread(&context, startGets);
+ }
- for (putters) |t|
- t.wait();
- _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);
- for (getters) |t|
- t.wait();
+ for (putters) |t|
+ t.wait();
+ _ = @atomicRmw(u8, &context.puts_done, builtin.AtomicRmwOp.Xchg, 1, AtomicOrder.SeqCst);
+ for (getters) |t|
+ t.wait();
+ }
if (context.put_sum != context.get_sum) {
std.debug.panic("failure\nput_sum:{} != get_sum:{}", context.put_sum, context.get_sum);
diff --git a/std/event/channel.zig b/std/event/channel.zig
index 133ce1c69c..f04ad1604e 100644
--- a/std/event/channel.zig
+++ b/std/event/channel.zig
@@ -319,6 +319,9 @@ pub fn Channel(comptime T: type) type {
}
test "std.event.Channel" {
+ // https://github.com/ziglang/zig/issues/1908
+ if (builtin.single_threaded) return error.SkipZigTest;
+
var da = std.heap.DirectAllocator.init();
defer da.deinit();
diff --git a/std/event/future.zig b/std/event/future.zig
index d61768b198..55ed01046d 100644
--- a/std/event/future.zig
+++ b/std/event/future.zig
@@ -84,6 +84,9 @@ pub fn Future(comptime T: type) type {
}
test "std.event.Future" {
+ // https://github.com/ziglang/zig/issues/1908
+ if (builtin.single_threaded) return error.SkipZigTest;
+
var da = std.heap.DirectAllocator.init();
defer da.deinit();
diff --git a/std/event/group.zig b/std/event/group.zig
index 9f2687a5b3..0e9c2d9655 100644
--- a/std/event/group.zig
+++ b/std/event/group.zig
@@ -121,6 +121,9 @@ pub fn Group(comptime ReturnType: type) type {
}
test "std.event.Group" {
+ // https://github.com/ziglang/zig/issues/1908
+ if (builtin.single_threaded) return error.SkipZigTest;
+
var da = std.heap.DirectAllocator.init();
defer da.deinit();
diff --git a/std/event/lock.zig b/std/event/lock.zig
index 46e0d13468..01978e1909 100644
--- a/std/event/lock.zig
+++ b/std/event/lock.zig
@@ -122,6 +122,9 @@ pub const Lock = struct {
};
test "std.event.Lock" {
+ // https://github.com/ziglang/zig/issues/1908
+ if (builtin.single_threaded) return error.SkipZigTest;
+
var da = std.heap.DirectAllocator.init();
defer da.deinit();
diff --git a/std/event/loop.zig b/std/event/loop.zig
index 43965e8293..d5228db604 100644
--- a/std/event/loop.zig
+++ b/std/event/loop.zig
@@ -97,6 +97,7 @@ pub const Loop = struct {
/// TODO copy elision / named return values so that the threads referencing *Loop
/// have the correct pointer value.
pub fn initMultiThreaded(self: *Loop, allocator: *mem.Allocator) !void {
+ if (builtin.single_threaded) @compileError("initMultiThreaded unavailable when building in single-threaded mode");
const core_count = try os.cpuCount(allocator);
return self.initInternal(allocator, core_count);
}
@@ -201,6 +202,11 @@ pub const Loop = struct {
self.os_data.fs_thread.wait();
}
+ if (builtin.single_threaded) {
+ assert(extra_thread_count == 0);
+ return;
+ }
+
var extra_thread_index: usize = 0;
errdefer {
// writing 8 bytes to an eventfd cannot fail
@@ -301,6 +307,11 @@ pub const Loop = struct {
self.os_data.fs_thread.wait();
}
+ if (builtin.single_threaded) {
+ assert(extra_thread_count == 0);
+ return;
+ }
+
var extra_thread_index: usize = 0;
errdefer {
_ = os.bsdKEvent(self.os_data.kqfd, final_kev_arr, empty_kevs, null) catch unreachable;
@@ -338,6 +349,11 @@ pub const Loop = struct {
self.available_eventfd_resume_nodes.push(eventfd_node);
}
+ if (builtin.single_threaded) {
+ assert(extra_thread_count == 0);
+ return;
+ }
+
var extra_thread_index: usize = 0;
errdefer {
var i: usize = 0;
@@ -845,6 +861,9 @@ pub const Loop = struct {
};
test "std.event.Loop - basic" {
+ // https://github.com/ziglang/zig/issues/1908
+ if (builtin.single_threaded) return error.SkipZigTest;
+
var da = std.heap.DirectAllocator.init();
defer da.deinit();
@@ -858,6 +877,9 @@ test "std.event.Loop - basic" {
}
test "std.event.Loop - call" {
+ // https://github.com/ziglang/zig/issues/1908
+ if (builtin.single_threaded) return error.SkipZigTest;
+
var da = std.heap.DirectAllocator.init();
defer da.deinit();
diff --git a/std/event/net.zig b/std/event/net.zig
index 6838704084..9dac6aa566 100644
--- a/std/event/net.zig
+++ b/std/event/net.zig
@@ -269,6 +269,9 @@ pub async fn connect(loop: *Loop, _address: *const std.net.Address) !os.File {
}
test "listen on a port, send bytes, receive bytes" {
+ // https://github.com/ziglang/zig/issues/1908
+ if (builtin.single_threaded) return error.SkipZigTest;
+
if (builtin.os != builtin.Os.linux) {
// TODO build abstractions for other operating systems
return error.SkipZigTest;
diff --git a/std/event/rwlock.zig b/std/event/rwlock.zig
index 5d48ea893e..f272ac71ea 100644
--- a/std/event/rwlock.zig
+++ b/std/event/rwlock.zig
@@ -211,6 +211,9 @@ pub const RwLock = struct {
};
test "std.event.RwLock" {
+ // https://github.com/ziglang/zig/issues/1908
+ if (builtin.single_threaded) return error.SkipZigTest;
+
var da = std.heap.DirectAllocator.init();
defer da.deinit();
diff --git a/std/mutex.zig b/std/mutex.zig
index 723581cbef..54173fa38a 100644
--- a/std/mutex.zig
+++ b/std/mutex.zig
@@ -14,7 +14,36 @@ const windows = std.os.windows;
/// If you need static initialization, use std.StaticallyInitializedMutex.
/// The Linux implementation is based on mutex3 from
/// https://www.akkadia.org/drepper/futex.pdf
-pub const Mutex = switch(builtin.os) {
+/// When an application is built in single threaded release mode, all the functions are
+/// no-ops. In single threaded debug mode, there is deadlock detection.
+pub const Mutex = if (builtin.single_threaded)
+ struct {
+ lock: @typeOf(lock_init),
+
+ const lock_init = if (std.debug.runtime_safety) false else {};
+
+ pub const Held = struct {
+ mutex: *Mutex,
+
+ pub fn release(self: Held) void {
+ if (std.debug.runtime_safety) {
+ self.mutex.lock = false;
+ }
+ }
+ };
+ pub fn init() Mutex {
+ return Mutex{ .lock = lock_init };
+ }
+ pub fn deinit(self: *Mutex) void {}
+
+ pub fn acquire(self: *Mutex) Held {
+ if (std.debug.runtime_safety and self.lock) {
+ @panic("deadlock detected");
+ }
+ return Held{ .mutex = self };
+ }
+ }
+else switch (builtin.os) {
builtin.Os.linux => struct {
/// 0: unlocked
/// 1: locked, no waiters
@@ -39,9 +68,7 @@ pub const Mutex = switch(builtin.os) {
};
pub fn init() Mutex {
- return Mutex {
- .lock = 0,
- };
+ return Mutex{ .lock = 0 };
}
pub fn deinit(self: *Mutex) void {}
@@ -60,7 +87,7 @@ pub const Mutex = switch(builtin.os) {
}
c = @atomicRmw(i32, &self.lock, AtomicRmwOp.Xchg, 2, AtomicOrder.Acquire);
}
- return Held { .mutex = self };
+ return Held{ .mutex = self };
}
},
// TODO once https://github.com/ziglang/zig/issues/287 (copy elision) is solved, we can make a
@@ -78,21 +105,19 @@ pub const Mutex = switch(builtin.os) {
mutex: *Mutex,
pub fn release(self: Held) void {
- SpinLock.Held.release(SpinLock.Held { .spinlock = &self.mutex.lock });
+ SpinLock.Held.release(SpinLock.Held{ .spinlock = &self.mutex.lock });
}
};
pub fn init() Mutex {
- return Mutex {
- .lock = SpinLock.init(),
- };
+ return Mutex{ .lock = SpinLock.init() };
}
pub fn deinit(self: *Mutex) void {}
pub fn acquire(self: *Mutex) Held {
_ = self.lock.acquire();
- return Held { .mutex = self };
+ return Held{ .mutex = self };
}
},
};
@@ -122,15 +147,20 @@ test "std.Mutex" {
.data = 0,
};
- const thread_count = 10;
- var threads: [thread_count]*std.os.Thread = undefined;
- for (threads) |*t| {
- t.* = try std.os.spawnThread(&context, worker);
- }
- for (threads) |t|
- t.wait();
+ if (builtin.single_threaded) {
+ worker(&context);
+ std.debug.assertOrPanic(context.data == TestContext.incr_count);
+ } else {
+ const thread_count = 10;
+ var threads: [thread_count]*std.os.Thread = undefined;
+ for (threads) |*t| {
+ t.* = try std.os.spawnThread(&context, worker);
+ }
+ for (threads) |t|
+ t.wait();
- std.debug.assertOrPanic(context.data == thread_count * TestContext.incr_count);
+ std.debug.assertOrPanic(context.data == thread_count * TestContext.incr_count);
+ }
}
fn worker(ctx: *TestContext) void {
diff --git a/std/os/index.zig b/std/os/index.zig
index 78d543583d..75abe3bbde 100644
--- a/std/os/index.zig
+++ b/std/os/index.zig
@@ -3013,6 +3013,7 @@ pub const SpawnThreadError = error{
/// where T is u8, noreturn, void, or !void
/// caller must call wait on the returned thread
pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread {
+ if (builtin.single_threaded) @compileError("cannot spawn thread when building in single-threaded mode");
// TODO compile-time call graph analysis to determine stack upper bound
// https://github.com/ziglang/zig/issues/157
const default_stack_size = 8 * 1024 * 1024;
diff --git a/std/os/test.zig b/std/os/test.zig
index 5142920687..f14cf47786 100644
--- a/std/os/test.zig
+++ b/std/os/test.zig
@@ -40,6 +40,8 @@ fn testThreadIdFn(thread_id: *os.Thread.Id) void {
}
test "std.os.Thread.getCurrentId" {
+ if (builtin.single_threaded) return error.SkipZigTest;
+
var thread_current_id: os.Thread.Id = undefined;
const thread = try os.spawnThread(&thread_current_id, testThreadIdFn);
const thread_id = thread.handle();
@@ -53,6 +55,8 @@ test "std.os.Thread.getCurrentId" {
}
test "spawn threads" {
+ if (builtin.single_threaded) return error.SkipZigTest;
+
var shared_ctx: i32 = 1;
const thread1 = try std.os.spawnThread({}, start1);
diff --git a/std/statically_initialized_mutex.zig b/std/statically_initialized_mutex.zig
index dd875eeaf9..37582d49c1 100644
--- a/std/statically_initialized_mutex.zig
+++ b/std/statically_initialized_mutex.zig
@@ -93,13 +93,18 @@ test "std.StaticallyInitializedMutex" {
.data = 0,
};
- const thread_count = 10;
- var threads: [thread_count]*std.os.Thread = undefined;
- for (threads) |*t| {
- t.* = try std.os.spawnThread(&context, TestContext.worker);
- }
- for (threads) |t|
- t.wait();
+ if (builtin.single_threaded) {
+ TestContext.worker(&context);
+ std.debug.assertOrPanic(context.data == TestContext.incr_count);
+ } else {
+ const thread_count = 10;
+ var threads: [thread_count]*std.os.Thread = undefined;
+ for (threads) |*t| {
+ t.* = try std.os.spawnThread(&context, TestContext.worker);
+ }
+ for (threads) |t|
+ t.wait();
- std.debug.assertOrPanic(context.data == thread_count * TestContext.incr_count);
+ std.debug.assertOrPanic(context.data == thread_count * TestContext.incr_count);
+ }
}
diff --git a/test/tests.zig b/test/tests.zig
index 1ca06b4b34..73d4644d18 100644
--- a/test/tests.zig
+++ b/test/tests.zig
@@ -163,25 +163,32 @@ pub fn addPkgTests(b: *build.Builder, test_filter: ?[]const u8, root_src: []cons
for (test_targets) |test_target| {
const is_native = (test_target.os == builtin.os and test_target.arch == builtin.arch);
for (modes) |mode| {
- for ([]bool{
- false,
- true,
- }) |link_libc| {
- if (link_libc and !is_native) {
- // don't assume we have a cross-compiling libc set up
- continue;
- }
- const these_tests = b.addTest(root_src);
- these_tests.setNamePrefix(b.fmt("{}-{}-{}-{}-{} ", name, @tagName(test_target.os), @tagName(test_target.arch), @tagName(mode), if (link_libc) "c" else "bare"));
- these_tests.setFilter(test_filter);
- these_tests.setBuildMode(mode);
- if (!is_native) {
- these_tests.setTarget(test_target.arch, test_target.os, test_target.environ);
- }
- if (link_libc) {
- these_tests.linkSystemLibrary("c");
+ for ([]bool{ false, true }) |link_libc| {
+ for ([]bool{ false, true }) |single_threaded| {
+ if (link_libc and !is_native) {
+ // don't assume we have a cross-compiling libc set up
+ continue;
+ }
+ const these_tests = b.addTest(root_src);
+ these_tests.setNamePrefix(b.fmt(
+ "{}-{}-{}-{}-{}-{} ",
+ name,
+ @tagName(test_target.os),
+ @tagName(test_target.arch),
+ @tagName(mode),
+ if (link_libc) "c" else "bare",
+ if (single_threaded) "single" else "multi",
+ ));
+ these_tests.setFilter(test_filter);
+ these_tests.setBuildMode(mode);
+ if (!is_native) {
+ these_tests.setTarget(test_target.arch, test_target.os, test_target.environ);
+ }
+ if (link_libc) {
+ these_tests.linkSystemLibrary("c");
+ }
+ step.dependOn(&these_tests.step);
}
- step.dependOn(&these_tests.step);
}
}
}
--
cgit v1.2.3
From d2602b442e7cdea2e74584f9529917d7a53625fd Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Wed, 6 Feb 2019 14:32:20 -0500
Subject: require running std lib tests coherently
this should actually improve CI times a bit too
See the description at the top of std/os/startup.zig (deleted in this
commit) for a more detailed understanding of what this commit does.
---
CMakeLists.txt | 1 -
src/codegen.cpp | 18 +++++++++++++-----
src/codegen.hpp | 2 +-
src/link.cpp | 2 +-
src/main.cpp | 12 +++++++++---
std/build.zig | 10 ++++++++++
std/index.zig | 1 -
std/os/index.zig | 31 +++++++++++++++++++++----------
std/os/startup.zig | 26 --------------------------
std/special/bootstrap.zig | 14 +++++++-------
test/tests.zig | 3 +++
11 files changed, 65 insertions(+), 55 deletions(-)
delete mode 100644 std/os/startup.zig
(limited to 'src/main.cpp')
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a093bfbfd9..4dd6a1dcfa 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -587,7 +587,6 @@ set(ZIG_STD_FILES
"os/linux/vdso.zig"
"os/linux/x86_64.zig"
"os/path.zig"
- "os/startup.zig"
"os/time.zig"
"os/uefi.zig"
"os/windows/advapi32.zig"
diff --git a/src/codegen.cpp b/src/codegen.cpp
index d8fc077efc..5e282160d6 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -88,7 +88,7 @@ static const char *symbols_that_llvm_depends_on[] = {
};
CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode,
- Buf *zig_lib_dir)
+ Buf *zig_lib_dir, Buf *override_std_dir)
{
CodeGen *g = allocate(1);
@@ -96,8 +96,12 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
g->zig_lib_dir = zig_lib_dir;
- g->zig_std_dir = buf_alloc();
- os_path_join(zig_lib_dir, buf_create_from_str("std"), g->zig_std_dir);
+ if (override_std_dir == nullptr) {
+ g->zig_std_dir = buf_alloc();
+ os_path_join(zig_lib_dir, buf_create_from_str("std"), g->zig_std_dir);
+ } else {
+ g->zig_std_dir = override_std_dir;
+ }
g->zig_c_headers_dir = buf_alloc();
os_path_join(zig_lib_dir, buf_create_from_str("include"), g->zig_c_headers_dir);
@@ -8356,8 +8360,12 @@ static void add_cache_pkg(CodeGen *g, CacheHash *ch, PackageTableEntry *pkg) {
if (!entry)
break;
- cache_buf(ch, entry->key);
- add_cache_pkg(g, ch, entry->value);
+ // TODO: I think we need a more sophisticated detection of
+ // packages we have already seen
+ if (entry->value != pkg) {
+ cache_buf(ch, entry->key);
+ add_cache_pkg(g, ch, entry->value);
+ }
}
}
diff --git a/src/codegen.hpp b/src/codegen.hpp
index 6f1cdfb677..4bd8f2dcca 100644
--- a/src/codegen.hpp
+++ b/src/codegen.hpp
@@ -15,7 +15,7 @@
#include
CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode,
- Buf *zig_lib_dir);
+ Buf *zig_lib_dir, Buf *override_std_dir);
void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len);
void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len);
diff --git a/src/link.cpp b/src/link.cpp
index 593f7f309f..58221a99ea 100644
--- a/src/link.cpp
+++ b/src/link.cpp
@@ -42,7 +42,7 @@ static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path)
}
CodeGen *child_gen = codegen_create(full_path, child_target, child_out_type,
- parent_gen->build_mode, parent_gen->zig_lib_dir);
+ parent_gen->build_mode, parent_gen->zig_lib_dir, parent_gen->zig_std_dir);
child_gen->out_h_path = nullptr;
child_gen->verbose_tokenize = parent_gen->verbose_tokenize;
diff --git a/src/main.cpp b/src/main.cpp
index 81f49089be..73a1d75d42 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -74,6 +74,7 @@ static int print_full_usage(const char *arg0) {
" -dirafter [dir] same as -isystem but do it last\n"
" -isystem [dir] add additional search path for other .h files\n"
" -mllvm [arg] forward an arg to LLVM's option processing\n"
+ " --override-std-dir [arg] use an alternate Zig standard library\n"
"\n"
"Link Options:\n"
" --dynamic-linker [path] set the path to ld.so\n"
@@ -395,6 +396,7 @@ int main(int argc, char **argv) {
bool system_linker_hack = false;
TargetSubsystem subsystem = TargetSubsystemAuto;
bool is_single_threaded = false;
+ Buf *override_std_dir = nullptr;
if (argc >= 2 && strcmp(argv[1], "build") == 0) {
Buf zig_exe_path_buf = BUF_INIT;
@@ -430,7 +432,8 @@ int main(int argc, char **argv) {
Buf *build_runner_path = buf_alloc();
os_path_join(get_zig_special_dir(), buf_create_from_str("build_runner.zig"), build_runner_path);
- CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe, BuildModeDebug, get_zig_lib_dir());
+ CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe, BuildModeDebug, get_zig_lib_dir(),
+ override_std_dir);
g->enable_time_report = timing_info;
buf_init_from_str(&g->cache_dir, cache_dir ? cache_dir : default_zig_cache_name);
codegen_set_out_name(g, buf_create_from_str("build"));
@@ -645,6 +648,8 @@ int main(int argc, char **argv) {
clang_argv.append(argv[i]);
llvm_argv.append(argv[i]);
+ } else if (strcmp(arg, "--override-std-dir") == 0) {
+ override_std_dir = buf_create_from_str(argv[i]);
} else if (strcmp(arg, "--library-path") == 0 || strcmp(arg, "-L") == 0) {
lib_dirs.append(argv[i]);
} else if (strcmp(arg, "--library") == 0) {
@@ -819,7 +824,7 @@ int main(int argc, char **argv) {
switch (cmd) {
case CmdBuiltin: {
- CodeGen *g = codegen_create(nullptr, target, out_type, build_mode, get_zig_lib_dir());
+ CodeGen *g = codegen_create(nullptr, target, out_type, build_mode, get_zig_lib_dir(), override_std_dir);
g->is_single_threaded = is_single_threaded;
Buf *builtin_source = codegen_generate_builtin_source(g);
if (fwrite(buf_ptr(builtin_source), 1, buf_len(builtin_source), stdout) != buf_len(builtin_source)) {
@@ -878,7 +883,8 @@ int main(int argc, char **argv) {
if (cmd == CmdRun && buf_out_name == nullptr) {
buf_out_name = buf_create_from_str("run");
}
- CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode, get_zig_lib_dir());
+ CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode, get_zig_lib_dir(),
+ override_std_dir);
g->subsystem = subsystem;
if (disable_pic) {
diff --git a/std/build.zig b/std/build.zig
index 5246d97339..07efcec30d 100644
--- a/std/build.zig
+++ b/std/build.zig
@@ -1686,6 +1686,7 @@ pub const TestStep = struct {
no_rosegment: bool,
output_path: ?[]const u8,
system_linker_hack: bool,
+ override_std_dir: ?[]const u8,
pub fn init(builder: *Builder, root_src: []const u8) TestStep {
const step_name = builder.fmt("test {}", root_src);
@@ -1707,6 +1708,7 @@ pub const TestStep = struct {
.no_rosegment = false,
.output_path = null,
.system_linker_hack = false,
+ .override_std_dir = null,
};
}
@@ -1737,6 +1739,10 @@ pub const TestStep = struct {
self.build_mode = mode;
}
+ pub fn overrideStdDir(self: *TestStep, dir_path: []const u8) void {
+ self.override_std_dir = dir_path;
+ }
+
pub fn setOutputPath(self: *TestStep, file_path: []const u8) void {
self.output_path = file_path;
@@ -1914,6 +1920,10 @@ pub const TestStep = struct {
if (self.system_linker_hack) {
try zig_args.append("--system-linker-hack");
}
+ if (self.override_std_dir) |dir| {
+ try zig_args.append("--override-std-dir");
+ try zig_args.append(builder.pathFromRoot(dir));
+ }
try builder.spawnChild(zig_args.toSliceConst());
}
diff --git a/std/index.zig b/std/index.zig
index ef3988460f..2a63244004 100644
--- a/std/index.zig
+++ b/std/index.zig
@@ -45,7 +45,6 @@ pub const unicode = @import("unicode.zig");
pub const zig = @import("zig/index.zig");
pub const lazyInit = @import("lazy_init.zig").lazyInit;
-pub const startup = @import("os/startup.zig");
test "std" {
// run tests from these
diff --git a/std/os/index.zig b/std/os/index.zig
index 68b3409757..d17b6f4f40 100644
--- a/std/os/index.zig
+++ b/std/os/index.zig
@@ -8,8 +8,9 @@ const is_posix = switch (builtin.os) {
};
const os = @This();
-// See the comment in startup.zig for why this does not use the `std` global above.
-const startup = @import("std").startup;
+comptime {
+ assert(@import("std") == std); // You have to run the std lib tests with --override-std-dir
+}
test "std.os" {
_ = @import("child_process.zig");
@@ -670,11 +671,14 @@ fn posixExecveErrnoToErr(err: usize) PosixExecveError {
}
}
+pub var linux_elf_aux_maybe: ?[*]std.elf.Auxv = null;
+pub var posix_environ_raw: [][*]u8 = undefined;
+
/// See std.elf for the constants.
pub fn linuxGetAuxVal(index: usize) usize {
if (builtin.link_libc) {
return usize(std.c.getauxval(index));
- } else if (startup.linux_elf_aux_maybe) |auxv| {
+ } else if (linux_elf_aux_maybe) |auxv| {
var i: usize = 0;
while (auxv[i].a_type != std.elf.AT_NULL) : (i += 1) {
if (auxv[i].a_type == index)
@@ -734,7 +738,7 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
try result.setMove(key, value);
}
} else {
- for (startup.posix_environ_raw) |ptr| {
+ for (posix_environ_raw) |ptr| {
var line_i: usize = 0;
while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {}
const key = ptr[0..line_i];
@@ -756,7 +760,7 @@ test "os.getEnvMap" {
/// TODO make this go through libc when we have it
pub fn getEnvPosix(key: []const u8) ?[]const u8 {
- for (startup.posix_environ_raw) |ptr| {
+ for (posix_environ_raw) |ptr| {
var line_i: usize = 0;
while (ptr[line_i] != 0 and ptr[line_i] != '=') : (line_i += 1) {}
const this_key = ptr[0..line_i];
@@ -1937,14 +1941,14 @@ pub const ArgIteratorPosix = struct {
pub fn init() ArgIteratorPosix {
return ArgIteratorPosix{
.index = 0,
- .count = startup.posix_argv_raw.len,
+ .count = raw.len,
};
}
pub fn next(self: *ArgIteratorPosix) ?[]const u8 {
if (self.index == self.count) return null;
- const s = startup.posix_argv_raw[self.index];
+ const s = raw[self.index];
self.index += 1;
return cstr.toSlice(s);
}
@@ -1955,6 +1959,10 @@ pub const ArgIteratorPosix = struct {
self.index += 1;
return true;
}
+
+ /// This is marked as public but actually it's only meant to be used
+ /// internally by zig's startup code.
+ pub var raw: [][*]u8 = undefined;
};
pub const ArgIteratorWindows = struct {
@@ -3000,6 +3008,9 @@ pub const SpawnThreadError = error{
Unexpected,
};
+pub var linux_tls_phdr: ?*std.elf.Phdr = null;
+pub var linux_tls_img_src: [*]const u8 = undefined; // defined if linux_tls_phdr is
+
/// caller must call wait on the returned thread
/// fn startFn(@typeOf(context)) T
/// where T is u8, noreturn, void, or !void
@@ -3109,7 +3120,7 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread
}
// Finally, the Thread Local Storage, if any.
if (!Thread.use_pthreads) {
- if (startup.linux_tls_phdr) |tls_phdr| {
+ if (linux_tls_phdr) |tls_phdr| {
l = mem.alignForward(l, tls_phdr.p_align);
tls_start_offset = l;
l += tls_phdr.p_memsz;
@@ -3153,8 +3164,8 @@ pub fn spawnThread(context: var, comptime startFn: var) SpawnThreadError!*Thread
posix.CLONE_THREAD | posix.CLONE_SYSVSEM | posix.CLONE_PARENT_SETTID | posix.CLONE_CHILD_CLEARTID |
posix.CLONE_DETACHED;
var newtls: usize = undefined;
- if (startup.linux_tls_phdr) |tls_phdr| {
- @memcpy(@intToPtr([*]u8, mmap_addr + tls_start_offset), startup.linux_tls_img_src, tls_phdr.p_filesz);
+ if (linux_tls_phdr) |tls_phdr| {
+ @memcpy(@intToPtr([*]u8, mmap_addr + tls_start_offset), linux_tls_img_src, tls_phdr.p_filesz);
thread_ptr.data.tls_end_addr = mmap_addr + mmap_len;
newtls = @ptrToInt(&thread_ptr.data.tls_end_addr);
flags |= posix.CLONE_SETTLS;
diff --git a/std/os/startup.zig b/std/os/startup.zig
deleted file mode 100644
index c54d274c5d..0000000000
--- a/std/os/startup.zig
+++ /dev/null
@@ -1,26 +0,0 @@
-// This file contains global variables that are initialized on startup from
-// std/special/bootstrap.zig. There are a few things to be aware of here.
-//
-// First, when building an object or library, and no entry point is defined
-// (such as pub fn main), std/special/bootstrap.zig is not included in the
-// compilation. And so these global variables will remain set to the values
-// you see here.
-//
-// Second, when using `zig test` to test the standard library, note that
-// `zig test` is self-hosted. This means that it uses std/special/bootstrap.zig
-// and an @import("std") from the install directory, which is distinct from
-// the standard library files that we are directly testing with `zig test`.
-// This means that these global variables would not get set. So the workaround
-// here is that references to these globals from the standard library must
-// use `@import("std").startup` rather than
-// `@import("path/to/std/index.zig").startup` (and rather than the file path of
-// this file directly). We also put "std" as a reference to itself in the
-// standard library package so that this can work.
-
-const std = @import("../index.zig");
-
-pub var linux_tls_phdr: ?*std.elf.Phdr = null;
-pub var linux_tls_img_src: [*]const u8 = undefined; // defined when linux_tls_phdr is non-null
-pub var linux_elf_aux_maybe: ?[*]std.elf.Auxv = null;
-pub var posix_environ_raw: [][*]u8 = undefined;
-pub var posix_argv_raw: [][*]u8 = undefined;
diff --git a/std/special/bootstrap.zig b/std/special/bootstrap.zig
index 0e84f67481..97699e0cc5 100644
--- a/std/special/bootstrap.zig
+++ b/std/special/bootstrap.zig
@@ -64,7 +64,7 @@ fn posixCallMainAndExit() noreturn {
if (builtin.os == builtin.Os.linux) {
// Scan auxiliary vector.
const auxv = @ptrCast([*]std.elf.Auxv, envp.ptr + envp_count + 1);
- std.startup.linux_elf_aux_maybe = auxv;
+ std.os.linux_elf_aux_maybe = auxv;
var i: usize = 0;
var at_phdr: usize = 0;
var at_phnum: usize = 0;
@@ -87,8 +87,8 @@ fn posixCallMainAndExit() noreturn {
// This is marked inline because for some reason LLVM in release mode fails to inline it,
// and we want fewer call frames in stack traces.
inline fn callMainWithArgs(argc: usize, argv: [*][*]u8, envp: [][*]u8) u8 {
- std.startup.posix_argv_raw = argv[0..argc];
- std.startup.posix_environ_raw = envp;
+ std.os.ArgIteratorPosix.raw = argv[0..argc];
+ std.os.posix_environ_raw = envp;
return callMain();
}
@@ -145,15 +145,15 @@ fn linuxInitializeThreadLocalStorage(at_phdr: usize, at_phnum: usize, at_phent:
// TODO look for PT_DYNAMIC when we have https://github.com/ziglang/zig/issues/1917
switch (phdr.p_type) {
std.elf.PT_PHDR => base = at_phdr - phdr.p_vaddr,
- std.elf.PT_TLS => std.startup.linux_tls_phdr = phdr,
+ std.elf.PT_TLS => std.os.linux_tls_phdr = phdr,
else => continue,
}
}
- const tls_phdr = std.startup.linux_tls_phdr orelse return;
- std.startup.linux_tls_img_src = @intToPtr([*]const u8, base + tls_phdr.p_vaddr);
+ const tls_phdr = std.os.linux_tls_phdr orelse return;
+ std.os.linux_tls_img_src = @intToPtr([*]const u8, base + tls_phdr.p_vaddr);
assert(main_thread_tls_bytes.len >= tls_phdr.p_memsz); // not enough preallocated Thread Local Storage
assert(main_thread_tls_align >= tls_phdr.p_align); // preallocated Thread Local Storage not aligned enough
- @memcpy(&main_thread_tls_bytes, std.startup.linux_tls_img_src, tls_phdr.p_filesz);
+ @memcpy(&main_thread_tls_bytes, std.os.linux_tls_img_src, tls_phdr.p_filesz);
tls_end_addr = @ptrToInt(&main_thread_tls_bytes) + tls_phdr.p_memsz;
linuxSetThreadArea(@ptrToInt(&tls_end_addr));
}
diff --git a/test/tests.zig b/test/tests.zig
index 548496fa2f..fc188f5550 100644
--- a/test/tests.zig
+++ b/test/tests.zig
@@ -194,6 +194,9 @@ pub fn addPkgTests(b: *build.Builder, test_filter: ?[]const u8, root_src: []cons
if (link_libc) {
these_tests.linkSystemLibrary("c");
}
+ if (mem.eql(u8, name, "std")) {
+ these_tests.overrideStdDir("std");
+ }
step.dependOn(&these_tests.step);
}
}
--
cgit v1.2.3
From ba56f365c813440b79c1710c6a8b0fd591883e13 Mon Sep 17 00:00:00 2001
From: Andrew Kelley
Date: Sat, 16 Feb 2019 00:42:56 -0500
Subject: bring zig fmt to stage1
---
CMakeLists.txt | 5 +
src-self-hosted/main.zig | 6 +-
src/main.cpp | 36 +++++-
std/special/fmt_runner.zig | 265 +++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 305 insertions(+), 7 deletions(-)
create mode 100644 std/special/fmt_runner.zig
(limited to 'src/main.cpp')
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8e80c65dbd..db5f50908c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -652,6 +652,7 @@ set(ZIG_STD_FILES
"special/compiler_rt/udivmodti4.zig"
"special/compiler_rt/udivti3.zig"
"special/compiler_rt/umodti3.zig"
+ "special/fmt_runner.zig"
"special/init-exe/build.zig"
"special/init-exe/src/main.zig"
"special/init-lib/build.zig"
@@ -905,3 +906,7 @@ foreach(file ${ZIG_STD_FILES})
get_filename_component(file_dir "${ZIG_STD_DEST}/${file}" DIRECTORY)
install(FILES "${CMAKE_SOURCE_DIR}/std/${file}" DESTINATION "${file_dir}")
endforeach()
+
+install(FILES "${CMAKE_SOURCE_DIR}/src-self-hosted/arg.zig" DESTINATION "${ZIG_STD_DEST}/special/fmt/")
+install(FILES "${CMAKE_SOURCE_DIR}/src-self-hosted/main.zig" DESTINATION "${ZIG_STD_DEST}/special/fmt/")
+install(FILES "${CMAKE_SOURCE_DIR}/src-self-hosted/errmsg.zig" DESTINATION "${ZIG_STD_DEST}/special/fmt/")
diff --git a/src-self-hosted/main.zig b/src-self-hosted/main.zig
index 64aa729469..42556beaed 100644
--- a/src-self-hosted/main.zig
+++ b/src-self-hosted/main.zig
@@ -24,7 +24,7 @@ var stderr_file: os.File = undefined;
var stderr: *io.OutStream(os.File.WriteError) = undefined;
var stdout: *io.OutStream(os.File.WriteError) = undefined;
-const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB
+pub const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB
const usage =
\\usage: zig [command] [options]
@@ -510,7 +510,7 @@ fn cmdBuildObj(allocator: *Allocator, args: []const []const u8) !void {
return buildOutputType(allocator, args, Compilation.Kind.Obj);
}
-const usage_fmt =
+pub const usage_fmt =
\\usage: zig fmt [file]...
\\
\\ Formats the input files and modifies them in-place.
@@ -527,7 +527,7 @@ const usage_fmt =
\\
;
-const args_fmt_spec = []Flag{
+pub const args_fmt_spec = []Flag{
Flag.Bool("--help"),
Flag.Bool("--check"),
Flag.Option("--color", []const []const u8{
diff --git a/src/main.cpp b/src/main.cpp
index 73a1d75d42..78446f9e98 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -21,8 +21,8 @@ static int print_error_usage(const char *arg0) {
return EXIT_FAILURE;
}
-static int print_full_usage(const char *arg0) {
- fprintf(stdout,
+static int print_full_usage(const char *arg0, FILE *file, int return_code) {
+ fprintf(file,
"Usage: %s [command] [options]\n"
"\n"
"Commands:\n"
@@ -31,6 +31,7 @@ static int print_full_usage(const char *arg0) {
" build-lib [source] create library from source or object files\n"
" build-obj [source] create object from source or assembly\n"
" builtin show the source code of that @import(\"builtin\")\n"
+ " fmt parse files and render in canonical zig format\n"
" help show this usage information\n"
" id print the base64-encoded compiler id\n"
" init-exe initialize a `zig build` application in the cwd\n"
@@ -106,7 +107,7 @@ static int print_full_usage(const char *arg0) {
" --test-cmd [arg] specify test execution command one arg at a time\n"
" --test-cmd-bin appends test binary path to test cmd args\n"
, arg0);
- return EXIT_SUCCESS;
+ return return_code;
}
static const char *ZIG_ZEN = "\n"
@@ -515,6 +516,31 @@ int main(int argc, char **argv) {
fprintf(stderr, "\n");
}
return (term.how == TerminationIdClean) ? term.code : -1;
+ } else if (argc >= 2 && strcmp(argv[1], "fmt") == 0) {
+ init_all_targets();
+ Buf *fmt_runner_path = buf_alloc();
+ os_path_join(get_zig_special_dir(), buf_create_from_str("fmt_runner.zig"), fmt_runner_path);
+ CodeGen *g = codegen_create(fmt_runner_path, nullptr, OutTypeExe, BuildModeDebug, get_zig_lib_dir(),
+ nullptr);
+ g->is_single_threaded = true;
+ codegen_set_out_name(g, buf_create_from_str("fmt"));
+ g->enable_cache = true;
+
+ codegen_build_and_link(g);
+
+ ZigList args = {0};
+ for (int i = 2; i < argc; i += 1) {
+ args.append(argv[i]);
+ }
+ args.append(nullptr);
+ const char *exec_path = buf_ptr(&g->output_file_path);
+
+ os_execv(exec_path, args.items);
+
+ args.pop();
+ Termination term;
+ os_spawn_process(exec_path, args, &term);
+ return term.code;
}
for (int i = 1; i < argc; i += 1) {
@@ -527,6 +553,8 @@ int main(int argc, char **argv) {
build_mode = BuildModeSafeRelease;
} else if (strcmp(arg, "--release-small") == 0) {
build_mode = BuildModeSmallRelease;
+ } else if (strcmp(arg, "--help") == 0) {
+ return print_full_usage(arg0, stderr, EXIT_FAILURE);
} else if (strcmp(arg, "--strip") == 0) {
strip = true;
} else if (strcmp(arg, "--static") == 0) {
@@ -1080,7 +1108,7 @@ int main(int argc, char **argv) {
}
}
case CmdHelp:
- return print_full_usage(arg0);
+ return print_full_usage(arg0, stdout, EXIT_SUCCESS);
case CmdVersion:
printf("%s\n", ZIG_VERSION_STRING);
return EXIT_SUCCESS;
diff --git a/std/special/fmt_runner.zig b/std/special/fmt_runner.zig
new file mode 100644
index 0000000000..b6b728f5cf
--- /dev/null
+++ b/std/special/fmt_runner.zig
@@ -0,0 +1,265 @@
+const std = @import("std");
+const builtin = @import("builtin");
+
+const os = std.os;
+const io = std.io;
+const mem = std.mem;
+const Allocator = mem.Allocator;
+const ArrayList = std.ArrayList;
+const Buffer = std.Buffer;
+const ast = std.zig.ast;
+
+const arg = @import("fmt/arg.zig");
+const self_hosted_main = @import("fmt/main.zig");
+const Args = arg.Args;
+const Flag = arg.Flag;
+const errmsg = @import("fmt/errmsg.zig");
+
+var stderr_file: os.File = undefined;
+var stderr: *io.OutStream(os.File.WriteError) = undefined;
+var stdout: *io.OutStream(os.File.WriteError) = undefined;
+
+// This brings `zig fmt` to stage 1.
+pub fn main() !void {
+ // Here we use an ArenaAllocator backed by a DirectAllocator because `zig fmt` is a short-lived,
+ // one shot program. We don't need to waste time freeing memory and finding places to squish
+ // bytes into. So we free everything all at once at the very end.
+ var direct_allocator = std.heap.DirectAllocator.init();
+ var arena = std.heap.ArenaAllocator.init(&direct_allocator.allocator);
+ const allocator = &arena.allocator;
+
+ var stdout_file = try std.io.getStdOut();
+ var stdout_out_stream = stdout_file.outStream();
+ stdout = &stdout_out_stream.stream;
+
+ stderr_file = try std.io.getStdErr();
+ var stderr_out_stream = stderr_file.outStream();
+ stderr = &stderr_out_stream.stream;
+ const args = try std.os.argsAlloc(allocator);
+
+ var flags = try Args.parse(allocator, self_hosted_main.args_fmt_spec, args);
+ defer flags.deinit();
+
+ if (flags.present("help")) {
+ try stdout.write(self_hosted_main.usage_fmt);
+ os.exit(0);
+ }
+
+ const color = blk: {
+ if (flags.single("color")) |color_flag| {
+ if (mem.eql(u8, color_flag, "auto")) {
+ break :blk errmsg.Color.Auto;
+ } else if (mem.eql(u8, color_flag, "on")) {
+ break :blk errmsg.Color.On;
+ } else if (mem.eql(u8, color_flag, "off")) {
+ break :blk errmsg.Color.Off;
+ } else unreachable;
+ } else {
+ break :blk errmsg.Color.Auto;
+ }
+ };
+
+ if (flags.present("stdin")) {
+ if (flags.positionals.len != 0) {
+ try stderr.write("cannot use --stdin with positional arguments\n");
+ os.exit(1);
+ }
+
+ var stdin_file = try io.getStdIn();
+ var stdin = stdin_file.inStream();
+
+ const source_code = try stdin.stream.readAllAlloc(allocator, self_hosted_main.max_src_size);
+ defer allocator.free(source_code);
+
+ var tree = std.zig.parse(allocator, source_code) catch |err| {
+ try stderr.print("error parsing stdin: {}\n", err);
+ os.exit(1);
+ };
+ defer tree.deinit();
+
+ var error_it = tree.errors.iterator(0);
+ while (error_it.next()) |parse_error| {
+ try printErrMsgToFile(allocator, parse_error, &tree, "", stderr_file, color);
+ }
+ if (tree.errors.len != 0) {
+ os.exit(1);
+ }
+ if (flags.present("check")) {
+ const anything_changed = try std.zig.render(allocator, io.null_out_stream, &tree);
+ const code = if (anything_changed) u8(1) else u8(0);
+ os.exit(code);
+ }
+
+ _ = try std.zig.render(allocator, stdout, &tree);
+ return;
+ }
+
+ if (flags.positionals.len == 0) {
+ try stderr.write("expected at least one source file argument\n");
+ os.exit(1);
+ }
+
+ if (flags.positionals.len == 0) {
+ try stderr.write("expected at least one source file argument\n");
+ os.exit(1);
+ }
+
+ var fmt = Fmt{
+ .seen = Fmt.SeenMap.init(allocator),
+ .any_error = false,
+ .color = color,
+ .allocator = allocator,
+ };
+
+ const check_mode = flags.present("check");
+
+ for (flags.positionals.toSliceConst()) |file_path| {
+ try fmtPath(&fmt, file_path, check_mode);
+ }
+ if (fmt.any_error) {
+ os.exit(1);
+ }
+}
+
+const FmtError = error{
+ SystemResources,
+ OperationAborted,
+ IoPending,
+ BrokenPipe,
+ Unexpected,
+ WouldBlock,
+ FileClosed,
+ DestinationAddressRequired,
+ DiskQuota,
+ FileTooBig,
+ InputOutput,
+ NoSpaceLeft,
+ AccessDenied,
+ OutOfMemory,
+ RenameAcrossMountPoints,
+ ReadOnlyFileSystem,
+ LinkQuotaExceeded,
+ FileBusy,
+} || os.File.OpenError;
+
+fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtError!void {
+ const file_path = try std.mem.dupe(fmt.allocator, u8, file_path_ref);
+ defer fmt.allocator.free(file_path);
+
+ if (try fmt.seen.put(file_path, {})) |_| return;
+
+ const source_code = io.readFileAlloc(fmt.allocator, file_path) catch |err| switch (err) {
+ error.IsDir, error.AccessDenied => {
+ // TODO make event based (and dir.next())
+ var dir = try std.os.Dir.open(fmt.allocator, file_path);
+ defer dir.close();
+
+ while (try dir.next()) |entry| {
+ if (entry.kind == std.os.Dir.Entry.Kind.Directory or mem.endsWith(u8, entry.name, ".zig")) {
+ const full_path = try os.path.join(fmt.allocator, [][]const u8{ file_path, entry.name });
+ try fmtPath(fmt, full_path, check_mode);
+ }
+ }
+ return;
+ },
+ else => {
+ // TODO lock stderr printing
+ try stderr.print("unable to open '{}': {}\n", file_path, err);
+ fmt.any_error = true;
+ return;
+ },
+ };
+ defer fmt.allocator.free(source_code);
+
+ var tree = std.zig.parse(fmt.allocator, source_code) catch |err| {
+ try stderr.print("error parsing file '{}': {}\n", file_path, err);
+ fmt.any_error = true;
+ return;
+ };
+ defer tree.deinit();
+
+ var error_it = tree.errors.iterator(0);
+ while (error_it.next()) |parse_error| {
+ try printErrMsgToFile(fmt.allocator, parse_error, &tree, file_path, stderr_file, fmt.color);
+ }
+ if (tree.errors.len != 0) {
+ fmt.any_error = true;
+ return;
+ }
+
+ if (check_mode) {
+ const anything_changed = try std.zig.render(fmt.allocator, io.null_out_stream, &tree);
+ if (anything_changed) {
+ try stderr.print("{}\n", file_path);
+ fmt.any_error = true;
+ }
+ } else {
+ // TODO make this evented
+ const baf = try io.BufferedAtomicFile.create(fmt.allocator, file_path);
+ defer baf.destroy();
+
+ const anything_changed = try std.zig.render(fmt.allocator, baf.stream(), &tree);
+ if (anything_changed) {
+ try stderr.print("{}\n", file_path);
+ try baf.finish();
+ }
+ }
+}
+
+const Fmt = struct {
+ seen: SeenMap,
+ any_error: bool,
+ color: errmsg.Color,
+ allocator: *mem.Allocator,
+
+ const SeenMap = std.HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8);
+};
+
+fn printErrMsgToFile(allocator: *mem.Allocator, parse_error: *const ast.Error, tree: *ast.Tree,
+ path: []const u8, file: os.File, color: errmsg.Color,) !void
+{
+ const color_on = switch (color) {
+ errmsg.Color.Auto => file.isTty(),
+ errmsg.Color.On => true,
+ errmsg.Color.Off => false,
+ };
+ const lok_token = parse_error.loc();
+ const span = errmsg.Span{
+ .first = lok_token,
+ .last = lok_token,
+ };
+
+ const first_token = tree.tokens.at(span.first);
+ const last_token = tree.tokens.at(span.last);
+ const start_loc = tree.tokenLocationPtr(0, first_token);
+ const end_loc = tree.tokenLocationPtr(first_token.end, last_token);
+
+ var text_buf = try std.Buffer.initSize(allocator, 0);
+ var out_stream = &std.io.BufferOutStream.init(&text_buf).stream;
+ try parse_error.render(&tree.tokens, out_stream);
+ const text = text_buf.toOwnedSlice();
+
+ const stream = &file.outStream().stream;
+ if (!color_on) {
+ try stream.print(
+ "{}:{}:{}: error: {}\n",
+ path,
+ start_loc.line + 1,
+ start_loc.column + 1,
+ text,
+ );
+ return;
+ }
+
+ try stream.print(
+ "{}:{}:{}: error: {}\n{}\n",
+ path,
+ start_loc.line + 1,
+ start_loc.column + 1,
+ text,
+ tree.source[start_loc.line_start..start_loc.line_end],
+ );
+ try stream.writeByteNTimes(' ', start_loc.column);
+ try stream.writeByteNTimes('~', last_token.end - first_token.start);
+ try stream.write("\n");
+}
--
cgit v1.2.3