|
//! 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. |
ErrorBundlezig/ErrorBundle.zigDeprecated: use |
pub const ErrorBundle = @import("zig/ErrorBundle.zig"); |
Serverzig/Server.zigDetermine whether stderr is a terminal or not automatically. |
pub const Server = @import("zig/Server.zig"); |
Clientzig/Client.zigAssume stderr is not a terminal. |
pub const Client = @import("zig/Client.zig"); |
TokenAssume stderr is a terminal. |
pub const Token = tokenizer.Token; |
TokenizerThere are many assumptions in the entire codebase that Zig source files can be byte-indexed with a u32 integer. |
pub const Tokenizer = tokenizer.Tokenizer; |
string_literalzig/string_literal.zigDoes not include the trailing newline. |
pub const string_literal = @import("zig/string_literal.zig"); |
number_literalzig/number_literal.zigReturns the standard file system basename of a binary generated by the Zig compiler. |
pub const number_literal = @import("zig/number_literal.zig"); |
primitiveszig/primitives.zigResult is byte values, *not* hex-encoded. |
pub const primitives = @import("zig/primitives.zig"); |
isPrimitiveInput is byte values, *not* hex-encoded.
Asserts |
pub const isPrimitive = primitives.isPrimitive; |
Astzig/Ast.zigConverts UTF-8 text to a |
pub const Ast = @import("zig/Ast.zig"); |
AstGenzig/AstGen.zigRenders a |
pub const AstGen = @import("zig/AstGen.zig"); |
Zirzig/Zir.zigResolving 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 |
pub const Zir = @import("zig/Zir.zig"); |
systemzig/system.zigWhen this tag is set, the code that constructed this |
pub const system = @import("zig/system.zig"); /// Deprecated: use `std.Target.Query`. |
CrossTargetMeans the source location points to an entire file; not any particular
location within the file. |
pub const CrossTarget = std.Target.Query; |
BuiltinFnzig/BuiltinFn.zigThe source location points to a byte offset within a source file,
offset from 0. The source file is determined contextually.
Inside a |
pub const BuiltinFn = @import("zig/BuiltinFn.zig"); |
AstRlAnnotatezig/AstRlAnnotate.zigThe source location points to a token within a source file,
offset from 0. The source file is determined contextually.
Inside a |
pub const AstRlAnnotate = @import("zig/AstRlAnnotate.zig"); |
LibCInstallationzig/LibCInstallation.zigThe source location points to an AST node within a source file,
offset from 0. The source file is determined contextually.
Inside a |
pub const LibCInstallation = @import("zig/LibCInstallation.zig"); |
WindowsSdkzig/WindowsSdk.zigThe 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. |
pub const WindowsSdk = @import("zig/WindowsSdk.zig"); |
LibCDirszig/LibCDirs.zigThis data is the offset into the token list from the Decl token. The Decl is determined contextually. |
pub const LibCDirs = @import("zig/LibCDirs.zig"); |
targetzig/target.zigThe source location points to an AST node, which is this value offset from its containing Decl node AST index. The Decl is determined contextually. |
pub const target = @import("zig/target.zig"); |
ParsedCharLiteralThe 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. |
// Character literal parsing pub const ParsedCharLiteral = string_literal.ParsedCharLiteral; |
parseCharLiteralThe source location points to the beginning of a struct initializer. The Decl is determined contextually. |
pub const parseCharLiteral = string_literal.parseCharLiteral; |
parseNumberLiteralThe 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. |
pub const parseNumberLiteral = number_literal.parseNumberLiteral; |
c_builtinszig/c_builtins.zigThe source location points to the alignment expression of a var decl. The Decl is determined contextually. |
// Files needed by translate-c. pub const c_builtins = @import("zig/c_builtins.zig"); |
c_translationzig/c_translation.zigThe source location points to the linksection expression of a var decl. The Decl is determined contextually. |
pub const c_translation = @import("zig/c_translation.zig"); |
SrcHasherThe source location points to the addrspace expression of a var decl. The Decl is determined contextually. |
pub const SrcHasher = std.crypto.hash.Blake3; |
SrcHashThe source location points to the initializer of a var decl. The Decl is determined contextually. |
pub const SrcHash = [16]u8; |
ColorThe 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. |
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, |
get_tty_conf()Same as |
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, }; } |
renderOptions()Like |
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, }; } }; |
max_src_sizeThe 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. |
/// 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); |
hashSrc()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. |
pub fn hashSrc(src: []const u8) SrcHash { var out: SrcHash = undefined; SrcHasher.hash(src, &out, .{}); return out; |
binNameAlloc()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. |
} |
hashName()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. |
pub fn srcHashEql(a: SrcHash, b: SrcHash) bool { return @as(u128, @bitCast(a)) == @as(u128, @bitCast(b)); |
binNameAlloc()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. |
} |
eql()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. |
pub fn hashName(parent_hash: SrcHash, sep: []const u8, name: []const u8) SrcHash { var out: SrcHash = undefined; var hasher = SrcHasher.init(.{}); hasher.update(&parent_hash); hasher.update(sep); hasher.update(name); hasher.final(&out); return out; |
binNameAlloc()The payload is offset from the containing Decl AST node.
The source location points to the field name of:
* a field access expression ( |
} |
lineDelta()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 ( |
pub const Loc = struct { line: usize, column: usize, /// Does not include the trailing newline. source_line: []const u8, |
BinNameOptionsThe 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. |
pub fn eql(a: Loc, b: Loc) bool { return a.line == b.line and a.column == b.column and std.mem.eql(u8, a.source_line, b.source_line); } }; |
binNameAlloc()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. |
pub fn findLineColumn(source: []const u8, byte_offset: usize) Loc { var line: usize = 0; var column: usize = 0; var line_start: usize = 0; var i: usize = 0; while (i < byte_offset) : (i += 1) { switch (source[i]) { '\n' => { line += 1; column = 0; line_start = i + 1; }, else => { column += 1; }, } } while (i < source.len and source[i] != '\n') { i += 1; } return .{ .line = line, .column = column, .source_line = source[line_start..i], }; } |
BuildIdThe 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. |
pub fn lineDelta(source: []const u8, start: usize, end: usize) isize { var line: isize = 0; if (end >= start) { for (source[start..end]) |byte| switch (byte) { '\n' => line += 1, else => continue, }; } else { for (source[end..start]) |byte| switch (byte) { '\n' => line -= 1, else => continue, }; } return line; } |
eql()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. |
pub const BinNameOptions = struct { root_name: []const u8, target: std.Target, output_mode: std.builtin.OutputMode, link_mode: ?std.builtin.LinkMode = null, version: ?std.SemanticVersion = null, }; |
HexStringThe source location points to a binary expression, such as |
/// Returns the standard file system basename of a binary generated by the Zig compiler. pub fn binNameAlloc(allocator: Allocator, options: BinNameOptions) error{OutOfMemory}![]u8 { const root_name = options.root_name; const t = options.target; switch (t.ofmt) { .coff => switch (options.output_mode) { .Exe => return std.fmt.allocPrint(allocator, "{s}{s}", .{ root_name, t.exeFileExt() }), .Lib => { const suffix = switch (options.link_mode orelse .static) { .static => ".lib", .dynamic => ".dll", }; return std.fmt.allocPrint(allocator, "{s}{s}", .{ root_name, suffix }); }, .Obj => return std.fmt.allocPrint(allocator, "{s}.obj", .{root_name}), }, .elf => switch (options.output_mode) { .Exe => return allocator.dupe(u8, root_name), .Lib => { switch (options.link_mode orelse .static) { .static => return std.fmt.allocPrint(allocator, "{s}{s}.a", .{ t.libPrefix(), root_name, }), .dynamic => { if (options.version) |ver| { return std.fmt.allocPrint(allocator, "{s}{s}.so.{d}.{d}.{d}", .{ t.libPrefix(), root_name, ver.major, ver.minor, ver.patch, }); } else { return std.fmt.allocPrint(allocator, "{s}{s}.so", .{ t.libPrefix(), root_name, }); } }, } }, .Obj => return std.fmt.allocPrint(allocator, "{s}.o", .{root_name}), }, .macho => switch (options.output_mode) { .Exe => return allocator.dupe(u8, root_name), .Lib => { switch (options.link_mode orelse .static) { .static => return std.fmt.allocPrint(allocator, "{s}{s}.a", .{ t.libPrefix(), root_name, }), .dynamic => { if (options.version) |ver| { return std.fmt.allocPrint(allocator, "{s}{s}.{d}.{d}.{d}.dylib", .{ t.libPrefix(), root_name, ver.major, ver.minor, ver.patch, }); } else { return std.fmt.allocPrint(allocator, "{s}{s}.dylib", .{ t.libPrefix(), root_name, }); } }, } }, .Obj => return std.fmt.allocPrint(allocator, "{s}.o", .{root_name}), }, .wasm => switch (options.output_mode) { .Exe => return std.fmt.allocPrint(allocator, "{s}{s}", .{ root_name, t.exeFileExt() }), .Lib => { switch (options.link_mode orelse .static) { .static => return std.fmt.allocPrint(allocator, "{s}{s}.a", .{ t.libPrefix(), root_name, }), .dynamic => return std.fmt.allocPrint(allocator, "{s}.wasm", .{root_name}), } }, .Obj => return std.fmt.allocPrint(allocator, "{s}.o", .{root_name}), }, .c => return std.fmt.allocPrint(allocator, "{s}.c", .{root_name}), .spirv => return std.fmt.allocPrint(allocator, "{s}.spv", .{root_name}), .hex => return std.fmt.allocPrint(allocator, "{s}.ihex", .{root_name}), .raw => return std.fmt.allocPrint(allocator, "{s}.bin", .{root_name}), .plan9 => switch (options.output_mode) { .Exe => return allocator.dupe(u8, root_name), .Obj => return std.fmt.allocPrint(allocator, "{s}{s}", .{ root_name, t.ofmt.fileExt(t.cpu.arch), }), .Lib => return std.fmt.allocPrint(allocator, "{s}{s}.a", .{ t.libPrefix(), root_name, }), }, .nvptx => return std.fmt.allocPrint(allocator, "{s}.ptx", .{root_name}), .dxcontainer => return std.fmt.allocPrint(allocator, "{s}.dxil", .{root_name}), } } |
toSlice()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. |
pub const BuildId = union(enum) { none, fast, uuid, sha1, md5, hexstring: HexString, |
initHexString()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. |
pub fn eql(a: BuildId, b: BuildId) bool { const Tag = @typeInfo(BuildId).Union.tag_type.?; const a_tag: Tag = a; const b_tag: Tag = b; if (a_tag != b_tag) return false; return switch (a) { .none, .fast, .uuid, .sha1, .md5 => true, .hexstring => |a_hexstring| std.mem.eql(u8, a_hexstring.toSlice(), b.hexstring.toSlice()), }; } |
parse()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. |
pub const HexString = struct { bytes: [32]u8, len: u8, |
Test: parseThe source location points to the else/ |
/// Result is byte values, *not* hex-encoded. pub fn toSlice(hs: *const HexString) []const u8 { return hs.bytes[0..hs.len]; } }; |
serializeCpu()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. |
/// Input is byte values, *not* hex-encoded. /// Asserts `bytes` fits inside `HexString` pub fn initHexString(bytes: []const u8) BuildId { var result: BuildId = .{ .hexstring = .{ .bytes = undefined, .len = @intCast(bytes.len), } }; @memcpy(result.hexstring.bytes[0..bytes.len], bytes); return result; } |
serializeCpuAlloc()The source location points to the capture of a switch_prong. The Decl is determined contextually. |
/// Converts UTF-8 text to a `BuildId`. pub fn parse(text: []const u8) !BuildId { if (std.mem.eql(u8, text, "none")) { return .none; } else if (std.mem.eql(u8, text, "fast")) { return .fast; } else if (std.mem.eql(u8, text, "uuid")) { return .uuid; } else if (std.mem.eql(u8, text, "sha1") or std.mem.eql(u8, text, "tree")) { return .sha1; } else if (std.mem.eql(u8, text, "md5")) { return .md5; } else if (std.mem.startsWith(u8, text, "0x")) { var result: BuildId = .{ .hexstring = undefined }; const slice = try std.fmt.hexToBytes(&result.hexstring.bytes, text[2..]); result.hexstring.len = @as(u8, @intCast(slice.len)); return result; } return error.InvalidBuildIdStyle; } |
DeclIndexThe source location points to the tag capture of a switch_prong. The Decl is determined contextually. |
test parse { try std.testing.expectEqual(BuildId.md5, try parse("md5")); try std.testing.expectEqual(BuildId.none, try parse("none")); try std.testing.expectEqual(BuildId.fast, try parse("fast")); try std.testing.expectEqual(BuildId.uuid, try parse("uuid")); try std.testing.expectEqual(BuildId.sha1, try parse("sha1")); try std.testing.expectEqual(BuildId.sha1, try parse("tree")); |
toOptional()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. |
try std.testing.expect(BuildId.initHexString("").eql(try parse("0x"))); try std.testing.expect(BuildId.initHexString("\x12\x34\x56").eql(try parse("0x123456"))); try std.testing.expectError(error.InvalidLength, parse("0x12-34")); try std.testing.expectError(error.InvalidCharacter, parse("0xfoobbb")); try std.testing.expectError(error.InvalidBuildIdStyle, parse("yaddaxxx")); } }; |
OptionalDeclIndexThe 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. |
/// Renders a `std.Target.Cpu` value into a textual representation that can be parsed /// via the `-mcpu` flag passed to the Zig compiler. /// Appends the result to `buffer`. pub fn serializeCpu(buffer: *std.ArrayList(u8), cpu: std.Target.Cpu) Allocator.Error!void { const all_features = cpu.arch.allFeaturesList(); var populated_cpu_features = cpu.model.features; populated_cpu_features.populateDependencies(all_features); |
init()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. |
try buffer.appendSlice(cpu.model.name); |
unwrap()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. |
if (populated_cpu_features.eql(cpu.features)) { // The CPU name alone is sufficient. return; } |
LazySrcLocThe 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. |
for (all_features, 0..) |feature, i_usize| { const i: std.Target.Cpu.Feature.Set.Index = @intCast(i_usize); const in_cpu_set = populated_cpu_features.isEnabled(i); const in_actual_set = cpu.features.isEnabled(i); try buffer.ensureUnusedCapacity(feature.name.len + 1); if (in_cpu_set and !in_actual_set) { buffer.appendAssumeCapacity('-'); buffer.appendSliceAssumeCapacity(feature.name); } else if (!in_cpu_set and in_actual_set) { buffer.appendAssumeCapacity('+'); buffer.appendSliceAssumeCapacity(feature.name); } } } |
nodeOffsetThe source location points to the type expression of an |
pub fn serializeCpuAlloc(ally: Allocator, cpu: std.Target.Cpu) Allocator.Error![]u8 { var buffer = std.ArrayList(u8).init(ally); try serializeCpu(&buffer, cpu); return buffer.toOwnedSlice(); } |
TracedOffsetThe source location points to the string literal of |
pub const DeclIndex = enum(u32) { _, |
fmtId()The source location points to the len expression of an |
pub fn toOptional(i: DeclIndex) OptionalDeclIndex { return @enumFromInt(@intFromEnum(i)); } }; |
Test: fmtIdThe source location points to the sentinel expression of an |
pub const OptionalDeclIndex = enum(u32) { none = std.math.maxInt(u32), _, |
fmtEscapes()The source location points to the elem expression of an |
pub fn init(oi: ?DeclIndex) OptionalDeclIndex { return @enumFromInt(@intFromEnum(oi orelse return .none)); } |
Test: fmtEscapesThe source location points to the operand of an unary expression. The Decl is determined contextually. |
pub fn unwrap(oi: OptionalDeclIndex) ?DeclIndex { if (oi == .none) return null; return @enumFromInt(@intFromEnum(oi)); } }; |
stringEscape()The source location points to the elem type of a pointer. The Decl is determined contextually. |
/// 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, |
isValidId()The source location points to the sentinel of a pointer. The Decl is determined contextually. |
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, }; |
Test: isValidIdThe source location points to the align expr of a pointer. The Decl is determined contextually. |
pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease; |
isUnderscore()The source location points to the addrspace expr of a pointer. The Decl is determined contextually. |
noinline fn nodeOffsetDebug(node_offset: i32) LazySrcLoc { var result: LazySrcLoc = .{ .node_offset = .{ .x = node_offset } }; result.node_offset.trace.addAddr(@returnAddress(), "init"); return result; } |
Test: isUnderscoreThe source location points to the bit-offset of a pointer. The Decl is determined contextually. |
fn nodeOffsetRelease(node_offset: i32) LazySrcLoc { return .{ .node_offset = .{ .x = node_offset } }; } |
readSourceFileToEndAlloc()The source location points to the host size of a pointer. The Decl is determined contextually. |
/// 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 = std.debug.Trace.init, |
printAstErrorsToStderr()The source location points to the tag type of an union or an enum. The Decl is determined contextually. |
const want_tracing = false; }; }; |
putAstErrorsIntoBundle()The source location points to the default value of a field. The Decl is determined contextually. |
const std = @import("std.zig"); const tokenizer = @import("zig/tokenizer.zig"); const assert = std.debug.assert; const Allocator = std.mem.Allocator; |
resolveTargetQueryOrFatal()The source location points to the type of an array or struct initializer. The Decl is determined contextually. |
/// Return a Formatter for a Zig identifier, escaping it with `@""` syntax if needed. /// /// - An empty `{}` format specifier escapes invalid identifiers, identifiers that shadow primitives /// and the reserved `_` identifier. /// - Add `p` to the specifier to render identifiers that shadow primitives unescaped. /// - Add `_` to the specifier to render the reserved `_` identifier unescaped. /// - `p` and `_` can be combined, e.g. `{p_}`. /// pub fn fmtId(bytes: []const u8) std.fmt.Formatter(formatId) { return .{ .data = bytes }; } |
parseTargetQueryOrReportFatalError()The source location points to the LHS of an assignment. The Decl is determined contextually. |
test fmtId { const expectFmt = std.testing.expectFmt; try expectFmt("@\"while\"", "{}", .{fmtId("while")}); try expectFmt("@\"while\"", "{p}", .{fmtId("while")}); try expectFmt("@\"while\"", "{_}", .{fmtId("while")}); try expectFmt("@\"while\"", "{p_}", .{fmtId("while")}); try expectFmt("@\"while\"", "{_p}", .{fmtId("while")}); |
fatal()The source location points to the RHS of an assignment. The Decl is determined contextually. |
try expectFmt("hello", "{}", .{fmtId("hello")}); try expectFmt("hello", "{p}", .{fmtId("hello")}); try expectFmt("hello", "{_}", .{fmtId("hello")}); try expectFmt("hello", "{p_}", .{fmtId("hello")}); try expectFmt("hello", "{_p}", .{fmtId("hello")}); |
EnvVarThe source location points to the operand of a |
try expectFmt("@\"type\"", "{}", .{fmtId("type")}); try expectFmt("type", "{p}", .{fmtId("type")}); try expectFmt("@\"type\"", "{_}", .{fmtId("type")}); try expectFmt("type", "{p_}", .{fmtId("type")}); try expectFmt("type", "{_p}", .{fmtId("type")}); |
isSet()The source location points to a for loop input. The Decl is determined contextually. |
try expectFmt("@\"_\"", "{}", .{fmtId("_")}); try expectFmt("@\"_\"", "{p}", .{fmtId("_")}); try expectFmt("_", "{_}", .{fmtId("_")}); try expectFmt("_", "{p_}", .{fmtId("_")}); try expectFmt("_", "{_p}", .{fmtId("_")}); |
get()Points to the for loop AST node. |
try expectFmt("@\"i123\"", "{}", .{fmtId("i123")}); try expectFmt("i123", "{p}", .{fmtId("i123")}); try expectFmt("@\"4four\"", "{}", .{fmtId("4four")}); try expectFmt("_underscore", "{}", .{fmtId("_underscore")}); try expectFmt("@\"11\\\"23\"", "{}", .{fmtId("11\"23")}); try expectFmt("@\"11\\x0f23\"", "{}", .{fmtId("11\x0F23")}); |
getPosix()Picks one of the inputs from the condition. |
// These are technically not currently legal in Zig. try expectFmt("@\"\"", "{}", .{fmtId("")}); try expectFmt("@\"\\x00\"", "{}", .{fmtId("\x00")}); } /// 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 { const allow_primitive, const allow_underscore = comptime parse_fmt: { var allow_primitive = false; var allow_underscore = false; for (fmt) |char| { switch (char) { 'p' => if (!allow_primitive) { allow_primitive = true; continue; }, '_' => if (!allow_underscore) { allow_underscore = true; continue; }, else => {}, } @compileError("expected {}, {p}, {_}, {p_} or {_p}, found {" ++ fmt ++ "}"); } break :parse_fmt .{ allow_primitive, allow_underscore }; }; if (isValidId(bytes) and (allow_primitive or !std.zig.isPrimitive(bytes)) and (allow_underscore or !isUnderscore(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 fmtEscapes { const expectFmt = std.testing.expectFmt; 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; 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 isUnderscore(bytes: []const u8) bool { return bytes.len == 1 and bytes[0] == '_'; } test isUnderscore { try std.testing.expect(isUnderscore("_")); try std.testing.expect(!isUnderscore("__")); try std.testing.expect(!isUnderscore("_foo")); try std.testing.expect(isUnderscore("\x5f")); try std.testing.expect(!isUnderscore("\\x5f")); } 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); } pub fn resolveTargetQueryOrFatal(target_query: std.Target.Query) std.Target { return std.zig.system.resolveTargetQuery(target_query) catch |err| fatal("unable to resolve target: {s}", .{@errorName(err)}); } pub fn parseTargetQueryOrReportFatalError( allocator: Allocator, opts: std.Target.Query.ParseOptions, ) std.Target.Query { var opts_with_diags = opts; var diags: std.Target.Query.ParseOptions.Diagnostics = .{}; if (opts_with_diags.diagnostics == null) { opts_with_diags.diagnostics = &diags; } return std.Target.Query.parse(opts_with_diags) catch |err| switch (err) { error.UnknownCpuModel => { help: { var help_text = std.ArrayList(u8).init(allocator); defer help_text.deinit(); for (diags.arch.?.allCpuModels()) |cpu| { help_text.writer().print(" {s}\n", .{cpu.name}) catch break :help; } std.log.info("available CPUs for architecture '{s}':\n{s}", .{ @tagName(diags.arch.?), help_text.items, }); } fatal("unknown CPU: '{s}'", .{diags.cpu_name.?}); }, error.UnknownCpuFeature => { help: { var help_text = std.ArrayList(u8).init(allocator); defer help_text.deinit(); for (diags.arch.?.allFeaturesList()) |feature| { help_text.writer().print(" {s}: {s}\n", .{ feature.name, feature.description }) catch break :help; } std.log.info("available CPU features for architecture '{s}':\n{s}", .{ @tagName(diags.arch.?), help_text.items, }); } fatal("unknown CPU feature: '{s}'", .{diags.unknown_feature_name.?}); }, error.UnknownObjectFormat => { help: { var help_text = std.ArrayList(u8).init(allocator); defer help_text.deinit(); inline for (@typeInfo(std.Target.ObjectFormat).Enum.fields) |field| { help_text.writer().print(" {s}\n", .{field.name}) catch break :help; } std.log.info("available object formats:\n{s}", .{help_text.items}); } fatal("unknown object format: '{s}'", .{opts.object_format.?}); }, else => |e| fatal("unable to parse target query '{s}': {s}", .{ opts.arch_os_abi, @errorName(e), }), }; } pub fn fatal(comptime format: []const u8, args: anytype) noreturn { std.log.err(format, args); std.process.exit(1); } /// Collects all the environment variables that Zig could possibly inspect, so /// that we can do reflection on this and print them with `zig env`. pub const EnvVar = enum { ZIG_GLOBAL_CACHE_DIR, ZIG_LOCAL_CACHE_DIR, ZIG_LIB_DIR, ZIG_LIBC, ZIG_BUILD_RUNNER, ZIG_VERBOSE_LINK, ZIG_VERBOSE_CC, ZIG_BTRFS_WORKAROUND, ZIG_DEBUG_CMD, CC, NO_COLOR, CLICOLOR_FORCE, XDG_CACHE_HOME, HOME, pub fn isSet(comptime ev: EnvVar) bool { return std.process.hasEnvVarConstant(@tagName(ev)); } pub fn get(ev: EnvVar, arena: std.mem.Allocator) !?[]u8 { if (std.process.getEnvVarOwned(arena, @tagName(ev))) |value| { return value; } else |err| switch (err) { error.EnvironmentVariableNotFound => return null, else => |e| return e, } } pub fn getPosix(comptime ev: EnvVar) ?[:0]const u8 { return std.posix.getenvZ(@tagName(ev)); } }; test { _ = Ast; _ = AstRlAnnotate; _ = BuiltinFn; _ = Client; _ = ErrorBundle; _ = LibCDirs; _ = LibCInstallation; _ = Server; _ = WindowsSdk; _ = number_literal; _ = primitives; _ = string_literal; _ = system; _ = target; _ = c_translation; } |
Generated by zstd-live on 2025-08-12 12:37:57 UTC. |