From eb0979189be33d6d957dad5104650cb5c532055b Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 31 Aug 2017 11:41:58 -0400 Subject: [PATCH] add windows to test targets cross-compiling hello world with no libc for windows is working --- src/link.cpp | 10 +--- src/main.cpp | 77 +++++++++++++++++-------------- src/target.cpp | 8 ++++ src/target.hpp | 1 + std/special/builtin.zig | 4 +- std/special/compiler_rt/index.zig | 33 +++++++++++++ test/tests.zig | 5 ++ 7 files changed, 92 insertions(+), 46 deletions(-) diff --git a/src/link.cpp b/src/link.cpp index 63f06af2cc..dae68c2814 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -78,14 +78,6 @@ static Buf *build_compiler_rt(CodeGen *parent_gen) { return build_o_raw(parent_gen, "compiler_rt", full_path); } -static const char *get_exe_file_extension(CodeGen *g) { - if (g->zig_target.os == ZigLLVM_Win32) { - return ".exe"; - } else { - return ""; - } -} - static const char *get_darwin_arch_string(const ZigTarget *t) { switch (t->arch.arch) { case ZigLLVM_aarch64: @@ -835,7 +827,7 @@ void codegen_link(CodeGen *g, const char *out_file) { buf_init_from_buf(&lj.out_file, g->root_out_name); if (g->out_type == OutTypeExe) { - buf_append_str(&lj.out_file, get_exe_file_extension(g)); + buf_append_str(&lj.out_file, target_exe_file_ext(&g->zig_target)); } } diff --git a/src/main.cpp b/src/main.cpp index d3a0c800a7..a31c15b868 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -509,6 +509,36 @@ int main(int argc, char **argv) { return EXIT_FAILURE; } + init_all_targets(); + + ZigTarget alloc_target; + ZigTarget *target; + if (!target_arch && !target_os && !target_environ) { + target = nullptr; + } else { + target = &alloc_target; + get_unknown_target(target); + if (target_arch) { + if (parse_target_arch(target_arch, &target->arch)) { + fprintf(stderr, "invalid --target-arch argument\n"); + return usage(arg0); + } + } + if (target_os) { + if (parse_target_os(target_os, &target->os)) { + fprintf(stderr, "invalid --target-os argument\n"); + return usage(arg0); + } + } + if (target_environ) { + if (parse_target_environ(target_environ, &target->env_type)) { + fprintf(stderr, "invalid --target-environ argument\n"); + return usage(arg0); + } + } + } + + switch (cmd) { case CmdBuild: case CmdParseH: @@ -527,35 +557,6 @@ int main(int argc, char **argv) { assert(cmd != CmdBuild || out_type != OutTypeUnknown); - init_all_targets(); - - ZigTarget alloc_target; - ZigTarget *target; - if (!target_arch && !target_os && !target_environ) { - target = nullptr; - } else { - target = &alloc_target; - get_unknown_target(target); - if (target_arch) { - if (parse_target_arch(target_arch, &target->arch)) { - fprintf(stderr, "invalid --target-arch argument\n"); - return usage(arg0); - } - } - if (target_os) { - if (parse_target_os(target_os, &target->os)) { - fprintf(stderr, "invalid --target-os argument\n"); - return usage(arg0); - } - } - if (target_environ) { - if (parse_target_environ(target_environ, &target->env_type)) { - fprintf(stderr, "invalid --target-environ argument\n"); - return usage(arg0); - } - } - } - bool need_name = (cmd == CmdBuild || cmd == CmdParseH); Buf *in_file_buf = nullptr; @@ -674,24 +675,30 @@ int main(int argc, char **argv) { codegen_print_timing_report(g, stdout); return EXIT_SUCCESS; } else if (cmd == CmdTest) { - codegen_build(g); - codegen_link(g, "./test"); - ZigTarget native; get_native_target(&native); + + ZigTarget *non_null_target = target ? target : &native; + + Buf *test_exe_name = buf_sprintf("./test%s", target_exe_file_ext(non_null_target)); + + codegen_build(g); + codegen_link(g, buf_ptr(test_exe_name)); + bool is_native_target = target == nullptr || (target->os == native.os && target->arch.arch == native.arch.arch && target->arch.sub_arch == native.arch.sub_arch); if (!is_native_target) { - fprintf(stderr, "Skipping execution of non-native test binary.\n"); + fprintf(stderr, "Created %s but skipping execution because it is non-native.\n", + buf_ptr(test_exe_name)); return 0; } ZigList args = {0}; Termination term; - os_spawn_process("./test", args, &term); + os_spawn_process(buf_ptr(test_exe_name), args, &term); if (term.how != TerminationIdClean || term.code != 0) { fprintf(stderr, "\nTests failed. Use the following command to reproduce the failure:\n"); - fprintf(stderr, "./test\n"); + fprintf(stderr, "%s\n", buf_ptr(test_exe_name)); } else if (timing_info) { codegen_print_timing_report(g, stdout); } diff --git a/src/target.cpp b/src/target.cpp index e3dad05cf6..8a58a42b59 100644 --- a/src/target.cpp +++ b/src/target.cpp @@ -555,6 +555,14 @@ const char *target_o_file_ext(ZigTarget *target) { } } +const char *target_exe_file_ext(ZigTarget *target) { + if (target->os == ZigLLVM_Win32) { + return ".exe"; + } else { + return ""; + } +} + enum FloatAbi { FloatAbiHard, FloatAbiSoft, diff --git a/src/target.hpp b/src/target.hpp index 07b1165944..dbacd6a2c7 100644 --- a/src/target.hpp +++ b/src/target.hpp @@ -73,6 +73,7 @@ void resolve_target_object_format(ZigTarget *target); uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id); const char *target_o_file_ext(ZigTarget *target); +const char *target_exe_file_ext(ZigTarget *target); Buf *target_dynamic_linker(ZigTarget *target); diff --git a/std/special/builtin.zig b/std/special/builtin.zig index d92bac7c60..17839a51d5 100644 --- a/std/special/builtin.zig +++ b/std/special/builtin.zig @@ -22,8 +22,8 @@ export fn memcpy(noalias dest: ?&u8, noalias src: ?&const u8, n: usize) { (??dest)[index] = (??src)[index]; } -export fn __stack_chk_fail() { - if (builtin.mode == builtin.Mode.ReleaseFast) { +export fn __stack_chk_fail() -> noreturn { + if (builtin.mode == builtin.Mode.ReleaseFast or builtin.os == builtin.Os.windows) { @setGlobalLinkage(__stack_chk_fail, builtin.GlobalLinkage.Internal); unreachable; } diff --git a/std/special/compiler_rt/index.zig b/std/special/compiler_rt/index.zig index 54da5148e7..7f80fd1e7c 100644 --- a/std/special/compiler_rt/index.zig +++ b/std/special/compiler_rt/index.zig @@ -98,6 +98,38 @@ export nakedcc fn __aeabi_uidivmod() { @setGlobalLinkage(__aeabi_uidivmod, builtin.GlobalLinkage.Internal); } +export nakedcc fn __chkstk() { + @setDebugSafety(this, false); + + if (comptime builtin.arch == builtin.Arch.x86_64) { + asm volatile ( + \\ push %%rcx + \\ cmp $0x1000,%%rax + \\ lea 16(%%rsp),%%rcx // rsp before calling this routine -> rcx + \\ jb 1f + \\ 2: + \\ sub $0x1000,%%rcx + \\ test %%rcx,(%%rcx) + \\ sub $0x1000,%%rax + \\ cmp $0x1000,%%rax + \\ ja 2b + \\ 1: + \\ sub %%rax,%%rcx + \\ test %%rcx,(%%rcx) + \\ + \\ lea 8(%%rsp),%%rax // load pointer to the return address into rax + \\ mov %%rcx,%%rsp // install the new top of stack pointer into rsp + \\ mov -8(%%rax),%%rcx // restore rcx + \\ push (%%rax) // push return address onto the stack + \\ sub %%rsp,%%rax // restore the original value in rax + \\ ret + ); + unreachable; + } + + @setGlobalLinkage(__chkstk, builtin.GlobalLinkage.Internal); +} + export fn __udivmodsi4(a: u32, b: u32, rem: &u32) -> u32 { @setDebugSafety(this, is_test); @setGlobalLinkage(__udivmodsi4, builtin.GlobalLinkage.LinkOnce); @@ -316,3 +348,4 @@ fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) { const q: u32 = __udivsi3(a, b); assert(q == expected_q); } + diff --git a/test/tests.zig b/test/tests.zig index 88577f9bb0..6e9ad014b1 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -36,6 +36,11 @@ const test_targets = []TestTarget { .arch = builtin.Arch.x86_64, .environ = builtin.Environ.unknown, }, + TestTarget { + .os = builtin.Os.windows, + .arch = builtin.Arch.x86_64, + .environ = builtin.Environ.msvc, + }, }; error TestFailed;