diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c06d247151f..7b7c120ab295 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -505,6 +505,7 @@ set(ZIG_STAGE2_SOURCES "${CMAKE_SOURCE_DIR}/lib/std/unicode.zig" "${CMAKE_SOURCE_DIR}/lib/std/zig.zig" "${CMAKE_SOURCE_DIR}/lib/std/zig/Ast.zig" + "${CMAKE_SOURCE_DIR}/lib/std/zig/AstGen.zig" "${CMAKE_SOURCE_DIR}/lib/std/zig/AstRlAnnotate.zig" "${CMAKE_SOURCE_DIR}/lib/std/zig/c_builtins.zig" "${CMAKE_SOURCE_DIR}/lib/std/zig/Parse.zig" @@ -515,8 +516,8 @@ set(ZIG_STAGE2_SOURCES "${CMAKE_SOURCE_DIR}/lib/std/zig/system/NativePaths.zig" "${CMAKE_SOURCE_DIR}/lib/std/zig/system/x86.zig" "${CMAKE_SOURCE_DIR}/lib/std/zig/tokenizer.zig" + "${CMAKE_SOURCE_DIR}/lib/std/zig/Zir.zig" "${CMAKE_SOURCE_DIR}/src/Air.zig" - "${CMAKE_SOURCE_DIR}/src/AstGen.zig" "${CMAKE_SOURCE_DIR}/src/Compilation.zig" "${CMAKE_SOURCE_DIR}/src/Compilation/Config.zig" "${CMAKE_SOURCE_DIR}/src/Liveness.zig" @@ -527,7 +528,6 @@ set(ZIG_STAGE2_SOURCES "${CMAKE_SOURCE_DIR}/src/Sema.zig" "${CMAKE_SOURCE_DIR}/src/TypedValue.zig" "${CMAKE_SOURCE_DIR}/src/Value.zig" - "${CMAKE_SOURCE_DIR}/src/Zir.zig" "${CMAKE_SOURCE_DIR}/src/arch/aarch64/CodeGen.zig" "${CMAKE_SOURCE_DIR}/src/arch/aarch64/Emit.zig" "${CMAKE_SOURCE_DIR}/src/arch/aarch64/Mir.zig" diff --git a/build.zig b/build.zig index 072f7817502a..9179d3d95943 100644 --- a/build.zig +++ b/build.zig @@ -34,7 +34,6 @@ pub fn build(b: *std.Build) !void { const skip_install_langref = b.option(bool, "no-langref", "skip copying of langref to the installation prefix") orelse skip_install_lib_files; const skip_install_autodocs = b.option(bool, "no-autodocs", "skip copying of standard library autodocs to the installation prefix") orelse skip_install_lib_files; const no_bin = b.option(bool, "no-bin", "skip emitting compiler binary") orelse false; - const only_reduce = b.option(bool, "only-reduce", "only build zig reduce") orelse false; const docgen_exe = b.addExecutable(.{ .name = "docgen", @@ -245,7 +244,6 @@ pub fn build(b: *std.Build) !void { exe_options.addOption(bool, "force_gpa", force_gpa); exe_options.addOption(bool, "only_c", only_c); exe_options.addOption(bool, "only_core_functionality", only_c); - exe_options.addOption(bool, "only_reduce", only_reduce); if (link_libc) { exe.linkLibC(); @@ -407,7 +405,6 @@ pub fn build(b: *std.Build) !void { test_cases_options.addOption(bool, "force_gpa", force_gpa); test_cases_options.addOption(bool, "only_c", only_c); test_cases_options.addOption(bool, "only_core_functionality", true); - test_cases_options.addOption(bool, "only_reduce", false); test_cases_options.addOption(bool, "enable_qemu", b.enable_qemu); test_cases_options.addOption(bool, "enable_wine", b.enable_wine); test_cases_options.addOption(bool, "enable_wasmtime", b.enable_wasmtime); @@ -599,7 +596,6 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void { exe_options.addOption(bool, "enable_tracy_allocation", false); exe_options.addOption(bool, "value_tracing", false); exe_options.addOption(bool, "only_core_functionality", true); - exe_options.addOption(bool, "only_reduce", false); const run_opt = b.addSystemCommand(&.{ "wasm-opt", diff --git a/lib/build_runner.zig b/lib/build_runner.zig index d4a503a5c59f..071b56a71cc0 100644 --- a/lib/build_runner.zig +++ b/lib/build_runner.zig @@ -13,7 +13,7 @@ const Step = std.Build.Step; pub const dependencies = @import("@dependencies"); pub fn main() !void { - // Here we use an ArenaAllocator backed by a DirectAllocator because a build is a short-lived, + // Here we use an ArenaAllocator backed by a page allocator because a build is a short-lived, // one shot program. We don't need to waste time freeing memory and finding places to squish // bytes into. So we free everything all at once at the very end. var single_threaded_arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); diff --git a/lib/compiler/fmt.zig b/lib/compiler/fmt.zig new file mode 100644 index 000000000000..2fc04b7935a7 --- /dev/null +++ b/lib/compiler/fmt.zig @@ -0,0 +1,342 @@ +const std = @import("std"); +const mem = std.mem; +const fs = std.fs; +const process = std.process; +const Allocator = std.mem.Allocator; +const warn = std.log.warn; +const Color = std.zig.Color; + +const usage_fmt = + \\Usage: zig fmt [file]... + \\ + \\ Formats the input files and modifies them in-place. + \\ Arguments can be files or directories, which are searched + \\ recursively. + \\ + \\Options: + \\ -h, --help Print this help and exit + \\ --color [auto|off|on] Enable or disable colored error messages + \\ --stdin Format code from stdin; output to stdout + \\ --check List non-conforming files and exit with an error + \\ if the list is non-empty + \\ --ast-check Run zig ast-check on every file + \\ --exclude [file] Exclude file or directory from formatting + \\ + \\ +; + +const Fmt = struct { + seen: SeenMap, + any_error: bool, + check_ast: bool, + color: Color, + gpa: Allocator, + arena: Allocator, + out_buffer: std.ArrayList(u8), + + const SeenMap = std.AutoHashMap(fs.File.INode, void); +}; + +pub fn main() !void { + var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena_instance.deinit(); + const arena = arena_instance.allocator(); + const gpa = arena; + + const args = try process.argsAlloc(arena); + + var color: Color = .auto; + var stdin_flag: bool = false; + var check_flag: bool = false; + var check_ast_flag: bool = false; + var input_files = std.ArrayList([]const u8).init(gpa); + defer input_files.deinit(); + var excluded_files = std.ArrayList([]const u8).init(gpa); + defer excluded_files.deinit(); + + { + var i: usize = 1; + while (i < args.len) : (i += 1) { + const arg = args[i]; + if (mem.startsWith(u8, arg, "-")) { + if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { + const stdout = std.io.getStdOut().writer(); + try stdout.writeAll(usage_fmt); + return process.cleanExit(); + } else if (mem.eql(u8, arg, "--color")) { + if (i + 1 >= args.len) { + fatal("expected [auto|on|off] after --color", .{}); + } + i += 1; + const next_arg = args[i]; + color = std.meta.stringToEnum(Color, next_arg) orelse { + fatal("expected [auto|on|off] after --color, found '{s}'", .{next_arg}); + }; + } else if (mem.eql(u8, arg, "--stdin")) { + stdin_flag = true; + } else if (mem.eql(u8, arg, "--check")) { + check_flag = true; + } else if (mem.eql(u8, arg, "--ast-check")) { + check_ast_flag = true; + } else if (mem.eql(u8, arg, "--exclude")) { + if (i + 1 >= args.len) { + fatal("expected parameter after --exclude", .{}); + } + i += 1; + const next_arg = args[i]; + try excluded_files.append(next_arg); + } else { + fatal("unrecognized parameter: '{s}'", .{arg}); + } + } else { + try input_files.append(arg); + } + } + } + + if (stdin_flag) { + if (input_files.items.len != 0) { + fatal("cannot use --stdin with positional arguments", .{}); + } + + const stdin = std.io.getStdIn(); + const source_code = std.zig.readSourceFileToEndAlloc(gpa, stdin, null) catch |err| { + fatal("unable to read stdin: {}", .{err}); + }; + defer gpa.free(source_code); + + var tree = std.zig.Ast.parse(gpa, source_code, .zig) catch |err| { + fatal("error parsing stdin: {}", .{err}); + }; + defer tree.deinit(gpa); + + if (check_ast_flag) { + var zir = try std.zig.AstGen.generate(gpa, tree); + + if (zir.hasCompileErrors()) { + var wip_errors: std.zig.ErrorBundle.Wip = undefined; + try wip_errors.init(gpa); + defer wip_errors.deinit(); + try wip_errors.addZirErrorMessages(zir, tree, source_code, ""); + var error_bundle = try wip_errors.toOwnedBundle(""); + defer error_bundle.deinit(gpa); + error_bundle.renderToStdErr(color.renderOptions()); + process.exit(2); + } + } else if (tree.errors.len != 0) { + try std.zig.printAstErrorsToStderr(gpa, tree, "", color); + process.exit(2); + } + const formatted = try tree.render(gpa); + defer gpa.free(formatted); + + if (check_flag) { + const code: u8 = @intFromBool(mem.eql(u8, formatted, source_code)); + process.exit(code); + } + + return std.io.getStdOut().writeAll(formatted); + } + + if (input_files.items.len == 0) { + fatal("expected at least one source file argument", .{}); + } + + var fmt = Fmt{ + .gpa = gpa, + .arena = arena, + .seen = Fmt.SeenMap.init(gpa), + .any_error = false, + .check_ast = check_ast_flag, + .color = color, + .out_buffer = std.ArrayList(u8).init(gpa), + }; + defer fmt.seen.deinit(); + defer fmt.out_buffer.deinit(); + + // Mark any excluded files/directories as already seen, + // so that they are skipped later during actual processing + for (excluded_files.items) |file_path| { + const stat = fs.cwd().statFile(file_path) catch |err| switch (err) { + error.FileNotFound => continue, + // On Windows, statFile does not work for directories + error.IsDir => dir: { + var dir = try fs.cwd().openDir(file_path, .{}); + defer dir.close(); + break :dir try dir.stat(); + }, + else => |e| return e, + }; + try fmt.seen.put(stat.inode, {}); + } + + for (input_files.items) |file_path| { + try fmtPath(&fmt, file_path, check_flag, fs.cwd(), file_path); + } + if (fmt.any_error) { + process.exit(1); + } +} + +const FmtError = error{ + SystemResources, + OperationAborted, + IoPending, + BrokenPipe, + Unexpected, + WouldBlock, + FileClosed, + DestinationAddressRequired, + DiskQuota, + FileTooBig, + InputOutput, + NoSpaceLeft, + AccessDenied, + OutOfMemory, + RenameAcrossMountPoints, + ReadOnlyFileSystem, + LinkQuotaExceeded, + FileBusy, + EndOfStream, + Unseekable, + NotOpenForWriting, + UnsupportedEncoding, + ConnectionResetByPeer, + SocketNotConnected, + LockViolation, + NetNameDeleted, + InvalidArgument, +} || fs.File.OpenError; + +fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool, dir: fs.Dir, sub_path: []const u8) FmtError!void { + fmtPathFile(fmt, file_path, check_mode, dir, sub_path) catch |err| switch (err) { + error.IsDir, error.AccessDenied => return fmtPathDir(fmt, file_path, check_mode, dir, sub_path), + else => { + warn("unable to format '{s}': {s}", .{ file_path, @errorName(err) }); + fmt.any_error = true; + return; + }, + }; +} + +fn fmtPathDir( + fmt: *Fmt, + file_path: []const u8, + check_mode: bool, + parent_dir: fs.Dir, + parent_sub_path: []const u8, +) FmtError!void { + var dir = try parent_dir.openDir(parent_sub_path, .{ .iterate = true }); + defer dir.close(); + + const stat = try dir.stat(); + if (try fmt.seen.fetchPut(stat.inode, {})) |_| return; + + var dir_it = dir.iterate(); + while (try dir_it.next()) |entry| { + const is_dir = entry.kind == .directory; + + if (is_dir and (mem.eql(u8, entry.name, "zig-cache") or mem.eql(u8, entry.name, "zig-out"))) continue; + + if (is_dir or entry.kind == .file and (mem.endsWith(u8, entry.name, ".zig") or mem.endsWith(u8, entry.name, ".zon"))) { + const full_path = try fs.path.join(fmt.gpa, &[_][]const u8{ file_path, entry.name }); + defer fmt.gpa.free(full_path); + + if (is_dir) { + try fmtPathDir(fmt, full_path, check_mode, dir, entry.name); + } else { + fmtPathFile(fmt, full_path, check_mode, dir, entry.name) catch |err| { + warn("unable to format '{s}': {s}", .{ full_path, @errorName(err) }); + fmt.any_error = true; + return; + }; + } + } + } +} + +fn fmtPathFile( + fmt: *Fmt, + file_path: []const u8, + check_mode: bool, + dir: fs.Dir, + sub_path: []const u8, +) FmtError!void { + const source_file = try dir.openFile(sub_path, .{}); + var file_closed = false; + errdefer if (!file_closed) source_file.close(); + + const stat = try source_file.stat(); + + if (stat.kind == .directory) + return error.IsDir; + + const gpa = fmt.gpa; + const source_code = try std.zig.readSourceFileToEndAlloc( + gpa, + source_file, + std.math.cast(usize, stat.size) orelse return error.FileTooBig, + ); + defer gpa.free(source_code); + + source_file.close(); + file_closed = true; + + // Add to set after no longer possible to get error.IsDir. + if (try fmt.seen.fetchPut(stat.inode, {})) |_| return; + + var tree = try std.zig.Ast.parse(gpa, source_code, .zig); + defer tree.deinit(gpa); + + if (tree.errors.len != 0) { + try std.zig.printAstErrorsToStderr(gpa, tree, file_path, fmt.color); + fmt.any_error = true; + return; + } + + if (fmt.check_ast) { + if (stat.size > std.zig.max_src_size) + return error.FileTooBig; + + var zir = try std.zig.AstGen.generate(gpa, tree); + defer zir.deinit(gpa); + + if (zir.hasCompileErrors()) { + var wip_errors: std.zig.ErrorBundle.Wip = undefined; + try wip_errors.init(gpa); + defer wip_errors.deinit(); + try wip_errors.addZirErrorMessages(zir, tree, source_code, file_path); + var error_bundle = try wip_errors.toOwnedBundle(""); + defer error_bundle.deinit(gpa); + error_bundle.renderToStdErr(fmt.color.renderOptions()); + fmt.any_error = true; + } + } + + // As a heuristic, we make enough capacity for the same as the input source. + fmt.out_buffer.shrinkRetainingCapacity(0); + try fmt.out_buffer.ensureTotalCapacity(source_code.len); + + try tree.renderToArrayList(&fmt.out_buffer, .{}); + if (mem.eql(u8, fmt.out_buffer.items, source_code)) + return; + + if (check_mode) { + const stdout = std.io.getStdOut().writer(); + try stdout.print("{s}\n", .{file_path}); + fmt.any_error = true; + } else { + var af = try dir.atomicFile(sub_path, .{ .mode = stat.mode }); + defer af.deinit(); + + try af.file.writeAll(fmt.out_buffer.items); + try af.finish(); + const stdout = std.io.getStdOut().writer(); + try stdout.print("{s}\n", .{file_path}); + } +} + +fn fatal(comptime format: []const u8, args: anytype) noreturn { + std.log.err(format, args); + process.exit(1); +} diff --git a/src/reduce.zig b/lib/compiler/reduce.zig similarity index 96% rename from src/reduce.zig rename to lib/compiler/reduce.zig index 027557bea51f..1b40856ffe55 100644 --- a/src/reduce.zig +++ b/lib/compiler/reduce.zig @@ -2,11 +2,10 @@ const std = @import("std"); const mem = std.mem; const Allocator = std.mem.Allocator; const assert = std.debug.assert; -const fatal = @import("./main.zig").fatal; const Ast = std.zig.Ast; const Walk = @import("reduce/Walk.zig"); -const AstGen = @import("AstGen.zig"); -const Zir = @import("Zir.zig"); +const AstGen = std.zig.AstGen; +const Zir = std.zig.Zir; const usage = \\zig reduce [options] ./checker root_source_file.zig [-- [argv]] @@ -47,7 +46,16 @@ const Interestingness = enum { interesting, unknown, boring }; // - reduce flags sent to the compiler // - integrate with the build system? -pub fn main(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { +pub fn main() !void { + var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena_instance.deinit(); + const arena = arena_instance.allocator(); + + var general_purpose_allocator: std.heap.GeneralPurposeAllocator(.{}) = .{}; + const gpa = general_purpose_allocator.allocator(); + + const args = try std.process.argsAlloc(arena); + var opt_checker_path: ?[]const u8 = null; var opt_root_source_file_path: ?[]const u8 = null; var argv: []const []const u8 = &.{}; @@ -55,7 +63,7 @@ pub fn main(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { var skip_smoke_test = false; { - var i: usize = 2; // skip over "zig" and "reduce" + var i: usize = 1; while (i < args.len) : (i += 1) { const arg = args[i]; if (mem.startsWith(u8, arg, "-")) { @@ -411,3 +419,8 @@ fn parse(gpa: Allocator, file_path: []const u8) !Ast { return tree; } + +fn fatal(comptime format: []const u8, args: anytype) noreturn { + std.log.err(format, args); + std.process.exit(1); +} diff --git a/src/reduce/Walk.zig b/lib/compiler/reduce/Walk.zig similarity index 100% rename from src/reduce/Walk.zig rename to lib/compiler/reduce/Walk.zig diff --git a/lib/test_runner.zig b/lib/compiler/test_runner.zig similarity index 100% rename from lib/test_runner.zig rename to lib/compiler/test_runner.zig diff --git a/lib/std/std.zig b/lib/std/std.zig index 98a1bba0dd6f..0781c877cfa4 100644 --- a/lib/std/std.zig +++ b/lib/std/std.zig @@ -193,7 +193,9 @@ pub const valgrind = @import("valgrind.zig"); /// Constants and types representing the Wasm binary format. pub const wasm = @import("wasm.zig"); -/// Tokenizing and parsing of Zig code and other Zig-specific language tooling. +/// Builds of the Zig compiler are distributed partly in source form. That +/// source lives here. These APIs are provided as-is and have absolutely no API +/// guarantees whatsoever. pub const zig = @import("zig.zig"); pub const start = @import("start.zig"); diff --git a/lib/std/zig.zig b/lib/std/zig.zig index e0787e731293..1437fee2e644 100644 --- a/lib/std/zig.zig +++ b/lib/std/zig.zig @@ -1,17 +1,14 @@ -pub const fmt = @import("zig/fmt.zig"); - pub const ErrorBundle = @import("zig/ErrorBundle.zig"); pub const Server = @import("zig/Server.zig"); pub const Client = @import("zig/Client.zig"); pub const Token = tokenizer.Token; pub const Tokenizer = tokenizer.Tokenizer; -pub const fmtId = fmt.fmtId; -pub const fmtEscapes = fmt.fmtEscapes; -pub const isValidId = fmt.isValidId; pub const string_literal = @import("zig/string_literal.zig"); pub const number_literal = @import("zig/number_literal.zig"); pub const primitives = @import("zig/primitives.zig"); pub const Ast = @import("zig/Ast.zig"); +pub const AstGen = @import("zig/AstGen.zig"); +pub const Zir = @import("zig/Zir.zig"); pub const system = @import("zig/system.zig"); /// Deprecated: use `std.Target.Query`. pub const CrossTarget = std.Target.Query; @@ -30,6 +27,36 @@ pub const c_translation = @import("zig/c_translation.zig"); pub const SrcHasher = std.crypto.hash.Blake3; pub const SrcHash = [16]u8; +pub const Color = enum { + /// Determine whether stderr is a terminal or not automatically. + auto, + /// Assume stderr is not a terminal. + off, + /// Assume stderr is a terminal. + on, + + pub fn get_tty_conf(color: Color) std.io.tty.Config { + return switch (color) { + .auto => std.io.tty.detectConfig(std.io.getStdErr()), + .on => .escape_codes, + .off => .no_color, + }; + } + + pub fn renderOptions(color: Color) std.zig.ErrorBundle.RenderOptions { + const ttyconf = get_tty_conf(color); + return .{ + .ttyconf = ttyconf, + .include_source_line = ttyconf != .no_color, + .include_reference_trace = ttyconf != .no_color, + }; + } +}; + +/// There are many assumptions in the entire codebase that Zig source files can +/// be byte-indexed with a u32 integer. +pub const max_src_size = std.math.maxInt(u32); + pub fn hashSrc(src: []const u8) SrcHash { var out: SrcHash = undefined; SrcHasher.hash(src, &out, .{}); @@ -315,11 +342,573 @@ pub fn serializeCpuAlloc(ally: Allocator, cpu: std.Target.Cpu) Allocator.Error![ return buffer.toOwnedSlice(); } +pub const DeclIndex = enum(u32) { + _, + + pub fn toOptional(i: DeclIndex) OptionalDeclIndex { + return @enumFromInt(@intFromEnum(i)); + } +}; + +pub const OptionalDeclIndex = enum(u32) { + none = std.math.maxInt(u32), + _, + + pub fn init(oi: ?DeclIndex) OptionalDeclIndex { + return @enumFromInt(@intFromEnum(oi orelse return .none)); + } + + pub fn unwrap(oi: OptionalDeclIndex) ?DeclIndex { + if (oi == .none) return null; + return @enumFromInt(@intFromEnum(oi)); + } +}; + +/// Resolving a source location into a byte offset may require doing work +/// that we would rather not do unless the error actually occurs. +/// Therefore we need a data structure that contains the information necessary +/// to lazily produce a `SrcLoc` as required. +/// Most of the offsets in this data structure are relative to the containing Decl. +/// This makes the source location resolve properly even when a Decl gets +/// shifted up or down in the file, as long as the Decl's contents itself +/// do not change. +pub const LazySrcLoc = union(enum) { + /// When this tag is set, the code that constructed this `LazySrcLoc` is asserting + /// that all code paths which would need to resolve the source location are + /// unreachable. If you are debugging this tag incorrectly being this value, + /// look into using reverse-continue with a memory watchpoint to see where the + /// value is being set to this tag. + unneeded, + /// Means the source location points to an entire file; not any particular + /// location within the file. `file_scope` union field will be active. + entire_file, + /// The source location points to a byte offset within a source file, + /// offset from 0. The source file is determined contextually. + /// Inside a `SrcLoc`, the `file_scope` union field will be active. + byte_abs: u32, + /// The source location points to a token within a source file, + /// offset from 0. The source file is determined contextually. + /// Inside a `SrcLoc`, the `file_scope` union field will be active. + token_abs: u32, + /// The source location points to an AST node within a source file, + /// offset from 0. The source file is determined contextually. + /// Inside a `SrcLoc`, the `file_scope` union field will be active. + node_abs: u32, + /// The source location points to a byte offset within a source file, + /// offset from the byte offset of the Decl within the file. + /// The Decl is determined contextually. + byte_offset: u32, + /// This data is the offset into the token list from the Decl token. + /// The Decl is determined contextually. + token_offset: u32, + /// The source location points to an AST node, which is this value offset + /// from its containing Decl node AST index. + /// The Decl is determined contextually. + node_offset: TracedOffset, + /// The source location points to the main token of an AST node, found + /// by taking this AST node index offset from the containing Decl AST node. + /// The Decl is determined contextually. + node_offset_main_token: i32, + /// The source location points to the beginning of a struct initializer. + /// The Decl is determined contextually. + node_offset_initializer: i32, + /// The source location points to a variable declaration type expression, + /// found by taking this AST node index offset from the containing + /// Decl AST node, which points to a variable declaration AST node. Next, navigate + /// to the type expression. + /// The Decl is determined contextually. + node_offset_var_decl_ty: i32, + /// The source location points to the alignment expression of a var decl. + /// The Decl is determined contextually. + node_offset_var_decl_align: i32, + /// The source location points to the linksection expression of a var decl. + /// The Decl is determined contextually. + node_offset_var_decl_section: i32, + /// The source location points to the addrspace expression of a var decl. + /// The Decl is determined contextually. + node_offset_var_decl_addrspace: i32, + /// The source location points to the initializer of a var decl. + /// The Decl is determined contextually. + node_offset_var_decl_init: i32, + /// The source location points to the first parameter of a builtin + /// function call, found by taking this AST node index offset from the containing + /// Decl AST node, which points to a builtin call AST node. Next, navigate + /// to the first parameter. + /// The Decl is determined contextually. + node_offset_builtin_call_arg0: i32, + /// Same as `node_offset_builtin_call_arg0` except arg index 1. + node_offset_builtin_call_arg1: i32, + node_offset_builtin_call_arg2: i32, + node_offset_builtin_call_arg3: i32, + node_offset_builtin_call_arg4: i32, + node_offset_builtin_call_arg5: i32, + /// Like `node_offset_builtin_call_arg0` but recurses through arbitrarily many calls + /// to pointer cast builtins. + node_offset_ptrcast_operand: i32, + /// The source location points to the index expression of an array access + /// expression, found by taking this AST node index offset from the containing + /// Decl AST node, which points to an array access AST node. Next, navigate + /// to the index expression. + /// The Decl is determined contextually. + node_offset_array_access_index: i32, + /// The source location points to the LHS of a slice expression + /// expression, found by taking this AST node index offset from the containing + /// Decl AST node, which points to a slice AST node. Next, navigate + /// to the sentinel expression. + /// The Decl is determined contextually. + node_offset_slice_ptr: i32, + /// The source location points to start expression of a slice expression + /// expression, found by taking this AST node index offset from the containing + /// Decl AST node, which points to a slice AST node. Next, navigate + /// to the sentinel expression. + /// The Decl is determined contextually. + node_offset_slice_start: i32, + /// The source location points to the end expression of a slice + /// expression, found by taking this AST node index offset from the containing + /// Decl AST node, which points to a slice AST node. Next, navigate + /// to the sentinel expression. + /// The Decl is determined contextually. + node_offset_slice_end: i32, + /// The source location points to the sentinel expression of a slice + /// expression, found by taking this AST node index offset from the containing + /// Decl AST node, which points to a slice AST node. Next, navigate + /// to the sentinel expression. + /// The Decl is determined contextually. + node_offset_slice_sentinel: i32, + /// The source location points to the callee expression of a function + /// call expression, found by taking this AST node index offset from the containing + /// Decl AST node, which points to a function call AST node. Next, navigate + /// to the callee expression. + /// The Decl is determined contextually. + node_offset_call_func: i32, + /// The payload is offset from the containing Decl AST node. + /// The source location points to the field name of: + /// * a field access expression (`a.b`), or + /// * the callee of a method call (`a.b()`) + /// The Decl is determined contextually. + node_offset_field_name: i32, + /// The payload is offset from the containing Decl AST node. + /// The source location points to the field name of the operand ("b" node) + /// of a field initialization expression (`.a = b`) + /// The Decl is determined contextually. + node_offset_field_name_init: i32, + /// The source location points to the pointer of a pointer deref expression, + /// found by taking this AST node index offset from the containing + /// Decl AST node, which points to a pointer deref AST node. Next, navigate + /// to the pointer expression. + /// The Decl is determined contextually. + node_offset_deref_ptr: i32, + /// The source location points to the assembly source code of an inline assembly + /// expression, found by taking this AST node index offset from the containing + /// Decl AST node, which points to inline assembly AST node. Next, navigate + /// to the asm template source code. + /// The Decl is determined contextually. + node_offset_asm_source: i32, + /// The source location points to the return type of an inline assembly + /// expression, found by taking this AST node index offset from the containing + /// Decl AST node, which points to inline assembly AST node. Next, navigate + /// to the return type expression. + /// The Decl is determined contextually. + node_offset_asm_ret_ty: i32, + /// The source location points to the condition expression of an if + /// expression, found by taking this AST node index offset from the containing + /// Decl AST node, which points to an if expression AST node. Next, navigate + /// to the condition expression. + /// The Decl is determined contextually. + node_offset_if_cond: i32, + /// The source location points to a binary expression, such as `a + b`, found + /// by taking this AST node index offset from the containing Decl AST node. + /// The Decl is determined contextually. + node_offset_bin_op: i32, + /// The source location points to the LHS of a binary expression, found + /// by taking this AST node index offset from the containing Decl AST node, + /// which points to a binary expression AST node. Next, navigate to the LHS. + /// The Decl is determined contextually. + node_offset_bin_lhs: i32, + /// The source location points to the RHS of a binary expression, found + /// by taking this AST node index offset from the containing Decl AST node, + /// which points to a binary expression AST node. Next, navigate to the RHS. + /// The Decl is determined contextually. + node_offset_bin_rhs: i32, + /// The source location points to the operand of a switch expression, found + /// by taking this AST node index offset from the containing Decl AST node, + /// which points to a switch expression AST node. Next, navigate to the operand. + /// The Decl is determined contextually. + node_offset_switch_operand: i32, + /// The source location points to the else/`_` prong of a switch expression, found + /// by taking this AST node index offset from the containing Decl AST node, + /// which points to a switch expression AST node. Next, navigate to the else/`_` prong. + /// The Decl is determined contextually. + node_offset_switch_special_prong: i32, + /// The source location points to all the ranges of a switch expression, found + /// by taking this AST node index offset from the containing Decl AST node, + /// which points to a switch expression AST node. Next, navigate to any of the + /// range nodes. The error applies to all of them. + /// The Decl is determined contextually. + node_offset_switch_range: i32, + /// The source location points to the capture of a switch_prong. + /// The Decl is determined contextually. + node_offset_switch_prong_capture: i32, + /// The source location points to the tag capture of a switch_prong. + /// The Decl is determined contextually. + node_offset_switch_prong_tag_capture: i32, + /// The source location points to the align expr of a function type + /// expression, found by taking this AST node index offset from the containing + /// Decl AST node, which points to a function type AST node. Next, navigate to + /// the calling convention node. + /// The Decl is determined contextually. + node_offset_fn_type_align: i32, + /// The source location points to the addrspace expr of a function type + /// expression, found by taking this AST node index offset from the containing + /// Decl AST node, which points to a function type AST node. Next, navigate to + /// the calling convention node. + /// The Decl is determined contextually. + node_offset_fn_type_addrspace: i32, + /// The source location points to the linksection expr of a function type + /// expression, found by taking this AST node index offset from the containing + /// Decl AST node, which points to a function type AST node. Next, navigate to + /// the calling convention node. + /// The Decl is determined contextually. + node_offset_fn_type_section: i32, + /// The source location points to the calling convention of a function type + /// expression, found by taking this AST node index offset from the containing + /// Decl AST node, which points to a function type AST node. Next, navigate to + /// the calling convention node. + /// The Decl is determined contextually. + node_offset_fn_type_cc: i32, + /// The source location points to the return type of a function type + /// expression, found by taking this AST node index offset from the containing + /// Decl AST node, which points to a function type AST node. Next, navigate to + /// the return type node. + /// The Decl is determined contextually. + node_offset_fn_type_ret_ty: i32, + node_offset_param: i32, + token_offset_param: i32, + /// The source location points to the type expression of an `anyframe->T` + /// expression, found by taking this AST node index offset from the containing + /// Decl AST node, which points to a `anyframe->T` expression AST node. Next, navigate + /// to the type expression. + /// The Decl is determined contextually. + node_offset_anyframe_type: i32, + /// The source location points to the string literal of `extern "foo"`, found + /// by taking this AST node index offset from the containing + /// Decl AST node, which points to a function prototype or variable declaration + /// expression AST node. Next, navigate to the string literal of the `extern "foo"`. + /// The Decl is determined contextually. + node_offset_lib_name: i32, + /// The source location points to the len expression of an `[N:S]T` + /// expression, found by taking this AST node index offset from the containing + /// Decl AST node, which points to an `[N:S]T` expression AST node. Next, navigate + /// to the len expression. + /// The Decl is determined contextually. + node_offset_array_type_len: i32, + /// The source location points to the sentinel expression of an `[N:S]T` + /// expression, found by taking this AST node index offset from the containing + /// Decl AST node, which points to an `[N:S]T` expression AST node. Next, navigate + /// to the sentinel expression. + /// The Decl is determined contextually. + node_offset_array_type_sentinel: i32, + /// The source location points to the elem expression of an `[N:S]T` + /// expression, found by taking this AST node index offset from the containing + /// Decl AST node, which points to an `[N:S]T` expression AST node. Next, navigate + /// to the elem expression. + /// The Decl is determined contextually. + node_offset_array_type_elem: i32, + /// The source location points to the operand of an unary expression. + /// The Decl is determined contextually. + node_offset_un_op: i32, + /// The source location points to the elem type of a pointer. + /// The Decl is determined contextually. + node_offset_ptr_elem: i32, + /// The source location points to the sentinel of a pointer. + /// The Decl is determined contextually. + node_offset_ptr_sentinel: i32, + /// The source location points to the align expr of a pointer. + /// The Decl is determined contextually. + node_offset_ptr_align: i32, + /// The source location points to the addrspace expr of a pointer. + /// The Decl is determined contextually. + node_offset_ptr_addrspace: i32, + /// The source location points to the bit-offset of a pointer. + /// The Decl is determined contextually. + node_offset_ptr_bitoffset: i32, + /// The source location points to the host size of a pointer. + /// The Decl is determined contextually. + node_offset_ptr_hostsize: i32, + /// The source location points to the tag type of an union or an enum. + /// The Decl is determined contextually. + node_offset_container_tag: i32, + /// The source location points to the default value of a field. + /// The Decl is determined contextually. + node_offset_field_default: i32, + /// The source location points to the type of an array or struct initializer. + /// The Decl is determined contextually. + node_offset_init_ty: i32, + /// The source location points to the LHS of an assignment. + /// The Decl is determined contextually. + node_offset_store_ptr: i32, + /// The source location points to the RHS of an assignment. + /// The Decl is determined contextually. + node_offset_store_operand: i32, + /// The source location points to the operand of a `return` statement, or + /// the `return` itself if there is no explicit operand. + /// The Decl is determined contextually. + node_offset_return_operand: i32, + /// The source location points to a for loop input. + /// The Decl is determined contextually. + for_input: struct { + /// Points to the for loop AST node. + for_node_offset: i32, + /// Picks one of the inputs from the condition. + input_index: u32, + }, + /// The source location points to one of the captures of a for loop, found + /// by taking this AST node index offset from the containing + /// Decl AST node, which points to one of the input nodes of a for loop. + /// Next, navigate to the corresponding capture. + /// The Decl is determined contextually. + for_capture_from_input: i32, + /// The source location points to the argument node of a function call. + call_arg: struct { + decl: DeclIndex, + /// Points to the function call AST node. + call_node_offset: i32, + /// The index of the argument the source location points to. + arg_index: u32, + }, + fn_proto_param: struct { + decl: DeclIndex, + /// Points to the function prototype AST node. + fn_proto_node_offset: i32, + /// The index of the parameter the source location points to. + param_index: u32, + }, + array_cat_lhs: ArrayCat, + array_cat_rhs: ArrayCat, + + const ArrayCat = struct { + /// Points to the array concat AST node. + array_cat_offset: i32, + /// The index of the element the source location points to. + elem_index: u32, + }; + + pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease; + + noinline fn nodeOffsetDebug(node_offset: i32) LazySrcLoc { + var result: LazySrcLoc = .{ .node_offset = .{ .x = node_offset } }; + result.node_offset.trace.addAddr(@returnAddress(), "init"); + return result; + } + + fn nodeOffsetRelease(node_offset: i32) LazySrcLoc { + return .{ .node_offset = .{ .x = node_offset } }; + } + + /// This wraps a simple integer in debug builds so that later on we can find out + /// where in semantic analysis the value got set. + pub const TracedOffset = struct { + x: i32, + trace: std.debug.Trace = .{}, + + const want_tracing = false; + }; +}; + const std = @import("std.zig"); const tokenizer = @import("zig/tokenizer.zig"); const assert = std.debug.assert; const Allocator = std.mem.Allocator; +/// Return a Formatter for a Zig identifier +pub fn fmtId(bytes: []const u8) std.fmt.Formatter(formatId) { + return .{ .data = bytes }; +} + +/// Print the string as a Zig identifier escaping it with @"" syntax if needed. +fn formatId( + bytes: []const u8, + comptime unused_format_string: []const u8, + options: std.fmt.FormatOptions, + writer: anytype, +) !void { + _ = unused_format_string; + if (isValidId(bytes)) { + return writer.writeAll(bytes); + } + try writer.writeAll("@\""); + try stringEscape(bytes, "", options, writer); + try writer.writeByte('"'); +} + +/// Return a Formatter for Zig Escapes of a double quoted string. +/// The format specifier must be one of: +/// * `{}` treats contents as a double-quoted string. +/// * `{'}` treats contents as a single-quoted string. +pub fn fmtEscapes(bytes: []const u8) std.fmt.Formatter(stringEscape) { + return .{ .data = bytes }; +} + +test "escape invalid identifiers" { + const expectFmt = std.testing.expectFmt; + try expectFmt("@\"while\"", "{}", .{fmtId("while")}); + try expectFmt("hello", "{}", .{fmtId("hello")}); + try expectFmt("@\"11\\\"23\"", "{}", .{fmtId("11\"23")}); + try expectFmt("@\"11\\x0f23\"", "{}", .{fmtId("11\x0F23")}); + try expectFmt("\\x0f", "{}", .{fmtEscapes("\x0f")}); + try expectFmt( + \\" \\ hi \x07 \x11 " derp \'" + , "\"{'}\"", .{fmtEscapes(" \\ hi \x07 \x11 \" derp '")}); + try expectFmt( + \\" \\ hi \x07 \x11 \" derp '" + , "\"{}\"", .{fmtEscapes(" \\ hi \x07 \x11 \" derp '")}); +} + +/// Print the string as escaped contents of a double quoted or single-quoted string. +/// Format `{}` treats contents as a double-quoted string. +/// Format `{'}` treats contents as a single-quoted string. +pub fn stringEscape( + bytes: []const u8, + comptime f: []const u8, + options: std.fmt.FormatOptions, + writer: anytype, +) !void { + _ = options; + for (bytes) |byte| switch (byte) { + '\n' => try writer.writeAll("\\n"), + '\r' => try writer.writeAll("\\r"), + '\t' => try writer.writeAll("\\t"), + '\\' => try writer.writeAll("\\\\"), + '"' => { + if (f.len == 1 and f[0] == '\'') { + try writer.writeByte('"'); + } else if (f.len == 0) { + try writer.writeAll("\\\""); + } else { + @compileError("expected {} or {'}, found {" ++ f ++ "}"); + } + }, + '\'' => { + if (f.len == 1 and f[0] == '\'') { + try writer.writeAll("\\'"); + } else if (f.len == 0) { + try writer.writeByte('\''); + } else { + @compileError("expected {} or {'}, found {" ++ f ++ "}"); + } + }, + ' ', '!', '#'...'&', '('...'[', ']'...'~' => try writer.writeByte(byte), + // Use hex escapes for rest any unprintable characters. + else => { + try writer.writeAll("\\x"); + try std.fmt.formatInt(byte, 16, .lower, .{ .width = 2, .fill = '0' }, writer); + }, + }; +} + +pub fn isValidId(bytes: []const u8) bool { + if (bytes.len == 0) return false; + if (std.mem.eql(u8, bytes, "_")) return false; + for (bytes, 0..) |c, i| { + switch (c) { + '_', 'a'...'z', 'A'...'Z' => {}, + '0'...'9' => if (i == 0) return false, + else => return false, + } + } + return std.zig.Token.getKeyword(bytes) == null; +} + +test isValidId { + try std.testing.expect(!isValidId("")); + try std.testing.expect(isValidId("foobar")); + try std.testing.expect(!isValidId("a b c")); + try std.testing.expect(!isValidId("3d")); + try std.testing.expect(!isValidId("enum")); + try std.testing.expect(isValidId("i386")); +} + +pub fn readSourceFileToEndAlloc( + allocator: Allocator, + input: std.fs.File, + size_hint: ?usize, +) ![:0]u8 { + const source_code = input.readToEndAllocOptions( + allocator, + max_src_size, + size_hint, + @alignOf(u16), + 0, + ) catch |err| switch (err) { + error.ConnectionResetByPeer => unreachable, + error.ConnectionTimedOut => unreachable, + error.NotOpenForReading => unreachable, + else => |e| return e, + }; + errdefer allocator.free(source_code); + + // Detect unsupported file types with their Byte Order Mark + const unsupported_boms = [_][]const u8{ + "\xff\xfe\x00\x00", // UTF-32 little endian + "\xfe\xff\x00\x00", // UTF-32 big endian + "\xfe\xff", // UTF-16 big endian + }; + for (unsupported_boms) |bom| { + if (std.mem.startsWith(u8, source_code, bom)) { + return error.UnsupportedEncoding; + } + } + + // If the file starts with a UTF-16 little endian BOM, translate it to UTF-8 + if (std.mem.startsWith(u8, source_code, "\xff\xfe")) { + const source_code_utf16_le = std.mem.bytesAsSlice(u16, source_code); + const source_code_utf8 = std.unicode.utf16LeToUtf8AllocZ(allocator, source_code_utf16_le) catch |err| switch (err) { + error.DanglingSurrogateHalf => error.UnsupportedEncoding, + error.ExpectedSecondSurrogateHalf => error.UnsupportedEncoding, + error.UnexpectedSecondSurrogateHalf => error.UnsupportedEncoding, + else => |e| return e, + }; + + allocator.free(source_code); + return source_code_utf8; + } + + return source_code; +} + +pub fn printAstErrorsToStderr(gpa: Allocator, tree: Ast, path: []const u8, color: Color) !void { + var wip_errors: std.zig.ErrorBundle.Wip = undefined; + try wip_errors.init(gpa); + defer wip_errors.deinit(); + + try putAstErrorsIntoBundle(gpa, tree, path, &wip_errors); + + var error_bundle = try wip_errors.toOwnedBundle(""); + defer error_bundle.deinit(gpa); + error_bundle.renderToStdErr(color.renderOptions()); +} + +pub fn putAstErrorsIntoBundle( + gpa: Allocator, + tree: Ast, + path: []const u8, + wip_errors: *std.zig.ErrorBundle.Wip, +) Allocator.Error!void { + var zir = try AstGen.generate(gpa, tree); + defer zir.deinit(gpa); + + try wip_errors.addZirErrorMessages(zir, tree, tree.source, path); +} + test { - @import("std").testing.refAllDecls(@This()); + _ = Ast; + _ = AstRlAnnotate; + _ = BuiltinFn; + _ = Client; + _ = ErrorBundle; + _ = Server; + _ = number_literal; + _ = primitives; + _ = string_literal; + _ = system; } diff --git a/lib/std/zig/Ast.zig b/lib/std/zig/Ast.zig index e358ee80d684..6f4afbbe4fd0 100644 --- a/lib/std/zig/Ast.zig +++ b/lib/std/zig/Ast.zig @@ -32,6 +32,12 @@ pub const Location = struct { line_end: usize, }; +pub const Span = struct { + start: u32, + end: u32, + main: u32, +}; + pub fn deinit(tree: *Ast, gpa: Allocator) void { tree.tokens.deinit(gpa); tree.nodes.deinit(gpa); @@ -105,9 +111,7 @@ pub fn parse(gpa: Allocator, source: [:0]const u8, mode: Mode) Allocator.Error!A }; } -/// `gpa` is used for allocating the resulting formatted source code, as well as -/// for allocating extra stack memory if needed, because this function utilizes recursion. -/// Note: that's not actually true yet, see https://github.com/ziglang/zig/issues/1006. +/// `gpa` is used for allocating the resulting formatted source code. /// Caller owns the returned slice of bytes, allocated with `gpa`. pub fn render(tree: Ast, gpa: Allocator) RenderError![]u8 { var buffer = std.ArrayList(u8).init(gpa); @@ -3535,6 +3539,39 @@ pub const Node = struct { }; }; +pub fn nodeToSpan(tree: *const Ast, node: u32) Span { + return tokensToSpan( + tree, + tree.firstToken(node), + tree.lastToken(node), + tree.nodes.items(.main_token)[node], + ); +} + +pub fn tokenToSpan(tree: *const Ast, token: Ast.TokenIndex) Span { + return tokensToSpan(tree, token, token, token); +} + +pub fn tokensToSpan(tree: *const Ast, start: Ast.TokenIndex, end: Ast.TokenIndex, main: Ast.TokenIndex) Span { + const token_starts = tree.tokens.items(.start); + var start_tok = start; + var end_tok = end; + + if (tree.tokensOnSameLine(start, end)) { + // do nothing + } else if (tree.tokensOnSameLine(start, main)) { + end_tok = main; + } else if (tree.tokensOnSameLine(main, end)) { + start_tok = main; + } else { + start_tok = main; + end_tok = main; + } + const start_off = token_starts[start_tok]; + const end_off = token_starts[end_tok] + @as(u32, @intCast(tree.tokenSlice(end_tok).len)); + return Span{ .start = start_off, .end = end_off, .main = token_starts[main] }; +} + const std = @import("../std.zig"); const assert = std.debug.assert; const testing = std.testing; @@ -3546,5 +3583,6 @@ const Parse = @import("Parse.zig"); const private_render = @import("./render.zig"); test { - testing.refAllDecls(@This()); + _ = Parse; + _ = private_render; } diff --git a/src/AstGen.zig b/lib/std/zig/AstGen.zig similarity index 99% rename from src/AstGen.zig rename to lib/std/zig/AstGen.zig index 375dafe8801d..20b1077420ff 100644 --- a/src/AstGen.zig +++ b/lib/std/zig/AstGen.zig @@ -12,7 +12,7 @@ const StringIndexContext = std.hash_map.StringIndexContext; const isPrimitive = std.zig.primitives.isPrimitive; -const Zir = @import("Zir.zig"); +const Zir = std.zig.Zir; const BuiltinFn = std.zig.BuiltinFn; const AstRlAnnotate = std.zig.AstRlAnnotate; diff --git a/lib/std/zig/ErrorBundle.zig b/lib/std/zig/ErrorBundle.zig index ff47e3794b2a..013d447ab116 100644 --- a/lib/std/zig/ErrorBundle.zig +++ b/lib/std/zig/ErrorBundle.zig @@ -459,6 +459,90 @@ pub const Wip = struct { return @intCast(wip.extra.items.len - notes_len); } + pub fn addZirErrorMessages( + eb: *ErrorBundle.Wip, + zir: std.zig.Zir, + tree: std.zig.Ast, + source: [:0]const u8, + src_path: []const u8, + ) !void { + const Zir = std.zig.Zir; + const payload_index = zir.extra[@intFromEnum(Zir.ExtraIndex.compile_errors)]; + assert(payload_index != 0); + + const header = zir.extraData(Zir.Inst.CompileErrors, payload_index); + const items_len = header.data.items_len; + var extra_index = header.end; + for (0..items_len) |_| { + const item = zir.extraData(Zir.Inst.CompileErrors.Item, extra_index); + extra_index = item.end; + const err_span = blk: { + if (item.data.node != 0) { + break :blk tree.nodeToSpan(item.data.node); + } + const token_starts = tree.tokens.items(.start); + const start = token_starts[item.data.token] + item.data.byte_offset; + const end = start + @as(u32, @intCast(tree.tokenSlice(item.data.token).len)) - item.data.byte_offset; + break :blk std.zig.Ast.Span{ .start = start, .end = end, .main = start }; + }; + const err_loc = std.zig.findLineColumn(source, err_span.main); + + { + const msg = zir.nullTerminatedString(item.data.msg); + try eb.addRootErrorMessage(.{ + .msg = try eb.addString(msg), + .src_loc = try eb.addSourceLocation(.{ + .src_path = try eb.addString(src_path), + .span_start = err_span.start, + .span_main = err_span.main, + .span_end = err_span.end, + .line = @intCast(err_loc.line), + .column = @intCast(err_loc.column), + .source_line = try eb.addString(err_loc.source_line), + }), + .notes_len = item.data.notesLen(zir), + }); + } + + if (item.data.notes != 0) { + const notes_start = try eb.reserveNotes(item.data.notes); + const block = zir.extraData(Zir.Inst.Block, item.data.notes); + const body = zir.extra[block.end..][0..block.data.body_len]; + for (notes_start.., body) |note_i, body_elem| { + const note_item = zir.extraData(Zir.Inst.CompileErrors.Item, body_elem); + const msg = zir.nullTerminatedString(note_item.data.msg); + const span = blk: { + if (note_item.data.node != 0) { + break :blk tree.nodeToSpan(note_item.data.node); + } + const token_starts = tree.tokens.items(.start); + const start = token_starts[note_item.data.token] + note_item.data.byte_offset; + const end = start + @as(u32, @intCast(tree.tokenSlice(note_item.data.token).len)) - item.data.byte_offset; + break :blk std.zig.Ast.Span{ .start = start, .end = end, .main = start }; + }; + const loc = std.zig.findLineColumn(source, span.main); + + eb.extra.items[note_i] = @intFromEnum(try eb.addErrorMessage(.{ + .msg = try eb.addString(msg), + .src_loc = try eb.addSourceLocation(.{ + .src_path = try eb.addString(src_path), + .span_start = span.start, + .span_main = span.main, + .span_end = span.end, + .line = @intCast(loc.line), + .column = @intCast(loc.column), + .source_line = if (loc.eql(err_loc)) + 0 + else + try eb.addString(loc.source_line), + }), + .notes_len = 0, // TODO rework this function to be recursive + })); + } + } + } + } + fn addOtherMessage(wip: *Wip, other: ErrorBundle, msg_index: MessageIndex) !MessageIndex { const other_msg = other.getErrorMessage(msg_index); const src_loc = try wip.addOtherSourceLocation(other, other_msg.src_loc); diff --git a/src/Zir.zig b/lib/std/zig/Zir.zig similarity index 96% rename from src/Zir.zig rename to lib/std/zig/Zir.zig index 3e6ffcc3257d..117212ccbbdc 100644 --- a/src/Zir.zig +++ b/lib/std/zig/Zir.zig @@ -19,10 +19,8 @@ const BigIntConst = std.math.big.int.Const; const BigIntMutable = std.math.big.int.Mutable; const Ast = std.zig.Ast; -const InternPool = @import("InternPool.zig"); const Zir = @This(); -const Module = @import("Module.zig"); -const LazySrcLoc = Module.LazySrcLoc; +const LazySrcLoc = std.zig.LazySrcLoc; instructions: std.MultiArrayList(Inst).Slice, /// In order to store references to strings in fewer bytes, we copy all @@ -2093,9 +2091,11 @@ pub const Inst = struct { /// ZIR is structured so that the outermost "main" struct of any file /// is always at index 0. main_struct_inst = 0, - ref_start_index = InternPool.static_len, + ref_start_index = static_len, _, + pub const static_len = 84; + pub fn toRef(i: Index) Inst.Ref { return @enumFromInt(@intFromEnum(Index.ref_start_index) + @intFromEnum(i)); } @@ -2109,7 +2109,7 @@ pub const Inst = struct { /// ZIR is structured so that the outermost "main" struct of any file /// is always at index 0. main_struct_inst = 0, - ref_start_index = InternPool.static_len, + ref_start_index = Index.static_len, none = std.math.maxInt(u32), _, @@ -2127,97 +2127,98 @@ pub const Inst = struct { /// The tag type is specified so that it is safe to bitcast between `[]u32` /// and `[]Ref`. pub const Ref = enum(u32) { - u0_type = @intFromEnum(InternPool.Index.u0_type), - i0_type = @intFromEnum(InternPool.Index.i0_type), - u1_type = @intFromEnum(InternPool.Index.u1_type), - u8_type = @intFromEnum(InternPool.Index.u8_type), - i8_type = @intFromEnum(InternPool.Index.i8_type), - u16_type = @intFromEnum(InternPool.Index.u16_type), - i16_type = @intFromEnum(InternPool.Index.i16_type), - u29_type = @intFromEnum(InternPool.Index.u29_type), - u32_type = @intFromEnum(InternPool.Index.u32_type), - i32_type = @intFromEnum(InternPool.Index.i32_type), - u64_type = @intFromEnum(InternPool.Index.u64_type), - i64_type = @intFromEnum(InternPool.Index.i64_type), - u80_type = @intFromEnum(InternPool.Index.u80_type), - u128_type = @intFromEnum(InternPool.Index.u128_type), - i128_type = @intFromEnum(InternPool.Index.i128_type), - usize_type = @intFromEnum(InternPool.Index.usize_type), - isize_type = @intFromEnum(InternPool.Index.isize_type), - c_char_type = @intFromEnum(InternPool.Index.c_char_type), - c_short_type = @intFromEnum(InternPool.Index.c_short_type), - c_ushort_type = @intFromEnum(InternPool.Index.c_ushort_type), - c_int_type = @intFromEnum(InternPool.Index.c_int_type), - c_uint_type = @intFromEnum(InternPool.Index.c_uint_type), - c_long_type = @intFromEnum(InternPool.Index.c_long_type), - c_ulong_type = @intFromEnum(InternPool.Index.c_ulong_type), - c_longlong_type = @intFromEnum(InternPool.Index.c_longlong_type), - c_ulonglong_type = @intFromEnum(InternPool.Index.c_ulonglong_type), - c_longdouble_type = @intFromEnum(InternPool.Index.c_longdouble_type), - f16_type = @intFromEnum(InternPool.Index.f16_type), - f32_type = @intFromEnum(InternPool.Index.f32_type), - f64_type = @intFromEnum(InternPool.Index.f64_type), - f80_type = @intFromEnum(InternPool.Index.f80_type), - f128_type = @intFromEnum(InternPool.Index.f128_type), - anyopaque_type = @intFromEnum(InternPool.Index.anyopaque_type), - bool_type = @intFromEnum(InternPool.Index.bool_type), - void_type = @intFromEnum(InternPool.Index.void_type), - type_type = @intFromEnum(InternPool.Index.type_type), - anyerror_type = @intFromEnum(InternPool.Index.anyerror_type), - comptime_int_type = @intFromEnum(InternPool.Index.comptime_int_type), - comptime_float_type = @intFromEnum(InternPool.Index.comptime_float_type), - noreturn_type = @intFromEnum(InternPool.Index.noreturn_type), - anyframe_type = @intFromEnum(InternPool.Index.anyframe_type), - null_type = @intFromEnum(InternPool.Index.null_type), - undefined_type = @intFromEnum(InternPool.Index.undefined_type), - enum_literal_type = @intFromEnum(InternPool.Index.enum_literal_type), - atomic_order_type = @intFromEnum(InternPool.Index.atomic_order_type), - atomic_rmw_op_type = @intFromEnum(InternPool.Index.atomic_rmw_op_type), - calling_convention_type = @intFromEnum(InternPool.Index.calling_convention_type), - address_space_type = @intFromEnum(InternPool.Index.address_space_type), - float_mode_type = @intFromEnum(InternPool.Index.float_mode_type), - reduce_op_type = @intFromEnum(InternPool.Index.reduce_op_type), - call_modifier_type = @intFromEnum(InternPool.Index.call_modifier_type), - prefetch_options_type = @intFromEnum(InternPool.Index.prefetch_options_type), - export_options_type = @intFromEnum(InternPool.Index.export_options_type), - extern_options_type = @intFromEnum(InternPool.Index.extern_options_type), - type_info_type = @intFromEnum(InternPool.Index.type_info_type), - manyptr_u8_type = @intFromEnum(InternPool.Index.manyptr_u8_type), - manyptr_const_u8_type = @intFromEnum(InternPool.Index.manyptr_const_u8_type), - manyptr_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.manyptr_const_u8_sentinel_0_type), - single_const_pointer_to_comptime_int_type = @intFromEnum(InternPool.Index.single_const_pointer_to_comptime_int_type), - slice_const_u8_type = @intFromEnum(InternPool.Index.slice_const_u8_type), - slice_const_u8_sentinel_0_type = @intFromEnum(InternPool.Index.slice_const_u8_sentinel_0_type), - optional_noreturn_type = @intFromEnum(InternPool.Index.optional_noreturn_type), - anyerror_void_error_union_type = @intFromEnum(InternPool.Index.anyerror_void_error_union_type), - adhoc_inferred_error_set_type = @intFromEnum(InternPool.Index.adhoc_inferred_error_set_type), - generic_poison_type = @intFromEnum(InternPool.Index.generic_poison_type), - empty_struct_type = @intFromEnum(InternPool.Index.empty_struct_type), - undef = @intFromEnum(InternPool.Index.undef), - zero = @intFromEnum(InternPool.Index.zero), - zero_usize = @intFromEnum(InternPool.Index.zero_usize), - zero_u8 = @intFromEnum(InternPool.Index.zero_u8), - one = @intFromEnum(InternPool.Index.one), - one_usize = @intFromEnum(InternPool.Index.one_usize), - one_u8 = @intFromEnum(InternPool.Index.one_u8), - four_u8 = @intFromEnum(InternPool.Index.four_u8), - negative_one = @intFromEnum(InternPool.Index.negative_one), - calling_convention_c = @intFromEnum(InternPool.Index.calling_convention_c), - calling_convention_inline = @intFromEnum(InternPool.Index.calling_convention_inline), - void_value = @intFromEnum(InternPool.Index.void_value), - unreachable_value = @intFromEnum(InternPool.Index.unreachable_value), - null_value = @intFromEnum(InternPool.Index.null_value), - bool_true = @intFromEnum(InternPool.Index.bool_true), - bool_false = @intFromEnum(InternPool.Index.bool_false), - empty_struct = @intFromEnum(InternPool.Index.empty_struct), - generic_poison = @intFromEnum(InternPool.Index.generic_poison), + u0_type, + i0_type, + u1_type, + u8_type, + i8_type, + u16_type, + i16_type, + u29_type, + u32_type, + i32_type, + u64_type, + i64_type, + u80_type, + u128_type, + i128_type, + usize_type, + isize_type, + c_char_type, + c_short_type, + c_ushort_type, + c_int_type, + c_uint_type, + c_long_type, + c_ulong_type, + c_longlong_type, + c_ulonglong_type, + c_longdouble_type, + f16_type, + f32_type, + f64_type, + f80_type, + f128_type, + anyopaque_type, + bool_type, + void_type, + type_type, + anyerror_type, + comptime_int_type, + comptime_float_type, + noreturn_type, + anyframe_type, + null_type, + undefined_type, + enum_literal_type, + atomic_order_type, + atomic_rmw_op_type, + calling_convention_type, + address_space_type, + float_mode_type, + reduce_op_type, + call_modifier_type, + prefetch_options_type, + export_options_type, + extern_options_type, + type_info_type, + manyptr_u8_type, + manyptr_const_u8_type, + manyptr_const_u8_sentinel_0_type, + single_const_pointer_to_comptime_int_type, + slice_const_u8_type, + slice_const_u8_sentinel_0_type, + optional_noreturn_type, + anyerror_void_error_union_type, + adhoc_inferred_error_set_type, + generic_poison_type, + empty_struct_type, + undef, + zero, + zero_usize, + zero_u8, + one, + one_usize, + one_u8, + four_u8, + negative_one, + calling_convention_c, + calling_convention_inline, + void_value, + unreachable_value, + null_value, + bool_true, + bool_false, + empty_struct, + generic_poison, /// This tag is here to match Air and InternPool, however it is unused /// for ZIR purposes. - var_args_param_type = @intFromEnum(InternPool.Index.var_args_param_type), + var_args_param_type = std.math.maxInt(u32) - 1, /// This Ref does not correspond to any ZIR instruction or constant /// value and may instead be used as a sentinel to indicate null. - none = @intFromEnum(InternPool.Index.none), + none = std.math.maxInt(u32), + _, pub fn toIndex(inst: Ref) ?Index { diff --git a/lib/std/zig/fmt.zig b/lib/std/zig/fmt.zig deleted file mode 100644 index 5375b9302525..000000000000 --- a/lib/std/zig/fmt.zig +++ /dev/null @@ -1,110 +0,0 @@ -const std = @import("std"); -const mem = std.mem; - -/// Print the string as a Zig identifier escaping it with @"" syntax if needed. -fn formatId( - bytes: []const u8, - comptime fmt: []const u8, - options: std.fmt.FormatOptions, - writer: anytype, -) !void { - _ = fmt; - if (isValidId(bytes)) { - return writer.writeAll(bytes); - } - try writer.writeAll("@\""); - try stringEscape(bytes, "", options, writer); - try writer.writeByte('"'); -} - -/// Return a Formatter for a Zig identifier -pub fn fmtId(bytes: []const u8) std.fmt.Formatter(formatId) { - return .{ .data = bytes }; -} - -pub fn isValidId(bytes: []const u8) bool { - if (bytes.len == 0) return false; - if (mem.eql(u8, bytes, "_")) return false; - for (bytes, 0..) |c, i| { - switch (c) { - '_', 'a'...'z', 'A'...'Z' => {}, - '0'...'9' => if (i == 0) return false, - else => return false, - } - } - return std.zig.Token.getKeyword(bytes) == null; -} - -test "isValidId" { - try std.testing.expect(!isValidId("")); - try std.testing.expect(isValidId("foobar")); - try std.testing.expect(!isValidId("a b c")); - try std.testing.expect(!isValidId("3d")); - try std.testing.expect(!isValidId("enum")); - try std.testing.expect(isValidId("i386")); -} - -/// Print the string as escaped contents of a double quoted or single-quoted string. -/// Format `{}` treats contents as a double-quoted string. -/// Format `{'}` treats contents as a single-quoted string. -pub fn stringEscape( - bytes: []const u8, - comptime fmt: []const u8, - options: std.fmt.FormatOptions, - writer: anytype, -) !void { - _ = options; - for (bytes) |byte| switch (byte) { - '\n' => try writer.writeAll("\\n"), - '\r' => try writer.writeAll("\\r"), - '\t' => try writer.writeAll("\\t"), - '\\' => try writer.writeAll("\\\\"), - '"' => { - if (fmt.len == 1 and fmt[0] == '\'') { - try writer.writeByte('"'); - } else if (fmt.len == 0) { - try writer.writeAll("\\\""); - } else { - @compileError("expected {} or {'}, found {" ++ fmt ++ "}"); - } - }, - '\'' => { - if (fmt.len == 1 and fmt[0] == '\'') { - try writer.writeAll("\\'"); - } else if (fmt.len == 0) { - try writer.writeByte('\''); - } else { - @compileError("expected {} or {'}, found {" ++ fmt ++ "}"); - } - }, - ' ', '!', '#'...'&', '('...'[', ']'...'~' => try writer.writeByte(byte), - // Use hex escapes for rest any unprintable characters. - else => { - try writer.writeAll("\\x"); - try std.fmt.formatInt(byte, 16, .lower, .{ .width = 2, .fill = '0' }, writer); - }, - }; -} - -/// Return a Formatter for Zig Escapes of a double quoted string. -/// The format specifier must be one of: -/// * `{}` treats contents as a double-quoted string. -/// * `{'}` treats contents as a single-quoted string. -pub fn fmtEscapes(bytes: []const u8) std.fmt.Formatter(stringEscape) { - return .{ .data = bytes }; -} - -test "escape invalid identifiers" { - const expectFmt = std.testing.expectFmt; - try expectFmt("@\"while\"", "{}", .{fmtId("while")}); - try expectFmt("hello", "{}", .{fmtId("hello")}); - try expectFmt("@\"11\\\"23\"", "{}", .{fmtId("11\"23")}); - try expectFmt("@\"11\\x0f23\"", "{}", .{fmtId("11\x0F23")}); - try expectFmt("\\x0f", "{}", .{fmtEscapes("\x0f")}); - try expectFmt( - \\" \\ hi \x07 \x11 " derp \'" - , "\"{'}\"", .{fmtEscapes(" \\ hi \x07 \x11 \" derp '")}); - try expectFmt( - \\" \\ hi \x07 \x11 \" derp '" - , "\"{}\"", .{fmtEscapes(" \\ hi \x07 \x11 \" derp '")}); -} diff --git a/src/Autodoc.zig b/src/Autodoc.zig index 6ede3637f8e9..f321fadbb79a 100644 --- a/src/Autodoc.zig +++ b/src/Autodoc.zig @@ -9,7 +9,7 @@ const File = Zcu.File; const Module = @import("Package.zig").Module; const Tokenizer = std.zig.Tokenizer; const InternPool = @import("InternPool.zig"); -const Zir = @import("Zir.zig"); +const Zir = std.zig.Zir; const Ref = Zir.Inst.Ref; const log = std.log.scoped(.autodoc); const renderer = @import("autodoc/render_source.zig"); diff --git a/src/Builtin.zig b/src/Builtin.zig index fb0c1e949074..5c8577f4cbab 100644 --- a/src/Builtin.zig +++ b/src/Builtin.zig @@ -296,7 +296,7 @@ const Allocator = std.mem.Allocator; const build_options = @import("build_options"); const Module = @import("Package/Module.zig"); const assert = std.debug.assert; -const AstGen = @import("AstGen.zig"); +const AstGen = std.zig.AstGen; const File = @import("Module.zig").File; const Compilation = @import("Compilation.zig"); const log = std.log.scoped(.builtin); diff --git a/src/Compilation.zig b/src/Compilation.zig index 5fa93fa677cb..4f4c5f46ef37 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -35,7 +35,7 @@ const InternPool = @import("InternPool.zig"); const Cache = std.Build.Cache; const c_codegen = @import("codegen/c.zig"); const libtsan = @import("libtsan.zig"); -const Zir = @import("Zir.zig"); +const Zir = std.zig.Zir; const Autodoc = @import("Autodoc.zig"); const resinator = @import("resinator.zig"); const Builtin = @import("Builtin.zig"); @@ -3322,85 +3322,10 @@ pub fn addZirErrorMessages(eb: *ErrorBundle.Wip, file: *Module.File) !void { assert(file.zir_loaded); assert(file.tree_loaded); assert(file.source_loaded); - const payload_index = file.zir.extra[@intFromEnum(Zir.ExtraIndex.compile_errors)]; - assert(payload_index != 0); const gpa = eb.gpa; - - const header = file.zir.extraData(Zir.Inst.CompileErrors, payload_index); - const items_len = header.data.items_len; - var extra_index = header.end; - for (0..items_len) |_| { - const item = file.zir.extraData(Zir.Inst.CompileErrors.Item, extra_index); - extra_index = item.end; - const err_span = blk: { - if (item.data.node != 0) { - break :blk Module.SrcLoc.nodeToSpan(&file.tree, item.data.node); - } - const token_starts = file.tree.tokens.items(.start); - const start = token_starts[item.data.token] + item.data.byte_offset; - const end = start + @as(u32, @intCast(file.tree.tokenSlice(item.data.token).len)) - item.data.byte_offset; - break :blk Module.SrcLoc.Span{ .start = start, .end = end, .main = start }; - }; - const err_loc = std.zig.findLineColumn(file.source, err_span.main); - - { - const msg = file.zir.nullTerminatedString(item.data.msg); - const src_path = try file.fullPath(gpa); - defer gpa.free(src_path); - try eb.addRootErrorMessage(.{ - .msg = try eb.addString(msg), - .src_loc = try eb.addSourceLocation(.{ - .src_path = try eb.addString(src_path), - .span_start = err_span.start, - .span_main = err_span.main, - .span_end = err_span.end, - .line = @as(u32, @intCast(err_loc.line)), - .column = @as(u32, @intCast(err_loc.column)), - .source_line = try eb.addString(err_loc.source_line), - }), - .notes_len = item.data.notesLen(file.zir), - }); - } - - if (item.data.notes != 0) { - const notes_start = try eb.reserveNotes(item.data.notes); - const block = file.zir.extraData(Zir.Inst.Block, item.data.notes); - const body = file.zir.extra[block.end..][0..block.data.body_len]; - for (notes_start.., body) |note_i, body_elem| { - const note_item = file.zir.extraData(Zir.Inst.CompileErrors.Item, body_elem); - const msg = file.zir.nullTerminatedString(note_item.data.msg); - const span = blk: { - if (note_item.data.node != 0) { - break :blk Module.SrcLoc.nodeToSpan(&file.tree, note_item.data.node); - } - const token_starts = file.tree.tokens.items(.start); - const start = token_starts[note_item.data.token] + note_item.data.byte_offset; - const end = start + @as(u32, @intCast(file.tree.tokenSlice(note_item.data.token).len)) - item.data.byte_offset; - break :blk Module.SrcLoc.Span{ .start = start, .end = end, .main = start }; - }; - const loc = std.zig.findLineColumn(file.source, span.main); - const src_path = try file.fullPath(gpa); - defer gpa.free(src_path); - - eb.extra.items[note_i] = @intFromEnum(try eb.addErrorMessage(.{ - .msg = try eb.addString(msg), - .src_loc = try eb.addSourceLocation(.{ - .src_path = try eb.addString(src_path), - .span_start = span.start, - .span_main = span.main, - .span_end = span.end, - .line = @as(u32, @intCast(loc.line)), - .column = @as(u32, @intCast(loc.column)), - .source_line = if (loc.eql(err_loc)) - 0 - else - try eb.addString(loc.source_line), - }), - .notes_len = 0, // TODO rework this function to be recursive - })); - } - } - } + const src_path = try file.fullPath(gpa); + defer gpa.free(src_path); + return eb.addZirErrorMessages(file.zir, file.tree, file.source, src_path); } pub fn performAllTheWork( diff --git a/src/InternPool.zig b/src/InternPool.zig index 46676097bf2a..5ff179cb7441 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -338,7 +338,7 @@ const Hash = std.hash.Wyhash; const InternPool = @This(); const Module = @import("Module.zig"); const Zcu = Module; -const Zir = @import("Zir.zig"); +const Zir = std.zig.Zir; const KeyAdapter = struct { intern_pool: *const InternPool, @@ -383,27 +383,8 @@ pub const RuntimeIndex = enum(u32) { } }; -pub const DeclIndex = enum(u32) { - _, - - pub fn toOptional(i: DeclIndex) OptionalDeclIndex { - return @enumFromInt(@intFromEnum(i)); - } -}; - -pub const OptionalDeclIndex = enum(u32) { - none = std.math.maxInt(u32), - _, - - pub fn init(oi: ?DeclIndex) OptionalDeclIndex { - return @enumFromInt(@intFromEnum(oi orelse return .none)); - } - - pub fn unwrap(oi: OptionalDeclIndex) ?DeclIndex { - if (oi == .none) return null; - return @enumFromInt(@intFromEnum(oi)); - } -}; +pub const DeclIndex = std.zig.DeclIndex; +pub const OptionalDeclIndex = std.zig.OptionalDeclIndex; pub const NamespaceIndex = enum(u32) { _, @@ -2877,7 +2858,7 @@ pub const static_keys = [_]Key{ /// This is specified with an integer literal and a corresponding comptime /// assert below to break an unfortunate and arguably incorrect dependency loop /// when compiling. -pub const static_len = 84; +pub const static_len = Zir.Inst.Index.static_len; comptime { //@compileLog(static_keys.len); assert(static_len == static_keys.len); diff --git a/src/Module.zig b/src/Module.zig index a4cedd9077e3..ad6487b1eb0f 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -13,6 +13,7 @@ const BigIntConst = std.math.big.int.Const; const BigIntMutable = std.math.big.int.Mutable; const Target = std.Target; const Ast = std.zig.Ast; +const LazySrcLoc = std.zig.LazySrcLoc; /// Deprecated, use `Zcu`. const Module = Zcu; @@ -25,9 +26,9 @@ const TypedValue = @import("TypedValue.zig"); const Package = @import("Package.zig"); const link = @import("link.zig"); const Air = @import("Air.zig"); -const Zir = @import("Zir.zig"); +const Zir = std.zig.Zir; const trace = @import("tracy.zig").trace; -const AstGen = @import("AstGen.zig"); +const AstGen = std.zig.AstGen; const Sema = @import("Sema.zig"); const target_util = @import("target.zig"); const build_options = @import("build_options"); @@ -664,6 +665,101 @@ pub const Decl = struct { if (decl.alignment != .none) return decl.alignment; return decl.ty.abiAlignment(zcu); } + + /// Upgrade a `LazySrcLoc` to a `SrcLoc` based on the `Decl` provided. + pub fn toSrcLoc(decl: *Decl, lazy: LazySrcLoc, mod: *Module) SrcLoc { + return switch (lazy) { + .unneeded, + .entire_file, + .byte_abs, + .token_abs, + .node_abs, + => .{ + .file_scope = decl.getFileScope(mod), + .parent_decl_node = 0, + .lazy = lazy, + }, + + .byte_offset, + .token_offset, + .node_offset, + .node_offset_main_token, + .node_offset_initializer, + .node_offset_var_decl_ty, + .node_offset_var_decl_align, + .node_offset_var_decl_section, + .node_offset_var_decl_addrspace, + .node_offset_var_decl_init, + .node_offset_builtin_call_arg0, + .node_offset_builtin_call_arg1, + .node_offset_builtin_call_arg2, + .node_offset_builtin_call_arg3, + .node_offset_builtin_call_arg4, + .node_offset_builtin_call_arg5, + .node_offset_ptrcast_operand, + .node_offset_array_access_index, + .node_offset_slice_ptr, + .node_offset_slice_start, + .node_offset_slice_end, + .node_offset_slice_sentinel, + .node_offset_call_func, + .node_offset_field_name, + .node_offset_field_name_init, + .node_offset_deref_ptr, + .node_offset_asm_source, + .node_offset_asm_ret_ty, + .node_offset_if_cond, + .node_offset_bin_op, + .node_offset_bin_lhs, + .node_offset_bin_rhs, + .node_offset_switch_operand, + .node_offset_switch_special_prong, + .node_offset_switch_range, + .node_offset_switch_prong_capture, + .node_offset_switch_prong_tag_capture, + .node_offset_fn_type_align, + .node_offset_fn_type_addrspace, + .node_offset_fn_type_section, + .node_offset_fn_type_cc, + .node_offset_fn_type_ret_ty, + .node_offset_param, + .token_offset_param, + .node_offset_anyframe_type, + .node_offset_lib_name, + .node_offset_array_type_len, + .node_offset_array_type_sentinel, + .node_offset_array_type_elem, + .node_offset_un_op, + .node_offset_ptr_elem, + .node_offset_ptr_sentinel, + .node_offset_ptr_align, + .node_offset_ptr_addrspace, + .node_offset_ptr_bitoffset, + .node_offset_ptr_hostsize, + .node_offset_container_tag, + .node_offset_field_default, + .node_offset_init_ty, + .node_offset_store_ptr, + .node_offset_store_operand, + .node_offset_return_operand, + .for_input, + .for_capture_from_input, + .array_cat_lhs, + .array_cat_rhs, + => .{ + .file_scope = decl.getFileScope(mod), + .parent_decl_node = decl.src_node, + .lazy = lazy, + }, + inline .call_arg, + .fn_proto_param, + => |x| .{ + .file_scope = decl.getFileScope(mod), + .parent_decl_node = mod.declPtr(x.decl).src_node, + .lazy = lazy, + }, + }; + } }; /// This state is attached to every Decl when Module emit_h is non-null. @@ -1159,11 +1255,7 @@ pub const SrcLoc = struct { return @bitCast(offset + @as(i32, @bitCast(src_loc.parent_decl_node))); } - pub const Span = struct { - start: u32, - end: u32, - main: u32, - }; + pub const Span = Ast.Span; pub fn span(src_loc: SrcLoc, gpa: Allocator) !Span { switch (src_loc.lazy) { @@ -1180,7 +1272,7 @@ pub const SrcLoc = struct { }, .node_abs => |node| { const tree = try src_loc.file_scope.getTree(gpa); - return nodeToSpan(tree, node); + return tree.nodeToSpan(node); }, .byte_offset => |byte_off| { const tree = try src_loc.file_scope.getTree(gpa); @@ -1201,25 +1293,24 @@ pub const SrcLoc = struct { const tree = try src_loc.file_scope.getTree(gpa); const node = src_loc.declRelativeToNodeIndex(node_off); assert(src_loc.file_scope.tree_loaded); - return nodeToSpan(tree, node); + return tree.nodeToSpan(node); }, .node_offset_main_token => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); const node = src_loc.declRelativeToNodeIndex(node_off); const main_token = tree.nodes.items(.main_token)[node]; - return tokensToSpan(tree, main_token, main_token, main_token); + return tree.tokensToSpan(main_token, main_token, main_token); }, .node_offset_bin_op => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); const node = src_loc.declRelativeToNodeIndex(node_off); assert(src_loc.file_scope.tree_loaded); - return nodeToSpan(tree, node); + return tree.nodeToSpan(node); }, .node_offset_initializer => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); const node = src_loc.declRelativeToNodeIndex(node_off); - return tokensToSpan( - tree, + return tree.tokensToSpan( tree.firstToken(node) - 3, tree.lastToken(node), tree.nodes.items(.main_token)[node] - 2, @@ -1237,12 +1328,12 @@ pub const SrcLoc = struct { => tree.fullVarDecl(node).?, .@"usingnamespace" => { const node_data = tree.nodes.items(.data); - return nodeToSpan(tree, node_data[node].lhs); + return tree.nodeToSpan(node_data[node].lhs); }, else => unreachable, }; if (full.ast.type_node != 0) { - return nodeToSpan(tree, full.ast.type_node); + return tree.nodeToSpan(full.ast.type_node); } const tok_index = full.ast.mut_token + 1; // the name token const start = tree.tokens.items(.start)[tok_index]; @@ -1253,25 +1344,25 @@ pub const SrcLoc = struct { const tree = try src_loc.file_scope.getTree(gpa); const node = src_loc.declRelativeToNodeIndex(node_off); const full = tree.fullVarDecl(node).?; - return nodeToSpan(tree, full.ast.align_node); + return tree.nodeToSpan(full.ast.align_node); }, .node_offset_var_decl_section => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); const node = src_loc.declRelativeToNodeIndex(node_off); const full = tree.fullVarDecl(node).?; - return nodeToSpan(tree, full.ast.section_node); + return tree.nodeToSpan(full.ast.section_node); }, .node_offset_var_decl_addrspace => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); const node = src_loc.declRelativeToNodeIndex(node_off); const full = tree.fullVarDecl(node).?; - return nodeToSpan(tree, full.ast.addrspace_node); + return tree.nodeToSpan(full.ast.addrspace_node); }, .node_offset_var_decl_init => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); const node = src_loc.declRelativeToNodeIndex(node_off); const full = tree.fullVarDecl(node).?; - return nodeToSpan(tree, full.ast.init_node); + return tree.nodeToSpan(full.ast.init_node); }, .node_offset_builtin_call_arg0 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 0), .node_offset_builtin_call_arg1 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 1), @@ -1312,13 +1403,13 @@ pub const SrcLoc = struct { node = node_datas[node].lhs; } - return nodeToSpan(tree, node); + return tree.nodeToSpan(node); }, .node_offset_array_access_index => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); const node_datas = tree.nodes.items(.data); const node = src_loc.declRelativeToNodeIndex(node_off); - return nodeToSpan(tree, node_datas[node].rhs); + return tree.nodeToSpan(node_datas[node].rhs); }, .node_offset_slice_ptr, .node_offset_slice_start, @@ -1335,14 +1426,14 @@ pub const SrcLoc = struct { .node_offset_slice_sentinel => full.ast.sentinel, else => unreachable, }; - return nodeToSpan(tree, part_node); + return tree.nodeToSpan(part_node); }, .node_offset_call_func => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); const node = src_loc.declRelativeToNodeIndex(node_off); var buf: [1]Ast.Node.Index = undefined; const full = tree.fullCall(&buf, node).?; - return nodeToSpan(tree, full.ast.fn_expr); + return tree.nodeToSpan(full.ast.fn_expr); }, .node_offset_field_name => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); @@ -1381,13 +1472,13 @@ pub const SrcLoc = struct { .node_offset_deref_ptr => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); const node = src_loc.declRelativeToNodeIndex(node_off); - return nodeToSpan(tree, node); + return tree.nodeToSpan(node); }, .node_offset_asm_source => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); const node = src_loc.declRelativeToNodeIndex(node_off); const full = tree.fullAsm(node).?; - return nodeToSpan(tree, full.ast.template); + return tree.nodeToSpan(full.ast.template); }, .node_offset_asm_ret_ty => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); @@ -1395,7 +1486,7 @@ pub const SrcLoc = struct { const full = tree.fullAsm(node).?; const asm_output = full.outputs[0]; const node_datas = tree.nodes.items(.data); - return nodeToSpan(tree, node_datas[asm_output].lhs); + return tree.nodeToSpan(node_datas[asm_output].lhs); }, .node_offset_if_cond => |node_off| { @@ -1418,21 +1509,21 @@ pub const SrcLoc = struct { const inputs = tree.fullFor(node).?.ast.inputs; const start = tree.firstToken(inputs[0]); const end = tree.lastToken(inputs[inputs.len - 1]); - return tokensToSpan(tree, start, end, start); + return tree.tokensToSpan(start, end, start); }, .@"orelse" => node, .@"catch" => node, else => unreachable, }; - return nodeToSpan(tree, src_node); + return tree.nodeToSpan(src_node); }, .for_input => |for_input| { const tree = try src_loc.file_scope.getTree(gpa); const node = src_loc.declRelativeToNodeIndex(for_input.for_node_offset); const for_full = tree.fullFor(node).?; const src_node = for_full.ast.inputs[for_input.input_index]; - return nodeToSpan(tree, src_node); + return tree.nodeToSpan(src_node); }, .for_capture_from_input => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); @@ -1458,12 +1549,12 @@ pub const SrcLoc = struct { }, .identifier => { if (count == 0) - return tokensToSpan(tree, tok, tok + 1, tok); + return tree.tokensToSpan(tok, tok + 1, tok); tok += 1; }, .asterisk => { if (count == 0) - return tokensToSpan(tree, tok, tok + 2, tok); + return tree.tokensToSpan(tok, tok + 2, tok); tok += 1; }, else => unreachable, @@ -1495,7 +1586,7 @@ pub const SrcLoc = struct { .array_init_comma, => { const full = tree.fullArrayInit(&buf, call_args_node).?.ast.elements; - return nodeToSpan(tree, full[call_arg.arg_index]); + return tree.nodeToSpan(full[call_arg.arg_index]); }, .struct_init_one, .struct_init_one_comma, @@ -1507,12 +1598,12 @@ pub const SrcLoc = struct { .struct_init_comma, => { const full = tree.fullStructInit(&buf, call_args_node).?.ast.fields; - return nodeToSpan(tree, full[call_arg.arg_index]); + return tree.nodeToSpan(full[call_arg.arg_index]); }, - else => return nodeToSpan(tree, call_args_node), + else => return tree.nodeToSpan(call_args_node), } }; - return nodeToSpan(tree, call_full.ast.params[call_arg.arg_index]); + return tree.nodeToSpan(call_full.ast.params[call_arg.arg_index]); }, .fn_proto_param => |fn_proto_param| { const tree = try src_loc.file_scope.getTree(gpa); @@ -1523,12 +1614,11 @@ pub const SrcLoc = struct { var i: usize = 0; while (it.next()) |param| : (i += 1) { if (i == fn_proto_param.param_index) { - if (param.anytype_ellipsis3) |token| return tokenToSpan(tree, token); + if (param.anytype_ellipsis3) |token| return tree.tokenToSpan(token); const first_token = param.comptime_noalias orelse param.name_token orelse tree.firstToken(param.type_expr); - return tokensToSpan( - tree, + return tree.tokensToSpan( first_token, tree.lastToken(param.type_expr), first_token, @@ -1541,13 +1631,13 @@ pub const SrcLoc = struct { const tree = try src_loc.file_scope.getTree(gpa); const node = src_loc.declRelativeToNodeIndex(node_off); const node_datas = tree.nodes.items(.data); - return nodeToSpan(tree, node_datas[node].lhs); + return tree.nodeToSpan(node_datas[node].lhs); }, .node_offset_bin_rhs => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); const node = src_loc.declRelativeToNodeIndex(node_off); const node_datas = tree.nodes.items(.data); - return nodeToSpan(tree, node_datas[node].rhs); + return tree.nodeToSpan(node_datas[node].rhs); }, .array_cat_lhs, .array_cat_rhs => |cat| { const tree = try src_loc.file_scope.getTree(gpa); @@ -1571,9 +1661,9 @@ pub const SrcLoc = struct { .array_init_comma, => { const full = tree.fullArrayInit(&buf, arr_node).?.ast.elements; - return nodeToSpan(tree, full[cat.elem_index]); + return tree.nodeToSpan(full[cat.elem_index]); }, - else => return nodeToSpan(tree, arr_node), + else => return tree.nodeToSpan(arr_node), } }, @@ -1581,7 +1671,7 @@ pub const SrcLoc = struct { const tree = try src_loc.file_scope.getTree(gpa); const node = src_loc.declRelativeToNodeIndex(node_off); const node_datas = tree.nodes.items(.data); - return nodeToSpan(tree, node_datas[node].lhs); + return tree.nodeToSpan(node_datas[node].lhs); }, .node_offset_switch_special_prong => |node_off| { @@ -1600,7 +1690,7 @@ pub const SrcLoc = struct { mem.eql(u8, tree.tokenSlice(main_tokens[case.ast.values[0]]), "_")); if (!is_special) continue; - return nodeToSpan(tree, case_node); + return tree.nodeToSpan(case_node); } else unreachable; }, @@ -1622,7 +1712,7 @@ pub const SrcLoc = struct { for (case.ast.values) |item_node| { if (node_tags[item_node] == .switch_range) { - return nodeToSpan(tree, item_node); + return tree.nodeToSpan(item_node); } } } else unreachable; @@ -1658,28 +1748,28 @@ pub const SrcLoc = struct { const node = src_loc.declRelativeToNodeIndex(node_off); var buf: [1]Ast.Node.Index = undefined; const full = tree.fullFnProto(&buf, node).?; - return nodeToSpan(tree, full.ast.align_expr); + return tree.nodeToSpan(full.ast.align_expr); }, .node_offset_fn_type_addrspace => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); const node = src_loc.declRelativeToNodeIndex(node_off); var buf: [1]Ast.Node.Index = undefined; const full = tree.fullFnProto(&buf, node).?; - return nodeToSpan(tree, full.ast.addrspace_expr); + return tree.nodeToSpan(full.ast.addrspace_expr); }, .node_offset_fn_type_section => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); const node = src_loc.declRelativeToNodeIndex(node_off); var buf: [1]Ast.Node.Index = undefined; const full = tree.fullFnProto(&buf, node).?; - return nodeToSpan(tree, full.ast.section_expr); + return tree.nodeToSpan(full.ast.section_expr); }, .node_offset_fn_type_cc => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); const node = src_loc.declRelativeToNodeIndex(node_off); var buf: [1]Ast.Node.Index = undefined; const full = tree.fullFnProto(&buf, node).?; - return nodeToSpan(tree, full.ast.callconv_expr); + return tree.nodeToSpan(full.ast.callconv_expr); }, .node_offset_fn_type_ret_ty => |node_off| { @@ -1687,7 +1777,7 @@ pub const SrcLoc = struct { const node = src_loc.declRelativeToNodeIndex(node_off); var buf: [1]Ast.Node.Index = undefined; const full = tree.fullFnProto(&buf, node).?; - return nodeToSpan(tree, full.ast.return_type); + return tree.nodeToSpan(full.ast.return_type); }, .node_offset_param => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); @@ -1699,8 +1789,7 @@ pub const SrcLoc = struct { .colon, .identifier, .keyword_comptime, .keyword_noalias => first_tok -= 1, else => break, }; - return tokensToSpan( - tree, + return tree.tokensToSpan( first_tok, tree.lastToken(node), first_tok, @@ -1717,8 +1806,7 @@ pub const SrcLoc = struct { .colon, .identifier, .keyword_comptime, .keyword_noalias => first_tok -= 1, else => break, }; - return tokensToSpan( - tree, + return tree.tokensToSpan( first_tok, tok_index, first_tok, @@ -1729,7 +1817,7 @@ pub const SrcLoc = struct { const tree = try src_loc.file_scope.getTree(gpa); const node_datas = tree.nodes.items(.data); const parent_node = src_loc.declRelativeToNodeIndex(node_off); - return nodeToSpan(tree, node_datas[parent_node].rhs); + return tree.nodeToSpan(node_datas[parent_node].rhs); }, .node_offset_lib_name => |node_off| { @@ -1748,70 +1836,70 @@ pub const SrcLoc = struct { const parent_node = src_loc.declRelativeToNodeIndex(node_off); const full = tree.fullArrayType(parent_node).?; - return nodeToSpan(tree, full.ast.elem_count); + return tree.nodeToSpan(full.ast.elem_count); }, .node_offset_array_type_sentinel => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); const parent_node = src_loc.declRelativeToNodeIndex(node_off); const full = tree.fullArrayType(parent_node).?; - return nodeToSpan(tree, full.ast.sentinel); + return tree.nodeToSpan(full.ast.sentinel); }, .node_offset_array_type_elem => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); const parent_node = src_loc.declRelativeToNodeIndex(node_off); const full = tree.fullArrayType(parent_node).?; - return nodeToSpan(tree, full.ast.elem_type); + return tree.nodeToSpan(full.ast.elem_type); }, .node_offset_un_op => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); const node_datas = tree.nodes.items(.data); const node = src_loc.declRelativeToNodeIndex(node_off); - return nodeToSpan(tree, node_datas[node].lhs); + return tree.nodeToSpan(node_datas[node].lhs); }, .node_offset_ptr_elem => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); const parent_node = src_loc.declRelativeToNodeIndex(node_off); const full = tree.fullPtrType(parent_node).?; - return nodeToSpan(tree, full.ast.child_type); + return tree.nodeToSpan(full.ast.child_type); }, .node_offset_ptr_sentinel => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); const parent_node = src_loc.declRelativeToNodeIndex(node_off); const full = tree.fullPtrType(parent_node).?; - return nodeToSpan(tree, full.ast.sentinel); + return tree.nodeToSpan(full.ast.sentinel); }, .node_offset_ptr_align => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); const parent_node = src_loc.declRelativeToNodeIndex(node_off); const full = tree.fullPtrType(parent_node).?; - return nodeToSpan(tree, full.ast.align_node); + return tree.nodeToSpan(full.ast.align_node); }, .node_offset_ptr_addrspace => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); const parent_node = src_loc.declRelativeToNodeIndex(node_off); const full = tree.fullPtrType(parent_node).?; - return nodeToSpan(tree, full.ast.addrspace_node); + return tree.nodeToSpan(full.ast.addrspace_node); }, .node_offset_ptr_bitoffset => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); const parent_node = src_loc.declRelativeToNodeIndex(node_off); const full = tree.fullPtrType(parent_node).?; - return nodeToSpan(tree, full.ast.bit_range_start); + return tree.nodeToSpan(full.ast.bit_range_start); }, .node_offset_ptr_hostsize => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); const parent_node = src_loc.declRelativeToNodeIndex(node_off); const full = tree.fullPtrType(parent_node).?; - return nodeToSpan(tree, full.ast.bit_range_end); + return tree.nodeToSpan(full.ast.bit_range_end); }, .node_offset_container_tag => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); @@ -1821,13 +1909,12 @@ pub const SrcLoc = struct { switch (node_tags[parent_node]) { .container_decl_arg, .container_decl_arg_trailing => { const full = tree.containerDeclArg(parent_node); - return nodeToSpan(tree, full.ast.arg); + return tree.nodeToSpan(full.ast.arg); }, .tagged_union_enum_tag, .tagged_union_enum_tag_trailing => { const full = tree.taggedUnionEnumTag(parent_node); - return tokensToSpan( - tree, + return tree.tokensToSpan( tree.firstToken(full.ast.arg) - 2, tree.lastToken(full.ast.arg) + 1, tree.nodes.items(.main_token)[full.ast.arg], @@ -1846,7 +1933,7 @@ pub const SrcLoc = struct { .container_field_init => tree.containerFieldInit(parent_node), else => unreachable, }; - return nodeToSpan(tree, full.ast.value_expr); + return tree.nodeToSpan(full.ast.value_expr); }, .node_offset_init_ty => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); @@ -1854,7 +1941,7 @@ pub const SrcLoc = struct { var buf: [2]Ast.Node.Index = undefined; const full = tree.fullArrayInit(&buf, parent_node).?; - return nodeToSpan(tree, full.ast.type_expr); + return tree.nodeToSpan(full.ast.type_expr); }, .node_offset_store_ptr => |node_off| { const tree = try src_loc.file_scope.getTree(gpa); @@ -1864,9 +1951,9 @@ pub const SrcLoc = struct { switch (node_tags[node]) { .assign => { - return nodeToSpan(tree, node_datas[node].lhs); + return tree.nodeToSpan(node_datas[node].lhs); }, - else => return nodeToSpan(tree, node), + else => return tree.nodeToSpan(node), } }, .node_offset_store_operand => |node_off| { @@ -1877,9 +1964,9 @@ pub const SrcLoc = struct { switch (node_tags[node]) { .assign => { - return nodeToSpan(tree, node_datas[node].rhs); + return tree.nodeToSpan(node_datas[node].rhs); }, - else => return nodeToSpan(tree, node), + else => return tree.nodeToSpan(node), } }, .node_offset_return_operand => |node_off| { @@ -1888,9 +1975,9 @@ pub const SrcLoc = struct { const node_tags = tree.nodes.items(.tag); const node_datas = tree.nodes.items(.data); if (node_tags[node] == .@"return" and node_datas[node].lhs != 0) { - return nodeToSpan(tree, node_datas[node].lhs); + return tree.nodeToSpan(node_datas[node].lhs); } - return nodeToSpan(tree, node); + return tree.nodeToSpan(node); }, } } @@ -1914,486 +2001,7 @@ pub const SrcLoc = struct { .builtin_call, .builtin_call_comma => tree.extra_data[node_datas[node].lhs + arg_index], else => unreachable, }; - return nodeToSpan(tree, param); - } - - pub fn nodeToSpan(tree: *const Ast, node: u32) Span { - return tokensToSpan( - tree, - tree.firstToken(node), - tree.lastToken(node), - tree.nodes.items(.main_token)[node], - ); - } - - fn tokenToSpan(tree: *const Ast, token: Ast.TokenIndex) Span { - return tokensToSpan(tree, token, token, token); - } - - fn tokensToSpan(tree: *const Ast, start: Ast.TokenIndex, end: Ast.TokenIndex, main: Ast.TokenIndex) Span { - const token_starts = tree.tokens.items(.start); - var start_tok = start; - var end_tok = end; - - if (tree.tokensOnSameLine(start, end)) { - // do nothing - } else if (tree.tokensOnSameLine(start, main)) { - end_tok = main; - } else if (tree.tokensOnSameLine(main, end)) { - start_tok = main; - } else { - start_tok = main; - end_tok = main; - } - const start_off = token_starts[start_tok]; - const end_off = token_starts[end_tok] + @as(u32, @intCast(tree.tokenSlice(end_tok).len)); - return Span{ .start = start_off, .end = end_off, .main = token_starts[main] }; - } -}; - -/// This wraps a simple integer in debug builds so that later on we can find out -/// where in semantic analysis the value got set. -const TracedOffset = struct { - x: i32, - trace: std.debug.Trace = .{}, - - const want_tracing = build_options.value_tracing; -}; - -/// Resolving a source location into a byte offset may require doing work -/// that we would rather not do unless the error actually occurs. -/// Therefore we need a data structure that contains the information necessary -/// to lazily produce a `SrcLoc` as required. -/// Most of the offsets in this data structure are relative to the containing Decl. -/// This makes the source location resolve properly even when a Decl gets -/// shifted up or down in the file, as long as the Decl's contents itself -/// do not change. -pub const LazySrcLoc = union(enum) { - /// When this tag is set, the code that constructed this `LazySrcLoc` is asserting - /// that all code paths which would need to resolve the source location are - /// unreachable. If you are debugging this tag incorrectly being this value, - /// look into using reverse-continue with a memory watchpoint to see where the - /// value is being set to this tag. - unneeded, - /// Means the source location points to an entire file; not any particular - /// location within the file. `file_scope` union field will be active. - entire_file, - /// The source location points to a byte offset within a source file, - /// offset from 0. The source file is determined contextually. - /// Inside a `SrcLoc`, the `file_scope` union field will be active. - byte_abs: u32, - /// The source location points to a token within a source file, - /// offset from 0. The source file is determined contextually. - /// Inside a `SrcLoc`, the `file_scope` union field will be active. - token_abs: u32, - /// The source location points to an AST node within a source file, - /// offset from 0. The source file is determined contextually. - /// Inside a `SrcLoc`, the `file_scope` union field will be active. - node_abs: u32, - /// The source location points to a byte offset within a source file, - /// offset from the byte offset of the Decl within the file. - /// The Decl is determined contextually. - byte_offset: u32, - /// This data is the offset into the token list from the Decl token. - /// The Decl is determined contextually. - token_offset: u32, - /// The source location points to an AST node, which is this value offset - /// from its containing Decl node AST index. - /// The Decl is determined contextually. - node_offset: TracedOffset, - /// The source location points to the main token of an AST node, found - /// by taking this AST node index offset from the containing Decl AST node. - /// The Decl is determined contextually. - node_offset_main_token: i32, - /// The source location points to the beginning of a struct initializer. - /// The Decl is determined contextually. - node_offset_initializer: i32, - /// The source location points to a variable declaration type expression, - /// found by taking this AST node index offset from the containing - /// Decl AST node, which points to a variable declaration AST node. Next, navigate - /// to the type expression. - /// The Decl is determined contextually. - node_offset_var_decl_ty: i32, - /// The source location points to the alignment expression of a var decl. - /// The Decl is determined contextually. - node_offset_var_decl_align: i32, - /// The source location points to the linksection expression of a var decl. - /// The Decl is determined contextually. - node_offset_var_decl_section: i32, - /// The source location points to the addrspace expression of a var decl. - /// The Decl is determined contextually. - node_offset_var_decl_addrspace: i32, - /// The source location points to the initializer of a var decl. - /// The Decl is determined contextually. - node_offset_var_decl_init: i32, - /// The source location points to the first parameter of a builtin - /// function call, found by taking this AST node index offset from the containing - /// Decl AST node, which points to a builtin call AST node. Next, navigate - /// to the first parameter. - /// The Decl is determined contextually. - node_offset_builtin_call_arg0: i32, - /// Same as `node_offset_builtin_call_arg0` except arg index 1. - node_offset_builtin_call_arg1: i32, - node_offset_builtin_call_arg2: i32, - node_offset_builtin_call_arg3: i32, - node_offset_builtin_call_arg4: i32, - node_offset_builtin_call_arg5: i32, - /// Like `node_offset_builtin_call_arg0` but recurses through arbitrarily many calls - /// to pointer cast builtins. - node_offset_ptrcast_operand: i32, - /// The source location points to the index expression of an array access - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to an array access AST node. Next, navigate - /// to the index expression. - /// The Decl is determined contextually. - node_offset_array_access_index: i32, - /// The source location points to the LHS of a slice expression - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to a slice AST node. Next, navigate - /// to the sentinel expression. - /// The Decl is determined contextually. - node_offset_slice_ptr: i32, - /// The source location points to start expression of a slice expression - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to a slice AST node. Next, navigate - /// to the sentinel expression. - /// The Decl is determined contextually. - node_offset_slice_start: i32, - /// The source location points to the end expression of a slice - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to a slice AST node. Next, navigate - /// to the sentinel expression. - /// The Decl is determined contextually. - node_offset_slice_end: i32, - /// The source location points to the sentinel expression of a slice - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to a slice AST node. Next, navigate - /// to the sentinel expression. - /// The Decl is determined contextually. - node_offset_slice_sentinel: i32, - /// The source location points to the callee expression of a function - /// call expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to a function call AST node. Next, navigate - /// to the callee expression. - /// The Decl is determined contextually. - node_offset_call_func: i32, - /// The payload is offset from the containing Decl AST node. - /// The source location points to the field name of: - /// * a field access expression (`a.b`), or - /// * the callee of a method call (`a.b()`) - /// The Decl is determined contextually. - node_offset_field_name: i32, - /// The payload is offset from the containing Decl AST node. - /// The source location points to the field name of the operand ("b" node) - /// of a field initialization expression (`.a = b`) - /// The Decl is determined contextually. - node_offset_field_name_init: i32, - /// The source location points to the pointer of a pointer deref expression, - /// found by taking this AST node index offset from the containing - /// Decl AST node, which points to a pointer deref AST node. Next, navigate - /// to the pointer expression. - /// The Decl is determined contextually. - node_offset_deref_ptr: i32, - /// The source location points to the assembly source code of an inline assembly - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to inline assembly AST node. Next, navigate - /// to the asm template source code. - /// The Decl is determined contextually. - node_offset_asm_source: i32, - /// The source location points to the return type of an inline assembly - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to inline assembly AST node. Next, navigate - /// to the return type expression. - /// The Decl is determined contextually. - node_offset_asm_ret_ty: i32, - /// The source location points to the condition expression of an if - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to an if expression AST node. Next, navigate - /// to the condition expression. - /// The Decl is determined contextually. - node_offset_if_cond: i32, - /// The source location points to a binary expression, such as `a + b`, found - /// by taking this AST node index offset from the containing Decl AST node. - /// The Decl is determined contextually. - node_offset_bin_op: i32, - /// The source location points to the LHS of a binary expression, found - /// by taking this AST node index offset from the containing Decl AST node, - /// which points to a binary expression AST node. Next, navigate to the LHS. - /// The Decl is determined contextually. - node_offset_bin_lhs: i32, - /// The source location points to the RHS of a binary expression, found - /// by taking this AST node index offset from the containing Decl AST node, - /// which points to a binary expression AST node. Next, navigate to the RHS. - /// The Decl is determined contextually. - node_offset_bin_rhs: i32, - /// The source location points to the operand of a switch expression, found - /// by taking this AST node index offset from the containing Decl AST node, - /// which points to a switch expression AST node. Next, navigate to the operand. - /// The Decl is determined contextually. - node_offset_switch_operand: i32, - /// The source location points to the else/`_` prong of a switch expression, found - /// by taking this AST node index offset from the containing Decl AST node, - /// which points to a switch expression AST node. Next, navigate to the else/`_` prong. - /// The Decl is determined contextually. - node_offset_switch_special_prong: i32, - /// The source location points to all the ranges of a switch expression, found - /// by taking this AST node index offset from the containing Decl AST node, - /// which points to a switch expression AST node. Next, navigate to any of the - /// range nodes. The error applies to all of them. - /// The Decl is determined contextually. - node_offset_switch_range: i32, - /// The source location points to the capture of a switch_prong. - /// The Decl is determined contextually. - node_offset_switch_prong_capture: i32, - /// The source location points to the tag capture of a switch_prong. - /// The Decl is determined contextually. - node_offset_switch_prong_tag_capture: i32, - /// The source location points to the align expr of a function type - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to a function type AST node. Next, navigate to - /// the calling convention node. - /// The Decl is determined contextually. - node_offset_fn_type_align: i32, - /// The source location points to the addrspace expr of a function type - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to a function type AST node. Next, navigate to - /// the calling convention node. - /// The Decl is determined contextually. - node_offset_fn_type_addrspace: i32, - /// The source location points to the linksection expr of a function type - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to a function type AST node. Next, navigate to - /// the calling convention node. - /// The Decl is determined contextually. - node_offset_fn_type_section: i32, - /// The source location points to the calling convention of a function type - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to a function type AST node. Next, navigate to - /// the calling convention node. - /// The Decl is determined contextually. - node_offset_fn_type_cc: i32, - /// The source location points to the return type of a function type - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to a function type AST node. Next, navigate to - /// the return type node. - /// The Decl is determined contextually. - node_offset_fn_type_ret_ty: i32, - node_offset_param: i32, - token_offset_param: i32, - /// The source location points to the type expression of an `anyframe->T` - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to a `anyframe->T` expression AST node. Next, navigate - /// to the type expression. - /// The Decl is determined contextually. - node_offset_anyframe_type: i32, - /// The source location points to the string literal of `extern "foo"`, found - /// by taking this AST node index offset from the containing - /// Decl AST node, which points to a function prototype or variable declaration - /// expression AST node. Next, navigate to the string literal of the `extern "foo"`. - /// The Decl is determined contextually. - node_offset_lib_name: i32, - /// The source location points to the len expression of an `[N:S]T` - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to an `[N:S]T` expression AST node. Next, navigate - /// to the len expression. - /// The Decl is determined contextually. - node_offset_array_type_len: i32, - /// The source location points to the sentinel expression of an `[N:S]T` - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to an `[N:S]T` expression AST node. Next, navigate - /// to the sentinel expression. - /// The Decl is determined contextually. - node_offset_array_type_sentinel: i32, - /// The source location points to the elem expression of an `[N:S]T` - /// expression, found by taking this AST node index offset from the containing - /// Decl AST node, which points to an `[N:S]T` expression AST node. Next, navigate - /// to the elem expression. - /// The Decl is determined contextually. - node_offset_array_type_elem: i32, - /// The source location points to the operand of an unary expression. - /// The Decl is determined contextually. - node_offset_un_op: i32, - /// The source location points to the elem type of a pointer. - /// The Decl is determined contextually. - node_offset_ptr_elem: i32, - /// The source location points to the sentinel of a pointer. - /// The Decl is determined contextually. - node_offset_ptr_sentinel: i32, - /// The source location points to the align expr of a pointer. - /// The Decl is determined contextually. - node_offset_ptr_align: i32, - /// The source location points to the addrspace expr of a pointer. - /// The Decl is determined contextually. - node_offset_ptr_addrspace: i32, - /// The source location points to the bit-offset of a pointer. - /// The Decl is determined contextually. - node_offset_ptr_bitoffset: i32, - /// The source location points to the host size of a pointer. - /// The Decl is determined contextually. - node_offset_ptr_hostsize: i32, - /// The source location points to the tag type of an union or an enum. - /// The Decl is determined contextually. - node_offset_container_tag: i32, - /// The source location points to the default value of a field. - /// The Decl is determined contextually. - node_offset_field_default: i32, - /// The source location points to the type of an array or struct initializer. - /// The Decl is determined contextually. - node_offset_init_ty: i32, - /// The source location points to the LHS of an assignment. - /// The Decl is determined contextually. - node_offset_store_ptr: i32, - /// The source location points to the RHS of an assignment. - /// The Decl is determined contextually. - node_offset_store_operand: i32, - /// The source location points to the operand of a `return` statement, or - /// the `return` itself if there is no explicit operand. - /// The Decl is determined contextually. - node_offset_return_operand: i32, - /// The source location points to a for loop input. - /// The Decl is determined contextually. - for_input: struct { - /// Points to the for loop AST node. - for_node_offset: i32, - /// Picks one of the inputs from the condition. - input_index: u32, - }, - /// The source location points to one of the captures of a for loop, found - /// by taking this AST node index offset from the containing - /// Decl AST node, which points to one of the input nodes of a for loop. - /// Next, navigate to the corresponding capture. - /// The Decl is determined contextually. - for_capture_from_input: i32, - /// The source location points to the argument node of a function call. - call_arg: struct { - decl: Decl.Index, - /// Points to the function call AST node. - call_node_offset: i32, - /// The index of the argument the source location points to. - arg_index: u32, - }, - fn_proto_param: struct { - decl: Decl.Index, - /// Points to the function prototype AST node. - fn_proto_node_offset: i32, - /// The index of the parameter the source location points to. - param_index: u32, - }, - array_cat_lhs: ArrayCat, - array_cat_rhs: ArrayCat, - - const ArrayCat = struct { - /// Points to the array concat AST node. - array_cat_offset: i32, - /// The index of the element the source location points to. - elem_index: u32, - }; - - pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease; - - noinline fn nodeOffsetDebug(node_offset: i32) LazySrcLoc { - var result: LazySrcLoc = .{ .node_offset = .{ .x = node_offset } }; - result.node_offset.trace.addAddr(@returnAddress(), "init"); - return result; - } - - fn nodeOffsetRelease(node_offset: i32) LazySrcLoc { - return .{ .node_offset = .{ .x = node_offset } }; - } - - /// Upgrade to a `SrcLoc` based on the `Decl` provided. - pub fn toSrcLoc(lazy: LazySrcLoc, decl: *Decl, mod: *Module) SrcLoc { - return switch (lazy) { - .unneeded, - .entire_file, - .byte_abs, - .token_abs, - .node_abs, - => .{ - .file_scope = decl.getFileScope(mod), - .parent_decl_node = 0, - .lazy = lazy, - }, - - .byte_offset, - .token_offset, - .node_offset, - .node_offset_main_token, - .node_offset_initializer, - .node_offset_var_decl_ty, - .node_offset_var_decl_align, - .node_offset_var_decl_section, - .node_offset_var_decl_addrspace, - .node_offset_var_decl_init, - .node_offset_builtin_call_arg0, - .node_offset_builtin_call_arg1, - .node_offset_builtin_call_arg2, - .node_offset_builtin_call_arg3, - .node_offset_builtin_call_arg4, - .node_offset_builtin_call_arg5, - .node_offset_ptrcast_operand, - .node_offset_array_access_index, - .node_offset_slice_ptr, - .node_offset_slice_start, - .node_offset_slice_end, - .node_offset_slice_sentinel, - .node_offset_call_func, - .node_offset_field_name, - .node_offset_field_name_init, - .node_offset_deref_ptr, - .node_offset_asm_source, - .node_offset_asm_ret_ty, - .node_offset_if_cond, - .node_offset_bin_op, - .node_offset_bin_lhs, - .node_offset_bin_rhs, - .node_offset_switch_operand, - .node_offset_switch_special_prong, - .node_offset_switch_range, - .node_offset_switch_prong_capture, - .node_offset_switch_prong_tag_capture, - .node_offset_fn_type_align, - .node_offset_fn_type_addrspace, - .node_offset_fn_type_section, - .node_offset_fn_type_cc, - .node_offset_fn_type_ret_ty, - .node_offset_param, - .token_offset_param, - .node_offset_anyframe_type, - .node_offset_lib_name, - .node_offset_array_type_len, - .node_offset_array_type_sentinel, - .node_offset_array_type_elem, - .node_offset_un_op, - .node_offset_ptr_elem, - .node_offset_ptr_sentinel, - .node_offset_ptr_align, - .node_offset_ptr_addrspace, - .node_offset_ptr_bitoffset, - .node_offset_ptr_hostsize, - .node_offset_container_tag, - .node_offset_field_default, - .node_offset_init_ty, - .node_offset_store_ptr, - .node_offset_store_operand, - .node_offset_return_operand, - .for_input, - .for_capture_from_input, - .array_cat_lhs, - .array_cat_rhs, - => .{ - .file_scope = decl.getFileScope(mod), - .parent_decl_node = decl.src_node, - .lazy = lazy, - }, - inline .call_arg, - .fn_proto_param, - => |x| .{ - .file_scope = decl.getFileScope(mod), - .parent_decl_node = mod.declPtr(x.decl).src_node, - .lazy = lazy, - }, - }; + return tree.nodeToSpan(param); } }; diff --git a/src/Package.zig b/src/Package.zig index da2e214154b4..1bb02c5a5afc 100644 --- a/src/Package.zig +++ b/src/Package.zig @@ -126,7 +126,7 @@ pub const Path = struct { ) !void { if (fmt_string.len == 1) { // Quote-escape the string. - const stringEscape = std.zig.fmt.stringEscape; + const stringEscape = std.zig.stringEscape; const f = switch (fmt_string[0]) { 'q' => "", '\'' => '\'', diff --git a/src/Package/Fetch.zig b/src/Package/Fetch.zig index e4e944d18692..ac21632a60ce 100644 --- a/src/Package/Fetch.zig +++ b/src/Package/Fetch.zig @@ -592,7 +592,7 @@ fn loadManifest(f: *Fetch, pkg_root: Package.Path) RunError!void { if (ast.errors.len > 0) { const file_path = try std.fmt.allocPrint(arena, "{}" ++ Manifest.basename, .{pkg_root}); - try main.putAstErrorsIntoBundle(arena, ast.*, file_path, eb); + try std.zig.putAstErrorsIntoBundle(arena, ast.*, file_path, eb); return error.FetchFailed; } @@ -1690,7 +1690,6 @@ const Cache = std.Build.Cache; const ThreadPool = std.Thread.Pool; const WaitGroup = std.Thread.WaitGroup; const Fetch = @This(); -const main = @import("../main.zig"); const git = @import("Fetch/git.zig"); const Package = @import("../Package.zig"); const Manifest = Package.Manifest; diff --git a/src/Sema.zig b/src/Sema.zig index daacf6d089ff..8976848befe6 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -148,7 +148,7 @@ const Value = @import("Value.zig"); const Type = @import("type.zig").Type; const TypedValue = @import("TypedValue.zig"); const Air = @import("Air.zig"); -const Zir = @import("Zir.zig"); +const Zir = std.zig.Zir; const Module = @import("Module.zig"); const trace = @import("tracy.zig").trace; const Namespace = Module.Namespace; @@ -156,7 +156,7 @@ const CompileError = Module.CompileError; const SemaError = Module.SemaError; const Decl = Module.Decl; const CaptureScope = Module.CaptureScope; -const LazySrcLoc = Module.LazySrcLoc; +const LazySrcLoc = std.zig.LazySrcLoc; const RangeSet = @import("RangeSet.zig"); const target_util = @import("target.zig"); const Package = @import("Package.zig"); @@ -397,7 +397,7 @@ pub const Block = struct { break :blk src_loc; } else blk: { const src_decl = mod.declPtr(rt.block.src_decl); - break :blk rt.func_src.toSrcLoc(src_decl, mod); + break :blk src_decl.toSrcLoc(rt.func_src, mod); }; if (rt.return_ty.isGenericPoison()) { return mod.errNoteNonLazy(src_loc, parent, prefix ++ "the generic function was instantiated with a comptime-only return type", .{}); @@ -2421,7 +2421,7 @@ fn errNote( ) error{OutOfMemory}!void { const mod = sema.mod; const src_decl = mod.declPtr(block.src_decl); - return mod.errNoteNonLazy(src.toSrcLoc(src_decl, mod), parent, format, args); + return mod.errNoteNonLazy(src_decl.toSrcLoc(src, mod), parent, format, args); } fn addFieldErrNote( @@ -2478,7 +2478,7 @@ fn errMsg( const mod = sema.mod; if (src == .unneeded) return error.NeededSourceLocation; const src_decl = mod.declPtr(block.src_decl); - return Module.ErrorMsg.create(sema.gpa, src.toSrcLoc(src_decl, mod), format, args); + return Module.ErrorMsg.create(sema.gpa, src_decl.toSrcLoc(src, mod), format, args); } pub fn fail( @@ -2556,7 +2556,7 @@ fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Module.ErrorMsg) const decl = mod.declPtr(ref.referencer); try reference_stack.append(.{ .decl = decl.name, - .src_loc = ref.src.toSrcLoc(decl, mod), + .src_loc = decl.toSrcLoc(ref.src, mod), }); } referenced_by = ref.referencer; @@ -2599,7 +2599,7 @@ fn reparentOwnedErrorMsg( ) !void { const mod = sema.mod; const src_decl = mod.declPtr(block.src_decl); - const resolved_src = src.toSrcLoc(src_decl, mod); + const resolved_src = src_decl.toSrcLoc(src, mod); const msg_str = try std.fmt.allocPrint(mod.gpa, format, args); const orig_notes = msg.notes.len; @@ -5252,7 +5252,7 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr errdefer msg.destroy(sema.gpa); const src_decl = mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsComptime(msg, src.toSrcLoc(src_decl, mod), elem_ty); + try sema.explainWhyTypeIsComptime(msg, src_decl.toSrcLoc(src, mod), elem_ty); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -5716,7 +5716,7 @@ fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError var child_block = parent_block.makeSubBlock(); child_block.label = &label; child_block.runtime_cond = null; - child_block.runtime_loop = src.toSrcLoc(mod.declPtr(child_block.src_decl), mod); + child_block.runtime_loop = mod.declPtr(child_block.src_decl).toSrcLoc(src, mod); child_block.runtime_index.increment(); const merges = &child_block.label.?.merges; @@ -6058,7 +6058,7 @@ fn analyzeBlockBody( try mod.errNoteNonLazy(runtime_src, msg, "runtime control flow here", .{}); const child_src_decl = mod.declPtr(child_block.src_decl); - try sema.explainWhyTypeIsComptime(msg, type_src.toSrcLoc(child_src_decl, mod), resolved_ty); + try sema.explainWhyTypeIsComptime(msg, child_src_decl.toSrcLoc(type_src, mod), resolved_ty); break :msg msg; }; @@ -6213,7 +6213,7 @@ pub fn analyzeExport( errdefer msg.destroy(gpa); const src_decl = mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl, mod), exported_decl.ty, .other); + try sema.explainWhyTypeIsNotExtern(msg, src_decl.toSrcLoc(src, mod), exported_decl.ty, .other); try sema.addDeclaredHereNote(msg, exported_decl.ty); break :msg msg; @@ -8082,7 +8082,7 @@ fn instantiateGenericCall( }; try child_sema.errNote(&child_block, param_src, msg, "declared here", .{}); const src_decl = mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsComptime(msg, arg_src.toSrcLoc(src_decl, mod), arg_ty); + try sema.explainWhyTypeIsComptime(msg, src_decl.toSrcLoc(arg_src, mod), arg_ty); break :msg msg; }), @@ -9387,7 +9387,7 @@ fn funcCommon( errdefer msg.destroy(sema.gpa); const src_decl = mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsNotExtern(msg, param_src.toSrcLoc(src_decl, mod), param_ty, .param_ty); + try sema.explainWhyTypeIsNotExtern(msg, src_decl.toSrcLoc(param_src, mod), param_ty, .param_ty); try sema.addDeclaredHereNote(msg, param_ty); break :msg msg; @@ -9402,7 +9402,7 @@ fn funcCommon( errdefer msg.destroy(sema.gpa); const src_decl = mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsComptime(msg, param_src.toSrcLoc(src_decl, mod), param_ty); + try sema.explainWhyTypeIsComptime(msg, src_decl.toSrcLoc(param_src, mod), param_ty); try sema.addDeclaredHereNote(msg, param_ty); break :msg msg; @@ -9671,7 +9671,7 @@ fn finishFunc( errdefer msg.destroy(gpa); const src_decl = mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsNotExtern(msg, ret_ty_src.toSrcLoc(src_decl, mod), return_type, .ret_ty); + try sema.explainWhyTypeIsNotExtern(msg, src_decl.toSrcLoc(ret_ty_src, mod), return_type, .ret_ty); try sema.addDeclaredHereNote(msg, return_type); break :msg msg; @@ -9692,7 +9692,7 @@ fn finishFunc( "function with comptime-only return type '{}' requires all parameters to be comptime", .{return_type.fmt(mod)}, ); - try sema.explainWhyTypeIsComptime(msg, ret_ty_src.toSrcLoc(sema.owner_decl, mod), return_type); + try sema.explainWhyTypeIsComptime(msg, sema.owner_decl.toSrcLoc(ret_ty_src, mod), return_type); const tags = sema.code.instructions.items(.tag); const data = sema.code.instructions.items(.data); @@ -9965,7 +9965,7 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! const msg = try sema.errMsg(block, ptr_src, "comptime-only type '{}' has no pointer address", .{pointee_ty.fmt(mod)}); errdefer msg.destroy(sema.gpa); const src_decl = mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsComptime(msg, ptr_src.toSrcLoc(src_decl, mod), pointee_ty); + try sema.explainWhyTypeIsComptime(msg, src_decl.toSrcLoc(ptr_src, mod), pointee_ty); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -11492,7 +11492,7 @@ fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp var sub_block = child_block.makeSubBlock(); sub_block.runtime_loop = null; - sub_block.runtime_cond = main_operand_src.toSrcLoc(mod.declPtr(child_block.src_decl), mod); + sub_block.runtime_cond = mod.declPtr(child_block.src_decl).toSrcLoc(main_operand_src, mod); sub_block.runtime_index.increment(); defer sub_block.instructions.deinit(gpa); @@ -12227,7 +12227,7 @@ fn analyzeSwitchRuntimeBlock( var case_block = child_block.makeSubBlock(); case_block.runtime_loop = null; - case_block.runtime_cond = operand_src.toSrcLoc(mod.declPtr(child_block.src_decl), mod); + case_block.runtime_cond = mod.declPtr(child_block.src_decl).toSrcLoc(operand_src, mod); case_block.runtime_index.increment(); defer case_block.instructions.deinit(gpa); @@ -13663,7 +13663,7 @@ fn zirEmbedFile(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A return sema.fail(block, operand_src, "file path name cannot be empty", .{}); } - const src_loc = operand_src.toSrcLoc(mod.declPtr(block.src_decl), mod); + const src_loc = mod.declPtr(block.src_decl).toSrcLoc(operand_src, mod); const val = mod.embedFile(block.getFileScope(mod), name, src_loc) catch |err| switch (err) { error.ImportOutsideModulePath => { return sema.fail(block, operand_src, "embed of file outside package path: '{s}'", .{name}); @@ -18766,7 +18766,7 @@ fn zirBoolBr( var child_block = parent_block.makeSubBlock(); child_block.runtime_loop = null; - child_block.runtime_cond = lhs_src.toSrcLoc(mod.declPtr(child_block.src_decl), mod); + child_block.runtime_cond = mod.declPtr(child_block.src_decl).toSrcLoc(lhs_src, mod); child_block.runtime_index.increment(); defer child_block.instructions.deinit(gpa); @@ -18963,7 +18963,7 @@ fn zirCondbr( // instructions array in between using it for the then block and else block. var sub_block = parent_block.makeSubBlock(); sub_block.runtime_loop = null; - sub_block.runtime_cond = cond_src.toSrcLoc(mod.declPtr(parent_block.src_decl), mod); + sub_block.runtime_cond = mod.declPtr(parent_block.src_decl).toSrcLoc(cond_src, mod); sub_block.runtime_index.increment(); defer sub_block.instructions.deinit(gpa); @@ -19503,7 +19503,7 @@ fn analyzeRet( if (sema.fn_ret_ty.isError(mod) and ret_val.getErrorName(mod) != .none) { const src_decl = mod.declPtr(block.src_decl); - const src_loc = src.toSrcLoc(src_decl, mod); + const src_loc = src_decl.toSrcLoc(src, mod); try sema.comptime_err_ret_trace.append(src_loc); } return error.ComptimeReturn; @@ -19660,7 +19660,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air errdefer msg.destroy(sema.gpa); const src_decl = mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsNotExtern(msg, elem_ty_src.toSrcLoc(src_decl, mod), elem_ty, .other); + try sema.explainWhyTypeIsNotExtern(msg, src_decl.toSrcLoc(elem_ty_src, mod), elem_ty, .other); try sema.addDeclaredHereNote(msg, elem_ty); break :msg msg; @@ -21128,7 +21128,7 @@ fn zirReify( errdefer msg.destroy(gpa); const src_decl = mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl, mod), elem_ty, .other); + try sema.explainWhyTypeIsNotExtern(msg, src_decl.toSrcLoc(src, mod), elem_ty, .other); try sema.addDeclaredHereNote(msg, elem_ty); break :msg msg; @@ -21572,7 +21572,7 @@ fn zirReify( errdefer msg.destroy(gpa); const src_decl = mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl, mod), field_ty, .union_field); + try sema.explainWhyTypeIsNotExtern(msg, src_decl.toSrcLoc(src, mod), field_ty, .union_field); try sema.addDeclaredHereNote(msg, field_ty); break :msg msg; @@ -21584,7 +21584,7 @@ fn zirReify( errdefer msg.destroy(gpa); const src_decl = mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsNotPacked(msg, src.toSrcLoc(src_decl, mod), field_ty); + try sema.explainWhyTypeIsNotPacked(msg, src_decl.toSrcLoc(src, mod), field_ty); try sema.addDeclaredHereNote(msg, field_ty); break :msg msg; @@ -21939,7 +21939,7 @@ fn reifyStruct( errdefer msg.destroy(gpa); const src_decl = sema.mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl, mod), field_ty, .struct_field); + try sema.explainWhyTypeIsNotExtern(msg, src_decl.toSrcLoc(src, mod), field_ty, .struct_field); try sema.addDeclaredHereNote(msg, field_ty); break :msg msg; @@ -21951,7 +21951,7 @@ fn reifyStruct( errdefer msg.destroy(gpa); const src_decl = sema.mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsNotPacked(msg, src.toSrcLoc(src_decl, mod), field_ty); + try sema.explainWhyTypeIsNotPacked(msg, src_decl.toSrcLoc(src, mod), field_ty); try sema.addDeclaredHereNote(msg, field_ty); break :msg msg; @@ -22018,7 +22018,7 @@ fn zirCVaArg(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C errdefer msg.destroy(sema.gpa); const src_decl = sema.mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsNotExtern(msg, ty_src.toSrcLoc(src_decl, mod), arg_ty, .param_ty); + try sema.explainWhyTypeIsNotExtern(msg, src_decl.toSrcLoc(ty_src, mod), arg_ty, .param_ty); try sema.addDeclaredHereNote(msg, arg_ty); break :msg msg; @@ -25859,7 +25859,7 @@ fn zirBuiltinExtern( const msg = try sema.errMsg(block, ty_src, "extern symbol cannot have type '{}'", .{ty.fmt(mod)}); errdefer msg.destroy(sema.gpa); const src_decl = sema.mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsNotExtern(msg, ty_src.toSrcLoc(src_decl, mod), ty, .other); + try sema.explainWhyTypeIsNotExtern(msg, src_decl.toSrcLoc(ty_src, mod), ty, .other); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -26003,7 +26003,7 @@ fn validateVarType( const msg = try sema.errMsg(block, src, "extern variable cannot have type '{}'", .{var_ty.fmt(mod)}); errdefer msg.destroy(sema.gpa); const src_decl = mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl, mod), var_ty, .other); + try sema.explainWhyTypeIsNotExtern(msg, src_decl.toSrcLoc(src, mod), var_ty, .other); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -26026,7 +26026,7 @@ fn validateVarType( errdefer msg.destroy(sema.gpa); const src_decl = mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsComptime(msg, src.toSrcLoc(src_decl, mod), var_ty); + try sema.explainWhyTypeIsComptime(msg, src_decl.toSrcLoc(src, mod), var_ty); if (var_ty.zigTypeTag(mod) == .ComptimeInt or var_ty.zigTypeTag(mod) == .ComptimeFloat) { try sema.errNote(block, src, msg, "to modify this variable at runtime, it must be given an explicit fixed-size number type", .{}); } @@ -28093,7 +28093,7 @@ fn validateRuntimeElemAccess( errdefer msg.destroy(sema.gpa); const src_decl = mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsComptime(msg, parent_src.toSrcLoc(src_decl, mod), parent_ty); + try sema.explainWhyTypeIsComptime(msg, src_decl.toSrcLoc(parent_src, mod), parent_ty); break :msg msg; }; @@ -28492,7 +28492,7 @@ const CoerceOpts = struct { .lazy = LazySrcLoc.nodeOffset(param_src.node_offset_param), }; } - return param_src.toSrcLoc(fn_decl, mod); + return fn_decl.toSrcLoc(param_src, mod); } } = .{}, }; @@ -29110,7 +29110,7 @@ fn coerceExtra( const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 }; const src_decl = mod.funcOwnerDeclPtr(sema.func_index); - try mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl, mod), msg, "'noreturn' declared here", .{}); + try mod.errNoteNonLazy(src_decl.toSrcLoc(ret_ty_src, mod), msg, "'noreturn' declared here", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(block, msg); @@ -29145,9 +29145,9 @@ fn coerceExtra( const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 }; const src_decl = mod.funcOwnerDeclPtr(sema.func_index); if (inst_ty.isError(mod) and !dest_ty.isError(mod)) { - try mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl, mod), msg, "function cannot return an error", .{}); + try mod.errNoteNonLazy(src_decl.toSrcLoc(ret_ty_src, mod), msg, "function cannot return an error", .{}); } else { - try mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl, mod), msg, "function return type declared here", .{}); + try mod.errNoteNonLazy(src_decl.toSrcLoc(ret_ty_src, mod), msg, "function return type declared here", .{}); } } @@ -30165,7 +30165,7 @@ fn coerceVarArgParam( errdefer msg.destroy(sema.gpa); const src_decl = sema.mod.declPtr(block.src_decl); - try sema.explainWhyTypeIsNotExtern(msg, inst_src.toSrcLoc(src_decl, mod), coerced_ty, .param_ty); + try sema.explainWhyTypeIsNotExtern(msg, src_decl.toSrcLoc(inst_src, mod), coerced_ty, .param_ty); try sema.addDeclaredHereNote(msg, coerced_ty); break :msg msg; @@ -37180,7 +37180,7 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Key.Un }); errdefer msg.destroy(sema.gpa); const decl_ptr = mod.declPtr(tag_info.decl); - try mod.errNoteNonLazy(enum_field_src.toSrcLoc(decl_ptr, mod), msg, "enum field here", .{}); + try mod.errNoteNonLazy(decl_ptr.toSrcLoc(enum_field_src, mod), msg, "enum field here", .{}); break :msg msg; }; return sema.failWithOwnedErrorMsg(&block_scope, msg); diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index c3a9bb889558..3a2a9c2d06b9 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -16,7 +16,7 @@ const Decl = Module.Decl; const Type = @import("../../type.zig").Type; const Value = @import("../../Value.zig"); const Compilation = @import("../../Compilation.zig"); -const LazySrcLoc = Module.LazySrcLoc; +const LazySrcLoc = std.zig.LazySrcLoc; const link = @import("../../link.zig"); const TypedValue = @import("../../TypedValue.zig"); const Air = @import("../../Air.zig"); @@ -767,8 +767,7 @@ pub fn deinit(func: *CodeGen) void { /// Sets `err_msg` on `CodeGen` and returns `error.CodegenFail` which is caught in link/Wasm.zig fn fail(func: *CodeGen, comptime fmt: []const u8, args: anytype) InnerError { const mod = func.bin_file.base.comp.module.?; - const src = LazySrcLoc.nodeOffset(0); - const src_loc = src.toSrcLoc(func.decl, mod); + const src_loc = func.decl.srcLoc(mod); func.err_msg = try Module.ErrorMsg.create(func.gpa, src_loc, fmt, args); return error.CodegenFail; } diff --git a/src/codegen.zig b/src/codegen.zig index 7bcba8006544..4856eff7d81e 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -21,7 +21,7 @@ const Target = std.Target; const Type = @import("type.zig").Type; const TypedValue = @import("TypedValue.zig"); const Value = @import("Value.zig"); -const Zir = @import("Zir.zig"); +const Zir = std.zig.Zir; const Alignment = InternPool.Alignment; pub const Result = union(enum) { diff --git a/src/codegen/c.zig b/src/codegen/c.zig index d4747256bbe0..92dc904c1a36 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -13,7 +13,7 @@ const TypedValue = @import("../TypedValue.zig"); const C = link.File.C; const Decl = Module.Decl; const trace = @import("../tracy.zig").trace; -const LazySrcLoc = Module.LazySrcLoc; +const LazySrcLoc = std.zig.LazySrcLoc; const Air = @import("../Air.zig"); const Liveness = @import("../Liveness.zig"); const InternPool = @import("../InternPool.zig"); @@ -570,8 +570,7 @@ pub const DeclGen = struct { const mod = dg.module; const decl_index = dg.pass.decl; const decl = mod.declPtr(decl_index); - const src = LazySrcLoc.nodeOffset(0); - const src_loc = src.toSrcLoc(decl, mod); + const src_loc = decl.srcLoc(mod); dg.error_msg = try Module.ErrorMsg.create(dg.gpa, src_loc, format, args); return error.AnalysisFail; } diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 331af769ca21..827fee9f0a52 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -23,7 +23,7 @@ const Air = @import("../Air.zig"); const Liveness = @import("../Liveness.zig"); const Value = @import("../Value.zig"); const Type = @import("../type.zig").Type; -const LazySrcLoc = Module.LazySrcLoc; +const LazySrcLoc = std.zig.LazySrcLoc; const x86_64_abi = @import("../arch/x86_64/abi.zig"); const wasm_c_abi = @import("../arch/wasm/abi.zig"); const aarch64_c_abi = @import("../arch/aarch64/abi.zig"); @@ -4686,7 +4686,7 @@ pub const DeclGen = struct { const o = dg.object; const gpa = o.gpa; const mod = o.module; - const src_loc = LazySrcLoc.nodeOffset(0).toSrcLoc(dg.decl, mod); + const src_loc = dg.decl.srcLoc(mod); dg.err_msg = try Module.ErrorMsg.create(gpa, src_loc, "TODO (LLVM): " ++ format, args); return error.CodegenFail; } diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index ca724c38799e..fb8d1e1e8ef6 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -8,9 +8,8 @@ const Module = @import("../Module.zig"); const Decl = Module.Decl; const Type = @import("../type.zig").Type; const Value = @import("../Value.zig"); -const LazySrcLoc = Module.LazySrcLoc; +const LazySrcLoc = std.zig.LazySrcLoc; const Air = @import("../Air.zig"); -const Zir = @import("../Zir.zig"); const Liveness = @import("../Liveness.zig"); const InternPool = @import("../InternPool.zig"); @@ -413,8 +412,7 @@ const DeclGen = struct { pub fn fail(self: *DeclGen, comptime format: []const u8, args: anytype) Error { @setCold(true); const mod = self.module; - const src = LazySrcLoc.nodeOffset(0); - const src_loc = src.toSrcLoc(self.module.declPtr(self.decl_index), mod); + const src_loc = self.module.declPtr(self.decl_index).srcLoc(mod); assert(self.error_msg == null); self.error_msg = try Module.ErrorMsg.create(self.module.gpa, src_loc, format, args); return error.CodegenFail; @@ -5270,8 +5268,7 @@ const DeclGen = struct { // TODO: Translate proper error locations. assert(as.errors.items.len != 0); assert(self.error_msg == null); - const loc = LazySrcLoc.nodeOffset(0); - const src_loc = loc.toSrcLoc(self.module.declPtr(self.decl_index), mod); + const src_loc = self.module.declPtr(self.decl_index).srcLoc(mod); self.error_msg = try Module.ErrorMsg.create(self.module.gpa, src_loc, "failed to assemble SPIR-V inline assembly", .{}); const notes = try self.module.gpa.alloc(Module.ErrorMsg, as.errors.items.len); diff --git a/src/crash_report.zig b/src/crash_report.zig index cedce84d94bb..0c2354af4e3d 100644 --- a/src/crash_report.zig +++ b/src/crash_report.zig @@ -8,7 +8,7 @@ const native_os = builtin.os.tag; const Module = @import("Module.zig"); const Sema = @import("Sema.zig"); -const Zir = @import("Zir.zig"); +const Zir = std.zig.Zir; const Decl = Module.Decl; pub const is_enabled = builtin.mode == .Debug; diff --git a/src/introspect.zig b/src/introspect.zig index 765e9409ed67..36821592df26 100644 --- a/src/introspect.zig +++ b/src/introspect.zig @@ -153,6 +153,7 @@ pub const EnvVar = enum { ZIG_VERBOSE_LINK, ZIG_VERBOSE_CC, ZIG_BTRFS_WORKAROUND, + ZIG_DEBUG_CMD, CC, NO_COLOR, XDG_CACHE_HOME, diff --git a/src/main.zig b/src/main.zig index bb8b25c60e41..24ca355238c7 100644 --- a/src/main.zig +++ b/src/main.zig @@ -8,6 +8,7 @@ const process = std.process; const Allocator = mem.Allocator; const ArrayList = std.ArrayList; const Ast = std.zig.Ast; +const Color = std.zig.Color; const warn = std.log.warn; const ThreadPool = std.Thread.Pool; const cleanExit = std.process.cleanExit; @@ -25,7 +26,7 @@ const Cache = std.Build.Cache; const target_util = @import("target.zig"); const crash_report = @import("crash_report.zig"); const Module = @import("Module.zig"); -const AstGen = @import("AstGen.zig"); +const AstGen = std.zig.AstGen; const mingw = @import("mingw.zig"); const Server = std.zig.Server; @@ -66,18 +67,8 @@ pub fn fatal(comptime format: []const u8, args: anytype) noreturn { process.exit(1); } -/// There are many assumptions in the entire codebase that Zig source files can -/// be byte-indexed with a u32 integer. -const max_src_size = std.math.maxInt(u32); - const debug_extensions_enabled = builtin.mode == .Debug; -const Color = enum { - auto, - off, - on, -}; - const normal_usage = \\Usage: zig [command] [options] \\ @@ -212,14 +203,6 @@ pub fn main() anyerror!void { } } - if (build_options.only_reduce) { - if (mem.eql(u8, args[1], "reduce")) { - return @import("reduce.zig").main(gpa, arena, args); - } else { - @panic("only reduce is supported in a -Donly-reduce build"); - } - } - return mainArgs(gpa, arena, args); } @@ -311,7 +294,7 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { } else if (mem.eql(u8, cmd, "rc")) { return cmdRc(gpa, arena, args[1..]); } else if (mem.eql(u8, cmd, "fmt")) { - return cmdFmt(gpa, arena, cmd_args); + return jitCmd(gpa, arena, cmd_args, "fmt", "fmt.zig"); } else if (mem.eql(u8, cmd, "objcopy")) { return @import("objcopy.zig").cmdObjCopy(gpa, arena, cmd_args); } else if (mem.eql(u8, cmd, "fetch")) { @@ -334,7 +317,7 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { verifyLibcxxCorrectlyLinked(); return @import("print_env.zig").cmdEnv(arena, cmd_args, io.getStdOut().writer()); } else if (mem.eql(u8, cmd, "reduce")) { - return @import("reduce.zig").main(gpa, arena, args); + return jitCmd(gpa, arena, cmd_args, "reduce", "reduce.zig"); } else if (mem.eql(u8, cmd, "zen")) { return io.getStdOut().writeAll(info_zen); } else if (mem.eql(u8, cmd, "help") or mem.eql(u8, cmd, "-h") or mem.eql(u8, cmd, "--help")) { @@ -2756,6 +2739,7 @@ fn buildOutputType( .paths = .{ .root = .{ .root_dir = zig_lib_directory, + .sub_path = "compiler", }, .root_src_path = "test_runner.zig", }, @@ -4501,7 +4485,7 @@ fn updateModule(comp: *Compilation, color: Color) !void { defer errors.deinit(comp.gpa); if (errors.errorMessageCount() > 0) { - errors.renderToStdErr(renderOptions(color)); + errors.renderToStdErr(color.renderOptions()); return error.SemanticAnalyzeFail; } } @@ -4601,7 +4585,7 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, fancy_output: ?*Compilati p.errors = errors; return; } else { - errors.renderToStdErr(renderOptions(color)); + errors.renderToStdErr(color.renderOptions()); process.exit(1); } }, @@ -5402,7 +5386,9 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { }, .root_src_path = fs.path.basename(runner), } else .{ - .root = .{ .root_dir = zig_lib_directory }, + .root = .{ + .root_dir = zig_lib_directory, + }, .root_src_path = "build_runner.zig", }; @@ -5528,7 +5514,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { if (fetch.error_bundle.root_list.items.len > 0) { var errors = try fetch.error_bundle.toOwnedBundle(""); - errors.renderToStdErr(renderOptions(color)); + errors.renderToStdErr(color.renderOptions()); process.exit(1); } @@ -5719,470 +5705,165 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { } } -fn readSourceFileToEndAlloc( - allocator: Allocator, - input: *const fs.File, - size_hint: ?usize, -) ![:0]u8 { - const source_code = input.readToEndAllocOptions( - allocator, - max_src_size, - size_hint, - @alignOf(u16), - 0, - ) catch |err| switch (err) { - error.ConnectionResetByPeer => unreachable, - error.ConnectionTimedOut => unreachable, - error.NotOpenForReading => unreachable, - else => |e| return e, - }; - errdefer allocator.free(source_code); - - // Detect unsupported file types with their Byte Order Mark - const unsupported_boms = [_][]const u8{ - "\xff\xfe\x00\x00", // UTF-32 little endian - "\xfe\xff\x00\x00", // UTF-32 big endian - "\xfe\xff", // UTF-16 big endian - }; - for (unsupported_boms) |bom| { - if (mem.startsWith(u8, source_code, bom)) { - return error.UnsupportedEncoding; - } - } - - // If the file starts with a UTF-16 little endian BOM, translate it to UTF-8 - if (mem.startsWith(u8, source_code, "\xff\xfe")) { - const source_code_utf16_le = mem.bytesAsSlice(u16, source_code); - const source_code_utf8 = std.unicode.utf16LeToUtf8AllocZ(allocator, source_code_utf16_le) catch |err| switch (err) { - error.DanglingSurrogateHalf => error.UnsupportedEncoding, - error.ExpectedSecondSurrogateHalf => error.UnsupportedEncoding, - error.UnexpectedSecondSurrogateHalf => error.UnsupportedEncoding, - else => |e| return e, - }; - - allocator.free(source_code); - return source_code_utf8; - } - - return source_code; -} - -const usage_fmt = - \\Usage: zig fmt [file]... - \\ - \\ Formats the input files and modifies them in-place. - \\ Arguments can be files or directories, which are searched - \\ recursively. - \\ - \\Options: - \\ -h, --help Print this help and exit - \\ --color [auto|off|on] Enable or disable colored error messages - \\ --stdin Format code from stdin; output to stdout - \\ --check List non-conforming files and exit with an error - \\ if the list is non-empty - \\ --ast-check Run zig ast-check on every file - \\ --exclude [file] Exclude file or directory from formatting - \\ - \\ -; - -const Fmt = struct { - seen: SeenMap, - any_error: bool, - check_ast: bool, - color: Color, +fn jitCmd( gpa: Allocator, arena: Allocator, - out_buffer: std.ArrayList(u8), - - const SeenMap = std.AutoHashMap(fs.File.INode, void); -}; - -fn cmdFmt(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { - var color: Color = .auto; - var stdin_flag: bool = false; - var check_flag: bool = false; - var check_ast_flag: bool = false; - var input_files = ArrayList([]const u8).init(gpa); - defer input_files.deinit(); - var excluded_files = ArrayList([]const u8).init(gpa); - defer excluded_files.deinit(); - - { - var i: usize = 0; - while (i < args.len) : (i += 1) { - const arg = args[i]; - if (mem.startsWith(u8, arg, "-")) { - if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { - const stdout = io.getStdOut().writer(); - try stdout.writeAll(usage_fmt); - return cleanExit(); - } else if (mem.eql(u8, arg, "--color")) { - if (i + 1 >= args.len) { - fatal("expected [auto|on|off] after --color", .{}); - } - i += 1; - const next_arg = args[i]; - color = std.meta.stringToEnum(Color, next_arg) orelse { - fatal("expected [auto|on|off] after --color, found '{s}'", .{next_arg}); - }; - } else if (mem.eql(u8, arg, "--stdin")) { - stdin_flag = true; - } else if (mem.eql(u8, arg, "--check")) { - check_flag = true; - } else if (mem.eql(u8, arg, "--ast-check")) { - check_ast_flag = true; - } else if (mem.eql(u8, arg, "--exclude")) { - if (i + 1 >= args.len) { - fatal("expected parameter after --exclude", .{}); - } - i += 1; - const next_arg = args[i]; - try excluded_files.append(next_arg); - } else { - fatal("unrecognized parameter: '{s}'", .{arg}); - } - } else { - try input_files.append(arg); - } - } - } - - if (stdin_flag) { - if (input_files.items.len != 0) { - fatal("cannot use --stdin with positional arguments", .{}); - } - - const stdin = io.getStdIn(); - const source_code = readSourceFileToEndAlloc(gpa, &stdin, null) catch |err| { - fatal("unable to read stdin: {}", .{err}); - }; - defer gpa.free(source_code); - - var tree = Ast.parse(gpa, source_code, .zig) catch |err| { - fatal("error parsing stdin: {}", .{err}); - }; - defer tree.deinit(gpa); - - if (check_ast_flag) { - var file: Module.File = .{ - .status = .never_loaded, - .source_loaded = true, - .zir_loaded = false, - .sub_file_path = "", - .source = source_code, - .stat = undefined, - .tree = tree, - .tree_loaded = true, - .zir = undefined, - .mod = undefined, - .root_decl = .none, - }; - - file.mod = try Package.Module.createLimited(arena, .{ - .root = Package.Path.cwd(), - .root_src_path = file.sub_file_path, - .fully_qualified_name = "root", - }); - - file.zir = try AstGen.generate(gpa, file.tree); - file.zir_loaded = true; - defer file.zir.deinit(gpa); - - if (file.zir.hasCompileErrors()) { - var wip_errors: std.zig.ErrorBundle.Wip = undefined; - try wip_errors.init(gpa); - defer wip_errors.deinit(); - try Compilation.addZirErrorMessages(&wip_errors, &file); - var error_bundle = try wip_errors.toOwnedBundle(""); - defer error_bundle.deinit(gpa); - error_bundle.renderToStdErr(renderOptions(color)); - process.exit(2); - } - } else if (tree.errors.len != 0) { - try printAstErrorsToStderr(gpa, tree, "", color); - process.exit(2); - } - const formatted = try tree.render(gpa); - defer gpa.free(formatted); - - if (check_flag) { - const code: u8 = @intFromBool(mem.eql(u8, formatted, source_code)); - process.exit(code); - } - - return io.getStdOut().writeAll(formatted); - } + args: []const []const u8, + cmd_name: []const u8, + root_src_path: []const u8, +) !void { + const color: Color = .auto; - if (input_files.items.len == 0) { - fatal("expected at least one source file argument", .{}); - } + const target_query: std.Target.Query = .{}; + const resolved_target: Package.Module.ResolvedTarget = .{ + .result = resolveTargetQueryOrFatal(target_query), + .is_native_os = true, + .is_native_abi = true, + }; - var fmt = Fmt{ - .gpa = gpa, - .arena = arena, - .seen = Fmt.SeenMap.init(gpa), - .any_error = false, - .check_ast = check_ast_flag, - .color = color, - .out_buffer = std.ArrayList(u8).init(gpa), + const exe_basename = try std.zig.binNameAlloc(arena, .{ + .root_name = cmd_name, + .target = resolved_target.result, + .output_mode = .Exe, + }); + const emit_bin: Compilation.EmitLoc = .{ + .directory = null, // Use the global zig-cache. + .basename = exe_basename, }; - defer fmt.seen.deinit(); - defer fmt.out_buffer.deinit(); - // Mark any excluded files/directories as already seen, - // so that they are skipped later during actual processing - for (excluded_files.items) |file_path| { - const stat = fs.cwd().statFile(file_path) catch |err| switch (err) { - error.FileNotFound => continue, - // On Windows, statFile does not work for directories - error.IsDir => dir: { - var dir = try fs.cwd().openDir(file_path, .{}); - defer dir.close(); - break :dir try dir.stat(); - }, - else => |e| return e, - }; - try fmt.seen.put(stat.inode, {}); - } + const self_exe_path = introspect.findZigExePath(arena) catch |err| { + fatal("unable to find self exe path: {s}", .{@errorName(err)}); + }; - for (input_files.items) |file_path| { - try fmtPath(&fmt, file_path, check_flag, fs.cwd(), file_path); - } - if (fmt.any_error) { - process.exit(1); - } -} + const optimize_mode: std.builtin.OptimizeMode = if (EnvVar.ZIG_DEBUG_CMD.isSet()) + .Debug + else + .ReleaseFast; + const override_lib_dir: ?[]const u8 = try EnvVar.ZIG_LIB_DIR.get(arena); + const override_global_cache_dir: ?[]const u8 = try EnvVar.ZIG_GLOBAL_CACHE_DIR.get(arena); -const FmtError = error{ - SystemResources, - OperationAborted, - IoPending, - BrokenPipe, - Unexpected, - WouldBlock, - FileClosed, - DestinationAddressRequired, - DiskQuota, - FileTooBig, - InputOutput, - NoSpaceLeft, - AccessDenied, - OutOfMemory, - RenameAcrossMountPoints, - ReadOnlyFileSystem, - LinkQuotaExceeded, - FileBusy, - EndOfStream, - Unseekable, - NotOpenForWriting, - UnsupportedEncoding, - ConnectionResetByPeer, - SocketNotConnected, - LockViolation, - NetNameDeleted, - InvalidArgument, -} || fs.File.OpenError; - -fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool, dir: fs.Dir, sub_path: []const u8) FmtError!void { - fmtPathFile(fmt, file_path, check_mode, dir, sub_path) catch |err| switch (err) { - error.IsDir, error.AccessDenied => return fmtPathDir(fmt, file_path, check_mode, dir, sub_path), - else => { - warn("unable to format '{s}': {s}", .{ file_path, @errorName(err) }); - fmt.any_error = true; - return; + var zig_lib_directory: Compilation.Directory = if (override_lib_dir) |lib_dir| .{ + .path = lib_dir, + .handle = fs.cwd().openDir(lib_dir, .{}) catch |err| { + fatal("unable to open zig lib directory from 'zig-lib-dir' argument: '{s}': {s}", .{ lib_dir, @errorName(err) }); }, + } else introspect.findZigLibDirFromSelfExe(arena, self_exe_path) catch |err| { + fatal("unable to find zig installation directory '{s}': {s}", .{ self_exe_path, @errorName(err) }); }; -} - -fn fmtPathDir( - fmt: *Fmt, - file_path: []const u8, - check_mode: bool, - parent_dir: fs.Dir, - parent_sub_path: []const u8, -) FmtError!void { - var dir = try parent_dir.openDir(parent_sub_path, .{ .iterate = true }); - defer dir.close(); - - const stat = try dir.stat(); - if (try fmt.seen.fetchPut(stat.inode, {})) |_| return; - - var dir_it = dir.iterate(); - while (try dir_it.next()) |entry| { - const is_dir = entry.kind == .directory; - - if (is_dir and (mem.eql(u8, entry.name, "zig-cache") or mem.eql(u8, entry.name, "zig-out"))) continue; - - if (is_dir or entry.kind == .file and (mem.endsWith(u8, entry.name, ".zig") or mem.endsWith(u8, entry.name, ".zon"))) { - const full_path = try fs.path.join(fmt.gpa, &[_][]const u8{ file_path, entry.name }); - defer fmt.gpa.free(full_path); - - if (is_dir) { - try fmtPathDir(fmt, full_path, check_mode, dir, entry.name); - } else { - fmtPathFile(fmt, full_path, check_mode, dir, entry.name) catch |err| { - warn("unable to format '{s}': {s}", .{ full_path, @errorName(err) }); - fmt.any_error = true; - return; - }; - } - } - } -} - -fn fmtPathFile( - fmt: *Fmt, - file_path: []const u8, - check_mode: bool, - dir: fs.Dir, - sub_path: []const u8, -) FmtError!void { - const source_file = try dir.openFile(sub_path, .{}); - var file_closed = false; - errdefer if (!file_closed) source_file.close(); - - const stat = try source_file.stat(); - - if (stat.kind == .directory) - return error.IsDir; - - const gpa = fmt.gpa; - const source_code = try readSourceFileToEndAlloc( - gpa, - &source_file, - std.math.cast(usize, stat.size) orelse return error.FileTooBig, - ); - defer gpa.free(source_code); - - source_file.close(); - file_closed = true; + defer zig_lib_directory.handle.close(); - // Add to set after no longer possible to get error.IsDir. - if (try fmt.seen.fetchPut(stat.inode, {})) |_| return; + var global_cache_directory: Compilation.Directory = l: { + const p = override_global_cache_dir orelse try introspect.resolveGlobalCacheDir(arena); + break :l .{ + .handle = try fs.cwd().makeOpenPath(p, .{}), + .path = p, + }; + }; + defer global_cache_directory.handle.close(); - var tree = try Ast.parse(gpa, source_code, .zig); - defer tree.deinit(gpa); + var thread_pool: ThreadPool = undefined; + try thread_pool.init(.{ .allocator = gpa }); + defer thread_pool.deinit(); - if (tree.errors.len != 0) { - try printAstErrorsToStderr(gpa, tree, file_path, fmt.color); - fmt.any_error = true; - return; - } + var child_argv: std.ArrayListUnmanaged([]const u8) = .{}; + try child_argv.ensureUnusedCapacity(arena, args.len + 1); - if (fmt.check_ast) { - var file: Module.File = .{ - .status = .never_loaded, - .source_loaded = true, - .zir_loaded = false, - .sub_file_path = file_path, - .source = source_code, - .stat = .{ - .size = stat.size, - .inode = stat.inode, - .mtime = stat.mtime, + // We want to release all the locks before executing the child process, so we make a nice + // big block here to ensure the cleanup gets run when we extract out our argv. + { + const main_mod_paths: Package.Module.CreateOptions.Paths = .{ + .root = .{ + .root_dir = zig_lib_directory, + .sub_path = "compiler", }, - .tree = tree, - .tree_loaded = true, - .zir = undefined, - .mod = undefined, - .root_decl = .none, + .root_src_path = root_src_path, }; - file.mod = try Package.Module.createLimited(fmt.arena, .{ - .root = Package.Path.cwd(), - .root_src_path = file.sub_file_path, - .fully_qualified_name = "root", + const config = try Compilation.Config.resolve(.{ + .output_mode = .Exe, + .root_optimize_mode = optimize_mode, + .resolved_target = resolved_target, + .have_zcu = true, + .emit_bin = true, + .is_test = false, }); - if (stat.size > max_src_size) - return error.FileTooBig; + const root_mod = try Package.Module.create(arena, .{ + .global_cache_directory = global_cache_directory, + .paths = main_mod_paths, + .fully_qualified_name = "root", + .cc_argv = &.{}, + .inherited = .{ + .resolved_target = resolved_target, + .optimize_mode = optimize_mode, + }, + .global = config, + .parent = null, + .builtin_mod = null, + }); - file.zir = try AstGen.generate(gpa, file.tree); - file.zir_loaded = true; - defer file.zir.deinit(gpa); - - if (file.zir.hasCompileErrors()) { - var wip_errors: std.zig.ErrorBundle.Wip = undefined; - try wip_errors.init(gpa); - defer wip_errors.deinit(); - try Compilation.addZirErrorMessages(&wip_errors, &file); - var error_bundle = try wip_errors.toOwnedBundle(""); - defer error_bundle.deinit(gpa); - error_bundle.renderToStdErr(renderOptions(fmt.color)); - fmt.any_error = true; - } - } + const comp = Compilation.create(gpa, arena, .{ + .zig_lib_directory = zig_lib_directory, + .local_cache_directory = global_cache_directory, + .global_cache_directory = global_cache_directory, + .root_name = cmd_name, + .config = config, + .root_mod = root_mod, + .main_mod = root_mod, + .emit_bin = emit_bin, + .emit_h = null, + .self_exe_path = self_exe_path, + .thread_pool = &thread_pool, + .cache_mode = .whole, + }) catch |err| { + fatal("unable to create compilation: {s}", .{@errorName(err)}); + }; + defer comp.destroy(); - // As a heuristic, we make enough capacity for the same as the input source. - fmt.out_buffer.shrinkRetainingCapacity(0); - try fmt.out_buffer.ensureTotalCapacity(source_code.len); + updateModule(comp, color) catch |err| switch (err) { + error.SemanticAnalyzeFail => process.exit(2), + else => |e| return e, + }; - try tree.renderToArrayList(&fmt.out_buffer, .{}); - if (mem.eql(u8, fmt.out_buffer.items, source_code)) - return; + const exe_path = try global_cache_directory.join(arena, &.{comp.cache_use.whole.bin_sub_path.?}); + child_argv.appendAssumeCapacity(exe_path); + } - if (check_mode) { - const stdout = io.getStdOut().writer(); - try stdout.print("{s}\n", .{file_path}); - fmt.any_error = true; - } else { - var af = try dir.atomicFile(sub_path, .{ .mode = stat.mode }); - defer af.deinit(); + child_argv.appendSliceAssumeCapacity(args); - try af.file.writeAll(fmt.out_buffer.items); - try af.finish(); - const stdout = io.getStdOut().writer(); - try stdout.print("{s}\n", .{file_path}); + if (process.can_execv) { + const err = process.execv(gpa, child_argv.items); + const cmd = try std.mem.join(arena, " ", child_argv.items); + fatal("the following command failed to execve with '{s}':\n{s}", .{ + @errorName(err), + cmd, + }); } -} - -fn printAstErrorsToStderr(gpa: Allocator, tree: Ast, path: []const u8, color: Color) !void { - var wip_errors: std.zig.ErrorBundle.Wip = undefined; - try wip_errors.init(gpa); - defer wip_errors.deinit(); - try putAstErrorsIntoBundle(gpa, tree, path, &wip_errors); + if (!process.can_spawn) { + const cmd = try std.mem.join(arena, " ", child_argv.items); + fatal("the following command cannot be executed ({s} does not support spawning a child process):\n{s}", .{ + @tagName(builtin.os.tag), cmd, + }); + } - var error_bundle = try wip_errors.toOwnedBundle(""); - defer error_bundle.deinit(gpa); - error_bundle.renderToStdErr(renderOptions(color)); -} + var child = std.ChildProcess.init(child_argv.items, gpa); + child.stdin_behavior = .Inherit; + child.stdout_behavior = .Inherit; + child.stderr_behavior = .Inherit; -pub fn putAstErrorsIntoBundle( - gpa: Allocator, - tree: Ast, - path: []const u8, - wip_errors: *std.zig.ErrorBundle.Wip, -) Allocator.Error!void { - var file: Module.File = .{ - .status = .never_loaded, - .source_loaded = true, - .zir_loaded = false, - .sub_file_path = path, - .source = tree.source, - .stat = .{ - .size = 0, - .inode = 0, - .mtime = 0, + const term = try child.spawnAndWait(); + switch (term) { + .Exited => |code| { + if (code == 0) return cleanExit(); + const cmd = try std.mem.join(arena, " ", child_argv.items); + fatal("the following build command failed with exit code {d}:\n{s}", .{ code, cmd }); }, - .tree = tree, - .tree_loaded = true, - .zir = undefined, - .mod = try Package.Module.createLimited(gpa, .{ - .root = Package.Path.cwd(), - .root_src_path = path, - .fully_qualified_name = "root", - }), - .root_decl = .none, - }; - defer gpa.destroy(file.mod); - - file.zir = try AstGen.generate(gpa, file.tree); - file.zir_loaded = true; - defer file.zir.deinit(gpa); - - try Compilation.addZirErrorMessages(wip_errors, &file); + else => { + const cmd = try std.mem.join(arena, " ", child_argv.items); + fatal("the following build command crashed:\n{s}", .{cmd}); + }, + } } const info_zen = @@ -6655,7 +6336,7 @@ fn cmdAstCheck( arena: Allocator, args: []const []const u8, ) !void { - const Zir = @import("Zir.zig"); + const Zir = std.zig.Zir; var color: Color = .auto; var want_output_text = false; @@ -6710,7 +6391,7 @@ fn cmdAstCheck( const stat = try f.stat(); - if (stat.size > max_src_size) + if (stat.size > std.zig.max_src_size) return error.FileTooBig; const source = try arena.allocSentinel(u8, @as(usize, @intCast(stat.size)), 0); @@ -6728,7 +6409,7 @@ fn cmdAstCheck( }; } else { const stdin = io.getStdIn(); - const source = readSourceFileToEndAlloc(arena, &stdin, null) catch |err| { + const source = std.zig.readSourceFileToEndAlloc(arena, stdin, null) catch |err| { fatal("unable to read stdin: {}", .{err}); }; file.sub_file_path = ""; @@ -6758,7 +6439,7 @@ fn cmdAstCheck( try Compilation.addZirErrorMessages(&wip_errors, &file); var error_bundle = try wip_errors.toOwnedBundle(""); defer error_bundle.deinit(gpa); - error_bundle.renderToStdErr(renderOptions(color)); + error_bundle.renderToStdErr(color.renderOptions()); process.exit(1); } @@ -6817,7 +6498,7 @@ fn cmdDumpZir( args: []const []const u8, ) !void { _ = arena; - const Zir = @import("Zir.zig"); + const Zir = std.zig.Zir; const cache_file = args[0]; @@ -6877,7 +6558,7 @@ fn cmdChangelist( args: []const []const u8, ) !void { const color: Color = .auto; - const Zir = @import("Zir.zig"); + const Zir = std.zig.Zir; const old_source_file = args[0]; const new_source_file = args[1]; @@ -6889,7 +6570,7 @@ fn cmdChangelist( const stat = try f.stat(); - if (stat.size > max_src_size) + if (stat.size > std.zig.max_src_size) return error.FileTooBig; var file: Module.File = .{ @@ -6938,7 +6619,7 @@ fn cmdChangelist( try Compilation.addZirErrorMessages(&wip_errors, &file); var error_bundle = try wip_errors.toOwnedBundle(""); defer error_bundle.deinit(gpa); - error_bundle.renderToStdErr(renderOptions(color)); + error_bundle.renderToStdErr(color.renderOptions()); process.exit(1); } @@ -6949,7 +6630,7 @@ fn cmdChangelist( const new_stat = try new_f.stat(); - if (new_stat.size > max_src_size) + if (new_stat.size > std.zig.max_src_size) return error.FileTooBig; const new_source = try arena.allocSentinel(u8, @as(usize, @intCast(new_stat.size)), 0); @@ -6973,7 +6654,7 @@ fn cmdChangelist( try Compilation.addZirErrorMessages(&wip_errors, &file); var error_bundle = try wip_errors.toOwnedBundle(""); defer error_bundle.deinit(gpa); - error_bundle.renderToStdErr(renderOptions(color)); + error_bundle.renderToStdErr(color.renderOptions()); process.exit(1); } @@ -7241,23 +6922,6 @@ const ClangSearchSanitizer = struct { }; }; -fn get_tty_conf(color: Color) std.io.tty.Config { - return switch (color) { - .auto => std.io.tty.detectConfig(std.io.getStdErr()), - .on => .escape_codes, - .off => .no_color, - }; -} - -fn renderOptions(color: Color) std.zig.ErrorBundle.RenderOptions { - const ttyconf = get_tty_conf(color); - return .{ - .ttyconf = ttyconf, - .include_source_line = ttyconf != .no_color, - .include_reference_trace = ttyconf != .no_color, - }; -} - fn accessLibPath( test_path: *std.ArrayList(u8), checked_paths: *std.ArrayList(u8), @@ -7498,7 +7162,7 @@ fn cmdFetch( if (fetch.error_bundle.root_list.items.len > 0) { var errors = try fetch.error_bundle.toOwnedBundle(""); - errors.renderToStdErr(renderOptions(color)); + errors.renderToStdErr(color.renderOptions()); process.exit(1); } @@ -7790,7 +7454,7 @@ fn loadManifest( errdefer ast.deinit(gpa); if (ast.errors.len > 0) { - try printAstErrorsToStderr(gpa, ast, Package.Manifest.basename, options.color); + try std.zig.printAstErrorsToStderr(gpa, ast, Package.Manifest.basename, options.color); process.exit(2); } @@ -7807,7 +7471,7 @@ fn loadManifest( var error_bundle = try wip_errors.toOwnedBundle(""); defer error_bundle.deinit(gpa); - error_bundle.renderToStdErr(renderOptions(options.color)); + error_bundle.renderToStdErr(options.color.renderOptions()); process.exit(2); } diff --git a/src/print_zir.zig b/src/print_zir.zig index 711dcaa2a3fc..42c2576ac556 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -5,9 +5,9 @@ const assert = std.debug.assert; const Ast = std.zig.Ast; const InternPool = @import("InternPool.zig"); -const Zir = @import("Zir.zig"); +const Zir = std.zig.Zir; const Module = @import("Module.zig"); -const LazySrcLoc = Module.LazySrcLoc; +const LazySrcLoc = std.zig.LazySrcLoc; /// Write human-readable, debug formatted ZIR code to a file. pub fn renderAsTextToFile( diff --git a/stage1/config.zig.in b/stage1/config.zig.in index 96215bb3621c..8e0a87e8169e 100644 --- a/stage1/config.zig.in +++ b/stage1/config.zig.in @@ -13,4 +13,3 @@ pub const skip_non_native = false; pub const only_c = false; pub const force_gpa = false; pub const only_core_functionality = true; -pub const only_reduce = false;