authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-05-10 23:38:44-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-05-10 23:38:44-04:00
logf5edf78eea403c14635a05e1729672cfb50aca89
tree1661a15b3ee4427ce6a4286f4c972be49e9f572c
parent458943e324e81762a9a2aa839d2fa3c851068e6f
parent45415093c655d30ec226172695248fbf28941667
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #10143 from nuald/single-threaded-cpp1

Normalized C++ compilation options for single-threaded targets

5 files changed, 106 insertions(+), 32 deletions(-)

src/Compilation.zig+13
...@@ -1180,6 +1180,15 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1180,6 +1180,15 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1180 if (must_single_thread and !single_threaded) {1180 if (must_single_thread and !single_threaded) {
1181 return error.TargetRequiresSingleThreaded;1181 return error.TargetRequiresSingleThreaded;
1182 }1182 }
1183 if (!single_threaded and options.link_libcpp) {
1184 if (options.target.cpu.arch.isARM()) {
1185 log.warn(
1186 \\libc++ does not work on multi-threaded ARM yet.
1187 \\For more details: https://github.com/ziglang/zig/issues/6573
1188 , .{});
1189 return error.TargetRequiresSingleThreaded;
1190 }
1191 }
11831192
1184 const llvm_cpu_features: ?[*:0]const u8 = if (build_options.have_llvm and use_llvm) blk: {1193 const llvm_cpu_features: ?[*:0]const u8 = if (build_options.have_llvm and use_llvm) blk: {
1185 var buf = std.ArrayList(u8).init(arena);1194 var buf = std.ArrayList(u8).init(arena);
...@@ -3803,6 +3812,10 @@ pub fn addCCArgs(...@@ -3803,6 +3812,10 @@ pub fn addCCArgs(
3803 try argv.append("-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS");3812 try argv.append("-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS");
3804 try argv.append("-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS");3813 try argv.append("-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS");
3805 try argv.append("-D_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS");3814 try argv.append("-D_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS");
3815
3816 if (comp.bin_file.options.single_threaded) {
3817 try argv.append("-D_LIBCPP_HAS_NO_THREADS");
3818 }
3806 }3819 }
38073820
3808 if (comp.bin_file.options.link_libunwind) {3821 if (comp.bin_file.options.link_libunwind) {
src/libcxx.zig+18-6
...@@ -128,6 +128,12 @@ pub fn buildLibCXX(comp: *Compilation) !void {...@@ -128,6 +128,12 @@ pub fn buildLibCXX(comp: *Compilation) !void {
128 continue;128 continue;
129 if (std.mem.startsWith(u8, cxx_src, "src/support/ibm/") and target.os.tag != .zos)129 if (std.mem.startsWith(u8, cxx_src, "src/support/ibm/") and target.os.tag != .zos)
130 continue;130 continue;
131 if (comp.bin_file.options.single_threaded) {
132 if (std.mem.startsWith(u8, cxx_src, "src/support/win32/thread_win32.cpp")) {
133 continue;
134 }
135 try cflags.append("-D_LIBCPP_HAS_NO_THREADS");
136 }
131137
132 try cflags.append("-DNDEBUG");138 try cflags.append("-DNDEBUG");
133 try cflags.append("-D_LIBCPP_BUILDING_LIBRARY");139 try cflags.append("-D_LIBCPP_BUILDING_LIBRARY");
...@@ -145,8 +151,7 @@ pub fn buildLibCXX(comp: *Compilation) !void {...@@ -145,8 +151,7 @@ pub fn buildLibCXX(comp: *Compilation) !void {
145 }151 }
146152
147 if (target.os.tag == .wasi) {153 if (target.os.tag == .wasi) {
148 // WASI doesn't support thread and exception yet.154 // WASI doesn't support exceptions yet.
149 try cflags.append("-D_LIBCPP_HAS_NO_THREADS");
150 try cflags.append("-fno-exceptions");155 try cflags.append("-fno-exceptions");
151 }156 }
152157
...@@ -264,13 +269,20 @@ pub fn buildLibCXXABI(comp: *Compilation) !void {...@@ -264,13 +269,20 @@ pub fn buildLibCXXABI(comp: *Compilation) !void {
264 var cflags = std.ArrayList([]const u8).init(arena);269 var cflags = std.ArrayList([]const u8).init(arena);
265270
266 if (target.os.tag == .wasi) {271 if (target.os.tag == .wasi) {
267 // WASI doesn't support thread and exception yet.272 // WASI doesn't support exceptions yet.
268 if (std.mem.startsWith(u8, cxxabi_src, "src/cxa_thread_atexit.cpp") or273 if (std.mem.startsWith(u8, cxxabi_src, "src/cxa_exception.cpp") or
269 std.mem.startsWith(u8, cxxabi_src, "src/cxa_exception.cpp") or
270 std.mem.startsWith(u8, cxxabi_src, "src/cxa_personality.cpp"))274 std.mem.startsWith(u8, cxxabi_src, "src/cxa_personality.cpp"))
271 continue;275 continue;
272 try cflags.append("-D_LIBCXXABI_HAS_NO_THREADS");
273 try cflags.append("-fno-exceptions");276 try cflags.append("-fno-exceptions");
277 }
278
279 // WASM targets are single threaded.
280 if (comp.bin_file.options.single_threaded) {
281 if (std.mem.startsWith(u8, cxxabi_src, "src/cxa_thread_atexit.cpp")) {
282 continue;
283 }
284 try cflags.append("-D_LIBCXXABI_HAS_NO_THREADS");
285 try cflags.append("-D_LIBCPP_HAS_NO_THREADS");
274 } else {286 } else {
275 try cflags.append("-DHAVE___CXA_THREAD_ATEXIT_IMPL");287 try cflags.append("-DHAVE___CXA_THREAD_ATEXIT_IMPL");
276 }288 }
test/standalone/c_compiler/build.zig+1-1
...@@ -29,7 +29,7 @@ pub fn build(b: *Builder) void {...@@ -29,7 +29,7 @@ pub fn build(b: *Builder) void {
29 exe_cpp.addCSourceFile("test.cpp", &[0][]const u8{});29 exe_cpp.addCSourceFile("test.cpp", &[0][]const u8{});
30 exe_cpp.setBuildMode(mode);30 exe_cpp.setBuildMode(mode);
31 exe_cpp.setTarget(target);31 exe_cpp.setTarget(target);
32 exe_cpp.linkSystemLibrary("c++");32 exe_cpp.linkLibCpp();
3333
34 switch (target.getOsTag()) {34 switch (target.getOsTag()) {
35 .windows => {35 .windows => {
test/standalone/c_compiler/test.c+13-10
...@@ -1,25 +1,28 @@...@@ -1,25 +1,28 @@
1#include <assert.h>1#include <assert.h>
2#include <stdio.h>2#include <stdio.h>
3#include <stdlib.h>
34
4typedef struct {5typedef struct {
5 int val;6 int val;
6} STest;7} STest;
78
8int getVal(STest* data) { return data->val; }9int getVal(STest* data) { return data->val; }
910
10int main (int argc, char *argv[])11int main (int argc, char *argv[])
11{12{
12 STest* data = (STest*)malloc(sizeof(STest));13 STest* data = (STest*)malloc(sizeof(STest));
13 data->val = 123;14 data->val = 123;
1415
15 assert(getVal(data) != 456);16 assert(getVal(data) != 456);
16 int ok = (getVal(data) == 123);17 int ok = (getVal(data) == 123);
1718
18 if (argc>1) fprintf(stdout, "val=%d\n", data->val);19 if (argc > 1) {
20 fprintf(stdout, "val=%d\n", data->val);
21 }
1922
20 free(data);23 free(data);
2124
22 if (!ok) abort();25 if (!ok) abort();
2326
24 return 0;27 return EXIT_SUCCESS;
25}28}
test/standalone/c_compiler/test.cpp+61-15
...@@ -1,33 +1,79 @@...@@ -1,33 +1,79 @@
1#include <iostream>
2#include <cassert>1#include <cassert>
2#include <iostream>
3
4#ifndef _LIBCPP_HAS_NO_THREADS
5#include <future>
6#endif
7
8thread_local unsigned int tls_counter = 1;
9
10// a non-optimized way of checking for prime numbers:
11bool is_prime(int x) {
12 for (int i = 2; i <x ; ++i) {
13 if (x % i == 0) {
14 return false;
15 }
16 }
17 return true;
18}
319
4class CTest {20class CTest {
5public:21public:
6 CTest(int val) : m_val(val) {};22 CTest(int val) : m_val(val) {
7 virtual ~CTest() {}23 tls_counter++;
24 };
25 virtual ~CTest() {}
826
9 virtual int getVal() const { return m_val; }27 virtual int getVal() const { return m_val; }
10 virtual void printVal() { std::cout << "val=" << m_val << std::endl; }28 virtual void printVal() { std::cout << "val=" << m_val << std::endl; }
11private:29private:
12 int m_val;30 int m_val;
31};
32
33class GlobalConstructorTest {
34public:
35 GlobalConstructorTest(int val) : m_val(val) {};
36 virtual ~GlobalConstructorTest() {}
37
38 virtual int getVal() const { return m_val; }
39 virtual void printVal() { std::cout << "val=" << m_val << std::endl; }
40private:
41 int m_val;
13};42};
1443
1544
16volatile int runtime_val = 456;45volatile int runtime_val = 456;
17CTest global(runtime_val); // test if global initializers are called.46GlobalConstructorTest global(runtime_val); // test if global initializers are called.
1847
19int main (int argc, char *argv[])48int main (int argc, char *argv[])
20{49{
21 assert(global.getVal() == 456);50 assert(global.getVal() == 456);
51
52 auto t = std::make_unique<CTest>(123);
53 assert(t->getVal() != 456);
54 assert(tls_counter == 2);
55 if (argc > 1) {
56 t->printVal();
57 }
58 bool ok = t->getVal() == 123;
2259
23 auto* t = new CTest(123);60 if (!ok) abort();
24 assert(t->getVal()!=456);
2561
26 if (argc>1) t->printVal();62#ifndef _LIBCPP_HAS_NO_THREADS
27 bool ok = t->getVal() == 123;63 std::future<bool> fut = std::async(is_prime, 313);
28 delete t;64 bool ret = fut.get();
65 assert(ret);
66#endif
2967
30 if (!ok) abort();68#if !defined(__wasm__) && !defined(__APPLE__)
69 // WASM and macOS are not passing this yet.
70 // TODO file an issue for this and link it here.
71 try {
72 throw 20;
73 } catch (int e) {
74 assert(e == 20);
75 }
76#endif
3177
32 return 0;78 return EXIT_SUCCESS;
33}79}