compiler: ensure result of block_comptime is comptime-known

To avoid this PR regressing error messages, most of the work here has
gone towards improving error notes for why code was comptime-evaluated.
ZIR `block_comptime` now stores a "comptime reason", the enum for which
is also used by Sema. There are two types in Sema:

* `ComptimeReason` represents the reason we started evaluating something
  at comptime.
* `BlockComptimeReason` represents the reason a given block is evaluated
  at comptime; it's either a `ComptimeReason` with an attached source
  location, or it's because we're in a function which was called at
  comptime (and that function's `Block` should be consulted for the
  "parent" reason).

Every `Block` stores a `?BlockComptimeReason`. The old `is_comptime`
field is replaced with a trivial `isComptime()` method which returns
whether that reason is non-`null`.

Lastly, the handling for `block_comptime` has been simplified. It was
previously going through an unnecessary runtime-handling path; now, it
is a trivial sub block exited through a `break_inline` instruction.

Resolves: #22296
This commit is contained in:
mlugg 2024-12-29 16:24:07 +00:00
parent 6d67658965
commit 6026a5f217
No known key found for this signature in database
GPG Key ID: 3F5B7DCCBF4AF02E
7 changed files with 824 additions and 661 deletions

View File

@ -718,6 +718,165 @@ pub const EnvVar = enum {
}
};
pub const SimpleComptimeReason = enum(u32) {
// Evaluating at comptime because a builtin operand must be comptime-known.
// These messages all mention a specific builtin.
operand_Type,
operand_setEvalBranchQuota,
operand_setFloatMode,
operand_branchHint,
operand_setRuntimeSafety,
operand_embedFile,
operand_cImport,
operand_cDefine_macro_name,
operand_cDefine_macro_value,
operand_cInclude_file_name,
operand_cUndef_macro_name,
operand_shuffle_mask,
operand_atomicRmw_operation,
operand_reduce_operation,
// Evaluating at comptime because an operand must be comptime-known.
// These messages do not mention a specific builtin (and may not be about a builtin at all).
export_target,
export_options,
extern_options,
prefetch_options,
call_modifier,
compile_error_string,
inline_assembly_code,
atomic_order,
array_mul_factor,
slice_cat_operand,
comptime_call_target,
wasm_memory_index,
work_group_dim_index,
// Evaluating at comptime because types must be comptime-known.
// Reasons other than `.type` are just more specific messages.
type,
array_sentinel,
pointer_sentinel,
slice_sentinel,
array_length,
vector_length,
error_set_contents,
struct_fields,
enum_fields,
union_fields,
function_ret_ty,
function_parameters,
// Evaluating at comptime because decl/field name must be comptime-known.
decl_name,
field_name,
struct_field_name,
enum_field_name,
union_field_name,
tuple_field_name,
tuple_field_index,
// Evaluating at comptime because it is an attribute of a global declaration.
container_var_init,
@"callconv",
@"align",
@"addrspace",
@"linksection",
// Miscellaneous reasons.
comptime_keyword,
comptime_call_modifier,
switch_item,
tuple_field_default_value,
struct_field_default_value,
enum_field_tag_value,
slice_single_item_ptr_bounds,
comptime_param_arg,
stored_to_comptime_field,
stored_to_comptime_var,
casted_to_comptime_enum,
casted_to_comptime_int,
casted_to_comptime_float,
panic_handler,
pub fn message(r: SimpleComptimeReason) []const u8 {
return switch (r) {
// zig fmt: off
.operand_Type => "operand to '@Type' must be comptime-known",
.operand_setEvalBranchQuota => "operand to '@setEvalBranchQuota' must be comptime-known",
.operand_setFloatMode => "operand to '@setFloatMode' must be comptime-known",
.operand_branchHint => "operand to '@branchHint' must be comptime-known",
.operand_setRuntimeSafety => "operand to '@setRuntimeSafety' must be comptime-known",
.operand_embedFile => "operand to '@embedFile' must be comptime-known",
.operand_cImport => "operand to '@cImport' is evaluated at comptime",
.operand_cDefine_macro_name => "'@cDefine' macro name must be comptime-known",
.operand_cDefine_macro_value => "'@cDefine' macro value must be comptime-known",
.operand_cInclude_file_name => "'@cInclude' file name must be comptime-known",
.operand_cUndef_macro_name => "'@cUndef' macro name must be comptime-known",
.operand_shuffle_mask => "'@shuffle' mask must be comptime-known",
.operand_atomicRmw_operation => "'@atomicRmw' operation must be comptime-known",
.operand_reduce_operation => "'@reduce' operation must be comptime-known",
.export_target => "export target must be comptime-known",
.export_options => "export options must be comptime-known",
.extern_options => "extern options must be comptime-known",
.prefetch_options => "prefetch options must be comptime-known",
.call_modifier => "call modifier must be comptime-known",
.compile_error_string => "compile error string must be comptime-known",
.inline_assembly_code => "inline assembly code must be comptime-known",
.atomic_order => "atomic order must be comptime-known",
.array_mul_factor => "array multiplication factor must be comptime-known",
.slice_cat_operand => "slice being concatenated must be comptime-known",
.comptime_call_target => "function being called at comptime must be comptime-known",
.wasm_memory_index => "wasm memory index must be comptime-known",
.work_group_dim_index => "work group dimension index must be comptime-known",
.type => "types must be comptime-known",
.array_sentinel => "array sentinel value must be comptime-known",
.pointer_sentinel => "pointer sentinel value must be comptime-known",
.slice_sentinel => "slice sentinel value must be comptime-known",
.array_length => "array length must be comptime-known",
.vector_length => "vector length must be comptime-known",
.error_set_contents => "error set contents must be comptime-known",
.struct_fields => "struct fields must be comptime-known",
.enum_fields => "enum fields must be comptime-known",
.union_fields => "union fields must be comptime-known",
.function_ret_ty => "function return type must be comptime-known",
.function_parameters => "function parameters must be comptime-known",
.decl_name => "declaration name must be comptime-known",
.field_name => "field name must be comptime-known",
.struct_field_name => "struct field name must be comptime-known",
.enum_field_name => "enum field name must be comptime-known",
.union_field_name => "union field name must be comptime-known",
.tuple_field_name => "tuple field name must be comptime-known",
.tuple_field_index => "tuple field index must be comptime-known",
.container_var_init => "initializer of container-level variable must be comptime-known",
.@"callconv" => "calling convention must be comptime-known",
.@"align" => "alignment must be comptime-known",
.@"addrspace" => "address space must be comptime-known",
.@"linksection" => "linksection must be comptime-known",
.comptime_keyword => "'comptime' keyword forces comptime evaluation",
.comptime_call_modifier => "'.compile_time' call modifier forces comptime evaluation",
.switch_item => "switch prong values must be comptime-known",
.tuple_field_default_value => "tuple field default value must be comptime-known",
.struct_field_default_value => "struct field default value must be comptime-known",
.enum_field_tag_value => "enum field tag value must be comptime-known",
.slice_single_item_ptr_bounds => "slice of single-item pointer must have comptime-known bounds",
.comptime_param_arg => "argument to comptime parameter must be comptime-known",
.stored_to_comptime_field => "value stored to a comptime field must be comptime-known",
.stored_to_comptime_var => "value stored to a comptime variable must be comptime-known",
.casted_to_comptime_enum => "value casted to enum with 'comptime_int' tag type must be comptime-known",
.casted_to_comptime_int => "value casted to 'comptime_int' must be comptime-known",
.casted_to_comptime_float => "value casted to 'comptime_float' must be comptime-known",
.panic_handler => "panic handler must be comptime-known",
// zig fmt: on
};
}
};
test {
_ = Ast;
_ = AstRlAnnotate;

View File

@ -97,6 +97,7 @@ fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void {
Zir.Inst.Ref,
Zir.Inst.Index,
Zir.Inst.Declaration.Name,
std.zig.SimpleComptimeReason,
Zir.NullTerminatedString,
=> @intFromEnum(@field(extra, field.name)),
@ -379,7 +380,7 @@ const coerced_type_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .type_type } };
const coerced_bool_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .bool_type } };
fn typeExpr(gz: *GenZir, scope: *Scope, type_node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
return comptimeExpr(gz, scope, coerced_type_ri, type_node);
return comptimeExpr(gz, scope, coerced_type_ri, type_node, .type);
}
fn reachableTypeExpr(
@ -388,7 +389,7 @@ fn reachableTypeExpr(
type_node: Ast.Node.Index,
reachable_node: Ast.Node.Index,
) InnerError!Zir.Inst.Ref {
return reachableExprComptime(gz, scope, coerced_type_ri, type_node, reachable_node, true);
return reachableExprComptime(gz, scope, coerced_type_ri, type_node, reachable_node, .type);
}
/// Same as `expr` but fails with a compile error if the result type is `noreturn`.
@ -399,7 +400,7 @@ fn reachableExpr(
node: Ast.Node.Index,
reachable_node: Ast.Node.Index,
) InnerError!Zir.Inst.Ref {
return reachableExprComptime(gz, scope, ri, node, reachable_node, false);
return reachableExprComptime(gz, scope, ri, node, reachable_node, null);
}
fn reachableExprComptime(
@ -408,10 +409,11 @@ fn reachableExprComptime(
ri: ResultInfo,
node: Ast.Node.Index,
reachable_node: Ast.Node.Index,
force_comptime: bool,
/// If `null`, the expression is not evaluated in a comptime context.
comptime_reason: ?std.zig.SimpleComptimeReason,
) InnerError!Zir.Inst.Ref {
const result_inst = if (force_comptime)
try comptimeExpr(gz, scope, ri, node)
const result_inst = if (comptime_reason) |r|
try comptimeExpr(gz, scope, ri, node, r)
else
try expr(gz, scope, ri, node);
@ -782,7 +784,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
const result = try gz.addPlNode(.array_mul, node, Zir.Inst.ArrayMul{
.res_ty = if (try ri.rl.resultType(gz, node)) |t| t else .none,
.lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs),
.rhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs),
.rhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs, .array_mul_factor),
});
return rvalue(gz, ri, result, node);
},
@ -1453,7 +1455,7 @@ fn arrayInitExpr(
});
break :inst .{ array_type_inst, elem_type };
} else {
const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, array_type.ast.sentinel);
const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, array_type.ast.sentinel, .array_sentinel);
const array_type_inst = try gz.addPlNode(
.array_type_sentinel,
array_init.ast.type_expr,
@ -1721,7 +1723,7 @@ fn structInitExpr(
.rhs = elem_type,
});
} else blk: {
const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, array_type.ast.sentinel);
const sentinel = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, array_type.ast.sentinel, .array_sentinel);
break :blk try gz.addPlNode(
.array_type_sentinel,
struct_init.ast.type_expr,
@ -1966,6 +1968,20 @@ fn comptimeExpr(
scope: *Scope,
ri: ResultInfo,
node: Ast.Node.Index,
reason: std.zig.SimpleComptimeReason,
) InnerError!Zir.Inst.Ref {
return comptimeExpr2(gz, scope, ri, node, node, reason);
}
/// Like `comptimeExpr`, but draws a distinction between `node`, the expression to evaluate at comptime,
/// and `src_node`, the node to attach to the `block_comptime`.
fn comptimeExpr2(
gz: *GenZir,
scope: *Scope,
ri: ResultInfo,
node: Ast.Node.Index,
src_node: Ast.Node.Index,
reason: std.zig.SimpleComptimeReason,
) InnerError!Zir.Inst.Ref {
if (gz.is_comptime) {
// No need to change anything!
@ -2049,23 +2065,23 @@ fn comptimeExpr(
block_scope.is_comptime = true;
defer block_scope.unstack();
const block_inst = try gz.makeBlockInst(.block_comptime, node);
const block_inst = try gz.makeBlockInst(.block_comptime, src_node);
// Replace result location and copy back later - see above.
const ty_only_ri: ResultInfo = .{
.ctx = ri.ctx,
.rl = if (try ri.rl.resultType(gz, node)) |res_ty|
.rl = if (try ri.rl.resultType(gz, src_node)) |res_ty|
.{ .coerced_ty = res_ty }
else
.none,
};
const block_result = try fullBodyExpr(&block_scope, scope, ty_only_ri, node, .normal);
if (!gz.refIsNoReturn(block_result)) {
_ = try block_scope.addBreak(.@"break", block_inst, block_result);
_ = try block_scope.addBreak(.break_inline, block_inst, block_result);
}
try block_scope.setBlockBody(block_inst);
try block_scope.setBlockComptimeBody(block_inst, reason);
try gz.instructions.append(gz.astgen.gpa, block_inst);
return rvalue(gz, ri, block_inst.toRef(), node);
return rvalue(gz, ri, block_inst.toRef(), src_node);
}
/// This one is for an actual `comptime` syntax, and will emit a compile error if
@ -2084,7 +2100,7 @@ fn comptimeExprAst(
const tree = astgen.tree;
const node_datas = tree.nodes.items(.data);
const body_node = node_datas[node].lhs;
return comptimeExpr(gz, scope, ri, body_node);
return comptimeExpr2(gz, scope, ri, body_node, node, .comptime_keyword);
}
/// Restore the error return trace index. Performs the restore only if the result is a non-error or
@ -2494,10 +2510,10 @@ fn labeledBlockExpr(
// Reserve the Block ZIR instruction index so that we can put it into the GenZir struct
// so that break statements can reference it.
const block_tag: Zir.Inst.Tag = if (force_comptime) .block_comptime else .block;
const block_inst = try gz.makeBlockInst(block_tag, block_node);
const block_inst = try gz.makeBlockInst(if (force_comptime) .block_comptime else .block, block_node);
try gz.instructions.append(astgen.gpa, block_inst);
var block_scope = gz.makeSubBlock(parent_scope);
block_scope.is_inline = force_comptime;
block_scope.label = GenZir.Label{
.token = label_token,
.block_inst = block_inst,
@ -2511,14 +2527,20 @@ fn labeledBlockExpr(
// As our last action before the return, "pop" the error trace if needed
_ = try gz.addRestoreErrRetIndex(.{ .block = block_inst }, .always, block_node);
const result = try rvalue(gz, block_scope.break_result_info, .void_value, block_node);
_ = try block_scope.addBreak(.@"break", block_inst, result);
const break_tag: Zir.Inst.Tag = if (force_comptime) .break_inline else .@"break";
_ = try block_scope.addBreak(break_tag, block_inst, result);
}
if (!block_scope.label.?.used) {
try astgen.appendErrorTok(label_token, "unused block label", .{});
}
try block_scope.setBlockBody(block_inst);
if (force_comptime) {
try block_scope.setBlockComptimeBody(block_inst, .comptime_keyword);
} else {
try block_scope.setBlockBody(block_inst);
}
if (need_result_rvalue) {
return rvalue(gz, ri, block_inst.toRef(), block_node);
} else {
@ -3255,7 +3277,7 @@ fn varDecl(
} else .{ .rl = .none, .ctx = .const_init };
const prev_anon_name_strategy = gz.anon_name_strategy;
gz.anon_name_strategy = .dbg_var;
const init_inst = try reachableExprComptime(gz, scope, result_info, var_decl.ast.init_node, node, force_comptime);
const init_inst = try reachableExprComptime(gz, scope, result_info, var_decl.ast.init_node, node, if (force_comptime) .comptime_keyword else null);
gz.anon_name_strategy = prev_anon_name_strategy;
try gz.addDbgVar(.dbg_var_val, ident_name, init_inst);
@ -3321,7 +3343,7 @@ fn varDecl(
const prev_anon_name_strategy = gz.anon_name_strategy;
gz.anon_name_strategy = .dbg_var;
defer gz.anon_name_strategy = prev_anon_name_strategy;
const init_inst = try reachableExprComptime(gz, scope, init_result_info, var_decl.ast.init_node, node, force_comptime);
const init_inst = try reachableExprComptime(gz, scope, init_result_info, var_decl.ast.init_node, node, if (force_comptime) .comptime_keyword else null);
// The const init expression may have modified the error return trace, so signal
// to Sema that it should save the new index for restoring later.
@ -3393,7 +3415,14 @@ fn varDecl(
};
const prev_anon_name_strategy = gz.anon_name_strategy;
gz.anon_name_strategy = .dbg_var;
_ = try reachableExprComptime(gz, scope, result_info, var_decl.ast.init_node, node, is_comptime);
_ = try reachableExprComptime(
gz,
scope,
result_info,
var_decl.ast.init_node,
node,
if (var_decl.comptime_token != null) .comptime_keyword else null,
);
gz.anon_name_strategy = prev_anon_name_strategy;
const final_ptr: Zir.Inst.Ref = if (resolve_inferred) ptr: {
break :ptr try gz.addUnNode(.resolve_inferred_alloc, alloc, node);
@ -3501,8 +3530,8 @@ fn assignDestructure(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerErro
if (full.comptime_token) |_| {
const comptime_block_inst = try gz.makeBlockInst(.block_comptime, node);
_ = try inner_gz.addBreak(.@"break", comptime_block_inst, .void_value);
try inner_gz.setBlockBody(comptime_block_inst);
_ = try inner_gz.addBreak(.break_inline, comptime_block_inst, .void_value);
try inner_gz.setBlockComptimeBody(comptime_block_inst, .comptime_keyword);
try gz.instructions.append(gz.astgen.gpa, comptime_block_inst);
}
}
@ -3673,8 +3702,8 @@ fn assignDestructureMaybeDecls(
// Finish the block_comptime. Inferred alloc resolution etc will occur
// in the parent block.
const comptime_block_inst = try gz.makeBlockInst(.block_comptime, node);
_ = try inner_gz.addBreak(.@"break", comptime_block_inst, .void_value);
try inner_gz.setBlockBody(comptime_block_inst);
_ = try inner_gz.addBreak(.break_inline, comptime_block_inst, .void_value);
try inner_gz.setBlockComptimeBody(comptime_block_inst, .comptime_keyword);
try gz.instructions.append(gz.astgen.gpa, comptime_block_inst);
}
@ -3867,7 +3896,16 @@ fn ptrType(
gz.astgen.source_line = source_line;
gz.astgen.source_column = source_column;
sentinel_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = elem_type } }, ptr_info.ast.sentinel);
sentinel_ref = try comptimeExpr(
gz,
scope,
.{ .rl = .{ .ty = elem_type } },
ptr_info.ast.sentinel,
switch (ptr_info.size) {
.Slice => .slice_sentinel,
else => .pointer_sentinel,
},
);
trailing_count += 1;
}
if (ptr_info.ast.addrspace_node != 0) {
@ -3953,7 +3991,7 @@ fn arrayType(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) !
{
return astgen.failNode(len_node, "unable to infer array size", .{});
}
const len = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, len_node);
const len = try reachableExprComptime(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, len_node, node, .type);
const elem_type = try typeExpr(gz, scope, node_datas[node].rhs);
const result = try gz.addPlNode(.array_type, node, Zir.Inst.Bin{
@ -3977,9 +4015,9 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.
{
return astgen.failNode(len_node, "unable to infer array size", .{});
}
const len = try reachableExpr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, len_node, node);
const len = try reachableExprComptime(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, len_node, node, .array_length);
const elem_type = try typeExpr(gz, scope, extra.elem_type);
const sentinel = try reachableExprComptime(gz, scope, .{ .rl = .{ .coerced_ty = elem_type } }, extra.sentinel, node, true);
const sentinel = try reachableExprComptime(gz, scope, .{ .rl = .{ .coerced_ty = elem_type } }, extra.sentinel, node, .array_sentinel);
const result = try gz.addPlNode(.array_type_sentinel, node, Zir.Inst.ArrayTypeSentinel{
.len = len,
@ -5321,7 +5359,7 @@ fn tupleDecl(
astgen.scratch.appendAssumeCapacity(@intFromEnum(field_type_ref));
if (field.ast.value_expr != 0) {
const field_init_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_type_ref } }, field.ast.value_expr);
const field_init_ref = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = field_type_ref } }, field.ast.value_expr, .tuple_field_default_value);
astgen.scratch.appendAssumeCapacity(@intFromEnum(field_init_ref));
} else {
astgen.scratch.appendAssumeCapacity(@intFromEnum(Zir.Inst.Ref.none));
@ -5693,7 +5731,7 @@ fn containerDecl(
namespace.base.tag = .namespace;
const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0)
try comptimeExpr(&block_scope, &namespace.base, coerced_type_ri, container_decl.ast.arg)
try comptimeExpr(&block_scope, &namespace.base, coerced_type_ri, container_decl.ast.arg, .type)
else
.none;
@ -7573,7 +7611,7 @@ fn switchExprErrUnion(
if (node_tags[item_node] == .switch_range) continue;
items_len += 1;
const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node);
const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node, .switch_item);
try payloads.append(gpa, @intFromEnum(item_inst));
}
@ -7583,8 +7621,8 @@ fn switchExprErrUnion(
if (node_tags[range] != .switch_range) continue;
ranges_len += 1;
const first = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].lhs);
const last = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].rhs);
const first = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].lhs, .switch_item);
const last = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].rhs, .switch_item);
try payloads.appendSlice(gpa, &[_]u32{
@intFromEnum(first), @intFromEnum(last),
});
@ -7602,7 +7640,7 @@ fn switchExprErrUnion(
scalar_case_index += 1;
try payloads.resize(gpa, header_index + 2); // item, body_len
const item_node = case.ast.values[0];
const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node);
const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node, .switch_item);
payloads.items[header_index] = @intFromEnum(item_inst);
break :blk header_index + 1;
};
@ -8046,7 +8084,7 @@ fn switchExpr(
if (node_tags[item_node] == .switch_range) continue;
items_len += 1;
const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node);
const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node, .switch_item);
try payloads.append(gpa, @intFromEnum(item_inst));
}
@ -8056,8 +8094,8 @@ fn switchExpr(
if (node_tags[range] != .switch_range) continue;
ranges_len += 1;
const first = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].lhs);
const last = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].rhs);
const first = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].lhs, .switch_item);
const last = try comptimeExpr(parent_gz, scope, item_ri, node_datas[range].rhs, .switch_item);
try payloads.appendSlice(gpa, &[_]u32{
@intFromEnum(first), @intFromEnum(last),
});
@ -8075,7 +8113,7 @@ fn switchExpr(
scalar_case_index += 1;
try payloads.resize(gpa, header_index + 2); // item, body_len
const item_node = case.ast.values[0];
const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node);
const item_inst = try comptimeExpr(parent_gz, scope, item_ri, item_node, .switch_item);
payloads.items[header_index] = @intFromEnum(item_inst);
break :blk header_index + 1;
};
@ -8836,7 +8874,7 @@ fn asmExpr(
},
else => .{
.tag = .asm_expr,
.tmpl = @enumFromInt(@intFromEnum(try comptimeExpr(gz, scope, .{ .rl = .none }, full.ast.template))),
.tmpl = @enumFromInt(@intFromEnum(try comptimeExpr(gz, scope, .{ .rl = .none }, full.ast.template, .inline_assembly_code))),
},
};
@ -8973,7 +9011,7 @@ fn unionInit(
params: []const Ast.Node.Index,
) InnerError!Zir.Inst.Ref {
const union_type = try typeExpr(gz, scope, params[0]);
const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1]);
const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1], .union_field_name);
const field_type = try gz.addPlNode(.field_type_ref, node, Zir.Inst.FieldTypeRef{
.container_type = union_type,
.field_name = field_name,
@ -9078,7 +9116,7 @@ fn ptrCast(
const flags_int: FlagsInt = @bitCast(flags);
const cursor = maybeAdvanceSourceCursorToMainToken(gz, root_node);
const parent_ptr_type = try ri.rl.resultTypeForCast(gz, root_node, "@alignCast");
const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, node_datas[node].lhs);
const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, node_datas[node].lhs, .field_name);
const field_ptr = try expr(gz, scope, .{ .rl = .none }, node_datas[node].rhs);
try emitDbgStmt(gz, cursor);
const result = try gz.addExtendedPayloadSmall(.field_parent_ptr, flags_int, Zir.Inst.FieldParentPtr{
@ -9279,7 +9317,7 @@ fn builtinCall(
return astgen.failNode(node, "'@branchHint' must appear as the first statement in a function or conditional branch", .{});
}
const hint_ty = try gz.addBuiltinValue(node, .branch_hint);
const hint_val = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = hint_ty } }, params[0]);
const hint_val = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = hint_ty } }, params[0], .operand_branchHint);
_ = try gz.addExtendedPayload(.branch_hint, Zir.Inst.UnNode{
.node = gz.nodeIndexToRelative(node),
.operand = hint_val,
@ -9326,18 +9364,18 @@ fn builtinCall(
if (ri.rl == .ref or ri.rl == .ref_coerced_ty) {
return gz.addPlNode(.field_ptr_named, node, Zir.Inst.FieldNamed{
.lhs = try expr(gz, scope, .{ .rl = .ref }, params[0]),
.field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1]),
.field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1], .field_name),
});
}
const result = try gz.addPlNode(.field_val_named, node, Zir.Inst.FieldNamed{
.lhs = try expr(gz, scope, .{ .rl = .none }, params[0]),
.field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1]),
.field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1], .field_name),
});
return rvalue(gz, ri, result, node);
},
.FieldType => {
const ty_inst = try typeExpr(gz, scope, params[0]);
const name_inst = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1]);
const name_inst = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1], .field_name);
const result = try gz.addPlNode(.field_type_ref, node, Zir.Inst.FieldTypeRef{
.container_type = ty_inst,
.field_name = name_inst,
@ -9358,7 +9396,7 @@ fn builtinCall(
.@"export" => {
const exported = try expr(gz, scope, .{ .rl = .none }, params[0]);
const export_options_ty = try gz.addBuiltinValue(node, .export_options);
const options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = export_options_ty } }, params[1]);
const options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = export_options_ty } }, params[1], .export_options);
_ = try gz.addPlNode(.@"export", node, Zir.Inst.Export{
.exported = exported,
.options = options,
@ -9368,7 +9406,7 @@ fn builtinCall(
.@"extern" => {
const type_inst = try typeExpr(gz, scope, params[0]);
const extern_options_ty = try gz.addBuiltinValue(node, .extern_options);
const options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = extern_options_ty } }, params[1]);
const options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = extern_options_ty } }, params[1], .extern_options);
const result = try gz.addExtendedPayload(.builtin_extern, Zir.Inst.BinNode{
.node = gz.nodeIndexToRelative(node),
.lhs = type_inst,
@ -9560,7 +9598,7 @@ fn builtinCall(
// zig fmt: on
.wasm_memory_size => {
const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0]);
const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0], .wasm_memory_index);
const result = try gz.addExtendedPayload(.wasm_memory_size, Zir.Inst.UnNode{
.node = gz.nodeIndexToRelative(node),
.operand = operand,
@ -9568,7 +9606,7 @@ fn builtinCall(
return rvalue(gz, ri, result, node);
},
.wasm_memory_grow => {
const index_arg = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0]);
const index_arg = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0], .wasm_memory_index);
const delta_arg = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, params[1]);
const result = try gz.addExtendedPayload(.wasm_memory_grow, Zir.Inst.BinNode{
.node = gz.nodeIndexToRelative(node),
@ -9579,8 +9617,8 @@ fn builtinCall(
},
.c_define => {
if (!gz.c_import) return gz.astgen.failNode(node, "C define valid only inside C import block", .{});
const name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[0]);
const value = try comptimeExpr(gz, scope, .{ .rl = .none }, params[1]);
const name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[0], .operand_cDefine_macro_name);
const value = try comptimeExpr(gz, scope, .{ .rl = .none }, params[1], .operand_cDefine_macro_value);
const result = try gz.addExtendedPayload(.c_define, Zir.Inst.BinNode{
.node = gz.nodeIndexToRelative(node),
.lhs = name,
@ -9666,7 +9704,7 @@ fn builtinCall(
},
.call => {
const call_modifier_ty = try gz.addBuiltinValue(node, .call_modifier);
const modifier = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = call_modifier_ty } }, params[0]);
const modifier = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = call_modifier_ty } }, params[0], .call_modifier);
const callee = try expr(gz, scope, .{ .rl = .none }, params[1]);
const args = try expr(gz, scope, .{ .rl = .none }, params[2]);
const result = try gz.addPlNode(.builtin_call, node, Zir.Inst.BuiltinCall{
@ -9682,7 +9720,7 @@ fn builtinCall(
},
.field_parent_ptr => {
const parent_ptr_type = try ri.rl.resultTypeForCast(gz, node, builtin_name);
const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[0]);
const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[0], .field_name);
const result = try gz.addExtendedPayloadSmall(.field_parent_ptr, 0, Zir.Inst.FieldParentPtr{
.src_node = gz.nodeIndexToRelative(node),
.parent_ptr_type = parent_ptr_type,
@ -9713,7 +9751,7 @@ fn builtinCall(
.elem_type = try typeExpr(gz, scope, params[0]),
.a = try expr(gz, scope, .{ .rl = .none }, params[1]),
.b = try expr(gz, scope, .{ .rl = .none }, params[2]),
.mask = try comptimeExpr(gz, scope, .{ .rl = .none }, params[3]),
.mask = try comptimeExpr(gz, scope, .{ .rl = .none }, params[3], .operand_shuffle_mask),
});
return rvalue(gz, ri, result, node);
},
@ -9739,7 +9777,7 @@ fn builtinCall(
},
.Vector => {
const result = try gz.addPlNode(.vector_type, node, Zir.Inst.Bin{
.lhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0]),
.lhs = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0], .type),
.rhs = try typeExpr(gz, scope, params[1]),
});
return rvalue(gz, ri, result, node);
@ -9747,7 +9785,7 @@ fn builtinCall(
.prefetch => {
const prefetch_options_ty = try gz.addBuiltinValue(node, .prefetch_options);
const ptr = try expr(gz, scope, .{ .rl = .none }, params[0]);
const options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = prefetch_options_ty } }, params[1]);
const options = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = prefetch_options_ty } }, params[1], .prefetch_options);
_ = try gz.addExtendedPayload(.prefetch, Zir.Inst.BinNode{
.node = gz.nodeIndexToRelative(node),
.lhs = ptr,
@ -9785,7 +9823,7 @@ fn builtinCall(
},
.work_item_id => {
const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0]);
const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0], .work_group_dim_index);
const result = try gz.addExtendedPayload(.work_item_id, Zir.Inst.UnNode{
.node = gz.nodeIndexToRelative(node),
.operand = operand,
@ -9793,7 +9831,7 @@ fn builtinCall(
return rvalue(gz, ri, result, node);
},
.work_group_size => {
const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0]);
const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0], .work_group_dim_index);
const result = try gz.addExtendedPayload(.work_group_size, Zir.Inst.UnNode{
.node = gz.nodeIndexToRelative(node),
.operand = operand,
@ -9801,7 +9839,7 @@ fn builtinCall(
return rvalue(gz, ri, result, node);
},
.work_group_id => {
const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0]);
const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0], .work_group_dim_index);
const result = try gz.addExtendedPayload(.work_group_id, Zir.Inst.UnNode{
.node = gz.nodeIndexToRelative(node),
.operand = operand,
@ -9821,7 +9859,13 @@ fn hasDeclOrField(
tag: Zir.Inst.Tag,
) InnerError!Zir.Inst.Ref {
const container_type = try typeExpr(gz, scope, lhs_node);
const name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, rhs_node);
const name = try comptimeExpr(
gz,
scope,
.{ .rl = .{ .coerced_ty = .slice_const_u8_type } },
rhs_node,
if (tag == .has_decl) .decl_name else .field_name,
);
const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
.lhs = container_type,
.rhs = name,
@ -9874,7 +9918,7 @@ fn simpleUnOp(
) InnerError!Zir.Inst.Ref {
const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
const operand = if (tag == .compile_error)
try comptimeExpr(gz, scope, operand_ri, operand_node)
try comptimeExpr(gz, scope, operand_ri, operand_node, .compile_error_string)
else
try expr(gz, scope, operand_ri, operand_node);
switch (tag) {
@ -9972,7 +10016,13 @@ fn simpleCBuiltin(
) InnerError!Zir.Inst.Ref {
const name: []const u8 = if (tag == .c_undef) "C undef" else "C include";
if (!gz.c_import) return gz.astgen.failNode(node, "{s} valid only inside C import block", .{name});
const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, operand_node);
const operand = try comptimeExpr(
gz,
scope,
.{ .rl = .{ .coerced_ty = .slice_const_u8_type } },
operand_node,
if (tag == .c_undef) .operand_cUndef_macro_name else .operand_cInclude_file_name,
);
_ = try gz.addExtendedPayload(tag, Zir.Inst.UnNode{
.node = gz.nodeIndexToRelative(node),
.operand = operand,
@ -9990,7 +10040,7 @@ fn offsetOf(
tag: Zir.Inst.Tag,
) InnerError!Zir.Inst.Ref {
const type_inst = try typeExpr(gz, scope, lhs_node);
const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, rhs_node);
const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, rhs_node, .field_name);
const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
.lhs = type_inst,
.rhs = field_name,
@ -11996,11 +12046,16 @@ const GenZir = struct {
}
/// Assumes nothing stacked on `gz`. Unstacks `gz`.
/// Asserts `inst` is not a `block_comptime`.
fn setBlockBody(gz: *GenZir, inst: Zir.Inst.Index) !void {
const astgen = gz.astgen;
const gpa = astgen.gpa;
const body = gz.instructionsSlice();
const body_len = astgen.countBodyLenAfterFixups(body);
const zir_tags = astgen.instructions.items(.tag);
assert(zir_tags[@intFromEnum(inst)] != .block_comptime); // use `setComptimeBlockBody` instead
try astgen.extra.ensureUnusedCapacity(
gpa,
@typeInfo(Zir.Inst.Block).@"struct".fields.len + body_len,
@ -12013,6 +12068,32 @@ const GenZir = struct {
gz.unstack();
}
/// Assumes nothing stacked on `gz`. Unstacks `gz`.
/// Asserts `inst` is a `block_comptime`.
fn setBlockComptimeBody(gz: *GenZir, inst: Zir.Inst.Index, comptime_reason: std.zig.SimpleComptimeReason) !void {
const astgen = gz.astgen;
const gpa = astgen.gpa;
const body = gz.instructionsSlice();
const body_len = astgen.countBodyLenAfterFixups(body);
const zir_tags = astgen.instructions.items(.tag);
assert(zir_tags[@intFromEnum(inst)] == .block_comptime); // use `setBlockBody` instead
try astgen.extra.ensureUnusedCapacity(
gpa,
@typeInfo(Zir.Inst.BlockComptime).@"struct".fields.len + body_len,
);
const zir_datas = astgen.instructions.items(.data);
zir_datas[@intFromEnum(inst)].pl_node.payload_index = astgen.addExtraAssumeCapacity(
Zir.Inst.BlockComptime{
.reason = comptime_reason,
.body_len = body_len,
},
);
astgen.appendBodyWithFixups(body);
gz.unstack();
}
/// Assumes nothing stacked on `gz`. Unstacks `gz`.
fn setTryBody(gz: *GenZir, inst: Zir.Inst.Index, operand: Zir.Inst.Ref) !void {
const astgen = gz.astgen;

View File

@ -78,6 +78,7 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) ExtraData(T) {
Inst.Ref,
Inst.Index,
Inst.Declaration.Name,
std.zig.SimpleComptimeReason,
NullTerminatedString,
=> @enumFromInt(code.extra[i]),
@ -291,7 +292,8 @@ pub const Inst = struct {
/// Uses the `pl_node` union field. Payload is `Block`.
block,
/// Like `block`, but forces full evaluation of its contents at compile-time.
/// Uses the `pl_node` union field. Payload is `Block`.
/// Exited with `break_inline`.
/// Uses the `pl_node` union field. Payload is `BlockComptime`.
block_comptime,
/// A list of instructions which are analyzed in the parent context, without
/// generating a runtime block. Must terminate with an "inline" variant of
@ -2547,6 +2549,13 @@ pub const Inst = struct {
body_len: u32,
};
/// Trailing:
/// * inst: Index // for each `body_len`
pub const BlockComptime = struct {
reason: std.zig.SimpleComptimeReason,
body_len: u32,
};
/// Trailing:
/// * inst: Index // for each `body_len`
pub const BoolBr = struct {
@ -4517,7 +4526,6 @@ fn findTrackableInner(
// Block instructions, recurse over the bodies.
.block,
.block_comptime,
.block_inline,
.c_import,
.typeof_builtin,
@ -4528,6 +4536,12 @@ fn findTrackableInner(
const body = zir.bodySlice(extra.end, extra.data.body_len);
return zir.findTrackableBody(gpa, contents, defers, body);
},
.block_comptime => {
const inst_data = datas[@intFromEnum(inst)].pl_node;
const extra = zir.extraData(Inst.BlockComptime, inst_data.payload_index);
const body = zir.bodySlice(extra.end, extra.data.body_len);
return zir.findTrackableBody(gpa, contents, defers, body);
},
.condbr, .condbr_inline => {
const inst_data = datas[@intFromEnum(inst)].pl_node;
const extra = zir.extraData(Inst.CondBr, inst_data.payload_index);

View File

@ -3435,6 +3435,7 @@ pub fn addModuleErrorMsg(
var notes: std.ArrayHashMapUnmanaged(ErrorBundle.ErrorMessage, void, ErrorNoteHashContext, true) = .empty;
defer notes.deinit(gpa);
var last_note_loc: ?std.zig.Loc = null;
for (module_err_msg.notes) |module_note| {
const note_src_loc = module_note.src_loc.upgrade(zcu);
const source = try note_src_loc.file_scope.getSource(gpa);
@ -3443,6 +3444,9 @@ pub fn addModuleErrorMsg(
const note_file_path = try note_src_loc.file_scope.fullPath(gpa);
defer gpa.free(note_file_path);
const omit_source_line = loc.eql(err_loc) or (last_note_loc != null and loc.eql(last_note_loc.?));
last_note_loc = loc;
const gop = try notes.getOrPutContext(gpa, .{
.msg = try eb.addString(module_note.msg),
.src_loc = try eb.addSourceLocation(.{
@ -3452,7 +3456,7 @@ pub fn addModuleErrorMsg(
.span_end = span.end,
.line = @intCast(loc.line),
.column = @intCast(loc.column),
.source_line = if (err_loc.eql(loc)) 0 else try eb.addString(loc.source_line),
.source_line = if (omit_source_line) 0 else try eb.addString(loc.source_line),
}),
}, .{ .eb = eb });
if (gop.found_existing) {

File diff suppressed because it is too large Load Diff

View File

@ -682,7 +682,13 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu
.namespace = comptime_unit.namespace,
.instructions = .{},
.inlining = null,
.is_comptime = true,
.comptime_reason = .{ .reason = .{
.src = .{
.base_node_inst = comptime_unit.zir_index,
.offset = .{ .token_offset = 0 },
},
.r = .{ .simple = .comptime_keyword },
} },
.src_base_inst = comptime_unit.zir_index,
.type_name_ctx = try ip.getOrPutStringFmt(gpa, pt.tid, "{}.comptime", .{
Type.fromInterned(zcu.namespacePtr(comptime_unit.namespace).owner_type).containerTypeName(ip).fmt(ip),
@ -878,7 +884,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
.namespace = old_nav.analysis.?.namespace,
.instructions = .{},
.inlining = null,
.is_comptime = true,
.comptime_reason = undefined, // set below
.src_base_inst = old_nav.analysis.?.zir_index,
.type_name_ctx = old_nav.fqn,
};
@ -893,6 +899,11 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
const section_src = block.src(.{ .node_offset_var_decl_section = 0 });
const addrspace_src = block.src(.{ .node_offset_var_decl_addrspace = 0 });
block.comptime_reason = .{ .reason = .{
.src = init_src,
.r = .{ .simple = .container_var_init },
} };
const maybe_ty: ?Type = if (zir_decl.type_body != null) ty: {
// Since we have a type body, the type is resolved separately!
// Of course, we need to make sure we depend on it properly.
@ -1253,7 +1264,7 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr
.namespace = old_nav.analysis.?.namespace,
.instructions = .{},
.inlining = null,
.is_comptime = true,
.comptime_reason = undefined, // set below
.src_base_inst = old_nav.analysis.?.zir_index,
.type_name_ctx = old_nav.fqn,
};
@ -1262,6 +1273,13 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr
const zir_decl = zir.getDeclaration(inst_resolved.inst);
assert(old_nav.is_usingnamespace == (zir_decl.kind == .@"usingnamespace"));
const ty_src = block.src(.{ .node_offset_var_decl_ty = 0 });
block.comptime_reason = .{ .reason = .{
.src = ty_src,
.r = .{ .simple = .type },
} };
const type_body = zir_decl.type_body orelse {
// The type of this `Nav` is inferred from the value.
// In other words, this `nav_ty` depends on the corresponding `nav_val`.
@ -1279,8 +1297,6 @@ fn analyzeNavType(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileEr
return .{ .type_changed = true };
};
const ty_src = block.src(.{ .node_offset_var_decl_ty = 0 });
const resolved_ty: Type = ty: {
const uncoerced_type_ref = try sema.resolveInlineBody(&block, type_body, inst_resolved.inst);
const type_ref = try sema.coerce(&block, .type, uncoerced_type_ref, ty_src);
@ -2442,7 +2458,7 @@ fn analyzeFnBodyInner(pt: Zcu.PerThread, func_index: InternPool.Index) Zcu.SemaE
.namespace = decl_nav.analysis.?.namespace,
.instructions = .{},
.inlining = null,
.is_comptime = false,
.comptime_reason = null,
.src_base_inst = decl_nav.analysis.?.zir_index,
.type_name_ctx = func_nav.fqn,
};

View File

@ -437,7 +437,6 @@ const Writer = struct {
.field_call => try self.writeCall(stream, inst, .field),
.block,
.block_comptime,
.block_inline,
.suspend_block,
.loop,
@ -445,6 +444,8 @@ const Writer = struct {
.typeof_builtin,
=> try self.writeBlock(stream, inst),
.block_comptime => try self.writeBlockComptime(stream, inst),
.condbr,
.condbr_inline,
=> try self.writeCondBr(stream, inst),
@ -1342,17 +1343,22 @@ const Writer = struct {
}
fn writeBlock(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
try self.writePlNodeBlockWithoutSrc(stream, inst);
try self.writeSrcNode(stream, inst_data.src_node);
}
fn writePlNodeBlockWithoutSrc(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
const extra = self.code.extraData(Zir.Inst.Block, inst_data.payload_index);
const body = self.code.bodySlice(extra.end, extra.data.body_len);
try self.writeBracedBody(stream, body);
try stream.writeAll(") ");
try self.writeSrcNode(stream, inst_data.src_node);
}
fn writeBlockComptime(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
const inst_data = self.code.instructions.items(.data)[@intFromEnum(inst)].pl_node;
const extra = self.code.extraData(Zir.Inst.BlockComptime, inst_data.payload_index);
const body = self.code.bodySlice(extra.end, extra.data.body_len);
try stream.print("reason={s}, ", .{@tagName(extra.data.reason)});
try self.writeBracedBody(stream, body);
try stream.writeAll(") ");
try self.writeSrcNode(stream, inst_data.src_node);
}
fn writeCondBr(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {