From 2ef68631cb7045c277b348777b1a064845b95cd8 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 18 Sep 2020 22:48:28 -0700 Subject: [PATCH] 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 --- BRANCH_TODO | 8 +- CMakeLists.txt | 1 - src-self-hosted/Compilation.zig | 247 +++++++++++++++++-- src-self-hosted/link.zig | 13 + src-self-hosted/link/Elf.zig | 15 +- src-self-hosted/main.zig | 114 ++++++--- src-self-hosted/stage1.zig | 412 +++++++++++--------------------- src/analyze.cpp | 2 +- src/codegen.cpp | 61 ++--- src/codegen.hpp | 3 +- src/stage1.cpp | 11 +- src/stage1.h | 25 +- src/stage2.cpp | 241 ------------------- src/stage2.h | 16 +- src/target.cpp | 7 +- src/target.hpp | 1 - src/zig0.cpp | 251 ++++++++++++++++++- 17 files changed, 750 insertions(+), 678 deletions(-) delete mode 100644 src/stage2.cpp diff --git a/BRANCH_TODO b/BRANCH_TODO index 9455511dbf..bee98d6d2b 100644 --- a/BRANCH_TODO +++ b/BRANCH_TODO @@ -1,3 +1,6 @@ + * build & link against compiler-rt + * build & link against freestanding libc + * Cache integration for stage1 zig code compilation * `zig test` * `zig build` * `-ftime-report` @@ -14,10 +17,7 @@ - using it as a preprocessor (-E) - try building some software * support rpaths in ELF linker code - * build & link against compiler-rt - - stage1 C++ code integration * repair @cImport - * build & link against freestanding libc * add CLI support for a way to pass extra flags to c source files * capture lld stdout/stderr better * musl @@ -35,10 +35,12 @@ * implement emit-h in stage2 * implement -fno-emit-bin * audit the base cache hash + * --main-pkg-path * audit the CLI options for stage2 * `zig init-lib` * `zig init-exe` * `zig run` + * restore error messages for stage2_add_link_lib * implement serialization/deserialization of incremental compilation metadata * incremental compilation - implement detection of which source files changed diff --git a/CMakeLists.txt b/CMakeLists.txt index d55c76ee9c..1a19c275d3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -258,7 +258,6 @@ find_package(Threads) # This is our shim which will be replaced by stage1.zig. set(ZIG0_SOURCES "${CMAKE_SOURCE_DIR}/src/zig0.cpp" - "${CMAKE_SOURCE_DIR}/src/stage2.cpp" ) set(ZIG_SOURCES diff --git a/src-self-hosted/Compilation.zig b/src-self-hosted/Compilation.zig index ed46508485..f08c5ef82f 100644 --- a/src-self-hosted/Compilation.zig +++ b/src-self-hosted/Compilation.zig @@ -19,6 +19,7 @@ const libunwind = @import("libunwind.zig"); const fatal = @import("main.zig").fatal; const Module = @import("Module.zig"); const Cache = @import("Cache.zig"); +const stage1 = @import("stage1.zig"); /// General-purpose allocator. Used for both temporary and long-term storage. gpa: *Allocator, @@ -26,6 +27,7 @@ gpa: *Allocator, arena_state: std.heap.ArenaAllocator.State, bin_file: *link.File, c_object_table: std.AutoArrayHashMapUnmanaged(*CObject, void) = .{}, +stage1_module: ?*stage1.Module, link_error_flags: link.File.ErrorFlags = .{}, @@ -122,6 +124,8 @@ const Job = union(enum) { /// Generate builtin.zig source code and write it into the correct place. generate_builtin_zig: void, + /// Use stage1 C++ code to compile zig code into an object file. + stage1_module: void, }; pub const CObject = struct { @@ -274,6 +278,7 @@ pub const InitOptions = struct { strip: bool = false, single_threaded: bool = false, is_native_os: bool, + time_report: bool = false, link_eh_frame_hdr: bool = false, linker_script: ?[]const u8 = null, version_script: ?[]const u8 = null, @@ -288,12 +293,20 @@ pub const InitOptions = struct { clang_passthrough_mode: bool = false, verbose_cc: bool = false, verbose_link: bool = false, + verbose_tokenize: bool = false, + verbose_ast: bool = false, + verbose_ir: bool = false, + verbose_llvm_ir: bool = false, + verbose_cimport: bool = false, + verbose_llvm_cpu_features: bool = false, is_test: bool = false, stack_size_override: ?u64 = null, self_exe_path: ?[]const u8 = null, version: ?std.builtin.Version = null, libc_installation: ?*const LibCInstallation = null, machine_code_model: std.builtin.CodeModel = .default, + /// This is for stage1 and should be deleted upon completion of self-hosting. + color: @import("main.zig").Color = .Auto, }; pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { @@ -332,11 +345,27 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { { break :blk true; } + + if (build_options.is_stage1) { + // If stage1 generates an object file, self-hosted linker is not + // yet sophisticated enough to handle that. + break :blk options.root_pkg != null; + } + break :blk false; }; // Make a decision on whether to use LLVM or our own backend. const use_llvm = if (options.use_llvm) |explicit| explicit else blk: { + // If we have no zig code to compile, no need for LLVM. + if (options.root_pkg == null) + break :blk false; + + // If we are the stage1 compiler, we depend on the stage1 c++ llvm backend + // to compile zig code. + if (build_options.is_stage1) + break :blk true; + // We would want to prefer LLVM for release builds when it is available, however // we don't have an LLVM backend yet :) // 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 { .ReleaseFast, .ReleaseSmall => false, }; + const llvm_cpu_features: ?[*:0]const u8 = if (build_options.have_llvm and use_llvm) blk: { + var buf = std.ArrayList(u8).init(arena); + for (options.target.cpu.arch.allFeaturesList()) |feature, index_usize| { + const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize); + const is_enabled = options.target.cpu.features.isEnabled(index); + + if (feature.llvm_name) |llvm_name| { + const plus_or_minus = "-+"[@boolToInt(is_enabled)]; + try buf.ensureCapacity(buf.items.len + 2 + llvm_name.len); + buf.appendAssumeCapacity(plus_or_minus); + buf.appendSliceAssumeCapacity(llvm_name); + buf.appendSliceAssumeCapacity(","); + } + } + assert(mem.endsWith(u8, buf.items, ",")); + buf.items[buf.items.len - 1] = 0; + buf.shrink(buf.items.len); + break :blk buf.items[0 .. buf.items.len - 1 :0].ptr; + } else null; + + const stage1_module: ?*stage1.Module = if (build_options.is_stage1 and use_llvm) blk: { + // Here we use the legacy stage1 C++ compiler to compile Zig code. + const stage2_target = try arena.create(stage1.Stage2Target); + stage2_target.* = .{ + .arch = @enumToInt(options.target.cpu.arch) + 1, // skip over ZigLLVM_UnknownArch + .os = @enumToInt(options.target.os.tag), + .abi = @enumToInt(options.target.abi), + .is_native_os = options.is_native_os, + .is_native_cpu = false, // Only true when bootstrapping the compiler. + .llvm_cpu_name = if (options.target.cpu.model.llvm_name) |s| s.ptr else null, + .llvm_cpu_features = llvm_cpu_features.?, + }; + const progress = try arena.create(std.Progress); + const main_progress_node = try progress.start("", 100); + if (options.color == .Off) progress.terminal = null; + + const mod = module.?; + const main_zig_file = mod.root_pkg.root_src_path; + const zig_lib_dir = options.zig_lib_directory.path.?; + const builtin_sub = &[_][]const u8{"builtin.zig"}; + const builtin_zig_path = try mod.zig_cache_artifact_directory.join(arena, builtin_sub); + + const stage1_module = stage1.create( + @enumToInt(options.optimize_mode), + undefined, + 0, // TODO --main-pkg-path + main_zig_file.ptr, + main_zig_file.len, + zig_lib_dir.ptr, + zig_lib_dir.len, + stage2_target, + options.is_test, + ) orelse return error.OutOfMemory; + + const output_dir = bin_directory.path orelse "."; + + const stage1_pkg = try arena.create(stage1.Pkg); + stage1_pkg.* = .{ + .name_ptr = undefined, + .name_len = 0, + .path_ptr = undefined, + .path_len = 0, + .children_ptr = undefined, + .children_len = 0, + .parent = null, + }; + + stage1_module.* = .{ + .root_name_ptr = root_name.ptr, + .root_name_len = root_name.len, + .output_dir_ptr = output_dir.ptr, + .output_dir_len = output_dir.len, + .builtin_zig_path_ptr = builtin_zig_path.ptr, + .builtin_zig_path_len = builtin_zig_path.len, + .test_filter_ptr = "", + .test_filter_len = 0, + .test_name_prefix_ptr = "", + .test_name_prefix_len = 0, + .userdata = @ptrToInt(comp), + .root_pkg = stage1_pkg, + .code_model = @enumToInt(options.machine_code_model), + .subsystem = stage1.TargetSubsystem.Auto, + .err_color = @enumToInt(options.color), + .pic = pic, + .link_libc = options.link_libc, + .link_libcpp = options.link_libcpp, + .strip = options.strip, + .is_single_threaded = single_threaded, + .dll_export_fns = dll_export_fns, + .link_mode_dynamic = link_mode == .Dynamic, + .valgrind_enabled = valgrind, + .function_sections = options.function_sections orelse false, + .enable_stack_probing = stack_check, + .enable_time_report = options.time_report, + .enable_stack_report = false, + .dump_analysis = false, + .enable_doc_generation = false, + .emit_bin = true, + .emit_asm = false, + .emit_llvm_ir = false, + .test_is_evented = false, + .verbose_tokenize = options.verbose_tokenize, + .verbose_ast = options.verbose_ast, + .verbose_ir = options.verbose_ir, + .verbose_llvm_ir = options.verbose_llvm_ir, + .verbose_cimport = options.verbose_cimport, + .verbose_llvm_cpu_features = options.verbose_llvm_cpu_features, + .main_progress_node = main_progress_node, + }; + break :blk stage1_module; + } else null; + const bin_file = try link.File.openPath(gpa, .{ .directory = bin_directory, .sub_path = emit_bin.basename, @@ -626,6 +767,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { .machine_code_model = options.machine_code_model, .dll_export_fns = dll_export_fns, .error_return_tracing = error_return_tracing, + .llvm_cpu_features = llvm_cpu_features, }); errdefer bin_file.destroy(); @@ -635,6 +777,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { .zig_lib_directory = options.zig_lib_directory, .zig_cache_directory = options.zig_cache_directory, .bin_file = bin_file, + .stage1_module = stage1_module, .work_queue = std.fifo.LinearFifo(Job, .Dynamic).init(gpa), .keep_source_files_loaded = options.keep_source_files_loaded, .use_clang = use_clang, @@ -681,6 +824,10 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { try comp.work_queue.writeItem(.{ .libunwind = {} }); } + if (comp.stage1_module) |module| { + try comp.work_queue.writeItem(.{ .stage1_module = {} }); + } + return comp; } @@ -689,6 +836,11 @@ pub fn destroy(self: *Compilation) void { self.bin_file.destroy(); if (optional_module) |module| module.deinit(); + if (self.stage1_module) |module| { + module.main_progress_node.?.end(); + module.destroy(); + } + const gpa = self.gpa; self.work_queue.deinit(); @@ -997,6 +1149,10 @@ pub fn performAllTheWork(self: *Compilation) error{OutOfMemory}!void { fatal("unable to update builtin.zig file: {}", .{@errorName(err)}); }; }, + .stage1_module => { + // This Job is only queued up if there is a zig module. + self.stage1_module.?.build_object(); + }, }; } @@ -1365,7 +1521,7 @@ pub fn addCCArgs( try argv.append("-fPIC"); } }, - .so, .assembly, .ll, .bc, .unknown => {}, + .shared_library, .assembly, .ll, .bc, .unknown, .static_library, .object, .zig, .zir => {}, } if (out_dep_path) |p| { try argv.appendSlice(&[_][]const u8{ "-MD", "-MV", "-MF", p }); @@ -1445,17 +1601,39 @@ pub const FileExt = enum { ll, bc, assembly, - so, + shared_library, + object, + static_library, + zig, + zir, unknown, pub fn clangSupportsDepFile(ext: FileExt) bool { return switch (ext) { .c, .cpp, .h => true, - .ll, .bc, .assembly, .so, .unknown => false, + + .ll, + .bc, + .assembly, + .shared_library, + .object, + .static_library, + .zig, + .zir, + .unknown, + => false, }; } }; +pub fn hasObjectExt(filename: []const u8) bool { + return mem.endsWith(u8, filename, ".o") or mem.endsWith(u8, filename, ".obj"); +} + +pub fn hasStaticLibraryExt(filename: []const u8) bool { + return mem.endsWith(u8, filename, ".a") or mem.endsWith(u8, filename, ".lib"); +} + pub fn hasCExt(filename: []const u8) bool { return mem.endsWith(u8, filename, ".c"); } @@ -1471,6 +1649,32 @@ pub fn hasAsmExt(filename: []const u8) bool { return mem.endsWith(u8, filename, ".s") or mem.endsWith(u8, filename, ".S"); } +pub fn hasSharedLibraryExt(filename: []const u8) bool { + if (mem.endsWith(u8, filename, ".so") or + mem.endsWith(u8, filename, ".dll") or + mem.endsWith(u8, filename, ".dylib")) + { + return true; + } + // Look for .so.X, .so.X.Y, .so.X.Y.Z + var it = mem.split(filename, "."); + _ = it.next().?; + var so_txt = it.next() orelse return false; + while (!mem.eql(u8, so_txt, "so")) { + so_txt = it.next() orelse return false; + } + const n1 = it.next() orelse return false; + const n2 = it.next(); + const n3 = it.next(); + + _ = std.fmt.parseInt(u32, n1, 10) catch return false; + if (n2) |x| _ = std.fmt.parseInt(u32, x, 10) catch return false; + if (n3) |x| _ = std.fmt.parseInt(u32, x, 10) catch return false; + if (it.next() != null) return false; + + return true; +} + pub fn classifyFileExt(filename: []const u8) FileExt { if (hasCExt(filename)) { return .c; @@ -1484,26 +1688,19 @@ pub fn classifyFileExt(filename: []const u8) FileExt { return .assembly; } else if (mem.endsWith(u8, filename, ".h")) { return .h; - } else if (mem.endsWith(u8, filename, ".so")) { - return .so; + } else if (mem.endsWith(u8, filename, ".zig")) { + return .zig; + } else if (mem.endsWith(u8, filename, ".zir")) { + return .zig; + } else if (hasSharedLibraryExt(filename)) { + return .shared_library; + } else if (hasStaticLibraryExt(filename)) { + return .static_library; + } else if (hasObjectExt(filename)) { + return .object; + } else { + return .unknown; } - // Look for .so.X, .so.X.Y, .so.X.Y.Z - var it = mem.split(filename, "."); - _ = it.next().?; - var so_txt = it.next() orelse return .unknown; - while (!mem.eql(u8, so_txt, "so")) { - so_txt = it.next() orelse return .unknown; - } - const n1 = it.next() orelse return .unknown; - const n2 = it.next(); - const n3 = it.next(); - - _ = std.fmt.parseInt(u32, n1, 10) catch return .unknown; - if (n2) |x| _ = std.fmt.parseInt(u32, x, 10) catch return .unknown; - if (n3) |x| _ = std.fmt.parseInt(u32, x, 10) catch return .unknown; - if (it.next() != null) return .unknown; - - return .so; } test "classifyFileExt" { @@ -1681,7 +1878,7 @@ pub fn dump_argv(argv: []const []const u8) void { } pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8 { - var buffer = std.ArrayList(u8).init(comp.gpa); + var buffer = std.ArrayList(u8).init(allocator); defer buffer.deinit(); const target = comp.getTarget(); @@ -1691,9 +1888,9 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8 try buffer.writer().print( \\usingnamespace @import("std").builtin; \\/// Deprecated - \\pub const arch = std.Target.current.cpu.arch; + \\pub const arch = Target.current.cpu.arch; \\/// Deprecated - \\pub const endian = std.Target.current.cpu.arch.endian(); + \\pub const endian = Target.current.cpu.arch.endian(); \\pub const output_mode = OutputMode.{}; \\pub const link_mode = LinkMode.{}; \\pub const is_test = {}; diff --git a/src-self-hosted/link.zig b/src-self-hosted/link.zig index 1ad293b275..88a964f2ff 100644 --- a/src-self-hosted/link.zig +++ b/src-self-hosted/link.zig @@ -69,6 +69,7 @@ pub const Options = struct { linker_script: ?[]const u8 = null, version_script: ?[]const u8 = null, override_soname: ?[]const u8 = null, + llvm_cpu_features: ?[*:0]const u8 = null, /// Extra args passed directly to LLD. Ignored when not linking with LLD. extra_lld_args: []const []const u8 = &[0][]const u8, @@ -134,6 +135,18 @@ pub const File = struct { /// rewriting it. A malicious file is detected as incremental link failure /// and does not cause Illegal Behavior. This operation is not atomic. pub fn openPath(allocator: *Allocator, options: Options) !*File { + const use_stage1 = build_options.is_stage1 and options.use_llvm; + if (use_stage1) { + return switch (options.object_format) { + .coff, .pe => &(try Coff.createEmpty(allocator, options)).base, + .elf => &(try Elf.createEmpty(allocator, options)).base, + .macho => &(try MachO.createEmpty(allocator, options)).base, + .wasm => &(try Wasm.createEmpty(allocator, options)).base, + .c => unreachable, // Reported error earlier. + .hex => return error.HexObjectFormatUnimplemented, + .raw => return error.RawObjectFormatUnimplemented, + }; + } const use_lld = build_options.have_llvm and options.use_lld; // comptime known false when !have_llvm const sub_path = if (use_lld) blk: { if (options.module == null) { diff --git a/src-self-hosted/link/Elf.zig b/src-self-hosted/link/Elf.zig index 62a5e486d0..5257b46279 100644 --- a/src-self-hosted/link/Elf.zig +++ b/src-self-hosted/link/Elf.zig @@ -1222,13 +1222,16 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { // If there is no Zig code to compile, then we should skip flushing the output file because it // will not be part of the linker line anyway. const module_obj_path: ?[]const u8 = if (self.base.options.module) |module| blk: { - try self.flushModule(comp); + const use_stage1 = build_options.is_stage1 and self.base.options.use_llvm; + if (use_stage1) { + const obj_basename = try std.fmt.allocPrint(arena, "{}.o", .{self.base.options.root_name}); + const full_obj_path = try directory.join(arena, &[_][]const u8{obj_basename}); + break :blk full_obj_path; + } + try self.flushModule(comp); const obj_basename = self.base.intermediary_basename.?; - const full_obj_path = if (directory.path) |dir_path| - try std.fs.path.join(arena, &[_][]const u8{dir_path, obj_basename}) - else - obj_basename; + const full_obj_path = try directory.join(arena, &[_][]const u8{obj_basename}); break :blk full_obj_path; } else null; @@ -1504,7 +1507,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { // (the check for that needs to be earlier), but they could be full paths to .so files, in which // case we want to avoid prepending "-l". const ext = Compilation.classifyFileExt(link_lib); - const arg = if (ext == .so) link_lib else try std.fmt.allocPrint(arena, "-l{}", .{link_lib}); + const arg = if (ext == .shared_library) link_lib else try std.fmt.allocPrint(arena, "-l{}", .{link_lib}); argv.appendAssumeCapacity(arg); } diff --git a/src-self-hosted/main.zig b/src-self-hosted/main.zig index f18ccdd803..6aa4be7c41 100644 --- a/src-self-hosted/main.zig +++ b/src-self-hosted/main.zig @@ -222,21 +222,27 @@ const usage_build_generic = \\ --libc [file] Provide a file which specifies libc paths \\ \\Link Options: - \\ -l[lib], --library [lib] Link against system library + \\ -l[lib], --library [lib] Link against system library \\ -L[d], --library-directory [d] Add a directory to the library search path - \\ -T[script] Use a custom linker script - \\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so) - \\ --version [ver] Dynamic library semver - \\ -rdynamic Add all symbols to the dynamic symbol table - \\ -rpath [path] Add directory to the runtime library search path - \\ --eh-frame-hdr Enable C++ exception handling by passing --eh-frame-hdr to linker - \\ -dynamic Force output to be dynamically linked - \\ -static Force output to be statically linked + \\ -T[script] Use a custom linker script + \\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so) + \\ --version [ver] Dynamic library semver + \\ -rdynamic Add all symbols to the dynamic symbol table + \\ -rpath [path] Add directory to the runtime library search path + \\ --eh-frame-hdr Enable C++ exception handling by passing --eh-frame-hdr to linker + \\ -dynamic Force output to be dynamically linked + \\ -static Force output to be statically linked \\ \\Debug Options (Zig Compiler Development): - \\ -ftime-report Print timing diagnostics - \\ --verbose-link Display linker invocations - \\ --verbose-cc Display C compiler invocations + \\ -ftime-report Print timing diagnostics + \\ --verbose-link Display linker invocations + \\ --verbose-cc Display C compiler invocations + \\ --verbose-tokenize Enable compiler debug output for tokenization + \\ --verbose-ast Enable compiler debug output for AST parsing + \\ --verbose-ir Enable compiler debug output for Zig IR + \\ --verbose-llvm-ir Enable compiler debug output for LLVM IR + \\ --verbose-cimport Enable compiler debug output for C imports + \\ --verbose-llvm-cpu-features Enable compiler debug output for LLVM CPU features \\ ; @@ -278,6 +284,12 @@ pub fn buildOutputType( var watch = false; var verbose_link = false; var verbose_cc = false; + var verbose_tokenize = false; + var verbose_ast = false; + var verbose_ir = false; + var verbose_llvm_ir = false; + var verbose_cimport = false; + var verbose_llvm_cpu_features = false; var time_report = false; var show_builtin = false; var emit_bin: Emit = .yes_default_path; @@ -548,6 +560,18 @@ pub fn buildOutputType( verbose_link = true; } else if (mem.eql(u8, arg, "--verbose-cc")) { verbose_cc = true; + } else if (mem.eql(u8, arg, "--verbose-tokenize")) { + verbose_tokenize = true; + } else if (mem.eql(u8, arg, "--verbose-ast")) { + verbose_ast = true; + } else if (mem.eql(u8, arg, "--verbose-ir")) { + verbose_ir = true; + } else if (mem.eql(u8, arg, "--verbose-llvm-ir")) { + verbose_llvm_ir = true; + } else if (mem.eql(u8, arg, "--verbose-cimport")) { + verbose_cimport = true; + } else if (mem.eql(u8, arg, "--verbose-llvm-cpu-features")) { + verbose_llvm_cpu_features = true; } else if (mem.startsWith(u8, arg, "-T")) { linker_script = arg[2..]; } else if (mem.startsWith(u8, arg, "-L")) { @@ -563,28 +587,27 @@ pub fn buildOutputType( } else { fatal("unrecognized parameter: '{}'", .{arg}); } - } else if (mem.endsWith(u8, arg, ".o") or - mem.endsWith(u8, arg, ".obj") or - mem.endsWith(u8, arg, ".a") or - mem.endsWith(u8, arg, ".lib")) - { - try link_objects.append(arg); - } else if (Compilation.hasAsmExt(arg) or Compilation.hasCExt(arg) or Compilation.hasCppExt(arg)) { - // TODO a way to pass extra flags on the CLI - try c_source_files.append(.{ .src_path = arg }); - } else if (mem.endsWith(u8, arg, ".so") or - mem.endsWith(u8, arg, ".dylib") or - mem.endsWith(u8, arg, ".dll")) - { - fatal("linking against dynamic libraries not yet supported", .{}); - } else if (mem.endsWith(u8, arg, ".zig") or mem.endsWith(u8, arg, ".zir")) { - if (root_src_file) |other| { - fatal("found another zig file '{}' after root source file '{}'", .{ arg, other }); - } else { - root_src_file = arg; - } - } else { - fatal("unrecognized file extension of parameter '{}'", .{arg}); + } else switch (Compilation.classifyFileExt(arg)) { + .object, .static_library => { + try link_objects.append(arg); + }, + .assembly, .c, .cpp, .h, .ll, .bc => { + // TODO a way to pass extra flags on the CLI + try c_source_files.append(.{ .src_path = arg }); + }, + .shared_library => { + fatal("linking against dynamic libraries not yet supported", .{}); + }, + .zig, .zir => { + if (root_src_file) |other| { + fatal("found another zig file '{}' after root source file '{}'", .{ arg, other }); + } else { + root_src_file = arg; + } + }, + .unknown => { + fatal("unrecognized file extension of parameter '{}'", .{arg}); + }, } } } else { @@ -617,7 +640,16 @@ pub fn buildOutputType( const file_ext = Compilation.classifyFileExt(mem.spanZ(it.only_arg)); switch (file_ext) { .assembly, .c, .cpp, .ll, .bc, .h => try c_source_files.append(.{ .src_path = it.only_arg }), - .unknown, .so => try link_objects.append(it.only_arg), + .unknown, .shared_library, .object, .static_library => { + try link_objects.append(it.only_arg); + }, + .zig, .zir => { + if (root_src_file) |other| { + fatal("found another zig file '{}' after root source file '{}'", .{ it.only_arg, other }); + } else { + root_src_file = it.only_arg; + } + }, } }, .l => { @@ -1173,7 +1205,15 @@ pub fn buildOutputType( .libc_installation = if (libc_installation) |*lci| lci else null, .verbose_cc = verbose_cc, .verbose_link = verbose_link, + .verbose_tokenize = verbose_tokenize, + .verbose_ast = verbose_ast, + .verbose_ir = verbose_ir, + .verbose_llvm_ir = verbose_llvm_ir, + .verbose_cimport = verbose_cimport, + .verbose_llvm_cpu_features = verbose_llvm_cpu_features, .machine_code_model = machine_code_model, + .color = color, + .time_report = time_report, }) catch |err| { fatal("unable to create compilation: {}", .{@errorName(err)}); }; @@ -1193,6 +1233,10 @@ pub fn buildOutputType( fatal("TODO: implement `zig cc` when using it as a preprocessor", .{}); } + if (build_options.is_stage1 and comp.stage1_module != null and watch) { + std.log.warn("--watch is not recommended with the stage1 backend; it leaks memory and is not capable of incremental compilation", .{}); + } + const stdin = std.io.getStdIn().inStream(); const stderr = std.io.getStdErr().outStream(); var repl_buf: [1024]u8 = undefined; diff --git a/src-self-hosted/stage1.zig b/src-self-hosted/stage1.zig index c2ce99db22..d8d32f02cd 100644 --- a/src-self-hosted/stage1.zig +++ b/src-self-hosted/stage1.zig @@ -10,6 +10,7 @@ const stage2 = @import("main.zig"); const fatal = stage2.fatal; const CrossTarget = std.zig.CrossTarget; const Target = std.Target; +const Compilation = @import("Compilation.zig"); comptime { assert(std.builtin.link_libc); @@ -23,6 +24,8 @@ pub const log_level = stage2.log_level; pub export fn main(argc: c_int, argv: [*]const [*:0]const u8) c_int { std.debug.maybeEnableSegfaultHandler(); + zig_stage1_os_init(); + const gpa = std.heap.c_allocator; var arena_instance = std.heap.ArenaAllocator.init(gpa); defer arena_instance.deinit(); @@ -36,6 +39,106 @@ pub export fn main(argc: c_int, argv: [*]const [*:0]const u8) c_int { return 0; } +/// Matches stage2.Color; +pub const ErrColor = c_int; +/// Matches std.builtin.CodeModel +pub const CodeModel = c_int; +/// Matches std.Target.Os.Tag +pub const OS = c_int; +/// Matches std.builtin.BuildMode +pub const BuildMode = c_int; + +pub const TargetSubsystem = extern enum(c_int) { + Console, + Windows, + Posix, + Native, + EfiApplication, + EfiBootServiceDriver, + EfiRom, + EfiRuntimeDriver, + Auto, +}; + +pub const Pkg = extern struct { + name_ptr: [*]const u8, + name_len: usize, + path_ptr: [*]const u8, + path_len: usize, + children_ptr: [*]*Pkg, + children_len: usize, + parent: ?*Pkg, +}; + +pub const Module = extern struct { + root_name_ptr: [*]const u8, + root_name_len: usize, + output_dir_ptr: [*]const u8, + output_dir_len: usize, + builtin_zig_path_ptr: [*]const u8, + builtin_zig_path_len: usize, + test_filter_ptr: [*]const u8, + test_filter_len: usize, + test_name_prefix_ptr: [*]const u8, + test_name_prefix_len: usize, + userdata: usize, + root_pkg: *Pkg, + main_progress_node: ?*std.Progress.Node, + code_model: CodeModel, + subsystem: TargetSubsystem, + err_color: ErrColor, + pic: bool, + link_libc: bool, + link_libcpp: bool, + strip: bool, + is_single_threaded: bool, + dll_export_fns: bool, + link_mode_dynamic: bool, + valgrind_enabled: bool, + function_sections: bool, + enable_stack_probing: bool, + enable_time_report: bool, + enable_stack_report: bool, + dump_analysis: bool, + enable_doc_generation: bool, + emit_bin: bool, + emit_asm: bool, + emit_llvm_ir: bool, + test_is_evented: bool, + verbose_tokenize: bool, + verbose_ast: bool, + verbose_ir: bool, + verbose_llvm_ir: bool, + verbose_cimport: bool, + verbose_llvm_cpu_features: bool, + + pub fn build_object(mod: *Module) void { + zig_stage1_build_object(mod); + } + + pub fn destroy(mod: *Module) void { + zig_stage1_destroy(mod); + } +}; + +extern fn zig_stage1_os_init() void; + +pub const create = zig_stage1_create; +extern fn zig_stage1_create( + optimize_mode: BuildMode, + main_pkg_path_ptr: [*]const u8, + main_pkg_path_len: usize, + root_src_path_ptr: [*]const u8, + root_src_path_len: usize, + zig_lib_dir_ptr: [*c]const u8, + zig_lib_dir_len: usize, + target: [*c]const Stage2Target, + is_test_build: bool, +) ?*Module; + +extern fn zig_stage1_build_object(*Module) void; +extern fn zig_stage1_destroy(*Module) void; + // ABI warning export fn stage2_panic(ptr: [*]const u8, len: usize) void { @panic(ptr[0..len]); @@ -199,297 +302,50 @@ export fn stage2_progress_update_node(node: *std.Progress.Node, done_count: usiz } // ABI warning -const Stage2Target = extern struct { +pub const Stage2Target = extern struct { arch: c_int, - vendor: c_int, - + os: OS, abi: c_int, - os: c_int, is_native_os: bool, is_native_cpu: bool, llvm_cpu_name: ?[*:0]const u8, llvm_cpu_features: ?[*:0]const u8, - cpu_builtin_str: ?[*:0]const u8, - os_builtin_str: ?[*:0]const u8, - - dynamic_linker: ?[*:0]const u8, - - llvm_cpu_features_asm_ptr: [*]const [*:0]const u8, - llvm_cpu_features_asm_len: usize, - - fn fromTarget(self: *Stage2Target, cross_target: CrossTarget) !void { - const allocator = std.heap.c_allocator; - - var dynamic_linker: ?[*:0]u8 = null; - const target = try crossTargetToTarget(cross_target, &dynamic_linker); - - const generic_arch_name = target.cpu.arch.genericName(); - var cpu_builtin_str_buffer = try std.ArrayListSentineled(u8, 0).allocPrint(allocator, - \\Cpu{{ - \\ .arch = .{}, - \\ .model = &Target.{}.cpu.{}, - \\ .features = Target.{}.featureSet(&[_]Target.{}.Feature{{ - \\ - , .{ - @tagName(target.cpu.arch), - generic_arch_name, - target.cpu.model.name, - generic_arch_name, - generic_arch_name, - }); - defer cpu_builtin_str_buffer.deinit(); - - var llvm_features_buffer = try std.ArrayListSentineled(u8, 0).initSize(allocator, 0); - defer llvm_features_buffer.deinit(); - - // Unfortunately we have to do the work twice, because Clang does not support - // the same command line parameters for CPU features when assembling code as it does - // when compiling C code. - var asm_features_list = std.ArrayList([*:0]const u8).init(allocator); - defer asm_features_list.deinit(); - - for (target.cpu.arch.allFeaturesList()) |feature, index_usize| { - const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize); - const is_enabled = target.cpu.features.isEnabled(index); - - if (feature.llvm_name) |llvm_name| { - const plus_or_minus = "-+"[@boolToInt(is_enabled)]; - try llvm_features_buffer.append(plus_or_minus); - try llvm_features_buffer.appendSlice(llvm_name); - try llvm_features_buffer.appendSlice(","); - } - - if (is_enabled) { - // TODO some kind of "zig identifier escape" function rather than - // unconditionally using @"" syntax - try cpu_builtin_str_buffer.appendSlice(" .@\""); - try cpu_builtin_str_buffer.appendSlice(feature.name); - try cpu_builtin_str_buffer.appendSlice("\",\n"); - } - } - - switch (target.cpu.arch) { - .riscv32, .riscv64 => { - if (Target.riscv.featureSetHas(target.cpu.features, .relax)) { - try asm_features_list.append("-mrelax"); - } else { - try asm_features_list.append("-mno-relax"); - } - }, - else => { - // TODO - // Argh, why doesn't the assembler accept the list of CPU features?! - // I don't see a way to do this other than hard coding everything. - }, - } - - try cpu_builtin_str_buffer.appendSlice( - \\ }), - \\}; - \\ - ); - - assert(mem.endsWith(u8, llvm_features_buffer.span(), ",")); - llvm_features_buffer.shrink(llvm_features_buffer.len() - 1); - - var os_builtin_str_buffer = try std.ArrayListSentineled(u8, 0).allocPrint(allocator, - \\Os{{ - \\ .tag = .{}, - \\ .version_range = .{{ - , .{@tagName(target.os.tag)}); - defer os_builtin_str_buffer.deinit(); - - // We'll re-use the OS version range builtin string for the cache hash. - const os_builtin_str_ver_start_index = os_builtin_str_buffer.len(); - - @setEvalBranchQuota(2000); - switch (target.os.tag) { - .freestanding, - .ananas, - .cloudabi, - .dragonfly, - .fuchsia, - .ios, - .kfreebsd, - .lv2, - .solaris, - .haiku, - .minix, - .rtems, - .nacl, - .cnk, - .aix, - .cuda, - .nvcl, - .amdhsa, - .ps4, - .elfiamcu, - .tvos, - .watchos, - .mesa3d, - .contiki, - .amdpal, - .hermit, - .hurd, - .wasi, - .emscripten, - .uefi, - .other, - => try os_builtin_str_buffer.appendSlice(" .none = {} }\n"), - - .freebsd, - .macosx, - .netbsd, - .openbsd, - => try os_builtin_str_buffer.outStream().print( - \\ .semver = .{{ - \\ .min = .{{ - \\ .major = {}, - \\ .minor = {}, - \\ .patch = {}, - \\ }}, - \\ .max = .{{ - \\ .major = {}, - \\ .minor = {}, - \\ .patch = {}, - \\ }}, - \\ }}}}, - \\ - , .{ - target.os.version_range.semver.min.major, - target.os.version_range.semver.min.minor, - target.os.version_range.semver.min.patch, - - target.os.version_range.semver.max.major, - target.os.version_range.semver.max.minor, - target.os.version_range.semver.max.patch, - }), - - .linux => try os_builtin_str_buffer.outStream().print( - \\ .linux = .{{ - \\ .range = .{{ - \\ .min = .{{ - \\ .major = {}, - \\ .minor = {}, - \\ .patch = {}, - \\ }}, - \\ .max = .{{ - \\ .major = {}, - \\ .minor = {}, - \\ .patch = {}, - \\ }}, - \\ }}, - \\ .glibc = .{{ - \\ .major = {}, - \\ .minor = {}, - \\ .patch = {}, - \\ }}, - \\ }}}}, - \\ - , .{ - target.os.version_range.linux.range.min.major, - target.os.version_range.linux.range.min.minor, - target.os.version_range.linux.range.min.patch, - - target.os.version_range.linux.range.max.major, - target.os.version_range.linux.range.max.minor, - target.os.version_range.linux.range.max.patch, - - target.os.version_range.linux.glibc.major, - target.os.version_range.linux.glibc.minor, - target.os.version_range.linux.glibc.patch, - }), - - .windows => try os_builtin_str_buffer.outStream().print( - \\ .windows = .{{ - \\ .min = {s}, - \\ .max = {s}, - \\ }}}}, - \\ - , .{ - target.os.version_range.windows.min, - target.os.version_range.windows.max, - }), - } - try os_builtin_str_buffer.appendSlice("};\n"); - - const glibc_or_darwin_version = blk: { - if (target.isGnuLibC()) { - const stage1_glibc = try std.heap.c_allocator.create(Stage2SemVer); - const stage2_glibc = target.os.version_range.linux.glibc; - stage1_glibc.* = .{ - .major = stage2_glibc.major, - .minor = stage2_glibc.minor, - .patch = stage2_glibc.patch, - }; - break :blk stage1_glibc; - } else if (target.isDarwin()) { - const stage1_semver = try std.heap.c_allocator.create(Stage2SemVer); - const stage2_semver = target.os.version_range.semver.min; - stage1_semver.* = .{ - .major = stage2_semver.major, - .minor = stage2_semver.minor, - .patch = stage2_semver.patch, - }; - break :blk stage1_semver; - } else { - break :blk null; - } - }; - - const std_dl = target.standardDynamicLinkerPath(); - const std_dl_z = if (std_dl.get()) |dl| - (try mem.dupeZ(std.heap.c_allocator, u8, dl)).ptr - else - null; - - const asm_features = asm_features_list.toOwnedSlice(); - self.* = .{ - .arch = @enumToInt(target.cpu.arch) + 1, // skip over ZigLLVM_UnknownArch - .vendor = 0, - .os = @enumToInt(target.os.tag), - .abi = @enumToInt(target.abi), - .llvm_cpu_name = if (target.cpu.model.llvm_name) |s| s.ptr else null, - .llvm_cpu_features = llvm_features_buffer.toOwnedSlice().ptr, - .llvm_cpu_features_asm_ptr = asm_features.ptr, - .llvm_cpu_features_asm_len = asm_features.len, - .cpu_builtin_str = cpu_builtin_str_buffer.toOwnedSlice().ptr, - .os_builtin_str = os_builtin_str_buffer.toOwnedSlice().ptr, - .is_native_os = cross_target.isNativeOs(), - .is_native_cpu = cross_target.isNativeCpu(), - .glibc_or_darwin_version = glibc_or_darwin_version, - .dynamic_linker = dynamic_linker, - .standard_dynamic_linker_path = std_dl_z, - }; - } }; -fn crossTargetToTarget(cross_target: CrossTarget, dynamic_linker_ptr: *?[*:0]u8) !Target { - var info = try std.zig.system.NativeTargetInfo.detect(std.heap.c_allocator, cross_target); - if (info.cpu_detection_unimplemented) { - // TODO We want to just use detected_info.target but implementing - // CPU model & feature detection is todo so here we rely on LLVM. - const llvm = @import("llvm.zig"); - const llvm_cpu_name = llvm.GetHostCPUName(); - const llvm_cpu_features = llvm.GetNativeFeatures(); - const arch = Target.current.cpu.arch; - info.target.cpu = try detectNativeCpuWithLLVM(arch, llvm_cpu_name, llvm_cpu_features); - cross_target.updateCpuFeatures(&info.target.cpu.features); - info.target.cpu.arch = cross_target.getCpuArch(); - } - if (info.dynamic_linker.get()) |dl| { - dynamic_linker_ptr.* = try mem.dupeZ(std.heap.c_allocator, u8, dl); - } else { - dynamic_linker_ptr.* = null; - } - return info.target; -} - // ABI warning const Stage2SemVer = extern struct { major: u32, minor: u32, patch: u32, }; + +// ABI warning +export fn stage2_cimport(stage1: *Module) [*:0]const u8 { + @panic("TODO implement stage2_cimport"); +} + +export fn stage2_add_link_lib( + stage1: *Module, + lib_name_ptr: [*c]const u8, + lib_name_len: usize, + symbol_name_ptr: [*c]const u8, + symbol_name_len: usize, +) ?[*:0]const u8 { + return null; // no error +} + +export fn stage2_fetch_file( + stage1: *Module, + path_ptr: [*]const u8, + path_len: usize, + result_len: *usize, +) ?[*]const u8 { + const comp = @intToPtr(*Compilation, stage1.userdata); + // TODO integrate this with cache hash + const file_path = path_ptr[0..path_len]; + const contents = std.fs.cwd().readFileAlloc(comp.gpa, file_path, std.math.maxInt(u32)) catch return null; + result_len.* = contents.len; + return contents.ptr; +} diff --git a/src/analyze.cpp b/src/analyze.cpp index ea19d81995..6c6f198e7a 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -7987,7 +7987,7 @@ Error file_fetch(CodeGen *g, Buf *resolved_path, Buf *contents_buf) { size_t len; const char *contents = stage2_fetch_file(&g->stage1, buf_ptr(resolved_path), buf_len(resolved_path), &len); if (contents == nullptr) - return ErrorNoMem; + return ErrorFileNotFound; buf_init_from_mem(contents_buf, contents, len); return ErrorNone; } diff --git a/src/codegen.cpp b/src/codegen.cpp index 07728ef06e..6768021410 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8809,33 +8809,18 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { static_assert(TargetSubsystemEfiBootServiceDriver == 5, ""); static_assert(TargetSubsystemEfiRom == 6, ""); static_assert(TargetSubsystemEfiRuntimeDriver == 7, ""); - { - const char *endian_str = g->is_big_endian ? "Endian.Big" : "Endian.Little"; - buf_appendf(contents, "pub const endian = %s;\n", endian_str); - } + + buf_append_str(contents, "/// Deprecated: use `std.Target.current.cpu.arch`\n"); + buf_append_str(contents, "pub const arch = Target.current.cpu.arch;\n"); + buf_append_str(contents, "/// Deprecated: use `std.Target.current.cpu.arch.endian()`\n"); + buf_append_str(contents, "pub const endian = Target.current.cpu.arch.endian();\n"); buf_appendf(contents, "pub const output_mode = OutputMode.Obj;\n"); buf_appendf(contents, "pub const link_mode = LinkMode.Static;\n"); buf_appendf(contents, "pub const is_test = false;\n"); buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded)); - buf_append_str(contents, "/// Deprecated: use `std.Target.cpu.arch`\n"); - buf_appendf(contents, "pub const arch = Arch.%s;\n", cur_arch); buf_appendf(contents, "pub const abi = Abi.%s;\n", cur_abi); - { - buf_append_str(contents, "pub const cpu: Cpu = "); - if (g->zig_target->cpu_builtin_str != nullptr) { - buf_append_str(contents, g->zig_target->cpu_builtin_str); - } else { - buf_appendf(contents, "Target.Cpu.baseline(.%s);\n", cur_arch); - } - } - { - buf_append_str(contents, "pub const os = "); - if (g->zig_target->os_builtin_str != nullptr) { - buf_append_str(contents, g->zig_target->os_builtin_str); - } else { - buf_appendf(contents, "Target.Os.Tag.defaultVersionRange(.%s);\n", cur_os); - } - } + buf_appendf(contents, "pub const cpu: Cpu = Target.Cpu.baseline(.%s);\n", cur_arch); + buf_appendf(contents, "pub const os = Target.Os.Tag.defaultVersionRange(.%s);\n", cur_os); buf_appendf(contents, "pub const object_format = ObjectFormat.%s;\n", cur_obj_fmt); buf_appendf(contents, "pub const mode = %s;\n", build_mode_to_str(g->build_mode)); 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) { if (g->std_package == nullptr) return ErrorNone; + assert(g->main_pkg); + const char *builtin_zig_basename = "builtin.zig"; Buf *contents; @@ -8879,17 +8866,22 @@ static Error define_builtin_compile_vars(CodeGen *g) { fprintf(stderr, "Unable to write file '%s': %s\n", buf_ptr(g->builtin_zig_path), err_str(err)); exit(1); } + + g->compile_var_package = new_package(buf_ptr(g->output_dir), builtin_zig_basename, "builtin"); } else { + Buf *resolve_paths[] = { g->builtin_zig_path, }; + *g->builtin_zig_path = os_path_resolve(resolve_paths, 1); + contents = buf_alloc(); if ((err = os_fetch_file_path(g->builtin_zig_path, contents))) { fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(g->builtin_zig_path), err_str(err)); exit(1); } + Buf builtin_dirname = BUF_INIT; + os_path_dirname(g->builtin_zig_path, &builtin_dirname); + g->compile_var_package = new_package(buf_ptr(&builtin_dirname), builtin_zig_basename, "builtin"); } - assert(g->main_pkg); - assert(g->std_package); - g->compile_var_package = new_package(buf_ptr(g->output_dir), builtin_zig_basename, "builtin"); if (g->is_test_build) { if (g->test_runner_package == nullptr) { g->test_runner_package = create_test_runner_pkg(g); @@ -8914,6 +8906,13 @@ static void init(CodeGen *g) { if (g->module) return; + codegen_add_time_event(g, "Initialize"); + { + const char *progress_name = "Initialize"; + codegen_switch_sub_prog_node(g, stage2_progress_start(g->main_progress_node, + progress_name, strlen(progress_name), 0)); + } + g->have_err_ret_tracing = detect_err_ret_tracing(g); assert(g->root_out_name); @@ -9374,19 +9373,11 @@ void codegen_destroy(CodeGen *g) { CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target, BuildMode build_mode, Buf *override_lib_dir, - bool is_test_build, Stage2ProgressNode *progress_node) + bool is_test_build) { CodeGen *g = heap::c_allocator.create(); g->emit_bin = true; g->pass1_arena = heap::ArenaAllocator::construct(&heap::c_allocator, &heap::c_allocator, "pass1"); - g->main_progress_node = progress_node; - - codegen_add_time_event(g, "Initialize"); - { - const char *progress_name = "Initialize"; - codegen_switch_sub_prog_node(g, stage2_progress_start(g->main_progress_node, - progress_name, strlen(progress_name), 0)); - } g->subsystem = TargetSubsystemAuto; g->zig_target = target; @@ -9440,7 +9431,7 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget Buf resolved_main_pkg_path = os_path_resolve(&main_pkg_path, 1); if (!buf_starts_with_buf(&resolved_root_src_path, &resolved_main_pkg_path)) { - fprintf(stderr, "Root source path '%s' outside main package path '%s'", + fprintf(stderr, "Root source path '%s' outside main package path '%s'\n", buf_ptr(root_src_path), buf_ptr(main_pkg_path)); exit(1); } diff --git a/src/codegen.hpp b/src/codegen.hpp index 5b4317c992..33b2f74757 100644 --- a/src/codegen.hpp +++ b/src/codegen.hpp @@ -16,8 +16,7 @@ #include CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target, - BuildMode build_mode, Buf *zig_lib_dir, - bool is_test_build, Stage2ProgressNode *progress_node); + BuildMode build_mode, Buf *zig_lib_dir, bool is_test_build); void codegen_build_object(CodeGen *g); void codegen_destroy(CodeGen *); diff --git a/src/stage1.cpp b/src/stage1.cpp index 36d59c0a05..b5b87c05d9 100644 --- a/src/stage1.cpp +++ b/src/stage1.cpp @@ -20,13 +20,14 @@ struct ZigStage1 *zig_stage1_create(BuildMode optimize_mode, const char *main_pkg_path_ptr, size_t main_pkg_path_len, const char *root_src_path_ptr, size_t root_src_path_len, const char *zig_lib_dir_ptr, size_t zig_lib_dir_len, - const ZigTarget *target, bool is_test_build, Stage2ProgressNode *progress_node) + const ZigTarget *target, bool is_test_build) { - Buf *main_pkg_path = buf_create_from_mem(main_pkg_path_ptr, main_pkg_path_len); + Buf *main_pkg_path = (main_pkg_path_len == 0) ? + nullptr : buf_create_from_mem(main_pkg_path_ptr, main_pkg_path_len); Buf *root_src_path = buf_create_from_mem(root_src_path_ptr, root_src_path_len); Buf *zig_lib_dir = buf_create_from_mem(zig_lib_dir_ptr, zig_lib_dir_len); CodeGen *g = codegen_create(main_pkg_path, root_src_path, target, optimize_mode, - zig_lib_dir, is_test_build, progress_node); + zig_lib_dir, is_test_build); return &g->stage1; } @@ -68,8 +69,6 @@ void zig_stage1_build_object(struct ZigStage1 *stage1) { CodeGen *g = reinterpret_cast(stage1); g->root_out_name = buf_create_from_mem(stage1->root_name_ptr, stage1->root_name_len); - g->zig_lib_dir = buf_create_from_mem(stage1->zig_lib_dir_ptr, stage1->zig_lib_dir_len); - g->zig_std_dir = buf_create_from_mem(stage1->zig_std_dir_ptr, stage1->zig_std_dir_len); g->output_dir = buf_create_from_mem(stage1->output_dir_ptr, stage1->output_dir_len); if (stage1->builtin_zig_path_len != 0) { 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) { } } + g->main_progress_node = stage1->main_progress_node; + add_package(g, stage1->root_pkg, g->main_pkg); codegen_build_object(g); diff --git a/src/stage1.h b/src/stage1.h index 5b0c4a4df6..c0bd0f70fc 100644 --- a/src/stage1.h +++ b/src/stage1.h @@ -100,22 +100,14 @@ enum Os { // ABI warning struct ZigTarget { enum ZigLLVM_ArchType arch; - enum ZigLLVM_VendorType vendor; - + enum Os os; enum ZigLLVM_EnvironmentType abi; - Os os; bool is_native_os; bool is_native_cpu; const char *llvm_cpu_name; const char *llvm_cpu_features; - const char *cpu_builtin_str; - const char *os_builtin_str; - const char *dynamic_linker; - - const char **llvm_cpu_features_asm_ptr; - size_t llvm_cpu_features_asm_len; }; // ABI warning @@ -161,18 +153,13 @@ struct ZigStage1 { const char *test_name_prefix_ptr; size_t test_name_prefix_len; - const char *zig_lib_dir_ptr; - size_t zig_lib_dir_len; - - const char *zig_std_dir_ptr; - size_t zig_std_dir_len; - void *userdata; struct ZigStage1Pkg *root_pkg; + struct Stage2ProgressNode *main_progress_node; - CodeModel code_model; - TargetSubsystem subsystem; - ErrColor err_color; + enum CodeModel code_model; + enum TargetSubsystem subsystem; + enum ErrColor err_color; bool pic; bool link_libc; @@ -206,7 +193,7 @@ ZIG_EXTERN_C struct ZigStage1 *zig_stage1_create(enum BuildMode optimize_mode, const char *main_pkg_path_ptr, size_t main_pkg_path_len, const char *root_src_path_ptr, size_t root_src_path_len, const char *zig_lib_dir_ptr, size_t zig_lib_dir_len, - const ZigTarget *target, bool is_test_build, Stage2ProgressNode *progress_node); + const struct ZigTarget *target, bool is_test_build); ZIG_EXTERN_C void zig_stage1_build_object(struct ZigStage1 *); diff --git a/src/stage2.cpp b/src/stage2.cpp deleted file mode 100644 index f8b078c237..0000000000 --- a/src/stage2.cpp +++ /dev/null @@ -1,241 +0,0 @@ -// This file is a shim for zig1. The real implementations of these are in -// src-self-hosted/stage1.zig - -#include "stage2.h" -#include "util.hpp" -#include "zig_llvm.h" -#include "target.hpp" -#include "buffer.hpp" -#include "os.hpp" -#include -#include -#include - -void stage2_panic(const char *ptr, size_t len) { - fwrite(ptr, 1, len, stderr); - fprintf(stderr, "\n"); - fflush(stderr); - abort(); -} - -struct Stage2Progress { - int trash; -}; - -struct Stage2ProgressNode { - int trash; -}; - -Stage2Progress *stage2_progress_create(void) { - return nullptr; -} - -void stage2_progress_destroy(Stage2Progress *progress) {} - -Stage2ProgressNode *stage2_progress_start_root(Stage2Progress *progress, - const char *name_ptr, size_t name_len, size_t estimated_total_items) -{ - return nullptr; -} -Stage2ProgressNode *stage2_progress_start(Stage2ProgressNode *node, - const char *name_ptr, size_t name_len, size_t estimated_total_items) -{ - return nullptr; -} -void stage2_progress_end(Stage2ProgressNode *node) {} -void stage2_progress_complete_one(Stage2ProgressNode *node) {} -void stage2_progress_disable_tty(Stage2Progress *progress) {} -void stage2_progress_update_node(Stage2ProgressNode *node, size_t completed_count, size_t estimated_total_items){} - -static Os get_zig_os_type(ZigLLVM_OSType os_type) { - switch (os_type) { - case ZigLLVM_UnknownOS: - return OsFreestanding; - case ZigLLVM_Ananas: - return OsAnanas; - case ZigLLVM_CloudABI: - return OsCloudABI; - case ZigLLVM_DragonFly: - return OsDragonFly; - case ZigLLVM_FreeBSD: - return OsFreeBSD; - case ZigLLVM_Fuchsia: - return OsFuchsia; - case ZigLLVM_IOS: - return OsIOS; - case ZigLLVM_KFreeBSD: - return OsKFreeBSD; - case ZigLLVM_Linux: - return OsLinux; - case ZigLLVM_Lv2: - return OsLv2; - case ZigLLVM_Darwin: - case ZigLLVM_MacOSX: - return OsMacOSX; - case ZigLLVM_NetBSD: - return OsNetBSD; - case ZigLLVM_OpenBSD: - return OsOpenBSD; - case ZigLLVM_Solaris: - return OsSolaris; - case ZigLLVM_Win32: - return OsWindows; - case ZigLLVM_Haiku: - return OsHaiku; - case ZigLLVM_Minix: - return OsMinix; - case ZigLLVM_RTEMS: - return OsRTEMS; - case ZigLLVM_NaCl: - return OsNaCl; - case ZigLLVM_CNK: - return OsCNK; - case ZigLLVM_AIX: - return OsAIX; - case ZigLLVM_CUDA: - return OsCUDA; - case ZigLLVM_NVCL: - return OsNVCL; - case ZigLLVM_AMDHSA: - return OsAMDHSA; - case ZigLLVM_PS4: - return OsPS4; - case ZigLLVM_ELFIAMCU: - return OsELFIAMCU; - case ZigLLVM_TvOS: - return OsTvOS; - case ZigLLVM_WatchOS: - return OsWatchOS; - case ZigLLVM_Mesa3D: - return OsMesa3D; - case ZigLLVM_Contiki: - return OsContiki; - case ZigLLVM_AMDPAL: - return OsAMDPAL; - case ZigLLVM_HermitCore: - return OsHermitCore; - case ZigLLVM_Hurd: - return OsHurd; - case ZigLLVM_WASI: - return OsWASI; - case ZigLLVM_Emscripten: - return OsEmscripten; - } - zig_unreachable(); -} - -static void get_native_target(ZigTarget *target) { - // first zero initialize - *target = {}; - - ZigLLVM_OSType os_type; - ZigLLVM_ObjectFormatType oformat; // ignored; based on arch/os - ZigLLVMGetNativeTarget( - &target->arch, - &target->vendor, - &os_type, - &target->abi, - &oformat); - target->os = get_zig_os_type(os_type); - target->is_native_os = true; - target->is_native_cpu = true; - if (target->abi == ZigLLVM_UnknownEnvironment) { - target->abi = target_default_abi(target->arch, target->os); - } -} - -Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, const char *mcpu, - const char *dynamic_linker) -{ - Error err; - - if (zig_triple != nullptr && strcmp(zig_triple, "native") == 0) { - zig_triple = nullptr; - } - - if (zig_triple == nullptr) { - get_native_target(target); - - if (mcpu == nullptr) { - target->llvm_cpu_name = ZigLLVMGetHostCPUName(); - target->llvm_cpu_features = ZigLLVMGetNativeFeatures(); - } else if (strcmp(mcpu, "baseline") == 0) { - target->is_native_os = false; - target->is_native_cpu = false; - target->llvm_cpu_name = ""; - target->llvm_cpu_features = ""; - } else { - const char *msg = "stage0 can't handle CPU/features in the target"; - stage2_panic(msg, strlen(msg)); - } - } else { - // first initialize all to zero - *target = {}; - - SplitIterator it = memSplit(str(zig_triple), str("-")); - - Optional> opt_archsub = SplitIterator_next(&it); - Optional> opt_os = SplitIterator_next(&it); - Optional> opt_abi = SplitIterator_next(&it); - - if (!opt_archsub.is_some) - return ErrorMissingArchitecture; - - if ((err = target_parse_arch(&target->arch, (char*)opt_archsub.value.ptr, opt_archsub.value.len))) { - return err; - } - - if (!opt_os.is_some) - return ErrorMissingOperatingSystem; - - if ((err = target_parse_os(&target->os, (char*)opt_os.value.ptr, opt_os.value.len))) { - return err; - } - - if (opt_abi.is_some) { - if ((err = target_parse_abi(&target->abi, (char*)opt_abi.value.ptr, opt_abi.value.len))) { - return err; - } - } else { - target->abi = target_default_abi(target->arch, target->os); - } - - if (mcpu != nullptr && strcmp(mcpu, "baseline") != 0) { - const char *msg = "stage0 can't handle CPU/features in the target"; - stage2_panic(msg, strlen(msg)); - } - } - - if (dynamic_linker != nullptr) { - target->dynamic_linker = dynamic_linker; - } - - return ErrorNone; -} - -const char *stage2_fetch_file(struct ZigStage1 *stage1, const char *path_ptr, size_t path_len, - size_t *result_len) -{ - Error err; - Buf contents_buf = BUF_INIT; - Buf path_buf = BUF_INIT; - - buf_init_from_mem(&path_buf, path_ptr, path_len); - if ((err = os_fetch_file_path(&path_buf, &contents_buf))) { - return nullptr; - } - *result_len = buf_len(&contents_buf); - return buf_ptr(&contents_buf); -} - -const char *stage2_cimport(struct ZigStage1 *stage1) { - const char *msg = "stage0 called stage2_cimport"; - stage2_panic(msg, strlen(msg)); -} - -const char *stage2_add_link_lib(struct ZigStage1 *stage1, - const char *lib_name_ptr, size_t lib_name_len, - const char *symbol_name_ptr, size_t symbol_name_len) -{ - return nullptr; -} diff --git a/src/stage2.h b/src/stage2.h index 4bc92631dc..104faa6ca8 100644 --- a/src/stage2.h +++ b/src/stage2.h @@ -130,23 +130,23 @@ struct Stage2ErrorMsg { ZIG_EXTERN_C ZIG_ATTRIBUTE_NORETURN void stage2_panic(const char *ptr, size_t len); // ABI warning -ZIG_EXTERN_C Stage2Progress *stage2_progress_create(void); +ZIG_EXTERN_C struct Stage2Progress *stage2_progress_create(void); // ABI warning -ZIG_EXTERN_C void stage2_progress_disable_tty(Stage2Progress *progress); +ZIG_EXTERN_C void stage2_progress_disable_tty(struct Stage2Progress *progress); // ABI warning -ZIG_EXTERN_C void stage2_progress_destroy(Stage2Progress *progress); +ZIG_EXTERN_C void stage2_progress_destroy(struct Stage2Progress *progress); // ABI warning -ZIG_EXTERN_C Stage2ProgressNode *stage2_progress_start_root(Stage2Progress *progress, +ZIG_EXTERN_C struct Stage2ProgressNode *stage2_progress_start_root(struct Stage2Progress *progress, const char *name_ptr, size_t name_len, size_t estimated_total_items); // ABI warning -ZIG_EXTERN_C Stage2ProgressNode *stage2_progress_start(Stage2ProgressNode *node, +ZIG_EXTERN_C struct Stage2ProgressNode *stage2_progress_start(struct Stage2ProgressNode *node, const char *name_ptr, size_t name_len, size_t estimated_total_items); // ABI warning -ZIG_EXTERN_C void stage2_progress_end(Stage2ProgressNode *node); +ZIG_EXTERN_C void stage2_progress_end(struct Stage2ProgressNode *node); // ABI warning -ZIG_EXTERN_C void stage2_progress_complete_one(Stage2ProgressNode *node); +ZIG_EXTERN_C void stage2_progress_complete_one(struct Stage2ProgressNode *node); // ABI warning -ZIG_EXTERN_C void stage2_progress_update_node(Stage2ProgressNode *node, +ZIG_EXTERN_C void stage2_progress_update_node(struct Stage2ProgressNode *node, size_t completed_count, size_t estimated_total_items); // ABI warning diff --git a/src/target.cpp b/src/target.cpp index f1cab8eded..433c988a01 100644 --- a/src/target.cpp +++ b/src/target.cpp @@ -380,10 +380,6 @@ Error target_parse_abi(ZigLLVM_EnvironmentType *out_abi, const char *abi_ptr, si return ErrorUnknownABI; } -Error target_parse_triple(ZigTarget *target, const char *triple, const char *mcpu, const char *dynamic_linker) { - return stage2_target_parse(target, triple, mcpu, dynamic_linker); -} - const char *target_arch_name(ZigLLVM_ArchType arch) { return ZigLLVMGetArchTypeName(arch); } @@ -408,7 +404,7 @@ void target_triple_llvm(Buf *triple, const ZigTarget *target) { buf_resize(triple, 0); buf_appendf(triple, "%s-%s-%s-%s", ZigLLVMGetArchTypeName(target->arch), - ZigLLVMGetVendorTypeName(target->vendor), + ZigLLVMGetVendorTypeName(ZigLLVM_UnknownVendor), ZigLLVMGetOSTypeName(get_llvm_os_type(target->os)), ZigLLVMGetEnvironmentTypeName(target->abi)); } @@ -1149,7 +1145,6 @@ void target_libc_enum(size_t index, ZigTarget *out_target) { out_target->arch = libcs_available[index].arch; out_target->os = libcs_available[index].os; out_target->abi = libcs_available[index].abi; - out_target->vendor = ZigLLVM_UnknownVendor; out_target->is_native_os = false; out_target->is_native_cpu = false; } diff --git a/src/target.hpp b/src/target.hpp index c9db4754f9..d34c2aeae5 100644 --- a/src/target.hpp +++ b/src/target.hpp @@ -25,7 +25,6 @@ enum CIntType { CIntTypeCount, }; -Error target_parse_triple(ZigTarget *target, const char *triple, const char *mcpu, const char *dynamic_linker); Error target_parse_arch(ZigLLVM_ArchType *arch, const char *arch_ptr, size_t arch_len); Error target_parse_os(Os *os, const char *os_ptr, size_t os_len); Error target_parse_abi(ZigLLVM_EnvironmentType *abi, const char *abi_ptr, size_t abi_len); diff --git a/src/zig0.cpp b/src/zig0.cpp index 62378ff68c..bd447abded 100644 --- a/src/zig0.cpp +++ b/src/zig0.cpp @@ -14,6 +14,9 @@ #include "stage2.h" #include "target.hpp" #include "error.hpp" +#include "util.hpp" +#include "buffer.hpp" +#include "os.hpp" #include #include @@ -33,7 +36,6 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) { " --output-dir [dir] override output directory (defaults to cwd)\n" " --pkg-begin [name] [path] make pkg available to import and push current pkg\n" " --pkg-end pop current pkg\n" - " --main-pkg-path set the directory of the root package\n" " --release-fast build with optimizations on and safety off\n" " --release-safe build with optimizations on and safety on\n" " --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) { return return_code; } +static Os get_zig_os_type(ZigLLVM_OSType os_type) { + switch (os_type) { + case ZigLLVM_UnknownOS: + return OsFreestanding; + case ZigLLVM_Ananas: + return OsAnanas; + case ZigLLVM_CloudABI: + return OsCloudABI; + case ZigLLVM_DragonFly: + return OsDragonFly; + case ZigLLVM_FreeBSD: + return OsFreeBSD; + case ZigLLVM_Fuchsia: + return OsFuchsia; + case ZigLLVM_IOS: + return OsIOS; + case ZigLLVM_KFreeBSD: + return OsKFreeBSD; + case ZigLLVM_Linux: + return OsLinux; + case ZigLLVM_Lv2: + return OsLv2; + case ZigLLVM_Darwin: + case ZigLLVM_MacOSX: + return OsMacOSX; + case ZigLLVM_NetBSD: + return OsNetBSD; + case ZigLLVM_OpenBSD: + return OsOpenBSD; + case ZigLLVM_Solaris: + return OsSolaris; + case ZigLLVM_Win32: + return OsWindows; + case ZigLLVM_Haiku: + return OsHaiku; + case ZigLLVM_Minix: + return OsMinix; + case ZigLLVM_RTEMS: + return OsRTEMS; + case ZigLLVM_NaCl: + return OsNaCl; + case ZigLLVM_CNK: + return OsCNK; + case ZigLLVM_AIX: + return OsAIX; + case ZigLLVM_CUDA: + return OsCUDA; + case ZigLLVM_NVCL: + return OsNVCL; + case ZigLLVM_AMDHSA: + return OsAMDHSA; + case ZigLLVM_PS4: + return OsPS4; + case ZigLLVM_ELFIAMCU: + return OsELFIAMCU; + case ZigLLVM_TvOS: + return OsTvOS; + case ZigLLVM_WatchOS: + return OsWatchOS; + case ZigLLVM_Mesa3D: + return OsMesa3D; + case ZigLLVM_Contiki: + return OsContiki; + case ZigLLVM_AMDPAL: + return OsAMDPAL; + case ZigLLVM_HermitCore: + return OsHermitCore; + case ZigLLVM_Hurd: + return OsHurd; + case ZigLLVM_WASI: + return OsWASI; + case ZigLLVM_Emscripten: + return OsEmscripten; + } + zig_unreachable(); +} + +static void get_native_target(ZigTarget *target) { + // first zero initialize + *target = {}; + + ZigLLVM_OSType os_type; + ZigLLVM_ObjectFormatType oformat; // ignored; based on arch/os + ZigLLVM_VendorType trash; + ZigLLVMGetNativeTarget( + &target->arch, + &trash, + &os_type, + &target->abi, + &oformat); + target->os = get_zig_os_type(os_type); + target->is_native_os = true; + target->is_native_cpu = true; + if (target->abi == ZigLLVM_UnknownEnvironment) { + target->abi = target_default_abi(target->arch, target->os); + } +} + +static Error target_parse_triple(struct ZigTarget *target, const char *zig_triple, const char *mcpu, + const char *dynamic_linker) +{ + Error err; + + if (zig_triple != nullptr && strcmp(zig_triple, "native") == 0) { + zig_triple = nullptr; + } + + if (zig_triple == nullptr) { + get_native_target(target); + + if (mcpu == nullptr) { + target->llvm_cpu_name = ZigLLVMGetHostCPUName(); + target->llvm_cpu_features = ZigLLVMGetNativeFeatures(); + } else if (strcmp(mcpu, "baseline") == 0) { + target->is_native_os = false; + target->is_native_cpu = false; + target->llvm_cpu_name = ""; + target->llvm_cpu_features = ""; + } else { + const char *msg = "stage0 can't handle CPU/features in the target"; + stage2_panic(msg, strlen(msg)); + } + } else { + // first initialize all to zero + *target = {}; + + SplitIterator it = memSplit(str(zig_triple), str("-")); + + Optional> opt_archsub = SplitIterator_next(&it); + Optional> opt_os = SplitIterator_next(&it); + Optional> opt_abi = SplitIterator_next(&it); + + if (!opt_archsub.is_some) + return ErrorMissingArchitecture; + + if ((err = target_parse_arch(&target->arch, (char*)opt_archsub.value.ptr, opt_archsub.value.len))) { + return err; + } + + if (!opt_os.is_some) + return ErrorMissingOperatingSystem; + + if ((err = target_parse_os(&target->os, (char*)opt_os.value.ptr, opt_os.value.len))) { + return err; + } + + if (opt_abi.is_some) { + if ((err = target_parse_abi(&target->abi, (char*)opt_abi.value.ptr, opt_abi.value.len))) { + return err; + } + } else { + target->abi = target_default_abi(target->arch, target->os); + } + + if (mcpu != nullptr && strcmp(mcpu, "baseline") != 0) { + const char *msg = "stage0 can't handle CPU/features in the target"; + stage2_panic(msg, strlen(msg)); + } + } + + return ErrorNone; +} + + static bool str_starts_with(const char *s1, const char *s2) { size_t s2_len = strlen(s2); if (strlen(s1) < s2_len) { @@ -90,10 +256,9 @@ int main(int argc, char **argv) { bool link_libcpp = false; const char *target_string = nullptr; ZigStage1Pkg *cur_pkg = heap::c_allocator.create(); - BuildMode build_mode = BuildModeDebug; + BuildMode optimize_mode = BuildModeDebug; TargetSubsystem subsystem = TargetSubsystemAuto; const char *override_lib_dir = nullptr; - const char *main_pkg_path = nullptr; const char *mcpu = nullptr; for (int i = 1; i < argc; i += 1) { @@ -103,11 +268,11 @@ int main(int argc, char **argv) { if (strcmp(arg, "--") == 0) { fprintf(stderr, "Unexpected end-of-parameter mark: %s\n", arg); } else if (strcmp(arg, "--release-fast") == 0) { - build_mode = BuildModeFastRelease; + optimize_mode = BuildModeFastRelease; } else if (strcmp(arg, "--release-safe") == 0) { - build_mode = BuildModeSafeRelease; + optimize_mode = BuildModeSafeRelease; } else if (strcmp(arg, "--release-small") == 0) { - build_mode = BuildModeSmallRelease; + optimize_mode = BuildModeSmallRelease; } else if (strcmp(arg, "--help") == 0) { return print_full_usage(arg0, stdout, EXIT_SUCCESS); } else if (strcmp(arg, "--strip") == 0) { @@ -183,8 +348,6 @@ int main(int argc, char **argv) { dynamic_linker = argv[i]; } else if (strcmp(arg, "--override-lib-dir") == 0) { override_lib_dir = argv[i]; - } else if (strcmp(arg, "--main-pkg-path") == 0) { - main_pkg_path = argv[i]; } else if (strcmp(arg, "--library") == 0 || strcmp(arg, "-l") == 0) { if (strcmp(argv[i], "c") == 0) { link_libc = true; @@ -264,12 +427,13 @@ int main(int argc, char **argv) { return print_error_usage(arg0); } - ZigStage1 *stage1 = zig_stage1_create(build_mode, - main_pkg_path, (main_pkg_path == nullptr) ? 0 : strlen(main_pkg_path), + ZigStage1 *stage1 = zig_stage1_create(optimize_mode, + nullptr, 0, in_file, strlen(in_file), - override_lib_dir, strlen(override_lib_dir), &target, false, - root_progress_node); + override_lib_dir, strlen(override_lib_dir), + &target, false); + stage1->main_progress_node = root_progress_node; stage1->root_name_ptr = out_name; stage1->root_name_len = strlen(out_name); stage1->strip = strip; @@ -295,3 +459,66 @@ int main(int argc, char **argv) { return main_exit(root_progress_node, EXIT_SUCCESS); } + +void stage2_panic(const char *ptr, size_t len) { + fwrite(ptr, 1, len, stderr); + fprintf(stderr, "\n"); + fflush(stderr); + abort(); +} + +struct Stage2Progress { + int trash; +}; + +struct Stage2ProgressNode { + int trash; +}; + +Stage2Progress *stage2_progress_create(void) { + return nullptr; +} + +void stage2_progress_destroy(Stage2Progress *progress) {} + +Stage2ProgressNode *stage2_progress_start_root(Stage2Progress *progress, + const char *name_ptr, size_t name_len, size_t estimated_total_items) +{ + return nullptr; +} +Stage2ProgressNode *stage2_progress_start(Stage2ProgressNode *node, + const char *name_ptr, size_t name_len, size_t estimated_total_items) +{ + return nullptr; +} +void stage2_progress_end(Stage2ProgressNode *node) {} +void stage2_progress_complete_one(Stage2ProgressNode *node) {} +void stage2_progress_disable_tty(Stage2Progress *progress) {} +void stage2_progress_update_node(Stage2ProgressNode *node, size_t completed_count, size_t estimated_total_items){} + +const char *stage2_fetch_file(struct ZigStage1 *stage1, const char *path_ptr, size_t path_len, + size_t *result_len) +{ + Error err; + Buf contents_buf = BUF_INIT; + Buf path_buf = BUF_INIT; + + buf_init_from_mem(&path_buf, path_ptr, path_len); + if ((err = os_fetch_file_path(&path_buf, &contents_buf))) { + return nullptr; + } + *result_len = buf_len(&contents_buf); + return buf_ptr(&contents_buf); +} + +const char *stage2_cimport(struct ZigStage1 *stage1) { + const char *msg = "stage0 called stage2_cimport"; + stage2_panic(msg, strlen(msg)); +} + +const char *stage2_add_link_lib(struct ZigStage1 *stage1, + const char *lib_name_ptr, size_t lib_name_len, + const char *symbol_name_ptr, size_t symbol_name_len) +{ + return nullptr; +}