| author | |
| committer | |
| log | 20f3b0efff76cb3c611b72c1c1862490aef79b80 |
| tree | a7480ae1b27776576f12392a798c18c2fb293be5 |
| parent | c25742010d69e0e56f1fda99f1b986be52165e3b |
15 files changed, 1486 insertions(+), 1486 deletions(-)
CMakeLists.txt+17-17| ... | @@ -434,8 +434,8 @@ find_package(Threads) | ... | @@ -434,8 +434,8 @@ find_package(Threads) |
| 434 | # CMake doesn't let us create an empty executable, so we hang on to this one separately. | 434 | # CMake doesn't let us create an empty executable, so we hang on to this one separately. |
| 435 | set(ZIG_MAIN_SRC "${CMAKE_SOURCE_DIR}/src/main.cpp") | 435 | set(ZIG_MAIN_SRC "${CMAKE_SOURCE_DIR}/src/main.cpp") |
| 436 | 436 | ||
| 437 | # This is our shim which will be replaced by libuserland written in Zig. | 437 | # This is our shim which will be replaced by libstage2 written in Zig. |
| 438 | set(ZIG0_SHIM_SRC "${CMAKE_SOURCE_DIR}/src/userland.cpp") | 438 | set(ZIG0_SHIM_SRC "${CMAKE_SOURCE_DIR}/src/stage2.cpp") |
| 439 | 439 | ||
| 440 | if(ZIG_ENABLE_MEM_PROFILE) | 440 | if(ZIG_ENABLE_MEM_PROFILE) |
| 441 | set(ZIG_SOURCES_MEM_PROFILE "${CMAKE_SOURCE_DIR}/src/mem_profile.cpp") | 441 | set(ZIG_SOURCES_MEM_PROFILE "${CMAKE_SOURCE_DIR}/src/mem_profile.cpp") |
| ... | @@ -599,38 +599,38 @@ set_target_properties(zig0 PROPERTIES | ... | @@ -599,38 +599,38 @@ set_target_properties(zig0 PROPERTIES |
| 599 | target_link_libraries(zig0 compiler) | 599 | target_link_libraries(zig0 compiler) |
| 600 | 600 | ||
| 601 | if(MSVC) | 601 | if(MSVC) |
| 602 | set(LIBUSERLAND "${CMAKE_BINARY_DIR}/userland.lib") | 602 | set(LIBSTAGE2 "${CMAKE_BINARY_DIR}/stage2.lib") |
| 603 | else() | 603 | else() |
| 604 | set(LIBUSERLAND "${CMAKE_BINARY_DIR}/libuserland.a") | 604 | set(LIBSTAGE2 "${CMAKE_BINARY_DIR}/libstage2.a") |
| 605 | endif() | 605 | endif() |
| 606 | if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") | 606 | if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") |
| 607 | set(LIBUSERLAND_RELEASE_ARG "") | 607 | set(LIBSTAGE2_RELEASE_ARG "") |
| 608 | else() | 608 | else() |
| 609 | set(LIBUSERLAND_RELEASE_ARG --release-fast --strip) | 609 | set(LIBSTAGE2_RELEASE_ARG --release-fast --strip) |
| 610 | endif() | 610 | endif() |
| 611 | if(WIN32) | 611 | if(WIN32) |
| 612 | set(LIBUSERLAND_WINDOWS_ARGS "-lntdll") | 612 | set(LIBSTAGE2_WINDOWS_ARGS "-lntdll") |
| 613 | else() | 613 | else() |
| 614 | set(LIBUSERLAND_WINDOWS_ARGS "") | 614 | set(LIBSTAGE2_WINDOWS_ARGS "") |
| 615 | endif() | 615 | endif() |
| 616 | 616 | ||
| 617 | set(BUILD_LIBUSERLAND_ARGS "build-lib" | 617 | set(BUILD_LIBSTAGE2_ARGS "build-lib" |
| 618 | --override-lib-dir "${CMAKE_SOURCE_DIR}/lib" | 618 | --override-lib-dir "${CMAKE_SOURCE_DIR}/lib" |
| 619 | --cache on | 619 | --cache on |
| 620 | --output-dir "${CMAKE_BINARY_DIR}" | 620 | --output-dir "${CMAKE_BINARY_DIR}" |
| 621 | ${LIBUSERLAND_RELEASE_ARG} | 621 | ${LIBSTAGE2_RELEASE_ARG} |
| 622 | "src-self-hosted/stage1.zig" | 622 | "src-self-hosted/stage2.zig" |
| 623 | --disable-gen-h | 623 | --disable-gen-h |
| 624 | --bundle-compiler-rt | 624 | --bundle-compiler-rt |
| 625 | -fPIC | 625 | -fPIC |
| 626 | -lc | 626 | -lc |
| 627 | ${LIBUSERLAND_WINDOWS_ARGS} | 627 | ${LIBSTAGE2_WINDOWS_ARGS} |
| 628 | ) | 628 | ) |
| 629 | 629 | ||
| 630 | add_custom_target(zig_build_libuserland ALL | 630 | add_custom_target(zig_build_libstage2 ALL |
| 631 | COMMAND zig0 ${BUILD_LIBUSERLAND_ARGS} | 631 | COMMAND zig0 ${BUILD_LIBSTAGE2_ARGS} |
| 632 | DEPENDS zig0 | 632 | DEPENDS zig0 |
| 633 | BYPRODUCTS "${LIBUSERLAND}" | 633 | BYPRODUCTS "${LIBSTAGE2}" |
| 634 | WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" | 634 | WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" |
| 635 | ) | 635 | ) |
| 636 | add_executable(zig "${ZIG_MAIN_SRC}") | 636 | add_executable(zig "${ZIG_MAIN_SRC}") |
| ... | @@ -639,13 +639,13 @@ set_target_properties(zig PROPERTIES | ... | @@ -639,13 +639,13 @@ set_target_properties(zig PROPERTIES |
| 639 | COMPILE_FLAGS ${EXE_CFLAGS} | 639 | COMPILE_FLAGS ${EXE_CFLAGS} |
| 640 | LINK_FLAGS ${EXE_LDFLAGS} | 640 | LINK_FLAGS ${EXE_LDFLAGS} |
| 641 | ) | 641 | ) |
| 642 | target_link_libraries(zig compiler "${LIBUSERLAND}") | 642 | target_link_libraries(zig compiler "${LIBSTAGE2}") |
| 643 | if(MSVC) | 643 | if(MSVC) |
| 644 | target_link_libraries(zig ntdll.lib) | 644 | target_link_libraries(zig ntdll.lib) |
| 645 | elseif(MINGW) | 645 | elseif(MINGW) |
| 646 | target_link_libraries(zig ntdll) | 646 | target_link_libraries(zig ntdll) |
| 647 | endif() | 647 | endif() |
| 648 | add_dependencies(zig zig_build_libuserland) | 648 | add_dependencies(zig zig_build_libstage2) |
| 649 | 649 | ||
| 650 | install(TARGETS zig DESTINATION bin) | 650 | install(TARGETS zig DESTINATION bin) |
| 651 | 651 |
cmake/install.cmake+2-2| ... | @@ -19,9 +19,9 @@ if(_result) | ... | @@ -19,9 +19,9 @@ if(_result) |
| 19 | message(":: ERROR: ${_result}") | 19 | message(":: ERROR: ${_result}") |
| 20 | message(":: (execute_process)") | 20 | message(":: (execute_process)") |
| 21 | 21 | ||
| 22 | string(REPLACE ";" " " s_INSTALL_LIBUSERLAND_ARGS "${ZIG_INSTALL_ARGS}") | 22 | string(REPLACE ";" " " s_INSTALL_LIBSTAGE2_ARGS "${ZIG_INSTALL_ARGS}") |
| 23 | message("::") | 23 | message("::") |
| 24 | message(":: argv: ${zig_EXE} ${s_INSTALL_LIBUSERLAND_ARGS}") | 24 | message(":: argv: ${zig_EXE} ${s_INSTALL_LIBSTAGE2_ARGS}") |
| 25 | 25 | ||
| 26 | set(_args ${zig_EXE} ${ZIG_INSTALL_ARGS}) | 26 | set(_args ${zig_EXE} ${ZIG_INSTALL_ARGS}) |
| 27 | list(LENGTH _args _len) | 27 | list(LENGTH _args _len) |
src-self-hosted/stage1.zig deleted-1033| ... | @@ -1,1033 +0,0 @@ | ||
| 1 | // This is Zig code that is used by both stage1 and stage2. | ||
| 2 | // The prototypes in src/userland.h must match these definitions. | ||
| 3 | |||
| 4 | const std = @import("std"); | ||
| 5 | const io = std.io; | ||
| 6 | const mem = std.mem; | ||
| 7 | const fs = std.fs; | ||
| 8 | const process = std.process; | ||
| 9 | const Allocator = mem.Allocator; | ||
| 10 | const ArrayList = std.ArrayList; | ||
| 11 | const Buffer = std.Buffer; | ||
| 12 | const Target = std.Target; | ||
| 13 | const self_hosted_main = @import("main.zig"); | ||
| 14 | const errmsg = @import("errmsg.zig"); | ||
| 15 | const DepTokenizer = @import("dep_tokenizer.zig").Tokenizer; | ||
| 16 | const assert = std.debug.assert; | ||
| 17 | const LibCInstallation = @import("libc_installation.zig").LibCInstallation; | ||
| 18 | |||
| 19 | var stderr_file: fs.File = undefined; | ||
| 20 | var stderr: *io.OutStream(fs.File.WriteError) = undefined; | ||
| 21 | var stdout: *io.OutStream(fs.File.WriteError) = undefined; | ||
| 22 | |||
| 23 | comptime { | ||
| 24 | _ = @import("dep_tokenizer.zig"); | ||
| 25 | } | ||
| 26 | |||
| 27 | // ABI warning | ||
| 28 | export fn stage2_zen(ptr: *[*]const u8, len: *usize) void { | ||
| 29 | const info_zen = @import("main.zig").info_zen; | ||
| 30 | ptr.* = info_zen; | ||
| 31 | len.* = info_zen.len; | ||
| 32 | } | ||
| 33 | |||
| 34 | // ABI warning | ||
| 35 | export fn stage2_panic(ptr: [*]const u8, len: usize) void { | ||
| 36 | @panic(ptr[0..len]); | ||
| 37 | } | ||
| 38 | |||
| 39 | // ABI warning | ||
| 40 | const Error = extern enum { | ||
| 41 | None, | ||
| 42 | OutOfMemory, | ||
| 43 | InvalidFormat, | ||
| 44 | SemanticAnalyzeFail, | ||
| 45 | AccessDenied, | ||
| 46 | Interrupted, | ||
| 47 | SystemResources, | ||
| 48 | FileNotFound, | ||
| 49 | FileSystem, | ||
| 50 | FileTooBig, | ||
| 51 | DivByZero, | ||
| 52 | Overflow, | ||
| 53 | PathAlreadyExists, | ||
| 54 | Unexpected, | ||
| 55 | ExactDivRemainder, | ||
| 56 | NegativeDenominator, | ||
| 57 | ShiftedOutOneBits, | ||
| 58 | CCompileErrors, | ||
| 59 | EndOfFile, | ||
| 60 | IsDir, | ||
| 61 | NotDir, | ||
| 62 | UnsupportedOperatingSystem, | ||
| 63 | SharingViolation, | ||
| 64 | PipeBusy, | ||
| 65 | PrimitiveTypeNotFound, | ||
| 66 | CacheUnavailable, | ||
| 67 | PathTooLong, | ||
| 68 | CCompilerCannotFindFile, | ||
| 69 | NoCCompilerInstalled, | ||
| 70 | ReadingDepFile, | ||
| 71 | InvalidDepFile, | ||
| 72 | MissingArchitecture, | ||
| 73 | MissingOperatingSystem, | ||
| 74 | UnknownArchitecture, | ||
| 75 | UnknownOperatingSystem, | ||
| 76 | UnknownABI, | ||
| 77 | InvalidFilename, | ||
| 78 | DiskQuota, | ||
| 79 | DiskSpace, | ||
| 80 | UnexpectedWriteFailure, | ||
| 81 | UnexpectedSeekFailure, | ||
| 82 | UnexpectedFileTruncationFailure, | ||
| 83 | Unimplemented, | ||
| 84 | OperationAborted, | ||
| 85 | BrokenPipe, | ||
| 86 | NoSpaceLeft, | ||
| 87 | NotLazy, | ||
| 88 | IsAsync, | ||
| 89 | ImportOutsidePkgPath, | ||
| 90 | UnknownCpu, | ||
| 91 | UnknownSubArchitecture, | ||
| 92 | UnknownCpuFeature, | ||
| 93 | InvalidCpuFeatures, | ||
| 94 | InvalidLlvmCpuFeaturesFormat, | ||
| 95 | UnknownApplicationBinaryInterface, | ||
| 96 | ASTUnitFailure, | ||
| 97 | BadPathName, | ||
| 98 | SymLinkLoop, | ||
| 99 | ProcessFdQuotaExceeded, | ||
| 100 | SystemFdQuotaExceeded, | ||
| 101 | NoDevice, | ||
| 102 | DeviceBusy, | ||
| 103 | UnableToSpawnCCompiler, | ||
| 104 | CCompilerExitCode, | ||
| 105 | CCompilerCrashed, | ||
| 106 | CCompilerCannotFindHeaders, | ||
| 107 | LibCRuntimeNotFound, | ||
| 108 | LibCStdLibHeaderNotFound, | ||
| 109 | LibCKernel32LibNotFound, | ||
| 110 | UnsupportedArchitecture, | ||
| 111 | }; | ||
| 112 | |||
| 113 | const FILE = std.c.FILE; | ||
| 114 | const ast = std.zig.ast; | ||
| 115 | const translate_c = @import("translate_c.zig"); | ||
| 116 | |||
| 117 | /// Args should have a null terminating last arg. | ||
| 118 | export fn stage2_translate_c( | ||
| 119 | out_ast: **ast.Tree, | ||
| 120 | out_errors_ptr: *[*]translate_c.ClangErrMsg, | ||
| 121 | out_errors_len: *usize, | ||
| 122 | args_begin: [*]?[*]const u8, | ||
| 123 | args_end: [*]?[*]const u8, | ||
| 124 | resources_path: [*:0]const u8, | ||
| 125 | ) Error { | ||
| 126 | var errors = @as([*]translate_c.ClangErrMsg, undefined)[0..0]; | ||
| 127 | out_ast.* = translate_c.translate(std.heap.c_allocator, args_begin, args_end, &errors, resources_path) catch |err| switch (err) { | ||
| 128 | error.SemanticAnalyzeFail => { | ||
| 129 | out_errors_ptr.* = errors.ptr; | ||
| 130 | out_errors_len.* = errors.len; | ||
| 131 | return .CCompileErrors; | ||
| 132 | }, | ||
| 133 | error.ASTUnitFailure => return .ASTUnitFailure, | ||
| 134 | error.OutOfMemory => return .OutOfMemory, | ||
| 135 | }; | ||
| 136 | return .None; | ||
| 137 | } | ||
| 138 | |||
| 139 | export fn stage2_free_clang_errors(errors_ptr: [*]translate_c.ClangErrMsg, errors_len: usize) void { | ||
| 140 | translate_c.freeErrors(errors_ptr[0..errors_len]); | ||
| 141 | } | ||
| 142 | |||
| 143 | export fn stage2_render_ast(tree: *ast.Tree, output_file: *FILE) Error { | ||
| 144 | const c_out_stream = &std.io.COutStream.init(output_file).stream; | ||
| 145 | _ = std.zig.render(std.heap.c_allocator, c_out_stream, tree) catch |e| switch (e) { | ||
| 146 | error.WouldBlock => unreachable, // stage1 opens stuff in exclusively blocking mode | ||
| 147 | error.SystemResources => return .SystemResources, | ||
| 148 | error.OperationAborted => return .OperationAborted, | ||
| 149 | error.BrokenPipe => return .BrokenPipe, | ||
| 150 | error.DiskQuota => return .DiskQuota, | ||
| 151 | error.FileTooBig => return .FileTooBig, | ||
| 152 | error.NoSpaceLeft => return .NoSpaceLeft, | ||
| 153 | error.AccessDenied => return .AccessDenied, | ||
| 154 | error.OutOfMemory => return .OutOfMemory, | ||
| 155 | error.Unexpected => return .Unexpected, | ||
| 156 | error.InputOutput => return .FileSystem, | ||
| 157 | }; | ||
| 158 | return .None; | ||
| 159 | } | ||
| 160 | |||
| 161 | // TODO: just use the actual self-hosted zig fmt. Until https://github.com/ziglang/zig/issues/2377, | ||
| 162 | // we use a blocking implementation. | ||
| 163 | export fn stage2_fmt(argc: c_int, argv: [*]const [*:0]const u8) c_int { | ||
| 164 | if (std.debug.runtime_safety) { | ||
| 165 | fmtMain(argc, argv) catch unreachable; | ||
| 166 | } else { | ||
| 167 | fmtMain(argc, argv) catch |e| { | ||
| 168 | std.debug.warn("{}\n", .{@errorName(e)}); | ||
| 169 | return -1; | ||
| 170 | }; | ||
| 171 | } | ||
| 172 | return 0; | ||
| 173 | } | ||
| 174 | |||
| 175 | fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void { | ||
| 176 | const allocator = std.heap.c_allocator; | ||
| 177 | var args_list = std.ArrayList([]const u8).init(allocator); | ||
| 178 | const argc_usize = @intCast(usize, argc); | ||
| 179 | var arg_i: usize = 0; | ||
| 180 | while (arg_i < argc_usize) : (arg_i += 1) { | ||
| 181 | try args_list.append(mem.toSliceConst(u8, argv[arg_i])); | ||
| 182 | } | ||
| 183 | |||
| 184 | stdout = &std.io.getStdOut().outStream().stream; | ||
| 185 | stderr_file = std.io.getStdErr(); | ||
| 186 | stderr = &stderr_file.outStream().stream; | ||
| 187 | |||
| 188 | const args = args_list.toSliceConst()[2..]; | ||
| 189 | |||
| 190 | var color: errmsg.Color = .Auto; | ||
| 191 | var stdin_flag: bool = false; | ||
| 192 | var check_flag: bool = false; | ||
| 193 | var input_files = ArrayList([]const u8).init(allocator); | ||
| 194 | |||
| 195 | { | ||
| 196 | var i: usize = 0; | ||
| 197 | while (i < args.len) : (i += 1) { | ||
| 198 | const arg = args[i]; | ||
| 199 | if (mem.startsWith(u8, arg, "-")) { | ||
| 200 | if (mem.eql(u8, arg, "--help")) { | ||
| 201 | try stdout.write(self_hosted_main.usage_fmt); | ||
| 202 | process.exit(0); | ||
| 203 | } else if (mem.eql(u8, arg, "--color")) { | ||
| 204 | if (i + 1 >= args.len) { | ||
| 205 | try stderr.write("expected [auto|on|off] after --color\n"); | ||
| 206 | process.exit(1); | ||
| 207 | } | ||
| 208 | i += 1; | ||
| 209 | const next_arg = args[i]; | ||
| 210 | if (mem.eql(u8, next_arg, "auto")) { | ||
| 211 | color = .Auto; | ||
| 212 | } else if (mem.eql(u8, next_arg, "on")) { | ||
| 213 | color = .On; | ||
| 214 | } else if (mem.eql(u8, next_arg, "off")) { | ||
| 215 | color = .Off; | ||
| 216 | } else { | ||
| 217 | try stderr.print("expected [auto|on|off] after --color, found '{}'\n", .{next_arg}); | ||
| 218 | process.exit(1); | ||
| 219 | } | ||
| 220 | } else if (mem.eql(u8, arg, "--stdin")) { | ||
| 221 | stdin_flag = true; | ||
| 222 | } else if (mem.eql(u8, arg, "--check")) { | ||
| 223 | check_flag = true; | ||
| 224 | } else { | ||
| 225 | try stderr.print("unrecognized parameter: '{}'", .{arg}); | ||
| 226 | process.exit(1); | ||
| 227 | } | ||
| 228 | } else { | ||
| 229 | try input_files.append(arg); | ||
| 230 | } | ||
| 231 | } | ||
| 232 | } | ||
| 233 | |||
| 234 | if (stdin_flag) { | ||
| 235 | if (input_files.len != 0) { | ||
| 236 | try stderr.write("cannot use --stdin with positional arguments\n"); | ||
| 237 | process.exit(1); | ||
| 238 | } | ||
| 239 | |||
| 240 | const stdin_file = io.getStdIn(); | ||
| 241 | var stdin = stdin_file.inStream(); | ||
| 242 | |||
| 243 | const source_code = try stdin.stream.readAllAlloc(allocator, self_hosted_main.max_src_size); | ||
| 244 | defer allocator.free(source_code); | ||
| 245 | |||
| 246 | const tree = std.zig.parse(allocator, source_code) catch |err| { | ||
| 247 | try stderr.print("error parsing stdin: {}\n", .{err}); | ||
| 248 | process.exit(1); | ||
| 249 | }; | ||
| 250 | defer tree.deinit(); | ||
| 251 | |||
| 252 | var error_it = tree.errors.iterator(0); | ||
| 253 | while (error_it.next()) |parse_error| { | ||
| 254 | try printErrMsgToFile(allocator, parse_error, tree, "<stdin>", stderr_file, color); | ||
| 255 | } | ||
| 256 | if (tree.errors.len != 0) { | ||
| 257 | process.exit(1); | ||
| 258 | } | ||
| 259 | if (check_flag) { | ||
| 260 | const anything_changed = try std.zig.render(allocator, io.null_out_stream, tree); | ||
| 261 | const code = if (anything_changed) @as(u8, 1) else @as(u8, 0); | ||
| 262 | process.exit(code); | ||
| 263 | } | ||
| 264 | |||
| 265 | _ = try std.zig.render(allocator, stdout, tree); | ||
| 266 | return; | ||
| 267 | } | ||
| 268 | |||
| 269 | if (input_files.len == 0) { | ||
| 270 | try stderr.write("expected at least one source file argument\n"); | ||
| 271 | process.exit(1); | ||
| 272 | } | ||
| 273 | |||
| 274 | var fmt = Fmt{ | ||
| 275 | .seen = Fmt.SeenMap.init(allocator), | ||
| 276 | .any_error = false, | ||
| 277 | .color = color, | ||
| 278 | .allocator = allocator, | ||
| 279 | }; | ||
| 280 | |||
| 281 | for (input_files.toSliceConst()) |file_path| { | ||
| 282 | try fmtPath(&fmt, file_path, check_flag); | ||
| 283 | } | ||
| 284 | if (fmt.any_error) { | ||
| 285 | process.exit(1); | ||
| 286 | } | ||
| 287 | } | ||
| 288 | |||
| 289 | const FmtError = error{ | ||
| 290 | SystemResources, | ||
| 291 | OperationAborted, | ||
| 292 | IoPending, | ||
| 293 | BrokenPipe, | ||
| 294 | Unexpected, | ||
| 295 | WouldBlock, | ||
| 296 | FileClosed, | ||
| 297 | DestinationAddressRequired, | ||
| 298 | DiskQuota, | ||
| 299 | FileTooBig, | ||
| 300 | InputOutput, | ||
| 301 | NoSpaceLeft, | ||
| 302 | AccessDenied, | ||
| 303 | OutOfMemory, | ||
| 304 | RenameAcrossMountPoints, | ||
| 305 | ReadOnlyFileSystem, | ||
| 306 | LinkQuotaExceeded, | ||
| 307 | FileBusy, | ||
| 308 | } || fs.File.OpenError; | ||
| 309 | |||
| 310 | fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool) FmtError!void { | ||
| 311 | if (fmt.seen.exists(file_path)) return; | ||
| 312 | try fmt.seen.put(file_path); | ||
| 313 | |||
| 314 | const source_code = io.readFileAlloc(fmt.allocator, file_path) catch |err| switch (err) { | ||
| 315 | error.IsDir, error.AccessDenied => { | ||
| 316 | // TODO make event based (and dir.next()) | ||
| 317 | var dir = try fs.cwd().openDirList(file_path); | ||
| 318 | defer dir.close(); | ||
| 319 | |||
| 320 | var dir_it = dir.iterate(); | ||
| 321 | |||
| 322 | while (try dir_it.next()) |entry| { | ||
| 323 | if (entry.kind == .Directory or mem.endsWith(u8, entry.name, ".zig")) { | ||
| 324 | const full_path = try fs.path.join(fmt.allocator, &[_][]const u8{ file_path, entry.name }); | ||
| 325 | try fmtPath(fmt, full_path, check_mode); | ||
| 326 | } | ||
| 327 | } | ||
| 328 | return; | ||
| 329 | }, | ||
| 330 | else => { | ||
| 331 | // TODO lock stderr printing | ||
| 332 | try stderr.print("unable to open '{}': {}\n", .{ file_path, err }); | ||
| 333 | fmt.any_error = true; | ||
| 334 | return; | ||
| 335 | }, | ||
| 336 | }; | ||
| 337 | defer fmt.allocator.free(source_code); | ||
| 338 | |||
| 339 | const tree = std.zig.parse(fmt.allocator, source_code) catch |err| { | ||
| 340 | try stderr.print("error parsing file '{}': {}\n", .{ file_path, err }); | ||
| 341 | fmt.any_error = true; | ||
| 342 | return; | ||
| 343 | }; | ||
| 344 | defer tree.deinit(); | ||
| 345 | |||
| 346 | var error_it = tree.errors.iterator(0); | ||
| 347 | while (error_it.next()) |parse_error| { | ||
| 348 | try printErrMsgToFile(fmt.allocator, parse_error, tree, file_path, stderr_file, fmt.color); | ||
| 349 | } | ||
| 350 | if (tree.errors.len != 0) { | ||
| 351 | fmt.any_error = true; | ||
| 352 | return; | ||
| 353 | } | ||
| 354 | |||
| 355 | if (check_mode) { | ||
| 356 | const anything_changed = try std.zig.render(fmt.allocator, io.null_out_stream, tree); | ||
| 357 | if (anything_changed) { | ||
| 358 | try stderr.print("{}\n", .{file_path}); | ||
| 359 | fmt.any_error = true; | ||
| 360 | } | ||
| 361 | } else { | ||
| 362 | const baf = try io.BufferedAtomicFile.create(fmt.allocator, file_path); | ||
| 363 | defer baf.destroy(); | ||
| 364 | |||
| 365 | const anything_changed = try std.zig.render(fmt.allocator, baf.stream(), tree); | ||
| 366 | if (anything_changed) { | ||
| 367 | try stderr.print("{}\n", .{file_path}); | ||
| 368 | try baf.finish(); | ||
| 369 | } | ||
| 370 | } | ||
| 371 | } | ||
| 372 | |||
| 373 | const Fmt = struct { | ||
| 374 | seen: SeenMap, | ||
| 375 | any_error: bool, | ||
| 376 | color: errmsg.Color, | ||
| 377 | allocator: *mem.Allocator, | ||
| 378 | |||
| 379 | const SeenMap = std.BufSet; | ||
| 380 | }; | ||
| 381 | |||
| 382 | fn printErrMsgToFile( | ||
| 383 | allocator: *mem.Allocator, | ||
| 384 | parse_error: *const ast.Error, | ||
| 385 | tree: *ast.Tree, | ||
| 386 | path: []const u8, | ||
| 387 | file: fs.File, | ||
| 388 | color: errmsg.Color, | ||
| 389 | ) !void { | ||
| 390 | const color_on = switch (color) { | ||
| 391 | .Auto => file.isTty(), | ||
| 392 | .On => true, | ||
| 393 | .Off => false, | ||
| 394 | }; | ||
| 395 | const lok_token = parse_error.loc(); | ||
| 396 | const span = errmsg.Span{ | ||
| 397 | .first = lok_token, | ||
| 398 | .last = lok_token, | ||
| 399 | }; | ||
| 400 | |||
| 401 | const first_token = tree.tokens.at(span.first); | ||
| 402 | const last_token = tree.tokens.at(span.last); | ||
| 403 | const start_loc = tree.tokenLocationPtr(0, first_token); | ||
| 404 | const end_loc = tree.tokenLocationPtr(first_token.end, last_token); | ||
| 405 | |||
| 406 | var text_buf = try std.Buffer.initSize(allocator, 0); | ||
| 407 | var out_stream = &std.io.BufferOutStream.init(&text_buf).stream; | ||
| 408 | try parse_error.render(&tree.tokens, out_stream); | ||
| 409 | const text = text_buf.toOwnedSlice(); | ||
| 410 | |||
| 411 | const stream = &file.outStream().stream; | ||
| 412 | try stream.print("{}:{}:{}: error: {}\n", .{ path, start_loc.line + 1, start_loc.column + 1, text }); | ||
| 413 | |||
| 414 | if (!color_on) return; | ||
| 415 | |||
| 416 | // Print \r and \t as one space each so that column counts line up | ||
| 417 | for (tree.source[start_loc.line_start..start_loc.line_end]) |byte| { | ||
| 418 | try stream.writeByte(switch (byte) { | ||
| 419 | '\r', '\t' => ' ', | ||
| 420 | else => byte, | ||
| 421 | }); | ||
| 422 | } | ||
| 423 | try stream.writeByte('\n'); | ||
| 424 | try stream.writeByteNTimes(' ', start_loc.column); | ||
| 425 | try stream.writeByteNTimes('~', last_token.end - first_token.start); | ||
| 426 | try stream.writeByte('\n'); | ||
| 427 | } | ||
| 428 | |||
| 429 | export fn stage2_DepTokenizer_init(input: [*]const u8, len: usize) stage2_DepTokenizer { | ||
| 430 | const t = std.heap.c_allocator.create(DepTokenizer) catch @panic("failed to create .d tokenizer"); | ||
| 431 | t.* = DepTokenizer.init(std.heap.c_allocator, input[0..len]); | ||
| 432 | return stage2_DepTokenizer{ | ||
| 433 | .handle = t, | ||
| 434 | }; | ||
| 435 | } | ||
| 436 | |||
| 437 | export fn stage2_DepTokenizer_deinit(self: *stage2_DepTokenizer) void { | ||
| 438 | self.handle.deinit(); | ||
| 439 | } | ||
| 440 | |||
| 441 | export fn stage2_DepTokenizer_next(self: *stage2_DepTokenizer) stage2_DepNextResult { | ||
| 442 | const otoken = self.handle.next() catch { | ||
| 443 | const textz = std.Buffer.init(&self.handle.arena.allocator, self.handle.error_text) catch @panic("failed to create .d tokenizer error text"); | ||
| 444 | return stage2_DepNextResult{ | ||
| 445 | .type_id = .error_, | ||
| 446 | .textz = textz.toSlice().ptr, | ||
| 447 | }; | ||
| 448 | }; | ||
| 449 | const token = otoken orelse { | ||
| 450 | return stage2_DepNextResult{ | ||
| 451 | .type_id = .null_, | ||
| 452 | .textz = undefined, | ||
| 453 | }; | ||
| 454 | }; | ||
| 455 | const textz = std.Buffer.init(&self.handle.arena.allocator, token.bytes) catch @panic("failed to create .d tokenizer token text"); | ||
| 456 | return stage2_DepNextResult{ | ||
| 457 | .type_id = switch (token.id) { | ||
| 458 | .target => .target, | ||
| 459 | .prereq => .prereq, | ||
| 460 | }, | ||
| 461 | .textz = textz.toSlice().ptr, | ||
| 462 | }; | ||
| 463 | } | ||
| 464 | |||
| 465 | const stage2_DepTokenizer = extern struct { | ||
| 466 | handle: *DepTokenizer, | ||
| 467 | }; | ||
| 468 | |||
| 469 | const stage2_DepNextResult = extern struct { | ||
| 470 | type_id: TypeId, | ||
| 471 | |||
| 472 | // when type_id == error --> error text | ||
| 473 | // when type_id == null --> undefined | ||
| 474 | // when type_id == target --> target pathname | ||
| 475 | // when type_id == prereq --> prereq pathname | ||
| 476 | textz: [*]const u8, | ||
| 477 | |||
| 478 | const TypeId = extern enum { | ||
| 479 | error_, | ||
| 480 | null_, | ||
| 481 | target, | ||
| 482 | prereq, | ||
| 483 | }; | ||
| 484 | }; | ||
| 485 | |||
| 486 | // ABI warning | ||
| 487 | export fn stage2_attach_segfault_handler() void { | ||
| 488 | if (std.debug.runtime_safety and std.debug.have_segfault_handling_support) { | ||
| 489 | std.debug.attachSegfaultHandler(); | ||
| 490 | } | ||
| 491 | } | ||
| 492 | |||
| 493 | // ABI warning | ||
| 494 | export fn stage2_progress_create() *std.Progress { | ||
| 495 | const ptr = std.heap.c_allocator.create(std.Progress) catch @panic("out of memory"); | ||
| 496 | ptr.* = std.Progress{}; | ||
| 497 | return ptr; | ||
| 498 | } | ||
| 499 | |||
| 500 | // ABI warning | ||
| 501 | export fn stage2_progress_destroy(progress: *std.Progress) void { | ||
| 502 | std.heap.c_allocator.destroy(progress); | ||
| 503 | } | ||
| 504 | |||
| 505 | // ABI warning | ||
| 506 | export fn stage2_progress_start_root( | ||
| 507 | progress: *std.Progress, | ||
| 508 | name_ptr: [*]const u8, | ||
| 509 | name_len: usize, | ||
| 510 | estimated_total_items: usize, | ||
| 511 | ) *std.Progress.Node { | ||
| 512 | return progress.start( | ||
| 513 | name_ptr[0..name_len], | ||
| 514 | if (estimated_total_items == 0) null else estimated_total_items, | ||
| 515 | ) catch @panic("timer unsupported"); | ||
| 516 | } | ||
| 517 | |||
| 518 | // ABI warning | ||
| 519 | export fn stage2_progress_disable_tty(progress: *std.Progress) void { | ||
| 520 | progress.terminal = null; | ||
| 521 | } | ||
| 522 | |||
| 523 | // ABI warning | ||
| 524 | export fn stage2_progress_start( | ||
| 525 | node: *std.Progress.Node, | ||
| 526 | name_ptr: [*]const u8, | ||
| 527 | name_len: usize, | ||
| 528 | estimated_total_items: usize, | ||
| 529 | ) *std.Progress.Node { | ||
| 530 | const child_node = std.heap.c_allocator.create(std.Progress.Node) catch @panic("out of memory"); | ||
| 531 | child_node.* = node.start( | ||
| 532 | name_ptr[0..name_len], | ||
| 533 | if (estimated_total_items == 0) null else estimated_total_items, | ||
| 534 | ); | ||
| 535 | child_node.activate(); | ||
| 536 | return child_node; | ||
| 537 | } | ||
| 538 | |||
| 539 | // ABI warning | ||
| 540 | export fn stage2_progress_end(node: *std.Progress.Node) void { | ||
| 541 | node.end(); | ||
| 542 | if (&node.context.root != node) { | ||
| 543 | std.heap.c_allocator.destroy(node); | ||
| 544 | } | ||
| 545 | } | ||
| 546 | |||
| 547 | // ABI warning | ||
| 548 | export fn stage2_progress_complete_one(node: *std.Progress.Node) void { | ||
| 549 | node.completeOne(); | ||
| 550 | } | ||
| 551 | |||
| 552 | // ABI warning | ||
| 553 | export fn stage2_progress_update_node(node: *std.Progress.Node, done_count: usize, total_count: usize) void { | ||
| 554 | node.completed_items = done_count; | ||
| 555 | node.estimated_total_items = total_count; | ||
| 556 | node.activate(); | ||
| 557 | node.context.maybeRefresh(); | ||
| 558 | } | ||
| 559 | |||
| 560 | fn cpuFeaturesFromLLVM( | ||
| 561 | arch: Target.Arch, | ||
| 562 | llvm_cpu_name_z: ?[*:0]const u8, | ||
| 563 | llvm_cpu_features_opt: ?[*:0]const u8, | ||
| 564 | ) !Target.CpuFeatures { | ||
| 565 | var result = arch.getBaselineCpuFeatures(); | ||
| 566 | |||
| 567 | if (llvm_cpu_name_z) |cpu_name_z| { | ||
| 568 | const llvm_cpu_name = mem.toSliceConst(u8, cpu_name_z); | ||
| 569 | |||
| 570 | for (arch.allCpus()) |cpu| { | ||
| 571 | const this_llvm_name = cpu.llvm_name orelse continue; | ||
| 572 | if (mem.eql(u8, this_llvm_name, llvm_cpu_name)) { | ||
| 573 | // Here we use the non-dependencies-populated set, | ||
| 574 | // so that subtracting features later in this function | ||
| 575 | // affect the prepopulated set. | ||
| 576 | result = Target.CpuFeatures{ | ||
| 577 | .cpu = cpu, | ||
| 578 | .features = cpu.features, | ||
| 579 | }; | ||
| 580 | break; | ||
| 581 | } | ||
| 582 | } | ||
| 583 | } | ||
| 584 | |||
| 585 | const all_features = arch.allFeaturesList(); | ||
| 586 | |||
| 587 | if (llvm_cpu_features_opt) |llvm_cpu_features| { | ||
| 588 | var it = mem.tokenize(mem.toSliceConst(u8, llvm_cpu_features), ","); | ||
| 589 | while (it.next()) |decorated_llvm_feat| { | ||
| 590 | var op: enum { | ||
| 591 | add, | ||
| 592 | sub, | ||
| 593 | } = undefined; | ||
| 594 | var llvm_feat: []const u8 = undefined; | ||
| 595 | if (mem.startsWith(u8, decorated_llvm_feat, "+")) { | ||
| 596 | op = .add; | ||
| 597 | llvm_feat = decorated_llvm_feat[1..]; | ||
| 598 | } else if (mem.startsWith(u8, decorated_llvm_feat, "-")) { | ||
| 599 | op = .sub; | ||
| 600 | llvm_feat = decorated_llvm_feat[1..]; | ||
| 601 | } else { | ||
| 602 | return error.InvalidLlvmCpuFeaturesFormat; | ||
| 603 | } | ||
| 604 | for (all_features) |feature, index_usize| { | ||
| 605 | const this_llvm_name = feature.llvm_name orelse continue; | ||
| 606 | if (mem.eql(u8, llvm_feat, this_llvm_name)) { | ||
| 607 | const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize); | ||
| 608 | switch (op) { | ||
| 609 | .add => result.features.addFeature(index), | ||
| 610 | .sub => result.features.removeFeature(index), | ||
| 611 | } | ||
| 612 | break; | ||
| 613 | } | ||
| 614 | } | ||
| 615 | } | ||
| 616 | } | ||
| 617 | |||
| 618 | result.features.populateDependencies(all_features); | ||
| 619 | return result; | ||
| 620 | } | ||
| 621 | |||
| 622 | // ABI warning | ||
| 623 | export fn stage2_cmd_targets(zig_triple: [*:0]const u8) c_int { | ||
| 624 | cmdTargets(zig_triple) catch |err| { | ||
| 625 | std.debug.warn("unable to list targets: {}\n", .{@errorName(err)}); | ||
| 626 | return -1; | ||
| 627 | }; | ||
| 628 | return 0; | ||
| 629 | } | ||
| 630 | |||
| 631 | fn cmdTargets(zig_triple: [*:0]const u8) !void { | ||
| 632 | var target = try Target.parse(mem.toSliceConst(u8, zig_triple)); | ||
| 633 | target.Cross.cpu_features = blk: { | ||
| 634 | const llvm = @import("llvm.zig"); | ||
| 635 | const llvm_cpu_name = llvm.GetHostCPUName(); | ||
| 636 | const llvm_cpu_features = llvm.GetNativeFeatures(); | ||
| 637 | break :blk try cpuFeaturesFromLLVM(target.Cross.arch, llvm_cpu_name, llvm_cpu_features); | ||
| 638 | }; | ||
| 639 | return @import("print_targets.zig").cmdTargets( | ||
| 640 | std.heap.c_allocator, | ||
| 641 | &[0][]u8{}, | ||
| 642 | &std.io.getStdOut().outStream().stream, | ||
| 643 | target, | ||
| 644 | ); | ||
| 645 | } | ||
| 646 | |||
| 647 | const Stage2CpuFeatures = struct { | ||
| 648 | allocator: *mem.Allocator, | ||
| 649 | cpu_features: Target.CpuFeatures, | ||
| 650 | |||
| 651 | llvm_features_str: ?[*:0]const u8, | ||
| 652 | |||
| 653 | builtin_str: [:0]const u8, | ||
| 654 | cache_hash: [:0]const u8, | ||
| 655 | |||
| 656 | const Self = @This(); | ||
| 657 | |||
| 658 | fn createFromNative(allocator: *mem.Allocator) !*Self { | ||
| 659 | const arch = Target.current.getArch(); | ||
| 660 | const llvm = @import("llvm.zig"); | ||
| 661 | const llvm_cpu_name = llvm.GetHostCPUName(); | ||
| 662 | const llvm_cpu_features = llvm.GetNativeFeatures(); | ||
| 663 | const cpu_features = try cpuFeaturesFromLLVM(arch, llvm_cpu_name, llvm_cpu_features); | ||
| 664 | return createFromCpuFeatures(allocator, arch, cpu_features); | ||
| 665 | } | ||
| 666 | |||
| 667 | fn createFromCpuFeatures( | ||
| 668 | allocator: *mem.Allocator, | ||
| 669 | arch: Target.Arch, | ||
| 670 | cpu_features: Target.CpuFeatures, | ||
| 671 | ) !*Self { | ||
| 672 | const self = try allocator.create(Self); | ||
| 673 | errdefer allocator.destroy(self); | ||
| 674 | |||
| 675 | const cache_hash = try std.fmt.allocPrint0(allocator, "{}\n{}", .{ | ||
| 676 | cpu_features.cpu.name, | ||
| 677 | cpu_features.features.asBytes(), | ||
| 678 | }); | ||
| 679 | errdefer allocator.free(cache_hash); | ||
| 680 | |||
| 681 | const generic_arch_name = arch.genericName(); | ||
| 682 | var builtin_str_buffer = try std.Buffer.allocPrint(allocator, | ||
| 683 | \\CpuFeatures{{ | ||
| 684 | \\ .cpu = &Target.{}.cpu.{}, | ||
| 685 | \\ .features = Target.{}.featureSet(&[_]Target.{}.Feature{{ | ||
| 686 | \\ | ||
| 687 | , .{ | ||
| 688 | generic_arch_name, | ||
| 689 | cpu_features.cpu.name, | ||
| 690 | generic_arch_name, | ||
| 691 | generic_arch_name, | ||
| 692 | }); | ||
| 693 | defer builtin_str_buffer.deinit(); | ||
| 694 | |||
| 695 | var llvm_features_buffer = try std.Buffer.initSize(allocator, 0); | ||
| 696 | defer llvm_features_buffer.deinit(); | ||
| 697 | |||
| 698 | for (arch.allFeaturesList()) |feature, index_usize| { | ||
| 699 | const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize); | ||
| 700 | const is_enabled = cpu_features.features.isEnabled(index); | ||
| 701 | |||
| 702 | if (feature.llvm_name) |llvm_name| { | ||
| 703 | const plus_or_minus = "-+"[@boolToInt(is_enabled)]; | ||
| 704 | try llvm_features_buffer.appendByte(plus_or_minus); | ||
| 705 | try llvm_features_buffer.append(llvm_name); | ||
| 706 | try llvm_features_buffer.append(","); | ||
| 707 | } | ||
| 708 | |||
| 709 | if (is_enabled) { | ||
| 710 | // TODO some kind of "zig identifier escape" function rather than | ||
| 711 | // unconditionally using @"" syntax | ||
| 712 | try builtin_str_buffer.append(" .@\""); | ||
| 713 | try builtin_str_buffer.append(feature.name); | ||
| 714 | try builtin_str_buffer.append("\",\n"); | ||
| 715 | } | ||
| 716 | } | ||
| 717 | |||
| 718 | try builtin_str_buffer.append( | ||
| 719 | \\ }), | ||
| 720 | \\}; | ||
| 721 | \\ | ||
| 722 | ); | ||
| 723 | |||
| 724 | assert(mem.endsWith(u8, llvm_features_buffer.toSliceConst(), ",")); | ||
| 725 | llvm_features_buffer.shrink(llvm_features_buffer.len() - 1); | ||
| 726 | |||
| 727 | self.* = Self{ | ||
| 728 | .allocator = allocator, | ||
| 729 | .cpu_features = cpu_features, | ||
| 730 | .llvm_features_str = llvm_features_buffer.toOwnedSlice().ptr, | ||
| 731 | .builtin_str = builtin_str_buffer.toOwnedSlice(), | ||
| 732 | .cache_hash = cache_hash, | ||
| 733 | }; | ||
| 734 | return self; | ||
| 735 | } | ||
| 736 | |||
| 737 | fn destroy(self: *Self) void { | ||
| 738 | self.allocator.free(self.cache_hash); | ||
| 739 | self.allocator.free(self.builtin_str); | ||
| 740 | // TODO if (self.llvm_features_str) |llvm_features_str| self.allocator.free(llvm_features_str); | ||
| 741 | self.allocator.destroy(self); | ||
| 742 | } | ||
| 743 | }; | ||
| 744 | |||
| 745 | // ABI warning | ||
| 746 | export fn stage2_cpu_features_parse( | ||
| 747 | result: **Stage2CpuFeatures, | ||
| 748 | zig_triple: ?[*:0]const u8, | ||
| 749 | cpu_name: ?[*:0]const u8, | ||
| 750 | cpu_features: ?[*:0]const u8, | ||
| 751 | ) Error { | ||
| 752 | result.* = stage2ParseCpuFeatures(zig_triple, cpu_name, cpu_features) catch |err| switch (err) { | ||
| 753 | error.OutOfMemory => return .OutOfMemory, | ||
| 754 | error.UnknownArchitecture => return .UnknownArchitecture, | ||
| 755 | error.UnknownSubArchitecture => return .UnknownSubArchitecture, | ||
| 756 | error.UnknownOperatingSystem => return .UnknownOperatingSystem, | ||
| 757 | error.UnknownApplicationBinaryInterface => return .UnknownApplicationBinaryInterface, | ||
| 758 | error.MissingOperatingSystem => return .MissingOperatingSystem, | ||
| 759 | error.MissingArchitecture => return .MissingArchitecture, | ||
| 760 | error.InvalidLlvmCpuFeaturesFormat => return .InvalidLlvmCpuFeaturesFormat, | ||
| 761 | error.InvalidCpuFeatures => return .InvalidCpuFeatures, | ||
| 762 | }; | ||
| 763 | return .None; | ||
| 764 | } | ||
| 765 | |||
| 766 | fn stage2ParseCpuFeatures( | ||
| 767 | zig_triple_oz: ?[*:0]const u8, | ||
| 768 | cpu_name_oz: ?[*:0]const u8, | ||
| 769 | cpu_features_oz: ?[*:0]const u8, | ||
| 770 | ) !*Stage2CpuFeatures { | ||
| 771 | const zig_triple_z = zig_triple_oz orelse return Stage2CpuFeatures.createFromNative(std.heap.c_allocator); | ||
| 772 | const target = try Target.parse(mem.toSliceConst(u8, zig_triple_z)); | ||
| 773 | const arch = target.Cross.arch; | ||
| 774 | |||
| 775 | const cpu = if (cpu_name_oz) |cpu_name_z| blk: { | ||
| 776 | const cpu_name = mem.toSliceConst(u8, cpu_name_z); | ||
| 777 | break :blk arch.parseCpu(cpu_name) catch |err| switch (err) { | ||
| 778 | error.UnknownCpu => { | ||
| 779 | std.debug.warn("Unknown CPU: '{}'\nAvailable CPUs for architecture '{}':\n", .{ | ||
| 780 | cpu_name, | ||
| 781 | @tagName(arch), | ||
| 782 | }); | ||
| 783 | for (arch.allCpus()) |cpu| { | ||
| 784 | std.debug.warn(" {}\n", .{cpu.name}); | ||
| 785 | } | ||
| 786 | process.exit(1); | ||
| 787 | }, | ||
| 788 | else => |e| return e, | ||
| 789 | }; | ||
| 790 | } else target.Cross.cpu_features.cpu; | ||
| 791 | |||
| 792 | var set = if (cpu_features_oz) |cpu_features_z| blk: { | ||
| 793 | const cpu_features = mem.toSliceConst(u8, cpu_features_z); | ||
| 794 | break :blk arch.parseCpuFeatureSet(cpu, cpu_features) catch |err| switch (err) { | ||
| 795 | error.UnknownCpuFeature => { | ||
| 796 | std.debug.warn( | ||
| 797 | \\Unknown CPU features specified. | ||
| 798 | \\Available CPU features for architecture '{}': | ||
| 799 | \\ | ||
| 800 | , .{@tagName(arch)}); | ||
| 801 | for (arch.allFeaturesList()) |feature| { | ||
| 802 | std.debug.warn(" {}\n", .{feature.name}); | ||
| 803 | } | ||
| 804 | process.exit(1); | ||
| 805 | }, | ||
| 806 | else => |e| return e, | ||
| 807 | }; | ||
| 808 | } else cpu.features; | ||
| 809 | |||
| 810 | if (arch.subArchFeature()) |index| { | ||
| 811 | set.addFeature(index); | ||
| 812 | } | ||
| 813 | set.populateDependencies(arch.allFeaturesList()); | ||
| 814 | |||
| 815 | return Stage2CpuFeatures.createFromCpuFeatures(std.heap.c_allocator, arch, .{ | ||
| 816 | .cpu = cpu, | ||
| 817 | .features = set, | ||
| 818 | }); | ||
| 819 | } | ||
| 820 | |||
| 821 | // ABI warning | ||
| 822 | export fn stage2_cpu_features_get_cache_hash( | ||
| 823 | cpu_features: *const Stage2CpuFeatures, | ||
| 824 | ptr: *[*:0]const u8, | ||
| 825 | len: *usize, | ||
| 826 | ) void { | ||
| 827 | ptr.* = cpu_features.cache_hash.ptr; | ||
| 828 | len.* = cpu_features.cache_hash.len; | ||
| 829 | } | ||
| 830 | |||
| 831 | // ABI warning | ||
| 832 | export fn stage2_cpu_features_get_builtin_str( | ||
| 833 | cpu_features: *const Stage2CpuFeatures, | ||
| 834 | ptr: *[*:0]const u8, | ||
| 835 | len: *usize, | ||
| 836 | ) void { | ||
| 837 | ptr.* = cpu_features.builtin_str.ptr; | ||
| 838 | len.* = cpu_features.builtin_str.len; | ||
| 839 | } | ||
| 840 | |||
| 841 | // ABI warning | ||
| 842 | export fn stage2_cpu_features_get_llvm_cpu(cpu_features: *const Stage2CpuFeatures) ?[*:0]const u8 { | ||
| 843 | return if (cpu_features.cpu_features.cpu.llvm_name) |s| s.ptr else null; | ||
| 844 | } | ||
| 845 | |||
| 846 | // ABI warning | ||
| 847 | export fn stage2_cpu_features_get_llvm_features(cpu_features: *const Stage2CpuFeatures) ?[*:0]const u8 { | ||
| 848 | return cpu_features.llvm_features_str; | ||
| 849 | } | ||
| 850 | |||
| 851 | // ABI warning | ||
| 852 | const Stage2LibCInstallation = extern struct { | ||
| 853 | include_dir: [*:0]const u8, | ||
| 854 | include_dir_len: usize, | ||
| 855 | sys_include_dir: [*:0]const u8, | ||
| 856 | sys_include_dir_len: usize, | ||
| 857 | crt_dir: [*:0]const u8, | ||
| 858 | crt_dir_len: usize, | ||
| 859 | static_crt_dir: [*:0]const u8, | ||
| 860 | static_crt_dir_len: usize, | ||
| 861 | msvc_lib_dir: [*:0]const u8, | ||
| 862 | msvc_lib_dir_len: usize, | ||
| 863 | kernel32_lib_dir: [*:0]const u8, | ||
| 864 | kernel32_lib_dir_len: usize, | ||
| 865 | |||
| 866 | fn initFromStage2(self: *Stage2LibCInstallation, libc: LibCInstallation) void { | ||
| 867 | if (libc.include_dir) |s| { | ||
| 868 | self.include_dir = s.ptr; | ||
| 869 | self.include_dir_len = s.len; | ||
| 870 | } else { | ||
| 871 | self.include_dir = ""; | ||
| 872 | self.include_dir_len = 0; | ||
| 873 | } | ||
| 874 | if (libc.sys_include_dir) |s| { | ||
| 875 | self.sys_include_dir = s.ptr; | ||
| 876 | self.sys_include_dir_len = s.len; | ||
| 877 | } else { | ||
| 878 | self.sys_include_dir = ""; | ||
| 879 | self.sys_include_dir_len = 0; | ||
| 880 | } | ||
| 881 | if (libc.crt_dir) |s| { | ||
| 882 | self.crt_dir = s.ptr; | ||
| 883 | self.crt_dir_len = s.len; | ||
| 884 | } else { | ||
| 885 | self.crt_dir = ""; | ||
| 886 | self.crt_dir_len = 0; | ||
| 887 | } | ||
| 888 | if (libc.static_crt_dir) |s| { | ||
| 889 | self.static_crt_dir = s.ptr; | ||
| 890 | self.static_crt_dir_len = s.len; | ||
| 891 | } else { | ||
| 892 | self.static_crt_dir = ""; | ||
| 893 | self.static_crt_dir_len = 0; | ||
| 894 | } | ||
| 895 | if (libc.msvc_lib_dir) |s| { | ||
| 896 | self.msvc_lib_dir = s.ptr; | ||
| 897 | self.msvc_lib_dir_len = s.len; | ||
| 898 | } else { | ||
| 899 | self.msvc_lib_dir = ""; | ||
| 900 | self.msvc_lib_dir_len = 0; | ||
| 901 | } | ||
| 902 | if (libc.kernel32_lib_dir) |s| { | ||
| 903 | self.kernel32_lib_dir = s.ptr; | ||
| 904 | self.kernel32_lib_dir_len = s.len; | ||
| 905 | } else { | ||
| 906 | self.kernel32_lib_dir = ""; | ||
| 907 | self.kernel32_lib_dir_len = 0; | ||
| 908 | } | ||
| 909 | } | ||
| 910 | |||
| 911 | fn toStage2(self: Stage2LibCInstallation) LibCInstallation { | ||
| 912 | var libc: LibCInstallation = .{}; | ||
| 913 | if (self.include_dir_len != 0) { | ||
| 914 | libc.include_dir = self.include_dir[0..self.include_dir_len :0]; | ||
| 915 | } | ||
| 916 | if (self.sys_include_dir_len != 0) { | ||
| 917 | libc.sys_include_dir = self.sys_include_dir[0..self.sys_include_dir_len :0]; | ||
| 918 | } | ||
| 919 | if (self.crt_dir_len != 0) { | ||
| 920 | libc.crt_dir = self.crt_dir[0..self.crt_dir_len :0]; | ||
| 921 | } | ||
| 922 | if (self.static_crt_dir_len != 0) { | ||
| 923 | libc.static_crt_dir = self.static_crt_dir[0..self.static_crt_dir_len :0]; | ||
| 924 | } | ||
| 925 | if (self.msvc_lib_dir_len != 0) { | ||
| 926 | libc.msvc_lib_dir = self.msvc_lib_dir[0..self.msvc_lib_dir_len :0]; | ||
| 927 | } | ||
| 928 | if (self.kernel32_lib_dir_len != 0) { | ||
| 929 | libc.kernel32_lib_dir = self.kernel32_lib_dir[0..self.kernel32_lib_dir_len :0]; | ||
| 930 | } | ||
| 931 | return libc; | ||
| 932 | } | ||
| 933 | }; | ||
| 934 | |||
| 935 | // ABI warning | ||
| 936 | export fn stage2_libc_parse(stage1_libc: *Stage2LibCInstallation, libc_file_z: [*:0]const u8) Error { | ||
| 937 | stderr_file = std.io.getStdErr(); | ||
| 938 | stderr = &stderr_file.outStream().stream; | ||
| 939 | const libc_file = mem.toSliceConst(u8, libc_file_z); | ||
| 940 | var libc = LibCInstallation.parse(std.heap.c_allocator, libc_file, stderr) catch |err| switch (err) { | ||
| 941 | error.ParseError => return .SemanticAnalyzeFail, | ||
| 942 | error.DiskQuota => return .DiskQuota, | ||
| 943 | error.FileTooBig => return .FileTooBig, | ||
| 944 | error.InputOutput => return .FileSystem, | ||
| 945 | error.NoSpaceLeft => return .NoSpaceLeft, | ||
| 946 | error.AccessDenied => return .AccessDenied, | ||
| 947 | error.BrokenPipe => return .BrokenPipe, | ||
| 948 | error.SystemResources => return .SystemResources, | ||
| 949 | error.OperationAborted => return .OperationAborted, | ||
| 950 | error.WouldBlock => unreachable, | ||
| 951 | error.Unexpected => return .Unexpected, | ||
| 952 | error.EndOfStream => return .EndOfFile, | ||
| 953 | error.IsDir => return .IsDir, | ||
| 954 | error.ConnectionResetByPeer => unreachable, | ||
| 955 | error.OutOfMemory => return .OutOfMemory, | ||
| 956 | error.Unseekable => unreachable, | ||
| 957 | error.SharingViolation => return .SharingViolation, | ||
| 958 | error.PathAlreadyExists => unreachable, | ||
| 959 | error.FileNotFound => return .FileNotFound, | ||
| 960 | error.PipeBusy => return .PipeBusy, | ||
| 961 | error.NameTooLong => return .PathTooLong, | ||
| 962 | error.InvalidUtf8 => return .BadPathName, | ||
| 963 | error.BadPathName => return .BadPathName, | ||
| 964 | error.SymLinkLoop => return .SymLinkLoop, | ||
| 965 | error.ProcessFdQuotaExceeded => return .ProcessFdQuotaExceeded, | ||
| 966 | error.SystemFdQuotaExceeded => return .SystemFdQuotaExceeded, | ||
| 967 | error.NoDevice => return .NoDevice, | ||
| 968 | error.NotDir => return .NotDir, | ||
| 969 | error.DeviceBusy => return .DeviceBusy, | ||
| 970 | }; | ||
| 971 | stage1_libc.initFromStage2(libc); | ||
| 972 | return .None; | ||
| 973 | } | ||
| 974 | |||
| 975 | // ABI warning | ||
| 976 | export fn stage2_libc_find_native(stage1_libc: *Stage2LibCInstallation) Error { | ||
| 977 | var libc = LibCInstallation.findNative(std.heap.c_allocator) catch |err| switch (err) { | ||
| 978 | error.OutOfMemory => return .OutOfMemory, | ||
| 979 | error.FileSystem => return .FileSystem, | ||
| 980 | error.UnableToSpawnCCompiler => return .UnableToSpawnCCompiler, | ||
| 981 | error.CCompilerExitCode => return .CCompilerExitCode, | ||
| 982 | error.CCompilerCrashed => return .CCompilerCrashed, | ||
| 983 | error.CCompilerCannotFindHeaders => return .CCompilerCannotFindHeaders, | ||
| 984 | error.LibCRuntimeNotFound => return .LibCRuntimeNotFound, | ||
| 985 | error.LibCStdLibHeaderNotFound => return .LibCStdLibHeaderNotFound, | ||
| 986 | error.LibCKernel32LibNotFound => return .LibCKernel32LibNotFound, | ||
| 987 | error.UnsupportedArchitecture => return .UnsupportedArchitecture, | ||
| 988 | }; | ||
| 989 | stage1_libc.initFromStage2(libc); | ||
| 990 | return .None; | ||
| 991 | } | ||
| 992 | |||
| 993 | // ABI warning | ||
| 994 | export fn stage2_libc_render(stage1_libc: *Stage2LibCInstallation, output_file: *FILE) Error { | ||
| 995 | var libc = stage1_libc.toStage2(); | ||
| 996 | const c_out_stream = &std.io.COutStream.init(output_file).stream; | ||
| 997 | libc.render(c_out_stream) catch |err| switch (err) { | ||
| 998 | error.WouldBlock => unreachable, // stage1 opens stuff in exclusively blocking mode | ||
| 999 | error.SystemResources => return .SystemResources, | ||
| 1000 | error.OperationAborted => return .OperationAborted, | ||
| 1001 | error.BrokenPipe => return .BrokenPipe, | ||
| 1002 | error.DiskQuota => return .DiskQuota, | ||
| 1003 | error.FileTooBig => return .FileTooBig, | ||
| 1004 | error.NoSpaceLeft => return .NoSpaceLeft, | ||
| 1005 | error.AccessDenied => return .AccessDenied, | ||
| 1006 | error.Unexpected => return .Unexpected, | ||
| 1007 | error.InputOutput => return .FileSystem, | ||
| 1008 | }; | ||
| 1009 | return .None; | ||
| 1010 | } | ||
| 1011 | |||
| 1012 | // ABI warning | ||
| 1013 | export fn stage2_libc_cc_print_file_name( | ||
| 1014 | out_ptr: *[*:0]u8, | ||
| 1015 | out_len: *usize, | ||
| 1016 | o_file: [*:0]const u8, | ||
| 1017 | want_dirname: bool, | ||
| 1018 | ) Error { | ||
| 1019 | const result = @import("libc_installation.zig").ccPrintFileName( | ||
| 1020 | std.heap.c_allocator, | ||
| 1021 | mem.toSliceConst(u8, o_file), | ||
| 1022 | if (want_dirname) .only_dir else .full_path, | ||
| 1023 | ) catch |err| switch (err) { | ||
| 1024 | error.OutOfMemory => return .OutOfMemory, | ||
| 1025 | error.LibCRuntimeNotFound => return .FileNotFound, | ||
| 1026 | error.CCompilerExitCode => return .CCompilerExitCode, | ||
| 1027 | error.CCompilerCrashed => return .CCompilerCrashed, | ||
| 1028 | error.UnableToSpawnCCompiler => return .UnableToSpawnCCompiler, | ||
| 1029 | }; | ||
| 1030 | out_ptr.* = result.ptr; | ||
| 1031 | out_len.* = result.len; | ||
| 1032 | return .None; | ||
| 1033 | } | ||
src-self-hosted/stage2.zig created+1033| ... | @@ -0,0 +1,1033 @@ | ||
| 1 | // This is Zig code that is used by both stage1 and stage2. | ||
| 2 | // The prototypes in src/userland.h must match these definitions. | ||
| 3 | |||
| 4 | const std = @import("std"); | ||
| 5 | const io = std.io; | ||
| 6 | const mem = std.mem; | ||
| 7 | const fs = std.fs; | ||
| 8 | const process = std.process; | ||
| 9 | const Allocator = mem.Allocator; | ||
| 10 | const ArrayList = std.ArrayList; | ||
| 11 | const Buffer = std.Buffer; | ||
| 12 | const Target = std.Target; | ||
| 13 | const self_hosted_main = @import("main.zig"); | ||
| 14 | const errmsg = @import("errmsg.zig"); | ||
| 15 | const DepTokenizer = @import("dep_tokenizer.zig").Tokenizer; | ||
| 16 | const assert = std.debug.assert; | ||
| 17 | const LibCInstallation = @import("libc_installation.zig").LibCInstallation; | ||
| 18 | |||
| 19 | var stderr_file: fs.File = undefined; | ||
| 20 | var stderr: *io.OutStream(fs.File.WriteError) = undefined; | ||
| 21 | var stdout: *io.OutStream(fs.File.WriteError) = undefined; | ||
| 22 | |||
| 23 | comptime { | ||
| 24 | _ = @import("dep_tokenizer.zig"); | ||
| 25 | } | ||
| 26 | |||
| 27 | // ABI warning | ||
| 28 | export fn stage2_zen(ptr: *[*]const u8, len: *usize) void { | ||
| 29 | const info_zen = @import("main.zig").info_zen; | ||
| 30 | ptr.* = info_zen; | ||
| 31 | len.* = info_zen.len; | ||
| 32 | } | ||
| 33 | |||
| 34 | // ABI warning | ||
| 35 | export fn stage2_panic(ptr: [*]const u8, len: usize) void { | ||
| 36 | @panic(ptr[0..len]); | ||
| 37 | } | ||
| 38 | |||
| 39 | // ABI warning | ||
| 40 | const Error = extern enum { | ||
| 41 | None, | ||
| 42 | OutOfMemory, | ||
| 43 | InvalidFormat, | ||
| 44 | SemanticAnalyzeFail, | ||
| 45 | AccessDenied, | ||
| 46 | Interrupted, | ||
| 47 | SystemResources, | ||
| 48 | FileNotFound, | ||
| 49 | FileSystem, | ||
| 50 | FileTooBig, | ||
| 51 | DivByZero, | ||
| 52 | Overflow, | ||
| 53 | PathAlreadyExists, | ||
| 54 | Unexpected, | ||
| 55 | ExactDivRemainder, | ||
| 56 | NegativeDenominator, | ||
| 57 | ShiftedOutOneBits, | ||
| 58 | CCompileErrors, | ||
| 59 | EndOfFile, | ||
| 60 | IsDir, | ||
| 61 | NotDir, | ||
| 62 | UnsupportedOperatingSystem, | ||
| 63 | SharingViolation, | ||
| 64 | PipeBusy, | ||
| 65 | PrimitiveTypeNotFound, | ||
| 66 | CacheUnavailable, | ||
| 67 | PathTooLong, | ||
| 68 | CCompilerCannotFindFile, | ||
| 69 | NoCCompilerInstalled, | ||
| 70 | ReadingDepFile, | ||
| 71 | InvalidDepFile, | ||
| 72 | MissingArchitecture, | ||
| 73 | MissingOperatingSystem, | ||
| 74 | UnknownArchitecture, | ||
| 75 | UnknownOperatingSystem, | ||
| 76 | UnknownABI, | ||
| 77 | InvalidFilename, | ||
| 78 | DiskQuota, | ||
| 79 | DiskSpace, | ||
| 80 | UnexpectedWriteFailure, | ||
| 81 | UnexpectedSeekFailure, | ||
| 82 | UnexpectedFileTruncationFailure, | ||
| 83 | Unimplemented, | ||
| 84 | OperationAborted, | ||
| 85 | BrokenPipe, | ||
| 86 | NoSpaceLeft, | ||
| 87 | NotLazy, | ||
| 88 | IsAsync, | ||
| 89 | ImportOutsidePkgPath, | ||
| 90 | UnknownCpu, | ||
| 91 | UnknownSubArchitecture, | ||
| 92 | UnknownCpuFeature, | ||
| 93 | InvalidCpuFeatures, | ||
| 94 | InvalidLlvmCpuFeaturesFormat, | ||
| 95 | UnknownApplicationBinaryInterface, | ||
| 96 | ASTUnitFailure, | ||
| 97 | BadPathName, | ||
| 98 | SymLinkLoop, | ||
| 99 | ProcessFdQuotaExceeded, | ||
| 100 | SystemFdQuotaExceeded, | ||
| 101 | NoDevice, | ||
| 102 | DeviceBusy, | ||
| 103 | UnableToSpawnCCompiler, | ||
| 104 | CCompilerExitCode, | ||
| 105 | CCompilerCrashed, | ||
| 106 | CCompilerCannotFindHeaders, | ||
| 107 | LibCRuntimeNotFound, | ||
| 108 | LibCStdLibHeaderNotFound, | ||
| 109 | LibCKernel32LibNotFound, | ||
| 110 | UnsupportedArchitecture, | ||
| 111 | }; | ||
| 112 | |||
| 113 | const FILE = std.c.FILE; | ||
| 114 | const ast = std.zig.ast; | ||
| 115 | const translate_c = @import("translate_c.zig"); | ||
| 116 | |||
| 117 | /// Args should have a null terminating last arg. | ||
| 118 | export fn stage2_translate_c( | ||
| 119 | out_ast: **ast.Tree, | ||
| 120 | out_errors_ptr: *[*]translate_c.ClangErrMsg, | ||
| 121 | out_errors_len: *usize, | ||
| 122 | args_begin: [*]?[*]const u8, | ||
| 123 | args_end: [*]?[*]const u8, | ||
| 124 | resources_path: [*:0]const u8, | ||
| 125 | ) Error { | ||
| 126 | var errors = @as([*]translate_c.ClangErrMsg, undefined)[0..0]; | ||
| 127 | out_ast.* = translate_c.translate(std.heap.c_allocator, args_begin, args_end, &errors, resources_path) catch |err| switch (err) { | ||
| 128 | error.SemanticAnalyzeFail => { | ||
| 129 | out_errors_ptr.* = errors.ptr; | ||
| 130 | out_errors_len.* = errors.len; | ||
| 131 | return .CCompileErrors; | ||
| 132 | }, | ||
| 133 | error.ASTUnitFailure => return .ASTUnitFailure, | ||
| 134 | error.OutOfMemory => return .OutOfMemory, | ||
| 135 | }; | ||
| 136 | return .None; | ||
| 137 | } | ||
| 138 | |||
| 139 | export fn stage2_free_clang_errors(errors_ptr: [*]translate_c.ClangErrMsg, errors_len: usize) void { | ||
| 140 | translate_c.freeErrors(errors_ptr[0..errors_len]); | ||
| 141 | } | ||
| 142 | |||
| 143 | export fn stage2_render_ast(tree: *ast.Tree, output_file: *FILE) Error { | ||
| 144 | const c_out_stream = &std.io.COutStream.init(output_file).stream; | ||
| 145 | _ = std.zig.render(std.heap.c_allocator, c_out_stream, tree) catch |e| switch (e) { | ||
| 146 | error.WouldBlock => unreachable, // stage1 opens stuff in exclusively blocking mode | ||
| 147 | error.SystemResources => return .SystemResources, | ||
| 148 | error.OperationAborted => return .OperationAborted, | ||
| 149 | error.BrokenPipe => return .BrokenPipe, | ||
| 150 | error.DiskQuota => return .DiskQuota, | ||
| 151 | error.FileTooBig => return .FileTooBig, | ||
| 152 | error.NoSpaceLeft => return .NoSpaceLeft, | ||
| 153 | error.AccessDenied => return .AccessDenied, | ||
| 154 | error.OutOfMemory => return .OutOfMemory, | ||
| 155 | error.Unexpected => return .Unexpected, | ||
| 156 | error.InputOutput => return .FileSystem, | ||
| 157 | }; | ||
| 158 | return .None; | ||
| 159 | } | ||
| 160 | |||
| 161 | // TODO: just use the actual self-hosted zig fmt. Until https://github.com/ziglang/zig/issues/2377, | ||
| 162 | // we use a blocking implementation. | ||
| 163 | export fn stage2_fmt(argc: c_int, argv: [*]const [*:0]const u8) c_int { | ||
| 164 | if (std.debug.runtime_safety) { | ||
| 165 | fmtMain(argc, argv) catch unreachable; | ||
| 166 | } else { | ||
| 167 | fmtMain(argc, argv) catch |e| { | ||
| 168 | std.debug.warn("{}\n", .{@errorName(e)}); | ||
| 169 | return -1; | ||
| 170 | }; | ||
| 171 | } | ||
| 172 | return 0; | ||
| 173 | } | ||
| 174 | |||
| 175 | fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void { | ||
| 176 | const allocator = std.heap.c_allocator; | ||
| 177 | var args_list = std.ArrayList([]const u8).init(allocator); | ||
| 178 | const argc_usize = @intCast(usize, argc); | ||
| 179 | var arg_i: usize = 0; | ||
| 180 | while (arg_i < argc_usize) : (arg_i += 1) { | ||
| 181 | try args_list.append(mem.toSliceConst(u8, argv[arg_i])); | ||
| 182 | } | ||
| 183 | |||
| 184 | stdout = &std.io.getStdOut().outStream().stream; | ||
| 185 | stderr_file = std.io.getStdErr(); | ||
| 186 | stderr = &stderr_file.outStream().stream; | ||
| 187 | |||
| 188 | const args = args_list.toSliceConst()[2..]; | ||
| 189 | |||
| 190 | var color: errmsg.Color = .Auto; | ||
| 191 | var stdin_flag: bool = false; | ||
| 192 | var check_flag: bool = false; | ||
| 193 | var input_files = ArrayList([]const u8).init(allocator); | ||
| 194 | |||
| 195 | { | ||
| 196 | var i: usize = 0; | ||
| 197 | while (i < args.len) : (i += 1) { | ||
| 198 | const arg = args[i]; | ||
| 199 | if (mem.startsWith(u8, arg, "-")) { | ||
| 200 | if (mem.eql(u8, arg, "--help")) { | ||
| 201 | try stdout.write(self_hosted_main.usage_fmt); | ||
| 202 | process.exit(0); | ||
| 203 | } else if (mem.eql(u8, arg, "--color")) { | ||
| 204 | if (i + 1 >= args.len) { | ||
| 205 | try stderr.write("expected [auto|on|off] after --color\n"); | ||
| 206 | process.exit(1); | ||
| 207 | } | ||
| 208 | i += 1; | ||
| 209 | const next_arg = args[i]; | ||
| 210 | if (mem.eql(u8, next_arg, "auto")) { | ||
| 211 | color = .Auto; | ||
| 212 | } else if (mem.eql(u8, next_arg, "on")) { | ||
| 213 | color = .On; | ||
| 214 | } else if (mem.eql(u8, next_arg, "off")) { | ||
| 215 | color = .Off; | ||
| 216 | } else { | ||
| 217 | try stderr.print("expected [auto|on|off] after --color, found '{}'\n", .{next_arg}); | ||
| 218 | process.exit(1); | ||
| 219 | } | ||
| 220 | } else if (mem.eql(u8, arg, "--stdin")) { | ||
| 221 | stdin_flag = true; | ||
| 222 | } else if (mem.eql(u8, arg, "--check")) { | ||
| 223 | check_flag = true; | ||
| 224 | } else { | ||
| 225 | try stderr.print("unrecognized parameter: '{}'", .{arg}); | ||
| 226 | process.exit(1); | ||
| 227 | } | ||
| 228 | } else { | ||
| 229 | try input_files.append(arg); | ||
| 230 | } | ||
| 231 | } | ||
| 232 | } | ||
| 233 | |||
| 234 | if (stdin_flag) { | ||
| 235 | if (input_files.len != 0) { | ||
| 236 | try stderr.write("cannot use --stdin with positional arguments\n"); | ||
| 237 | process.exit(1); | ||
| 238 | } | ||
| 239 | |||
| 240 | const stdin_file = io.getStdIn(); | ||
| 241 | var stdin = stdin_file.inStream(); | ||
| 242 | |||
| 243 | const source_code = try stdin.stream.readAllAlloc(allocator, self_hosted_main.max_src_size); | ||
| 244 | defer allocator.free(source_code); | ||
| 245 | |||
| 246 | const tree = std.zig.parse(allocator, source_code) catch |err| { | ||
| 247 | try stderr.print("error parsing stdin: {}\n", .{err}); | ||
| 248 | process.exit(1); | ||
| 249 | }; | ||
| 250 | defer tree.deinit(); | ||
| 251 | |||
| 252 | var error_it = tree.errors.iterator(0); | ||
| 253 | while (error_it.next()) |parse_error| { | ||
| 254 | try printErrMsgToFile(allocator, parse_error, tree, "<stdin>", stderr_file, color); | ||
| 255 | } | ||
| 256 | if (tree.errors.len != 0) { | ||
| 257 | process.exit(1); | ||
| 258 | } | ||
| 259 | if (check_flag) { | ||
| 260 | const anything_changed = try std.zig.render(allocator, io.null_out_stream, tree); | ||
| 261 | const code = if (anything_changed) @as(u8, 1) else @as(u8, 0); | ||
| 262 | process.exit(code); | ||
| 263 | } | ||
| 264 | |||
| 265 | _ = try std.zig.render(allocator, stdout, tree); | ||
| 266 | return; | ||
| 267 | } | ||
| 268 | |||
| 269 | if (input_files.len == 0) { | ||
| 270 | try stderr.write("expected at least one source file argument\n"); | ||
| 271 | process.exit(1); | ||
| 272 | } | ||
| 273 | |||
| 274 | var fmt = Fmt{ | ||
| 275 | .seen = Fmt.SeenMap.init(allocator), | ||
| 276 | .any_error = false, | ||
| 277 | .color = color, | ||
| 278 | .allocator = allocator, | ||
| 279 | }; | ||
| 280 | |||
| 281 | for (input_files.toSliceConst()) |file_path| { | ||
| 282 | try fmtPath(&fmt, file_path, check_flag); | ||
| 283 | } | ||
| 284 | if (fmt.any_error) { | ||
| 285 | process.exit(1); | ||
| 286 | } | ||
| 287 | } | ||
| 288 | |||
| 289 | const FmtError = error{ | ||
| 290 | SystemResources, | ||
| 291 | OperationAborted, | ||
| 292 | IoPending, | ||
| 293 | BrokenPipe, | ||
| 294 | Unexpected, | ||
| 295 | WouldBlock, | ||
| 296 | FileClosed, | ||
| 297 | DestinationAddressRequired, | ||
| 298 | DiskQuota, | ||
| 299 | FileTooBig, | ||
| 300 | InputOutput, | ||
| 301 | NoSpaceLeft, | ||
| 302 | AccessDenied, | ||
| 303 | OutOfMemory, | ||
| 304 | RenameAcrossMountPoints, | ||
| 305 | ReadOnlyFileSystem, | ||
| 306 | LinkQuotaExceeded, | ||
| 307 | FileBusy, | ||
| 308 | } || fs.File.OpenError; | ||
| 309 | |||
| 310 | fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool) FmtError!void { | ||
| 311 | if (fmt.seen.exists(file_path)) return; | ||
| 312 | try fmt.seen.put(file_path); | ||
| 313 | |||
| 314 | const source_code = io.readFileAlloc(fmt.allocator, file_path) catch |err| switch (err) { | ||
| 315 | error.IsDir, error.AccessDenied => { | ||
| 316 | // TODO make event based (and dir.next()) | ||
| 317 | var dir = try fs.cwd().openDirList(file_path); | ||
| 318 | defer dir.close(); | ||
| 319 | |||
| 320 | var dir_it = dir.iterate(); | ||
| 321 | |||
| 322 | while (try dir_it.next()) |entry| { | ||
| 323 | if (entry.kind == .Directory or mem.endsWith(u8, entry.name, ".zig")) { | ||
| 324 | const full_path = try fs.path.join(fmt.allocator, &[_][]const u8{ file_path, entry.name }); | ||
| 325 | try fmtPath(fmt, full_path, check_mode); | ||
| 326 | } | ||
| 327 | } | ||
| 328 | return; | ||
| 329 | }, | ||
| 330 | else => { | ||
| 331 | // TODO lock stderr printing | ||
| 332 | try stderr.print("unable to open '{}': {}\n", .{ file_path, err }); | ||
| 333 | fmt.any_error = true; | ||
| 334 | return; | ||
| 335 | }, | ||
| 336 | }; | ||
| 337 | defer fmt.allocator.free(source_code); | ||
| 338 | |||
| 339 | const tree = std.zig.parse(fmt.allocator, source_code) catch |err| { | ||
| 340 | try stderr.print("error parsing file '{}': {}\n", .{ file_path, err }); | ||
| 341 | fmt.any_error = true; | ||
| 342 | return; | ||
| 343 | }; | ||
| 344 | defer tree.deinit(); | ||
| 345 | |||
| 346 | var error_it = tree.errors.iterator(0); | ||
| 347 | while (error_it.next()) |parse_error| { | ||
| 348 | try printErrMsgToFile(fmt.allocator, parse_error, tree, file_path, stderr_file, fmt.color); | ||
| 349 | } | ||
| 350 | if (tree.errors.len != 0) { | ||
| 351 | fmt.any_error = true; | ||
| 352 | return; | ||
| 353 | } | ||
| 354 | |||
| 355 | if (check_mode) { | ||
| 356 | const anything_changed = try std.zig.render(fmt.allocator, io.null_out_stream, tree); | ||
| 357 | if (anything_changed) { | ||
| 358 | try stderr.print("{}\n", .{file_path}); | ||
| 359 | fmt.any_error = true; | ||
| 360 | } | ||
| 361 | } else { | ||
| 362 | const baf = try io.BufferedAtomicFile.create(fmt.allocator, file_path); | ||
| 363 | defer baf.destroy(); | ||
| 364 | |||
| 365 | const anything_changed = try std.zig.render(fmt.allocator, baf.stream(), tree); | ||
| 366 | if (anything_changed) { | ||
| 367 | try stderr.print("{}\n", .{file_path}); | ||
| 368 | try baf.finish(); | ||
| 369 | } | ||
| 370 | } | ||
| 371 | } | ||
| 372 | |||
| 373 | const Fmt = struct { | ||
| 374 | seen: SeenMap, | ||
| 375 | any_error: bool, | ||
| 376 | color: errmsg.Color, | ||
| 377 | allocator: *mem.Allocator, | ||
| 378 | |||
| 379 | const SeenMap = std.BufSet; | ||
| 380 | }; | ||
| 381 | |||
| 382 | fn printErrMsgToFile( | ||
| 383 | allocator: *mem.Allocator, | ||
| 384 | parse_error: *const ast.Error, | ||
| 385 | tree: *ast.Tree, | ||
| 386 | path: []const u8, | ||
| 387 | file: fs.File, | ||
| 388 | color: errmsg.Color, | ||
| 389 | ) !void { | ||
| 390 | const color_on = switch (color) { | ||
| 391 | .Auto => file.isTty(), | ||
| 392 | .On => true, | ||
| 393 | .Off => false, | ||
| 394 | }; | ||
| 395 | const lok_token = parse_error.loc(); | ||
| 396 | const span = errmsg.Span{ | ||
| 397 | .first = lok_token, | ||
| 398 | .last = lok_token, | ||
| 399 | }; | ||
| 400 | |||
| 401 | const first_token = tree.tokens.at(span.first); | ||
| 402 | const last_token = tree.tokens.at(span.last); | ||
| 403 | const start_loc = tree.tokenLocationPtr(0, first_token); | ||
| 404 | const end_loc = tree.tokenLocationPtr(first_token.end, last_token); | ||
| 405 | |||
| 406 | var text_buf = try std.Buffer.initSize(allocator, 0); | ||
| 407 | var out_stream = &std.io.BufferOutStream.init(&text_buf).stream; | ||
| 408 | try parse_error.render(&tree.tokens, out_stream); | ||
| 409 | const text = text_buf.toOwnedSlice(); | ||
| 410 | |||
| 411 | const stream = &file.outStream().stream; | ||
| 412 | try stream.print("{}:{}:{}: error: {}\n", .{ path, start_loc.line + 1, start_loc.column + 1, text }); | ||
| 413 | |||
| 414 | if (!color_on) return; | ||
| 415 | |||
| 416 | // Print \r and \t as one space each so that column counts line up | ||
| 417 | for (tree.source[start_loc.line_start..start_loc.line_end]) |byte| { | ||
| 418 | try stream.writeByte(switch (byte) { | ||
| 419 | '\r', '\t' => ' ', | ||
| 420 | else => byte, | ||
| 421 | }); | ||
| 422 | } | ||
| 423 | try stream.writeByte('\n'); | ||
| 424 | try stream.writeByteNTimes(' ', start_loc.column); | ||
| 425 | try stream.writeByteNTimes('~', last_token.end - first_token.start); | ||
| 426 | try stream.writeByte('\n'); | ||
| 427 | } | ||
| 428 | |||
| 429 | export fn stage2_DepTokenizer_init(input: [*]const u8, len: usize) stage2_DepTokenizer { | ||
| 430 | const t = std.heap.c_allocator.create(DepTokenizer) catch @panic("failed to create .d tokenizer"); | ||
| 431 | t.* = DepTokenizer.init(std.heap.c_allocator, input[0..len]); | ||
| 432 | return stage2_DepTokenizer{ | ||
| 433 | .handle = t, | ||
| 434 | }; | ||
| 435 | } | ||
| 436 | |||
| 437 | export fn stage2_DepTokenizer_deinit(self: *stage2_DepTokenizer) void { | ||
| 438 | self.handle.deinit(); | ||
| 439 | } | ||
| 440 | |||
| 441 | export fn stage2_DepTokenizer_next(self: *stage2_DepTokenizer) stage2_DepNextResult { | ||
| 442 | const otoken = self.handle.next() catch { | ||
| 443 | const textz = std.Buffer.init(&self.handle.arena.allocator, self.handle.error_text) catch @panic("failed to create .d tokenizer error text"); | ||
| 444 | return stage2_DepNextResult{ | ||
| 445 | .type_id = .error_, | ||
| 446 | .textz = textz.toSlice().ptr, | ||
| 447 | }; | ||
| 448 | }; | ||
| 449 | const token = otoken orelse { | ||
| 450 | return stage2_DepNextResult{ | ||
| 451 | .type_id = .null_, | ||
| 452 | .textz = undefined, | ||
| 453 | }; | ||
| 454 | }; | ||
| 455 | const textz = std.Buffer.init(&self.handle.arena.allocator, token.bytes) catch @panic("failed to create .d tokenizer token text"); | ||
| 456 | return stage2_DepNextResult{ | ||
| 457 | .type_id = switch (token.id) { | ||
| 458 | .target => .target, | ||
| 459 | .prereq => .prereq, | ||
| 460 | }, | ||
| 461 | .textz = textz.toSlice().ptr, | ||
| 462 | }; | ||
| 463 | } | ||
| 464 | |||
| 465 | const stage2_DepTokenizer = extern struct { | ||
| 466 | handle: *DepTokenizer, | ||
| 467 | }; | ||
| 468 | |||
| 469 | const stage2_DepNextResult = extern struct { | ||
| 470 | type_id: TypeId, | ||
| 471 | |||
| 472 | // when type_id == error --> error text | ||
| 473 | // when type_id == null --> undefined | ||
| 474 | // when type_id == target --> target pathname | ||
| 475 | // when type_id == prereq --> prereq pathname | ||
| 476 | textz: [*]const u8, | ||
| 477 | |||
| 478 | const TypeId = extern enum { | ||
| 479 | error_, | ||
| 480 | null_, | ||
| 481 | target, | ||
| 482 | prereq, | ||
| 483 | }; | ||
| 484 | }; | ||
| 485 | |||
| 486 | // ABI warning | ||
| 487 | export fn stage2_attach_segfault_handler() void { | ||
| 488 | if (std.debug.runtime_safety and std.debug.have_segfault_handling_support) { | ||
| 489 | std.debug.attachSegfaultHandler(); | ||
| 490 | } | ||
| 491 | } | ||
| 492 | |||
| 493 | // ABI warning | ||
| 494 | export fn stage2_progress_create() *std.Progress { | ||
| 495 | const ptr = std.heap.c_allocator.create(std.Progress) catch @panic("out of memory"); | ||
| 496 | ptr.* = std.Progress{}; | ||
| 497 | return ptr; | ||
| 498 | } | ||
| 499 | |||
| 500 | // ABI warning | ||
| 501 | export fn stage2_progress_destroy(progress: *std.Progress) void { | ||
| 502 | std.heap.c_allocator.destroy(progress); | ||
| 503 | } | ||
| 504 | |||
| 505 | // ABI warning | ||
| 506 | export fn stage2_progress_start_root( | ||
| 507 | progress: *std.Progress, | ||
| 508 | name_ptr: [*]const u8, | ||
| 509 | name_len: usize, | ||
| 510 | estimated_total_items: usize, | ||
| 511 | ) *std.Progress.Node { | ||
| 512 | return progress.start( | ||
| 513 | name_ptr[0..name_len], | ||
| 514 | if (estimated_total_items == 0) null else estimated_total_items, | ||
| 515 | ) catch @panic("timer unsupported"); | ||
| 516 | } | ||
| 517 | |||
| 518 | // ABI warning | ||
| 519 | export fn stage2_progress_disable_tty(progress: *std.Progress) void { | ||
| 520 | progress.terminal = null; | ||
| 521 | } | ||
| 522 | |||
| 523 | // ABI warning | ||
| 524 | export fn stage2_progress_start( | ||
| 525 | node: *std.Progress.Node, | ||
| 526 | name_ptr: [*]const u8, | ||
| 527 | name_len: usize, | ||
| 528 | estimated_total_items: usize, | ||
| 529 | ) *std.Progress.Node { | ||
| 530 | const child_node = std.heap.c_allocator.create(std.Progress.Node) catch @panic("out of memory"); | ||
| 531 | child_node.* = node.start( | ||
| 532 | name_ptr[0..name_len], | ||
| 533 | if (estimated_total_items == 0) null else estimated_total_items, | ||
| 534 | ); | ||
| 535 | child_node.activate(); | ||
| 536 | return child_node; | ||
| 537 | } | ||
| 538 | |||
| 539 | // ABI warning | ||
| 540 | export fn stage2_progress_end(node: *std.Progress.Node) void { | ||
| 541 | node.end(); | ||
| 542 | if (&node.context.root != node) { | ||
| 543 | std.heap.c_allocator.destroy(node); | ||
| 544 | } | ||
| 545 | } | ||
| 546 | |||
| 547 | // ABI warning | ||
| 548 | export fn stage2_progress_complete_one(node: *std.Progress.Node) void { | ||
| 549 | node.completeOne(); | ||
| 550 | } | ||
| 551 | |||
| 552 | // ABI warning | ||
| 553 | export fn stage2_progress_update_node(node: *std.Progress.Node, done_count: usize, total_count: usize) void { | ||
| 554 | node.completed_items = done_count; | ||
| 555 | node.estimated_total_items = total_count; | ||
| 556 | node.activate(); | ||
| 557 | node.context.maybeRefresh(); | ||
| 558 | } | ||
| 559 | |||
| 560 | fn cpuFeaturesFromLLVM( | ||
| 561 | arch: Target.Arch, | ||
| 562 | llvm_cpu_name_z: ?[*:0]const u8, | ||
| 563 | llvm_cpu_features_opt: ?[*:0]const u8, | ||
| 564 | ) !Target.CpuFeatures { | ||
| 565 | var result = arch.getBaselineCpuFeatures(); | ||
| 566 | |||
| 567 | if (llvm_cpu_name_z) |cpu_name_z| { | ||
| 568 | const llvm_cpu_name = mem.toSliceConst(u8, cpu_name_z); | ||
| 569 | |||
| 570 | for (arch.allCpus()) |cpu| { | ||
| 571 | const this_llvm_name = cpu.llvm_name orelse continue; | ||
| 572 | if (mem.eql(u8, this_llvm_name, llvm_cpu_name)) { | ||
| 573 | // Here we use the non-dependencies-populated set, | ||
| 574 | // so that subtracting features later in this function | ||
| 575 | // affect the prepopulated set. | ||
| 576 | result = Target.CpuFeatures{ | ||
| 577 | .cpu = cpu, | ||
| 578 | .features = cpu.features, | ||
| 579 | }; | ||
| 580 | break; | ||
| 581 | } | ||
| 582 | } | ||
| 583 | } | ||
| 584 | |||
| 585 | const all_features = arch.allFeaturesList(); | ||
| 586 | |||
| 587 | if (llvm_cpu_features_opt) |llvm_cpu_features| { | ||
| 588 | var it = mem.tokenize(mem.toSliceConst(u8, llvm_cpu_features), ","); | ||
| 589 | while (it.next()) |decorated_llvm_feat| { | ||
| 590 | var op: enum { | ||
| 591 | add, | ||
| 592 | sub, | ||
| 593 | } = undefined; | ||
| 594 | var llvm_feat: []const u8 = undefined; | ||
| 595 | if (mem.startsWith(u8, decorated_llvm_feat, "+")) { | ||
| 596 | op = .add; | ||
| 597 | llvm_feat = decorated_llvm_feat[1..]; | ||
| 598 | } else if (mem.startsWith(u8, decorated_llvm_feat, "-")) { | ||
| 599 | op = .sub; | ||
| 600 | llvm_feat = decorated_llvm_feat[1..]; | ||
| 601 | } else { | ||
| 602 | return error.InvalidLlvmCpuFeaturesFormat; | ||
| 603 | } | ||
| 604 | for (all_features) |feature, index_usize| { | ||
| 605 | const this_llvm_name = feature.llvm_name orelse continue; | ||
| 606 | if (mem.eql(u8, llvm_feat, this_llvm_name)) { | ||
| 607 | const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize); | ||
| 608 | switch (op) { | ||
| 609 | .add => result.features.addFeature(index), | ||
| 610 | .sub => result.features.removeFeature(index), | ||
| 611 | } | ||
| 612 | break; | ||
| 613 | } | ||
| 614 | } | ||
| 615 | } | ||
| 616 | } | ||
| 617 | |||
| 618 | result.features.populateDependencies(all_features); | ||
| 619 | return result; | ||
| 620 | } | ||
| 621 | |||
| 622 | // ABI warning | ||
| 623 | export fn stage2_cmd_targets(zig_triple: [*:0]const u8) c_int { | ||
| 624 | cmdTargets(zig_triple) catch |err| { | ||
| 625 | std.debug.warn("unable to list targets: {}\n", .{@errorName(err)}); | ||
| 626 | return -1; | ||
| 627 | }; | ||
| 628 | return 0; | ||
| 629 | } | ||
| 630 | |||
| 631 | fn cmdTargets(zig_triple: [*:0]const u8) !void { | ||
| 632 | var target = try Target.parse(mem.toSliceConst(u8, zig_triple)); | ||
| 633 | target.Cross.cpu_features = blk: { | ||
| 634 | const llvm = @import("llvm.zig"); | ||
| 635 | const llvm_cpu_name = llvm.GetHostCPUName(); | ||
| 636 | const llvm_cpu_features = llvm.GetNativeFeatures(); | ||
| 637 | break :blk try cpuFeaturesFromLLVM(target.Cross.arch, llvm_cpu_name, llvm_cpu_features); | ||
| 638 | }; | ||
| 639 | return @import("print_targets.zig").cmdTargets( | ||
| 640 | std.heap.c_allocator, | ||
| 641 | &[0][]u8{}, | ||
| 642 | &std.io.getStdOut().outStream().stream, | ||
| 643 | target, | ||
| 644 | ); | ||
| 645 | } | ||
| 646 | |||
| 647 | const Stage2CpuFeatures = struct { | ||
| 648 | allocator: *mem.Allocator, | ||
| 649 | cpu_features: Target.CpuFeatures, | ||
| 650 | |||
| 651 | llvm_features_str: ?[*:0]const u8, | ||
| 652 | |||
| 653 | builtin_str: [:0]const u8, | ||
| 654 | cache_hash: [:0]const u8, | ||
| 655 | |||
| 656 | const Self = @This(); | ||
| 657 | |||
| 658 | fn createFromNative(allocator: *mem.Allocator) !*Self { | ||
| 659 | const arch = Target.current.getArch(); | ||
| 660 | const llvm = @import("llvm.zig"); | ||
| 661 | const llvm_cpu_name = llvm.GetHostCPUName(); | ||
| 662 | const llvm_cpu_features = llvm.GetNativeFeatures(); | ||
| 663 | const cpu_features = try cpuFeaturesFromLLVM(arch, llvm_cpu_name, llvm_cpu_features); | ||
| 664 | return createFromCpuFeatures(allocator, arch, cpu_features); | ||
| 665 | } | ||
| 666 | |||
| 667 | fn createFromCpuFeatures( | ||
| 668 | allocator: *mem.Allocator, | ||
| 669 | arch: Target.Arch, | ||
| 670 | cpu_features: Target.CpuFeatures, | ||
| 671 | ) !*Self { | ||
| 672 | const self = try allocator.create(Self); | ||
| 673 | errdefer allocator.destroy(self); | ||
| 674 | |||
| 675 | const cache_hash = try std.fmt.allocPrint0(allocator, "{}\n{}", .{ | ||
| 676 | cpu_features.cpu.name, | ||
| 677 | cpu_features.features.asBytes(), | ||
| 678 | }); | ||
| 679 | errdefer allocator.free(cache_hash); | ||
| 680 | |||
| 681 | const generic_arch_name = arch.genericName(); | ||
| 682 | var builtin_str_buffer = try std.Buffer.allocPrint(allocator, | ||
| 683 | \\CpuFeatures{{ | ||
| 684 | \\ .cpu = &Target.{}.cpu.{}, | ||
| 685 | \\ .features = Target.{}.featureSet(&[_]Target.{}.Feature{{ | ||
| 686 | \\ | ||
| 687 | , .{ | ||
| 688 | generic_arch_name, | ||
| 689 | cpu_features.cpu.name, | ||
| 690 | generic_arch_name, | ||
| 691 | generic_arch_name, | ||
| 692 | }); | ||
| 693 | defer builtin_str_buffer.deinit(); | ||
| 694 | |||
| 695 | var llvm_features_buffer = try std.Buffer.initSize(allocator, 0); | ||
| 696 | defer llvm_features_buffer.deinit(); | ||
| 697 | |||
| 698 | for (arch.allFeaturesList()) |feature, index_usize| { | ||
| 699 | const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize); | ||
| 700 | const is_enabled = cpu_features.features.isEnabled(index); | ||
| 701 | |||
| 702 | if (feature.llvm_name) |llvm_name| { | ||
| 703 | const plus_or_minus = "-+"[@boolToInt(is_enabled)]; | ||
| 704 | try llvm_features_buffer.appendByte(plus_or_minus); | ||
| 705 | try llvm_features_buffer.append(llvm_name); | ||
| 706 | try llvm_features_buffer.append(","); | ||
| 707 | } | ||
| 708 | |||
| 709 | if (is_enabled) { | ||
| 710 | // TODO some kind of "zig identifier escape" function rather than | ||
| 711 | // unconditionally using @"" syntax | ||
| 712 | try builtin_str_buffer.append(" .@\""); | ||
| 713 | try builtin_str_buffer.append(feature.name); | ||
| 714 | try builtin_str_buffer.append("\",\n"); | ||
| 715 | } | ||
| 716 | } | ||
| 717 | |||
| 718 | try builtin_str_buffer.append( | ||
| 719 | \\ }), | ||
| 720 | \\}; | ||
| 721 | \\ | ||
| 722 | ); | ||
| 723 | |||
| 724 | assert(mem.endsWith(u8, llvm_features_buffer.toSliceConst(), ",")); | ||
| 725 | llvm_features_buffer.shrink(llvm_features_buffer.len() - 1); | ||
| 726 | |||
| 727 | self.* = Self{ | ||
| 728 | .allocator = allocator, | ||
| 729 | .cpu_features = cpu_features, | ||
| 730 | .llvm_features_str = llvm_features_buffer.toOwnedSlice().ptr, | ||
| 731 | .builtin_str = builtin_str_buffer.toOwnedSlice(), | ||
| 732 | .cache_hash = cache_hash, | ||
| 733 | }; | ||
| 734 | return self; | ||
| 735 | } | ||
| 736 | |||
| 737 | fn destroy(self: *Self) void { | ||
| 738 | self.allocator.free(self.cache_hash); | ||
| 739 | self.allocator.free(self.builtin_str); | ||
| 740 | // TODO if (self.llvm_features_str) |llvm_features_str| self.allocator.free(llvm_features_str); | ||
| 741 | self.allocator.destroy(self); | ||
| 742 | } | ||
| 743 | }; | ||
| 744 | |||
| 745 | // ABI warning | ||
| 746 | export fn stage2_cpu_features_parse( | ||
| 747 | result: **Stage2CpuFeatures, | ||
| 748 | zig_triple: ?[*:0]const u8, | ||
| 749 | cpu_name: ?[*:0]const u8, | ||
| 750 | cpu_features: ?[*:0]const u8, | ||
| 751 | ) Error { | ||
| 752 | result.* = stage2ParseCpuFeatures(zig_triple, cpu_name, cpu_features) catch |err| switch (err) { | ||
| 753 | error.OutOfMemory => return .OutOfMemory, | ||
| 754 | error.UnknownArchitecture => return .UnknownArchitecture, | ||
| 755 | error.UnknownSubArchitecture => return .UnknownSubArchitecture, | ||
| 756 | error.UnknownOperatingSystem => return .UnknownOperatingSystem, | ||
| 757 | error.UnknownApplicationBinaryInterface => return .UnknownApplicationBinaryInterface, | ||
| 758 | error.MissingOperatingSystem => return .MissingOperatingSystem, | ||
| 759 | error.MissingArchitecture => return .MissingArchitecture, | ||
| 760 | error.InvalidLlvmCpuFeaturesFormat => return .InvalidLlvmCpuFeaturesFormat, | ||
| 761 | error.InvalidCpuFeatures => return .InvalidCpuFeatures, | ||
| 762 | }; | ||
| 763 | return .None; | ||
| 764 | } | ||
| 765 | |||
| 766 | fn stage2ParseCpuFeatures( | ||
| 767 | zig_triple_oz: ?[*:0]const u8, | ||
| 768 | cpu_name_oz: ?[*:0]const u8, | ||
| 769 | cpu_features_oz: ?[*:0]const u8, | ||
| 770 | ) !*Stage2CpuFeatures { | ||
| 771 | const zig_triple_z = zig_triple_oz orelse return Stage2CpuFeatures.createFromNative(std.heap.c_allocator); | ||
| 772 | const target = try Target.parse(mem.toSliceConst(u8, zig_triple_z)); | ||
| 773 | const arch = target.Cross.arch; | ||
| 774 | |||
| 775 | const cpu = if (cpu_name_oz) |cpu_name_z| blk: { | ||
| 776 | const cpu_name = mem.toSliceConst(u8, cpu_name_z); | ||
| 777 | break :blk arch.parseCpu(cpu_name) catch |err| switch (err) { | ||
| 778 | error.UnknownCpu => { | ||
| 779 | std.debug.warn("Unknown CPU: '{}'\nAvailable CPUs for architecture '{}':\n", .{ | ||
| 780 | cpu_name, | ||
| 781 | @tagName(arch), | ||
| 782 | }); | ||
| 783 | for (arch.allCpus()) |cpu| { | ||
| 784 | std.debug.warn(" {}\n", .{cpu.name}); | ||
| 785 | } | ||
| 786 | process.exit(1); | ||
| 787 | }, | ||
| 788 | else => |e| return e, | ||
| 789 | }; | ||
| 790 | } else target.Cross.cpu_features.cpu; | ||
| 791 | |||
| 792 | var set = if (cpu_features_oz) |cpu_features_z| blk: { | ||
| 793 | const cpu_features = mem.toSliceConst(u8, cpu_features_z); | ||
| 794 | break :blk arch.parseCpuFeatureSet(cpu, cpu_features) catch |err| switch (err) { | ||
| 795 | error.UnknownCpuFeature => { | ||
| 796 | std.debug.warn( | ||
| 797 | \\Unknown CPU features specified. | ||
| 798 | \\Available CPU features for architecture '{}': | ||
| 799 | \\ | ||
| 800 | , .{@tagName(arch)}); | ||
| 801 | for (arch.allFeaturesList()) |feature| { | ||
| 802 | std.debug.warn(" {}\n", .{feature.name}); | ||
| 803 | } | ||
| 804 | process.exit(1); | ||
| 805 | }, | ||
| 806 | else => |e| return e, | ||
| 807 | }; | ||
| 808 | } else cpu.features; | ||
| 809 | |||
| 810 | if (arch.subArchFeature()) |index| { | ||
| 811 | set.addFeature(index); | ||
| 812 | } | ||
| 813 | set.populateDependencies(arch.allFeaturesList()); | ||
| 814 | |||
| 815 | return Stage2CpuFeatures.createFromCpuFeatures(std.heap.c_allocator, arch, .{ | ||
| 816 | .cpu = cpu, | ||
| 817 | .features = set, | ||
| 818 | }); | ||
| 819 | } | ||
| 820 | |||
| 821 | // ABI warning | ||
| 822 | export fn stage2_cpu_features_get_cache_hash( | ||
| 823 | cpu_features: *const Stage2CpuFeatures, | ||
| 824 | ptr: *[*:0]const u8, | ||
| 825 | len: *usize, | ||
| 826 | ) void { | ||
| 827 | ptr.* = cpu_features.cache_hash.ptr; | ||
| 828 | len.* = cpu_features.cache_hash.len; | ||
| 829 | } | ||
| 830 | |||
| 831 | // ABI warning | ||
| 832 | export fn stage2_cpu_features_get_builtin_str( | ||
| 833 | cpu_features: *const Stage2CpuFeatures, | ||
| 834 | ptr: *[*:0]const u8, | ||
| 835 | len: *usize, | ||
| 836 | ) void { | ||
| 837 | ptr.* = cpu_features.builtin_str.ptr; | ||
| 838 | len.* = cpu_features.builtin_str.len; | ||
| 839 | } | ||
| 840 | |||
| 841 | // ABI warning | ||
| 842 | export fn stage2_cpu_features_get_llvm_cpu(cpu_features: *const Stage2CpuFeatures) ?[*:0]const u8 { | ||
| 843 | return if (cpu_features.cpu_features.cpu.llvm_name) |s| s.ptr else null; | ||
| 844 | } | ||
| 845 | |||
| 846 | // ABI warning | ||
| 847 | export fn stage2_cpu_features_get_llvm_features(cpu_features: *const Stage2CpuFeatures) ?[*:0]const u8 { | ||
| 848 | return cpu_features.llvm_features_str; | ||
| 849 | } | ||
| 850 | |||
| 851 | // ABI warning | ||
| 852 | const Stage2LibCInstallation = extern struct { | ||
| 853 | include_dir: [*:0]const u8, | ||
| 854 | include_dir_len: usize, | ||
| 855 | sys_include_dir: [*:0]const u8, | ||
| 856 | sys_include_dir_len: usize, | ||
| 857 | crt_dir: [*:0]const u8, | ||
| 858 | crt_dir_len: usize, | ||
| 859 | static_crt_dir: [*:0]const u8, | ||
| 860 | static_crt_dir_len: usize, | ||
| 861 | msvc_lib_dir: [*:0]const u8, | ||
| 862 | msvc_lib_dir_len: usize, | ||
| 863 | kernel32_lib_dir: [*:0]const u8, | ||
| 864 | kernel32_lib_dir_len: usize, | ||
| 865 | |||
| 866 | fn initFromStage2(self: *Stage2LibCInstallation, libc: LibCInstallation) void { | ||
| 867 | if (libc.include_dir) |s| { | ||
| 868 | self.include_dir = s.ptr; | ||
| 869 | self.include_dir_len = s.len; | ||
| 870 | } else { | ||
| 871 | self.include_dir = ""; | ||
| 872 | self.include_dir_len = 0; | ||
| 873 | } | ||
| 874 | if (libc.sys_include_dir) |s| { | ||
| 875 | self.sys_include_dir = s.ptr; | ||
| 876 | self.sys_include_dir_len = s.len; | ||
| 877 | } else { | ||
| 878 | self.sys_include_dir = ""; | ||
| 879 | self.sys_include_dir_len = 0; | ||
| 880 | } | ||
| 881 | if (libc.crt_dir) |s| { | ||
| 882 | self.crt_dir = s.ptr; | ||
| 883 | self.crt_dir_len = s.len; | ||
| 884 | } else { | ||
| 885 | self.crt_dir = ""; | ||
| 886 | self.crt_dir_len = 0; | ||
| 887 | } | ||
| 888 | if (libc.static_crt_dir) |s| { | ||
| 889 | self.static_crt_dir = s.ptr; | ||
| 890 | self.static_crt_dir_len = s.len; | ||
| 891 | } else { | ||
| 892 | self.static_crt_dir = ""; | ||
| 893 | self.static_crt_dir_len = 0; | ||
| 894 | } | ||
| 895 | if (libc.msvc_lib_dir) |s| { | ||
| 896 | self.msvc_lib_dir = s.ptr; | ||
| 897 | self.msvc_lib_dir_len = s.len; | ||
| 898 | } else { | ||
| 899 | self.msvc_lib_dir = ""; | ||
| 900 | self.msvc_lib_dir_len = 0; | ||
| 901 | } | ||
| 902 | if (libc.kernel32_lib_dir) |s| { | ||
| 903 | self.kernel32_lib_dir = s.ptr; | ||
| 904 | self.kernel32_lib_dir_len = s.len; | ||
| 905 | } else { | ||
| 906 | self.kernel32_lib_dir = ""; | ||
| 907 | self.kernel32_lib_dir_len = 0; | ||
| 908 | } | ||
| 909 | } | ||
| 910 | |||
| 911 | fn toStage2(self: Stage2LibCInstallation) LibCInstallation { | ||
| 912 | var libc: LibCInstallation = .{}; | ||
| 913 | if (self.include_dir_len != 0) { | ||
| 914 | libc.include_dir = self.include_dir[0..self.include_dir_len :0]; | ||
| 915 | } | ||
| 916 | if (self.sys_include_dir_len != 0) { | ||
| 917 | libc.sys_include_dir = self.sys_include_dir[0..self.sys_include_dir_len :0]; | ||
| 918 | } | ||
| 919 | if (self.crt_dir_len != 0) { | ||
| 920 | libc.crt_dir = self.crt_dir[0..self.crt_dir_len :0]; | ||
| 921 | } | ||
| 922 | if (self.static_crt_dir_len != 0) { | ||
| 923 | libc.static_crt_dir = self.static_crt_dir[0..self.static_crt_dir_len :0]; | ||
| 924 | } | ||
| 925 | if (self.msvc_lib_dir_len != 0) { | ||
| 926 | libc.msvc_lib_dir = self.msvc_lib_dir[0..self.msvc_lib_dir_len :0]; | ||
| 927 | } | ||
| 928 | if (self.kernel32_lib_dir_len != 0) { | ||
| 929 | libc.kernel32_lib_dir = self.kernel32_lib_dir[0..self.kernel32_lib_dir_len :0]; | ||
| 930 | } | ||
| 931 | return libc; | ||
| 932 | } | ||
| 933 | }; | ||
| 934 | |||
| 935 | // ABI warning | ||
| 936 | export fn stage2_libc_parse(stage1_libc: *Stage2LibCInstallation, libc_file_z: [*:0]const u8) Error { | ||
| 937 | stderr_file = std.io.getStdErr(); | ||
| 938 | stderr = &stderr_file.outStream().stream; | ||
| 939 | const libc_file = mem.toSliceConst(u8, libc_file_z); | ||
| 940 | var libc = LibCInstallation.parse(std.heap.c_allocator, libc_file, stderr) catch |err| switch (err) { | ||
| 941 | error.ParseError => return .SemanticAnalyzeFail, | ||
| 942 | error.DiskQuota => return .DiskQuota, | ||
| 943 | error.FileTooBig => return .FileTooBig, | ||
| 944 | error.InputOutput => return .FileSystem, | ||
| 945 | error.NoSpaceLeft => return .NoSpaceLeft, | ||
| 946 | error.AccessDenied => return .AccessDenied, | ||
| 947 | error.BrokenPipe => return .BrokenPipe, | ||
| 948 | error.SystemResources => return .SystemResources, | ||
| 949 | error.OperationAborted => return .OperationAborted, | ||
| 950 | error.WouldBlock => unreachable, | ||
| 951 | error.Unexpected => return .Unexpected, | ||
| 952 | error.EndOfStream => return .EndOfFile, | ||
| 953 | error.IsDir => return .IsDir, | ||
| 954 | error.ConnectionResetByPeer => unreachable, | ||
| 955 | error.OutOfMemory => return .OutOfMemory, | ||
| 956 | error.Unseekable => unreachable, | ||
| 957 | error.SharingViolation => return .SharingViolation, | ||
| 958 | error.PathAlreadyExists => unreachable, | ||
| 959 | error.FileNotFound => return .FileNotFound, | ||
| 960 | error.PipeBusy => return .PipeBusy, | ||
| 961 | error.NameTooLong => return .PathTooLong, | ||
| 962 | error.InvalidUtf8 => return .BadPathName, | ||
| 963 | error.BadPathName => return .BadPathName, | ||
| 964 | error.SymLinkLoop => return .SymLinkLoop, | ||
| 965 | error.ProcessFdQuotaExceeded => return .ProcessFdQuotaExceeded, | ||
| 966 | error.SystemFdQuotaExceeded => return .SystemFdQuotaExceeded, | ||
| 967 | error.NoDevice => return .NoDevice, | ||
| 968 | error.NotDir => return .NotDir, | ||
| 969 | error.DeviceBusy => return .DeviceBusy, | ||
| 970 | }; | ||
| 971 | stage1_libc.initFromStage2(libc); | ||
| 972 | return .None; | ||
| 973 | } | ||
| 974 | |||
| 975 | // ABI warning | ||
| 976 | export fn stage2_libc_find_native(stage1_libc: *Stage2LibCInstallation) Error { | ||
| 977 | var libc = LibCInstallation.findNative(std.heap.c_allocator) catch |err| switch (err) { | ||
| 978 | error.OutOfMemory => return .OutOfMemory, | ||
| 979 | error.FileSystem => return .FileSystem, | ||
| 980 | error.UnableToSpawnCCompiler => return .UnableToSpawnCCompiler, | ||
| 981 | error.CCompilerExitCode => return .CCompilerExitCode, | ||
| 982 | error.CCompilerCrashed => return .CCompilerCrashed, | ||
| 983 | error.CCompilerCannotFindHeaders => return .CCompilerCannotFindHeaders, | ||
| 984 | error.LibCRuntimeNotFound => return .LibCRuntimeNotFound, | ||
| 985 | error.LibCStdLibHeaderNotFound => return .LibCStdLibHeaderNotFound, | ||
| 986 | error.LibCKernel32LibNotFound => return .LibCKernel32LibNotFound, | ||
| 987 | error.UnsupportedArchitecture => return .UnsupportedArchitecture, | ||
| 988 | }; | ||
| 989 | stage1_libc.initFromStage2(libc); | ||
| 990 | return .None; | ||
| 991 | } | ||
| 992 | |||
| 993 | // ABI warning | ||
| 994 | export fn stage2_libc_render(stage1_libc: *Stage2LibCInstallation, output_file: *FILE) Error { | ||
| 995 | var libc = stage1_libc.toStage2(); | ||
| 996 | const c_out_stream = &std.io.COutStream.init(output_file).stream; | ||
| 997 | libc.render(c_out_stream) catch |err| switch (err) { | ||
| 998 | error.WouldBlock => unreachable, // stage1 opens stuff in exclusively blocking mode | ||
| 999 | error.SystemResources => return .SystemResources, | ||
| 1000 | error.OperationAborted => return .OperationAborted, | ||
| 1001 | error.BrokenPipe => return .BrokenPipe, | ||
| 1002 | error.DiskQuota => return .DiskQuota, | ||
| 1003 | error.FileTooBig => return .FileTooBig, | ||
| 1004 | error.NoSpaceLeft => return .NoSpaceLeft, | ||
| 1005 | error.AccessDenied => return .AccessDenied, | ||
| 1006 | error.Unexpected => return .Unexpected, | ||
| 1007 | error.InputOutput => return .FileSystem, | ||
| 1008 | }; | ||
| 1009 | return .None; | ||
| 1010 | } | ||
| 1011 | |||
| 1012 | // ABI warning | ||
| 1013 | export fn stage2_libc_cc_print_file_name( | ||
| 1014 | out_ptr: *[*:0]u8, | ||
| 1015 | out_len: *usize, | ||
| 1016 | o_file: [*:0]const u8, | ||
| 1017 | want_dirname: bool, | ||
| 1018 | ) Error { | ||
| 1019 | const result = @import("libc_installation.zig").ccPrintFileName( | ||
| 1020 | std.heap.c_allocator, | ||
| 1021 | mem.toSliceConst(u8, o_file), | ||
| 1022 | if (want_dirname) .only_dir else .full_path, | ||
| 1023 | ) catch |err| switch (err) { | ||
| 1024 | error.OutOfMemory => return .OutOfMemory, | ||
| 1025 | error.LibCRuntimeNotFound => return .FileNotFound, | ||
| 1026 | error.CCompilerExitCode => return .CCompilerExitCode, | ||
| 1027 | error.CCompilerCrashed => return .CCompilerCrashed, | ||
| 1028 | error.UnableToSpawnCCompiler => return .UnableToSpawnCCompiler, | ||
| 1029 | }; | ||
| 1030 | out_ptr.* = result.ptr; | ||
| 1031 | out_len.* = result.len; | ||
| 1032 | return .None; | ||
| 1033 | } | ||
src/cache_hash.cpp+1-1| ... | @@ -5,7 +5,7 @@ | ... | @@ -5,7 +5,7 @@ |
| 5 | * See http://opensource.org/licenses/MIT | 5 | * See http://opensource.org/licenses/MIT |
| 6 | */ | 6 | */ |
| 7 | 7 | ||
| 8 | #include "userland.h" | 8 | #include "stage2.h" |
| 9 | #include "cache_hash.hpp" | 9 | #include "cache_hash.hpp" |
| 10 | #include "all_types.hpp" | 10 | #include "all_types.hpp" |
| 11 | #include "buffer.hpp" | 11 | #include "buffer.hpp" |
src/codegen.cpp+1-1| ... | @@ -18,7 +18,7 @@ | ... | @@ -18,7 +18,7 @@ |
| 18 | #include "target.hpp" | 18 | #include "target.hpp" |
| 19 | #include "util.hpp" | 19 | #include "util.hpp" |
| 20 | #include "zig_llvm.h" | 20 | #include "zig_llvm.h" |
| 21 | #include "userland.h" | 21 | #include "stage2.h" |
| 22 | #include "dump_analysis.hpp" | 22 | #include "dump_analysis.hpp" |
| 23 | #include "softfloat.hpp" | 23 | #include "softfloat.hpp" |
| 24 | #include "mem_profile.hpp" | 24 | #include "mem_profile.hpp" |
src/codegen.hpp+1-1| ... | @@ -11,7 +11,7 @@ | ... | @@ -11,7 +11,7 @@ |
| 11 | #include "parser.hpp" | 11 | #include "parser.hpp" |
| 12 | #include "errmsg.hpp" | 12 | #include "errmsg.hpp" |
| 13 | #include "target.hpp" | 13 | #include "target.hpp" |
| 14 | #include "userland.h" | 14 | #include "stage2.h" |
| 15 | 15 | ||
| 16 | #include <stdio.h> | 16 | #include <stdio.h> |
| 17 | 17 |
src/error.hpp+1-1| ... | @@ -8,7 +8,7 @@ | ... | @@ -8,7 +8,7 @@ |
| 8 | #ifndef ERROR_HPP | 8 | #ifndef ERROR_HPP |
| 9 | #define ERROR_HPP | 9 | #define ERROR_HPP |
| 10 | 10 | ||
| 11 | #include "userland.h" | 11 | #include "stage2.h" |
| 12 | 12 | ||
| 13 | const char *err_str(Error err); | 13 | const char *err_str(Error err); |
| 14 | 14 |
src/main.cpp+1-1| ... | @@ -14,7 +14,7 @@ | ... | @@ -14,7 +14,7 @@ |
| 14 | #include "heap.hpp" | 14 | #include "heap.hpp" |
| 15 | #include "os.hpp" | 15 | #include "os.hpp" |
| 16 | #include "target.hpp" | 16 | #include "target.hpp" |
| 17 | #include "userland.h" | 17 | #include "stage2.h" |
| 18 | #include "glibc.hpp" | 18 | #include "glibc.hpp" |
| 19 | #include "dump_analysis.hpp" | 19 | #include "dump_analysis.hpp" |
| 20 | #include "mem_profile.hpp" | 20 | #include "mem_profile.hpp" |
src/stage2.cpp created+179| ... | @@ -0,0 +1,179 @@ | ||
| 1 | // This file is a shim for zig1. The real implementations of these are in | ||
| 2 | // src-self-hosted/stage1.zig | ||
| 3 | |||
| 4 | #include "stage2.h" | ||
| 5 | #include "util.hpp" | ||
| 6 | #include "zig_llvm.h" | ||
| 7 | #include <stdio.h> | ||
| 8 | #include <stdlib.h> | ||
| 9 | #include <string.h> | ||
| 10 | |||
| 11 | Error stage2_translate_c(struct Stage2Ast **out_ast, | ||
| 12 | struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len, | ||
| 13 | const char **args_begin, const char **args_end, const char *resources_path) | ||
| 14 | { | ||
| 15 | const char *msg = "stage0 called stage2_translate_c"; | ||
| 16 | stage2_panic(msg, strlen(msg)); | ||
| 17 | } | ||
| 18 | |||
| 19 | void stage2_free_clang_errors(struct Stage2ErrorMsg *ptr, size_t len) { | ||
| 20 | const char *msg = "stage0 called stage2_free_clang_errors"; | ||
| 21 | stage2_panic(msg, strlen(msg)); | ||
| 22 | } | ||
| 23 | |||
| 24 | void stage2_zen(const char **ptr, size_t *len) { | ||
| 25 | const char *msg = "stage0 called stage2_zen"; | ||
| 26 | stage2_panic(msg, strlen(msg)); | ||
| 27 | } | ||
| 28 | |||
| 29 | void stage2_attach_segfault_handler(void) { } | ||
| 30 | |||
| 31 | void stage2_panic(const char *ptr, size_t len) { | ||
| 32 | fwrite(ptr, 1, len, stderr); | ||
| 33 | fprintf(stderr, "\n"); | ||
| 34 | fflush(stderr); | ||
| 35 | abort(); | ||
| 36 | } | ||
| 37 | |||
| 38 | void stage2_render_ast(struct Stage2Ast *ast, FILE *output_file) { | ||
| 39 | const char *msg = "stage0 called stage2_render_ast"; | ||
| 40 | stage2_panic(msg, strlen(msg)); | ||
| 41 | } | ||
| 42 | |||
| 43 | int stage2_fmt(int argc, char **argv) { | ||
| 44 | const char *msg = "stage0 called stage2_fmt"; | ||
| 45 | stage2_panic(msg, strlen(msg)); | ||
| 46 | } | ||
| 47 | |||
| 48 | stage2_DepTokenizer stage2_DepTokenizer_init(const char *input, size_t len) { | ||
| 49 | const char *msg = "stage0 called stage2_DepTokenizer_init"; | ||
| 50 | stage2_panic(msg, strlen(msg)); | ||
| 51 | } | ||
| 52 | |||
| 53 | void stage2_DepTokenizer_deinit(stage2_DepTokenizer *self) { | ||
| 54 | const char *msg = "stage0 called stage2_DepTokenizer_deinit"; | ||
| 55 | stage2_panic(msg, strlen(msg)); | ||
| 56 | } | ||
| 57 | |||
| 58 | stage2_DepNextResult stage2_DepTokenizer_next(stage2_DepTokenizer *self) { | ||
| 59 | const char *msg = "stage0 called stage2_DepTokenizer_next"; | ||
| 60 | stage2_panic(msg, strlen(msg)); | ||
| 61 | } | ||
| 62 | |||
| 63 | |||
| 64 | struct Stage2Progress { | ||
| 65 | int trash; | ||
| 66 | }; | ||
| 67 | |||
| 68 | struct Stage2ProgressNode { | ||
| 69 | int trash; | ||
| 70 | }; | ||
| 71 | |||
| 72 | Stage2Progress *stage2_progress_create(void) { | ||
| 73 | return nullptr; | ||
| 74 | } | ||
| 75 | |||
| 76 | void stage2_progress_destroy(Stage2Progress *progress) {} | ||
| 77 | |||
| 78 | Stage2ProgressNode *stage2_progress_start_root(Stage2Progress *progress, | ||
| 79 | const char *name_ptr, size_t name_len, size_t estimated_total_items) | ||
| 80 | { | ||
| 81 | return nullptr; | ||
| 82 | } | ||
| 83 | Stage2ProgressNode *stage2_progress_start(Stage2ProgressNode *node, | ||
| 84 | const char *name_ptr, size_t name_len, size_t estimated_total_items) | ||
| 85 | { | ||
| 86 | return nullptr; | ||
| 87 | } | ||
| 88 | void stage2_progress_end(Stage2ProgressNode *node) {} | ||
| 89 | void stage2_progress_complete_one(Stage2ProgressNode *node) {} | ||
| 90 | void stage2_progress_disable_tty(Stage2Progress *progress) {} | ||
| 91 | void stage2_progress_update_node(Stage2ProgressNode *node, size_t completed_count, size_t estimated_total_items){} | ||
| 92 | |||
| 93 | struct Stage2CpuFeatures { | ||
| 94 | const char *llvm_cpu_name; | ||
| 95 | const char *llvm_cpu_features; | ||
| 96 | const char *builtin_str; | ||
| 97 | const char *cache_hash; | ||
| 98 | }; | ||
| 99 | |||
| 100 | Error stage2_cpu_features_parse(struct Stage2CpuFeatures **out, const char *zig_triple, | ||
| 101 | const char *cpu_name, const char *cpu_features) | ||
| 102 | { | ||
| 103 | if (zig_triple == nullptr) { | ||
| 104 | Stage2CpuFeatures *result = heap::c_allocator.create<Stage2CpuFeatures>(); | ||
| 105 | result->llvm_cpu_name = ZigLLVMGetHostCPUName(); | ||
| 106 | result->llvm_cpu_features = ZigLLVMGetNativeFeatures(); | ||
| 107 | result->builtin_str = "arch.getBaselineCpuFeatures();\n"; | ||
| 108 | result->cache_hash = "native\n\n"; | ||
| 109 | *out = result; | ||
| 110 | return ErrorNone; | ||
| 111 | } | ||
| 112 | if (cpu_name == nullptr && cpu_features == nullptr) { | ||
| 113 | Stage2CpuFeatures *result = heap::c_allocator.create<Stage2CpuFeatures>(); | ||
| 114 | result->builtin_str = "arch.getBaselineCpuFeatures();\n"; | ||
| 115 | result->cache_hash = "\n\n"; | ||
| 116 | *out = result; | ||
| 117 | return ErrorNone; | ||
| 118 | } | ||
| 119 | |||
| 120 | const char *msg = "stage0 called stage2_cpu_features_parse with non-null cpu name or features"; | ||
| 121 | stage2_panic(msg, strlen(msg)); | ||
| 122 | } | ||
| 123 | |||
| 124 | void stage2_cpu_features_get_cache_hash(const Stage2CpuFeatures *cpu_features, | ||
| 125 | const char **ptr, size_t *len) | ||
| 126 | { | ||
| 127 | *ptr = cpu_features->cache_hash; | ||
| 128 | *len = strlen(cpu_features->cache_hash); | ||
| 129 | } | ||
| 130 | const char *stage2_cpu_features_get_llvm_cpu(const Stage2CpuFeatures *cpu_features) { | ||
| 131 | return cpu_features->llvm_cpu_name; | ||
| 132 | } | ||
| 133 | const char *stage2_cpu_features_get_llvm_features(const Stage2CpuFeatures *cpu_features) { | ||
| 134 | return cpu_features->llvm_cpu_features; | ||
| 135 | } | ||
| 136 | void stage2_cpu_features_get_builtin_str(const Stage2CpuFeatures *cpu_features, | ||
| 137 | const char **ptr, size_t *len) | ||
| 138 | { | ||
| 139 | *ptr = cpu_features->builtin_str; | ||
| 140 | *len = strlen(cpu_features->builtin_str); | ||
| 141 | } | ||
| 142 | |||
| 143 | int stage2_cmd_targets(const char *zig_triple) { | ||
| 144 | const char *msg = "stage0 called stage2_cmd_targets"; | ||
| 145 | stage2_panic(msg, strlen(msg)); | ||
| 146 | } | ||
| 147 | |||
| 148 | enum Error stage2_libc_parse(struct Stage2LibCInstallation *libc, const char *libc_file) { | ||
| 149 | libc->include_dir = "/dummy/include"; | ||
| 150 | libc->include_dir_len = strlen(libc->include_dir); | ||
| 151 | libc->sys_include_dir = "/dummy/sys/include"; | ||
| 152 | libc->sys_include_dir_len = strlen(libc->sys_include_dir); | ||
| 153 | libc->crt_dir = ""; | ||
| 154 | libc->crt_dir_len = strlen(libc->crt_dir); | ||
| 155 | libc->static_crt_dir = ""; | ||
| 156 | libc->static_crt_dir_len = strlen(libc->static_crt_dir); | ||
| 157 | libc->msvc_lib_dir = ""; | ||
| 158 | libc->msvc_lib_dir_len = strlen(libc->msvc_lib_dir); | ||
| 159 | libc->kernel32_lib_dir = ""; | ||
| 160 | libc->kernel32_lib_dir_len = strlen(libc->kernel32_lib_dir); | ||
| 161 | return ErrorNone; | ||
| 162 | } | ||
| 163 | |||
| 164 | enum Error stage2_libc_render(struct Stage2LibCInstallation *self, FILE *file) { | ||
| 165 | const char *msg = "stage0 called stage2_libc_render"; | ||
| 166 | stage2_panic(msg, strlen(msg)); | ||
| 167 | } | ||
| 168 | |||
| 169 | enum Error stage2_libc_find_native(struct Stage2LibCInstallation *libc) { | ||
| 170 | const char *msg = "stage0 called stage2_libc_find_native"; | ||
| 171 | stage2_panic(msg, strlen(msg)); | ||
| 172 | } | ||
| 173 | |||
| 174 | enum Error stage2_libc_cc_print_file_name(char **out_ptr, size_t *out_len, | ||
| 175 | const char *o_file, bool want_dirname) | ||
| 176 | { | ||
| 177 | const char *msg = "stage0 called stage2_libc_cc_print_file_name"; | ||
| 178 | stage2_panic(msg, strlen(msg)); | ||
| 179 | } | ||
src/stage2.h created+248| ... | @@ -0,0 +1,248 @@ | ||
| 1 | /* | ||
| 2 | * Copyright (c) 2019 Andrew Kelley | ||
| 3 | * | ||
| 4 | * This file is part of zig, which is MIT licensed. | ||
| 5 | * See http://opensource.org/licenses/MIT | ||
| 6 | */ | ||
| 7 | |||
| 8 | #ifndef ZIG_STAGE2_H | ||
| 9 | #define ZIG_STAGE2_H | ||
| 10 | |||
| 11 | #include <stddef.h> | ||
| 12 | #include <stdint.h> | ||
| 13 | #include <stdio.h> | ||
| 14 | |||
| 15 | #ifdef __cplusplus | ||
| 16 | #define ZIG_EXTERN_C extern "C" | ||
| 17 | #else | ||
| 18 | #define ZIG_EXTERN_C | ||
| 19 | #endif | ||
| 20 | |||
| 21 | #if defined(_MSC_VER) | ||
| 22 | #define ZIG_ATTRIBUTE_NORETURN __declspec(noreturn) | ||
| 23 | #else | ||
| 24 | #define ZIG_ATTRIBUTE_NORETURN __attribute__((noreturn)) | ||
| 25 | #endif | ||
| 26 | |||
| 27 | // ABI warning: the types and declarations in this file must match both those in | ||
| 28 | // stage2.cpp and src-self-hosted/stage2.zig. | ||
| 29 | |||
| 30 | // ABI warning | ||
| 31 | enum Error { | ||
| 32 | ErrorNone, | ||
| 33 | ErrorNoMem, | ||
| 34 | ErrorInvalidFormat, | ||
| 35 | ErrorSemanticAnalyzeFail, | ||
| 36 | ErrorAccess, | ||
| 37 | ErrorInterrupted, | ||
| 38 | ErrorSystemResources, | ||
| 39 | ErrorFileNotFound, | ||
| 40 | ErrorFileSystem, | ||
| 41 | ErrorFileTooBig, | ||
| 42 | ErrorDivByZero, | ||
| 43 | ErrorOverflow, | ||
| 44 | ErrorPathAlreadyExists, | ||
| 45 | ErrorUnexpected, | ||
| 46 | ErrorExactDivRemainder, | ||
| 47 | ErrorNegativeDenominator, | ||
| 48 | ErrorShiftedOutOneBits, | ||
| 49 | ErrorCCompileErrors, | ||
| 50 | ErrorEndOfFile, | ||
| 51 | ErrorIsDir, | ||
| 52 | ErrorNotDir, | ||
| 53 | ErrorUnsupportedOperatingSystem, | ||
| 54 | ErrorSharingViolation, | ||
| 55 | ErrorPipeBusy, | ||
| 56 | ErrorPrimitiveTypeNotFound, | ||
| 57 | ErrorCacheUnavailable, | ||
| 58 | ErrorPathTooLong, | ||
| 59 | ErrorCCompilerCannotFindFile, | ||
| 60 | ErrorNoCCompilerInstalled, | ||
| 61 | ErrorReadingDepFile, | ||
| 62 | ErrorInvalidDepFile, | ||
| 63 | ErrorMissingArchitecture, | ||
| 64 | ErrorMissingOperatingSystem, | ||
| 65 | ErrorUnknownArchitecture, | ||
| 66 | ErrorUnknownOperatingSystem, | ||
| 67 | ErrorUnknownABI, | ||
| 68 | ErrorInvalidFilename, | ||
| 69 | ErrorDiskQuota, | ||
| 70 | ErrorDiskSpace, | ||
| 71 | ErrorUnexpectedWriteFailure, | ||
| 72 | ErrorUnexpectedSeekFailure, | ||
| 73 | ErrorUnexpectedFileTruncationFailure, | ||
| 74 | ErrorUnimplemented, | ||
| 75 | ErrorOperationAborted, | ||
| 76 | ErrorBrokenPipe, | ||
| 77 | ErrorNoSpaceLeft, | ||
| 78 | ErrorNotLazy, | ||
| 79 | ErrorIsAsync, | ||
| 80 | ErrorImportOutsidePkgPath, | ||
| 81 | ErrorUnknownCpu, | ||
| 82 | ErrorUnknownSubArchitecture, | ||
| 83 | ErrorUnknownCpuFeature, | ||
| 84 | ErrorInvalidCpuFeatures, | ||
| 85 | ErrorInvalidLlvmCpuFeaturesFormat, | ||
| 86 | ErrorUnknownApplicationBinaryInterface, | ||
| 87 | ErrorASTUnitFailure, | ||
| 88 | ErrorBadPathName, | ||
| 89 | ErrorSymLinkLoop, | ||
| 90 | ErrorProcessFdQuotaExceeded, | ||
| 91 | ErrorSystemFdQuotaExceeded, | ||
| 92 | ErrorNoDevice, | ||
| 93 | ErrorDeviceBusy, | ||
| 94 | ErrorUnableToSpawnCCompiler, | ||
| 95 | ErrorCCompilerExitCode, | ||
| 96 | ErrorCCompilerCrashed, | ||
| 97 | ErrorCCompilerCannotFindHeaders, | ||
| 98 | ErrorLibCRuntimeNotFound, | ||
| 99 | ErrorLibCStdLibHeaderNotFound, | ||
| 100 | ErrorLibCKernel32LibNotFound, | ||
| 101 | ErrorUnsupportedArchitecture, | ||
| 102 | }; | ||
| 103 | |||
| 104 | // ABI warning | ||
| 105 | struct Stage2ErrorMsg { | ||
| 106 | const char *filename_ptr; // can be null | ||
| 107 | size_t filename_len; | ||
| 108 | const char *msg_ptr; | ||
| 109 | size_t msg_len; | ||
| 110 | const char *source; // valid until the ASTUnit is freed. can be null | ||
| 111 | unsigned line; // 0 based | ||
| 112 | unsigned column; // 0 based | ||
| 113 | unsigned offset; // byte offset into source | ||
| 114 | }; | ||
| 115 | |||
| 116 | // ABI warning | ||
| 117 | struct Stage2Ast; | ||
| 118 | |||
| 119 | // ABI warning | ||
| 120 | ZIG_EXTERN_C enum Error stage2_translate_c(struct Stage2Ast **out_ast, | ||
| 121 | struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len, | ||
| 122 | const char **args_begin, const char **args_end, const char *resources_path); | ||
| 123 | |||
| 124 | // ABI warning | ||
| 125 | ZIG_EXTERN_C void stage2_free_clang_errors(struct Stage2ErrorMsg *ptr, size_t len); | ||
| 126 | |||
| 127 | // ABI warning | ||
| 128 | ZIG_EXTERN_C void stage2_render_ast(struct Stage2Ast *ast, FILE *output_file); | ||
| 129 | |||
| 130 | // ABI warning | ||
| 131 | ZIG_EXTERN_C void stage2_zen(const char **ptr, size_t *len); | ||
| 132 | |||
| 133 | // ABI warning | ||
| 134 | ZIG_EXTERN_C void stage2_attach_segfault_handler(void); | ||
| 135 | |||
| 136 | // ABI warning | ||
| 137 | ZIG_EXTERN_C ZIG_ATTRIBUTE_NORETURN void stage2_panic(const char *ptr, size_t len); | ||
| 138 | |||
| 139 | // ABI warning | ||
| 140 | ZIG_EXTERN_C int stage2_fmt(int argc, char **argv); | ||
| 141 | |||
| 142 | // ABI warning | ||
| 143 | struct stage2_DepTokenizer { | ||
| 144 | void *handle; | ||
| 145 | }; | ||
| 146 | |||
| 147 | // ABI warning | ||
| 148 | struct stage2_DepNextResult { | ||
| 149 | enum TypeId { | ||
| 150 | error, | ||
| 151 | null, | ||
| 152 | target, | ||
| 153 | prereq, | ||
| 154 | }; | ||
| 155 | |||
| 156 | TypeId type_id; | ||
| 157 | |||
| 158 | // when ent == error --> error text | ||
| 159 | // when ent == null --> undefined | ||
| 160 | // when ent == target --> target pathname | ||
| 161 | // when ent == prereq --> prereq pathname | ||
| 162 | const char *textz; | ||
| 163 | }; | ||
| 164 | |||
| 165 | // ABI warning | ||
| 166 | ZIG_EXTERN_C stage2_DepTokenizer stage2_DepTokenizer_init(const char *input, size_t len); | ||
| 167 | |||
| 168 | // ABI warning | ||
| 169 | ZIG_EXTERN_C void stage2_DepTokenizer_deinit(stage2_DepTokenizer *self); | ||
| 170 | |||
| 171 | // ABI warning | ||
| 172 | ZIG_EXTERN_C stage2_DepNextResult stage2_DepTokenizer_next(stage2_DepTokenizer *self); | ||
| 173 | |||
| 174 | // ABI warning | ||
| 175 | struct Stage2Progress; | ||
| 176 | // ABI warning | ||
| 177 | struct Stage2ProgressNode; | ||
| 178 | // ABI warning | ||
| 179 | ZIG_EXTERN_C Stage2Progress *stage2_progress_create(void); | ||
| 180 | // ABI warning | ||
| 181 | ZIG_EXTERN_C void stage2_progress_disable_tty(Stage2Progress *progress); | ||
| 182 | // ABI warning | ||
| 183 | ZIG_EXTERN_C void stage2_progress_destroy(Stage2Progress *progress); | ||
| 184 | // ABI warning | ||
| 185 | ZIG_EXTERN_C Stage2ProgressNode *stage2_progress_start_root(Stage2Progress *progress, | ||
| 186 | const char *name_ptr, size_t name_len, size_t estimated_total_items); | ||
| 187 | // ABI warning | ||
| 188 | ZIG_EXTERN_C Stage2ProgressNode *stage2_progress_start(Stage2ProgressNode *node, | ||
| 189 | const char *name_ptr, size_t name_len, size_t estimated_total_items); | ||
| 190 | // ABI warning | ||
| 191 | ZIG_EXTERN_C void stage2_progress_end(Stage2ProgressNode *node); | ||
| 192 | // ABI warning | ||
| 193 | ZIG_EXTERN_C void stage2_progress_complete_one(Stage2ProgressNode *node); | ||
| 194 | // ABI warning | ||
| 195 | ZIG_EXTERN_C void stage2_progress_update_node(Stage2ProgressNode *node, | ||
| 196 | size_t completed_count, size_t estimated_total_items); | ||
| 197 | |||
| 198 | // ABI warning | ||
| 199 | struct Stage2CpuFeatures; | ||
| 200 | |||
| 201 | // ABI warning | ||
| 202 | ZIG_EXTERN_C enum Error stage2_cpu_features_parse(struct Stage2CpuFeatures **result, | ||
| 203 | const char *zig_triple, const char *cpu_name, const char *cpu_features); | ||
| 204 | |||
| 205 | // ABI warning | ||
| 206 | ZIG_EXTERN_C const char *stage2_cpu_features_get_llvm_cpu(const struct Stage2CpuFeatures *cpu_features); | ||
| 207 | |||
| 208 | // ABI warning | ||
| 209 | ZIG_EXTERN_C const char *stage2_cpu_features_get_llvm_features(const struct Stage2CpuFeatures *cpu_features); | ||
| 210 | |||
| 211 | // ABI warning | ||
| 212 | ZIG_EXTERN_C void stage2_cpu_features_get_builtin_str(const struct Stage2CpuFeatures *cpu_features, | ||
| 213 | const char **ptr, size_t *len); | ||
| 214 | |||
| 215 | // ABI warning | ||
| 216 | ZIG_EXTERN_C void stage2_cpu_features_get_cache_hash(const struct Stage2CpuFeatures *cpu_features, | ||
| 217 | const char **ptr, size_t *len); | ||
| 218 | |||
| 219 | // ABI warning | ||
| 220 | ZIG_EXTERN_C int stage2_cmd_targets(const char *zig_triple); | ||
| 221 | |||
| 222 | // ABI warning | ||
| 223 | struct Stage2LibCInstallation { | ||
| 224 | const char *include_dir; | ||
| 225 | size_t include_dir_len; | ||
| 226 | const char *sys_include_dir; | ||
| 227 | size_t sys_include_dir_len; | ||
| 228 | const char *crt_dir; | ||
| 229 | size_t crt_dir_len; | ||
| 230 | const char *static_crt_dir; | ||
| 231 | size_t static_crt_dir_len; | ||
| 232 | const char *msvc_lib_dir; | ||
| 233 | size_t msvc_lib_dir_len; | ||
| 234 | const char *kernel32_lib_dir; | ||
| 235 | size_t kernel32_lib_dir_len; | ||
| 236 | }; | ||
| 237 | |||
| 238 | // ABI warning | ||
| 239 | ZIG_EXTERN_C enum Error stage2_libc_parse(struct Stage2LibCInstallation *libc, const char *libc_file); | ||
| 240 | // ABI warning | ||
| 241 | ZIG_EXTERN_C enum Error stage2_libc_render(struct Stage2LibCInstallation *self, FILE *file); | ||
| 242 | // ABI warning | ||
| 243 | ZIG_EXTERN_C enum Error stage2_libc_find_native(struct Stage2LibCInstallation *libc); | ||
| 244 | // ABI warning | ||
| 245 | ZIG_EXTERN_C enum Error stage2_libc_cc_print_file_name(char **out_ptr, size_t *out_len, | ||
| 246 | const char *o_file, bool want_dirname); | ||
| 247 | |||
| 248 | #endif | ||
src/userland.cpp deleted-179| ... | @@ -1,179 +0,0 @@ | ||
| 1 | // This file is a shim for zig1. The real implementations of these are in | ||
| 2 | // src-self-hosted/stage1.zig | ||
| 3 | |||
| 4 | #include "userland.h" | ||
| 5 | #include "util.hpp" | ||
| 6 | #include "zig_llvm.h" | ||
| 7 | #include <stdio.h> | ||
| 8 | #include <stdlib.h> | ||
| 9 | #include <string.h> | ||
| 10 | |||
| 11 | Error stage2_translate_c(struct Stage2Ast **out_ast, | ||
| 12 | struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len, | ||
| 13 | const char **args_begin, const char **args_end, const char *resources_path) | ||
| 14 | { | ||
| 15 | const char *msg = "stage0 called stage2_translate_c"; | ||
| 16 | stage2_panic(msg, strlen(msg)); | ||
| 17 | } | ||
| 18 | |||
| 19 | void stage2_free_clang_errors(struct Stage2ErrorMsg *ptr, size_t len) { | ||
| 20 | const char *msg = "stage0 called stage2_free_clang_errors"; | ||
| 21 | stage2_panic(msg, strlen(msg)); | ||
| 22 | } | ||
| 23 | |||
| 24 | void stage2_zen(const char **ptr, size_t *len) { | ||
| 25 | const char *msg = "stage0 called stage2_zen"; | ||
| 26 | stage2_panic(msg, strlen(msg)); | ||
| 27 | } | ||
| 28 | |||
| 29 | void stage2_attach_segfault_handler(void) { } | ||
| 30 | |||
| 31 | void stage2_panic(const char *ptr, size_t len) { | ||
| 32 | fwrite(ptr, 1, len, stderr); | ||
| 33 | fprintf(stderr, "\n"); | ||
| 34 | fflush(stderr); | ||
| 35 | abort(); | ||
| 36 | } | ||
| 37 | |||
| 38 | void stage2_render_ast(struct Stage2Ast *ast, FILE *output_file) { | ||
| 39 | const char *msg = "stage0 called stage2_render_ast"; | ||
| 40 | stage2_panic(msg, strlen(msg)); | ||
| 41 | } | ||
| 42 | |||
| 43 | int stage2_fmt(int argc, char **argv) { | ||
| 44 | const char *msg = "stage0 called stage2_fmt"; | ||
| 45 | stage2_panic(msg, strlen(msg)); | ||
| 46 | } | ||
| 47 | |||
| 48 | stage2_DepTokenizer stage2_DepTokenizer_init(const char *input, size_t len) { | ||
| 49 | const char *msg = "stage0 called stage2_DepTokenizer_init"; | ||
| 50 | stage2_panic(msg, strlen(msg)); | ||
| 51 | } | ||
| 52 | |||
| 53 | void stage2_DepTokenizer_deinit(stage2_DepTokenizer *self) { | ||
| 54 | const char *msg = "stage0 called stage2_DepTokenizer_deinit"; | ||
| 55 | stage2_panic(msg, strlen(msg)); | ||
| 56 | } | ||
| 57 | |||
| 58 | stage2_DepNextResult stage2_DepTokenizer_next(stage2_DepTokenizer *self) { | ||
| 59 | const char *msg = "stage0 called stage2_DepTokenizer_next"; | ||
| 60 | stage2_panic(msg, strlen(msg)); | ||
| 61 | } | ||
| 62 | |||
| 63 | |||
| 64 | struct Stage2Progress { | ||
| 65 | int trash; | ||
| 66 | }; | ||
| 67 | |||
| 68 | struct Stage2ProgressNode { | ||
| 69 | int trash; | ||
| 70 | }; | ||
| 71 | |||
| 72 | Stage2Progress *stage2_progress_create(void) { | ||
| 73 | return nullptr; | ||
| 74 | } | ||
| 75 | |||
| 76 | void stage2_progress_destroy(Stage2Progress *progress) {} | ||
| 77 | |||
| 78 | Stage2ProgressNode *stage2_progress_start_root(Stage2Progress *progress, | ||
| 79 | const char *name_ptr, size_t name_len, size_t estimated_total_items) | ||
| 80 | { | ||
| 81 | return nullptr; | ||
| 82 | } | ||
| 83 | Stage2ProgressNode *stage2_progress_start(Stage2ProgressNode *node, | ||
| 84 | const char *name_ptr, size_t name_len, size_t estimated_total_items) | ||
| 85 | { | ||
| 86 | return nullptr; | ||
| 87 | } | ||
| 88 | void stage2_progress_end(Stage2ProgressNode *node) {} | ||
| 89 | void stage2_progress_complete_one(Stage2ProgressNode *node) {} | ||
| 90 | void stage2_progress_disable_tty(Stage2Progress *progress) {} | ||
| 91 | void stage2_progress_update_node(Stage2ProgressNode *node, size_t completed_count, size_t estimated_total_items){} | ||
| 92 | |||
| 93 | struct Stage2CpuFeatures { | ||
| 94 | const char *llvm_cpu_name; | ||
| 95 | const char *llvm_cpu_features; | ||
| 96 | const char *builtin_str; | ||
| 97 | const char *cache_hash; | ||
| 98 | }; | ||
| 99 | |||
| 100 | Error stage2_cpu_features_parse(struct Stage2CpuFeatures **out, const char *zig_triple, | ||
| 101 | const char *cpu_name, const char *cpu_features) | ||
| 102 | { | ||
| 103 | if (zig_triple == nullptr) { | ||
| 104 | Stage2CpuFeatures *result = heap::c_allocator.create<Stage2CpuFeatures>(); | ||
| 105 | result->llvm_cpu_name = ZigLLVMGetHostCPUName(); | ||
| 106 | result->llvm_cpu_features = ZigLLVMGetNativeFeatures(); | ||
| 107 | result->builtin_str = "arch.getBaselineCpuFeatures();\n"; | ||
| 108 | result->cache_hash = "native\n\n"; | ||
| 109 | *out = result; | ||
| 110 | return ErrorNone; | ||
| 111 | } | ||
| 112 | if (cpu_name == nullptr && cpu_features == nullptr) { | ||
| 113 | Stage2CpuFeatures *result = heap::c_allocator.create<Stage2CpuFeatures>(); | ||
| 114 | result->builtin_str = "arch.getBaselineCpuFeatures();\n"; | ||
| 115 | result->cache_hash = "\n\n"; | ||
| 116 | *out = result; | ||
| 117 | return ErrorNone; | ||
| 118 | } | ||
| 119 | |||
| 120 | const char *msg = "stage0 called stage2_cpu_features_parse with non-null cpu name or features"; | ||
| 121 | stage2_panic(msg, strlen(msg)); | ||
| 122 | } | ||
| 123 | |||
| 124 | void stage2_cpu_features_get_cache_hash(const Stage2CpuFeatures *cpu_features, | ||
| 125 | const char **ptr, size_t *len) | ||
| 126 | { | ||
| 127 | *ptr = cpu_features->cache_hash; | ||
| 128 | *len = strlen(cpu_features->cache_hash); | ||
| 129 | } | ||
| 130 | const char *stage2_cpu_features_get_llvm_cpu(const Stage2CpuFeatures *cpu_features) { | ||
| 131 | return cpu_features->llvm_cpu_name; | ||
| 132 | } | ||
| 133 | const char *stage2_cpu_features_get_llvm_features(const Stage2CpuFeatures *cpu_features) { | ||
| 134 | return cpu_features->llvm_cpu_features; | ||
| 135 | } | ||
| 136 | void stage2_cpu_features_get_builtin_str(const Stage2CpuFeatures *cpu_features, | ||
| 137 | const char **ptr, size_t *len) | ||
| 138 | { | ||
| 139 | *ptr = cpu_features->builtin_str; | ||
| 140 | *len = strlen(cpu_features->builtin_str); | ||
| 141 | } | ||
| 142 | |||
| 143 | int stage2_cmd_targets(const char *zig_triple) { | ||
| 144 | const char *msg = "stage0 called stage2_cmd_targets"; | ||
| 145 | stage2_panic(msg, strlen(msg)); | ||
| 146 | } | ||
| 147 | |||
| 148 | enum Error stage2_libc_parse(struct Stage2LibCInstallation *libc, const char *libc_file) { | ||
| 149 | libc->include_dir = "/dummy/include"; | ||
| 150 | libc->include_dir_len = strlen(libc->include_dir); | ||
| 151 | libc->sys_include_dir = "/dummy/sys/include"; | ||
| 152 | libc->sys_include_dir_len = strlen(libc->sys_include_dir); | ||
| 153 | libc->crt_dir = ""; | ||
| 154 | libc->crt_dir_len = strlen(libc->crt_dir); | ||
| 155 | libc->static_crt_dir = ""; | ||
| 156 | libc->static_crt_dir_len = strlen(libc->static_crt_dir); | ||
| 157 | libc->msvc_lib_dir = ""; | ||
| 158 | libc->msvc_lib_dir_len = strlen(libc->msvc_lib_dir); | ||
| 159 | libc->kernel32_lib_dir = ""; | ||
| 160 | libc->kernel32_lib_dir_len = strlen(libc->kernel32_lib_dir); | ||
| 161 | return ErrorNone; | ||
| 162 | } | ||
| 163 | |||
| 164 | enum Error stage2_libc_render(struct Stage2LibCInstallation *self, FILE *file) { | ||
| 165 | const char *msg = "stage0 called stage2_libc_render"; | ||
| 166 | stage2_panic(msg, strlen(msg)); | ||
| 167 | } | ||
| 168 | |||
| 169 | enum Error stage2_libc_find_native(struct Stage2LibCInstallation *libc) { | ||
| 170 | const char *msg = "stage0 called stage2_libc_find_native"; | ||
| 171 | stage2_panic(msg, strlen(msg)); | ||
| 172 | } | ||
| 173 | |||
| 174 | enum Error stage2_libc_cc_print_file_name(char **out_ptr, size_t *out_len, | ||
| 175 | const char *o_file, bool want_dirname) | ||
| 176 | { | ||
| 177 | const char *msg = "stage0 called stage2_libc_cc_print_file_name"; | ||
| 178 | stage2_panic(msg, strlen(msg)); | ||
| 179 | } | ||
src/userland.h deleted-248| ... | @@ -1,248 +0,0 @@ | ||
| 1 | /* | ||
| 2 | * Copyright (c) 2019 Andrew Kelley | ||
| 3 | * | ||
| 4 | * This file is part of zig, which is MIT licensed. | ||
| 5 | * See http://opensource.org/licenses/MIT | ||
| 6 | */ | ||
| 7 | |||
| 8 | #ifndef ZIG_USERLAND_H | ||
| 9 | #define ZIG_USERLAND_H | ||
| 10 | |||
| 11 | #include <stddef.h> | ||
| 12 | #include <stdint.h> | ||
| 13 | #include <stdio.h> | ||
| 14 | |||
| 15 | #ifdef __cplusplus | ||
| 16 | #define ZIG_EXTERN_C extern "C" | ||
| 17 | #else | ||
| 18 | #define ZIG_EXTERN_C | ||
| 19 | #endif | ||
| 20 | |||
| 21 | #if defined(_MSC_VER) | ||
| 22 | #define ZIG_ATTRIBUTE_NORETURN __declspec(noreturn) | ||
| 23 | #else | ||
| 24 | #define ZIG_ATTRIBUTE_NORETURN __attribute__((noreturn)) | ||
| 25 | #endif | ||
| 26 | |||
| 27 | // ABI warning: the types and declarations in this file must match both those in | ||
| 28 | // userland.cpp and src-self-hosted/stage1.zig. | ||
| 29 | |||
| 30 | // ABI warning | ||
| 31 | enum Error { | ||
| 32 | ErrorNone, | ||
| 33 | ErrorNoMem, | ||
| 34 | ErrorInvalidFormat, | ||
| 35 | ErrorSemanticAnalyzeFail, | ||
| 36 | ErrorAccess, | ||
| 37 | ErrorInterrupted, | ||
| 38 | ErrorSystemResources, | ||
| 39 | ErrorFileNotFound, | ||
| 40 | ErrorFileSystem, | ||
| 41 | ErrorFileTooBig, | ||
| 42 | ErrorDivByZero, | ||
| 43 | ErrorOverflow, | ||
| 44 | ErrorPathAlreadyExists, | ||
| 45 | ErrorUnexpected, | ||
| 46 | ErrorExactDivRemainder, | ||
| 47 | ErrorNegativeDenominator, | ||
| 48 | ErrorShiftedOutOneBits, | ||
| 49 | ErrorCCompileErrors, | ||
| 50 | ErrorEndOfFile, | ||
| 51 | ErrorIsDir, | ||
| 52 | ErrorNotDir, | ||
| 53 | ErrorUnsupportedOperatingSystem, | ||
| 54 | ErrorSharingViolation, | ||
| 55 | ErrorPipeBusy, | ||
| 56 | ErrorPrimitiveTypeNotFound, | ||
| 57 | ErrorCacheUnavailable, | ||
| 58 | ErrorPathTooLong, | ||
| 59 | ErrorCCompilerCannotFindFile, | ||
| 60 | ErrorNoCCompilerInstalled, | ||
| 61 | ErrorReadingDepFile, | ||
| 62 | ErrorInvalidDepFile, | ||
| 63 | ErrorMissingArchitecture, | ||
| 64 | ErrorMissingOperatingSystem, | ||
| 65 | ErrorUnknownArchitecture, | ||
| 66 | ErrorUnknownOperatingSystem, | ||
| 67 | ErrorUnknownABI, | ||
| 68 | ErrorInvalidFilename, | ||
| 69 | ErrorDiskQuota, | ||
| 70 | ErrorDiskSpace, | ||
| 71 | ErrorUnexpectedWriteFailure, | ||
| 72 | ErrorUnexpectedSeekFailure, | ||
| 73 | ErrorUnexpectedFileTruncationFailure, | ||
| 74 | ErrorUnimplemented, | ||
| 75 | ErrorOperationAborted, | ||
| 76 | ErrorBrokenPipe, | ||
| 77 | ErrorNoSpaceLeft, | ||
| 78 | ErrorNotLazy, | ||
| 79 | ErrorIsAsync, | ||
| 80 | ErrorImportOutsidePkgPath, | ||
| 81 | ErrorUnknownCpu, | ||
| 82 | ErrorUnknownSubArchitecture, | ||
| 83 | ErrorUnknownCpuFeature, | ||
| 84 | ErrorInvalidCpuFeatures, | ||
| 85 | ErrorInvalidLlvmCpuFeaturesFormat, | ||
| 86 | ErrorUnknownApplicationBinaryInterface, | ||
| 87 | ErrorASTUnitFailure, | ||
| 88 | ErrorBadPathName, | ||
| 89 | ErrorSymLinkLoop, | ||
| 90 | ErrorProcessFdQuotaExceeded, | ||
| 91 | ErrorSystemFdQuotaExceeded, | ||
| 92 | ErrorNoDevice, | ||
| 93 | ErrorDeviceBusy, | ||
| 94 | ErrorUnableToSpawnCCompiler, | ||
| 95 | ErrorCCompilerExitCode, | ||
| 96 | ErrorCCompilerCrashed, | ||
| 97 | ErrorCCompilerCannotFindHeaders, | ||
| 98 | ErrorLibCRuntimeNotFound, | ||
| 99 | ErrorLibCStdLibHeaderNotFound, | ||
| 100 | ErrorLibCKernel32LibNotFound, | ||
| 101 | ErrorUnsupportedArchitecture, | ||
| 102 | }; | ||
| 103 | |||
| 104 | // ABI warning | ||
| 105 | struct Stage2ErrorMsg { | ||
| 106 | const char *filename_ptr; // can be null | ||
| 107 | size_t filename_len; | ||
| 108 | const char *msg_ptr; | ||
| 109 | size_t msg_len; | ||
| 110 | const char *source; // valid until the ASTUnit is freed. can be null | ||
| 111 | unsigned line; // 0 based | ||
| 112 | unsigned column; // 0 based | ||
| 113 | unsigned offset; // byte offset into source | ||
| 114 | }; | ||
| 115 | |||
| 116 | // ABI warning | ||
| 117 | struct Stage2Ast; | ||
| 118 | |||
| 119 | // ABI warning | ||
| 120 | ZIG_EXTERN_C enum Error stage2_translate_c(struct Stage2Ast **out_ast, | ||
| 121 | struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len, | ||
| 122 | const char **args_begin, const char **args_end, const char *resources_path); | ||
| 123 | |||
| 124 | // ABI warning | ||
| 125 | ZIG_EXTERN_C void stage2_free_clang_errors(struct Stage2ErrorMsg *ptr, size_t len); | ||
| 126 | |||
| 127 | // ABI warning | ||
| 128 | ZIG_EXTERN_C void stage2_render_ast(struct Stage2Ast *ast, FILE *output_file); | ||
| 129 | |||
| 130 | // ABI warning | ||
| 131 | ZIG_EXTERN_C void stage2_zen(const char **ptr, size_t *len); | ||
| 132 | |||
| 133 | // ABI warning | ||
| 134 | ZIG_EXTERN_C void stage2_attach_segfault_handler(void); | ||
| 135 | |||
| 136 | // ABI warning | ||
| 137 | ZIG_EXTERN_C ZIG_ATTRIBUTE_NORETURN void stage2_panic(const char *ptr, size_t len); | ||
| 138 | |||
| 139 | // ABI warning | ||
| 140 | ZIG_EXTERN_C int stage2_fmt(int argc, char **argv); | ||
| 141 | |||
| 142 | // ABI warning | ||
| 143 | struct stage2_DepTokenizer { | ||
| 144 | void *handle; | ||
| 145 | }; | ||
| 146 | |||
| 147 | // ABI warning | ||
| 148 | struct stage2_DepNextResult { | ||
| 149 | enum TypeId { | ||
| 150 | error, | ||
| 151 | null, | ||
| 152 | target, | ||
| 153 | prereq, | ||
| 154 | }; | ||
| 155 | |||
| 156 | TypeId type_id; | ||
| 157 | |||
| 158 | // when ent == error --> error text | ||
| 159 | // when ent == null --> undefined | ||
| 160 | // when ent == target --> target pathname | ||
| 161 | // when ent == prereq --> prereq pathname | ||
| 162 | const char *textz; | ||
| 163 | }; | ||
| 164 | |||
| 165 | // ABI warning | ||
| 166 | ZIG_EXTERN_C stage2_DepTokenizer stage2_DepTokenizer_init(const char *input, size_t len); | ||
| 167 | |||
| 168 | // ABI warning | ||
| 169 | ZIG_EXTERN_C void stage2_DepTokenizer_deinit(stage2_DepTokenizer *self); | ||
| 170 | |||
| 171 | // ABI warning | ||
| 172 | ZIG_EXTERN_C stage2_DepNextResult stage2_DepTokenizer_next(stage2_DepTokenizer *self); | ||
| 173 | |||
| 174 | // ABI warning | ||
| 175 | struct Stage2Progress; | ||
| 176 | // ABI warning | ||
| 177 | struct Stage2ProgressNode; | ||
| 178 | // ABI warning | ||
| 179 | ZIG_EXTERN_C Stage2Progress *stage2_progress_create(void); | ||
| 180 | // ABI warning | ||
| 181 | ZIG_EXTERN_C void stage2_progress_disable_tty(Stage2Progress *progress); | ||
| 182 | // ABI warning | ||
| 183 | ZIG_EXTERN_C void stage2_progress_destroy(Stage2Progress *progress); | ||
| 184 | // ABI warning | ||
| 185 | ZIG_EXTERN_C Stage2ProgressNode *stage2_progress_start_root(Stage2Progress *progress, | ||
| 186 | const char *name_ptr, size_t name_len, size_t estimated_total_items); | ||
| 187 | // ABI warning | ||
| 188 | ZIG_EXTERN_C Stage2ProgressNode *stage2_progress_start(Stage2ProgressNode *node, | ||
| 189 | const char *name_ptr, size_t name_len, size_t estimated_total_items); | ||
| 190 | // ABI warning | ||
| 191 | ZIG_EXTERN_C void stage2_progress_end(Stage2ProgressNode *node); | ||
| 192 | // ABI warning | ||
| 193 | ZIG_EXTERN_C void stage2_progress_complete_one(Stage2ProgressNode *node); | ||
| 194 | // ABI warning | ||
| 195 | ZIG_EXTERN_C void stage2_progress_update_node(Stage2ProgressNode *node, | ||
| 196 | size_t completed_count, size_t estimated_total_items); | ||
| 197 | |||
| 198 | // ABI warning | ||
| 199 | struct Stage2CpuFeatures; | ||
| 200 | |||
| 201 | // ABI warning | ||
| 202 | ZIG_EXTERN_C enum Error stage2_cpu_features_parse(struct Stage2CpuFeatures **result, | ||
| 203 | const char *zig_triple, const char *cpu_name, const char *cpu_features); | ||
| 204 | |||
| 205 | // ABI warning | ||
| 206 | ZIG_EXTERN_C const char *stage2_cpu_features_get_llvm_cpu(const struct Stage2CpuFeatures *cpu_features); | ||
| 207 | |||
| 208 | // ABI warning | ||
| 209 | ZIG_EXTERN_C const char *stage2_cpu_features_get_llvm_features(const struct Stage2CpuFeatures *cpu_features); | ||
| 210 | |||
| 211 | // ABI warning | ||
| 212 | ZIG_EXTERN_C void stage2_cpu_features_get_builtin_str(const struct Stage2CpuFeatures *cpu_features, | ||
| 213 | const char **ptr, size_t *len); | ||
| 214 | |||
| 215 | // ABI warning | ||
| 216 | ZIG_EXTERN_C void stage2_cpu_features_get_cache_hash(const struct Stage2CpuFeatures *cpu_features, | ||
| 217 | const char **ptr, size_t *len); | ||
| 218 | |||
| 219 | // ABI warning | ||
| 220 | ZIG_EXTERN_C int stage2_cmd_targets(const char *zig_triple); | ||
| 221 | |||
| 222 | // ABI warning | ||
| 223 | struct Stage2LibCInstallation { | ||
| 224 | const char *include_dir; | ||
| 225 | size_t include_dir_len; | ||
| 226 | const char *sys_include_dir; | ||
| 227 | size_t sys_include_dir_len; | ||
| 228 | const char *crt_dir; | ||
| 229 | size_t crt_dir_len; | ||
| 230 | const char *static_crt_dir; | ||
| 231 | size_t static_crt_dir_len; | ||
| 232 | const char *msvc_lib_dir; | ||
| 233 | size_t msvc_lib_dir_len; | ||
| 234 | const char *kernel32_lib_dir; | ||
| 235 | size_t kernel32_lib_dir_len; | ||
| 236 | }; | ||
| 237 | |||
| 238 | // ABI warning | ||
| 239 | ZIG_EXTERN_C enum Error stage2_libc_parse(struct Stage2LibCInstallation *libc, const char *libc_file); | ||
| 240 | // ABI warning | ||
| 241 | ZIG_EXTERN_C enum Error stage2_libc_render(struct Stage2LibCInstallation *self, FILE *file); | ||
| 242 | // ABI warning | ||
| 243 | ZIG_EXTERN_C enum Error stage2_libc_find_native(struct Stage2LibCInstallation *libc); | ||
| 244 | // ABI warning | ||
| 245 | ZIG_EXTERN_C enum Error stage2_libc_cc_print_file_name(char **out_ptr, size_t *out_len, | ||
| 246 | const char *o_file, bool want_dirname); | ||
| 247 | |||
| 248 | #endif | ||
src/util.cpp+1-1| ... | @@ -6,7 +6,7 @@ | ... | @@ -6,7 +6,7 @@ |
| 6 | */ | 6 | */ |
| 7 | 7 | ||
| 8 | #include "util.hpp" | 8 | #include "util.hpp" |
| 9 | #include "userland.h" | 9 | #include "stage2.h" |
| 10 | 10 | ||
| 11 | #include <stdio.h> | 11 | #include <stdio.h> |
| 12 | #include <stdarg.h> | 12 | #include <stdarg.h> |
src/zig_clang.h+1-1| ... | @@ -8,7 +8,7 @@ | ... | @@ -8,7 +8,7 @@ |
| 8 | #ifndef ZIG_ZIG_CLANG_H | 8 | #ifndef ZIG_ZIG_CLANG_H |
| 9 | #define ZIG_ZIG_CLANG_H | 9 | #define ZIG_ZIG_CLANG_H |
| 10 | 10 | ||
| 11 | #include "userland.h" | 11 | #include "stage2.h" |
| 12 | #include <inttypes.h> | 12 | #include <inttypes.h> |
| 13 | #include <stdbool.h> | 13 | #include <stdbool.h> |
| 14 | 14 |