astgen: typeCast DBG_STMT, builtinEvalToError, memset/memcpy fixes
- Add emitDbgStmt and result type from RL to typeCast builtins (@intCast, @truncate, @ptrCast, @enumFromInt, @bitCast) - Pass ResultLoc to builtinCall for result type access - Fix @memset: upstream derives elem_ty via typeof+indexable_ptr_elem_type and evaluates value with coerced_ty RL - Fix @memcpy/@memset to return void_value (not instruction ref) - Add builtinEvalToError: per-builtin eval_to_error lookup instead of always returning MAYBE for all builtins - Fix nodeMayAppendToErrorTrace: pass loop var 'n' to nodeMayEvalToError instead of original 'node' parameter Corpus: ref=4177 got=4160, mismatch at inst[557], gap=17 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
255
astgen.c
255
astgen.c
@@ -217,6 +217,7 @@ typedef struct {
|
||||
uint32_t decl_node_index;
|
||||
uint32_t decl_line;
|
||||
bool is_comptime;
|
||||
bool is_inline; // true for inline for/while, labeled blocks in comptime
|
||||
bool c_import; // true inside @cImport block
|
||||
uint32_t instructions_top; // start index in shared array
|
||||
uint32_t break_block; // UINT32_MAX = none (AstGen.zig:11780)
|
||||
@@ -842,11 +843,11 @@ static uint32_t addBreak(GenZir* gz, ZirInstTag tag, uint32_t block_inst,
|
||||
// Mirrors GenZir.addCondBr (AstGen.zig:12834).
|
||||
// Creates condbr instruction placeholder with src_node set.
|
||||
// Payload is filled later by setCondBrPayload.
|
||||
static uint32_t addCondBr(GenZir* gz, uint32_t node) {
|
||||
static uint32_t addCondBr(GenZir* gz, ZirInstTag tag, uint32_t node) {
|
||||
AstGenCtx* ag = gz->astgen;
|
||||
ensureInstCapacity(ag, 1);
|
||||
uint32_t idx = ag->inst_len;
|
||||
ag->inst_tags[idx] = ZIR_INST_CONDBR;
|
||||
ag->inst_tags[idx] = tag;
|
||||
ZirInstData data;
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.pl_node.src_node = (int32_t)node - (int32_t)gz->decl_node_index;
|
||||
@@ -1690,7 +1691,8 @@ static uint32_t simpleCBuiltin(GenZir* gz, Scope* scope, uint32_t node,
|
||||
}
|
||||
|
||||
// Mirrors builtinCall (AstGen.zig:9191) dispatch.
|
||||
static uint32_t builtinCall(GenZir* gz, Scope* scope, uint32_t node) {
|
||||
static uint32_t builtinCall(
|
||||
GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) {
|
||||
AstGenCtx* ag = gz->astgen;
|
||||
const Ast* tree = ag->tree;
|
||||
|
||||
@@ -1719,12 +1721,17 @@ static uint32_t builtinCall(GenZir* gz, Scope* scope, uint32_t node) {
|
||||
AstData nd = tree->nodes.datas[node];
|
||||
return simpleCBuiltin(gz, scope, node, nd.lhs, (uint16_t)ZIR_EXT_C_INCLUDE);
|
||||
}
|
||||
// @intCast (AstGen.zig:9416).
|
||||
// @intCast — typeCast pattern (AstGen.zig:9416, 9807-9826).
|
||||
if (name_len == 7 && memcmp(source + name_start, "intCast", 7) == 0) {
|
||||
advanceSourceCursorToMainToken(ag, node);
|
||||
uint32_t saved_line = ag->source_line - gz->decl_line;
|
||||
uint32_t saved_col = ag->source_column;
|
||||
uint32_t result_type = rlResultType(gz, rl, node);
|
||||
AstData nd = tree->nodes.datas[node];
|
||||
uint32_t operand = expr(gz, scope, nd.lhs);
|
||||
emitDbgStmt(gz, saved_line, saved_col);
|
||||
return addPlNodeBin(gz, ZIR_INST_INT_CAST, node,
|
||||
ZIR_REF_NONE, operand);
|
||||
result_type, operand);
|
||||
}
|
||||
// @embedFile (AstGen.zig:9626).
|
||||
if (name_len == 9 && memcmp(source + name_start, "embedFile", 9) == 0) {
|
||||
@@ -1753,47 +1760,74 @@ static uint32_t builtinCall(GenZir* gz, Scope* scope, uint32_t node) {
|
||||
uint32_t operand = expr(gz, scope, nd.rhs);
|
||||
return addPlNodeBin(gz, ZIR_INST_AS_NODE, node, dest_type, operand);
|
||||
}
|
||||
// @truncate (AstGen.zig:9416).
|
||||
// @truncate — typeCast pattern (AstGen.zig:9417, 9807-9826).
|
||||
if (name_len == 8 && memcmp(source + name_start, "truncate", 8) == 0) {
|
||||
advanceSourceCursorToMainToken(ag, node);
|
||||
uint32_t saved_line = ag->source_line - gz->decl_line;
|
||||
uint32_t saved_col = ag->source_column;
|
||||
uint32_t result_type = rlResultType(gz, rl, node);
|
||||
AstData nd = tree->nodes.datas[node];
|
||||
uint32_t operand = expr(gz, scope, nd.lhs);
|
||||
emitDbgStmt(gz, saved_line, saved_col);
|
||||
return addPlNodeBin(gz, ZIR_INST_TRUNCATE, node,
|
||||
ZIR_REF_NONE, operand);
|
||||
result_type, operand);
|
||||
}
|
||||
// @ptrCast (AstGen.zig:9416).
|
||||
// @ptrCast — typeCast pattern (AstGen.zig:9056, 9807-9826).
|
||||
if (name_len == 7 && memcmp(source + name_start, "ptrCast", 7) == 0) {
|
||||
advanceSourceCursorToMainToken(ag, node);
|
||||
uint32_t saved_line = ag->source_line - gz->decl_line;
|
||||
uint32_t saved_col = ag->source_column;
|
||||
uint32_t result_type = rlResultType(gz, rl, node);
|
||||
AstData nd = tree->nodes.datas[node];
|
||||
uint32_t operand = expr(gz, scope, nd.lhs);
|
||||
emitDbgStmt(gz, saved_line, saved_col);
|
||||
return addPlNodeBin(gz, ZIR_INST_PTR_CAST, node,
|
||||
ZIR_REF_NONE, operand);
|
||||
result_type, operand);
|
||||
}
|
||||
// @enumFromInt (AstGen.zig:9480).
|
||||
// @enumFromInt — typeCast pattern (AstGen.zig:9414, 9807-9826).
|
||||
if (name_len == 11 && memcmp(source + name_start, "enumFromInt", 11) == 0) {
|
||||
advanceSourceCursorToMainToken(ag, node);
|
||||
uint32_t saved_line = ag->source_line - gz->decl_line;
|
||||
uint32_t saved_col = ag->source_column;
|
||||
uint32_t result_type = rlResultType(gz, rl, node);
|
||||
AstData nd = tree->nodes.datas[node];
|
||||
uint32_t operand = expr(gz, scope, nd.lhs);
|
||||
emitDbgStmt(gz, saved_line, saved_col);
|
||||
return addPlNodeBin(gz, ZIR_INST_ENUM_FROM_INT, node,
|
||||
ZIR_REF_NONE, operand);
|
||||
result_type, operand);
|
||||
}
|
||||
// @bitCast (AstGen.zig:9416).
|
||||
// @bitCast — typeCast pattern (AstGen.zig:9416, 9807-9826).
|
||||
if (name_len == 7 && memcmp(source + name_start, "bitCast", 7) == 0) {
|
||||
advanceSourceCursorToMainToken(ag, node);
|
||||
uint32_t saved_line = ag->source_line - gz->decl_line;
|
||||
uint32_t saved_col = ag->source_column;
|
||||
uint32_t result_type = rlResultType(gz, rl, node);
|
||||
AstData nd = tree->nodes.datas[node];
|
||||
uint32_t operand = expr(gz, scope, nd.lhs);
|
||||
emitDbgStmt(gz, saved_line, saved_col);
|
||||
return addPlNodeBin(gz, ZIR_INST_BITCAST, node,
|
||||
ZIR_REF_NONE, operand);
|
||||
result_type, operand);
|
||||
}
|
||||
// @memcpy (AstGen.zig:9586).
|
||||
// @memcpy (AstGen.zig:9631-9637).
|
||||
if (name_len == 6 && memcmp(source + name_start, "memcpy", 6) == 0) {
|
||||
AstData nd = tree->nodes.datas[node];
|
||||
uint32_t dst = expr(gz, scope, nd.lhs);
|
||||
uint32_t src = expr(gz, scope, nd.rhs);
|
||||
return addPlNodeBin(gz, ZIR_INST_MEMCPY, node, dst, src);
|
||||
addPlNodeBin(gz, ZIR_INST_MEMCPY, node, dst, src);
|
||||
return ZIR_REF_VOID_VALUE;
|
||||
}
|
||||
// @memset (AstGen.zig:9582).
|
||||
// @memset (AstGen.zig:9638-9647).
|
||||
if (name_len == 6 && memcmp(source + name_start, "memset", 6) == 0) {
|
||||
AstData nd = tree->nodes.datas[node];
|
||||
uint32_t dst = expr(gz, scope, nd.lhs);
|
||||
uint32_t val = expr(gz, scope, nd.rhs);
|
||||
return addPlNodeBin(gz, ZIR_INST_MEMSET, node, dst, val);
|
||||
uint32_t lhs = expr(gz, scope, nd.lhs);
|
||||
uint32_t lhs_ty = addUnNode(gz, ZIR_INST_TYPEOF, lhs, nd.lhs);
|
||||
uint32_t elem_ty =
|
||||
addUnNode(gz, ZIR_INST_INDEXABLE_PTR_ELEM_TYPE, lhs_ty, nd.lhs);
|
||||
ResultLoc val_rl = {
|
||||
.tag = RL_COERCED_TY, .data = elem_ty, .src_node = 0};
|
||||
uint32_t val = exprRl(gz, scope, val_rl, nd.rhs);
|
||||
addPlNodeBin(gz, ZIR_INST_MEMSET, node, lhs, val);
|
||||
return ZIR_REF_VOID_VALUE;
|
||||
}
|
||||
// @min (AstGen.zig:9155).
|
||||
if (name_len == 3 && memcmp(source + name_start, "min", 3) == 0) {
|
||||
@@ -1837,13 +1871,45 @@ static uint32_t tryResolvePrimitiveIdent(GenZir* gz, uint32_t node) {
|
||||
tok_end++;
|
||||
uint32_t tok_len = tok_end - tok_start;
|
||||
|
||||
// Check well-known primitive refs (primitive_instrs map, AstGen.zig:8300).
|
||||
// Check well-known primitive refs (primitive_instrs map,
|
||||
// AstGen.zig:10236-10281).
|
||||
// clang-format off
|
||||
if (tok_len == 2 && memcmp(source+tok_start, "u1", 2) == 0) return ZIR_REF_U1_TYPE;
|
||||
if (tok_len == 2 && memcmp(source+tok_start, "u8", 2) == 0) return ZIR_REF_U8_TYPE;
|
||||
if (tok_len == 2 && memcmp(source+tok_start, "i8", 2) == 0) return ZIR_REF_I8_TYPE;
|
||||
if (tok_len == 3 && memcmp(source+tok_start, "u16", 3) == 0) return ZIR_REF_U16_TYPE;
|
||||
if (tok_len == 3 && memcmp(source+tok_start, "i16", 3) == 0) return ZIR_REF_I16_TYPE;
|
||||
if (tok_len == 3 && memcmp(source+tok_start, "u29", 3) == 0) return ZIR_REF_U29_TYPE;
|
||||
if (tok_len == 3 && memcmp(source+tok_start, "u32", 3) == 0) return ZIR_REF_U32_TYPE;
|
||||
if (tok_len == 3 && memcmp(source+tok_start, "i32", 3) == 0) return ZIR_REF_I32_TYPE;
|
||||
if (tok_len == 3 && memcmp(source+tok_start, "u64", 3) == 0) return ZIR_REF_U64_TYPE;
|
||||
if (tok_len == 3 && memcmp(source+tok_start, "i64", 3) == 0) return ZIR_REF_I64_TYPE;
|
||||
if (tok_len == 4 && memcmp(source+tok_start, "u128", 4) == 0) return ZIR_REF_U128_TYPE;
|
||||
if (tok_len == 4 && memcmp(source+tok_start, "i128", 4) == 0) return ZIR_REF_I128_TYPE;
|
||||
if (tok_len == 5 && memcmp(source+tok_start, "usize", 5) == 0) return ZIR_REF_USIZE_TYPE;
|
||||
if (tok_len == 5 && memcmp(source+tok_start, "isize", 5) == 0) return ZIR_REF_ISIZE_TYPE;
|
||||
if (tok_len == 6 && memcmp(source+tok_start, "c_char", 6) == 0) return ZIR_REF_C_CHAR_TYPE;
|
||||
if (tok_len == 7 && memcmp(source+tok_start, "c_short", 7) == 0) return ZIR_REF_C_SHORT_TYPE;
|
||||
if (tok_len == 8 && memcmp(source+tok_start, "c_ushort", 8) == 0) return ZIR_REF_C_USHORT_TYPE;
|
||||
if (tok_len == 5 && memcmp(source+tok_start, "c_int", 5) == 0) return ZIR_REF_C_INT_TYPE;
|
||||
if (tok_len == 6 && memcmp(source+tok_start, "c_uint", 6) == 0) return ZIR_REF_C_UINT_TYPE;
|
||||
if (tok_len == 6 && memcmp(source+tok_start, "c_long", 6) == 0) return ZIR_REF_C_LONG_TYPE;
|
||||
if (tok_len == 7 && memcmp(source+tok_start, "c_ulong", 7) == 0) return ZIR_REF_C_ULONG_TYPE;
|
||||
if (tok_len == 10 && memcmp(source+tok_start, "c_longlong", 10) == 0) return ZIR_REF_C_LONGLONG_TYPE;
|
||||
if (tok_len == 11 && memcmp(source+tok_start, "c_ulonglong", 11) == 0) return ZIR_REF_C_ULONGLONG_TYPE;
|
||||
if (tok_len == 14 && memcmp(source+tok_start, "comptime_float", 14) == 0) return ZIR_REF_COMPTIME_FLOAT_TYPE;
|
||||
if (tok_len == 12 && memcmp(source+tok_start, "comptime_int", 12) == 0) return ZIR_REF_COMPTIME_INT_TYPE;
|
||||
if (tok_len == 3 && memcmp(source+tok_start, "f16", 3) == 0) return ZIR_REF_F16_TYPE;
|
||||
if (tok_len == 3 && memcmp(source+tok_start, "f32", 3) == 0) return ZIR_REF_F32_TYPE;
|
||||
if (tok_len == 3 && memcmp(source+tok_start, "f64", 3) == 0) return ZIR_REF_F64_TYPE;
|
||||
if (tok_len == 3 && memcmp(source+tok_start, "f80", 3) == 0) return ZIR_REF_F80_TYPE;
|
||||
if (tok_len == 4 && memcmp(source+tok_start, "f128", 4) == 0) return ZIR_REF_F128_TYPE;
|
||||
if (tok_len == 9 && memcmp(source+tok_start, "anyopaque", 9) == 0) return ZIR_REF_ANYOPAQUE_TYPE;
|
||||
if (tok_len == 4 && memcmp(source+tok_start, "bool", 4) == 0) return ZIR_REF_BOOL_TYPE;
|
||||
if (tok_len == 4 && memcmp(source+tok_start, "void", 4) == 0) return ZIR_REF_VOID_TYPE;
|
||||
if (tok_len == 6 && memcmp(source+tok_start, "c_uint", 6) == 0) return ZIR_REF_C_UINT_TYPE;
|
||||
if (tok_len == 4 && memcmp(source+tok_start, "type", 4) == 0) return ZIR_REF_TYPE_TYPE;
|
||||
if (tok_len == 8 && memcmp(source+tok_start, "anyerror", 8) == 0) return ZIR_REF_ANYERROR_TYPE;
|
||||
if (tok_len == 8 && memcmp(source+tok_start, "noreturn", 8) == 0) return ZIR_REF_NORETURN_TYPE;
|
||||
if (tok_len == 4 && memcmp(source+tok_start, "true", 4) == 0) return ZIR_REF_BOOL_TRUE;
|
||||
if (tok_len == 5 && memcmp(source+tok_start, "false", 5) == 0) return ZIR_REF_BOOL_FALSE;
|
||||
if (tok_len == 4 && memcmp(source+tok_start, "null", 4) == 0) return ZIR_REF_NULL_VALUE;
|
||||
@@ -1886,7 +1952,7 @@ static uint32_t identifierExpr(
|
||||
// Check for primitive types FIRST (AstGen.zig:8298-8338).
|
||||
uint32_t prim = tryResolvePrimitiveIdent(gz, node);
|
||||
if (prim != ZIR_REF_NONE)
|
||||
return prim;
|
||||
return rvalue(gz, rl, prim, node);
|
||||
|
||||
// Scope chain walk (AstGen.zig:8340-8461).
|
||||
uint32_t name_str = identAsString(ag, ident_token);
|
||||
@@ -2819,7 +2885,7 @@ static uint32_t exprRl(GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) {
|
||||
return rvalue(gz, rl, numberLiteral(gz, node), node);
|
||||
case AST_NODE_BUILTIN_CALL_TWO:
|
||||
case AST_NODE_BUILTIN_CALL_TWO_COMMA:
|
||||
return rvalue(gz, rl, builtinCall(gz, scope, node), node);
|
||||
return rvalue(gz, rl, builtinCall(gz, scope, rl, node), node);
|
||||
case AST_NODE_FIELD_ACCESS:
|
||||
return fieldAccessExpr(gz, scope, rl, node);
|
||||
case AST_NODE_IDENTIFIER:
|
||||
@@ -3177,7 +3243,7 @@ static uint32_t exprRl(GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) {
|
||||
}
|
||||
if (block_inst != UINT32_MAX) {
|
||||
// Found target (AstGen.zig:2188-2228).
|
||||
ZirInstTag break_tag = block_gz->is_comptime
|
||||
ZirInstTag break_tag = block_gz->is_inline
|
||||
? ZIR_INST_BREAK_INLINE
|
||||
: ZIR_INST_BREAK;
|
||||
if (opt_rhs == 0) {
|
||||
@@ -3245,7 +3311,10 @@ static uint32_t exprRl(GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) {
|
||||
GenZir* gz2 = (GenZir*)s;
|
||||
if (gz2->continue_block != UINT32_MAX) {
|
||||
genDefers(gz, s, scope, DEFER_NORMAL_ONLY);
|
||||
addBreak(gz, ZIR_INST_BREAK, gz2->continue_block,
|
||||
ZirInstTag break_tag = gz2->is_inline
|
||||
? ZIR_INST_BREAK_INLINE
|
||||
: ZIR_INST_BREAK;
|
||||
addBreak(gz, break_tag, gz2->continue_block,
|
||||
ZIR_REF_VOID_VALUE,
|
||||
(int32_t)node - (int32_t)gz->decl_node_index);
|
||||
return ZIR_REF_UNREACHABLE_VALUE;
|
||||
@@ -3480,6 +3549,7 @@ static uint32_t blockExprExpr(
|
||||
gzAppendInstruction(gz, block_inst);
|
||||
|
||||
GenZir block_scope = makeSubBlock(gz, scope);
|
||||
block_scope.is_inline = force_comptime; // AstGen.zig:2503
|
||||
if (force_comptime)
|
||||
block_scope.is_comptime = true;
|
||||
// Set label on block_scope (AstGen.zig:2504-2508).
|
||||
@@ -3736,7 +3806,7 @@ static uint32_t ifExpr(GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) {
|
||||
bool_bit = cond_inst;
|
||||
}
|
||||
|
||||
uint32_t condbr = addCondBr(&block_scope, node);
|
||||
uint32_t condbr = addCondBr(&block_scope, ZIR_INST_CONDBR, node);
|
||||
uint32_t block_inst = makeBlockInst(ag, ZIR_INST_BLOCK, gz, node);
|
||||
setBlockBody(ag, &block_scope, block_inst);
|
||||
gzAppendInstruction(gz, block_inst);
|
||||
@@ -3852,6 +3922,11 @@ static uint32_t forExpr(
|
||||
AstData nd = tree->nodes.datas[node];
|
||||
AstNodeTag node_tag = tree->nodes.tags[node];
|
||||
|
||||
// Detect inline keyword (AstGen.zig:6847).
|
||||
uint32_t main_token = tree->nodes.main_tokens[node];
|
||||
bool is_inline = (main_token > 0
|
||||
&& tree->tokens.tags[main_token - 1] == TOKEN_KEYWORD_INLINE);
|
||||
|
||||
// Extract input nodes and body/else nodes.
|
||||
// FOR_SIMPLE: lhs = input node, rhs = body (Ast.zig:1960-1968).
|
||||
// FOR: lhs = extra_data index, rhs = packed AstFor (Ast.zig:1970-1981).
|
||||
@@ -3881,8 +3956,9 @@ static uint32_t forExpr(
|
||||
uint32_t lens[FOR_MAX_INPUTS][2]; // [ref0, ref1] per input
|
||||
|
||||
// Allocate index counter (AstGen.zig:6865-6874).
|
||||
uint32_t index_ptr
|
||||
= addUnNode(gz, ZIR_INST_ALLOC, ZIR_REF_USIZE_TYPE, node);
|
||||
ZirInstTag alloc_tag
|
||||
= is_inline ? ZIR_INST_ALLOC_COMPTIME_MUT : ZIR_INST_ALLOC;
|
||||
uint32_t index_ptr = addUnNode(gz, alloc_tag, ZIR_REF_USIZE_TYPE, node);
|
||||
addPlNodeBin(gz, ZIR_INST_STORE_NODE, node, index_ptr, ZIR_REF_ZERO_USIZE);
|
||||
|
||||
// Compute payload_token (AstGen.zig fullForComponents:2349-2350).
|
||||
@@ -3967,9 +4043,11 @@ static uint32_t forExpr(
|
||||
}
|
||||
|
||||
// Create loop (AstGen.zig:6944-6956).
|
||||
uint32_t loop_inst = makeBlockInst(ag, ZIR_INST_LOOP, gz, node);
|
||||
ZirInstTag loop_tag = is_inline ? ZIR_INST_BLOCK_INLINE : ZIR_INST_LOOP;
|
||||
uint32_t loop_inst = makeBlockInst(ag, loop_tag, gz, node);
|
||||
|
||||
GenZir loop_scope = makeSubBlock(gz, scope);
|
||||
loop_scope.is_inline = is_inline;
|
||||
|
||||
// Load index (AstGen.zig:6955-6956).
|
||||
uint32_t index = addUnNode(&loop_scope, ZIR_INST_LOAD, index_ptr, node);
|
||||
@@ -3980,8 +4058,11 @@ static uint32_t forExpr(
|
||||
|
||||
// Create condbr + block (AstGen.zig:6967-6974).
|
||||
GenZir cond_scope = makeSubBlock(&loop_scope, &loop_scope.base);
|
||||
uint32_t condbr = addCondBr(&cond_scope, node);
|
||||
uint32_t cond_block = makeBlockInst(ag, ZIR_INST_BLOCK, &loop_scope, node);
|
||||
ZirInstTag condbr_tag
|
||||
= is_inline ? ZIR_INST_CONDBR_INLINE : ZIR_INST_CONDBR;
|
||||
uint32_t condbr = addCondBr(&cond_scope, condbr_tag, node);
|
||||
ZirInstTag block_tag = is_inline ? ZIR_INST_BLOCK_INLINE : ZIR_INST_BLOCK;
|
||||
uint32_t cond_block = makeBlockInst(ag, block_tag, &loop_scope, node);
|
||||
setBlockBody(ag, &cond_scope, cond_block);
|
||||
loop_scope.break_block = loop_inst;
|
||||
gzAppendInstruction(&loop_scope, cond_block);
|
||||
@@ -4068,12 +4149,13 @@ static uint32_t forExpr(
|
||||
addInstruction(gz, ZIR_INST_EXTENDED, ext_data);
|
||||
}
|
||||
|
||||
addBreak(&then_scope, ZIR_INST_BREAK, cond_block, ZIR_REF_VOID_VALUE,
|
||||
ZirInstTag break_tag = is_inline ? ZIR_INST_BREAK_INLINE : ZIR_INST_BREAK;
|
||||
addBreak(&then_scope, break_tag, cond_block, ZIR_REF_VOID_VALUE,
|
||||
AST_NODE_OFFSET_NONE);
|
||||
|
||||
// Else branch: break out of loop (AstGen.zig:7066-7091).
|
||||
GenZir else_scope = makeSubBlock(&loop_scope, &loop_scope.base);
|
||||
addBreak(&else_scope, ZIR_INST_BREAK, loop_inst, ZIR_REF_VOID_VALUE,
|
||||
addBreak(&else_scope, break_tag, loop_inst, ZIR_REF_VOID_VALUE,
|
||||
AST_NODE_OFFSET_NONE);
|
||||
|
||||
setCondBrPayload(ag, condbr, cond, &then_scope, &else_scope);
|
||||
@@ -4084,12 +4166,14 @@ static uint32_t forExpr(
|
||||
addPlNodeBin(
|
||||
&loop_scope, ZIR_INST_STORE_NODE, node, index_ptr, index_plus_one);
|
||||
|
||||
// Repeat (AstGen.zig:7112).
|
||||
// Repeat (AstGen.zig:7110-7111).
|
||||
{
|
||||
ZirInstTag repeat_tag
|
||||
= is_inline ? ZIR_INST_REPEAT_INLINE : ZIR_INST_REPEAT;
|
||||
ZirInstData repeat_data;
|
||||
memset(&repeat_data, 0, sizeof(repeat_data));
|
||||
repeat_data.node = (int32_t)node - (int32_t)loop_scope.decl_node_index;
|
||||
addInstruction(&loop_scope, ZIR_INST_REPEAT, repeat_data);
|
||||
addInstruction(&loop_scope, repeat_tag, repeat_data);
|
||||
}
|
||||
|
||||
setBlockBody(ag, &loop_scope, loop_inst);
|
||||
@@ -4128,7 +4212,7 @@ static uint32_t orelseCatchExpr(
|
||||
uint32_t condition = addUnNode(&block_scope, test_tag, operand, node);
|
||||
|
||||
// condbr in block_scope (AstGen.zig:6076).
|
||||
uint32_t condbr = addCondBr(&block_scope, node);
|
||||
uint32_t condbr = addCondBr(&block_scope, ZIR_INST_CONDBR, node);
|
||||
|
||||
// Create block in parent gz (AstGen.zig:6078-6081).
|
||||
uint32_t block_inst = makeBlockInst(ag, ZIR_INST_BLOCK, gz, node);
|
||||
@@ -4174,36 +4258,47 @@ static uint32_t whileExpr(
|
||||
const Ast* tree = ag->tree;
|
||||
AstData nd = tree->nodes.datas[node];
|
||||
|
||||
// Detect inline keyword (AstGen.zig:6558).
|
||||
uint32_t main_token = tree->nodes.main_tokens[node];
|
||||
bool is_inline = (main_token > 0
|
||||
&& tree->tokens.tags[main_token - 1] == TOKEN_KEYWORD_INLINE);
|
||||
|
||||
// WHILE_SIMPLE: lhs = cond_expr, rhs = body.
|
||||
uint32_t cond_node = nd.lhs;
|
||||
uint32_t body_node = nd.rhs;
|
||||
|
||||
// Create loop instruction (AstGen.zig:6562-6564).
|
||||
uint32_t loop_inst = makeBlockInst(ag, ZIR_INST_LOOP, gz, node);
|
||||
ZirInstTag loop_tag = is_inline ? ZIR_INST_BLOCK_INLINE : ZIR_INST_LOOP;
|
||||
uint32_t loop_inst = makeBlockInst(ag, loop_tag, gz, node);
|
||||
gzAppendInstruction(gz, loop_inst);
|
||||
|
||||
GenZir loop_scope = makeSubBlock(gz, scope);
|
||||
loop_scope.is_inline = is_inline;
|
||||
|
||||
// Evaluate condition in cond_scope (AstGen.zig:6571-6607).
|
||||
GenZir cond_scope = makeSubBlock(&loop_scope, &loop_scope.base);
|
||||
uint32_t cond = expr(&cond_scope, &cond_scope.base, cond_node);
|
||||
|
||||
// Create condbr + cond_block (AstGen.zig:6609-6615).
|
||||
uint32_t condbr = addCondBr(&cond_scope, node);
|
||||
uint32_t cond_block = makeBlockInst(ag, ZIR_INST_BLOCK, &loop_scope, node);
|
||||
ZirInstTag condbr_tag
|
||||
= is_inline ? ZIR_INST_CONDBR_INLINE : ZIR_INST_CONDBR;
|
||||
uint32_t condbr = addCondBr(&cond_scope, condbr_tag, node);
|
||||
ZirInstTag block_tag = is_inline ? ZIR_INST_BLOCK_INLINE : ZIR_INST_BLOCK;
|
||||
uint32_t cond_block = makeBlockInst(ag, block_tag, &loop_scope, node);
|
||||
setBlockBody(ag, &cond_scope, cond_block); // unstacks cond_scope
|
||||
gzAppendInstruction(&loop_scope, cond_block);
|
||||
|
||||
// Create continue_block (AstGen.zig:6694).
|
||||
uint32_t continue_block
|
||||
= makeBlockInst(ag, ZIR_INST_BLOCK, &loop_scope, node);
|
||||
uint32_t continue_block = makeBlockInst(ag, block_tag, &loop_scope, node);
|
||||
|
||||
// Add repeat to loop_scope (AstGen.zig:6696-6697).
|
||||
{
|
||||
ZirInstTag repeat_tag
|
||||
= is_inline ? ZIR_INST_REPEAT_INLINE : ZIR_INST_REPEAT;
|
||||
ZirInstData repeat_data;
|
||||
memset(&repeat_data, 0, sizeof(repeat_data));
|
||||
repeat_data.node = (int32_t)node - (int32_t)loop_scope.decl_node_index;
|
||||
addInstruction(&loop_scope, ZIR_INST_REPEAT, repeat_data);
|
||||
addInstruction(&loop_scope, repeat_tag, repeat_data);
|
||||
}
|
||||
|
||||
// Set loop body and configure break/continue (AstGen.zig:6699-6701).
|
||||
@@ -4238,19 +4333,29 @@ static uint32_t whileExpr(
|
||||
ext_data.extended.operand = 0;
|
||||
addInstruction(gz, ZIR_INST_EXTENDED, ext_data);
|
||||
}
|
||||
addBreak(&continue_scope, ZIR_INST_BREAK, continue_block,
|
||||
ZirInstTag break_tag
|
||||
= is_inline ? ZIR_INST_BREAK_INLINE : ZIR_INST_BREAK;
|
||||
addBreak(&continue_scope, break_tag, continue_block,
|
||||
ZIR_REF_VOID_VALUE, AST_NODE_OFFSET_NONE);
|
||||
}
|
||||
setBlockBody(ag, &continue_scope, continue_block);
|
||||
|
||||
// Break cond_block from then_scope (AstGen.zig:7064).
|
||||
addBreak(&then_scope, ZIR_INST_BREAK, cond_block, ZIR_REF_VOID_VALUE,
|
||||
AST_NODE_OFFSET_NONE);
|
||||
{
|
||||
ZirInstTag break_tag
|
||||
= is_inline ? ZIR_INST_BREAK_INLINE : ZIR_INST_BREAK;
|
||||
addBreak(&then_scope, break_tag, cond_block, ZIR_REF_VOID_VALUE,
|
||||
AST_NODE_OFFSET_NONE);
|
||||
}
|
||||
|
||||
// Else scope: break loop with void (AstGen.zig:6785-6788).
|
||||
GenZir else_scope = makeSubBlock(gz, &cond_scope.base);
|
||||
addBreak(&else_scope, ZIR_INST_BREAK, loop_inst, ZIR_REF_VOID_VALUE,
|
||||
AST_NODE_OFFSET_NONE);
|
||||
{
|
||||
ZirInstTag break_tag
|
||||
= is_inline ? ZIR_INST_BREAK_INLINE : ZIR_INST_BREAK;
|
||||
addBreak(&else_scope, break_tag, loop_inst, ZIR_REF_VOID_VALUE,
|
||||
AST_NODE_OFFSET_NONE);
|
||||
}
|
||||
|
||||
// Wire up condbr (AstGen.zig:6795).
|
||||
setCondBrPayload(ag, condbr, cond, &then_scope, &else_scope);
|
||||
@@ -4703,6 +4808,37 @@ static void assignOp(
|
||||
addPlNodeBin(gz, ZIR_INST_STORE_NODE, infix_node, lhs_ptr, result);
|
||||
}
|
||||
|
||||
// --- builtinEvalToError (BuiltinFn.zig) ---
|
||||
// Returns per-builtin eval_to_error. Default is .never; only a few are
|
||||
// .maybe or .always. Mirrors BuiltinFn.list lookup in AstGen.zig:10539.
|
||||
static int builtinEvalToError(const Ast* tree, uint32_t node) {
|
||||
uint32_t main_tok = tree->nodes.main_tokens[node];
|
||||
uint32_t tok_start = tree->tokens.starts[main_tok];
|
||||
const char* source = tree->source;
|
||||
uint32_t name_start = tok_start + 1; // skip '@'
|
||||
uint32_t name_end = name_start;
|
||||
while (name_end < tree->source_len
|
||||
&& ((source[name_end] >= 'a' && source[name_end] <= 'z')
|
||||
|| (source[name_end] >= 'A' && source[name_end] <= 'Z')
|
||||
|| source[name_end] == '_')) {
|
||||
name_end++;
|
||||
}
|
||||
uint32_t name_len = name_end - name_start;
|
||||
const char* name = source + name_start;
|
||||
// clang-format off
|
||||
// .always:
|
||||
if (name_len == 12 && memcmp(name, "errorFromInt", 12) == 0)
|
||||
return 1; // EVAL_TO_ERROR_ALWAYS
|
||||
// .maybe:
|
||||
if (name_len == 2 && memcmp(name, "as", 2) == 0) return 2;
|
||||
if (name_len == 4 && memcmp(name, "call", 4) == 0) return 2;
|
||||
if (name_len == 5 && memcmp(name, "field", 5) == 0) return 2;
|
||||
if (name_len == 9 && memcmp(name, "errorCast", 9) == 0) return 2;
|
||||
// clang-format on
|
||||
// Default: .never
|
||||
return 0;
|
||||
}
|
||||
|
||||
// --- nodeMayEvalToError (AstGen.zig:10340) ---
|
||||
// Three-way result: 0=never, 1=always, 2=maybe.
|
||||
#define EVAL_TO_ERROR_NEVER 0
|
||||
@@ -4760,12 +4896,13 @@ static int nodeMayEvalToError(const Ast* tree, uint32_t node) {
|
||||
return EVAL_TO_ERROR_MAYBE;
|
||||
return EVAL_TO_ERROR_NEVER;
|
||||
}
|
||||
// Builtins: simplified — return maybe for safety.
|
||||
// Builtins: look up per-builtin eval_to_error
|
||||
// (AstGen.zig:10530-10541).
|
||||
case AST_NODE_BUILTIN_CALL:
|
||||
case AST_NODE_BUILTIN_CALL_COMMA:
|
||||
case AST_NODE_BUILTIN_CALL_TWO:
|
||||
case AST_NODE_BUILTIN_CALL_TWO_COMMA:
|
||||
return EVAL_TO_ERROR_MAYBE;
|
||||
return builtinEvalToError(tree, n);
|
||||
// Everything else: .never
|
||||
default:
|
||||
return EVAL_TO_ERROR_NEVER;
|
||||
@@ -4796,7 +4933,7 @@ static bool nodeMayAppendToErrorTrace(const Ast* tree, uint32_t node) {
|
||||
continue;
|
||||
// Anything else: check if it may eval to error.
|
||||
default:
|
||||
return nodeMayEvalToError(tree, node) != EVAL_TO_ERROR_NEVER;
|
||||
return nodeMayEvalToError(tree, n) != EVAL_TO_ERROR_NEVER;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4910,12 +5047,20 @@ static void varDecl(GenZir* gz, Scope* scope, uint32_t node,
|
||||
// --- CONST path (AstGen.zig:3232-3340) ---
|
||||
if (!nodesNeedRlContains(ag, node)) {
|
||||
// Rvalue path (AstGen.zig:3246-3271).
|
||||
// Evaluate type annotation if present (AstGen.zig:3248).
|
||||
if (type_node != 0)
|
||||
(void)typeExpr(gz, scope, type_node);
|
||||
// Evaluate type annotation and build result_info
|
||||
// (AstGen.zig:3247-3250).
|
||||
ResultLoc result_info;
|
||||
if (type_node != 0) {
|
||||
uint32_t type_ref = typeExpr(gz, scope, type_node);
|
||||
result_info = (ResultLoc) {
|
||||
.tag = RL_TY, .data = type_ref, .src_node = 0
|
||||
};
|
||||
} else {
|
||||
result_info = RL_NONE_VAL;
|
||||
}
|
||||
|
||||
// Evaluate init expression (AstGen.zig:3259-3264).
|
||||
uint32_t init_ref = expr(gz, scope, init_node);
|
||||
// Evaluate init expression (AstGen.zig:3251-3252).
|
||||
uint32_t init_ref = exprRl(gz, scope, result_info, init_node);
|
||||
|
||||
if (ag->has_compile_errors)
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user