| ... | @@ -18,7 +18,8 @@ pub fn build(b: *Build) void { | ... | @@ -18,7 +18,8 @@ pub fn build(b: *Build) void { |
| 18 | // Exercise linker with LLVM backend | 18 | // Exercise linker with LLVM backend |
| 19 | elf_step.dependOn(testEmptyObject(b, .{ .target = musl_target })); | 19 | elf_step.dependOn(testEmptyObject(b, .{ .target = musl_target })); |
| 20 | elf_step.dependOn(testLinkingC(b, .{ .target = musl_target })); | 20 | elf_step.dependOn(testLinkingC(b, .{ .target = musl_target })); |
| 21 | elf_step.dependOn(testLinkingZig(b, .{})); | 21 | elf_step.dependOn(testLinkingZig(b, .{ .target = musl_target })); |
| | 22 | elf_step.dependOn(testTlsStatic(b, .{ .target = musl_target })); |
| 22 | } | 23 | } |
| 23 | | 24 | |
| 24 | fn testEmptyObject(b: *Build, opts: Options) *Step { | 25 | fn testEmptyObject(b: *Build, opts: Options) *Step { |
| ... | @@ -91,6 +92,37 @@ fn testLinkingZig(b: *Build, opts: Options) *Step { | ... | @@ -91,6 +92,37 @@ fn testLinkingZig(b: *Build, opts: Options) *Step { |
| 91 | return test_step; | 92 | return test_step; |
| 92 | } | 93 | } |
| 93 | | 94 | |
| | 95 | fn testTlsStatic(b: *Build, opts: Options) *Step { |
| | 96 | const test_step = addTestStep(b, "tls-static", opts); |
| | 97 | |
| | 98 | const exe = addExecutable(b, opts); |
| | 99 | addCSourceBytes(exe, |
| | 100 | \\#include <stdio.h> |
| | 101 | \\_Thread_local int a = 10; |
| | 102 | \\_Thread_local int b; |
| | 103 | \\_Thread_local char c = 'a'; |
| | 104 | \\int main(int argc, char* argv[]) { |
| | 105 | \\ printf("%d %d %c\n", a, b, c); |
| | 106 | \\ a += 1; |
| | 107 | \\ b += 1; |
| | 108 | \\ c += 1; |
| | 109 | \\ printf("%d %d %c\n", a, b, c); |
| | 110 | \\ return 0; |
| | 111 | \\} |
| | 112 | ); |
| | 113 | exe.is_linking_libc = true; |
| | 114 | |
| | 115 | const run = addRunArtifact(exe); |
| | 116 | run.expectStdOutEqual( |
| | 117 | \\10 0 a |
| | 118 | \\11 1 b |
| | 119 | \\ |
| | 120 | ); |
| | 121 | test_step.dependOn(&run.step); |
| | 122 | |
| | 123 | return test_step; |
| | 124 | } |
| | 125 | |
| 94 | const Options = struct { | 126 | const Options = struct { |
| 95 | target: CrossTarget = .{ .cpu_arch = .x86_64, .os_tag = .linux }, | 127 | target: CrossTarget = .{ .cpu_arch = .x86_64, .os_tag = .linux }, |
| 96 | optimize: std.builtin.OptimizeMode = .Debug, | 128 | optimize: std.builtin.OptimizeMode = .Debug, |
| ... | @@ -114,7 +146,6 @@ fn addExecutable(b: *Build, opts: Options) *Compile { | ... | @@ -114,7 +146,6 @@ fn addExecutable(b: *Build, opts: Options) *Compile { |
| 114 | .name = "test", | 146 | .name = "test", |
| 115 | .target = opts.target, | 147 | .target = opts.target, |
| 116 | .optimize = opts.optimize, | 148 | .optimize = opts.optimize, |
| 117 | .single_threaded = true, // TODO temp until we teach linker how to handle TLS | | |
| 118 | .use_llvm = opts.use_llvm, | 149 | .use_llvm = opts.use_llvm, |
| 119 | .use_lld = false, | 150 | .use_lld = false, |
| 120 | }); | 151 | }); |