From 20c36949e1d82e9e8790ca51a0f7713f6e853ff0 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 13 Mar 2019 23:15:34 -0400 Subject: [PATCH] fix target_requires_pic and reloc_mode disable failing thread local variable test. see #2063 --- src/codegen.cpp | 13 ++++++++++--- src/main.cpp | 5 ++++- src/target.cpp | 5 +++-- src/target.hpp | 2 +- std/os/test.zig | 4 ++++ test/stage1/behavior/misc.zig | 5 +++++ 6 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 11a368cda66d..44e66c4dd88f 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -7288,7 +7288,7 @@ static bool detect_dynamic_link(CodeGen *g) { return true; if (g->zig_target->os == OsFreestanding) return false; - if (target_requires_pic(g->zig_target)) + if (target_requires_pic(g->zig_target, g->libc_link_lib != nullptr)) return true; if (g->out_type == OutTypeExe) { // If there are no dynamic libraries then we can disable PIC @@ -7304,7 +7304,7 @@ static bool detect_dynamic_link(CodeGen *g) { } static bool detect_pic(CodeGen *g) { - if (target_requires_pic(g->zig_target)) + if (target_requires_pic(g->zig_target, g->libc_link_lib != nullptr)) return true; switch (g->want_pic) { case WantPICDisabled: @@ -7848,7 +7848,14 @@ static void init(CodeGen *g) { bool is_optimized = g->build_mode != BuildModeDebug; LLVMCodeGenOptLevel opt_level = is_optimized ? LLVMCodeGenLevelAggressive : LLVMCodeGenLevelNone; - LLVMRelocMode reloc_mode = g->have_pic ? LLVMRelocPIC: LLVMRelocStatic; + LLVMRelocMode reloc_mode; + if (g->have_pic) { + reloc_mode = LLVMRelocPIC; + } else if (g->have_dynamic_link) { + reloc_mode = LLVMRelocDynamicNoPic; + } else { + reloc_mode = LLVMRelocStatic; + } const char *target_specific_cpu_args; const char *target_specific_features; diff --git a/src/main.cpp b/src/main.cpp index 81aaaaa3680a..f58a00209a1b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -417,6 +417,7 @@ int main(int argc, char **argv) { ZigList link_libs = {0}; ZigList forbidden_link_libs = {0}; ZigList frameworks = {0}; + bool have_libc = false; const char *target_string = nullptr; bool rdynamic = false; const char *mmacosx_version_min = nullptr; @@ -745,6 +746,8 @@ int main(int argc, char **argv) { } else if (strcmp(arg, "--library-path") == 0 || strcmp(arg, "-L") == 0) { lib_dirs.append(argv[i]); } else if (strcmp(arg, "--library") == 0) { + if (strcmp(argv[i], "c") == 0) + have_libc = true; link_libs.append(argv[i]); } else if (strcmp(arg, "--forbid-library") == 0) { forbidden_link_libs.append(argv[i]); @@ -911,7 +914,7 @@ int main(int argc, char **argv) { return print_error_usage(arg0); } - if (target_requires_pic(&target) && want_pic == WantPICDisabled) { + if (target_requires_pic(&target, have_libc) && want_pic == WantPICDisabled) { Buf triple_buf = BUF_INIT; get_target_triple(&triple_buf, &target); fprintf(stderr, "`--disable-pic` is incompatible with target '%s'\n", buf_ptr(&triple_buf)); diff --git a/src/target.cpp b/src/target.cpp index 22d8dd23577e..7239ea17ba98 100644 --- a/src/target.cpp +++ b/src/target.cpp @@ -1300,9 +1300,10 @@ bool target_supports_fpic(const ZigTarget *target) { return target->os != OsWindows; } -bool target_requires_pic(const ZigTarget *target) { +bool target_requires_pic(const ZigTarget *target, bool linking_libc) { // This function returns whether non-pic code is completely invalid on the given target. - return target->os == OsWindows || target_os_requires_libc(target->os) || target_is_glibc(target); + return target->os == OsWindows || target_os_requires_libc(target->os) || + (linking_libc && target_is_glibc(target)); } bool target_is_glibc(const ZigTarget *target) { diff --git a/src/target.hpp b/src/target.hpp index 072bfc184ce9..d42ebcc57695 100644 --- a/src/target.hpp +++ b/src/target.hpp @@ -161,7 +161,7 @@ bool target_can_build_libc(const ZigTarget *target); const char *target_libc_generic_name(const ZigTarget *target); bool target_is_libc_lib_name(const ZigTarget *target, const char *name); bool target_supports_fpic(const ZigTarget *target); -bool target_requires_pic(const ZigTarget *target); +bool target_requires_pic(const ZigTarget *target, bool linking_libc); bool target_abi_is_gnu(ZigLLVM_EnvironmentType abi); bool target_abi_is_musl(ZigLLVM_EnvironmentType abi); bool target_is_glibc(const ZigTarget *target); diff --git a/std/os/test.zig b/std/os/test.zig index ab21ea1568b0..943960a925d7 100644 --- a/std/os/test.zig +++ b/std/os/test.zig @@ -108,6 +108,10 @@ test "AtomicFile" { test "thread local storage" { if (builtin.single_threaded) return error.SkipZigTest; + if (!builtin.position_independent_code and !builtin.link_libc) { + // TODO https://github.com/ziglang/zig/issues/2063 + return error.SkipZigTest; + } const thread1 = try std.os.spawnThread({}, testTls); const thread2 = try std.os.spawnThread({}, testTls); testTls({}); diff --git a/test/stage1/behavior/misc.zig b/test/stage1/behavior/misc.zig index a2d752457c50..36246162f52d 100644 --- a/test/stage1/behavior/misc.zig +++ b/test/stage1/behavior/misc.zig @@ -688,6 +688,11 @@ fn getNull() ?*i32 { } test "thread local variable" { + if (!builtin.position_independent_code and !builtin.link_libc) { + // TODO https://github.com/ziglang/zig/issues/2063 + return error.SkipZigTest; + } + const S = struct { threadlocal var t: i32 = 1234; };