mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 04:48:20 +00:00
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:
parent
6d67658965
commit
6026a5f217
159
lib/std/zig.zig
159
lib/std/zig.zig
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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) {
|
||||
|
||||
1043
src/Sema.zig
1043
src/Sema.zig
File diff suppressed because it is too large
Load Diff
@ -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,
|
||||
};
|
||||
|
||||
@ -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 {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user