authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-11 00:50:17-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2018-07-11 00:50:17-04:00
logc620a1fe3d40d25d6b6654a4c828e8d7d7e37c38
tree4cab564fe918fcc167bfcd52c3a619607f0fc364
parent8fba0a6ae862993afa2aeca774347adc399b3605
parent8197a14ceb2938c64526c7b84e2ac8da343960fa
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #1215 from ziglang/self-hosted-first-test

self-hosted: first passing test

11 files changed, 420 insertions(+), 107 deletions(-)

CMakeLists.txt+1
......@@ -431,6 +431,7 @@ set(ZIG_CPP_SOURCES
431431set(ZIG_STD_FILES
432432 "array_list.zig"
433433 "atomic/index.zig"
434 "atomic/int.zig"
434435 "atomic/queue_mpmc.zig"
435436 "atomic/queue_mpsc.zig"
436437 "atomic/stack.zig"
build.zig+89-63
......@@ -35,70 +35,27 @@ pub fn build(b: *Builder) !void {
3535 "BUILD_INFO",
3636 });
3737 var index: usize = 0;
38 const cmake_binary_dir = nextValue(&index, build_info);
39 const cxx_compiler = nextValue(&index, build_info);
40 const llvm_config_exe = nextValue(&index, build_info);
41 const lld_include_dir = nextValue(&index, build_info);
42 const lld_libraries = nextValue(&index, build_info);
43 const std_files = nextValue(&index, build_info);
44 const c_header_files = nextValue(&index, build_info);
45 const dia_guids_lib = nextValue(&index, build_info);
38 var ctx = Context{
39 .cmake_binary_dir = nextValue(&index, build_info),
40 .cxx_compiler = nextValue(&index, build_info),
41 .llvm_config_exe = nextValue(&index, build_info),
42 .lld_include_dir = nextValue(&index, build_info),
43 .lld_libraries = nextValue(&index, build_info),
44 .std_files = nextValue(&index, build_info),
45 .c_header_files = nextValue(&index, build_info),
46 .dia_guids_lib = nextValue(&index, build_info),
47 .llvm = undefined,
48 };
49 ctx.llvm = try findLLVM(b, ctx.llvm_config_exe);
4650
47 const llvm = findLLVM(b, llvm_config_exe) catch unreachable;
51 var test_stage2 = b.addTest("src-self-hosted/test.zig");
52 test_stage2.setBuildMode(builtin.Mode.Debug);
4853
4954 var exe = b.addExecutable("zig", "src-self-hosted/main.zig");
5055 exe.setBuildMode(mode);
5156
52 // This is for finding /lib/libz.a on alpine linux.
53 // TODO turn this into -Dextra-lib-path=/lib option
54 exe.addLibPath("/lib");
55
56 exe.addIncludeDir("src");
57 exe.addIncludeDir(cmake_binary_dir);
58 addCppLib(b, exe, cmake_binary_dir, "zig_cpp");
59 if (lld_include_dir.len != 0) {
60 exe.addIncludeDir(lld_include_dir);
61 var it = mem.split(lld_libraries, ";");
62 while (it.next()) |lib| {
63 exe.addObjectFile(lib);
64 }
65 } else {
66 addCppLib(b, exe, cmake_binary_dir, "embedded_lld_wasm");
67 addCppLib(b, exe, cmake_binary_dir, "embedded_lld_elf");
68 addCppLib(b, exe, cmake_binary_dir, "embedded_lld_coff");
69 addCppLib(b, exe, cmake_binary_dir, "embedded_lld_lib");
70 }
71 dependOnLib(exe, llvm);
72
73 if (exe.target.getOs() == builtin.Os.linux) {
74 const libstdcxx_path_padded = try b.exec([][]const u8{
75 cxx_compiler,
76 "-print-file-name=libstdc++.a",
77 });
78 const libstdcxx_path = mem.split(libstdcxx_path_padded, "\r\n").next().?;
79 if (mem.eql(u8, libstdcxx_path, "libstdc++.a")) {
80 warn(
81 \\Unable to determine path to libstdc++.a
82 \\On Fedora, install libstdc++-static and try again.
83 \\
84 );
85 return error.RequiredLibraryNotFound;
86 }
87 exe.addObjectFile(libstdcxx_path);
88
89 exe.linkSystemLibrary("pthread");
90 } else if (exe.target.isDarwin()) {
91 exe.linkSystemLibrary("c++");
92 }
93
94 if (dia_guids_lib.len != 0) {
95 exe.addObjectFile(dia_guids_lib);
96 }
97
98 if (exe.target.getOs() != builtin.Os.windows) {
99 exe.linkSystemLibrary("xml2");
100 }
101 exe.linkSystemLibrary("c");
57 try configureStage2(b, test_stage2, ctx);
58 try configureStage2(b, exe, ctx);
10259
10360 b.default_step.dependOn(&exe.step);
10461
......@@ -110,12 +67,16 @@ pub fn build(b: *Builder) !void {
11067 exe.setVerboseLink(verbose_link_exe);
11168
11269 b.installArtifact(exe);
113 installStdLib(b, std_files);
114 installCHeaders(b, c_header_files);
70 installStdLib(b, ctx.std_files);
71 installCHeaders(b, ctx.c_header_files);
11572
11673 const test_filter = b.option([]const u8, "test-filter", "Skip tests that do not match filter");
11774 const with_lldb = b.option(bool, "with-lldb", "Run tests in LLDB to get a backtrace if one fails") orelse false;
11875
76 const test_stage2_step = b.step("test-stage2", "Run the stage2 compiler tests");
77 test_stage2_step.dependOn(&test_stage2.step);
78 test_step.dependOn(test_stage2_step);
79
11980 test_step.dependOn(docs_step);
12081
12182 test_step.dependOn(tests.addPkgTests(b, test_filter, "test/behavior.zig", "behavior", "Run the behavior tests", with_lldb));
......@@ -133,7 +94,7 @@ pub fn build(b: *Builder) !void {
13394 test_step.dependOn(tests.addGenHTests(b, test_filter));
13495}
13596
136fn dependOnLib(lib_exe_obj: *std.build.LibExeObjStep, dep: *const LibraryDep) void {
97fn dependOnLib(lib_exe_obj: var, dep: *const LibraryDep) void {
13798 for (dep.libdirs.toSliceConst()) |lib_dir| {
13899 lib_exe_obj.addLibPath(lib_dir);
139100 }
......@@ -148,7 +109,7 @@ fn dependOnLib(lib_exe_obj: *std.build.LibExeObjStep, dep: *const LibraryDep) vo
148109 }
149110}
150111
151fn addCppLib(b: *Builder, lib_exe_obj: *std.build.LibExeObjStep, cmake_binary_dir: []const u8, lib_name: []const u8) void {
112fn addCppLib(b: *Builder, lib_exe_obj: var, cmake_binary_dir: []const u8, lib_name: []const u8) void {
152113 const lib_prefix = if (lib_exe_obj.target.isWindows()) "" else "lib";
153114 lib_exe_obj.addObjectFile(os.path.join(b.allocator, cmake_binary_dir, "zig_cpp", b.fmt("{}{}{}", lib_prefix, lib_name, lib_exe_obj.target.libFileExt())) catch unreachable);
154115}
......@@ -254,3 +215,68 @@ fn nextValue(index: *usize, build_info: []const u8) []const u8 {
254215 }
255216 }
256217}
218
219fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {
220 // This is for finding /lib/libz.a on alpine linux.
221 // TODO turn this into -Dextra-lib-path=/lib option
222 exe.addLibPath("/lib");
223
224 exe.addIncludeDir("src");
225 exe.addIncludeDir(ctx.cmake_binary_dir);
226 addCppLib(b, exe, ctx.cmake_binary_dir, "zig_cpp");
227 if (ctx.lld_include_dir.len != 0) {
228 exe.addIncludeDir(ctx.lld_include_dir);
229 var it = mem.split(ctx.lld_libraries, ";");
230 while (it.next()) |lib| {
231 exe.addObjectFile(lib);
232 }
233 } else {
234 addCppLib(b, exe, ctx.cmake_binary_dir, "embedded_lld_wasm");
235 addCppLib(b, exe, ctx.cmake_binary_dir, "embedded_lld_elf");
236 addCppLib(b, exe, ctx.cmake_binary_dir, "embedded_lld_coff");
237 addCppLib(b, exe, ctx.cmake_binary_dir, "embedded_lld_lib");
238 }
239 dependOnLib(exe, ctx.llvm);
240
241 if (exe.target.getOs() == builtin.Os.linux) {
242 const libstdcxx_path_padded = try b.exec([][]const u8{
243 ctx.cxx_compiler,
244 "-print-file-name=libstdc++.a",
245 });
246 const libstdcxx_path = mem.split(libstdcxx_path_padded, "\r\n").next().?;
247 if (mem.eql(u8, libstdcxx_path, "libstdc++.a")) {
248 warn(
249 \\Unable to determine path to libstdc++.a
250 \\On Fedora, install libstdc++-static and try again.
251 \\
252 );
253 return error.RequiredLibraryNotFound;
254 }
255 exe.addObjectFile(libstdcxx_path);
256
257 exe.linkSystemLibrary("pthread");
258 } else if (exe.target.isDarwin()) {
259 exe.linkSystemLibrary("c++");
260 }
261
262 if (ctx.dia_guids_lib.len != 0) {
263 exe.addObjectFile(ctx.dia_guids_lib);
264 }
265
266 if (exe.target.getOs() != builtin.Os.windows) {
267 exe.linkSystemLibrary("xml2");
268 }
269 exe.linkSystemLibrary("c");
270}
271
272const Context = struct {
273 cmake_binary_dir: []const u8,
274 cxx_compiler: []const u8,
275 llvm_config_exe: []const u8,
276 lld_include_dir: []const u8,
277 lld_libraries: []const u8,
278 std_files: []const u8,
279 c_header_files: []const u8,
280 dia_guids_lib: []const u8,
281 llvm: LibraryDep,
282};
src-self-hosted/errmsg.zig+12-6
......@@ -11,11 +11,15 @@ pub const Color = enum {
1111 On,
1212};
1313
14pub const Span = struct {
15 first: ast.TokenIndex,
16 last: ast.TokenIndex,
17};
18
1419pub const Msg = struct {
1520 path: []const u8,
1621 text: []u8,
17 first_token: TokenIndex,
18 last_token: TokenIndex,
22 span: Span,
1923 tree: *ast.Tree,
2024};
2125
......@@ -39,8 +43,10 @@ pub fn createFromParseError(
3943 .tree = tree,
4044 .path = path,
4145 .text = text_buf.toOwnedSlice(),
42 .first_token = loc_token,
43 .last_token = loc_token,
46 .span = Span{
47 .first = loc_token,
48 .last = loc_token,
49 },
4450 });
4551 errdefer allocator.destroy(msg);
4652
......@@ -48,8 +54,8 @@ pub fn createFromParseError(
4854}
4955
5056pub fn printToStream(stream: var, msg: *const Msg, color_on: bool) !void {
51 const first_token = msg.tree.tokens.at(msg.first_token);
52 const last_token = msg.tree.tokens.at(msg.last_token);
57 const first_token = msg.tree.tokens.at(msg.span.first);
58 const last_token = msg.tree.tokens.at(msg.span.last);
5359 const start_loc = msg.tree.tokenLocationPtr(0, first_token);
5460 const end_loc = msg.tree.tokenLocationPtr(first_token.end, last_token);
5561 if (!color_on) {
src-self-hosted/introspect.zig+5
......@@ -53,3 +53,8 @@ pub fn resolveZigLibDir(allocator: *mem.Allocator) ![]u8 {
5353 return error.ZigLibDirNotFound;
5454 };
5555}
56
57/// Caller must free result
58pub fn resolveZigCacheDir(allocator: *mem.Allocator) ![]u8 {
59 return std.mem.dupe(allocator, u8, "zig-cache");
60}
src-self-hosted/main.zig+18-18
......@@ -481,29 +481,29 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo
481481 module.link_out_file = flags.single("out-file");
482482
483483 try module.build();
484 const process_build_events_handle = try async<loop.allocator> processBuildEvents(module, true);
484 const process_build_events_handle = try async<loop.allocator> processBuildEvents(module, color);
485485 defer cancel process_build_events_handle;
486486 loop.run();
487487}
488488
489async fn processBuildEvents(module: *Module, watch: bool) void {
490 while (watch) {
491 // TODO directly awaiting async should guarantee memory allocation elision
492 const build_event = await (async module.events.get() catch unreachable);
489async fn processBuildEvents(module: *Module, color: errmsg.Color) void {
490 // TODO directly awaiting async should guarantee memory allocation elision
491 const build_event = await (async module.events.get() catch unreachable);
493492
494 switch (build_event) {
495 Module.Event.Ok => {
496 std.debug.warn("Build succeeded\n");
497 return;
498 },
499 Module.Event.Error => |err| {
500 std.debug.warn("build failed: {}\n", @errorName(err));
501 @panic("TODO error return trace");
502 },
503 Module.Event.Fail => |errs| {
504 @panic("TODO print compile error messages");
505 },
506 }
493 switch (build_event) {
494 Module.Event.Ok => {
495 std.debug.warn("Build succeeded\n");
496 return;
497 },
498 Module.Event.Error => |err| {
499 std.debug.warn("build failed: {}\n", @errorName(err));
500 @panic("TODO error return trace");
501 },
502 Module.Event.Fail => |msgs| {
503 for (msgs) |msg| {
504 errmsg.printToFile(&stderr_file, msg, color) catch os.exit(1);
505 }
506 },
507507 }
508508}
509509
src-self-hosted/module.zig+81-17
......@@ -89,12 +89,9 @@ pub const Module = struct {
8989 /// the build is complete.
9090 build_group: event.Group(BuildError!void),
9191
92 const BuildErrorsList = std.SegmentedList(BuildErrorDesc, 1);
92 compile_errors: event.Locked(CompileErrList),
9393
94 pub const BuildErrorDesc = struct {
95 code: BuildError,
96 text: []const u8,
97 };
94 const CompileErrList = std.ArrayList(*errmsg.Msg);
9895
9996 // TODO handle some of these earlier and report them in a way other than error codes
10097 pub const BuildError = error{
......@@ -131,11 +128,12 @@ pub const Module = struct {
131128 NoStdHandles,
132129 Overflow,
133130 NotSupported,
131 BufferTooSmall,
134132 };
135133
136134 pub const Event = union(enum) {
137135 Ok,
138 Fail: []errmsg.Msg,
136 Fail: []*errmsg.Msg,
139137 Error: BuildError,
140138 };
141139
......@@ -249,6 +247,7 @@ pub const Module = struct {
249247 .link_out_file = null,
250248 .exported_symbol_names = event.Locked(Decl.Table).init(loop, Decl.Table.init(loop.allocator)),
251249 .build_group = event.Group(BuildError!void).init(loop),
250 .compile_errors = event.Locked(CompileErrList).init(loop, CompileErrList.init(loop.allocator)),
252251 });
253252 }
254253
......@@ -288,7 +287,17 @@ pub const Module = struct {
288287 await (async self.events.put(Event{ .Error = err }) catch unreachable);
289288 return;
290289 };
291 await (async self.events.put(Event.Ok) catch unreachable);
290 const compile_errors = blk: {
291 const held = await (async self.compile_errors.acquire() catch unreachable);
292 defer held.release();
293 break :blk held.value.toOwnedSlice();
294 };
295
296 if (compile_errors.len == 0) {
297 await (async self.events.put(Event.Ok) catch unreachable);
298 } else {
299 await (async self.events.put(Event{ .Fail = compile_errors }) catch unreachable);
300 }
292301 // for now we stop after 1
293302 return;
294303 }
......@@ -310,10 +319,13 @@ pub const Module = struct {
310319 };
311320 errdefer self.a().free(source_code);
312321
313 var parsed_file = ParsedFile{
314 .tree = try std.zig.parse(self.a(), source_code),
322 const parsed_file = try self.a().create(ParsedFile{
323 .tree = undefined,
315324 .realpath = root_src_real_path,
316 };
325 });
326 errdefer self.a().destroy(parsed_file);
327
328 parsed_file.tree = try std.zig.parse(self.a(), source_code);
317329 errdefer parsed_file.tree.deinit();
318330
319331 const tree = &parsed_file.tree;
......@@ -337,7 +349,7 @@ pub const Module = struct {
337349 const name = if (fn_proto.name_token) |name_token| tree.tokenSlice(name_token) else {
338350 @panic("TODO add compile error");
339351 //try self.addCompileError(
340 // &parsed_file,
352 // parsed_file,
341353 // fn_proto.fn_token,
342354 // fn_proto.fn_token + 1,
343355 // "missing function name",
......@@ -357,7 +369,7 @@ pub const Module = struct {
357369 });
358370 errdefer self.a().destroy(fn_decl);
359371
360 try decl_group.call(addTopLevelDecl, self, tree, &fn_decl.base);
372 try decl_group.call(addTopLevelDecl, self, parsed_file, &fn_decl.base);
361373 },
362374 ast.Node.Id.TestDecl => @panic("TODO"),
363375 else => unreachable,
......@@ -367,20 +379,56 @@ pub const Module = struct {
367379 try await (async self.build_group.wait() catch unreachable);
368380 }
369381
370 async fn addTopLevelDecl(self: *Module, tree: *ast.Tree, decl: *Decl) !void {
371 const is_export = decl.isExported(tree);
382 async fn addTopLevelDecl(self: *Module, parsed_file: *ParsedFile, decl: *Decl) !void {
383 const is_export = decl.isExported(&parsed_file.tree);
372384
373385 if (is_export) {
374 try self.build_group.call(verifyUniqueSymbol, self, decl);
386 try self.build_group.call(verifyUniqueSymbol, self, parsed_file, decl);
375387 }
376388 }
377389
378 async fn verifyUniqueSymbol(self: *Module, decl: *Decl) !void {
390 fn addCompileError(self: *Module, parsed_file: *ParsedFile, span: errmsg.Span, comptime fmt: []const u8, args: ...) !void {
391 const text = try std.fmt.allocPrint(self.loop.allocator, fmt, args);
392 errdefer self.loop.allocator.free(text);
393
394 try self.build_group.call(addCompileErrorAsync, self, parsed_file, span.first, span.last, text);
395 }
396
397 async fn addCompileErrorAsync(
398 self: *Module,
399 parsed_file: *ParsedFile,
400 first_token: ast.TokenIndex,
401 last_token: ast.TokenIndex,
402 text: []u8,
403 ) !void {
404 const msg = try self.loop.allocator.create(errmsg.Msg{
405 .path = parsed_file.realpath,
406 .text = text,
407 .span = errmsg.Span{
408 .first = first_token,
409 .last = last_token,
410 },
411 .tree = &parsed_file.tree,
412 });
413 errdefer self.loop.allocator.destroy(msg);
414
415 const compile_errors = await (async self.compile_errors.acquire() catch unreachable);
416 defer compile_errors.release();
417
418 try compile_errors.value.append(msg);
419 }
420
421 async fn verifyUniqueSymbol(self: *Module, parsed_file: *ParsedFile, decl: *Decl) !void {
379422 const exported_symbol_names = await (async self.exported_symbol_names.acquire() catch unreachable);
380423 defer exported_symbol_names.release();
381424
382425 if (try exported_symbol_names.value.put(decl.name, decl)) |other_decl| {
383 @panic("TODO report compile error");
426 try self.addCompileError(
427 parsed_file,
428 decl.getSpan(),
429 "exported symbol collision: '{}'",
430 decl.name,
431 );
384432 }
385433 }
386434
......@@ -503,6 +551,22 @@ pub const Decl = struct {
503551 }
504552 }
505553
554 pub fn getSpan(base: *const Decl) errmsg.Span {
555 switch (base.id) {
556 Id.Fn => {
557 const fn_decl = @fieldParentPtr(Fn, "base", base);
558 const fn_proto = fn_decl.fn_proto;
559 const start = fn_proto.fn_token;
560 const end = fn_proto.name_token orelse start;
561 return errmsg.Span{
562 .first = start,
563 .last = end + 1,
564 };
565 },
566 else => @panic("TODO"),
567 }
568 }
569
506570 pub const Resolution = enum {
507571 Unresolved,
508572 InProgress,
src-self-hosted/test.zig created+164
......@@ -0,0 +1,164 @@
1const std = @import("std");
2const mem = std.mem;
3const builtin = @import("builtin");
4const Target = @import("target.zig").Target;
5const Module = @import("module.zig").Module;
6const introspect = @import("introspect.zig");
7const assertOrPanic = std.debug.assertOrPanic;
8const errmsg = @import("errmsg.zig");
9
10test "compile errors" {
11 var ctx: TestContext = undefined;
12 try ctx.init();
13 defer ctx.deinit();
14
15 try ctx.testCompileError(
16 \\export fn entry() void {}
17 \\export fn entry() void {}
18 , file1, 2, 8, "exported symbol collision: 'entry'");
19
20 try ctx.run();
21}
22
23const file1 = "1.zig";
24const allocator = std.heap.c_allocator;
25
26const TestContext = struct {
27 loop: std.event.Loop,
28 zig_lib_dir: []u8,
29 zig_cache_dir: []u8,
30 file_index: std.atomic.Int(usize),
31 group: std.event.Group(error!void),
32 any_err: error!void,
33
34 const tmp_dir_name = "stage2_test_tmp";
35
36 fn init(self: *TestContext) !void {
37 self.* = TestContext{
38 .any_err = {},
39 .loop = undefined,
40 .zig_lib_dir = undefined,
41 .zig_cache_dir = undefined,
42 .group = undefined,
43 .file_index = std.atomic.Int(usize).init(0),
44 };
45
46 try self.loop.initMultiThreaded(allocator);
47 errdefer self.loop.deinit();
48
49 self.group = std.event.Group(error!void).init(&self.loop);
50 errdefer self.group.cancelAll();
51
52 self.zig_lib_dir = try introspect.resolveZigLibDir(allocator);
53 errdefer allocator.free(self.zig_lib_dir);
54
55 self.zig_cache_dir = try introspect.resolveZigCacheDir(allocator);
56 errdefer allocator.free(self.zig_cache_dir);
57
58 try std.os.makePath(allocator, tmp_dir_name);
59 errdefer std.os.deleteTree(allocator, tmp_dir_name) catch {};
60 }
61
62 fn deinit(self: *TestContext) void {
63 std.os.deleteTree(allocator, tmp_dir_name) catch {};
64 allocator.free(self.zig_cache_dir);
65 allocator.free(self.zig_lib_dir);
66 self.loop.deinit();
67 }
68
69 fn run(self: *TestContext) !void {
70 const handle = try self.loop.call(waitForGroup, self);
71 defer cancel handle;
72 self.loop.run();
73 return self.any_err;
74 }
75
76 async fn waitForGroup(self: *TestContext) void {
77 self.any_err = await (async self.group.wait() catch unreachable);
78 }
79
80 fn testCompileError(
81 self: *TestContext,
82 source: []const u8,
83 path: []const u8,
84 line: usize,
85 column: usize,
86 msg: []const u8,
87 ) !void {
88 var file_index_buf: [20]u8 = undefined;
89 const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", self.file_index.next());
90 const file1_path = try std.os.path.join(allocator, tmp_dir_name, file_index, file1);
91
92 if (std.os.path.dirname(file1_path)) |dirname| {
93 try std.os.makePath(allocator, dirname);
94 }
95
96 // TODO async I/O
97 try std.io.writeFile(allocator, file1_path, source);
98
99 var module = try Module.create(
100 &self.loop,
101 "test",
102 file1_path,
103 Target.Native,
104 Module.Kind.Obj,
105 builtin.Mode.Debug,
106 self.zig_lib_dir,
107 self.zig_cache_dir,
108 );
109 errdefer module.destroy();
110
111 try module.build();
112
113 try self.group.call(getModuleEvent, module, source, path, line, column, msg);
114 }
115
116 async fn getModuleEvent(
117 module: *Module,
118 source: []const u8,
119 path: []const u8,
120 line: usize,
121 column: usize,
122 text: []const u8,
123 ) !void {
124 defer module.destroy();
125 const build_event = await (async module.events.get() catch unreachable);
126
127 switch (build_event) {
128 Module.Event.Ok => {
129 @panic("build incorrectly succeeded");
130 },
131 Module.Event.Error => |err| {
132 @panic("build incorrectly failed");
133 },
134 Module.Event.Fail => |msgs| {
135 assertOrPanic(msgs.len != 0);
136 for (msgs) |msg| {
137 if (mem.endsWith(u8, msg.path, path) and mem.eql(u8, msg.text, text)) {
138 const first_token = msg.tree.tokens.at(msg.span.first);
139 const last_token = msg.tree.tokens.at(msg.span.first);
140 const start_loc = msg.tree.tokenLocationPtr(0, first_token);
141 if (start_loc.line + 1 == line and start_loc.column + 1 == column) {
142 return;
143 }
144 }
145 }
146 std.debug.warn(
147 "\n=====source:=======\n{}\n====expected:========\n{}:{}:{}: error: {}\n",
148 source,
149 path,
150 line,
151 column,
152 text,
153 );
154 std.debug.warn("\n====found:========\n");
155 var stderr = try std.io.getStdErr();
156 for (msgs) |msg| {
157 try errmsg.printToFile(&stderr, msg, errmsg.Color.Auto);
158 }
159 std.debug.warn("============\n");
160 return error.TestFailed;
161 },
162 }
163 }
164};
src/main.cpp+7-3
......@@ -891,15 +891,19 @@ int main(int argc, char **argv) {
891891
892892 add_package(g, cur_pkg, g->root_package);
893893
894 if (cmd == CmdBuild || cmd == CmdRun) {
895 codegen_set_emit_file_type(g, emit_file_type);
896
894 if (cmd == CmdBuild || cmd == CmdRun || cmd == CmdTest) {
897895 for (size_t i = 0; i < objects.length; i += 1) {
898896 codegen_add_object(g, buf_create_from_str(objects.at(i)));
899897 }
900898 for (size_t i = 0; i < asm_files.length; i += 1) {
901899 codegen_add_assembly(g, buf_create_from_str(asm_files.at(i)));
902900 }
901 }
902
903
904 if (cmd == CmdBuild || cmd == CmdRun) {
905 codegen_set_emit_file_type(g, emit_file_type);
906
903907 codegen_build(g);
904908 codegen_link(g, out_file);
905909 if (timing_info)
std/atomic/index.zig+2
......@@ -1,9 +1,11 @@
11pub const Stack = @import("stack.zig").Stack;
22pub const QueueMpsc = @import("queue_mpsc.zig").QueueMpsc;
33pub const QueueMpmc = @import("queue_mpmc.zig").QueueMpmc;
4pub const Int = @import("int.zig").Int;
45
56test "std.atomic" {
67 _ = @import("stack.zig");
78 _ = @import("queue_mpsc.zig");
89 _ = @import("queue_mpmc.zig");
10 _ = @import("int.zig");
911}
std/atomic/int.zig created+19
......@@ -0,0 +1,19 @@
1const builtin = @import("builtin");
2const AtomicOrder = builtin.AtomicOrder;
3
4/// Thread-safe, lock-free integer
5pub fn Int(comptime T: type) type {
6 return struct {
7 value: T,
8
9 pub const Self = this;
10
11 pub fn init(init_val: T) Self {
12 return Self{ .value = init_val };
13 }
14
15 pub fn next(self: *Self) T {
16 return @atomicRmw(T, &self.value, builtin.AtomicRmwOp.Add, 1, AtomicOrder.SeqCst);
17 }
18 };
19}
std/build.zig+22
......@@ -1596,6 +1596,8 @@ pub const TestStep = struct {
15961596 target: Target,
15971597 exec_cmd_args: ?[]const ?[]const u8,
15981598 include_dirs: ArrayList([]const u8),
1599 lib_paths: ArrayList([]const u8),
1600 object_files: ArrayList([]const u8),
15991601
16001602 pub fn init(builder: *Builder, root_src: []const u8) TestStep {
16011603 const step_name = builder.fmt("test {}", root_src);
......@@ -1611,9 +1613,15 @@ pub const TestStep = struct {
16111613 .target = Target{ .Native = {} },
16121614 .exec_cmd_args = null,
16131615 .include_dirs = ArrayList([]const u8).init(builder.allocator),
1616 .lib_paths = ArrayList([]const u8).init(builder.allocator),
1617 .object_files = ArrayList([]const u8).init(builder.allocator),
16141618 };
16151619 }
16161620
1621 pub fn addLibPath(self: *TestStep, path: []const u8) void {
1622 self.lib_paths.append(path) catch unreachable;
1623 }
1624
16171625 pub fn setVerbose(self: *TestStep, value: bool) void {
16181626 self.verbose = value;
16191627 }
......@@ -1638,6 +1646,10 @@ pub const TestStep = struct {
16381646 self.filter = text;
16391647 }
16401648
1649 pub fn addObjectFile(self: *TestStep, path: []const u8) void {
1650 self.object_files.append(path) catch unreachable;
1651 }
1652
16411653 pub fn setTarget(self: *TestStep, target_arch: builtin.Arch, target_os: builtin.Os, target_environ: builtin.Environ) void {
16421654 self.target = Target{
16431655 .Cross = CrossTarget{
......@@ -1699,6 +1711,11 @@ pub const TestStep = struct {
16991711 try zig_args.append(self.name_prefix);
17001712 }
17011713
1714 for (self.object_files.toSliceConst()) |object_file| {
1715 try zig_args.append("--object");
1716 try zig_args.append(builder.pathFromRoot(object_file));
1717 }
1718
17021719 {
17031720 var it = self.link_libs.iterator();
17041721 while (true) {
......@@ -1734,6 +1751,11 @@ pub const TestStep = struct {
17341751 try zig_args.append(rpath);
17351752 }
17361753
1754 for (self.lib_paths.toSliceConst()) |lib_path| {
1755 try zig_args.append("--library-path");
1756 try zig_args.append(lib_path);
1757 }
1758
17371759 for (builder.lib_paths.toSliceConst()) |lib_path| {
17381760 try zig_args.append("--library-path");
17391761 try zig_args.append(lib_path);