authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-18 22:48:28-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-18 22:48:28-07:00
log2ef68631cb7045c277b348777b1a064845b95cd8
tree00e1dca9b53a828a9926cf5b6d2a227dc939375a
parent333b12a8f9beb5864fa05ce413c5b935e925ec14

stage2 now supports using stage1 as a backend for compiling zig code

* move stage2.cpp code into zig0.cpp for simplicity * add -ftime-report and some more CLI options to stage2 * stage2 compites the llvm cpu features string * classifyFileExt understands more file extensions * correction to generateBuiltinZigSource using the wrong allocator (thanks dbandstra!) * stage2 is now able to build hello.zig into hello.o using stage1 as a library however it fails linking due to missing compiler-rt * remove dead code * simplify zig0 builtin.zig source * fix not resolving builtin.zig source path causing duplicate imports * fix stage1.h not being valid C code * fix stage2.h not being valid C code

17 files changed, 750 insertions(+), 678 deletions(-)

BRANCH_TODO+5-3
......@@ -1,3 +1,6 @@
1 * build & link against compiler-rt
2 * build & link against freestanding libc
3 * Cache integration for stage1 zig code compilation
14 * `zig test`
25 * `zig build`
36 * `-ftime-report`
......@@ -14,10 +17,7 @@
1417 - using it as a preprocessor (-E)
1518 - try building some software
1619 * support rpaths in ELF linker code
17 * build & link against compiler-rt
18 - stage1 C++ code integration
1920 * repair @cImport
20 * build & link against freestanding libc
2121 * add CLI support for a way to pass extra flags to c source files
2222 * capture lld stdout/stderr better
2323 * musl
......@@ -35,10 +35,12 @@
3535 * implement emit-h in stage2
3636 * implement -fno-emit-bin
3737 * audit the base cache hash
38 * --main-pkg-path
3839 * audit the CLI options for stage2
3940 * `zig init-lib`
4041 * `zig init-exe`
4142 * `zig run`
43 * restore error messages for stage2_add_link_lib
4244
4345 * implement serialization/deserialization of incremental compilation metadata
4446 * incremental compilation - implement detection of which source files changed
CMakeLists.txt-1
......@@ -258,7 +258,6 @@ find_package(Threads)
258258# This is our shim which will be replaced by stage1.zig.
259259set(ZIG0_SOURCES
260260 "${CMAKE_SOURCE_DIR}/src/zig0.cpp"
261 "${CMAKE_SOURCE_DIR}/src/stage2.cpp"
262261)
263262
264263set(ZIG_SOURCES
src-self-hosted/Compilation.zig+222-25
......@@ -19,6 +19,7 @@ const libunwind = @import("libunwind.zig");
1919const fatal = @import("main.zig").fatal;
2020const Module = @import("Module.zig");
2121const Cache = @import("Cache.zig");
22const stage1 = @import("stage1.zig");
2223
2324/// General-purpose allocator. Used for both temporary and long-term storage.
2425gpa: *Allocator,
......@@ -26,6 +27,7 @@ gpa: *Allocator,
2627arena_state: std.heap.ArenaAllocator.State,
2728bin_file: *link.File,
2829c_object_table: std.AutoArrayHashMapUnmanaged(*CObject, void) = .{},
30stage1_module: ?*stage1.Module,
2931
3032link_error_flags: link.File.ErrorFlags = .{},
3133
......@@ -122,6 +124,8 @@ const Job = union(enum) {
122124
123125 /// Generate builtin.zig source code and write it into the correct place.
124126 generate_builtin_zig: void,
127 /// Use stage1 C++ code to compile zig code into an object file.
128 stage1_module: void,
125129};
126130
127131pub const CObject = struct {
......@@ -274,6 +278,7 @@ pub const InitOptions = struct {
274278 strip: bool = false,
275279 single_threaded: bool = false,
276280 is_native_os: bool,
281 time_report: bool = false,
277282 link_eh_frame_hdr: bool = false,
278283 linker_script: ?[]const u8 = null,
279284 version_script: ?[]const u8 = null,
......@@ -288,12 +293,20 @@ pub const InitOptions = struct {
288293 clang_passthrough_mode: bool = false,
289294 verbose_cc: bool = false,
290295 verbose_link: bool = false,
296 verbose_tokenize: bool = false,
297 verbose_ast: bool = false,
298 verbose_ir: bool = false,
299 verbose_llvm_ir: bool = false,
300 verbose_cimport: bool = false,
301 verbose_llvm_cpu_features: bool = false,
291302 is_test: bool = false,
292303 stack_size_override: ?u64 = null,
293304 self_exe_path: ?[]const u8 = null,
294305 version: ?std.builtin.Version = null,
295306 libc_installation: ?*const LibCInstallation = null,
296307 machine_code_model: std.builtin.CodeModel = .default,
308 /// This is for stage1 and should be deleted upon completion of self-hosting.
309 color: @import("main.zig").Color = .Auto,
297310};
298311
299312pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
......@@ -332,11 +345,27 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
332345 {
333346 break :blk true;
334347 }
348
349 if (build_options.is_stage1) {
350 // If stage1 generates an object file, self-hosted linker is not
351 // yet sophisticated enough to handle that.
352 break :blk options.root_pkg != null;
353 }
354
335355 break :blk false;
336356 };
337357
338358 // Make a decision on whether to use LLVM or our own backend.
339359 const use_llvm = if (options.use_llvm) |explicit| explicit else blk: {
360 // If we have no zig code to compile, no need for LLVM.
361 if (options.root_pkg == null)
362 break :blk false;
363
364 // If we are the stage1 compiler, we depend on the stage1 c++ llvm backend
365 // to compile zig code.
366 if (build_options.is_stage1)
367 break :blk true;
368
340369 // We would want to prefer LLVM for release builds when it is available, however
341370 // we don't have an LLVM backend yet :)
342371 // We would also want to prefer LLVM for architectures that we don't have self-hosted support for too.
......@@ -580,6 +609,118 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
580609 .ReleaseFast, .ReleaseSmall => false,
581610 };
582611
612 const llvm_cpu_features: ?[*:0]const u8 = if (build_options.have_llvm and use_llvm) blk: {
613 var buf = std.ArrayList(u8).init(arena);
614 for (options.target.cpu.arch.allFeaturesList()) |feature, index_usize| {
615 const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize);
616 const is_enabled = options.target.cpu.features.isEnabled(index);
617
618 if (feature.llvm_name) |llvm_name| {
619 const plus_or_minus = "-+"[@boolToInt(is_enabled)];
620 try buf.ensureCapacity(buf.items.len + 2 + llvm_name.len);
621 buf.appendAssumeCapacity(plus_or_minus);
622 buf.appendSliceAssumeCapacity(llvm_name);
623 buf.appendSliceAssumeCapacity(",");
624 }
625 }
626 assert(mem.endsWith(u8, buf.items, ","));
627 buf.items[buf.items.len - 1] = 0;
628 buf.shrink(buf.items.len);
629 break :blk buf.items[0 .. buf.items.len - 1 :0].ptr;
630 } else null;
631
632 const stage1_module: ?*stage1.Module = if (build_options.is_stage1 and use_llvm) blk: {
633 // Here we use the legacy stage1 C++ compiler to compile Zig code.
634 const stage2_target = try arena.create(stage1.Stage2Target);
635 stage2_target.* = .{
636 .arch = @enumToInt(options.target.cpu.arch) + 1, // skip over ZigLLVM_UnknownArch
637 .os = @enumToInt(options.target.os.tag),
638 .abi = @enumToInt(options.target.abi),
639 .is_native_os = options.is_native_os,
640 .is_native_cpu = false, // Only true when bootstrapping the compiler.
641 .llvm_cpu_name = if (options.target.cpu.model.llvm_name) |s| s.ptr else null,
642 .llvm_cpu_features = llvm_cpu_features.?,
643 };
644 const progress = try arena.create(std.Progress);
645 const main_progress_node = try progress.start("", 100);
646 if (options.color == .Off) progress.terminal = null;
647
648 const mod = module.?;
649 const main_zig_file = mod.root_pkg.root_src_path;
650 const zig_lib_dir = options.zig_lib_directory.path.?;
651 const builtin_sub = &[_][]const u8{"builtin.zig"};
652 const builtin_zig_path = try mod.zig_cache_artifact_directory.join(arena, builtin_sub);
653
654 const stage1_module = stage1.create(
655 @enumToInt(options.optimize_mode),
656 undefined,
657 0, // TODO --main-pkg-path
658 main_zig_file.ptr,
659 main_zig_file.len,
660 zig_lib_dir.ptr,
661 zig_lib_dir.len,
662 stage2_target,
663 options.is_test,
664 ) orelse return error.OutOfMemory;
665
666 const output_dir = bin_directory.path orelse ".";
667
668 const stage1_pkg = try arena.create(stage1.Pkg);
669 stage1_pkg.* = .{
670 .name_ptr = undefined,
671 .name_len = 0,
672 .path_ptr = undefined,
673 .path_len = 0,
674 .children_ptr = undefined,
675 .children_len = 0,
676 .parent = null,
677 };
678
679 stage1_module.* = .{
680 .root_name_ptr = root_name.ptr,
681 .root_name_len = root_name.len,
682 .output_dir_ptr = output_dir.ptr,
683 .output_dir_len = output_dir.len,
684 .builtin_zig_path_ptr = builtin_zig_path.ptr,
685 .builtin_zig_path_len = builtin_zig_path.len,
686 .test_filter_ptr = "",
687 .test_filter_len = 0,
688 .test_name_prefix_ptr = "",
689 .test_name_prefix_len = 0,
690 .userdata = @ptrToInt(comp),
691 .root_pkg = stage1_pkg,
692 .code_model = @enumToInt(options.machine_code_model),
693 .subsystem = stage1.TargetSubsystem.Auto,
694 .err_color = @enumToInt(options.color),
695 .pic = pic,
696 .link_libc = options.link_libc,
697 .link_libcpp = options.link_libcpp,
698 .strip = options.strip,
699 .is_single_threaded = single_threaded,
700 .dll_export_fns = dll_export_fns,
701 .link_mode_dynamic = link_mode == .Dynamic,
702 .valgrind_enabled = valgrind,
703 .function_sections = options.function_sections orelse false,
704 .enable_stack_probing = stack_check,
705 .enable_time_report = options.time_report,
706 .enable_stack_report = false,
707 .dump_analysis = false,
708 .enable_doc_generation = false,
709 .emit_bin = true,
710 .emit_asm = false,
711 .emit_llvm_ir = false,
712 .test_is_evented = false,
713 .verbose_tokenize = options.verbose_tokenize,
714 .verbose_ast = options.verbose_ast,
715 .verbose_ir = options.verbose_ir,
716 .verbose_llvm_ir = options.verbose_llvm_ir,
717 .verbose_cimport = options.verbose_cimport,
718 .verbose_llvm_cpu_features = options.verbose_llvm_cpu_features,
719 .main_progress_node = main_progress_node,
720 };
721 break :blk stage1_module;
722 } else null;
723
583724 const bin_file = try link.File.openPath(gpa, .{
584725 .directory = bin_directory,
585726 .sub_path = emit_bin.basename,
......@@ -626,6 +767,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
626767 .machine_code_model = options.machine_code_model,
627768 .dll_export_fns = dll_export_fns,
628769 .error_return_tracing = error_return_tracing,
770 .llvm_cpu_features = llvm_cpu_features,
629771 });
630772 errdefer bin_file.destroy();
631773
......@@ -635,6 +777,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
635777 .zig_lib_directory = options.zig_lib_directory,
636778 .zig_cache_directory = options.zig_cache_directory,
637779 .bin_file = bin_file,
780 .stage1_module = stage1_module,
638781 .work_queue = std.fifo.LinearFifo(Job, .Dynamic).init(gpa),
639782 .keep_source_files_loaded = options.keep_source_files_loaded,
640783 .use_clang = use_clang,
......@@ -681,6 +824,10 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
681824 try comp.work_queue.writeItem(.{ .libunwind = {} });
682825 }
683826
827 if (comp.stage1_module) |module| {
828 try comp.work_queue.writeItem(.{ .stage1_module = {} });
829 }
830
684831 return comp;
685832}
686833
......@@ -689,6 +836,11 @@ pub fn destroy(self: *Compilation) void {
689836 self.bin_file.destroy();
690837 if (optional_module) |module| module.deinit();
691838
839 if (self.stage1_module) |module| {
840 module.main_progress_node.?.end();
841 module.destroy();
842 }
843
692844 const gpa = self.gpa;
693845 self.work_queue.deinit();
694846
......@@ -997,6 +1149,10 @@ pub fn performAllTheWork(self: *Compilation) error{OutOfMemory}!void {
9971149 fatal("unable to update builtin.zig file: {}", .{@errorName(err)});
9981150 };
9991151 },
1152 .stage1_module => {
1153 // This Job is only queued up if there is a zig module.
1154 self.stage1_module.?.build_object();
1155 },
10001156 };
10011157}
10021158
......@@ -1365,7 +1521,7 @@ pub fn addCCArgs(
13651521 try argv.append("-fPIC");
13661522 }
13671523 },
1368 .so, .assembly, .ll, .bc, .unknown => {},
1524 .shared_library, .assembly, .ll, .bc, .unknown, .static_library, .object, .zig, .zir => {},
13691525 }
13701526 if (out_dep_path) |p| {
13711527 try argv.appendSlice(&[_][]const u8{ "-MD", "-MV", "-MF", p });
......@@ -1445,17 +1601,39 @@ pub const FileExt = enum {
14451601 ll,
14461602 bc,
14471603 assembly,
1448 so,
1604 shared_library,
1605 object,
1606 static_library,
1607 zig,
1608 zir,
14491609 unknown,
14501610
14511611 pub fn clangSupportsDepFile(ext: FileExt) bool {
14521612 return switch (ext) {
14531613 .c, .cpp, .h => true,
1454 .ll, .bc, .assembly, .so, .unknown => false,
1614
1615 .ll,
1616 .bc,
1617 .assembly,
1618 .shared_library,
1619 .object,
1620 .static_library,
1621 .zig,
1622 .zir,
1623 .unknown,
1624 => false,
14551625 };
14561626 }
14571627};
14581628
1629pub fn hasObjectExt(filename: []const u8) bool {
1630 return mem.endsWith(u8, filename, ".o") or mem.endsWith(u8, filename, ".obj");
1631}
1632
1633pub fn hasStaticLibraryExt(filename: []const u8) bool {
1634 return mem.endsWith(u8, filename, ".a") or mem.endsWith(u8, filename, ".lib");
1635}
1636
14591637pub fn hasCExt(filename: []const u8) bool {
14601638 return mem.endsWith(u8, filename, ".c");
14611639}
......@@ -1471,6 +1649,32 @@ pub fn hasAsmExt(filename: []const u8) bool {
14711649 return mem.endsWith(u8, filename, ".s") or mem.endsWith(u8, filename, ".S");
14721650}
14731651
1652pub fn hasSharedLibraryExt(filename: []const u8) bool {
1653 if (mem.endsWith(u8, filename, ".so") or
1654 mem.endsWith(u8, filename, ".dll") or
1655 mem.endsWith(u8, filename, ".dylib"))
1656 {
1657 return true;
1658 }
1659 // Look for .so.X, .so.X.Y, .so.X.Y.Z
1660 var it = mem.split(filename, ".");
1661 _ = it.next().?;
1662 var so_txt = it.next() orelse return false;
1663 while (!mem.eql(u8, so_txt, "so")) {
1664 so_txt = it.next() orelse return false;
1665 }
1666 const n1 = it.next() orelse return false;
1667 const n2 = it.next();
1668 const n3 = it.next();
1669
1670 _ = std.fmt.parseInt(u32, n1, 10) catch return false;
1671 if (n2) |x| _ = std.fmt.parseInt(u32, x, 10) catch return false;
1672 if (n3) |x| _ = std.fmt.parseInt(u32, x, 10) catch return false;
1673 if (it.next() != null) return false;
1674
1675 return true;
1676}
1677
14741678pub fn classifyFileExt(filename: []const u8) FileExt {
14751679 if (hasCExt(filename)) {
14761680 return .c;
......@@ -1484,26 +1688,19 @@ pub fn classifyFileExt(filename: []const u8) FileExt {
14841688 return .assembly;
14851689 } else if (mem.endsWith(u8, filename, ".h")) {
14861690 return .h;
1487 } else if (mem.endsWith(u8, filename, ".so")) {
1488 return .so;
1489 }
1490 // Look for .so.X, .so.X.Y, .so.X.Y.Z
1491 var it = mem.split(filename, ".");
1492 _ = it.next().?;
1493 var so_txt = it.next() orelse return .unknown;
1494 while (!mem.eql(u8, so_txt, "so")) {
1495 so_txt = it.next() orelse return .unknown;
1691 } else if (mem.endsWith(u8, filename, ".zig")) {
1692 return .zig;
1693 } else if (mem.endsWith(u8, filename, ".zir")) {
1694 return .zig;
1695 } else if (hasSharedLibraryExt(filename)) {
1696 return .shared_library;
1697 } else if (hasStaticLibraryExt(filename)) {
1698 return .static_library;
1699 } else if (hasObjectExt(filename)) {
1700 return .object;
1701 } else {
1702 return .unknown;
14961703 }
1497 const n1 = it.next() orelse return .unknown;
1498 const n2 = it.next();
1499 const n3 = it.next();
1500
1501 _ = std.fmt.parseInt(u32, n1, 10) catch return .unknown;
1502 if (n2) |x| _ = std.fmt.parseInt(u32, x, 10) catch return .unknown;
1503 if (n3) |x| _ = std.fmt.parseInt(u32, x, 10) catch return .unknown;
1504 if (it.next() != null) return .unknown;
1505
1506 return .so;
15071704}
15081705
15091706test "classifyFileExt" {
......@@ -1681,7 +1878,7 @@ pub fn dump_argv(argv: []const []const u8) void {
16811878}
16821879
16831880pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8 {
1684 var buffer = std.ArrayList(u8).init(comp.gpa);
1881 var buffer = std.ArrayList(u8).init(allocator);
16851882 defer buffer.deinit();
16861883
16871884 const target = comp.getTarget();
......@@ -1691,9 +1888,9 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8
16911888 try buffer.writer().print(
16921889 \\usingnamespace @import("std").builtin;
16931890 \\/// Deprecated
1694 \\pub const arch = std.Target.current.cpu.arch;
1891 \\pub const arch = Target.current.cpu.arch;
16951892 \\/// Deprecated
1696 \\pub const endian = std.Target.current.cpu.arch.endian();
1893 \\pub const endian = Target.current.cpu.arch.endian();
16971894 \\pub const output_mode = OutputMode.{};
16981895 \\pub const link_mode = LinkMode.{};
16991896 \\pub const is_test = {};
src-self-hosted/link.zig+13
......@@ -69,6 +69,7 @@ pub const Options = struct {
6969 linker_script: ?[]const u8 = null,
7070 version_script: ?[]const u8 = null,
7171 override_soname: ?[]const u8 = null,
72 llvm_cpu_features: ?[*:0]const u8 = null,
7273 /// Extra args passed directly to LLD. Ignored when not linking with LLD.
7374 extra_lld_args: []const []const u8 = &[0][]const u8,
7475
......@@ -134,6 +135,18 @@ pub const File = struct {
134135 /// rewriting it. A malicious file is detected as incremental link failure
135136 /// and does not cause Illegal Behavior. This operation is not atomic.
136137 pub fn openPath(allocator: *Allocator, options: Options) !*File {
138 const use_stage1 = build_options.is_stage1 and options.use_llvm;
139 if (use_stage1) {
140 return switch (options.object_format) {
141 .coff, .pe => &(try Coff.createEmpty(allocator, options)).base,
142 .elf => &(try Elf.createEmpty(allocator, options)).base,
143 .macho => &(try MachO.createEmpty(allocator, options)).base,
144 .wasm => &(try Wasm.createEmpty(allocator, options)).base,
145 .c => unreachable, // Reported error earlier.
146 .hex => return error.HexObjectFormatUnimplemented,
147 .raw => return error.RawObjectFormatUnimplemented,
148 };
149 }
137150 const use_lld = build_options.have_llvm and options.use_lld; // comptime known false when !have_llvm
138151 const sub_path = if (use_lld) blk: {
139152 if (options.module == null) {
src-self-hosted/link/Elf.zig+9-6
......@@ -1222,13 +1222,16 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
12221222 // If there is no Zig code to compile, then we should skip flushing the output file because it
12231223 // will not be part of the linker line anyway.
12241224 const module_obj_path: ?[]const u8 = if (self.base.options.module) |module| blk: {
1225 try self.flushModule(comp);
1225 const use_stage1 = build_options.is_stage1 and self.base.options.use_llvm;
1226 if (use_stage1) {
1227 const obj_basename = try std.fmt.allocPrint(arena, "{}.o", .{self.base.options.root_name});
1228 const full_obj_path = try directory.join(arena, &[_][]const u8{obj_basename});
1229 break :blk full_obj_path;
1230 }
12261231
1232 try self.flushModule(comp);
12271233 const obj_basename = self.base.intermediary_basename.?;
1228 const full_obj_path = if (directory.path) |dir_path|
1229 try std.fs.path.join(arena, &[_][]const u8{dir_path, obj_basename})
1230 else
1231 obj_basename;
1234 const full_obj_path = try directory.join(arena, &[_][]const u8{obj_basename});
12321235 break :blk full_obj_path;
12331236 } else null;
12341237
......@@ -1504,7 +1507,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
15041507 // (the check for that needs to be earlier), but they could be full paths to .so files, in which
15051508 // case we want to avoid prepending "-l".
15061509 const ext = Compilation.classifyFileExt(link_lib);
1507 const arg = if (ext == .so) link_lib else try std.fmt.allocPrint(arena, "-l{}", .{link_lib});
1510 const arg = if (ext == .shared_library) link_lib else try std.fmt.allocPrint(arena, "-l{}", .{link_lib});
15081511 argv.appendAssumeCapacity(arg);
15091512 }
15101513
src-self-hosted/main.zig+79-35
......@@ -222,21 +222,27 @@ const usage_build_generic =
222222 \\ --libc [file] Provide a file which specifies libc paths
223223 \\
224224 \\Link Options:
225 \\ -l[lib], --library [lib] Link against system library
225 \\ -l[lib], --library [lib] Link against system library
226226 \\ -L[d], --library-directory [d] Add a directory to the library search path
227 \\ -T[script] Use a custom linker script
228 \\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so)
229 \\ --version [ver] Dynamic library semver
230 \\ -rdynamic Add all symbols to the dynamic symbol table
231 \\ -rpath [path] Add directory to the runtime library search path
232 \\ --eh-frame-hdr Enable C++ exception handling by passing --eh-frame-hdr to linker
233 \\ -dynamic Force output to be dynamically linked
234 \\ -static Force output to be statically linked
227 \\ -T[script] Use a custom linker script
228 \\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so)
229 \\ --version [ver] Dynamic library semver
230 \\ -rdynamic Add all symbols to the dynamic symbol table
231 \\ -rpath [path] Add directory to the runtime library search path
232 \\ --eh-frame-hdr Enable C++ exception handling by passing --eh-frame-hdr to linker
233 \\ -dynamic Force output to be dynamically linked
234 \\ -static Force output to be statically linked
235235 \\
236236 \\Debug Options (Zig Compiler Development):
237 \\ -ftime-report Print timing diagnostics
238 \\ --verbose-link Display linker invocations
239 \\ --verbose-cc Display C compiler invocations
237 \\ -ftime-report Print timing diagnostics
238 \\ --verbose-link Display linker invocations
239 \\ --verbose-cc Display C compiler invocations
240 \\ --verbose-tokenize Enable compiler debug output for tokenization
241 \\ --verbose-ast Enable compiler debug output for AST parsing
242 \\ --verbose-ir Enable compiler debug output for Zig IR
243 \\ --verbose-llvm-ir Enable compiler debug output for LLVM IR
244 \\ --verbose-cimport Enable compiler debug output for C imports
245 \\ --verbose-llvm-cpu-features Enable compiler debug output for LLVM CPU features
240246 \\
241247;
242248
......@@ -278,6 +284,12 @@ pub fn buildOutputType(
278284 var watch = false;
279285 var verbose_link = false;
280286 var verbose_cc = false;
287 var verbose_tokenize = false;
288 var verbose_ast = false;
289 var verbose_ir = false;
290 var verbose_llvm_ir = false;
291 var verbose_cimport = false;
292 var verbose_llvm_cpu_features = false;
281293 var time_report = false;
282294 var show_builtin = false;
283295 var emit_bin: Emit = .yes_default_path;
......@@ -548,6 +560,18 @@ pub fn buildOutputType(
548560 verbose_link = true;
549561 } else if (mem.eql(u8, arg, "--verbose-cc")) {
550562 verbose_cc = true;
563 } else if (mem.eql(u8, arg, "--verbose-tokenize")) {
564 verbose_tokenize = true;
565 } else if (mem.eql(u8, arg, "--verbose-ast")) {
566 verbose_ast = true;
567 } else if (mem.eql(u8, arg, "--verbose-ir")) {
568 verbose_ir = true;
569 } else if (mem.eql(u8, arg, "--verbose-llvm-ir")) {
570 verbose_llvm_ir = true;
571 } else if (mem.eql(u8, arg, "--verbose-cimport")) {
572 verbose_cimport = true;
573 } else if (mem.eql(u8, arg, "--verbose-llvm-cpu-features")) {
574 verbose_llvm_cpu_features = true;
551575 } else if (mem.startsWith(u8, arg, "-T")) {
552576 linker_script = arg[2..];
553577 } else if (mem.startsWith(u8, arg, "-L")) {
......@@ -563,28 +587,27 @@ pub fn buildOutputType(
563587 } else {
564588 fatal("unrecognized parameter: '{}'", .{arg});
565589 }
566 } else if (mem.endsWith(u8, arg, ".o") or
567 mem.endsWith(u8, arg, ".obj") or
568 mem.endsWith(u8, arg, ".a") or
569 mem.endsWith(u8, arg, ".lib"))
570 {
571 try link_objects.append(arg);
572 } else if (Compilation.hasAsmExt(arg) or Compilation.hasCExt(arg) or Compilation.hasCppExt(arg)) {
573 // TODO a way to pass extra flags on the CLI
574 try c_source_files.append(.{ .src_path = arg });
575 } else if (mem.endsWith(u8, arg, ".so") or
576 mem.endsWith(u8, arg, ".dylib") or
577 mem.endsWith(u8, arg, ".dll"))
578 {
579 fatal("linking against dynamic libraries not yet supported", .{});
580 } else if (mem.endsWith(u8, arg, ".zig") or mem.endsWith(u8, arg, ".zir")) {
581 if (root_src_file) |other| {
582 fatal("found another zig file '{}' after root source file '{}'", .{ arg, other });
583 } else {
584 root_src_file = arg;
585 }
586 } else {
587 fatal("unrecognized file extension of parameter '{}'", .{arg});
590 } else switch (Compilation.classifyFileExt(arg)) {
591 .object, .static_library => {
592 try link_objects.append(arg);
593 },
594 .assembly, .c, .cpp, .h, .ll, .bc => {
595 // TODO a way to pass extra flags on the CLI
596 try c_source_files.append(.{ .src_path = arg });
597 },
598 .shared_library => {
599 fatal("linking against dynamic libraries not yet supported", .{});
600 },
601 .zig, .zir => {
602 if (root_src_file) |other| {
603 fatal("found another zig file '{}' after root source file '{}'", .{ arg, other });
604 } else {
605 root_src_file = arg;
606 }
607 },
608 .unknown => {
609 fatal("unrecognized file extension of parameter '{}'", .{arg});
610 },
588611 }
589612 }
590613 } else {
......@@ -617,7 +640,16 @@ pub fn buildOutputType(
617640 const file_ext = Compilation.classifyFileExt(mem.spanZ(it.only_arg));
618641 switch (file_ext) {
619642 .assembly, .c, .cpp, .ll, .bc, .h => try c_source_files.append(.{ .src_path = it.only_arg }),
620 .unknown, .so => try link_objects.append(it.only_arg),
643 .unknown, .shared_library, .object, .static_library => {
644 try link_objects.append(it.only_arg);
645 },
646 .zig, .zir => {
647 if (root_src_file) |other| {
648 fatal("found another zig file '{}' after root source file '{}'", .{ it.only_arg, other });
649 } else {
650 root_src_file = it.only_arg;
651 }
652 },
621653 }
622654 },
623655 .l => {
......@@ -1173,7 +1205,15 @@ pub fn buildOutputType(
11731205 .libc_installation = if (libc_installation) |*lci| lci else null,
11741206 .verbose_cc = verbose_cc,
11751207 .verbose_link = verbose_link,
1208 .verbose_tokenize = verbose_tokenize,
1209 .verbose_ast = verbose_ast,
1210 .verbose_ir = verbose_ir,
1211 .verbose_llvm_ir = verbose_llvm_ir,
1212 .verbose_cimport = verbose_cimport,
1213 .verbose_llvm_cpu_features = verbose_llvm_cpu_features,
11761214 .machine_code_model = machine_code_model,
1215 .color = color,
1216 .time_report = time_report,
11771217 }) catch |err| {
11781218 fatal("unable to create compilation: {}", .{@errorName(err)});
11791219 };
......@@ -1193,6 +1233,10 @@ pub fn buildOutputType(
11931233 fatal("TODO: implement `zig cc` when using it as a preprocessor", .{});
11941234 }
11951235
1236 if (build_options.is_stage1 and comp.stage1_module != null and watch) {
1237 std.log.warn("--watch is not recommended with the stage1 backend; it leaks memory and is not capable of incremental compilation", .{});
1238 }
1239
11961240 const stdin = std.io.getStdIn().inStream();
11971241 const stderr = std.io.getStdErr().outStream();
11981242 var repl_buf: [1024]u8 = undefined;
src-self-hosted/stage1.zig+134-278
......@@ -10,6 +10,7 @@ const stage2 = @import("main.zig");
1010const fatal = stage2.fatal;
1111const CrossTarget = std.zig.CrossTarget;
1212const Target = std.Target;
13const Compilation = @import("Compilation.zig");
1314
1415comptime {
1516 assert(std.builtin.link_libc);
......@@ -23,6 +24,8 @@ pub const log_level = stage2.log_level;
2324pub export fn main(argc: c_int, argv: [*]const [*:0]const u8) c_int {
2425 std.debug.maybeEnableSegfaultHandler();
2526
27 zig_stage1_os_init();
28
2629 const gpa = std.heap.c_allocator;
2730 var arena_instance = std.heap.ArenaAllocator.init(gpa);
2831 defer arena_instance.deinit();
......@@ -36,6 +39,106 @@ pub export fn main(argc: c_int, argv: [*]const [*:0]const u8) c_int {
3639 return 0;
3740}
3841
42/// Matches stage2.Color;
43pub const ErrColor = c_int;
44/// Matches std.builtin.CodeModel
45pub const CodeModel = c_int;
46/// Matches std.Target.Os.Tag
47pub const OS = c_int;
48/// Matches std.builtin.BuildMode
49pub const BuildMode = c_int;
50
51pub const TargetSubsystem = extern enum(c_int) {
52 Console,
53 Windows,
54 Posix,
55 Native,
56 EfiApplication,
57 EfiBootServiceDriver,
58 EfiRom,
59 EfiRuntimeDriver,
60 Auto,
61};
62
63pub const Pkg = extern struct {
64 name_ptr: [*]const u8,
65 name_len: usize,
66 path_ptr: [*]const u8,
67 path_len: usize,
68 children_ptr: [*]*Pkg,
69 children_len: usize,
70 parent: ?*Pkg,
71};
72
73pub const Module = extern struct {
74 root_name_ptr: [*]const u8,
75 root_name_len: usize,
76 output_dir_ptr: [*]const u8,
77 output_dir_len: usize,
78 builtin_zig_path_ptr: [*]const u8,
79 builtin_zig_path_len: usize,
80 test_filter_ptr: [*]const u8,
81 test_filter_len: usize,
82 test_name_prefix_ptr: [*]const u8,
83 test_name_prefix_len: usize,
84 userdata: usize,
85 root_pkg: *Pkg,
86 main_progress_node: ?*std.Progress.Node,
87 code_model: CodeModel,
88 subsystem: TargetSubsystem,
89 err_color: ErrColor,
90 pic: bool,
91 link_libc: bool,
92 link_libcpp: bool,
93 strip: bool,
94 is_single_threaded: bool,
95 dll_export_fns: bool,
96 link_mode_dynamic: bool,
97 valgrind_enabled: bool,
98 function_sections: bool,
99 enable_stack_probing: bool,
100 enable_time_report: bool,
101 enable_stack_report: bool,
102 dump_analysis: bool,
103 enable_doc_generation: bool,
104 emit_bin: bool,
105 emit_asm: bool,
106 emit_llvm_ir: bool,
107 test_is_evented: bool,
108 verbose_tokenize: bool,
109 verbose_ast: bool,
110 verbose_ir: bool,
111 verbose_llvm_ir: bool,
112 verbose_cimport: bool,
113 verbose_llvm_cpu_features: bool,
114
115 pub fn build_object(mod: *Module) void {
116 zig_stage1_build_object(mod);
117 }
118
119 pub fn destroy(mod: *Module) void {
120 zig_stage1_destroy(mod);
121 }
122};
123
124extern fn zig_stage1_os_init() void;
125
126pub const create = zig_stage1_create;
127extern fn zig_stage1_create(
128 optimize_mode: BuildMode,
129 main_pkg_path_ptr: [*]const u8,
130 main_pkg_path_len: usize,
131 root_src_path_ptr: [*]const u8,
132 root_src_path_len: usize,
133 zig_lib_dir_ptr: [*c]const u8,
134 zig_lib_dir_len: usize,
135 target: [*c]const Stage2Target,
136 is_test_build: bool,
137) ?*Module;
138
139extern fn zig_stage1_build_object(*Module) void;
140extern fn zig_stage1_destroy(*Module) void;
141
39142// ABI warning
40143export fn stage2_panic(ptr: [*]const u8, len: usize) void {
41144 @panic(ptr[0..len]);
......@@ -199,297 +302,50 @@ export fn stage2_progress_update_node(node: *std.Progress.Node, done_count: usiz
199302}
200303
201304// ABI warning
202const Stage2Target = extern struct {
305pub const Stage2Target = extern struct {
203306 arch: c_int,
204 vendor: c_int,
205
307 os: OS,
206308 abi: c_int,
207 os: c_int,
208309
209310 is_native_os: bool,
210311 is_native_cpu: bool,
211312
212313 llvm_cpu_name: ?[*:0]const u8,
213314 llvm_cpu_features: ?[*:0]const u8,
214 cpu_builtin_str: ?[*:0]const u8,
215 os_builtin_str: ?[*:0]const u8,
216
217 dynamic_linker: ?[*:0]const u8,
218
219 llvm_cpu_features_asm_ptr: [*]const [*:0]const u8,
220 llvm_cpu_features_asm_len: usize,
221
222 fn fromTarget(self: *Stage2Target, cross_target: CrossTarget) !void {
223 const allocator = std.heap.c_allocator;
224
225 var dynamic_linker: ?[*:0]u8 = null;
226 const target = try crossTargetToTarget(cross_target, &dynamic_linker);
227
228 const generic_arch_name = target.cpu.arch.genericName();
229 var cpu_builtin_str_buffer = try std.ArrayListSentineled(u8, 0).allocPrint(allocator,
230 \\Cpu{{
231 \\ .arch = .{},
232 \\ .model = &Target.{}.cpu.{},
233 \\ .features = Target.{}.featureSet(&[_]Target.{}.Feature{{
234 \\
235 , .{
236 @tagName(target.cpu.arch),
237 generic_arch_name,
238 target.cpu.model.name,
239 generic_arch_name,
240 generic_arch_name,
241 });
242 defer cpu_builtin_str_buffer.deinit();
243
244 var llvm_features_buffer = try std.ArrayListSentineled(u8, 0).initSize(allocator, 0);
245 defer llvm_features_buffer.deinit();
246
247 // Unfortunately we have to do the work twice, because Clang does not support
248 // the same command line parameters for CPU features when assembling code as it does
249 // when compiling C code.
250 var asm_features_list = std.ArrayList([*:0]const u8).init(allocator);
251 defer asm_features_list.deinit();
252
253 for (target.cpu.arch.allFeaturesList()) |feature, index_usize| {
254 const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize);
255 const is_enabled = target.cpu.features.isEnabled(index);
256
257 if (feature.llvm_name) |llvm_name| {
258 const plus_or_minus = "-+"[@boolToInt(is_enabled)];
259 try llvm_features_buffer.append(plus_or_minus);
260 try llvm_features_buffer.appendSlice(llvm_name);
261 try llvm_features_buffer.appendSlice(",");
262 }
263
264 if (is_enabled) {
265 // TODO some kind of "zig identifier escape" function rather than
266 // unconditionally using @"" syntax
267 try cpu_builtin_str_buffer.appendSlice(" .@\"");
268 try cpu_builtin_str_buffer.appendSlice(feature.name);
269 try cpu_builtin_str_buffer.appendSlice("\",\n");
270 }
271 }
272
273 switch (target.cpu.arch) {
274 .riscv32, .riscv64 => {
275 if (Target.riscv.featureSetHas(target.cpu.features, .relax)) {
276 try asm_features_list.append("-mrelax");
277 } else {
278 try asm_features_list.append("-mno-relax");
279 }
280 },
281 else => {
282 // TODO
283 // Argh, why doesn't the assembler accept the list of CPU features?!
284 // I don't see a way to do this other than hard coding everything.
285 },
286 }
287
288 try cpu_builtin_str_buffer.appendSlice(
289 \\ }),
290 \\};
291 \\
292 );
293
294 assert(mem.endsWith(u8, llvm_features_buffer.span(), ","));
295 llvm_features_buffer.shrink(llvm_features_buffer.len() - 1);
296
297 var os_builtin_str_buffer = try std.ArrayListSentineled(u8, 0).allocPrint(allocator,
298 \\Os{{
299 \\ .tag = .{},
300 \\ .version_range = .{{
301 , .{@tagName(target.os.tag)});
302 defer os_builtin_str_buffer.deinit();
303
304 // We'll re-use the OS version range builtin string for the cache hash.
305 const os_builtin_str_ver_start_index = os_builtin_str_buffer.len();
306
307 @setEvalBranchQuota(2000);
308 switch (target.os.tag) {
309 .freestanding,
310 .ananas,
311 .cloudabi,
312 .dragonfly,
313 .fuchsia,
314 .ios,
315 .kfreebsd,
316 .lv2,
317 .solaris,
318 .haiku,
319 .minix,
320 .rtems,
321 .nacl,
322 .cnk,
323 .aix,
324 .cuda,
325 .nvcl,
326 .amdhsa,
327 .ps4,
328 .elfiamcu,
329 .tvos,
330 .watchos,
331 .mesa3d,
332 .contiki,
333 .amdpal,
334 .hermit,
335 .hurd,
336 .wasi,
337 .emscripten,
338 .uefi,
339 .other,
340 => try os_builtin_str_buffer.appendSlice(" .none = {} }\n"),
341
342 .freebsd,
343 .macosx,
344 .netbsd,
345 .openbsd,
346 => try os_builtin_str_buffer.outStream().print(
347 \\ .semver = .{{
348 \\ .min = .{{
349 \\ .major = {},
350 \\ .minor = {},
351 \\ .patch = {},
352 \\ }},
353 \\ .max = .{{
354 \\ .major = {},
355 \\ .minor = {},
356 \\ .patch = {},
357 \\ }},
358 \\ }}}},
359 \\
360 , .{
361 target.os.version_range.semver.min.major,
362 target.os.version_range.semver.min.minor,
363 target.os.version_range.semver.min.patch,
364
365 target.os.version_range.semver.max.major,
366 target.os.version_range.semver.max.minor,
367 target.os.version_range.semver.max.patch,
368 }),
369
370 .linux => try os_builtin_str_buffer.outStream().print(
371 \\ .linux = .{{
372 \\ .range = .{{
373 \\ .min = .{{
374 \\ .major = {},
375 \\ .minor = {},
376 \\ .patch = {},
377 \\ }},
378 \\ .max = .{{
379 \\ .major = {},
380 \\ .minor = {},
381 \\ .patch = {},
382 \\ }},
383 \\ }},
384 \\ .glibc = .{{
385 \\ .major = {},
386 \\ .minor = {},
387 \\ .patch = {},
388 \\ }},
389 \\ }}}},
390 \\
391 , .{
392 target.os.version_range.linux.range.min.major,
393 target.os.version_range.linux.range.min.minor,
394 target.os.version_range.linux.range.min.patch,
395
396 target.os.version_range.linux.range.max.major,
397 target.os.version_range.linux.range.max.minor,
398 target.os.version_range.linux.range.max.patch,
399
400 target.os.version_range.linux.glibc.major,
401 target.os.version_range.linux.glibc.minor,
402 target.os.version_range.linux.glibc.patch,
403 }),
404
405 .windows => try os_builtin_str_buffer.outStream().print(
406 \\ .windows = .{{
407 \\ .min = {s},
408 \\ .max = {s},
409 \\ }}}},
410 \\
411 , .{
412 target.os.version_range.windows.min,
413 target.os.version_range.windows.max,
414 }),
415 }
416 try os_builtin_str_buffer.appendSlice("};\n");
417
418 const glibc_or_darwin_version = blk: {
419 if (target.isGnuLibC()) {
420 const stage1_glibc = try std.heap.c_allocator.create(Stage2SemVer);
421 const stage2_glibc = target.os.version_range.linux.glibc;
422 stage1_glibc.* = .{
423 .major = stage2_glibc.major,
424 .minor = stage2_glibc.minor,
425 .patch = stage2_glibc.patch,
426 };
427 break :blk stage1_glibc;
428 } else if (target.isDarwin()) {
429 const stage1_semver = try std.heap.c_allocator.create(Stage2SemVer);
430 const stage2_semver = target.os.version_range.semver.min;
431 stage1_semver.* = .{
432 .major = stage2_semver.major,
433 .minor = stage2_semver.minor,
434 .patch = stage2_semver.patch,
435 };
436 break :blk stage1_semver;
437 } else {
438 break :blk null;
439 }
440 };
441
442 const std_dl = target.standardDynamicLinkerPath();
443 const std_dl_z = if (std_dl.get()) |dl|
444 (try mem.dupeZ(std.heap.c_allocator, u8, dl)).ptr
445 else
446 null;
447
448 const asm_features = asm_features_list.toOwnedSlice();
449 self.* = .{
450 .arch = @enumToInt(target.cpu.arch) + 1, // skip over ZigLLVM_UnknownArch
451 .vendor = 0,
452 .os = @enumToInt(target.os.tag),
453 .abi = @enumToInt(target.abi),
454 .llvm_cpu_name = if (target.cpu.model.llvm_name) |s| s.ptr else null,
455 .llvm_cpu_features = llvm_features_buffer.toOwnedSlice().ptr,
456 .llvm_cpu_features_asm_ptr = asm_features.ptr,
457 .llvm_cpu_features_asm_len = asm_features.len,
458 .cpu_builtin_str = cpu_builtin_str_buffer.toOwnedSlice().ptr,
459 .os_builtin_str = os_builtin_str_buffer.toOwnedSlice().ptr,
460 .is_native_os = cross_target.isNativeOs(),
461 .is_native_cpu = cross_target.isNativeCpu(),
462 .glibc_or_darwin_version = glibc_or_darwin_version,
463 .dynamic_linker = dynamic_linker,
464 .standard_dynamic_linker_path = std_dl_z,
465 };
466 }
467315};
468316
469fn crossTargetToTarget(cross_target: CrossTarget, dynamic_linker_ptr: *?[*:0]u8) !Target {
470 var info = try std.zig.system.NativeTargetInfo.detect(std.heap.c_allocator, cross_target);
471 if (info.cpu_detection_unimplemented) {
472 // TODO We want to just use detected_info.target but implementing
473 // CPU model & feature detection is todo so here we rely on LLVM.
474 const llvm = @import("llvm.zig");
475 const llvm_cpu_name = llvm.GetHostCPUName();
476 const llvm_cpu_features = llvm.GetNativeFeatures();
477 const arch = Target.current.cpu.arch;
478 info.target.cpu = try detectNativeCpuWithLLVM(arch, llvm_cpu_name, llvm_cpu_features);
479 cross_target.updateCpuFeatures(&info.target.cpu.features);
480 info.target.cpu.arch = cross_target.getCpuArch();
481 }
482 if (info.dynamic_linker.get()) |dl| {
483 dynamic_linker_ptr.* = try mem.dupeZ(std.heap.c_allocator, u8, dl);
484 } else {
485 dynamic_linker_ptr.* = null;
486 }
487 return info.target;
488}
489
490317// ABI warning
491318const Stage2SemVer = extern struct {
492319 major: u32,
493320 minor: u32,
494321 patch: u32,
495322};
323
324// ABI warning
325export fn stage2_cimport(stage1: *Module) [*:0]const u8 {
326 @panic("TODO implement stage2_cimport");
327}
328
329export fn stage2_add_link_lib(
330 stage1: *Module,
331 lib_name_ptr: [*c]const u8,
332 lib_name_len: usize,
333 symbol_name_ptr: [*c]const u8,
334 symbol_name_len: usize,
335) ?[*:0]const u8 {
336 return null; // no error
337}
338
339export fn stage2_fetch_file(
340 stage1: *Module,
341 path_ptr: [*]const u8,
342 path_len: usize,
343 result_len: *usize,
344) ?[*]const u8 {
345 const comp = @intToPtr(*Compilation, stage1.userdata);
346 // TODO integrate this with cache hash
347 const file_path = path_ptr[0..path_len];
348 const contents = std.fs.cwd().readFileAlloc(comp.gpa, file_path, std.math.maxInt(u32)) catch return null;
349 result_len.* = contents.len;
350 return contents.ptr;
351}
src/analyze.cpp+1-1
......@@ -7987,7 +7987,7 @@ Error file_fetch(CodeGen *g, Buf *resolved_path, Buf *contents_buf) {
79877987 size_t len;
79887988 const char *contents = stage2_fetch_file(&g->stage1, buf_ptr(resolved_path), buf_len(resolved_path), &len);
79897989 if (contents == nullptr)
7990 return ErrorNoMem;
7990 return ErrorFileNotFound;
79917991 buf_init_from_mem(contents_buf, contents, len);
79927992 return ErrorNone;
79937993}
src/codegen.cpp+26-35
......@@ -8809,33 +8809,18 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
88098809 static_assert(TargetSubsystemEfiBootServiceDriver == 5, "");
88108810 static_assert(TargetSubsystemEfiRom == 6, "");
88118811 static_assert(TargetSubsystemEfiRuntimeDriver == 7, "");
8812 {
8813 const char *endian_str = g->is_big_endian ? "Endian.Big" : "Endian.Little";
8814 buf_appendf(contents, "pub const endian = %s;\n", endian_str);
8815 }
8812
8813 buf_append_str(contents, "/// Deprecated: use `std.Target.current.cpu.arch`\n");
8814 buf_append_str(contents, "pub const arch = Target.current.cpu.arch;\n");
8815 buf_append_str(contents, "/// Deprecated: use `std.Target.current.cpu.arch.endian()`\n");
8816 buf_append_str(contents, "pub const endian = Target.current.cpu.arch.endian();\n");
88168817 buf_appendf(contents, "pub const output_mode = OutputMode.Obj;\n");
88178818 buf_appendf(contents, "pub const link_mode = LinkMode.Static;\n");
88188819 buf_appendf(contents, "pub const is_test = false;\n");
88198820 buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded));
8820 buf_append_str(contents, "/// Deprecated: use `std.Target.cpu.arch`\n");
8821 buf_appendf(contents, "pub const arch = Arch.%s;\n", cur_arch);
88228821 buf_appendf(contents, "pub const abi = Abi.%s;\n", cur_abi);
8823 {
8824 buf_append_str(contents, "pub const cpu: Cpu = ");
8825 if (g->zig_target->cpu_builtin_str != nullptr) {
8826 buf_append_str(contents, g->zig_target->cpu_builtin_str);
8827 } else {
8828 buf_appendf(contents, "Target.Cpu.baseline(.%s);\n", cur_arch);
8829 }
8830 }
8831 {
8832 buf_append_str(contents, "pub const os = ");
8833 if (g->zig_target->os_builtin_str != nullptr) {
8834 buf_append_str(contents, g->zig_target->os_builtin_str);
8835 } else {
8836 buf_appendf(contents, "Target.Os.Tag.defaultVersionRange(.%s);\n", cur_os);
8837 }
8838 }
8822 buf_appendf(contents, "pub const cpu: Cpu = Target.Cpu.baseline(.%s);\n", cur_arch);
8823 buf_appendf(contents, "pub const os = Target.Os.Tag.defaultVersionRange(.%s);\n", cur_os);
88398824 buf_appendf(contents, "pub const object_format = ObjectFormat.%s;\n", cur_obj_fmt);
88408825 buf_appendf(contents, "pub const mode = %s;\n", build_mode_to_str(g->build_mode));
88418826 buf_appendf(contents, "pub const link_libc = %s;\n", bool_to_str(g->link_libc));
......@@ -8866,6 +8851,8 @@ static Error define_builtin_compile_vars(CodeGen *g) {
88668851 if (g->std_package == nullptr)
88678852 return ErrorNone;
88688853
8854 assert(g->main_pkg);
8855
88698856 const char *builtin_zig_basename = "builtin.zig";
88708857
88718858 Buf *contents;
......@@ -8879,17 +8866,22 @@ static Error define_builtin_compile_vars(CodeGen *g) {
88798866 fprintf(stderr, "Unable to write file '%s': %s\n", buf_ptr(g->builtin_zig_path), err_str(err));
88808867 exit(1);
88818868 }
8869
8870 g->compile_var_package = new_package(buf_ptr(g->output_dir), builtin_zig_basename, "builtin");
88828871 } else {
8872 Buf *resolve_paths[] = { g->builtin_zig_path, };
8873 *g->builtin_zig_path = os_path_resolve(resolve_paths, 1);
8874
88838875 contents = buf_alloc();
88848876 if ((err = os_fetch_file_path(g->builtin_zig_path, contents))) {
88858877 fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(g->builtin_zig_path), err_str(err));
88868878 exit(1);
88878879 }
8880 Buf builtin_dirname = BUF_INIT;
8881 os_path_dirname(g->builtin_zig_path, &builtin_dirname);
8882 g->compile_var_package = new_package(buf_ptr(&builtin_dirname), builtin_zig_basename, "builtin");
88888883 }
88898884
8890 assert(g->main_pkg);
8891 assert(g->std_package);
8892 g->compile_var_package = new_package(buf_ptr(g->output_dir), builtin_zig_basename, "builtin");
88938885 if (g->is_test_build) {
88948886 if (g->test_runner_package == nullptr) {
88958887 g->test_runner_package = create_test_runner_pkg(g);
......@@ -8914,6 +8906,13 @@ static void init(CodeGen *g) {
89148906 if (g->module)
89158907 return;
89168908
8909 codegen_add_time_event(g, "Initialize");
8910 {
8911 const char *progress_name = "Initialize";
8912 codegen_switch_sub_prog_node(g, stage2_progress_start(g->main_progress_node,
8913 progress_name, strlen(progress_name), 0));
8914 }
8915
89178916 g->have_err_ret_tracing = detect_err_ret_tracing(g);
89188917
89198918 assert(g->root_out_name);
......@@ -9374,19 +9373,11 @@ void codegen_destroy(CodeGen *g) {
93749373
93759374CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target,
93769375 BuildMode build_mode, Buf *override_lib_dir,
9377 bool is_test_build, Stage2ProgressNode *progress_node)
9376 bool is_test_build)
93789377{
93799378 CodeGen *g = heap::c_allocator.create<CodeGen>();
93809379 g->emit_bin = true;
93819380 g->pass1_arena = heap::ArenaAllocator::construct(&heap::c_allocator, &heap::c_allocator, "pass1");
9382 g->main_progress_node = progress_node;
9383
9384 codegen_add_time_event(g, "Initialize");
9385 {
9386 const char *progress_name = "Initialize";
9387 codegen_switch_sub_prog_node(g, stage2_progress_start(g->main_progress_node,
9388 progress_name, strlen(progress_name), 0));
9389 }
93909381
93919382 g->subsystem = TargetSubsystemAuto;
93929383 g->zig_target = target;
......@@ -9440,7 +9431,7 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget
94409431 Buf resolved_main_pkg_path = os_path_resolve(&main_pkg_path, 1);
94419432
94429433 if (!buf_starts_with_buf(&resolved_root_src_path, &resolved_main_pkg_path)) {
9443 fprintf(stderr, "Root source path '%s' outside main package path '%s'",
9434 fprintf(stderr, "Root source path '%s' outside main package path '%s'\n",
94449435 buf_ptr(root_src_path), buf_ptr(main_pkg_path));
94459436 exit(1);
94469437 }
src/codegen.hpp+1-2
......@@ -16,8 +16,7 @@
1616#include <stdio.h>
1717
1818CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target,
19 BuildMode build_mode, Buf *zig_lib_dir,
20 bool is_test_build, Stage2ProgressNode *progress_node);
19 BuildMode build_mode, Buf *zig_lib_dir, bool is_test_build);
2120
2221void codegen_build_object(CodeGen *g);
2322void codegen_destroy(CodeGen *);
src/stage1.cpp+6-5
......@@ -20,13 +20,14 @@ struct ZigStage1 *zig_stage1_create(BuildMode optimize_mode,
2020 const char *main_pkg_path_ptr, size_t main_pkg_path_len,
2121 const char *root_src_path_ptr, size_t root_src_path_len,
2222 const char *zig_lib_dir_ptr, size_t zig_lib_dir_len,
23 const ZigTarget *target, bool is_test_build, Stage2ProgressNode *progress_node)
23 const ZigTarget *target, bool is_test_build)
2424{
25 Buf *main_pkg_path = buf_create_from_mem(main_pkg_path_ptr, main_pkg_path_len);
25 Buf *main_pkg_path = (main_pkg_path_len == 0) ?
26 nullptr : buf_create_from_mem(main_pkg_path_ptr, main_pkg_path_len);
2627 Buf *root_src_path = buf_create_from_mem(root_src_path_ptr, root_src_path_len);
2728 Buf *zig_lib_dir = buf_create_from_mem(zig_lib_dir_ptr, zig_lib_dir_len);
2829 CodeGen *g = codegen_create(main_pkg_path, root_src_path, target, optimize_mode,
29 zig_lib_dir, is_test_build, progress_node);
30 zig_lib_dir, is_test_build);
3031 return &g->stage1;
3132}
3233
......@@ -68,8 +69,6 @@ void zig_stage1_build_object(struct ZigStage1 *stage1) {
6869 CodeGen *g = reinterpret_cast<CodeGen *>(stage1);
6970
7071 g->root_out_name = buf_create_from_mem(stage1->root_name_ptr, stage1->root_name_len);
71 g->zig_lib_dir = buf_create_from_mem(stage1->zig_lib_dir_ptr, stage1->zig_lib_dir_len);
72 g->zig_std_dir = buf_create_from_mem(stage1->zig_std_dir_ptr, stage1->zig_std_dir_len);
7372 g->output_dir = buf_create_from_mem(stage1->output_dir_ptr, stage1->output_dir_len);
7473 if (stage1->builtin_zig_path_len != 0) {
7574 g->builtin_zig_path = buf_create_from_mem(stage1->builtin_zig_path_ptr, stage1->builtin_zig_path_len);
......@@ -119,6 +118,8 @@ void zig_stage1_build_object(struct ZigStage1 *stage1) {
119118 }
120119 }
121120
121 g->main_progress_node = stage1->main_progress_node;
122
122123 add_package(g, stage1->root_pkg, g->main_pkg);
123124
124125 codegen_build_object(g);
src/stage1.h+6-19
......@@ -100,22 +100,14 @@ enum Os {
100100// ABI warning
101101struct ZigTarget {
102102 enum ZigLLVM_ArchType arch;
103 enum ZigLLVM_VendorType vendor;
104
103 enum Os os;
105104 enum ZigLLVM_EnvironmentType abi;
106 Os os;
107105
108106 bool is_native_os;
109107 bool is_native_cpu;
110108
111109 const char *llvm_cpu_name;
112110 const char *llvm_cpu_features;
113 const char *cpu_builtin_str;
114 const char *os_builtin_str;
115 const char *dynamic_linker;
116
117 const char **llvm_cpu_features_asm_ptr;
118 size_t llvm_cpu_features_asm_len;
119111};
120112
121113// ABI warning
......@@ -161,18 +153,13 @@ struct ZigStage1 {
161153 const char *test_name_prefix_ptr;
162154 size_t test_name_prefix_len;
163155
164 const char *zig_lib_dir_ptr;
165 size_t zig_lib_dir_len;
166
167 const char *zig_std_dir_ptr;
168 size_t zig_std_dir_len;
169
170156 void *userdata;
171157 struct ZigStage1Pkg *root_pkg;
158 struct Stage2ProgressNode *main_progress_node;
172159
173 CodeModel code_model;
174 TargetSubsystem subsystem;
175 ErrColor err_color;
160 enum CodeModel code_model;
161 enum TargetSubsystem subsystem;
162 enum ErrColor err_color;
176163
177164 bool pic;
178165 bool link_libc;
......@@ -206,7 +193,7 @@ ZIG_EXTERN_C struct ZigStage1 *zig_stage1_create(enum BuildMode optimize_mode,
206193 const char *main_pkg_path_ptr, size_t main_pkg_path_len,
207194 const char *root_src_path_ptr, size_t root_src_path_len,
208195 const char *zig_lib_dir_ptr, size_t zig_lib_dir_len,
209 const ZigTarget *target, bool is_test_build, Stage2ProgressNode *progress_node);
196 const struct ZigTarget *target, bool is_test_build);
210197
211198ZIG_EXTERN_C void zig_stage1_build_object(struct ZigStage1 *);
212199
src/stage2.cpp deleted-241
......@@ -1,241 +0,0 @@
1// This file is a shim for zig1. The real implementations of these are in
2// src-self-hosted/stage1.zig
3
4#include "stage2.h"
5#include "util.hpp"
6#include "zig_llvm.h"
7#include "target.hpp"
8#include "buffer.hpp"
9#include "os.hpp"
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13
14void stage2_panic(const char *ptr, size_t len) {
15 fwrite(ptr, 1, len, stderr);
16 fprintf(stderr, "\n");
17 fflush(stderr);
18 abort();
19}
20
21struct Stage2Progress {
22 int trash;
23};
24
25struct Stage2ProgressNode {
26 int trash;
27};
28
29Stage2Progress *stage2_progress_create(void) {
30 return nullptr;
31}
32
33void stage2_progress_destroy(Stage2Progress *progress) {}
34
35Stage2ProgressNode *stage2_progress_start_root(Stage2Progress *progress,
36 const char *name_ptr, size_t name_len, size_t estimated_total_items)
37{
38 return nullptr;
39}
40Stage2ProgressNode *stage2_progress_start(Stage2ProgressNode *node,
41 const char *name_ptr, size_t name_len, size_t estimated_total_items)
42{
43 return nullptr;
44}
45void stage2_progress_end(Stage2ProgressNode *node) {}
46void stage2_progress_complete_one(Stage2ProgressNode *node) {}
47void stage2_progress_disable_tty(Stage2Progress *progress) {}
48void stage2_progress_update_node(Stage2ProgressNode *node, size_t completed_count, size_t estimated_total_items){}
49
50static Os get_zig_os_type(ZigLLVM_OSType os_type) {
51 switch (os_type) {
52 case ZigLLVM_UnknownOS:
53 return OsFreestanding;
54 case ZigLLVM_Ananas:
55 return OsAnanas;
56 case ZigLLVM_CloudABI:
57 return OsCloudABI;
58 case ZigLLVM_DragonFly:
59 return OsDragonFly;
60 case ZigLLVM_FreeBSD:
61 return OsFreeBSD;
62 case ZigLLVM_Fuchsia:
63 return OsFuchsia;
64 case ZigLLVM_IOS:
65 return OsIOS;
66 case ZigLLVM_KFreeBSD:
67 return OsKFreeBSD;
68 case ZigLLVM_Linux:
69 return OsLinux;
70 case ZigLLVM_Lv2:
71 return OsLv2;
72 case ZigLLVM_Darwin:
73 case ZigLLVM_MacOSX:
74 return OsMacOSX;
75 case ZigLLVM_NetBSD:
76 return OsNetBSD;
77 case ZigLLVM_OpenBSD:
78 return OsOpenBSD;
79 case ZigLLVM_Solaris:
80 return OsSolaris;
81 case ZigLLVM_Win32:
82 return OsWindows;
83 case ZigLLVM_Haiku:
84 return OsHaiku;
85 case ZigLLVM_Minix:
86 return OsMinix;
87 case ZigLLVM_RTEMS:
88 return OsRTEMS;
89 case ZigLLVM_NaCl:
90 return OsNaCl;
91 case ZigLLVM_CNK:
92 return OsCNK;
93 case ZigLLVM_AIX:
94 return OsAIX;
95 case ZigLLVM_CUDA:
96 return OsCUDA;
97 case ZigLLVM_NVCL:
98 return OsNVCL;
99 case ZigLLVM_AMDHSA:
100 return OsAMDHSA;
101 case ZigLLVM_PS4:
102 return OsPS4;
103 case ZigLLVM_ELFIAMCU:
104 return OsELFIAMCU;
105 case ZigLLVM_TvOS:
106 return OsTvOS;
107 case ZigLLVM_WatchOS:
108 return OsWatchOS;
109 case ZigLLVM_Mesa3D:
110 return OsMesa3D;
111 case ZigLLVM_Contiki:
112 return OsContiki;
113 case ZigLLVM_AMDPAL:
114 return OsAMDPAL;
115 case ZigLLVM_HermitCore:
116 return OsHermitCore;
117 case ZigLLVM_Hurd:
118 return OsHurd;
119 case ZigLLVM_WASI:
120 return OsWASI;
121 case ZigLLVM_Emscripten:
122 return OsEmscripten;
123 }
124 zig_unreachable();
125}
126
127static void get_native_target(ZigTarget *target) {
128 // first zero initialize
129 *target = {};
130
131 ZigLLVM_OSType os_type;
132 ZigLLVM_ObjectFormatType oformat; // ignored; based on arch/os
133 ZigLLVMGetNativeTarget(
134 &target->arch,
135 &target->vendor,
136 &os_type,
137 &target->abi,
138 &oformat);
139 target->os = get_zig_os_type(os_type);
140 target->is_native_os = true;
141 target->is_native_cpu = true;
142 if (target->abi == ZigLLVM_UnknownEnvironment) {
143 target->abi = target_default_abi(target->arch, target->os);
144 }
145}
146
147Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, const char *mcpu,
148 const char *dynamic_linker)
149{
150 Error err;
151
152 if (zig_triple != nullptr && strcmp(zig_triple, "native") == 0) {
153 zig_triple = nullptr;
154 }
155
156 if (zig_triple == nullptr) {
157 get_native_target(target);
158
159 if (mcpu == nullptr) {
160 target->llvm_cpu_name = ZigLLVMGetHostCPUName();
161 target->llvm_cpu_features = ZigLLVMGetNativeFeatures();
162 } else if (strcmp(mcpu, "baseline") == 0) {
163 target->is_native_os = false;
164 target->is_native_cpu = false;
165 target->llvm_cpu_name = "";
166 target->llvm_cpu_features = "";
167 } else {
168 const char *msg = "stage0 can't handle CPU/features in the target";
169 stage2_panic(msg, strlen(msg));
170 }
171 } else {
172 // first initialize all to zero
173 *target = {};
174
175 SplitIterator it = memSplit(str(zig_triple), str("-"));
176
177 Optional<Slice<uint8_t>> opt_archsub = SplitIterator_next(&it);
178 Optional<Slice<uint8_t>> opt_os = SplitIterator_next(&it);
179 Optional<Slice<uint8_t>> opt_abi = SplitIterator_next(&it);
180
181 if (!opt_archsub.is_some)
182 return ErrorMissingArchitecture;
183
184 if ((err = target_parse_arch(&target->arch, (char*)opt_archsub.value.ptr, opt_archsub.value.len))) {
185 return err;
186 }
187
188 if (!opt_os.is_some)
189 return ErrorMissingOperatingSystem;
190
191 if ((err = target_parse_os(&target->os, (char*)opt_os.value.ptr, opt_os.value.len))) {
192 return err;
193 }
194
195 if (opt_abi.is_some) {
196 if ((err = target_parse_abi(&target->abi, (char*)opt_abi.value.ptr, opt_abi.value.len))) {
197 return err;
198 }
199 } else {
200 target->abi = target_default_abi(target->arch, target->os);
201 }
202
203 if (mcpu != nullptr && strcmp(mcpu, "baseline") != 0) {
204 const char *msg = "stage0 can't handle CPU/features in the target";
205 stage2_panic(msg, strlen(msg));
206 }
207 }
208
209 if (dynamic_linker != nullptr) {
210 target->dynamic_linker = dynamic_linker;
211 }
212
213 return ErrorNone;
214}
215
216const char *stage2_fetch_file(struct ZigStage1 *stage1, const char *path_ptr, size_t path_len,
217 size_t *result_len)
218{
219 Error err;
220 Buf contents_buf = BUF_INIT;
221 Buf path_buf = BUF_INIT;
222
223 buf_init_from_mem(&path_buf, path_ptr, path_len);
224 if ((err = os_fetch_file_path(&path_buf, &contents_buf))) {
225 return nullptr;
226 }
227 *result_len = buf_len(&contents_buf);
228 return buf_ptr(&contents_buf);
229}
230
231const char *stage2_cimport(struct ZigStage1 *stage1) {
232 const char *msg = "stage0 called stage2_cimport";
233 stage2_panic(msg, strlen(msg));
234}
235
236const char *stage2_add_link_lib(struct ZigStage1 *stage1,
237 const char *lib_name_ptr, size_t lib_name_len,
238 const char *symbol_name_ptr, size_t symbol_name_len)
239{
240 return nullptr;
241}
src/stage2.h+8-8
......@@ -130,23 +130,23 @@ struct Stage2ErrorMsg {
130130ZIG_EXTERN_C ZIG_ATTRIBUTE_NORETURN void stage2_panic(const char *ptr, size_t len);
131131
132132// ABI warning
133ZIG_EXTERN_C Stage2Progress *stage2_progress_create(void);
133ZIG_EXTERN_C struct Stage2Progress *stage2_progress_create(void);
134134// ABI warning
135ZIG_EXTERN_C void stage2_progress_disable_tty(Stage2Progress *progress);
135ZIG_EXTERN_C void stage2_progress_disable_tty(struct Stage2Progress *progress);
136136// ABI warning
137ZIG_EXTERN_C void stage2_progress_destroy(Stage2Progress *progress);
137ZIG_EXTERN_C void stage2_progress_destroy(struct Stage2Progress *progress);
138138// ABI warning
139ZIG_EXTERN_C Stage2ProgressNode *stage2_progress_start_root(Stage2Progress *progress,
139ZIG_EXTERN_C struct Stage2ProgressNode *stage2_progress_start_root(struct Stage2Progress *progress,
140140 const char *name_ptr, size_t name_len, size_t estimated_total_items);
141141// ABI warning
142ZIG_EXTERN_C Stage2ProgressNode *stage2_progress_start(Stage2ProgressNode *node,
142ZIG_EXTERN_C struct Stage2ProgressNode *stage2_progress_start(struct Stage2ProgressNode *node,
143143 const char *name_ptr, size_t name_len, size_t estimated_total_items);
144144// ABI warning
145ZIG_EXTERN_C void stage2_progress_end(Stage2ProgressNode *node);
145ZIG_EXTERN_C void stage2_progress_end(struct Stage2ProgressNode *node);
146146// ABI warning
147ZIG_EXTERN_C void stage2_progress_complete_one(Stage2ProgressNode *node);
147ZIG_EXTERN_C void stage2_progress_complete_one(struct Stage2ProgressNode *node);
148148// ABI warning
149ZIG_EXTERN_C void stage2_progress_update_node(Stage2ProgressNode *node,
149ZIG_EXTERN_C void stage2_progress_update_node(struct Stage2ProgressNode *node,
150150 size_t completed_count, size_t estimated_total_items);
151151
152152// ABI warning
src/target.cpp+1-6
......@@ -380,10 +380,6 @@ Error target_parse_abi(ZigLLVM_EnvironmentType *out_abi, const char *abi_ptr, si
380380 return ErrorUnknownABI;
381381}
382382
383Error target_parse_triple(ZigTarget *target, const char *triple, const char *mcpu, const char *dynamic_linker) {
384 return stage2_target_parse(target, triple, mcpu, dynamic_linker);
385}
386
387383const char *target_arch_name(ZigLLVM_ArchType arch) {
388384 return ZigLLVMGetArchTypeName(arch);
389385}
......@@ -408,7 +404,7 @@ void target_triple_llvm(Buf *triple, const ZigTarget *target) {
408404 buf_resize(triple, 0);
409405 buf_appendf(triple, "%s-%s-%s-%s",
410406 ZigLLVMGetArchTypeName(target->arch),
411 ZigLLVMGetVendorTypeName(target->vendor),
407 ZigLLVMGetVendorTypeName(ZigLLVM_UnknownVendor),
412408 ZigLLVMGetOSTypeName(get_llvm_os_type(target->os)),
413409 ZigLLVMGetEnvironmentTypeName(target->abi));
414410}
......@@ -1149,7 +1145,6 @@ void target_libc_enum(size_t index, ZigTarget *out_target) {
11491145 out_target->arch = libcs_available[index].arch;
11501146 out_target->os = libcs_available[index].os;
11511147 out_target->abi = libcs_available[index].abi;
1152 out_target->vendor = ZigLLVM_UnknownVendor;
11531148 out_target->is_native_os = false;
11541149 out_target->is_native_cpu = false;
11551150}
src/target.hpp-1
......@@ -25,7 +25,6 @@ enum CIntType {
2525 CIntTypeCount,
2626};
2727
28Error target_parse_triple(ZigTarget *target, const char *triple, const char *mcpu, const char *dynamic_linker);
2928Error target_parse_arch(ZigLLVM_ArchType *arch, const char *arch_ptr, size_t arch_len);
3029Error target_parse_os(Os *os, const char *os_ptr, size_t os_len);
3130Error target_parse_abi(ZigLLVM_EnvironmentType *abi, const char *abi_ptr, size_t abi_len);
src/zig0.cpp+239-12
......@@ -14,6 +14,9 @@
1414#include "stage2.h"
1515#include "target.hpp"
1616#include "error.hpp"
17#include "util.hpp"
18#include "buffer.hpp"
19#include "os.hpp"
1720
1821#include <stdio.h>
1922#include <string.h>
......@@ -33,7 +36,6 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
3336 " --output-dir [dir] override output directory (defaults to cwd)\n"
3437 " --pkg-begin [name] [path] make pkg available to import and push current pkg\n"
3538 " --pkg-end pop current pkg\n"
36 " --main-pkg-path set the directory of the root package\n"
3739 " --release-fast build with optimizations on and safety off\n"
3840 " --release-safe build with optimizations on and safety on\n"
3941 " --release-small build with size optimizations on and safety off\n"
......@@ -53,6 +55,170 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
5355 return return_code;
5456}
5557
58static Os get_zig_os_type(ZigLLVM_OSType os_type) {
59 switch (os_type) {
60 case ZigLLVM_UnknownOS:
61 return OsFreestanding;
62 case ZigLLVM_Ananas:
63 return OsAnanas;
64 case ZigLLVM_CloudABI:
65 return OsCloudABI;
66 case ZigLLVM_DragonFly:
67 return OsDragonFly;
68 case ZigLLVM_FreeBSD:
69 return OsFreeBSD;
70 case ZigLLVM_Fuchsia:
71 return OsFuchsia;
72 case ZigLLVM_IOS:
73 return OsIOS;
74 case ZigLLVM_KFreeBSD:
75 return OsKFreeBSD;
76 case ZigLLVM_Linux:
77 return OsLinux;
78 case ZigLLVM_Lv2:
79 return OsLv2;
80 case ZigLLVM_Darwin:
81 case ZigLLVM_MacOSX:
82 return OsMacOSX;
83 case ZigLLVM_NetBSD:
84 return OsNetBSD;
85 case ZigLLVM_OpenBSD:
86 return OsOpenBSD;
87 case ZigLLVM_Solaris:
88 return OsSolaris;
89 case ZigLLVM_Win32:
90 return OsWindows;
91 case ZigLLVM_Haiku:
92 return OsHaiku;
93 case ZigLLVM_Minix:
94 return OsMinix;
95 case ZigLLVM_RTEMS:
96 return OsRTEMS;
97 case ZigLLVM_NaCl:
98 return OsNaCl;
99 case ZigLLVM_CNK:
100 return OsCNK;
101 case ZigLLVM_AIX:
102 return OsAIX;
103 case ZigLLVM_CUDA:
104 return OsCUDA;
105 case ZigLLVM_NVCL:
106 return OsNVCL;
107 case ZigLLVM_AMDHSA:
108 return OsAMDHSA;
109 case ZigLLVM_PS4:
110 return OsPS4;
111 case ZigLLVM_ELFIAMCU:
112 return OsELFIAMCU;
113 case ZigLLVM_TvOS:
114 return OsTvOS;
115 case ZigLLVM_WatchOS:
116 return OsWatchOS;
117 case ZigLLVM_Mesa3D:
118 return OsMesa3D;
119 case ZigLLVM_Contiki:
120 return OsContiki;
121 case ZigLLVM_AMDPAL:
122 return OsAMDPAL;
123 case ZigLLVM_HermitCore:
124 return OsHermitCore;
125 case ZigLLVM_Hurd:
126 return OsHurd;
127 case ZigLLVM_WASI:
128 return OsWASI;
129 case ZigLLVM_Emscripten:
130 return OsEmscripten;
131 }
132 zig_unreachable();
133}
134
135static void get_native_target(ZigTarget *target) {
136 // first zero initialize
137 *target = {};
138
139 ZigLLVM_OSType os_type;
140 ZigLLVM_ObjectFormatType oformat; // ignored; based on arch/os
141 ZigLLVM_VendorType trash;
142 ZigLLVMGetNativeTarget(
143 &target->arch,
144 &trash,
145 &os_type,
146 &target->abi,
147 &oformat);
148 target->os = get_zig_os_type(os_type);
149 target->is_native_os = true;
150 target->is_native_cpu = true;
151 if (target->abi == ZigLLVM_UnknownEnvironment) {
152 target->abi = target_default_abi(target->arch, target->os);
153 }
154}
155
156static Error target_parse_triple(struct ZigTarget *target, const char *zig_triple, const char *mcpu,
157 const char *dynamic_linker)
158{
159 Error err;
160
161 if (zig_triple != nullptr && strcmp(zig_triple, "native") == 0) {
162 zig_triple = nullptr;
163 }
164
165 if (zig_triple == nullptr) {
166 get_native_target(target);
167
168 if (mcpu == nullptr) {
169 target->llvm_cpu_name = ZigLLVMGetHostCPUName();
170 target->llvm_cpu_features = ZigLLVMGetNativeFeatures();
171 } else if (strcmp(mcpu, "baseline") == 0) {
172 target->is_native_os = false;
173 target->is_native_cpu = false;
174 target->llvm_cpu_name = "";
175 target->llvm_cpu_features = "";
176 } else {
177 const char *msg = "stage0 can't handle CPU/features in the target";
178 stage2_panic(msg, strlen(msg));
179 }
180 } else {
181 // first initialize all to zero
182 *target = {};
183
184 SplitIterator it = memSplit(str(zig_triple), str("-"));
185
186 Optional<Slice<uint8_t>> opt_archsub = SplitIterator_next(&it);
187 Optional<Slice<uint8_t>> opt_os = SplitIterator_next(&it);
188 Optional<Slice<uint8_t>> opt_abi = SplitIterator_next(&it);
189
190 if (!opt_archsub.is_some)
191 return ErrorMissingArchitecture;
192
193 if ((err = target_parse_arch(&target->arch, (char*)opt_archsub.value.ptr, opt_archsub.value.len))) {
194 return err;
195 }
196
197 if (!opt_os.is_some)
198 return ErrorMissingOperatingSystem;
199
200 if ((err = target_parse_os(&target->os, (char*)opt_os.value.ptr, opt_os.value.len))) {
201 return err;
202 }
203
204 if (opt_abi.is_some) {
205 if ((err = target_parse_abi(&target->abi, (char*)opt_abi.value.ptr, opt_abi.value.len))) {
206 return err;
207 }
208 } else {
209 target->abi = target_default_abi(target->arch, target->os);
210 }
211
212 if (mcpu != nullptr && strcmp(mcpu, "baseline") != 0) {
213 const char *msg = "stage0 can't handle CPU/features in the target";
214 stage2_panic(msg, strlen(msg));
215 }
216 }
217
218 return ErrorNone;
219}
220
221
56222static bool str_starts_with(const char *s1, const char *s2) {
57223 size_t s2_len = strlen(s2);
58224 if (strlen(s1) < s2_len) {
......@@ -90,10 +256,9 @@ int main(int argc, char **argv) {
90256 bool link_libcpp = false;
91257 const char *target_string = nullptr;
92258 ZigStage1Pkg *cur_pkg = heap::c_allocator.create<ZigStage1Pkg>();
93 BuildMode build_mode = BuildModeDebug;
259 BuildMode optimize_mode = BuildModeDebug;
94260 TargetSubsystem subsystem = TargetSubsystemAuto;
95261 const char *override_lib_dir = nullptr;
96 const char *main_pkg_path = nullptr;
97262 const char *mcpu = nullptr;
98263
99264 for (int i = 1; i < argc; i += 1) {
......@@ -103,11 +268,11 @@ int main(int argc, char **argv) {
103268 if (strcmp(arg, "--") == 0) {
104269 fprintf(stderr, "Unexpected end-of-parameter mark: %s\n", arg);
105270 } else if (strcmp(arg, "--release-fast") == 0) {
106 build_mode = BuildModeFastRelease;
271 optimize_mode = BuildModeFastRelease;
107272 } else if (strcmp(arg, "--release-safe") == 0) {
108 build_mode = BuildModeSafeRelease;
273 optimize_mode = BuildModeSafeRelease;
109274 } else if (strcmp(arg, "--release-small") == 0) {
110 build_mode = BuildModeSmallRelease;
275 optimize_mode = BuildModeSmallRelease;
111276 } else if (strcmp(arg, "--help") == 0) {
112277 return print_full_usage(arg0, stdout, EXIT_SUCCESS);
113278 } else if (strcmp(arg, "--strip") == 0) {
......@@ -183,8 +348,6 @@ int main(int argc, char **argv) {
183348 dynamic_linker = argv[i];
184349 } else if (strcmp(arg, "--override-lib-dir") == 0) {
185350 override_lib_dir = argv[i];
186 } else if (strcmp(arg, "--main-pkg-path") == 0) {
187 main_pkg_path = argv[i];
188351 } else if (strcmp(arg, "--library") == 0 || strcmp(arg, "-l") == 0) {
189352 if (strcmp(argv[i], "c") == 0) {
190353 link_libc = true;
......@@ -264,12 +427,13 @@ int main(int argc, char **argv) {
264427 return print_error_usage(arg0);
265428 }
266429
267 ZigStage1 *stage1 = zig_stage1_create(build_mode,
268 main_pkg_path, (main_pkg_path == nullptr) ? 0 : strlen(main_pkg_path),
430 ZigStage1 *stage1 = zig_stage1_create(optimize_mode,
431 nullptr, 0,
269432 in_file, strlen(in_file),
270 override_lib_dir, strlen(override_lib_dir), &target, false,
271 root_progress_node);
433 override_lib_dir, strlen(override_lib_dir),
434 &target, false);
272435
436 stage1->main_progress_node = root_progress_node;
273437 stage1->root_name_ptr = out_name;
274438 stage1->root_name_len = strlen(out_name);
275439 stage1->strip = strip;
......@@ -295,3 +459,66 @@ int main(int argc, char **argv) {
295459
296460 return main_exit(root_progress_node, EXIT_SUCCESS);
297461}
462
463void stage2_panic(const char *ptr, size_t len) {
464 fwrite(ptr, 1, len, stderr);
465 fprintf(stderr, "\n");
466 fflush(stderr);
467 abort();
468}
469
470struct Stage2Progress {
471 int trash;
472};
473
474struct Stage2ProgressNode {
475 int trash;
476};
477
478Stage2Progress *stage2_progress_create(void) {
479 return nullptr;
480}
481
482void stage2_progress_destroy(Stage2Progress *progress) {}
483
484Stage2ProgressNode *stage2_progress_start_root(Stage2Progress *progress,
485 const char *name_ptr, size_t name_len, size_t estimated_total_items)
486{
487 return nullptr;
488}
489Stage2ProgressNode *stage2_progress_start(Stage2ProgressNode *node,
490 const char *name_ptr, size_t name_len, size_t estimated_total_items)
491{
492 return nullptr;
493}
494void stage2_progress_end(Stage2ProgressNode *node) {}
495void stage2_progress_complete_one(Stage2ProgressNode *node) {}
496void stage2_progress_disable_tty(Stage2Progress *progress) {}
497void stage2_progress_update_node(Stage2ProgressNode *node, size_t completed_count, size_t estimated_total_items){}
498
499const char *stage2_fetch_file(struct ZigStage1 *stage1, const char *path_ptr, size_t path_len,
500 size_t *result_len)
501{
502 Error err;
503 Buf contents_buf = BUF_INIT;
504 Buf path_buf = BUF_INIT;
505
506 buf_init_from_mem(&path_buf, path_ptr, path_len);
507 if ((err = os_fetch_file_path(&path_buf, &contents_buf))) {
508 return nullptr;
509 }
510 *result_len = buf_len(&contents_buf);
511 return buf_ptr(&contents_buf);
512}
513
514const char *stage2_cimport(struct ZigStage1 *stage1) {
515 const char *msg = "stage0 called stage2_cimport";
516 stage2_panic(msg, strlen(msg));
517}
518
519const char *stage2_add_link_lib(struct ZigStage1 *stage1,
520 const char *lib_name_ptr, size_t lib_name_len,
521 const char *symbol_name_ptr, size_t symbol_name_len)
522{
523 return nullptr;
524}