authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-26 01:42:54-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-26 01:47:27-07:00
log6af2990549709ec5e2bc1efeb5090a944f1a8bdf
treec4dc51ddde68c2842b6450bd6dee6432e2226bde
parenta337046832b936d912b6902e331cb58bdc513a2d

implement -femit-asm, -femit-docs, -femit-llvm-ir, etc

These CLI options are now forwarded to the stage1 backend. We're not going to support the -mllvm CLI option any longer. As a compromise, we unconditionally tell LLVM to output intel x86 syntax when using -femit-asm. Simplify stage1 logic; it no longer has the concept of an output directory. --output-dir is no longer a valid CLI option. cmake uses the `-femit-bin=[path]` option. Note the changes to test/cli.zig. This breaks the CLI API that Godbolt is using so we're going to want to open a PR to help them upgrade to the new CLI for the upcoming Zig 0.7.0 release.

12 files changed, 263 insertions(+), 158 deletions(-)

BRANCH_TODO+4-9
...@@ -1,13 +1,7 @@...@@ -1,13 +1,7 @@
1 * support -fno-emit-bin for godbolt
1 * tests passing with -Dskip-non-native2 * tests passing with -Dskip-non-native
2 * `-ftime-report`3 * `-ftime-report`
3 * -fstack-report print stack size diagnostics\n"4 * -fstack-report print stack size diagnostics\n"
4 * -fdump-analysis write analysis.json file with type information\n"
5 * -femit-docs create a docs/ dir with html documentation\n"
6 * -fno-emit-docs do not produce docs/ dir with html documentation\n"
7 * -femit-asm output .s (assembly code)\n"
8 * -fno-emit-asm (default) do not output .s (assembly code)\n"
9 * -femit-llvm-ir produce a .ll file with LLVM IR\n"
10 * -fno-emit-llvm-ir (default) do not produce a .ll file with LLVM IR\n"
11 * mingw-w645 * mingw-w64
12 * MachO LLD linking6 * MachO LLD linking
13 * COFF LLD linking7 * COFF LLD linking
...@@ -17,8 +11,8 @@...@@ -17,8 +11,8 @@
17 * On operating systems that support it, do an execve for `zig test` and `zig run` rather than child process.11 * On operating systems that support it, do an execve for `zig test` and `zig run` rather than child process.
18 * restore error messages for stage2_add_link_lib12 * restore error messages for stage2_add_link_lib
19 * windows CUSTOMBUILD : error : unable to build compiler_rt: FileNotFound [D:\a\1\s\build\zig_install_lib_files.vcxproj]13 * windows CUSTOMBUILD : error : unable to build compiler_rt: FileNotFound [D:\a\1\s\build\zig_install_lib_files.vcxproj]
20 * try building some software with zig cc14 * try building some software with zig cc to make sure it didn't regress
21 * implement support for -femit-asm15 * restore the legacy -femit-h feature using the stage1 backend
2216
23 * implement proper parsing of clang stderr/stdout and exposing compile errors with the Compilation API17 * implement proper parsing of clang stderr/stdout and exposing compile errors with the Compilation API
24 * implement proper parsing of LLD stderr/stdout and exposing compile errors with the Compilation API18 * implement proper parsing of LLD stderr/stdout and exposing compile errors with the Compilation API
...@@ -56,3 +50,4 @@...@@ -56,3 +50,4 @@
56 * make std.Progress support multithreaded50 * make std.Progress support multithreaded
57 * update musl.zig static data to use native path separator in static data rather than replacing '/' at runtime51 * update musl.zig static data to use native path separator in static data rather than replacing '/' at runtime
58 * linking hello world with LLD, lld is silently calling exit(1) instead of reporting ok=false. when run standalone the error message is: ld.lld: error: section [index 3] has a sh_offset (0x57000) + sh_size (0x68) that is greater than the file size (0x57060)52 * linking hello world with LLD, lld is silently calling exit(1) instead of reporting ok=false. when run standalone the error message is: ld.lld: error: section [index 3] has a sh_offset (0x57000) + sh_size (0x68) that is greater than the file size (0x57060)
53 * submit PR to godbolt and update the CLI options (see changes to test/cli.zig)
CMakeLists.txt+3-3
...@@ -449,7 +449,7 @@ endif()...@@ -449,7 +449,7 @@ endif()
449if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")449if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
450 set(ZIG1_RELEASE_ARG "")450 set(ZIG1_RELEASE_ARG "")
451else()451else()
452 set(ZIG1_RELEASE_ARG --release-fast --strip)452 set(ZIG1_RELEASE_ARG -OReleaseFast --strip)
453endif()453endif()
454454
455set(BUILD_ZIG1_ARGS455set(BUILD_ZIG1_ARGS
...@@ -458,8 +458,8 @@ set(BUILD_ZIG1_ARGS...@@ -458,8 +458,8 @@ set(BUILD_ZIG1_ARGS
458 "-mcpu=${ZIG_TARGET_MCPU}"458 "-mcpu=${ZIG_TARGET_MCPU}"
459 --name zig1459 --name zig1
460 --override-lib-dir "${CMAKE_SOURCE_DIR}/lib"460 --override-lib-dir "${CMAKE_SOURCE_DIR}/lib"
461 --output-dir "${CMAKE_BINARY_DIR}"461 "-femit-bin=${ZIG1_OBJECT}"
462 ${ZIG1_RELEASE_ARG}462 "${ZIG1_RELEASE_ARG}"
463 -lc463 -lc
464 --pkg-begin build_options "${ZIG_CONFIG_ZIG_OUT}"464 --pkg-begin build_options "${ZIG_CONFIG_ZIG_OUT}"
465 --pkg-end465 --pkg-end
src/Compilation.zig+54-14
...@@ -107,6 +107,12 @@ test_filter: ?[]const u8,...@@ -107,6 +107,12 @@ test_filter: ?[]const u8,
107test_name_prefix: ?[]const u8,107test_name_prefix: ?[]const u8,
108test_evented_io: bool,108test_evented_io: bool,
109109
110emit_h: ?EmitLoc,
111emit_asm: ?EmitLoc,
112emit_llvm_ir: ?EmitLoc,
113emit_analysis: ?EmitLoc,
114emit_docs: ?EmitLoc,
115
110pub const InnerError = Module.InnerError;116pub const InnerError = Module.InnerError;
111117
112pub const CRTFile = struct {118pub const CRTFile = struct {
...@@ -296,6 +302,12 @@ pub const InitOptions = struct {...@@ -296,6 +302,12 @@ pub const InitOptions = struct {
296 emit_h: ?EmitLoc = null,302 emit_h: ?EmitLoc = null,
297 /// `null` means to not emit assembly.303 /// `null` means to not emit assembly.
298 emit_asm: ?EmitLoc = null,304 emit_asm: ?EmitLoc = null,
305 /// `null` means to not emit LLVM IR.
306 emit_llvm_ir: ?EmitLoc = null,
307 /// `null` means to not emit semantic analysis JSON.
308 emit_analysis: ?EmitLoc = null,
309 /// `null` means to not emit docs.
310 emit_docs: ?EmitLoc = null,
299 link_mode: ?std.builtin.LinkMode = null,311 link_mode: ?std.builtin.LinkMode = null,
300 dll_export_fns: ?bool = false,312 dll_export_fns: ?bool = false,
301 /// Normally when using LLD to link, Zig uses a file named "lld.id" in the313 /// Normally when using LLD to link, Zig uses a file named "lld.id" in the
...@@ -442,7 +454,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -442,7 +454,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
442 break :blk false;454 break :blk false;
443 };455 };
444456
445
446 const link_libc = options.link_libc or457 const link_libc = options.link_libc or
447 (is_exe_or_dyn_lib and target_util.osRequiresLibC(options.target));458 (is_exe_or_dyn_lib and target_util.osRequiresLibC(options.target));
448459
...@@ -489,9 +500,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -489,9 +500,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
489 break :pic explicit;500 break :pic explicit;
490 } else must_pic;501 } else must_pic;
491502
492 if (options.emit_h != null) fatal("-femit-h not supported yet", .{}); // TODO
493 if (options.emit_asm != null) fatal("-femit-asm not supported yet", .{}); // TODO
494
495 const emit_bin = options.emit_bin orelse fatal("-fno-emit-bin not supported yet", .{}); // TODO503 const emit_bin = options.emit_bin orelse fatal("-fno-emit-bin not supported yet", .{}); // TODO
496504
497 // Make a decision on whether to use Clang for translate-c and compiling C files.505 // Make a decision on whether to use Clang for translate-c and compiling C files.
...@@ -579,6 +587,12 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -579,6 +587,12 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
579 cache.hash.add(options.link_libcpp);587 cache.hash.add(options.link_libcpp);
580 cache.hash.add(options.output_mode);588 cache.hash.add(options.output_mode);
581 cache.hash.add(options.machine_code_model);589 cache.hash.add(options.machine_code_model);
590 cache.hash.add(options.emit_bin != null);
591 cache.hash.add(options.emit_h != null);
592 cache.hash.add(options.emit_asm != null);
593 cache.hash.add(options.emit_llvm_ir != null);
594 cache.hash.add(options.emit_analysis != null);
595 cache.hash.add(options.emit_docs != null);
582 // TODO audit this and make sure everything is in it596 // TODO audit this and make sure everything is in it
583597
584 const module: ?*Module = if (options.root_pkg) |root_pkg| blk: {598 const module: ?*Module = if (options.root_pkg) |root_pkg| blk: {
...@@ -752,6 +766,11 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -752,6 +766,11 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
752 .local_cache_directory = options.local_cache_directory,766 .local_cache_directory = options.local_cache_directory,
753 .global_cache_directory = options.global_cache_directory,767 .global_cache_directory = options.global_cache_directory,
754 .bin_file = bin_file,768 .bin_file = bin_file,
769 .emit_h = options.emit_h,
770 .emit_asm = options.emit_asm,
771 .emit_llvm_ir = options.emit_llvm_ir,
772 .emit_analysis = options.emit_analysis,
773 .emit_docs = options.emit_docs,
755 .work_queue = std.fifo.LinearFifo(Job, .Dynamic).init(gpa),774 .work_queue = std.fifo.LinearFifo(Job, .Dynamic).init(gpa),
756 .keep_source_files_loaded = options.keep_source_files_loaded,775 .keep_source_files_loaded = options.keep_source_files_loaded,
757 .use_clang = use_clang,776 .use_clang = use_clang,
...@@ -1450,8 +1469,8 @@ fn updateCObject(comp: *Compilation, c_object: *CObject) !void {...@@ -1450,8 +1469,8 @@ fn updateCObject(comp: *Compilation, c_object: *CObject) !void {
14501469
1451 try argv.ensureCapacity(argv.items.len + 3);1470 try argv.ensureCapacity(argv.items.len + 3);
1452 switch (comp.clang_preprocessor_mode) {1471 switch (comp.clang_preprocessor_mode) {
1453 .no => argv.appendSliceAssumeCapacity(&[_][]const u8{"-c", "-o", out_obj_path}),1472 .no => argv.appendSliceAssumeCapacity(&[_][]const u8{ "-c", "-o", out_obj_path }),
1454 .yes => argv.appendSliceAssumeCapacity(&[_][]const u8{"-E", "-o", out_obj_path}),1473 .yes => argv.appendSliceAssumeCapacity(&[_][]const u8{ "-E", "-o", out_obj_path }),
1455 .stdout => argv.appendAssumeCapacity("-E"),1474 .stdout => argv.appendAssumeCapacity("-E"),
1456 }1475 }
14571476
...@@ -2498,15 +2517,35 @@ fn updateStage1Module(comp: *Compilation) !void {...@@ -2498,15 +2517,35 @@ fn updateStage1Module(comp: *Compilation) !void {
2498 comp.is_test,2517 comp.is_test,
2499 ) orelse return error.OutOfMemory;2518 ) orelse return error.OutOfMemory;
25002519
2520 const bin_basename = try std.zig.binNameAlloc(arena, .{
2521 .root_name = comp.bin_file.options.root_name,
2522 .target = target,
2523 .output_mode = .Obj,
2524 });
2525 const emit_bin_path = try directory.join(arena, &[_][]const u8{bin_basename});
2526 const emit_h_path = try stage1LocPath(arena, comp.emit_h, directory);
2527 const emit_asm_path = try stage1LocPath(arena, comp.emit_asm, directory);
2528 const emit_llvm_ir_path = try stage1LocPath(arena, comp.emit_llvm_ir, directory);
2529 const emit_analysis_path = try stage1LocPath(arena, comp.emit_analysis, directory);
2530 const emit_docs_path = try stage1LocPath(arena, comp.emit_docs, directory);
2501 const stage1_pkg = try createStage1Pkg(arena, "root", mod.root_pkg, null);2531 const stage1_pkg = try createStage1Pkg(arena, "root", mod.root_pkg, null);
2502 const output_dir = directory.path orelse ".";
2503 const test_filter = comp.test_filter orelse ""[0..0];2532 const test_filter = comp.test_filter orelse ""[0..0];
2504 const test_name_prefix = comp.test_name_prefix orelse ""[0..0];2533 const test_name_prefix = comp.test_name_prefix orelse ""[0..0];
2505 stage1_module.* = .{2534 stage1_module.* = .{
2506 .root_name_ptr = comp.bin_file.options.root_name.ptr,2535 .root_name_ptr = comp.bin_file.options.root_name.ptr,
2507 .root_name_len = comp.bin_file.options.root_name.len,2536 .root_name_len = comp.bin_file.options.root_name.len,
2508 .output_dir_ptr = output_dir.ptr,2537 .emit_o_ptr = emit_bin_path.ptr,
2509 .output_dir_len = output_dir.len,2538 .emit_o_len = emit_bin_path.len,
2539 .emit_h_ptr = emit_h_path.ptr,
2540 .emit_h_len = emit_h_path.len,
2541 .emit_asm_ptr = emit_asm_path.ptr,
2542 .emit_asm_len = emit_asm_path.len,
2543 .emit_llvm_ir_ptr = emit_llvm_ir_path.ptr,
2544 .emit_llvm_ir_len = emit_llvm_ir_path.len,
2545 .emit_analysis_json_ptr = emit_analysis_path.ptr,
2546 .emit_analysis_json_len = emit_analysis_path.len,
2547 .emit_docs_ptr = emit_docs_path.ptr,
2548 .emit_docs_len = emit_docs_path.len,
2510 .builtin_zig_path_ptr = builtin_zig_path.ptr,2549 .builtin_zig_path_ptr = builtin_zig_path.ptr,
2511 .builtin_zig_path_len = builtin_zig_path.len,2550 .builtin_zig_path_len = builtin_zig_path.len,
2512 .test_filter_ptr = test_filter.ptr,2551 .test_filter_ptr = test_filter.ptr,
...@@ -2530,11 +2569,6 @@ fn updateStage1Module(comp: *Compilation) !void {...@@ -2530,11 +2569,6 @@ fn updateStage1Module(comp: *Compilation) !void {
2530 .enable_stack_probing = comp.bin_file.options.stack_check,2569 .enable_stack_probing = comp.bin_file.options.stack_check,
2531 .enable_time_report = comp.time_report,2570 .enable_time_report = comp.time_report,
2532 .enable_stack_report = false,2571 .enable_stack_report = false,
2533 .dump_analysis = false,
2534 .enable_doc_generation = false,
2535 .emit_bin = true,
2536 .emit_asm = false,
2537 .emit_llvm_ir = false,
2538 .test_is_evented = comp.test_evented_io,2572 .test_is_evented = comp.test_evented_io,
2539 .verbose_tokenize = comp.verbose_tokenize,2573 .verbose_tokenize = comp.verbose_tokenize,
2540 .verbose_ast = comp.verbose_ast,2574 .verbose_ast = comp.verbose_ast,
...@@ -2565,6 +2599,12 @@ fn updateStage1Module(comp: *Compilation) !void {...@@ -2565,6 +2599,12 @@ fn updateStage1Module(comp: *Compilation) !void {
2565 comp.stage1_lock = man.toOwnedLock();2599 comp.stage1_lock = man.toOwnedLock();
2566}2600}
25672601
2602fn stage1LocPath(arena: *Allocator, opt_loc: ?EmitLoc, cache_directory: Directory) ![]const u8 {
2603 const loc = opt_loc orelse return "";
2604 const directory = loc.directory orelse cache_directory;
2605 return directory.join(arena, &[_][]const u8{loc.basename});
2606}
2607
2568fn createStage1Pkg(2608fn createStage1Pkg(
2569 arena: *Allocator,2609 arena: *Allocator,
2570 name: []const u8,2610 name: []const u8,
src/llvm.zig+3
...@@ -72,3 +72,6 @@ pub const OSType = extern enum(c_int) {...@@ -72,3 +72,6 @@ pub const OSType = extern enum(c_int) {
72 WASI = 34,72 WASI = 34,
73 Emscripten = 35,73 Emscripten = 35,
74};74};
75
76pub const ParseCommandLineOptions = ZigLLVMParseCommandLineOptions;
77extern fn ZigLLVMParseCommandLineOptions(argc: usize, argv: [*]const [*:0]const u8) void;
src/main.zig+122-35
...@@ -195,8 +195,20 @@ const usage_build_generic =...@@ -195,8 +195,20 @@ const usage_build_generic =
195 \\ -h, --help Print this help and exit195 \\ -h, --help Print this help and exit
196 \\ --watch Enable compiler REPL196 \\ --watch Enable compiler REPL
197 \\ --color [auto|off|on] Enable or disable colored error messages197 \\ --color [auto|off|on] Enable or disable colored error messages
198 \\ -femit-bin[=path] (default) output machine code198 \\ -femit-bin[=path] (default) Output machine code
199 \\ -fno-emit-bin Do not output machine code199 \\ -fno-emit-bin Do not output machine code
200 \\ -femit-asm[=path] Output .s (assembly code)
201 \\ -fno-emit-asm (default) Do not output .s (assembly code)
202 \\ -femit-zir[=path] Produce a .zir file with Zig IR
203 \\ -fno-emit-zir (default) Do not produce a .zir file with Zig IR
204 \\ -femit-llvm-ir[=path] Produce a .ll file with LLVM IR (requires LLVM extensions)
205 \\ -fno-emit-llvm-ir (default) Do not produce a .ll file with LLVM IR
206 \\ -femit-h[=path] Generate a C header file (.h)
207 \\ -fno-emit-h (default) Do not generate a C header file (.h)
208 \\ -femit-docs[=path] Create a docs/ dir with html documentation
209 \\ -fno-emit-docs (default) Do not produce docs/ dir with html documentation
210 \\ -femit-analysis[=path] Write analysis JSON file with type information
211 \\ -fno-emit-analysis (default) Do not write analysis JSON file with type information
200 \\ --show-builtin Output the source of @import("builtin") then exit212 \\ --show-builtin Output the source of @import("builtin") then exit
201 \\ --cache-dir [path] Override the local cache directory213 \\ --cache-dir [path] Override the local cache directory
202 \\ --global-cache-dir [path] Override the global cache directory214 \\ --global-cache-dir [path] Override the global cache directory
...@@ -210,10 +222,11 @@ const usage_build_generic =...@@ -210,10 +222,11 @@ const usage_build_generic =
210 \\ small|kernel|222 \\ small|kernel|
211 \\ medium|large]223 \\ medium|large]
212 \\ --name [name] Override root name (not a file path)224 \\ --name [name] Override root name (not a file path)
213 \\ -ODebug (default) optimizations off, safety on225 \\ -O [mode] Choose what to optimize for
214 \\ -OReleaseFast Optimizations on, safety off226 \\ Debug (default) Optimizations off, safety on
215 \\ -OReleaseSafe Optimizations on, safety on227 \\ ReleaseFast Optimizations on, safety off
216 \\ -OReleaseSmall Optimize for small binary, safety off228 \\ ReleaseSafe Optimizations on, safety on
229 \\ ReleaseSmall Optimize for small binary, safety off
217 \\ --pkg-begin [name] [path] Make pkg available to import and push current pkg230 \\ --pkg-begin [name] [path] Make pkg available to import and push current pkg
218 \\ --pkg-end Pop current pkg231 \\ --pkg-end Pop current pkg
219 \\ --main-pkg-path Set the directory of the root package232 \\ --main-pkg-path Set the directory of the root package
...@@ -290,9 +303,57 @@ const Emit = union(enum) {...@@ -290,9 +303,57 @@ const Emit = union(enum) {
290 no,303 no,
291 yes_default_path,304 yes_default_path,
292 yes: []const u8,305 yes: []const u8,
306
307 const Resolved = struct {
308 data: ?Compilation.EmitLoc,
309 dir: ?fs.Dir,
310
311 fn deinit(self: *Resolved) void {
312 if (self.dir) |*dir| {
313 dir.close();
314 }
315 }
316 };
317
318 fn resolve(emit: Emit, default_basename: []const u8) !Resolved {
319 var resolved: Resolved = .{ .data = null, .dir = null };
320 errdefer resolved.deinit();
321
322 switch (emit) {
323 .no => {},
324 .yes_default_path => {
325 resolved.data = Compilation.EmitLoc{
326 .directory = .{ .path = null, .handle = fs.cwd() },
327 .basename = default_basename,
328 };
329 },
330 .yes => |full_path| {
331 const basename = fs.path.basename(full_path);
332 if (fs.path.dirname(full_path)) |dirname| {
333 const handle = try fs.cwd().openDir(dirname, .{});
334 resolved = .{
335 .dir = handle,
336 .data = Compilation.EmitLoc{
337 .basename = basename,
338 .directory = .{
339 .path = dirname,
340 .handle = handle,
341 },
342 },
343 };
344 } else {
345 resolved.data = Compilation.EmitLoc{
346 .basename = basename,
347 .directory = .{ .path = null, .handle = fs.cwd() },
348 };
349 }
350 },
351 }
352 return resolved;
353 }
293};354};
294355
295pub fn buildOutputType(356fn buildOutputType(
296 gpa: *Allocator,357 gpa: *Allocator,
297 arena: *Allocator,358 arena: *Allocator,
298 all_args: []const []const u8,359 all_args: []const []const u8,
...@@ -328,7 +389,10 @@ pub fn buildOutputType(...@@ -328,7 +389,10 @@ pub fn buildOutputType(
328 var show_builtin = false;389 var show_builtin = false;
329 var emit_bin: Emit = .yes_default_path;390 var emit_bin: Emit = .yes_default_path;
330 var emit_asm: Emit = .no;391 var emit_asm: Emit = .no;
392 var emit_llvm_ir: Emit = .no;
331 var emit_zir: Emit = .no;393 var emit_zir: Emit = .no;
394 var emit_docs: Emit = .no;
395 var emit_analysis: Emit = .no;
332 var target_arch_os_abi: []const u8 = "native";396 var target_arch_os_abi: []const u8 = "native";
333 var target_mcpu: ?[]const u8 = null;397 var target_mcpu: ?[]const u8 = null;
334 var target_dynamic_linker: ?[]const u8 = null;398 var target_dynamic_linker: ?[]const u8 = null;
...@@ -667,6 +731,30 @@ pub fn buildOutputType(...@@ -667,6 +731,30 @@ pub fn buildOutputType(
667 emit_h = .{ .yes = arg["-femit-h=".len..] };731 emit_h = .{ .yes = arg["-femit-h=".len..] };
668 } else if (mem.eql(u8, arg, "-fno-emit-h")) {732 } else if (mem.eql(u8, arg, "-fno-emit-h")) {
669 emit_h = .no;733 emit_h = .no;
734 } else if (mem.eql(u8, arg, "-femit-asm")) {
735 emit_asm = .yes_default_path;
736 } else if (mem.startsWith(u8, arg, "-femit-asm=")) {
737 emit_asm = .{ .yes = arg["-femit-asm=".len..] };
738 } else if (mem.eql(u8, arg, "-fno-emit-asm")) {
739 emit_asm = .no;
740 } else if (mem.eql(u8, arg, "-femit-llvm-ir")) {
741 emit_llvm_ir = .yes_default_path;
742 } else if (mem.startsWith(u8, arg, "-femit-llvm-ir=")) {
743 emit_llvm_ir = .{ .yes = arg["-femit-llvm-ir=".len..] };
744 } else if (mem.eql(u8, arg, "-fno-emit-llvm-ir")) {
745 emit_llvm_ir = .no;
746 } else if (mem.eql(u8, arg, "-femit-docs")) {
747 emit_docs = .yes_default_path;
748 } else if (mem.startsWith(u8, arg, "-femit-docs=")) {
749 emit_docs = .{ .yes = arg["-femit-docs=".len..] };
750 } else if (mem.eql(u8, arg, "-fno-emit-docs")) {
751 emit_docs = .no;
752 } else if (mem.eql(u8, arg, "-femit-analysis")) {
753 emit_analysis = .yes_default_path;
754 } else if (mem.startsWith(u8, arg, "-femit-analysis=")) {
755 emit_analysis = .{ .yes = arg["-femit-analysis=".len..] };
756 } else if (mem.eql(u8, arg, "-fno-emit-analysis")) {
757 emit_analysis = .no;
670 } else if (mem.eql(u8, arg, "-dynamic")) {758 } else if (mem.eql(u8, arg, "-dynamic")) {
671 link_mode = .Dynamic;759 link_mode = .Dynamic;
672 } else if (mem.eql(u8, arg, "-static")) {760 } else if (mem.eql(u8, arg, "-static")) {
...@@ -1237,35 +1325,24 @@ pub fn buildOutputType(...@@ -1237,35 +1325,24 @@ pub fn buildOutputType(
1237 },1325 },
1238 };1326 };
12391327
1240 var cleanup_emit_h_dir: ?fs.Dir = null;1328 const default_h_basename = try std.fmt.allocPrint(arena, "{}.h", .{root_name});
1241 defer if (cleanup_emit_h_dir) |*dir| dir.close();1329 var emit_h_resolved = try emit_h.resolve(default_h_basename);
1330 defer emit_h_resolved.deinit();
12421331
1243 const emit_h_loc: ?Compilation.EmitLoc = switch (emit_h) {1332 const default_asm_basename = try std.fmt.allocPrint(arena, "{}.s", .{root_name});
1244 .no => null,1333 var emit_asm_resolved = try emit_asm.resolve(default_asm_basename);
1245 .yes_default_path => Compilation.EmitLoc{1334 defer emit_asm_resolved.deinit();
1246 .directory = .{ .path = null, .handle = fs.cwd() },1335
1247 .basename = try std.fmt.allocPrint(arena, "{}.h", .{root_name}),1336 const default_llvm_ir_basename = try std.fmt.allocPrint(arena, "{}.ll", .{root_name});
1248 },1337 var emit_llvm_ir_resolved = try emit_llvm_ir.resolve(default_llvm_ir_basename);
1249 .yes => |full_path| b: {1338 defer emit_llvm_ir_resolved.deinit();
1250 const basename = fs.path.basename(full_path);1339
1251 if (fs.path.dirname(full_path)) |dirname| {1340 const default_analysis_basename = try std.fmt.allocPrint(arena, "{}-analysis.json", .{root_name});
1252 const handle = try fs.cwd().openDir(dirname, .{});1341 var emit_analysis_resolved = try emit_analysis.resolve(default_analysis_basename);
1253 cleanup_emit_h_dir = handle;1342 defer emit_analysis_resolved.deinit();
1254 break :b Compilation.EmitLoc{1343
1255 .basename = basename,1344 var emit_docs_resolved = try emit_docs.resolve("docs");
1256 .directory = .{1345 defer emit_docs_resolved.deinit();
1257 .path = dirname,
1258 .handle = handle,
1259 },
1260 };
1261 } else {
1262 break :b Compilation.EmitLoc{
1263 .basename = basename,
1264 .directory = .{ .path = null, .handle = fs.cwd() },
1265 };
1266 }
1267 },
1268 };
12691346
1270 const zir_out_path: ?[]const u8 = switch (emit_zir) {1347 const zir_out_path: ?[]const u8 = switch (emit_zir) {
1271 .no => null,1348 .no => null,
...@@ -1365,6 +1442,12 @@ pub fn buildOutputType(...@@ -1365,6 +1442,12 @@ pub fn buildOutputType(
1365 };1442 };
1366 };1443 };
13671444
1445 if (build_options.have_llvm and emit_asm != .no) {
1446 // LLVM has no way to set this non-globally.
1447 const argv = [_][*:0]const u8{ "zig (LLVM option parsing)", "--x86-asm-syntax=intel" };
1448 @import("llvm.zig").ParseCommandLineOptions(argv.len, &argv);
1449 }
1450
1368 gimmeMoreOfThoseSweetSweetFileDescriptors();1451 gimmeMoreOfThoseSweetSweetFileDescriptors();
13691452
1370 const comp = Compilation.create(gpa, .{1453 const comp = Compilation.create(gpa, .{
...@@ -1378,7 +1461,11 @@ pub fn buildOutputType(...@@ -1378,7 +1461,11 @@ pub fn buildOutputType(
1378 .output_mode = output_mode,1461 .output_mode = output_mode,
1379 .root_pkg = root_pkg,1462 .root_pkg = root_pkg,
1380 .emit_bin = emit_bin_loc,1463 .emit_bin = emit_bin_loc,
1381 .emit_h = emit_h_loc,1464 .emit_h = emit_h_resolved.data,
1465 .emit_asm = emit_asm_resolved.data,
1466 .emit_llvm_ir = emit_llvm_ir_resolved.data,
1467 .emit_docs = emit_docs_resolved.data,
1468 .emit_analysis = emit_analysis_resolved.data,
1382 .link_mode = link_mode,1469 .link_mode = link_mode,
1383 .dll_export_fns = dll_export_fns,1470 .dll_export_fns = dll_export_fns,
1384 .object_format = object_format,1471 .object_format = object_format,
src/stage1.zig+12-7
...@@ -75,8 +75,18 @@ pub const Pkg = extern struct {...@@ -75,8 +75,18 @@ pub const Pkg = extern struct {
75pub const Module = extern struct {75pub const Module = extern struct {
76 root_name_ptr: [*]const u8,76 root_name_ptr: [*]const u8,
77 root_name_len: usize,77 root_name_len: usize,
78 output_dir_ptr: [*]const u8,78 emit_o_ptr: [*]const u8,
79 output_dir_len: usize,79 emit_o_len: usize,
80 emit_h_ptr: [*]const u8,
81 emit_h_len: usize,
82 emit_asm_ptr: [*]const u8,
83 emit_asm_len: usize,
84 emit_llvm_ir_ptr: [*]const u8,
85 emit_llvm_ir_len: usize,
86 emit_analysis_json_ptr: [*]const u8,
87 emit_analysis_json_len: usize,
88 emit_docs_ptr: [*]const u8,
89 emit_docs_len: usize,
80 builtin_zig_path_ptr: [*]const u8,90 builtin_zig_path_ptr: [*]const u8,
81 builtin_zig_path_len: usize,91 builtin_zig_path_len: usize,
82 test_filter_ptr: [*]const u8,92 test_filter_ptr: [*]const u8,
...@@ -101,11 +111,6 @@ pub const Module = extern struct {...@@ -101,11 +111,6 @@ pub const Module = extern struct {
101 enable_stack_probing: bool,111 enable_stack_probing: bool,
102 enable_time_report: bool,112 enable_time_report: bool,
103 enable_stack_report: bool,113 enable_stack_report: bool,
104 dump_analysis: bool,
105 enable_doc_generation: bool,
106 emit_bin: bool,
107 emit_asm: bool,
108 emit_llvm_ir: bool,
109 test_is_evented: bool,114 test_is_evented: bool,
110 verbose_tokenize: bool,115 verbose_tokenize: bool,
111 verbose_ast: bool,116 verbose_ast: bool,
src/stage1/all_types.hpp+3-8
...@@ -2116,12 +2116,12 @@ struct CodeGen {...@@ -2116,12 +2116,12 @@ struct CodeGen {
2116 Buf llvm_triple_str;2116 Buf llvm_triple_str;
2117 Buf global_asm;2117 Buf global_asm;
2118 Buf o_file_output_path;2118 Buf o_file_output_path;
2119 Buf h_file_output_path;
2119 Buf asm_file_output_path;2120 Buf asm_file_output_path;
2120 Buf llvm_ir_file_output_path;2121 Buf llvm_ir_file_output_path;
2122 Buf analysis_json_output_path;
2123 Buf docs_output_path;
2121 Buf *cache_dir;2124 Buf *cache_dir;
2122 // As an input parameter, mutually exclusive with enable_cache. But it gets
2123 // populated in codegen_build_and_link.
2124 Buf *output_dir;
2125 Buf *c_artifact_dir;2125 Buf *c_artifact_dir;
2126 const char **libc_include_dir_list;2126 const char **libc_include_dir_list;
2127 size_t libc_include_dir_len;2127 size_t libc_include_dir_len;
...@@ -2186,11 +2186,6 @@ struct CodeGen {...@@ -2186,11 +2186,6 @@ struct CodeGen {
2186 bool dll_export_fns;2186 bool dll_export_fns;
2187 bool have_stack_probing;2187 bool have_stack_probing;
2188 bool function_sections;2188 bool function_sections;
2189 bool enable_dump_analysis;
2190 bool enable_doc_generation;
2191 bool emit_bin;
2192 bool emit_asm;
2193 bool emit_llvm_ir;
2194 bool test_is_evented;2189 bool test_is_evented;
2195 bool valgrind_enabled;2190 bool valgrind_enabled;
21962191
src/stage1/codegen.cpp+21-54
...@@ -8243,9 +8243,9 @@ static void zig_llvm_emit_output(CodeGen *g) {...@@ -8243,9 +8243,9 @@ static void zig_llvm_emit_output(CodeGen *g) {
8243 const char *bin_filename = nullptr;8243 const char *bin_filename = nullptr;
8244 const char *llvm_ir_filename = nullptr;8244 const char *llvm_ir_filename = nullptr;
82458245
8246 if (g->emit_bin) bin_filename = buf_ptr(&g->o_file_output_path);8246 if (buf_len(&g->o_file_output_path) != 0) bin_filename = buf_ptr(&g->o_file_output_path);
8247 if (g->emit_asm) asm_filename = buf_ptr(&g->asm_file_output_path);8247 if (buf_len(&g->asm_file_output_path) != 0) asm_filename = buf_ptr(&g->asm_file_output_path);
8248 if (g->emit_llvm_ir) llvm_ir_filename = buf_ptr(&g->llvm_ir_file_output_path);8248 if (buf_len(&g->llvm_ir_file_output_path) != 0) llvm_ir_filename = buf_ptr(&g->llvm_ir_file_output_path);
82498249
8250 // Unfortunately, LLVM shits the bed when we ask for both binary and assembly. So we call the entire8250 // Unfortunately, LLVM shits the bed when we ask for both binary and assembly. So we call the entire
8251 // pipeline multiple times if this is requested.8251 // pipeline multiple times if this is requested.
...@@ -8858,8 +8858,10 @@ static Error define_builtin_compile_vars(CodeGen *g) {...@@ -8858,8 +8858,10 @@ static Error define_builtin_compile_vars(CodeGen *g) {
8858 Buf *contents;8858 Buf *contents;
8859 if (g->builtin_zig_path == nullptr) {8859 if (g->builtin_zig_path == nullptr) {
8860 // Then this is zig0 building stage2. We can make many assumptions about the compilation.8860 // Then this is zig0 building stage2. We can make many assumptions about the compilation.
8861 Buf *out_dir = buf_alloc();
8862 os_path_split(&g->o_file_output_path, out_dir, nullptr);
8861 g->builtin_zig_path = buf_alloc();8863 g->builtin_zig_path = buf_alloc();
8862 os_path_join(g->output_dir, buf_create_from_str(builtin_zig_basename), g->builtin_zig_path);8864 os_path_join(out_dir, buf_create_from_str(builtin_zig_basename), g->builtin_zig_path);
88638865
8864 Buf *resolve_paths[] = { g->builtin_zig_path, };8866 Buf *resolve_paths[] = { g->builtin_zig_path, };
8865 *g->builtin_zig_path = os_path_resolve(resolve_paths, 1);8867 *g->builtin_zig_path = os_path_resolve(resolve_paths, 1);
...@@ -8870,7 +8872,7 @@ static Error define_builtin_compile_vars(CodeGen *g) {...@@ -8870,7 +8872,7 @@ static Error define_builtin_compile_vars(CodeGen *g) {
8870 exit(1);8872 exit(1);
8871 }8873 }
88728874
8873 g->compile_var_package = new_package(buf_ptr(g->output_dir), builtin_zig_basename, "builtin");8875 g->compile_var_package = new_package(buf_ptr(out_dir), builtin_zig_basename, "builtin");
8874 } else {8876 } else {
8875 Buf *resolve_paths[] = { g->builtin_zig_path, };8877 Buf *resolve_paths[] = { g->builtin_zig_path, };
8876 *g->builtin_zig_path = os_path_resolve(resolve_paths, 1);8878 *g->builtin_zig_path = os_path_resolve(resolve_paths, 1);
...@@ -9232,33 +9234,20 @@ void codegen_add_time_event(CodeGen *g, const char *name) {...@@ -9232,33 +9234,20 @@ void codegen_add_time_event(CodeGen *g, const char *name) {
9232 g->timing_events.append({seconds, name});9234 g->timing_events.append({seconds, name});
9233}9235}
92349236
9235static void resolve_out_paths(CodeGen *g) {9237void codegen_build_object(CodeGen *g) {
9236 assert(g->output_dir != nullptr);9238 g->have_err_ret_tracing = detect_err_ret_tracing(g);
9237 assert(g->root_out_name != nullptr);
92389239
9239 if (g->emit_bin) {9240 init(g);
9240 Buf *o_basename = buf_create_from_buf(g->root_out_name);9241
9241 buf_append_str(o_basename, target_o_file_ext(g->zig_target));9242 codegen_add_time_event(g, "Semantic Analysis");
9242 os_path_join(g->output_dir, o_basename, &g->o_file_output_path);9243 const char *progress_name = "Semantic Analysis";
9243 }9244 codegen_switch_sub_prog_node(g, stage2_progress_start(g->main_progress_node,
9244 if (g->emit_asm) {9245 progress_name, strlen(progress_name), 0));
9245 Buf *asm_basename = buf_create_from_buf(g->root_out_name);
9246 const char *asm_ext = target_asm_file_ext(g->zig_target);
9247 buf_append_str(asm_basename, asm_ext);
9248 os_path_join(g->output_dir, asm_basename, &g->asm_file_output_path);
9249 }
9250 if (g->emit_llvm_ir) {
9251 Buf *llvm_ir_basename = buf_create_from_buf(g->root_out_name);
9252 const char *llvm_ir_ext = target_llvm_ir_file_ext(g->zig_target);
9253 buf_append_str(llvm_ir_basename, llvm_ir_ext);
9254 os_path_join(g->output_dir, llvm_ir_basename, &g->llvm_ir_file_output_path);
9255 }
9256}
92579246
9258static void output_type_information(CodeGen *g) {9247 gen_root_source(g);
9259 if (g->enable_dump_analysis) {9248
9260 const char *analysis_json_filename = buf_ptr(buf_sprintf("%s" OS_SEP "%s-analysis.json",9249 if (buf_len(&g->analysis_json_output_path) != 0) {
9261 buf_ptr(g->output_dir), buf_ptr(g->root_out_name)));9250 const char *analysis_json_filename = buf_ptr(&g->analysis_json_output_path);
9262 FILE *f = fopen(analysis_json_filename, "wb");9251 FILE *f = fopen(analysis_json_filename, "wb");
9263 if (f == nullptr) {9252 if (f == nullptr) {
9264 fprintf(stderr, "Unable to open '%s': %s\n", analysis_json_filename, strerror(errno));9253 fprintf(stderr, "Unable to open '%s': %s\n", analysis_json_filename, strerror(errno));
...@@ -9270,9 +9259,9 @@ static void output_type_information(CodeGen *g) {...@@ -9270,9 +9259,9 @@ static void output_type_information(CodeGen *g) {
9270 exit(1);9259 exit(1);
9271 }9260 }
9272 }9261 }
9273 if (g->enable_doc_generation) {9262 if (buf_len(&g->docs_output_path) != 0) {
9274 Error err;9263 Error err;
9275 Buf *doc_dir_path = buf_sprintf("%s" OS_SEP "docs", buf_ptr(g->output_dir));9264 Buf *doc_dir_path = &g->docs_output_path;
9276 if ((err = os_make_path(doc_dir_path))) {9265 if ((err = os_make_path(doc_dir_path))) {
9277 fprintf(stderr, "Unable to create directory %s: %s\n", buf_ptr(doc_dir_path), err_str(err));9266 fprintf(stderr, "Unable to create directory %s: %s\n", buf_ptr(doc_dir_path), err_str(err));
9278 exit(1);9267 exit(1);
...@@ -9308,27 +9297,6 @@ static void output_type_information(CodeGen *g) {...@@ -9308,27 +9297,6 @@ static void output_type_information(CodeGen *g) {
9308 exit(1);9297 exit(1);
9309 }9298 }
9310 }9299 }
9311}
9312
9313void codegen_build_object(CodeGen *g) {
9314 assert(g->output_dir != nullptr);
9315
9316 g->have_err_ret_tracing = detect_err_ret_tracing(g);
9317
9318 init(g);
9319
9320 codegen_add_time_event(g, "Semantic Analysis");
9321 const char *progress_name = "Semantic Analysis";
9322 codegen_switch_sub_prog_node(g, stage2_progress_start(g->main_progress_node,
9323 progress_name, strlen(progress_name), 0));
9324
9325 gen_root_source(g);
9326
9327 resolve_out_paths(g);
9328
9329 if (g->enable_dump_analysis || g->enable_doc_generation) {
9330 output_type_information(g);
9331 }
93329300
9333 codegen_add_time_event(g, "Code Generation");9301 codegen_add_time_event(g, "Code Generation");
9334 {9302 {
...@@ -9379,7 +9347,6 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget...@@ -9379,7 +9347,6 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget
9379 bool is_test_build)9347 bool is_test_build)
9380{9348{
9381 CodeGen *g = heap::c_allocator.create<CodeGen>();9349 CodeGen *g = heap::c_allocator.create<CodeGen>();
9382 g->emit_bin = true;
9383 g->pass1_arena = heap::ArenaAllocator::construct(&heap::c_allocator, &heap::c_allocator, "pass1");9350 g->pass1_arena = heap::ArenaAllocator::construct(&heap::c_allocator, &heap::c_allocator, "pass1");
93849351
9385 g->subsystem = TargetSubsystemAuto;9352 g->subsystem = TargetSubsystemAuto;
src/stage1/stage1.cpp+7-6
...@@ -69,7 +69,13 @@ void zig_stage1_build_object(struct ZigStage1 *stage1) {...@@ -69,7 +69,13 @@ void zig_stage1_build_object(struct ZigStage1 *stage1) {
69 CodeGen *g = reinterpret_cast<CodeGen *>(stage1);69 CodeGen *g = reinterpret_cast<CodeGen *>(stage1);
7070
71 g->root_out_name = buf_create_from_mem(stage1->root_name_ptr, stage1->root_name_len);71 g->root_out_name = buf_create_from_mem(stage1->root_name_ptr, stage1->root_name_len);
72 g->output_dir = buf_create_from_mem(stage1->output_dir_ptr, stage1->output_dir_len);72 buf_init_from_mem(&g->o_file_output_path, stage1->emit_o_ptr, stage1->emit_o_len);
73 buf_init_from_mem(&g->h_file_output_path, stage1->emit_h_ptr, stage1->emit_h_len);
74 buf_init_from_mem(&g->asm_file_output_path, stage1->emit_asm_ptr, stage1->emit_asm_len);
75 buf_init_from_mem(&g->llvm_ir_file_output_path, stage1->emit_llvm_ir_ptr, stage1->emit_llvm_ir_len);
76 buf_init_from_mem(&g->analysis_json_output_path, stage1->emit_analysis_json_ptr, stage1->emit_analysis_json_len);
77 buf_init_from_mem(&g->docs_output_path, stage1->emit_docs_ptr, stage1->emit_docs_len);
78
73 if (stage1->builtin_zig_path_len != 0) {79 if (stage1->builtin_zig_path_len != 0) {
74 g->builtin_zig_path = buf_create_from_mem(stage1->builtin_zig_path_ptr, stage1->builtin_zig_path_len);80 g->builtin_zig_path = buf_create_from_mem(stage1->builtin_zig_path_ptr, stage1->builtin_zig_path_len);
75 }81 }
...@@ -94,11 +100,6 @@ void zig_stage1_build_object(struct ZigStage1 *stage1) {...@@ -94,11 +100,6 @@ void zig_stage1_build_object(struct ZigStage1 *stage1) {
94100
95 g->enable_time_report = stage1->enable_time_report;101 g->enable_time_report = stage1->enable_time_report;
96 g->enable_stack_report = stage1->enable_stack_report;102 g->enable_stack_report = stage1->enable_stack_report;
97 g->enable_dump_analysis = stage1->dump_analysis;
98 g->enable_doc_generation = stage1->enable_doc_generation;
99 g->emit_bin = stage1->emit_bin;
100 g->emit_asm = stage1->emit_asm;
101 g->emit_llvm_ir = stage1->emit_llvm_ir;
102 g->test_is_evented = stage1->test_is_evented;103 g->test_is_evented = stage1->test_is_evented;
103104
104 g->verbose_tokenize = stage1->verbose_tokenize;105 g->verbose_tokenize = stage1->verbose_tokenize;
src/stage1/stage1.h+17-7
...@@ -141,8 +141,23 @@ struct ZigStage1 {...@@ -141,8 +141,23 @@ struct ZigStage1 {
141 const char *root_name_ptr;141 const char *root_name_ptr;
142 size_t root_name_len;142 size_t root_name_len;
143143
144 const char *output_dir_ptr;144 const char *emit_o_ptr;
145 size_t output_dir_len;145 size_t emit_o_len;
146
147 const char *emit_h_ptr;
148 size_t emit_h_len;
149
150 const char *emit_asm_ptr;
151 size_t emit_asm_len;
152
153 const char *emit_llvm_ir_ptr;
154 size_t emit_llvm_ir_len;
155
156 const char *emit_analysis_json_ptr;
157 size_t emit_analysis_json_len;
158
159 const char *emit_docs_ptr;
160 size_t emit_docs_len;
146161
147 const char *builtin_zig_path_ptr;162 const char *builtin_zig_path_ptr;
148 size_t builtin_zig_path_len;163 size_t builtin_zig_path_len;
...@@ -173,11 +188,6 @@ struct ZigStage1 {...@@ -173,11 +188,6 @@ struct ZigStage1 {
173 bool enable_stack_probing;188 bool enable_stack_probing;
174 bool enable_time_report;189 bool enable_time_report;
175 bool enable_stack_report;190 bool enable_stack_report;
176 bool dump_analysis;
177 bool enable_doc_generation;
178 bool emit_bin;
179 bool emit_asm;
180 bool emit_llvm_ir;
181 bool test_is_evented;191 bool test_is_evented;
182 bool verbose_tokenize;192 bool verbose_tokenize;
183 bool verbose_ast;193 bool verbose_ast;
src/stage1/zig0.cpp+6-7
...@@ -241,7 +241,7 @@ int main(int argc, char **argv) {...@@ -241,7 +241,7 @@ int main(int argc, char **argv) {
241 Error err;241 Error err;
242242
243 const char *in_file = nullptr;243 const char *in_file = nullptr;
244 const char *output_dir = nullptr;244 const char *emit_bin_path = nullptr;
245 bool strip = false;245 bool strip = false;
246 const char *out_name = nullptr;246 const char *out_name = nullptr;
247 bool verbose_tokenize = false;247 bool verbose_tokenize = false;
...@@ -324,14 +324,14 @@ int main(int argc, char **argv) {...@@ -324,14 +324,14 @@ int main(int argc, char **argv) {
324 cur_pkg = cur_pkg->parent;324 cur_pkg = cur_pkg->parent;
325 } else if (str_starts_with(arg, "-mcpu=")) {325 } else if (str_starts_with(arg, "-mcpu=")) {
326 mcpu = arg + strlen("-mcpu=");326 mcpu = arg + strlen("-mcpu=");
327 } else if (str_starts_with(arg, "-femit-bin=")) {
328 emit_bin_path = arg + strlen("-femit-bin=");
327 } else if (i + 1 >= argc) {329 } else if (i + 1 >= argc) {
328 fprintf(stderr, "Expected another argument after %s\n", arg);330 fprintf(stderr, "Expected another argument after %s\n", arg);
329 return print_error_usage(arg0);331 return print_error_usage(arg0);
330 } else {332 } else {
331 i += 1;333 i += 1;
332 if (strcmp(arg, "--output-dir") == 0) {334 if (strcmp(arg, "--color") == 0) {
333 output_dir = argv[i];
334 } else if (strcmp(arg, "--color") == 0) {
335 if (strcmp(argv[i], "auto") == 0) {335 if (strcmp(argv[i], "auto") == 0) {
336 color = ErrColorAuto;336 color = ErrColorAuto;
337 } else if (strcmp(argv[i], "on") == 0) {337 } else if (strcmp(argv[i], "on") == 0) {
...@@ -443,15 +443,14 @@ int main(int argc, char **argv) {...@@ -443,15 +443,14 @@ int main(int argc, char **argv) {
443 stage1->verbose_llvm_ir = verbose_llvm_ir;443 stage1->verbose_llvm_ir = verbose_llvm_ir;
444 stage1->verbose_cimport = verbose_cimport;444 stage1->verbose_cimport = verbose_cimport;
445 stage1->verbose_llvm_cpu_features = verbose_llvm_cpu_features;445 stage1->verbose_llvm_cpu_features = verbose_llvm_cpu_features;
446 stage1->output_dir_ptr = output_dir;446 stage1->emit_o_ptr = emit_bin_path;
447 stage1->output_dir_len = strlen(output_dir);447 stage1->emit_o_len = strlen(emit_bin_path);
448 stage1->root_pkg = cur_pkg;448 stage1->root_pkg = cur_pkg;
449 stage1->err_color = color;449 stage1->err_color = color;
450 stage1->link_libc = link_libc;450 stage1->link_libc = link_libc;
451 stage1->link_libcpp = link_libcpp;451 stage1->link_libcpp = link_libcpp;
452 stage1->subsystem = subsystem;452 stage1->subsystem = subsystem;
453 stage1->pic = true;453 stage1->pic = true;
454 stage1->emit_bin = true;
455454
456 zig_stage1_build_object(stage1);455 zig_stage1_build_object(stage1);
457456
test/cli.zig+11-8
...@@ -118,17 +118,20 @@ fn testGodboltApi(zig_exe: []const u8, dir_path: []const u8) anyerror!void {...@@ -118,17 +118,20 @@ fn testGodboltApi(zig_exe: []const u8, dir_path: []const u8) anyerror!void {
118 \\}118 \\}
119 );119 );
120120
121 const args = [_][]const u8{121 var args = std.ArrayList([]const u8).init(a);
122 try args.appendSlice(&[_][]const u8{
122 zig_exe, "build-obj",123 zig_exe, "build-obj",
123 "--cache-dir", dir_path,124 "--cache-dir", dir_path,
124 "--name", "example",125 "--name", "example",
125 "--output-dir", dir_path,126 "-fno-emit-bin", "-fno-emit-h",
126 "--emit", "asm",127 "--strip", "-OReleaseFast",
127 "-mllvm", "--x86-asm-syntax=intel",128 example_zig_path,
128 "--strip", "--release-fast",129 });
129 example_zig_path, "--disable-gen-h",130
130 };131 const emit_asm_arg = try std.fmt.allocPrint(a, "-femit-asm={s}", .{example_s_path});
131 _ = try exec(dir_path, &args);132 try args.append(emit_asm_arg);
133
134 _ = try exec(dir_path, args.items);
132135
133 const out_asm = try std.fs.cwd().readFileAlloc(a, example_s_path, std.math.maxInt(usize));136 const out_asm = try std.fs.cwd().readFileAlloc(a, example_s_path, std.math.maxInt(usize));
134 testing.expect(std.mem.indexOf(u8, out_asm, "square:") != null);137 testing.expect(std.mem.indexOf(u8, out_asm, "square:") != null);