diff --git a/CMakeLists.txt b/CMakeLists.txt index b990261d08e14d395fccfb8b445ccff7f341604a..a9dec5019301d6b2295930b4aeaf73783646117d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -434,8 +434,8 @@ find_package(Threads) # CMake doesn't let us create an empty executable, so we hang on to this one separately. set(ZIG_MAIN_SRC "${CMAKE_SOURCE_DIR}/src/main.cpp") -# This is our shim which will be replaced by libuserland written in Zig. -set(ZIG0_SHIM_SRC "${CMAKE_SOURCE_DIR}/src/userland.cpp") +# This is our shim which will be replaced by libstage2 written in Zig. +set(ZIG0_SHIM_SRC "${CMAKE_SOURCE_DIR}/src/stage2.cpp") if(ZIG_ENABLE_MEM_PROFILE) set(ZIG_SOURCES_MEM_PROFILE "${CMAKE_SOURCE_DIR}/src/mem_profile.cpp") @@ -599,38 +599,38 @@ set_target_properties(zig0 PROPERTIES target_link_libraries(zig0 compiler) if(MSVC) - set(LIBUSERLAND "${CMAKE_BINARY_DIR}/userland.lib") + set(LIBSTAGE2 "${CMAKE_BINARY_DIR}/stage2.lib") else() - set(LIBUSERLAND "${CMAKE_BINARY_DIR}/libuserland.a") + set(LIBSTAGE2 "${CMAKE_BINARY_DIR}/libstage2.a") endif() if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") - set(LIBUSERLAND_RELEASE_ARG "") + set(LIBSTAGE2_RELEASE_ARG "") else() - set(LIBUSERLAND_RELEASE_ARG --release-fast --strip) + set(LIBSTAGE2_RELEASE_ARG --release-fast --strip) endif() if(WIN32) - set(LIBUSERLAND_WINDOWS_ARGS "-lntdll") + set(LIBSTAGE2_WINDOWS_ARGS "-lntdll") else() - set(LIBUSERLAND_WINDOWS_ARGS "") + set(LIBSTAGE2_WINDOWS_ARGS "") endif() -set(BUILD_LIBUSERLAND_ARGS "build-lib" +set(BUILD_LIBSTAGE2_ARGS "build-lib" --override-lib-dir "${CMAKE_SOURCE_DIR}/lib" --cache on --output-dir "${CMAKE_BINARY_DIR}" - ${LIBUSERLAND_RELEASE_ARG} - "src-self-hosted/stage1.zig" + ${LIBSTAGE2_RELEASE_ARG} + "src-self-hosted/stage2.zig" --disable-gen-h --bundle-compiler-rt -fPIC -lc - ${LIBUSERLAND_WINDOWS_ARGS} + ${LIBSTAGE2_WINDOWS_ARGS} ) -add_custom_target(zig_build_libuserland ALL - COMMAND zig0 ${BUILD_LIBUSERLAND_ARGS} +add_custom_target(zig_build_libstage2 ALL + COMMAND zig0 ${BUILD_LIBSTAGE2_ARGS} DEPENDS zig0 - BYPRODUCTS "${LIBUSERLAND}" + BYPRODUCTS "${LIBSTAGE2}" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" ) add_executable(zig "${ZIG_MAIN_SRC}") @@ -639,13 +639,13 @@ set_target_properties(zig PROPERTIES COMPILE_FLAGS ${EXE_CFLAGS} LINK_FLAGS ${EXE_LDFLAGS} ) -target_link_libraries(zig compiler "${LIBUSERLAND}") +target_link_libraries(zig compiler "${LIBSTAGE2}") if(MSVC) target_link_libraries(zig ntdll.lib) elseif(MINGW) target_link_libraries(zig ntdll) endif() -add_dependencies(zig zig_build_libuserland) +add_dependencies(zig zig_build_libstage2) install(TARGETS zig DESTINATION bin) diff --git a/cmake/install.cmake b/cmake/install.cmake index e485652a05db0af4db8d31d1760e4323cbe70616..386773e30cb67fb6912e8e115cc3d52b5c75e032 100644 --- a/cmake/install.cmake +++ b/cmake/install.cmake @@ -19,9 +19,9 @@ if(_result) message(":: ERROR: ${_result}") message(":: (execute_process)") - string(REPLACE ";" " " s_INSTALL_LIBUSERLAND_ARGS "${ZIG_INSTALL_ARGS}") + string(REPLACE ";" " " s_INSTALL_LIBSTAGE2_ARGS "${ZIG_INSTALL_ARGS}") message("::") - message(":: argv: ${zig_EXE} ${s_INSTALL_LIBUSERLAND_ARGS}") + message(":: argv: ${zig_EXE} ${s_INSTALL_LIBSTAGE2_ARGS}") set(_args ${zig_EXE} ${ZIG_INSTALL_ARGS}) list(LENGTH _args _len) diff --git a/src-self-hosted/stage1.zig b/src-self-hosted/stage1.zig deleted file mode 100644 index 95719d47a9c2f8d64884e3a4f824b4e3739db76a..0000000000000000000000000000000000000000 --- a/src-self-hosted/stage1.zig +++ /dev/null @@ -1,1033 +0,0 @@ -// This is Zig code that is used by both stage1 and stage2. -// The prototypes in src/userland.h must match these definitions. - -const std = @import("std"); -const io = std.io; -const mem = std.mem; -const fs = std.fs; -const process = std.process; -const Allocator = mem.Allocator; -const ArrayList = std.ArrayList; -const Buffer = std.Buffer; -const Target = std.Target; -const self_hosted_main = @import("main.zig"); -const errmsg = @import("errmsg.zig"); -const DepTokenizer = @import("dep_tokenizer.zig").Tokenizer; -const assert = std.debug.assert; -const LibCInstallation = @import("libc_installation.zig").LibCInstallation; - -var stderr_file: fs.File = undefined; -var stderr: *io.OutStream(fs.File.WriteError) = undefined; -var stdout: *io.OutStream(fs.File.WriteError) = undefined; - -comptime { - _ = @import("dep_tokenizer.zig"); -} - -// ABI warning -export fn stage2_zen(ptr: *[*]const u8, len: *usize) void { - const info_zen = @import("main.zig").info_zen; - ptr.* = info_zen; - len.* = info_zen.len; -} - -// ABI warning -export fn stage2_panic(ptr: [*]const u8, len: usize) void { - @panic(ptr[0..len]); -} - -// ABI warning -const Error = extern enum { - None, - OutOfMemory, - InvalidFormat, - SemanticAnalyzeFail, - AccessDenied, - Interrupted, - SystemResources, - FileNotFound, - FileSystem, - FileTooBig, - DivByZero, - Overflow, - PathAlreadyExists, - Unexpected, - ExactDivRemainder, - NegativeDenominator, - ShiftedOutOneBits, - CCompileErrors, - EndOfFile, - IsDir, - NotDir, - UnsupportedOperatingSystem, - SharingViolation, - PipeBusy, - PrimitiveTypeNotFound, - CacheUnavailable, - PathTooLong, - CCompilerCannotFindFile, - NoCCompilerInstalled, - ReadingDepFile, - InvalidDepFile, - MissingArchitecture, - MissingOperatingSystem, - UnknownArchitecture, - UnknownOperatingSystem, - UnknownABI, - InvalidFilename, - DiskQuota, - DiskSpace, - UnexpectedWriteFailure, - UnexpectedSeekFailure, - UnexpectedFileTruncationFailure, - Unimplemented, - OperationAborted, - BrokenPipe, - NoSpaceLeft, - NotLazy, - IsAsync, - ImportOutsidePkgPath, - UnknownCpu, - UnknownSubArchitecture, - UnknownCpuFeature, - InvalidCpuFeatures, - InvalidLlvmCpuFeaturesFormat, - UnknownApplicationBinaryInterface, - ASTUnitFailure, - BadPathName, - SymLinkLoop, - ProcessFdQuotaExceeded, - SystemFdQuotaExceeded, - NoDevice, - DeviceBusy, - UnableToSpawnCCompiler, - CCompilerExitCode, - CCompilerCrashed, - CCompilerCannotFindHeaders, - LibCRuntimeNotFound, - LibCStdLibHeaderNotFound, - LibCKernel32LibNotFound, - UnsupportedArchitecture, -}; - -const FILE = std.c.FILE; -const ast = std.zig.ast; -const translate_c = @import("translate_c.zig"); - -/// Args should have a null terminating last arg. -export fn stage2_translate_c( - out_ast: **ast.Tree, - out_errors_ptr: *[*]translate_c.ClangErrMsg, - out_errors_len: *usize, - args_begin: [*]?[*]const u8, - args_end: [*]?[*]const u8, - resources_path: [*:0]const u8, -) Error { - var errors = @as([*]translate_c.ClangErrMsg, undefined)[0..0]; - out_ast.* = translate_c.translate(std.heap.c_allocator, args_begin, args_end, &errors, resources_path) catch |err| switch (err) { - error.SemanticAnalyzeFail => { - out_errors_ptr.* = errors.ptr; - out_errors_len.* = errors.len; - return .CCompileErrors; - }, - error.ASTUnitFailure => return .ASTUnitFailure, - error.OutOfMemory => return .OutOfMemory, - }; - return .None; -} - -export fn stage2_free_clang_errors(errors_ptr: [*]translate_c.ClangErrMsg, errors_len: usize) void { - translate_c.freeErrors(errors_ptr[0..errors_len]); -} - -export fn stage2_render_ast(tree: *ast.Tree, output_file: *FILE) Error { - const c_out_stream = &std.io.COutStream.init(output_file).stream; - _ = std.zig.render(std.heap.c_allocator, c_out_stream, tree) catch |e| switch (e) { - error.WouldBlock => unreachable, // stage1 opens stuff in exclusively blocking mode - error.SystemResources => return .SystemResources, - error.OperationAborted => return .OperationAborted, - error.BrokenPipe => return .BrokenPipe, - error.DiskQuota => return .DiskQuota, - error.FileTooBig => return .FileTooBig, - error.NoSpaceLeft => return .NoSpaceLeft, - error.AccessDenied => return .AccessDenied, - error.OutOfMemory => return .OutOfMemory, - error.Unexpected => return .Unexpected, - error.InputOutput => return .FileSystem, - }; - return .None; -} - -// TODO: just use the actual self-hosted zig fmt. Until https://github.com/ziglang/zig/issues/2377, -// we use a blocking implementation. -export fn stage2_fmt(argc: c_int, argv: [*]const [*:0]const u8) c_int { - if (std.debug.runtime_safety) { - fmtMain(argc, argv) catch unreachable; - } else { - fmtMain(argc, argv) catch |e| { - std.debug.warn("{}\n", .{@errorName(e)}); - return -1; - }; - } - return 0; -} - -fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void { - const allocator = std.heap.c_allocator; - var args_list = std.ArrayList([]const u8).init(allocator); - const argc_usize = @intCast(usize, argc); - var arg_i: usize = 0; - while (arg_i < argc_usize) : (arg_i += 1) { - try args_list.append(mem.toSliceConst(u8, argv[arg_i])); - } - - stdout = &std.io.getStdOut().outStream().stream; - stderr_file = std.io.getStdErr(); - stderr = &stderr_file.outStream().stream; - - const args = args_list.toSliceConst()[2..]; - - var color: errmsg.Color = .Auto; - var stdin_flag: bool = false; - var check_flag: bool = false; - var input_files = ArrayList([]const u8).init(allocator); - - { - var i: usize = 0; - while (i < args.len) : (i += 1) { - const arg = args[i]; - if (mem.startsWith(u8, arg, "-")) { - if (mem.eql(u8, arg, "--help")) { - try stdout.write(self_hosted_main.usage_fmt); - process.exit(0); - } else if (mem.eql(u8, arg, "--color")) { - if (i + 1 >= args.len) { - try stderr.write("expected [auto|on|off] after --color\n"); - process.exit(1); - } - i += 1; - const next_arg = args[i]; - if (mem.eql(u8, next_arg, "auto")) { - color = .Auto; - } else if (mem.eql(u8, next_arg, "on")) { - color = .On; - } else if (mem.eql(u8, next_arg, "off")) { - color = .Off; - } else { - try stderr.print("expected [auto|on|off] after --color, found '{}'\n", .{next_arg}); - process.exit(1); - } - } else if (mem.eql(u8, arg, "--stdin")) { - stdin_flag = true; - } else if (mem.eql(u8, arg, "--check")) { - check_flag = true; - } else { - try stderr.print("unrecognized parameter: '{}'", .{arg}); - process.exit(1); - } - } else { - try input_files.append(arg); - } - } - } - - if (stdin_flag) { - if (input_files.len != 0) { - try stderr.write("cannot use --stdin with positional arguments\n"); - process.exit(1); - } - - const stdin_file = io.getStdIn(); - var stdin = stdin_file.inStream(); - - const source_code = try stdin.stream.readAllAlloc(allocator, self_hosted_main.max_src_size); - defer allocator.free(source_code); - - const tree = std.zig.parse(allocator, source_code) catch |err| { - try stderr.print("error parsing stdin: {}\n", .{err}); - process.exit(1); - }; - defer tree.deinit(); - - var error_it = tree.errors.iterator(0); - while (error_it.next()) |parse_error| { - try printErrMsgToFile(allocator, parse_error, tree, "", stderr_file, color); - } - if (tree.errors.len != 0) { - process.exit(1); - } - if (check_flag) { - const anything_changed = try std.zig.render(allocator, io.null_out_stream, tree); - const code = if (anything_changed) @as(u8, 1) else @as(u8, 0); - process.exit(code); - } - - _ = try std.zig.render(allocator, stdout, tree); - return; - } - - if (input_files.len == 0) { - try stderr.write("expected at least one source file argument\n"); - process.exit(1); - } - - var fmt = Fmt{ - .seen = Fmt.SeenMap.init(allocator), - .any_error = false, - .color = color, - .allocator = allocator, - }; - - for (input_files.toSliceConst()) |file_path| { - try fmtPath(&fmt, file_path, check_flag); - } - if (fmt.any_error) { - process.exit(1); - } -} - -const FmtError = error{ - SystemResources, - OperationAborted, - IoPending, - BrokenPipe, - Unexpected, - WouldBlock, - FileClosed, - DestinationAddressRequired, - DiskQuota, - FileTooBig, - InputOutput, - NoSpaceLeft, - AccessDenied, - OutOfMemory, - RenameAcrossMountPoints, - ReadOnlyFileSystem, - LinkQuotaExceeded, - FileBusy, -} || fs.File.OpenError; - -fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool) FmtError!void { - if (fmt.seen.exists(file_path)) return; - try fmt.seen.put(file_path); - - const source_code = io.readFileAlloc(fmt.allocator, file_path) catch |err| switch (err) { - error.IsDir, error.AccessDenied => { - // TODO make event based (and dir.next()) - var dir = try fs.cwd().openDirList(file_path); - defer dir.close(); - - var dir_it = dir.iterate(); - - while (try dir_it.next()) |entry| { - if (entry.kind == .Directory or mem.endsWith(u8, entry.name, ".zig")) { - const full_path = try fs.path.join(fmt.allocator, &[_][]const u8{ file_path, entry.name }); - try fmtPath(fmt, full_path, check_mode); - } - } - return; - }, - else => { - // TODO lock stderr printing - try stderr.print("unable to open '{}': {}\n", .{ file_path, err }); - fmt.any_error = true; - return; - }, - }; - defer fmt.allocator.free(source_code); - - const tree = std.zig.parse(fmt.allocator, source_code) catch |err| { - try stderr.print("error parsing file '{}': {}\n", .{ file_path, err }); - fmt.any_error = true; - return; - }; - defer tree.deinit(); - - var error_it = tree.errors.iterator(0); - while (error_it.next()) |parse_error| { - try printErrMsgToFile(fmt.allocator, parse_error, tree, file_path, stderr_file, fmt.color); - } - if (tree.errors.len != 0) { - fmt.any_error = true; - return; - } - - if (check_mode) { - const anything_changed = try std.zig.render(fmt.allocator, io.null_out_stream, tree); - if (anything_changed) { - try stderr.print("{}\n", .{file_path}); - fmt.any_error = true; - } - } else { - const baf = try io.BufferedAtomicFile.create(fmt.allocator, file_path); - defer baf.destroy(); - - const anything_changed = try std.zig.render(fmt.allocator, baf.stream(), tree); - if (anything_changed) { - try stderr.print("{}\n", .{file_path}); - try baf.finish(); - } - } -} - -const Fmt = struct { - seen: SeenMap, - any_error: bool, - color: errmsg.Color, - allocator: *mem.Allocator, - - const SeenMap = std.BufSet; -}; - -fn printErrMsgToFile( - allocator: *mem.Allocator, - parse_error: *const ast.Error, - tree: *ast.Tree, - path: []const u8, - file: fs.File, - color: errmsg.Color, -) !void { - const color_on = switch (color) { - .Auto => file.isTty(), - .On => true, - .Off => false, - }; - const lok_token = parse_error.loc(); - const span = errmsg.Span{ - .first = lok_token, - .last = lok_token, - }; - - const first_token = tree.tokens.at(span.first); - const last_token = tree.tokens.at(span.last); - const start_loc = tree.tokenLocationPtr(0, first_token); - const end_loc = tree.tokenLocationPtr(first_token.end, last_token); - - var text_buf = try std.Buffer.initSize(allocator, 0); - var out_stream = &std.io.BufferOutStream.init(&text_buf).stream; - try parse_error.render(&tree.tokens, out_stream); - const text = text_buf.toOwnedSlice(); - - const stream = &file.outStream().stream; - try stream.print("{}:{}:{}: error: {}\n", .{ path, start_loc.line + 1, start_loc.column + 1, text }); - - if (!color_on) return; - - // Print \r and \t as one space each so that column counts line up - for (tree.source[start_loc.line_start..start_loc.line_end]) |byte| { - try stream.writeByte(switch (byte) { - '\r', '\t' => ' ', - else => byte, - }); - } - try stream.writeByte('\n'); - try stream.writeByteNTimes(' ', start_loc.column); - try stream.writeByteNTimes('~', last_token.end - first_token.start); - try stream.writeByte('\n'); -} - -export fn stage2_DepTokenizer_init(input: [*]const u8, len: usize) stage2_DepTokenizer { - const t = std.heap.c_allocator.create(DepTokenizer) catch @panic("failed to create .d tokenizer"); - t.* = DepTokenizer.init(std.heap.c_allocator, input[0..len]); - return stage2_DepTokenizer{ - .handle = t, - }; -} - -export fn stage2_DepTokenizer_deinit(self: *stage2_DepTokenizer) void { - self.handle.deinit(); -} - -export fn stage2_DepTokenizer_next(self: *stage2_DepTokenizer) stage2_DepNextResult { - const otoken = self.handle.next() catch { - const textz = std.Buffer.init(&self.handle.arena.allocator, self.handle.error_text) catch @panic("failed to create .d tokenizer error text"); - return stage2_DepNextResult{ - .type_id = .error_, - .textz = textz.toSlice().ptr, - }; - }; - const token = otoken orelse { - return stage2_DepNextResult{ - .type_id = .null_, - .textz = undefined, - }; - }; - const textz = std.Buffer.init(&self.handle.arena.allocator, token.bytes) catch @panic("failed to create .d tokenizer token text"); - return stage2_DepNextResult{ - .type_id = switch (token.id) { - .target => .target, - .prereq => .prereq, - }, - .textz = textz.toSlice().ptr, - }; -} - -const stage2_DepTokenizer = extern struct { - handle: *DepTokenizer, -}; - -const stage2_DepNextResult = extern struct { - type_id: TypeId, - - // when type_id == error --> error text - // when type_id == null --> undefined - // when type_id == target --> target pathname - // when type_id == prereq --> prereq pathname - textz: [*]const u8, - - const TypeId = extern enum { - error_, - null_, - target, - prereq, - }; -}; - -// ABI warning -export fn stage2_attach_segfault_handler() void { - if (std.debug.runtime_safety and std.debug.have_segfault_handling_support) { - std.debug.attachSegfaultHandler(); - } -} - -// ABI warning -export fn stage2_progress_create() *std.Progress { - const ptr = std.heap.c_allocator.create(std.Progress) catch @panic("out of memory"); - ptr.* = std.Progress{}; - return ptr; -} - -// ABI warning -export fn stage2_progress_destroy(progress: *std.Progress) void { - std.heap.c_allocator.destroy(progress); -} - -// ABI warning -export fn stage2_progress_start_root( - progress: *std.Progress, - name_ptr: [*]const u8, - name_len: usize, - estimated_total_items: usize, -) *std.Progress.Node { - return progress.start( - name_ptr[0..name_len], - if (estimated_total_items == 0) null else estimated_total_items, - ) catch @panic("timer unsupported"); -} - -// ABI warning -export fn stage2_progress_disable_tty(progress: *std.Progress) void { - progress.terminal = null; -} - -// ABI warning -export fn stage2_progress_start( - node: *std.Progress.Node, - name_ptr: [*]const u8, - name_len: usize, - estimated_total_items: usize, -) *std.Progress.Node { - const child_node = std.heap.c_allocator.create(std.Progress.Node) catch @panic("out of memory"); - child_node.* = node.start( - name_ptr[0..name_len], - if (estimated_total_items == 0) null else estimated_total_items, - ); - child_node.activate(); - return child_node; -} - -// ABI warning -export fn stage2_progress_end(node: *std.Progress.Node) void { - node.end(); - if (&node.context.root != node) { - std.heap.c_allocator.destroy(node); - } -} - -// ABI warning -export fn stage2_progress_complete_one(node: *std.Progress.Node) void { - node.completeOne(); -} - -// ABI warning -export fn stage2_progress_update_node(node: *std.Progress.Node, done_count: usize, total_count: usize) void { - node.completed_items = done_count; - node.estimated_total_items = total_count; - node.activate(); - node.context.maybeRefresh(); -} - -fn cpuFeaturesFromLLVM( - arch: Target.Arch, - llvm_cpu_name_z: ?[*:0]const u8, - llvm_cpu_features_opt: ?[*:0]const u8, -) !Target.CpuFeatures { - var result = arch.getBaselineCpuFeatures(); - - if (llvm_cpu_name_z) |cpu_name_z| { - const llvm_cpu_name = mem.toSliceConst(u8, cpu_name_z); - - for (arch.allCpus()) |cpu| { - const this_llvm_name = cpu.llvm_name orelse continue; - if (mem.eql(u8, this_llvm_name, llvm_cpu_name)) { - // Here we use the non-dependencies-populated set, - // so that subtracting features later in this function - // affect the prepopulated set. - result = Target.CpuFeatures{ - .cpu = cpu, - .features = cpu.features, - }; - break; - } - } - } - - const all_features = arch.allFeaturesList(); - - if (llvm_cpu_features_opt) |llvm_cpu_features| { - var it = mem.tokenize(mem.toSliceConst(u8, llvm_cpu_features), ","); - while (it.next()) |decorated_llvm_feat| { - var op: enum { - add, - sub, - } = undefined; - var llvm_feat: []const u8 = undefined; - if (mem.startsWith(u8, decorated_llvm_feat, "+")) { - op = .add; - llvm_feat = decorated_llvm_feat[1..]; - } else if (mem.startsWith(u8, decorated_llvm_feat, "-")) { - op = .sub; - llvm_feat = decorated_llvm_feat[1..]; - } else { - return error.InvalidLlvmCpuFeaturesFormat; - } - for (all_features) |feature, index_usize| { - const this_llvm_name = feature.llvm_name orelse continue; - if (mem.eql(u8, llvm_feat, this_llvm_name)) { - const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize); - switch (op) { - .add => result.features.addFeature(index), - .sub => result.features.removeFeature(index), - } - break; - } - } - } - } - - result.features.populateDependencies(all_features); - return result; -} - -// ABI warning -export fn stage2_cmd_targets(zig_triple: [*:0]const u8) c_int { - cmdTargets(zig_triple) catch |err| { - std.debug.warn("unable to list targets: {}\n", .{@errorName(err)}); - return -1; - }; - return 0; -} - -fn cmdTargets(zig_triple: [*:0]const u8) !void { - var target = try Target.parse(mem.toSliceConst(u8, zig_triple)); - target.Cross.cpu_features = blk: { - const llvm = @import("llvm.zig"); - const llvm_cpu_name = llvm.GetHostCPUName(); - const llvm_cpu_features = llvm.GetNativeFeatures(); - break :blk try cpuFeaturesFromLLVM(target.Cross.arch, llvm_cpu_name, llvm_cpu_features); - }; - return @import("print_targets.zig").cmdTargets( - std.heap.c_allocator, - &[0][]u8{}, - &std.io.getStdOut().outStream().stream, - target, - ); -} - -const Stage2CpuFeatures = struct { - allocator: *mem.Allocator, - cpu_features: Target.CpuFeatures, - - llvm_features_str: ?[*:0]const u8, - - builtin_str: [:0]const u8, - cache_hash: [:0]const u8, - - const Self = @This(); - - fn createFromNative(allocator: *mem.Allocator) !*Self { - const arch = Target.current.getArch(); - const llvm = @import("llvm.zig"); - const llvm_cpu_name = llvm.GetHostCPUName(); - const llvm_cpu_features = llvm.GetNativeFeatures(); - const cpu_features = try cpuFeaturesFromLLVM(arch, llvm_cpu_name, llvm_cpu_features); - return createFromCpuFeatures(allocator, arch, cpu_features); - } - - fn createFromCpuFeatures( - allocator: *mem.Allocator, - arch: Target.Arch, - cpu_features: Target.CpuFeatures, - ) !*Self { - const self = try allocator.create(Self); - errdefer allocator.destroy(self); - - const cache_hash = try std.fmt.allocPrint0(allocator, "{}\n{}", .{ - cpu_features.cpu.name, - cpu_features.features.asBytes(), - }); - errdefer allocator.free(cache_hash); - - const generic_arch_name = arch.genericName(); - var builtin_str_buffer = try std.Buffer.allocPrint(allocator, - \\CpuFeatures{{ - \\ .cpu = &Target.{}.cpu.{}, - \\ .features = Target.{}.featureSet(&[_]Target.{}.Feature{{ - \\ - , .{ - generic_arch_name, - cpu_features.cpu.name, - generic_arch_name, - generic_arch_name, - }); - defer builtin_str_buffer.deinit(); - - var llvm_features_buffer = try std.Buffer.initSize(allocator, 0); - defer llvm_features_buffer.deinit(); - - for (arch.allFeaturesList()) |feature, index_usize| { - const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize); - const is_enabled = cpu_features.features.isEnabled(index); - - if (feature.llvm_name) |llvm_name| { - const plus_or_minus = "-+"[@boolToInt(is_enabled)]; - try llvm_features_buffer.appendByte(plus_or_minus); - try llvm_features_buffer.append(llvm_name); - try llvm_features_buffer.append(","); - } - - if (is_enabled) { - // TODO some kind of "zig identifier escape" function rather than - // unconditionally using @"" syntax - try builtin_str_buffer.append(" .@\""); - try builtin_str_buffer.append(feature.name); - try builtin_str_buffer.append("\",\n"); - } - } - - try builtin_str_buffer.append( - \\ }), - \\}; - \\ - ); - - assert(mem.endsWith(u8, llvm_features_buffer.toSliceConst(), ",")); - llvm_features_buffer.shrink(llvm_features_buffer.len() - 1); - - self.* = Self{ - .allocator = allocator, - .cpu_features = cpu_features, - .llvm_features_str = llvm_features_buffer.toOwnedSlice().ptr, - .builtin_str = builtin_str_buffer.toOwnedSlice(), - .cache_hash = cache_hash, - }; - return self; - } - - fn destroy(self: *Self) void { - self.allocator.free(self.cache_hash); - self.allocator.free(self.builtin_str); - // TODO if (self.llvm_features_str) |llvm_features_str| self.allocator.free(llvm_features_str); - self.allocator.destroy(self); - } -}; - -// ABI warning -export fn stage2_cpu_features_parse( - result: **Stage2CpuFeatures, - zig_triple: ?[*:0]const u8, - cpu_name: ?[*:0]const u8, - cpu_features: ?[*:0]const u8, -) Error { - result.* = stage2ParseCpuFeatures(zig_triple, cpu_name, cpu_features) catch |err| switch (err) { - error.OutOfMemory => return .OutOfMemory, - error.UnknownArchitecture => return .UnknownArchitecture, - error.UnknownSubArchitecture => return .UnknownSubArchitecture, - error.UnknownOperatingSystem => return .UnknownOperatingSystem, - error.UnknownApplicationBinaryInterface => return .UnknownApplicationBinaryInterface, - error.MissingOperatingSystem => return .MissingOperatingSystem, - error.MissingArchitecture => return .MissingArchitecture, - error.InvalidLlvmCpuFeaturesFormat => return .InvalidLlvmCpuFeaturesFormat, - error.InvalidCpuFeatures => return .InvalidCpuFeatures, - }; - return .None; -} - -fn stage2ParseCpuFeatures( - zig_triple_oz: ?[*:0]const u8, - cpu_name_oz: ?[*:0]const u8, - cpu_features_oz: ?[*:0]const u8, -) !*Stage2CpuFeatures { - const zig_triple_z = zig_triple_oz orelse return Stage2CpuFeatures.createFromNative(std.heap.c_allocator); - const target = try Target.parse(mem.toSliceConst(u8, zig_triple_z)); - const arch = target.Cross.arch; - - const cpu = if (cpu_name_oz) |cpu_name_z| blk: { - const cpu_name = mem.toSliceConst(u8, cpu_name_z); - break :blk arch.parseCpu(cpu_name) catch |err| switch (err) { - error.UnknownCpu => { - std.debug.warn("Unknown CPU: '{}'\nAvailable CPUs for architecture '{}':\n", .{ - cpu_name, - @tagName(arch), - }); - for (arch.allCpus()) |cpu| { - std.debug.warn(" {}\n", .{cpu.name}); - } - process.exit(1); - }, - else => |e| return e, - }; - } else target.Cross.cpu_features.cpu; - - var set = if (cpu_features_oz) |cpu_features_z| blk: { - const cpu_features = mem.toSliceConst(u8, cpu_features_z); - break :blk arch.parseCpuFeatureSet(cpu, cpu_features) catch |err| switch (err) { - error.UnknownCpuFeature => { - std.debug.warn( - \\Unknown CPU features specified. - \\Available CPU features for architecture '{}': - \\ - , .{@tagName(arch)}); - for (arch.allFeaturesList()) |feature| { - std.debug.warn(" {}\n", .{feature.name}); - } - process.exit(1); - }, - else => |e| return e, - }; - } else cpu.features; - - if (arch.subArchFeature()) |index| { - set.addFeature(index); - } - set.populateDependencies(arch.allFeaturesList()); - - return Stage2CpuFeatures.createFromCpuFeatures(std.heap.c_allocator, arch, .{ - .cpu = cpu, - .features = set, - }); -} - -// ABI warning -export fn stage2_cpu_features_get_cache_hash( - cpu_features: *const Stage2CpuFeatures, - ptr: *[*:0]const u8, - len: *usize, -) void { - ptr.* = cpu_features.cache_hash.ptr; - len.* = cpu_features.cache_hash.len; -} - -// ABI warning -export fn stage2_cpu_features_get_builtin_str( - cpu_features: *const Stage2CpuFeatures, - ptr: *[*:0]const u8, - len: *usize, -) void { - ptr.* = cpu_features.builtin_str.ptr; - len.* = cpu_features.builtin_str.len; -} - -// ABI warning -export fn stage2_cpu_features_get_llvm_cpu(cpu_features: *const Stage2CpuFeatures) ?[*:0]const u8 { - return if (cpu_features.cpu_features.cpu.llvm_name) |s| s.ptr else null; -} - -// ABI warning -export fn stage2_cpu_features_get_llvm_features(cpu_features: *const Stage2CpuFeatures) ?[*:0]const u8 { - return cpu_features.llvm_features_str; -} - -// ABI warning -const Stage2LibCInstallation = extern struct { - include_dir: [*:0]const u8, - include_dir_len: usize, - sys_include_dir: [*:0]const u8, - sys_include_dir_len: usize, - crt_dir: [*:0]const u8, - crt_dir_len: usize, - static_crt_dir: [*:0]const u8, - static_crt_dir_len: usize, - msvc_lib_dir: [*:0]const u8, - msvc_lib_dir_len: usize, - kernel32_lib_dir: [*:0]const u8, - kernel32_lib_dir_len: usize, - - fn initFromStage2(self: *Stage2LibCInstallation, libc: LibCInstallation) void { - if (libc.include_dir) |s| { - self.include_dir = s.ptr; - self.include_dir_len = s.len; - } else { - self.include_dir = ""; - self.include_dir_len = 0; - } - if (libc.sys_include_dir) |s| { - self.sys_include_dir = s.ptr; - self.sys_include_dir_len = s.len; - } else { - self.sys_include_dir = ""; - self.sys_include_dir_len = 0; - } - if (libc.crt_dir) |s| { - self.crt_dir = s.ptr; - self.crt_dir_len = s.len; - } else { - self.crt_dir = ""; - self.crt_dir_len = 0; - } - if (libc.static_crt_dir) |s| { - self.static_crt_dir = s.ptr; - self.static_crt_dir_len = s.len; - } else { - self.static_crt_dir = ""; - self.static_crt_dir_len = 0; - } - if (libc.msvc_lib_dir) |s| { - self.msvc_lib_dir = s.ptr; - self.msvc_lib_dir_len = s.len; - } else { - self.msvc_lib_dir = ""; - self.msvc_lib_dir_len = 0; - } - if (libc.kernel32_lib_dir) |s| { - self.kernel32_lib_dir = s.ptr; - self.kernel32_lib_dir_len = s.len; - } else { - self.kernel32_lib_dir = ""; - self.kernel32_lib_dir_len = 0; - } - } - - fn toStage2(self: Stage2LibCInstallation) LibCInstallation { - var libc: LibCInstallation = .{}; - if (self.include_dir_len != 0) { - libc.include_dir = self.include_dir[0..self.include_dir_len :0]; - } - if (self.sys_include_dir_len != 0) { - libc.sys_include_dir = self.sys_include_dir[0..self.sys_include_dir_len :0]; - } - if (self.crt_dir_len != 0) { - libc.crt_dir = self.crt_dir[0..self.crt_dir_len :0]; - } - if (self.static_crt_dir_len != 0) { - libc.static_crt_dir = self.static_crt_dir[0..self.static_crt_dir_len :0]; - } - if (self.msvc_lib_dir_len != 0) { - libc.msvc_lib_dir = self.msvc_lib_dir[0..self.msvc_lib_dir_len :0]; - } - if (self.kernel32_lib_dir_len != 0) { - libc.kernel32_lib_dir = self.kernel32_lib_dir[0..self.kernel32_lib_dir_len :0]; - } - return libc; - } -}; - -// ABI warning -export fn stage2_libc_parse(stage1_libc: *Stage2LibCInstallation, libc_file_z: [*:0]const u8) Error { - stderr_file = std.io.getStdErr(); - stderr = &stderr_file.outStream().stream; - const libc_file = mem.toSliceConst(u8, libc_file_z); - var libc = LibCInstallation.parse(std.heap.c_allocator, libc_file, stderr) catch |err| switch (err) { - error.ParseError => return .SemanticAnalyzeFail, - error.DiskQuota => return .DiskQuota, - error.FileTooBig => return .FileTooBig, - error.InputOutput => return .FileSystem, - error.NoSpaceLeft => return .NoSpaceLeft, - error.AccessDenied => return .AccessDenied, - error.BrokenPipe => return .BrokenPipe, - error.SystemResources => return .SystemResources, - error.OperationAborted => return .OperationAborted, - error.WouldBlock => unreachable, - error.Unexpected => return .Unexpected, - error.EndOfStream => return .EndOfFile, - error.IsDir => return .IsDir, - error.ConnectionResetByPeer => unreachable, - error.OutOfMemory => return .OutOfMemory, - error.Unseekable => unreachable, - error.SharingViolation => return .SharingViolation, - error.PathAlreadyExists => unreachable, - error.FileNotFound => return .FileNotFound, - error.PipeBusy => return .PipeBusy, - error.NameTooLong => return .PathTooLong, - error.InvalidUtf8 => return .BadPathName, - error.BadPathName => return .BadPathName, - error.SymLinkLoop => return .SymLinkLoop, - error.ProcessFdQuotaExceeded => return .ProcessFdQuotaExceeded, - error.SystemFdQuotaExceeded => return .SystemFdQuotaExceeded, - error.NoDevice => return .NoDevice, - error.NotDir => return .NotDir, - error.DeviceBusy => return .DeviceBusy, - }; - stage1_libc.initFromStage2(libc); - return .None; -} - -// ABI warning -export fn stage2_libc_find_native(stage1_libc: *Stage2LibCInstallation) Error { - var libc = LibCInstallation.findNative(std.heap.c_allocator) catch |err| switch (err) { - error.OutOfMemory => return .OutOfMemory, - error.FileSystem => return .FileSystem, - error.UnableToSpawnCCompiler => return .UnableToSpawnCCompiler, - error.CCompilerExitCode => return .CCompilerExitCode, - error.CCompilerCrashed => return .CCompilerCrashed, - error.CCompilerCannotFindHeaders => return .CCompilerCannotFindHeaders, - error.LibCRuntimeNotFound => return .LibCRuntimeNotFound, - error.LibCStdLibHeaderNotFound => return .LibCStdLibHeaderNotFound, - error.LibCKernel32LibNotFound => return .LibCKernel32LibNotFound, - error.UnsupportedArchitecture => return .UnsupportedArchitecture, - }; - stage1_libc.initFromStage2(libc); - return .None; -} - -// ABI warning -export fn stage2_libc_render(stage1_libc: *Stage2LibCInstallation, output_file: *FILE) Error { - var libc = stage1_libc.toStage2(); - const c_out_stream = &std.io.COutStream.init(output_file).stream; - libc.render(c_out_stream) catch |err| switch (err) { - error.WouldBlock => unreachable, // stage1 opens stuff in exclusively blocking mode - error.SystemResources => return .SystemResources, - error.OperationAborted => return .OperationAborted, - error.BrokenPipe => return .BrokenPipe, - error.DiskQuota => return .DiskQuota, - error.FileTooBig => return .FileTooBig, - error.NoSpaceLeft => return .NoSpaceLeft, - error.AccessDenied => return .AccessDenied, - error.Unexpected => return .Unexpected, - error.InputOutput => return .FileSystem, - }; - return .None; -} - -// ABI warning -export fn stage2_libc_cc_print_file_name( - out_ptr: *[*:0]u8, - out_len: *usize, - o_file: [*:0]const u8, - want_dirname: bool, -) Error { - const result = @import("libc_installation.zig").ccPrintFileName( - std.heap.c_allocator, - mem.toSliceConst(u8, o_file), - if (want_dirname) .only_dir else .full_path, - ) catch |err| switch (err) { - error.OutOfMemory => return .OutOfMemory, - error.LibCRuntimeNotFound => return .FileNotFound, - error.CCompilerExitCode => return .CCompilerExitCode, - error.CCompilerCrashed => return .CCompilerCrashed, - error.UnableToSpawnCCompiler => return .UnableToSpawnCCompiler, - }; - out_ptr.* = result.ptr; - out_len.* = result.len; - return .None; -} diff --git a/src-self-hosted/stage2.zig b/src-self-hosted/stage2.zig new file mode 100644 index 0000000000000000000000000000000000000000..95719d47a9c2f8d64884e3a4f824b4e3739db76a --- /dev/null +++ b/src-self-hosted/stage2.zig @@ -0,0 +1,1033 @@ +// This is Zig code that is used by both stage1 and stage2. +// The prototypes in src/userland.h must match these definitions. + +const std = @import("std"); +const io = std.io; +const mem = std.mem; +const fs = std.fs; +const process = std.process; +const Allocator = mem.Allocator; +const ArrayList = std.ArrayList; +const Buffer = std.Buffer; +const Target = std.Target; +const self_hosted_main = @import("main.zig"); +const errmsg = @import("errmsg.zig"); +const DepTokenizer = @import("dep_tokenizer.zig").Tokenizer; +const assert = std.debug.assert; +const LibCInstallation = @import("libc_installation.zig").LibCInstallation; + +var stderr_file: fs.File = undefined; +var stderr: *io.OutStream(fs.File.WriteError) = undefined; +var stdout: *io.OutStream(fs.File.WriteError) = undefined; + +comptime { + _ = @import("dep_tokenizer.zig"); +} + +// ABI warning +export fn stage2_zen(ptr: *[*]const u8, len: *usize) void { + const info_zen = @import("main.zig").info_zen; + ptr.* = info_zen; + len.* = info_zen.len; +} + +// ABI warning +export fn stage2_panic(ptr: [*]const u8, len: usize) void { + @panic(ptr[0..len]); +} + +// ABI warning +const Error = extern enum { + None, + OutOfMemory, + InvalidFormat, + SemanticAnalyzeFail, + AccessDenied, + Interrupted, + SystemResources, + FileNotFound, + FileSystem, + FileTooBig, + DivByZero, + Overflow, + PathAlreadyExists, + Unexpected, + ExactDivRemainder, + NegativeDenominator, + ShiftedOutOneBits, + CCompileErrors, + EndOfFile, + IsDir, + NotDir, + UnsupportedOperatingSystem, + SharingViolation, + PipeBusy, + PrimitiveTypeNotFound, + CacheUnavailable, + PathTooLong, + CCompilerCannotFindFile, + NoCCompilerInstalled, + ReadingDepFile, + InvalidDepFile, + MissingArchitecture, + MissingOperatingSystem, + UnknownArchitecture, + UnknownOperatingSystem, + UnknownABI, + InvalidFilename, + DiskQuota, + DiskSpace, + UnexpectedWriteFailure, + UnexpectedSeekFailure, + UnexpectedFileTruncationFailure, + Unimplemented, + OperationAborted, + BrokenPipe, + NoSpaceLeft, + NotLazy, + IsAsync, + ImportOutsidePkgPath, + UnknownCpu, + UnknownSubArchitecture, + UnknownCpuFeature, + InvalidCpuFeatures, + InvalidLlvmCpuFeaturesFormat, + UnknownApplicationBinaryInterface, + ASTUnitFailure, + BadPathName, + SymLinkLoop, + ProcessFdQuotaExceeded, + SystemFdQuotaExceeded, + NoDevice, + DeviceBusy, + UnableToSpawnCCompiler, + CCompilerExitCode, + CCompilerCrashed, + CCompilerCannotFindHeaders, + LibCRuntimeNotFound, + LibCStdLibHeaderNotFound, + LibCKernel32LibNotFound, + UnsupportedArchitecture, +}; + +const FILE = std.c.FILE; +const ast = std.zig.ast; +const translate_c = @import("translate_c.zig"); + +/// Args should have a null terminating last arg. +export fn stage2_translate_c( + out_ast: **ast.Tree, + out_errors_ptr: *[*]translate_c.ClangErrMsg, + out_errors_len: *usize, + args_begin: [*]?[*]const u8, + args_end: [*]?[*]const u8, + resources_path: [*:0]const u8, +) Error { + var errors = @as([*]translate_c.ClangErrMsg, undefined)[0..0]; + out_ast.* = translate_c.translate(std.heap.c_allocator, args_begin, args_end, &errors, resources_path) catch |err| switch (err) { + error.SemanticAnalyzeFail => { + out_errors_ptr.* = errors.ptr; + out_errors_len.* = errors.len; + return .CCompileErrors; + }, + error.ASTUnitFailure => return .ASTUnitFailure, + error.OutOfMemory => return .OutOfMemory, + }; + return .None; +} + +export fn stage2_free_clang_errors(errors_ptr: [*]translate_c.ClangErrMsg, errors_len: usize) void { + translate_c.freeErrors(errors_ptr[0..errors_len]); +} + +export fn stage2_render_ast(tree: *ast.Tree, output_file: *FILE) Error { + const c_out_stream = &std.io.COutStream.init(output_file).stream; + _ = std.zig.render(std.heap.c_allocator, c_out_stream, tree) catch |e| switch (e) { + error.WouldBlock => unreachable, // stage1 opens stuff in exclusively blocking mode + error.SystemResources => return .SystemResources, + error.OperationAborted => return .OperationAborted, + error.BrokenPipe => return .BrokenPipe, + error.DiskQuota => return .DiskQuota, + error.FileTooBig => return .FileTooBig, + error.NoSpaceLeft => return .NoSpaceLeft, + error.AccessDenied => return .AccessDenied, + error.OutOfMemory => return .OutOfMemory, + error.Unexpected => return .Unexpected, + error.InputOutput => return .FileSystem, + }; + return .None; +} + +// TODO: just use the actual self-hosted zig fmt. Until https://github.com/ziglang/zig/issues/2377, +// we use a blocking implementation. +export fn stage2_fmt(argc: c_int, argv: [*]const [*:0]const u8) c_int { + if (std.debug.runtime_safety) { + fmtMain(argc, argv) catch unreachable; + } else { + fmtMain(argc, argv) catch |e| { + std.debug.warn("{}\n", .{@errorName(e)}); + return -1; + }; + } + return 0; +} + +fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void { + const allocator = std.heap.c_allocator; + var args_list = std.ArrayList([]const u8).init(allocator); + const argc_usize = @intCast(usize, argc); + var arg_i: usize = 0; + while (arg_i < argc_usize) : (arg_i += 1) { + try args_list.append(mem.toSliceConst(u8, argv[arg_i])); + } + + stdout = &std.io.getStdOut().outStream().stream; + stderr_file = std.io.getStdErr(); + stderr = &stderr_file.outStream().stream; + + const args = args_list.toSliceConst()[2..]; + + var color: errmsg.Color = .Auto; + var stdin_flag: bool = false; + var check_flag: bool = false; + var input_files = ArrayList([]const u8).init(allocator); + + { + var i: usize = 0; + while (i < args.len) : (i += 1) { + const arg = args[i]; + if (mem.startsWith(u8, arg, "-")) { + if (mem.eql(u8, arg, "--help")) { + try stdout.write(self_hosted_main.usage_fmt); + process.exit(0); + } else if (mem.eql(u8, arg, "--color")) { + if (i + 1 >= args.len) { + try stderr.write("expected [auto|on|off] after --color\n"); + process.exit(1); + } + i += 1; + const next_arg = args[i]; + if (mem.eql(u8, next_arg, "auto")) { + color = .Auto; + } else if (mem.eql(u8, next_arg, "on")) { + color = .On; + } else if (mem.eql(u8, next_arg, "off")) { + color = .Off; + } else { + try stderr.print("expected [auto|on|off] after --color, found '{}'\n", .{next_arg}); + process.exit(1); + } + } else if (mem.eql(u8, arg, "--stdin")) { + stdin_flag = true; + } else if (mem.eql(u8, arg, "--check")) { + check_flag = true; + } else { + try stderr.print("unrecognized parameter: '{}'", .{arg}); + process.exit(1); + } + } else { + try input_files.append(arg); + } + } + } + + if (stdin_flag) { + if (input_files.len != 0) { + try stderr.write("cannot use --stdin with positional arguments\n"); + process.exit(1); + } + + const stdin_file = io.getStdIn(); + var stdin = stdin_file.inStream(); + + const source_code = try stdin.stream.readAllAlloc(allocator, self_hosted_main.max_src_size); + defer allocator.free(source_code); + + const tree = std.zig.parse(allocator, source_code) catch |err| { + try stderr.print("error parsing stdin: {}\n", .{err}); + process.exit(1); + }; + defer tree.deinit(); + + var error_it = tree.errors.iterator(0); + while (error_it.next()) |parse_error| { + try printErrMsgToFile(allocator, parse_error, tree, "", stderr_file, color); + } + if (tree.errors.len != 0) { + process.exit(1); + } + if (check_flag) { + const anything_changed = try std.zig.render(allocator, io.null_out_stream, tree); + const code = if (anything_changed) @as(u8, 1) else @as(u8, 0); + process.exit(code); + } + + _ = try std.zig.render(allocator, stdout, tree); + return; + } + + if (input_files.len == 0) { + try stderr.write("expected at least one source file argument\n"); + process.exit(1); + } + + var fmt = Fmt{ + .seen = Fmt.SeenMap.init(allocator), + .any_error = false, + .color = color, + .allocator = allocator, + }; + + for (input_files.toSliceConst()) |file_path| { + try fmtPath(&fmt, file_path, check_flag); + } + if (fmt.any_error) { + process.exit(1); + } +} + +const FmtError = error{ + SystemResources, + OperationAborted, + IoPending, + BrokenPipe, + Unexpected, + WouldBlock, + FileClosed, + DestinationAddressRequired, + DiskQuota, + FileTooBig, + InputOutput, + NoSpaceLeft, + AccessDenied, + OutOfMemory, + RenameAcrossMountPoints, + ReadOnlyFileSystem, + LinkQuotaExceeded, + FileBusy, +} || fs.File.OpenError; + +fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool) FmtError!void { + if (fmt.seen.exists(file_path)) return; + try fmt.seen.put(file_path); + + const source_code = io.readFileAlloc(fmt.allocator, file_path) catch |err| switch (err) { + error.IsDir, error.AccessDenied => { + // TODO make event based (and dir.next()) + var dir = try fs.cwd().openDirList(file_path); + defer dir.close(); + + var dir_it = dir.iterate(); + + while (try dir_it.next()) |entry| { + if (entry.kind == .Directory or mem.endsWith(u8, entry.name, ".zig")) { + const full_path = try fs.path.join(fmt.allocator, &[_][]const u8{ file_path, entry.name }); + try fmtPath(fmt, full_path, check_mode); + } + } + return; + }, + else => { + // TODO lock stderr printing + try stderr.print("unable to open '{}': {}\n", .{ file_path, err }); + fmt.any_error = true; + return; + }, + }; + defer fmt.allocator.free(source_code); + + const tree = std.zig.parse(fmt.allocator, source_code) catch |err| { + try stderr.print("error parsing file '{}': {}\n", .{ file_path, err }); + fmt.any_error = true; + return; + }; + defer tree.deinit(); + + var error_it = tree.errors.iterator(0); + while (error_it.next()) |parse_error| { + try printErrMsgToFile(fmt.allocator, parse_error, tree, file_path, stderr_file, fmt.color); + } + if (tree.errors.len != 0) { + fmt.any_error = true; + return; + } + + if (check_mode) { + const anything_changed = try std.zig.render(fmt.allocator, io.null_out_stream, tree); + if (anything_changed) { + try stderr.print("{}\n", .{file_path}); + fmt.any_error = true; + } + } else { + const baf = try io.BufferedAtomicFile.create(fmt.allocator, file_path); + defer baf.destroy(); + + const anything_changed = try std.zig.render(fmt.allocator, baf.stream(), tree); + if (anything_changed) { + try stderr.print("{}\n", .{file_path}); + try baf.finish(); + } + } +} + +const Fmt = struct { + seen: SeenMap, + any_error: bool, + color: errmsg.Color, + allocator: *mem.Allocator, + + const SeenMap = std.BufSet; +}; + +fn printErrMsgToFile( + allocator: *mem.Allocator, + parse_error: *const ast.Error, + tree: *ast.Tree, + path: []const u8, + file: fs.File, + color: errmsg.Color, +) !void { + const color_on = switch (color) { + .Auto => file.isTty(), + .On => true, + .Off => false, + }; + const lok_token = parse_error.loc(); + const span = errmsg.Span{ + .first = lok_token, + .last = lok_token, + }; + + const first_token = tree.tokens.at(span.first); + const last_token = tree.tokens.at(span.last); + const start_loc = tree.tokenLocationPtr(0, first_token); + const end_loc = tree.tokenLocationPtr(first_token.end, last_token); + + var text_buf = try std.Buffer.initSize(allocator, 0); + var out_stream = &std.io.BufferOutStream.init(&text_buf).stream; + try parse_error.render(&tree.tokens, out_stream); + const text = text_buf.toOwnedSlice(); + + const stream = &file.outStream().stream; + try stream.print("{}:{}:{}: error: {}\n", .{ path, start_loc.line + 1, start_loc.column + 1, text }); + + if (!color_on) return; + + // Print \r and \t as one space each so that column counts line up + for (tree.source[start_loc.line_start..start_loc.line_end]) |byte| { + try stream.writeByte(switch (byte) { + '\r', '\t' => ' ', + else => byte, + }); + } + try stream.writeByte('\n'); + try stream.writeByteNTimes(' ', start_loc.column); + try stream.writeByteNTimes('~', last_token.end - first_token.start); + try stream.writeByte('\n'); +} + +export fn stage2_DepTokenizer_init(input: [*]const u8, len: usize) stage2_DepTokenizer { + const t = std.heap.c_allocator.create(DepTokenizer) catch @panic("failed to create .d tokenizer"); + t.* = DepTokenizer.init(std.heap.c_allocator, input[0..len]); + return stage2_DepTokenizer{ + .handle = t, + }; +} + +export fn stage2_DepTokenizer_deinit(self: *stage2_DepTokenizer) void { + self.handle.deinit(); +} + +export fn stage2_DepTokenizer_next(self: *stage2_DepTokenizer) stage2_DepNextResult { + const otoken = self.handle.next() catch { + const textz = std.Buffer.init(&self.handle.arena.allocator, self.handle.error_text) catch @panic("failed to create .d tokenizer error text"); + return stage2_DepNextResult{ + .type_id = .error_, + .textz = textz.toSlice().ptr, + }; + }; + const token = otoken orelse { + return stage2_DepNextResult{ + .type_id = .null_, + .textz = undefined, + }; + }; + const textz = std.Buffer.init(&self.handle.arena.allocator, token.bytes) catch @panic("failed to create .d tokenizer token text"); + return stage2_DepNextResult{ + .type_id = switch (token.id) { + .target => .target, + .prereq => .prereq, + }, + .textz = textz.toSlice().ptr, + }; +} + +const stage2_DepTokenizer = extern struct { + handle: *DepTokenizer, +}; + +const stage2_DepNextResult = extern struct { + type_id: TypeId, + + // when type_id == error --> error text + // when type_id == null --> undefined + // when type_id == target --> target pathname + // when type_id == prereq --> prereq pathname + textz: [*]const u8, + + const TypeId = extern enum { + error_, + null_, + target, + prereq, + }; +}; + +// ABI warning +export fn stage2_attach_segfault_handler() void { + if (std.debug.runtime_safety and std.debug.have_segfault_handling_support) { + std.debug.attachSegfaultHandler(); + } +} + +// ABI warning +export fn stage2_progress_create() *std.Progress { + const ptr = std.heap.c_allocator.create(std.Progress) catch @panic("out of memory"); + ptr.* = std.Progress{}; + return ptr; +} + +// ABI warning +export fn stage2_progress_destroy(progress: *std.Progress) void { + std.heap.c_allocator.destroy(progress); +} + +// ABI warning +export fn stage2_progress_start_root( + progress: *std.Progress, + name_ptr: [*]const u8, + name_len: usize, + estimated_total_items: usize, +) *std.Progress.Node { + return progress.start( + name_ptr[0..name_len], + if (estimated_total_items == 0) null else estimated_total_items, + ) catch @panic("timer unsupported"); +} + +// ABI warning +export fn stage2_progress_disable_tty(progress: *std.Progress) void { + progress.terminal = null; +} + +// ABI warning +export fn stage2_progress_start( + node: *std.Progress.Node, + name_ptr: [*]const u8, + name_len: usize, + estimated_total_items: usize, +) *std.Progress.Node { + const child_node = std.heap.c_allocator.create(std.Progress.Node) catch @panic("out of memory"); + child_node.* = node.start( + name_ptr[0..name_len], + if (estimated_total_items == 0) null else estimated_total_items, + ); + child_node.activate(); + return child_node; +} + +// ABI warning +export fn stage2_progress_end(node: *std.Progress.Node) void { + node.end(); + if (&node.context.root != node) { + std.heap.c_allocator.destroy(node); + } +} + +// ABI warning +export fn stage2_progress_complete_one(node: *std.Progress.Node) void { + node.completeOne(); +} + +// ABI warning +export fn stage2_progress_update_node(node: *std.Progress.Node, done_count: usize, total_count: usize) void { + node.completed_items = done_count; + node.estimated_total_items = total_count; + node.activate(); + node.context.maybeRefresh(); +} + +fn cpuFeaturesFromLLVM( + arch: Target.Arch, + llvm_cpu_name_z: ?[*:0]const u8, + llvm_cpu_features_opt: ?[*:0]const u8, +) !Target.CpuFeatures { + var result = arch.getBaselineCpuFeatures(); + + if (llvm_cpu_name_z) |cpu_name_z| { + const llvm_cpu_name = mem.toSliceConst(u8, cpu_name_z); + + for (arch.allCpus()) |cpu| { + const this_llvm_name = cpu.llvm_name orelse continue; + if (mem.eql(u8, this_llvm_name, llvm_cpu_name)) { + // Here we use the non-dependencies-populated set, + // so that subtracting features later in this function + // affect the prepopulated set. + result = Target.CpuFeatures{ + .cpu = cpu, + .features = cpu.features, + }; + break; + } + } + } + + const all_features = arch.allFeaturesList(); + + if (llvm_cpu_features_opt) |llvm_cpu_features| { + var it = mem.tokenize(mem.toSliceConst(u8, llvm_cpu_features), ","); + while (it.next()) |decorated_llvm_feat| { + var op: enum { + add, + sub, + } = undefined; + var llvm_feat: []const u8 = undefined; + if (mem.startsWith(u8, decorated_llvm_feat, "+")) { + op = .add; + llvm_feat = decorated_llvm_feat[1..]; + } else if (mem.startsWith(u8, decorated_llvm_feat, "-")) { + op = .sub; + llvm_feat = decorated_llvm_feat[1..]; + } else { + return error.InvalidLlvmCpuFeaturesFormat; + } + for (all_features) |feature, index_usize| { + const this_llvm_name = feature.llvm_name orelse continue; + if (mem.eql(u8, llvm_feat, this_llvm_name)) { + const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize); + switch (op) { + .add => result.features.addFeature(index), + .sub => result.features.removeFeature(index), + } + break; + } + } + } + } + + result.features.populateDependencies(all_features); + return result; +} + +// ABI warning +export fn stage2_cmd_targets(zig_triple: [*:0]const u8) c_int { + cmdTargets(zig_triple) catch |err| { + std.debug.warn("unable to list targets: {}\n", .{@errorName(err)}); + return -1; + }; + return 0; +} + +fn cmdTargets(zig_triple: [*:0]const u8) !void { + var target = try Target.parse(mem.toSliceConst(u8, zig_triple)); + target.Cross.cpu_features = blk: { + const llvm = @import("llvm.zig"); + const llvm_cpu_name = llvm.GetHostCPUName(); + const llvm_cpu_features = llvm.GetNativeFeatures(); + break :blk try cpuFeaturesFromLLVM(target.Cross.arch, llvm_cpu_name, llvm_cpu_features); + }; + return @import("print_targets.zig").cmdTargets( + std.heap.c_allocator, + &[0][]u8{}, + &std.io.getStdOut().outStream().stream, + target, + ); +} + +const Stage2CpuFeatures = struct { + allocator: *mem.Allocator, + cpu_features: Target.CpuFeatures, + + llvm_features_str: ?[*:0]const u8, + + builtin_str: [:0]const u8, + cache_hash: [:0]const u8, + + const Self = @This(); + + fn createFromNative(allocator: *mem.Allocator) !*Self { + const arch = Target.current.getArch(); + const llvm = @import("llvm.zig"); + const llvm_cpu_name = llvm.GetHostCPUName(); + const llvm_cpu_features = llvm.GetNativeFeatures(); + const cpu_features = try cpuFeaturesFromLLVM(arch, llvm_cpu_name, llvm_cpu_features); + return createFromCpuFeatures(allocator, arch, cpu_features); + } + + fn createFromCpuFeatures( + allocator: *mem.Allocator, + arch: Target.Arch, + cpu_features: Target.CpuFeatures, + ) !*Self { + const self = try allocator.create(Self); + errdefer allocator.destroy(self); + + const cache_hash = try std.fmt.allocPrint0(allocator, "{}\n{}", .{ + cpu_features.cpu.name, + cpu_features.features.asBytes(), + }); + errdefer allocator.free(cache_hash); + + const generic_arch_name = arch.genericName(); + var builtin_str_buffer = try std.Buffer.allocPrint(allocator, + \\CpuFeatures{{ + \\ .cpu = &Target.{}.cpu.{}, + \\ .features = Target.{}.featureSet(&[_]Target.{}.Feature{{ + \\ + , .{ + generic_arch_name, + cpu_features.cpu.name, + generic_arch_name, + generic_arch_name, + }); + defer builtin_str_buffer.deinit(); + + var llvm_features_buffer = try std.Buffer.initSize(allocator, 0); + defer llvm_features_buffer.deinit(); + + for (arch.allFeaturesList()) |feature, index_usize| { + const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize); + const is_enabled = cpu_features.features.isEnabled(index); + + if (feature.llvm_name) |llvm_name| { + const plus_or_minus = "-+"[@boolToInt(is_enabled)]; + try llvm_features_buffer.appendByte(plus_or_minus); + try llvm_features_buffer.append(llvm_name); + try llvm_features_buffer.append(","); + } + + if (is_enabled) { + // TODO some kind of "zig identifier escape" function rather than + // unconditionally using @"" syntax + try builtin_str_buffer.append(" .@\""); + try builtin_str_buffer.append(feature.name); + try builtin_str_buffer.append("\",\n"); + } + } + + try builtin_str_buffer.append( + \\ }), + \\}; + \\ + ); + + assert(mem.endsWith(u8, llvm_features_buffer.toSliceConst(), ",")); + llvm_features_buffer.shrink(llvm_features_buffer.len() - 1); + + self.* = Self{ + .allocator = allocator, + .cpu_features = cpu_features, + .llvm_features_str = llvm_features_buffer.toOwnedSlice().ptr, + .builtin_str = builtin_str_buffer.toOwnedSlice(), + .cache_hash = cache_hash, + }; + return self; + } + + fn destroy(self: *Self) void { + self.allocator.free(self.cache_hash); + self.allocator.free(self.builtin_str); + // TODO if (self.llvm_features_str) |llvm_features_str| self.allocator.free(llvm_features_str); + self.allocator.destroy(self); + } +}; + +// ABI warning +export fn stage2_cpu_features_parse( + result: **Stage2CpuFeatures, + zig_triple: ?[*:0]const u8, + cpu_name: ?[*:0]const u8, + cpu_features: ?[*:0]const u8, +) Error { + result.* = stage2ParseCpuFeatures(zig_triple, cpu_name, cpu_features) catch |err| switch (err) { + error.OutOfMemory => return .OutOfMemory, + error.UnknownArchitecture => return .UnknownArchitecture, + error.UnknownSubArchitecture => return .UnknownSubArchitecture, + error.UnknownOperatingSystem => return .UnknownOperatingSystem, + error.UnknownApplicationBinaryInterface => return .UnknownApplicationBinaryInterface, + error.MissingOperatingSystem => return .MissingOperatingSystem, + error.MissingArchitecture => return .MissingArchitecture, + error.InvalidLlvmCpuFeaturesFormat => return .InvalidLlvmCpuFeaturesFormat, + error.InvalidCpuFeatures => return .InvalidCpuFeatures, + }; + return .None; +} + +fn stage2ParseCpuFeatures( + zig_triple_oz: ?[*:0]const u8, + cpu_name_oz: ?[*:0]const u8, + cpu_features_oz: ?[*:0]const u8, +) !*Stage2CpuFeatures { + const zig_triple_z = zig_triple_oz orelse return Stage2CpuFeatures.createFromNative(std.heap.c_allocator); + const target = try Target.parse(mem.toSliceConst(u8, zig_triple_z)); + const arch = target.Cross.arch; + + const cpu = if (cpu_name_oz) |cpu_name_z| blk: { + const cpu_name = mem.toSliceConst(u8, cpu_name_z); + break :blk arch.parseCpu(cpu_name) catch |err| switch (err) { + error.UnknownCpu => { + std.debug.warn("Unknown CPU: '{}'\nAvailable CPUs for architecture '{}':\n", .{ + cpu_name, + @tagName(arch), + }); + for (arch.allCpus()) |cpu| { + std.debug.warn(" {}\n", .{cpu.name}); + } + process.exit(1); + }, + else => |e| return e, + }; + } else target.Cross.cpu_features.cpu; + + var set = if (cpu_features_oz) |cpu_features_z| blk: { + const cpu_features = mem.toSliceConst(u8, cpu_features_z); + break :blk arch.parseCpuFeatureSet(cpu, cpu_features) catch |err| switch (err) { + error.UnknownCpuFeature => { + std.debug.warn( + \\Unknown CPU features specified. + \\Available CPU features for architecture '{}': + \\ + , .{@tagName(arch)}); + for (arch.allFeaturesList()) |feature| { + std.debug.warn(" {}\n", .{feature.name}); + } + process.exit(1); + }, + else => |e| return e, + }; + } else cpu.features; + + if (arch.subArchFeature()) |index| { + set.addFeature(index); + } + set.populateDependencies(arch.allFeaturesList()); + + return Stage2CpuFeatures.createFromCpuFeatures(std.heap.c_allocator, arch, .{ + .cpu = cpu, + .features = set, + }); +} + +// ABI warning +export fn stage2_cpu_features_get_cache_hash( + cpu_features: *const Stage2CpuFeatures, + ptr: *[*:0]const u8, + len: *usize, +) void { + ptr.* = cpu_features.cache_hash.ptr; + len.* = cpu_features.cache_hash.len; +} + +// ABI warning +export fn stage2_cpu_features_get_builtin_str( + cpu_features: *const Stage2CpuFeatures, + ptr: *[*:0]const u8, + len: *usize, +) void { + ptr.* = cpu_features.builtin_str.ptr; + len.* = cpu_features.builtin_str.len; +} + +// ABI warning +export fn stage2_cpu_features_get_llvm_cpu(cpu_features: *const Stage2CpuFeatures) ?[*:0]const u8 { + return if (cpu_features.cpu_features.cpu.llvm_name) |s| s.ptr else null; +} + +// ABI warning +export fn stage2_cpu_features_get_llvm_features(cpu_features: *const Stage2CpuFeatures) ?[*:0]const u8 { + return cpu_features.llvm_features_str; +} + +// ABI warning +const Stage2LibCInstallation = extern struct { + include_dir: [*:0]const u8, + include_dir_len: usize, + sys_include_dir: [*:0]const u8, + sys_include_dir_len: usize, + crt_dir: [*:0]const u8, + crt_dir_len: usize, + static_crt_dir: [*:0]const u8, + static_crt_dir_len: usize, + msvc_lib_dir: [*:0]const u8, + msvc_lib_dir_len: usize, + kernel32_lib_dir: [*:0]const u8, + kernel32_lib_dir_len: usize, + + fn initFromStage2(self: *Stage2LibCInstallation, libc: LibCInstallation) void { + if (libc.include_dir) |s| { + self.include_dir = s.ptr; + self.include_dir_len = s.len; + } else { + self.include_dir = ""; + self.include_dir_len = 0; + } + if (libc.sys_include_dir) |s| { + self.sys_include_dir = s.ptr; + self.sys_include_dir_len = s.len; + } else { + self.sys_include_dir = ""; + self.sys_include_dir_len = 0; + } + if (libc.crt_dir) |s| { + self.crt_dir = s.ptr; + self.crt_dir_len = s.len; + } else { + self.crt_dir = ""; + self.crt_dir_len = 0; + } + if (libc.static_crt_dir) |s| { + self.static_crt_dir = s.ptr; + self.static_crt_dir_len = s.len; + } else { + self.static_crt_dir = ""; + self.static_crt_dir_len = 0; + } + if (libc.msvc_lib_dir) |s| { + self.msvc_lib_dir = s.ptr; + self.msvc_lib_dir_len = s.len; + } else { + self.msvc_lib_dir = ""; + self.msvc_lib_dir_len = 0; + } + if (libc.kernel32_lib_dir) |s| { + self.kernel32_lib_dir = s.ptr; + self.kernel32_lib_dir_len = s.len; + } else { + self.kernel32_lib_dir = ""; + self.kernel32_lib_dir_len = 0; + } + } + + fn toStage2(self: Stage2LibCInstallation) LibCInstallation { + var libc: LibCInstallation = .{}; + if (self.include_dir_len != 0) { + libc.include_dir = self.include_dir[0..self.include_dir_len :0]; + } + if (self.sys_include_dir_len != 0) { + libc.sys_include_dir = self.sys_include_dir[0..self.sys_include_dir_len :0]; + } + if (self.crt_dir_len != 0) { + libc.crt_dir = self.crt_dir[0..self.crt_dir_len :0]; + } + if (self.static_crt_dir_len != 0) { + libc.static_crt_dir = self.static_crt_dir[0..self.static_crt_dir_len :0]; + } + if (self.msvc_lib_dir_len != 0) { + libc.msvc_lib_dir = self.msvc_lib_dir[0..self.msvc_lib_dir_len :0]; + } + if (self.kernel32_lib_dir_len != 0) { + libc.kernel32_lib_dir = self.kernel32_lib_dir[0..self.kernel32_lib_dir_len :0]; + } + return libc; + } +}; + +// ABI warning +export fn stage2_libc_parse(stage1_libc: *Stage2LibCInstallation, libc_file_z: [*:0]const u8) Error { + stderr_file = std.io.getStdErr(); + stderr = &stderr_file.outStream().stream; + const libc_file = mem.toSliceConst(u8, libc_file_z); + var libc = LibCInstallation.parse(std.heap.c_allocator, libc_file, stderr) catch |err| switch (err) { + error.ParseError => return .SemanticAnalyzeFail, + error.DiskQuota => return .DiskQuota, + error.FileTooBig => return .FileTooBig, + error.InputOutput => return .FileSystem, + error.NoSpaceLeft => return .NoSpaceLeft, + error.AccessDenied => return .AccessDenied, + error.BrokenPipe => return .BrokenPipe, + error.SystemResources => return .SystemResources, + error.OperationAborted => return .OperationAborted, + error.WouldBlock => unreachable, + error.Unexpected => return .Unexpected, + error.EndOfStream => return .EndOfFile, + error.IsDir => return .IsDir, + error.ConnectionResetByPeer => unreachable, + error.OutOfMemory => return .OutOfMemory, + error.Unseekable => unreachable, + error.SharingViolation => return .SharingViolation, + error.PathAlreadyExists => unreachable, + error.FileNotFound => return .FileNotFound, + error.PipeBusy => return .PipeBusy, + error.NameTooLong => return .PathTooLong, + error.InvalidUtf8 => return .BadPathName, + error.BadPathName => return .BadPathName, + error.SymLinkLoop => return .SymLinkLoop, + error.ProcessFdQuotaExceeded => return .ProcessFdQuotaExceeded, + error.SystemFdQuotaExceeded => return .SystemFdQuotaExceeded, + error.NoDevice => return .NoDevice, + error.NotDir => return .NotDir, + error.DeviceBusy => return .DeviceBusy, + }; + stage1_libc.initFromStage2(libc); + return .None; +} + +// ABI warning +export fn stage2_libc_find_native(stage1_libc: *Stage2LibCInstallation) Error { + var libc = LibCInstallation.findNative(std.heap.c_allocator) catch |err| switch (err) { + error.OutOfMemory => return .OutOfMemory, + error.FileSystem => return .FileSystem, + error.UnableToSpawnCCompiler => return .UnableToSpawnCCompiler, + error.CCompilerExitCode => return .CCompilerExitCode, + error.CCompilerCrashed => return .CCompilerCrashed, + error.CCompilerCannotFindHeaders => return .CCompilerCannotFindHeaders, + error.LibCRuntimeNotFound => return .LibCRuntimeNotFound, + error.LibCStdLibHeaderNotFound => return .LibCStdLibHeaderNotFound, + error.LibCKernel32LibNotFound => return .LibCKernel32LibNotFound, + error.UnsupportedArchitecture => return .UnsupportedArchitecture, + }; + stage1_libc.initFromStage2(libc); + return .None; +} + +// ABI warning +export fn stage2_libc_render(stage1_libc: *Stage2LibCInstallation, output_file: *FILE) Error { + var libc = stage1_libc.toStage2(); + const c_out_stream = &std.io.COutStream.init(output_file).stream; + libc.render(c_out_stream) catch |err| switch (err) { + error.WouldBlock => unreachable, // stage1 opens stuff in exclusively blocking mode + error.SystemResources => return .SystemResources, + error.OperationAborted => return .OperationAborted, + error.BrokenPipe => return .BrokenPipe, + error.DiskQuota => return .DiskQuota, + error.FileTooBig => return .FileTooBig, + error.NoSpaceLeft => return .NoSpaceLeft, + error.AccessDenied => return .AccessDenied, + error.Unexpected => return .Unexpected, + error.InputOutput => return .FileSystem, + }; + return .None; +} + +// ABI warning +export fn stage2_libc_cc_print_file_name( + out_ptr: *[*:0]u8, + out_len: *usize, + o_file: [*:0]const u8, + want_dirname: bool, +) Error { + const result = @import("libc_installation.zig").ccPrintFileName( + std.heap.c_allocator, + mem.toSliceConst(u8, o_file), + if (want_dirname) .only_dir else .full_path, + ) catch |err| switch (err) { + error.OutOfMemory => return .OutOfMemory, + error.LibCRuntimeNotFound => return .FileNotFound, + error.CCompilerExitCode => return .CCompilerExitCode, + error.CCompilerCrashed => return .CCompilerCrashed, + error.UnableToSpawnCCompiler => return .UnableToSpawnCCompiler, + }; + out_ptr.* = result.ptr; + out_len.* = result.len; + return .None; +} diff --git a/src/cache_hash.cpp b/src/cache_hash.cpp index 714b9b4c1861b2645e53adeabf5c686f20cdac8e..35b05a1ddf8be39afe0b4d24fad7b5c60925c766 100644 --- a/src/cache_hash.cpp +++ b/src/cache_hash.cpp @@ -5,7 +5,7 @@ * See http://opensource.org/licenses/MIT */ -#include "userland.h" +#include "stage2.h" #include "cache_hash.hpp" #include "all_types.hpp" #include "buffer.hpp" diff --git a/src/codegen.cpp b/src/codegen.cpp index 22d76c1372dd13b6a55b18334e9bd5f9c655dd58..0b5d2e82f1be681022a5ec6a713937040cb4702e 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -18,7 +18,7 @@ #include "target.hpp" #include "util.hpp" #include "zig_llvm.h" -#include "userland.h" +#include "stage2.h" #include "dump_analysis.hpp" #include "softfloat.hpp" #include "mem_profile.hpp" diff --git a/src/codegen.hpp b/src/codegen.hpp index 623ae12fef62d0d62d4f1c5a3bd200f023691725..f8be29494a8cab83905d12ed6ef3dc05ceaacfac 100644 --- a/src/codegen.hpp +++ b/src/codegen.hpp @@ -11,7 +11,7 @@ #include "parser.hpp" #include "errmsg.hpp" #include "target.hpp" -#include "userland.h" +#include "stage2.h" #include diff --git a/src/error.hpp b/src/error.hpp index 3ff36e1a5f224fa797db37a9686b597d984f702e..90772df10814b6f8ce452675803e9847658eb5cf 100644 --- a/src/error.hpp +++ b/src/error.hpp @@ -8,7 +8,7 @@ #ifndef ERROR_HPP #define ERROR_HPP -#include "userland.h" +#include "stage2.h" const char *err_str(Error err); diff --git a/src/main.cpp b/src/main.cpp index 4f5367be7bf945af37666de9523a0e6736a33410..df6e07a5a71f3940250a10e74be3633b014af8d9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -14,7 +14,7 @@ #include "heap.hpp" #include "os.hpp" #include "target.hpp" -#include "userland.h" +#include "stage2.h" #include "glibc.hpp" #include "dump_analysis.hpp" #include "mem_profile.hpp" diff --git a/src/stage2.cpp b/src/stage2.cpp new file mode 100644 index 0000000000000000000000000000000000000000..db4f529c68ecfbe6627400a8855895f2aa0877e8 --- /dev/null +++ b/src/stage2.cpp @@ -0,0 +1,179 @@ +// 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 +#include +#include + +Error stage2_translate_c(struct Stage2Ast **out_ast, + struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len, + const char **args_begin, const char **args_end, const char *resources_path) +{ + const char *msg = "stage0 called stage2_translate_c"; + stage2_panic(msg, strlen(msg)); +} + +void stage2_free_clang_errors(struct Stage2ErrorMsg *ptr, size_t len) { + const char *msg = "stage0 called stage2_free_clang_errors"; + stage2_panic(msg, strlen(msg)); +} + +void stage2_zen(const char **ptr, size_t *len) { + const char *msg = "stage0 called stage2_zen"; + stage2_panic(msg, strlen(msg)); +} + +void stage2_attach_segfault_handler(void) { } + +void stage2_panic(const char *ptr, size_t len) { + fwrite(ptr, 1, len, stderr); + fprintf(stderr, "\n"); + fflush(stderr); + abort(); +} + +void stage2_render_ast(struct Stage2Ast *ast, FILE *output_file) { + const char *msg = "stage0 called stage2_render_ast"; + stage2_panic(msg, strlen(msg)); +} + +int stage2_fmt(int argc, char **argv) { + const char *msg = "stage0 called stage2_fmt"; + stage2_panic(msg, strlen(msg)); +} + +stage2_DepTokenizer stage2_DepTokenizer_init(const char *input, size_t len) { + const char *msg = "stage0 called stage2_DepTokenizer_init"; + stage2_panic(msg, strlen(msg)); +} + +void stage2_DepTokenizer_deinit(stage2_DepTokenizer *self) { + const char *msg = "stage0 called stage2_DepTokenizer_deinit"; + stage2_panic(msg, strlen(msg)); +} + +stage2_DepNextResult stage2_DepTokenizer_next(stage2_DepTokenizer *self) { + const char *msg = "stage0 called stage2_DepTokenizer_next"; + stage2_panic(msg, strlen(msg)); +} + + +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){} + +struct Stage2CpuFeatures { + const char *llvm_cpu_name; + const char *llvm_cpu_features; + const char *builtin_str; + const char *cache_hash; +}; + +Error stage2_cpu_features_parse(struct Stage2CpuFeatures **out, const char *zig_triple, + const char *cpu_name, const char *cpu_features) +{ + if (zig_triple == nullptr) { + Stage2CpuFeatures *result = heap::c_allocator.create(); + result->llvm_cpu_name = ZigLLVMGetHostCPUName(); + result->llvm_cpu_features = ZigLLVMGetNativeFeatures(); + result->builtin_str = "arch.getBaselineCpuFeatures();\n"; + result->cache_hash = "native\n\n"; + *out = result; + return ErrorNone; + } + if (cpu_name == nullptr && cpu_features == nullptr) { + Stage2CpuFeatures *result = heap::c_allocator.create(); + result->builtin_str = "arch.getBaselineCpuFeatures();\n"; + result->cache_hash = "\n\n"; + *out = result; + return ErrorNone; + } + + const char *msg = "stage0 called stage2_cpu_features_parse with non-null cpu name or features"; + stage2_panic(msg, strlen(msg)); +} + +void stage2_cpu_features_get_cache_hash(const Stage2CpuFeatures *cpu_features, + const char **ptr, size_t *len) +{ + *ptr = cpu_features->cache_hash; + *len = strlen(cpu_features->cache_hash); +} +const char *stage2_cpu_features_get_llvm_cpu(const Stage2CpuFeatures *cpu_features) { + return cpu_features->llvm_cpu_name; +} +const char *stage2_cpu_features_get_llvm_features(const Stage2CpuFeatures *cpu_features) { + return cpu_features->llvm_cpu_features; +} +void stage2_cpu_features_get_builtin_str(const Stage2CpuFeatures *cpu_features, + const char **ptr, size_t *len) +{ + *ptr = cpu_features->builtin_str; + *len = strlen(cpu_features->builtin_str); +} + +int stage2_cmd_targets(const char *zig_triple) { + const char *msg = "stage0 called stage2_cmd_targets"; + stage2_panic(msg, strlen(msg)); +} + +enum Error stage2_libc_parse(struct Stage2LibCInstallation *libc, const char *libc_file) { + libc->include_dir = "/dummy/include"; + libc->include_dir_len = strlen(libc->include_dir); + libc->sys_include_dir = "/dummy/sys/include"; + libc->sys_include_dir_len = strlen(libc->sys_include_dir); + libc->crt_dir = ""; + libc->crt_dir_len = strlen(libc->crt_dir); + libc->static_crt_dir = ""; + libc->static_crt_dir_len = strlen(libc->static_crt_dir); + libc->msvc_lib_dir = ""; + libc->msvc_lib_dir_len = strlen(libc->msvc_lib_dir); + libc->kernel32_lib_dir = ""; + libc->kernel32_lib_dir_len = strlen(libc->kernel32_lib_dir); + return ErrorNone; +} + +enum Error stage2_libc_render(struct Stage2LibCInstallation *self, FILE *file) { + const char *msg = "stage0 called stage2_libc_render"; + stage2_panic(msg, strlen(msg)); +} + +enum Error stage2_libc_find_native(struct Stage2LibCInstallation *libc) { + const char *msg = "stage0 called stage2_libc_find_native"; + stage2_panic(msg, strlen(msg)); +} + +enum Error stage2_libc_cc_print_file_name(char **out_ptr, size_t *out_len, + const char *o_file, bool want_dirname) +{ + const char *msg = "stage0 called stage2_libc_cc_print_file_name"; + stage2_panic(msg, strlen(msg)); +} diff --git a/src/stage2.h b/src/stage2.h new file mode 100644 index 0000000000000000000000000000000000000000..f6bb17c8843977701203aff12a0a511c02b5395e --- /dev/null +++ b/src/stage2.h @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2019 Andrew Kelley + * + * This file is part of zig, which is MIT licensed. + * See http://opensource.org/licenses/MIT + */ + +#ifndef ZIG_STAGE2_H +#define ZIG_STAGE2_H + +#include +#include +#include + +#ifdef __cplusplus +#define ZIG_EXTERN_C extern "C" +#else +#define ZIG_EXTERN_C +#endif + +#if defined(_MSC_VER) +#define ZIG_ATTRIBUTE_NORETURN __declspec(noreturn) +#else +#define ZIG_ATTRIBUTE_NORETURN __attribute__((noreturn)) +#endif + +// ABI warning: the types and declarations in this file must match both those in +// stage2.cpp and src-self-hosted/stage2.zig. + +// ABI warning +enum Error { + ErrorNone, + ErrorNoMem, + ErrorInvalidFormat, + ErrorSemanticAnalyzeFail, + ErrorAccess, + ErrorInterrupted, + ErrorSystemResources, + ErrorFileNotFound, + ErrorFileSystem, + ErrorFileTooBig, + ErrorDivByZero, + ErrorOverflow, + ErrorPathAlreadyExists, + ErrorUnexpected, + ErrorExactDivRemainder, + ErrorNegativeDenominator, + ErrorShiftedOutOneBits, + ErrorCCompileErrors, + ErrorEndOfFile, + ErrorIsDir, + ErrorNotDir, + ErrorUnsupportedOperatingSystem, + ErrorSharingViolation, + ErrorPipeBusy, + ErrorPrimitiveTypeNotFound, + ErrorCacheUnavailable, + ErrorPathTooLong, + ErrorCCompilerCannotFindFile, + ErrorNoCCompilerInstalled, + ErrorReadingDepFile, + ErrorInvalidDepFile, + ErrorMissingArchitecture, + ErrorMissingOperatingSystem, + ErrorUnknownArchitecture, + ErrorUnknownOperatingSystem, + ErrorUnknownABI, + ErrorInvalidFilename, + ErrorDiskQuota, + ErrorDiskSpace, + ErrorUnexpectedWriteFailure, + ErrorUnexpectedSeekFailure, + ErrorUnexpectedFileTruncationFailure, + ErrorUnimplemented, + ErrorOperationAborted, + ErrorBrokenPipe, + ErrorNoSpaceLeft, + ErrorNotLazy, + ErrorIsAsync, + ErrorImportOutsidePkgPath, + ErrorUnknownCpu, + ErrorUnknownSubArchitecture, + ErrorUnknownCpuFeature, + ErrorInvalidCpuFeatures, + ErrorInvalidLlvmCpuFeaturesFormat, + ErrorUnknownApplicationBinaryInterface, + ErrorASTUnitFailure, + ErrorBadPathName, + ErrorSymLinkLoop, + ErrorProcessFdQuotaExceeded, + ErrorSystemFdQuotaExceeded, + ErrorNoDevice, + ErrorDeviceBusy, + ErrorUnableToSpawnCCompiler, + ErrorCCompilerExitCode, + ErrorCCompilerCrashed, + ErrorCCompilerCannotFindHeaders, + ErrorLibCRuntimeNotFound, + ErrorLibCStdLibHeaderNotFound, + ErrorLibCKernel32LibNotFound, + ErrorUnsupportedArchitecture, +}; + +// ABI warning +struct Stage2ErrorMsg { + const char *filename_ptr; // can be null + size_t filename_len; + const char *msg_ptr; + size_t msg_len; + const char *source; // valid until the ASTUnit is freed. can be null + unsigned line; // 0 based + unsigned column; // 0 based + unsigned offset; // byte offset into source +}; + +// ABI warning +struct Stage2Ast; + +// ABI warning +ZIG_EXTERN_C enum Error stage2_translate_c(struct Stage2Ast **out_ast, + struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len, + const char **args_begin, const char **args_end, const char *resources_path); + +// ABI warning +ZIG_EXTERN_C void stage2_free_clang_errors(struct Stage2ErrorMsg *ptr, size_t len); + +// ABI warning +ZIG_EXTERN_C void stage2_render_ast(struct Stage2Ast *ast, FILE *output_file); + +// ABI warning +ZIG_EXTERN_C void stage2_zen(const char **ptr, size_t *len); + +// ABI warning +ZIG_EXTERN_C void stage2_attach_segfault_handler(void); + +// ABI warning +ZIG_EXTERN_C ZIG_ATTRIBUTE_NORETURN void stage2_panic(const char *ptr, size_t len); + +// ABI warning +ZIG_EXTERN_C int stage2_fmt(int argc, char **argv); + +// ABI warning +struct stage2_DepTokenizer { + void *handle; +}; + +// ABI warning +struct stage2_DepNextResult { + enum TypeId { + error, + null, + target, + prereq, + }; + + TypeId type_id; + + // when ent == error --> error text + // when ent == null --> undefined + // when ent == target --> target pathname + // when ent == prereq --> prereq pathname + const char *textz; +}; + +// ABI warning +ZIG_EXTERN_C stage2_DepTokenizer stage2_DepTokenizer_init(const char *input, size_t len); + +// ABI warning +ZIG_EXTERN_C void stage2_DepTokenizer_deinit(stage2_DepTokenizer *self); + +// ABI warning +ZIG_EXTERN_C stage2_DepNextResult stage2_DepTokenizer_next(stage2_DepTokenizer *self); + +// ABI warning +struct Stage2Progress; +// ABI warning +struct Stage2ProgressNode; +// ABI warning +ZIG_EXTERN_C Stage2Progress *stage2_progress_create(void); +// ABI warning +ZIG_EXTERN_C void stage2_progress_disable_tty(Stage2Progress *progress); +// ABI warning +ZIG_EXTERN_C void stage2_progress_destroy(Stage2Progress *progress); +// ABI warning +ZIG_EXTERN_C Stage2ProgressNode *stage2_progress_start_root(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, + const char *name_ptr, size_t name_len, size_t estimated_total_items); +// ABI warning +ZIG_EXTERN_C void stage2_progress_end(Stage2ProgressNode *node); +// ABI warning +ZIG_EXTERN_C void stage2_progress_complete_one(Stage2ProgressNode *node); +// ABI warning +ZIG_EXTERN_C void stage2_progress_update_node(Stage2ProgressNode *node, + size_t completed_count, size_t estimated_total_items); + +// ABI warning +struct Stage2CpuFeatures; + +// ABI warning +ZIG_EXTERN_C enum Error stage2_cpu_features_parse(struct Stage2CpuFeatures **result, + const char *zig_triple, const char *cpu_name, const char *cpu_features); + +// ABI warning +ZIG_EXTERN_C const char *stage2_cpu_features_get_llvm_cpu(const struct Stage2CpuFeatures *cpu_features); + +// ABI warning +ZIG_EXTERN_C const char *stage2_cpu_features_get_llvm_features(const struct Stage2CpuFeatures *cpu_features); + +// ABI warning +ZIG_EXTERN_C void stage2_cpu_features_get_builtin_str(const struct Stage2CpuFeatures *cpu_features, + const char **ptr, size_t *len); + +// ABI warning +ZIG_EXTERN_C void stage2_cpu_features_get_cache_hash(const struct Stage2CpuFeatures *cpu_features, + const char **ptr, size_t *len); + +// ABI warning +ZIG_EXTERN_C int stage2_cmd_targets(const char *zig_triple); + +// ABI warning +struct Stage2LibCInstallation { + const char *include_dir; + size_t include_dir_len; + const char *sys_include_dir; + size_t sys_include_dir_len; + const char *crt_dir; + size_t crt_dir_len; + const char *static_crt_dir; + size_t static_crt_dir_len; + const char *msvc_lib_dir; + size_t msvc_lib_dir_len; + const char *kernel32_lib_dir; + size_t kernel32_lib_dir_len; +}; + +// ABI warning +ZIG_EXTERN_C enum Error stage2_libc_parse(struct Stage2LibCInstallation *libc, const char *libc_file); +// ABI warning +ZIG_EXTERN_C enum Error stage2_libc_render(struct Stage2LibCInstallation *self, FILE *file); +// ABI warning +ZIG_EXTERN_C enum Error stage2_libc_find_native(struct Stage2LibCInstallation *libc); +// ABI warning +ZIG_EXTERN_C enum Error stage2_libc_cc_print_file_name(char **out_ptr, size_t *out_len, + const char *o_file, bool want_dirname); + +#endif diff --git a/src/userland.cpp b/src/userland.cpp deleted file mode 100644 index 2be97f22d65b5ca2cf8537053439ce680328fe61..0000000000000000000000000000000000000000 --- a/src/userland.cpp +++ /dev/null @@ -1,179 +0,0 @@ -// This file is a shim for zig1. The real implementations of these are in -// src-self-hosted/stage1.zig - -#include "userland.h" -#include "util.hpp" -#include "zig_llvm.h" -#include -#include -#include - -Error stage2_translate_c(struct Stage2Ast **out_ast, - struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len, - const char **args_begin, const char **args_end, const char *resources_path) -{ - const char *msg = "stage0 called stage2_translate_c"; - stage2_panic(msg, strlen(msg)); -} - -void stage2_free_clang_errors(struct Stage2ErrorMsg *ptr, size_t len) { - const char *msg = "stage0 called stage2_free_clang_errors"; - stage2_panic(msg, strlen(msg)); -} - -void stage2_zen(const char **ptr, size_t *len) { - const char *msg = "stage0 called stage2_zen"; - stage2_panic(msg, strlen(msg)); -} - -void stage2_attach_segfault_handler(void) { } - -void stage2_panic(const char *ptr, size_t len) { - fwrite(ptr, 1, len, stderr); - fprintf(stderr, "\n"); - fflush(stderr); - abort(); -} - -void stage2_render_ast(struct Stage2Ast *ast, FILE *output_file) { - const char *msg = "stage0 called stage2_render_ast"; - stage2_panic(msg, strlen(msg)); -} - -int stage2_fmt(int argc, char **argv) { - const char *msg = "stage0 called stage2_fmt"; - stage2_panic(msg, strlen(msg)); -} - -stage2_DepTokenizer stage2_DepTokenizer_init(const char *input, size_t len) { - const char *msg = "stage0 called stage2_DepTokenizer_init"; - stage2_panic(msg, strlen(msg)); -} - -void stage2_DepTokenizer_deinit(stage2_DepTokenizer *self) { - const char *msg = "stage0 called stage2_DepTokenizer_deinit"; - stage2_panic(msg, strlen(msg)); -} - -stage2_DepNextResult stage2_DepTokenizer_next(stage2_DepTokenizer *self) { - const char *msg = "stage0 called stage2_DepTokenizer_next"; - stage2_panic(msg, strlen(msg)); -} - - -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){} - -struct Stage2CpuFeatures { - const char *llvm_cpu_name; - const char *llvm_cpu_features; - const char *builtin_str; - const char *cache_hash; -}; - -Error stage2_cpu_features_parse(struct Stage2CpuFeatures **out, const char *zig_triple, - const char *cpu_name, const char *cpu_features) -{ - if (zig_triple == nullptr) { - Stage2CpuFeatures *result = heap::c_allocator.create(); - result->llvm_cpu_name = ZigLLVMGetHostCPUName(); - result->llvm_cpu_features = ZigLLVMGetNativeFeatures(); - result->builtin_str = "arch.getBaselineCpuFeatures();\n"; - result->cache_hash = "native\n\n"; - *out = result; - return ErrorNone; - } - if (cpu_name == nullptr && cpu_features == nullptr) { - Stage2CpuFeatures *result = heap::c_allocator.create(); - result->builtin_str = "arch.getBaselineCpuFeatures();\n"; - result->cache_hash = "\n\n"; - *out = result; - return ErrorNone; - } - - const char *msg = "stage0 called stage2_cpu_features_parse with non-null cpu name or features"; - stage2_panic(msg, strlen(msg)); -} - -void stage2_cpu_features_get_cache_hash(const Stage2CpuFeatures *cpu_features, - const char **ptr, size_t *len) -{ - *ptr = cpu_features->cache_hash; - *len = strlen(cpu_features->cache_hash); -} -const char *stage2_cpu_features_get_llvm_cpu(const Stage2CpuFeatures *cpu_features) { - return cpu_features->llvm_cpu_name; -} -const char *stage2_cpu_features_get_llvm_features(const Stage2CpuFeatures *cpu_features) { - return cpu_features->llvm_cpu_features; -} -void stage2_cpu_features_get_builtin_str(const Stage2CpuFeatures *cpu_features, - const char **ptr, size_t *len) -{ - *ptr = cpu_features->builtin_str; - *len = strlen(cpu_features->builtin_str); -} - -int stage2_cmd_targets(const char *zig_triple) { - const char *msg = "stage0 called stage2_cmd_targets"; - stage2_panic(msg, strlen(msg)); -} - -enum Error stage2_libc_parse(struct Stage2LibCInstallation *libc, const char *libc_file) { - libc->include_dir = "/dummy/include"; - libc->include_dir_len = strlen(libc->include_dir); - libc->sys_include_dir = "/dummy/sys/include"; - libc->sys_include_dir_len = strlen(libc->sys_include_dir); - libc->crt_dir = ""; - libc->crt_dir_len = strlen(libc->crt_dir); - libc->static_crt_dir = ""; - libc->static_crt_dir_len = strlen(libc->static_crt_dir); - libc->msvc_lib_dir = ""; - libc->msvc_lib_dir_len = strlen(libc->msvc_lib_dir); - libc->kernel32_lib_dir = ""; - libc->kernel32_lib_dir_len = strlen(libc->kernel32_lib_dir); - return ErrorNone; -} - -enum Error stage2_libc_render(struct Stage2LibCInstallation *self, FILE *file) { - const char *msg = "stage0 called stage2_libc_render"; - stage2_panic(msg, strlen(msg)); -} - -enum Error stage2_libc_find_native(struct Stage2LibCInstallation *libc) { - const char *msg = "stage0 called stage2_libc_find_native"; - stage2_panic(msg, strlen(msg)); -} - -enum Error stage2_libc_cc_print_file_name(char **out_ptr, size_t *out_len, - const char *o_file, bool want_dirname) -{ - const char *msg = "stage0 called stage2_libc_cc_print_file_name"; - stage2_panic(msg, strlen(msg)); -} diff --git a/src/userland.h b/src/userland.h deleted file mode 100644 index 7903dc8fe4d45bb8559b75fe51016fd4b2336211..0000000000000000000000000000000000000000 --- a/src/userland.h +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (c) 2019 Andrew Kelley - * - * This file is part of zig, which is MIT licensed. - * See http://opensource.org/licenses/MIT - */ - -#ifndef ZIG_USERLAND_H -#define ZIG_USERLAND_H - -#include -#include -#include - -#ifdef __cplusplus -#define ZIG_EXTERN_C extern "C" -#else -#define ZIG_EXTERN_C -#endif - -#if defined(_MSC_VER) -#define ZIG_ATTRIBUTE_NORETURN __declspec(noreturn) -#else -#define ZIG_ATTRIBUTE_NORETURN __attribute__((noreturn)) -#endif - -// ABI warning: the types and declarations in this file must match both those in -// userland.cpp and src-self-hosted/stage1.zig. - -// ABI warning -enum Error { - ErrorNone, - ErrorNoMem, - ErrorInvalidFormat, - ErrorSemanticAnalyzeFail, - ErrorAccess, - ErrorInterrupted, - ErrorSystemResources, - ErrorFileNotFound, - ErrorFileSystem, - ErrorFileTooBig, - ErrorDivByZero, - ErrorOverflow, - ErrorPathAlreadyExists, - ErrorUnexpected, - ErrorExactDivRemainder, - ErrorNegativeDenominator, - ErrorShiftedOutOneBits, - ErrorCCompileErrors, - ErrorEndOfFile, - ErrorIsDir, - ErrorNotDir, - ErrorUnsupportedOperatingSystem, - ErrorSharingViolation, - ErrorPipeBusy, - ErrorPrimitiveTypeNotFound, - ErrorCacheUnavailable, - ErrorPathTooLong, - ErrorCCompilerCannotFindFile, - ErrorNoCCompilerInstalled, - ErrorReadingDepFile, - ErrorInvalidDepFile, - ErrorMissingArchitecture, - ErrorMissingOperatingSystem, - ErrorUnknownArchitecture, - ErrorUnknownOperatingSystem, - ErrorUnknownABI, - ErrorInvalidFilename, - ErrorDiskQuota, - ErrorDiskSpace, - ErrorUnexpectedWriteFailure, - ErrorUnexpectedSeekFailure, - ErrorUnexpectedFileTruncationFailure, - ErrorUnimplemented, - ErrorOperationAborted, - ErrorBrokenPipe, - ErrorNoSpaceLeft, - ErrorNotLazy, - ErrorIsAsync, - ErrorImportOutsidePkgPath, - ErrorUnknownCpu, - ErrorUnknownSubArchitecture, - ErrorUnknownCpuFeature, - ErrorInvalidCpuFeatures, - ErrorInvalidLlvmCpuFeaturesFormat, - ErrorUnknownApplicationBinaryInterface, - ErrorASTUnitFailure, - ErrorBadPathName, - ErrorSymLinkLoop, - ErrorProcessFdQuotaExceeded, - ErrorSystemFdQuotaExceeded, - ErrorNoDevice, - ErrorDeviceBusy, - ErrorUnableToSpawnCCompiler, - ErrorCCompilerExitCode, - ErrorCCompilerCrashed, - ErrorCCompilerCannotFindHeaders, - ErrorLibCRuntimeNotFound, - ErrorLibCStdLibHeaderNotFound, - ErrorLibCKernel32LibNotFound, - ErrorUnsupportedArchitecture, -}; - -// ABI warning -struct Stage2ErrorMsg { - const char *filename_ptr; // can be null - size_t filename_len; - const char *msg_ptr; - size_t msg_len; - const char *source; // valid until the ASTUnit is freed. can be null - unsigned line; // 0 based - unsigned column; // 0 based - unsigned offset; // byte offset into source -}; - -// ABI warning -struct Stage2Ast; - -// ABI warning -ZIG_EXTERN_C enum Error stage2_translate_c(struct Stage2Ast **out_ast, - struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len, - const char **args_begin, const char **args_end, const char *resources_path); - -// ABI warning -ZIG_EXTERN_C void stage2_free_clang_errors(struct Stage2ErrorMsg *ptr, size_t len); - -// ABI warning -ZIG_EXTERN_C void stage2_render_ast(struct Stage2Ast *ast, FILE *output_file); - -// ABI warning -ZIG_EXTERN_C void stage2_zen(const char **ptr, size_t *len); - -// ABI warning -ZIG_EXTERN_C void stage2_attach_segfault_handler(void); - -// ABI warning -ZIG_EXTERN_C ZIG_ATTRIBUTE_NORETURN void stage2_panic(const char *ptr, size_t len); - -// ABI warning -ZIG_EXTERN_C int stage2_fmt(int argc, char **argv); - -// ABI warning -struct stage2_DepTokenizer { - void *handle; -}; - -// ABI warning -struct stage2_DepNextResult { - enum TypeId { - error, - null, - target, - prereq, - }; - - TypeId type_id; - - // when ent == error --> error text - // when ent == null --> undefined - // when ent == target --> target pathname - // when ent == prereq --> prereq pathname - const char *textz; -}; - -// ABI warning -ZIG_EXTERN_C stage2_DepTokenizer stage2_DepTokenizer_init(const char *input, size_t len); - -// ABI warning -ZIG_EXTERN_C void stage2_DepTokenizer_deinit(stage2_DepTokenizer *self); - -// ABI warning -ZIG_EXTERN_C stage2_DepNextResult stage2_DepTokenizer_next(stage2_DepTokenizer *self); - -// ABI warning -struct Stage2Progress; -// ABI warning -struct Stage2ProgressNode; -// ABI warning -ZIG_EXTERN_C Stage2Progress *stage2_progress_create(void); -// ABI warning -ZIG_EXTERN_C void stage2_progress_disable_tty(Stage2Progress *progress); -// ABI warning -ZIG_EXTERN_C void stage2_progress_destroy(Stage2Progress *progress); -// ABI warning -ZIG_EXTERN_C Stage2ProgressNode *stage2_progress_start_root(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, - const char *name_ptr, size_t name_len, size_t estimated_total_items); -// ABI warning -ZIG_EXTERN_C void stage2_progress_end(Stage2ProgressNode *node); -// ABI warning -ZIG_EXTERN_C void stage2_progress_complete_one(Stage2ProgressNode *node); -// ABI warning -ZIG_EXTERN_C void stage2_progress_update_node(Stage2ProgressNode *node, - size_t completed_count, size_t estimated_total_items); - -// ABI warning -struct Stage2CpuFeatures; - -// ABI warning -ZIG_EXTERN_C enum Error stage2_cpu_features_parse(struct Stage2CpuFeatures **result, - const char *zig_triple, const char *cpu_name, const char *cpu_features); - -// ABI warning -ZIG_EXTERN_C const char *stage2_cpu_features_get_llvm_cpu(const struct Stage2CpuFeatures *cpu_features); - -// ABI warning -ZIG_EXTERN_C const char *stage2_cpu_features_get_llvm_features(const struct Stage2CpuFeatures *cpu_features); - -// ABI warning -ZIG_EXTERN_C void stage2_cpu_features_get_builtin_str(const struct Stage2CpuFeatures *cpu_features, - const char **ptr, size_t *len); - -// ABI warning -ZIG_EXTERN_C void stage2_cpu_features_get_cache_hash(const struct Stage2CpuFeatures *cpu_features, - const char **ptr, size_t *len); - -// ABI warning -ZIG_EXTERN_C int stage2_cmd_targets(const char *zig_triple); - -// ABI warning -struct Stage2LibCInstallation { - const char *include_dir; - size_t include_dir_len; - const char *sys_include_dir; - size_t sys_include_dir_len; - const char *crt_dir; - size_t crt_dir_len; - const char *static_crt_dir; - size_t static_crt_dir_len; - const char *msvc_lib_dir; - size_t msvc_lib_dir_len; - const char *kernel32_lib_dir; - size_t kernel32_lib_dir_len; -}; - -// ABI warning -ZIG_EXTERN_C enum Error stage2_libc_parse(struct Stage2LibCInstallation *libc, const char *libc_file); -// ABI warning -ZIG_EXTERN_C enum Error stage2_libc_render(struct Stage2LibCInstallation *self, FILE *file); -// ABI warning -ZIG_EXTERN_C enum Error stage2_libc_find_native(struct Stage2LibCInstallation *libc); -// ABI warning -ZIG_EXTERN_C enum Error stage2_libc_cc_print_file_name(char **out_ptr, size_t *out_len, - const char *o_file, bool want_dirname); - -#endif diff --git a/src/util.cpp b/src/util.cpp index 56f1de9839db8246b9f1e8fc2ea806c306bcc9cd..2de09df8087be2d8a012328117e1898560f0dc0f 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -6,7 +6,7 @@ */ #include "util.hpp" -#include "userland.h" +#include "stage2.h" #include #include diff --git a/src/zig_clang.h b/src/zig_clang.h index f7de9c2cee37173d121903cc5d1343afd3b97b26..2d9485ae9b8230df2a1fcf5c9be29c2d3002c75a 100644 --- a/src/zig_clang.h +++ b/src/zig_clang.h @@ -8,7 +8,7 @@ #ifndef ZIG_ZIG_CLANG_H #define ZIG_ZIG_CLANG_H -#include "userland.h" +#include "stage2.h" #include #include