@@ -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);
}
};