astgen: fix whileExpr condition coercion, payload handling, else/continue, result info, and labels
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
344
astgen.c
344
astgen.c
@@ -2348,7 +2348,7 @@ static uint32_t arrayInitDotExpr(
|
|||||||
static uint32_t switchExpr(
|
static uint32_t switchExpr(
|
||||||
GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node);
|
GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node);
|
||||||
static uint32_t whileExpr(
|
static uint32_t whileExpr(
|
||||||
GenZir* gz, Scope* scope, uint32_t node, bool is_statement);
|
GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node, bool is_statement);
|
||||||
#define EVAL_TO_ERROR_NEVER 0
|
#define EVAL_TO_ERROR_NEVER 0
|
||||||
#define EVAL_TO_ERROR_ALWAYS 1
|
#define EVAL_TO_ERROR_ALWAYS 1
|
||||||
#define EVAL_TO_ERROR_MAYBE 2
|
#define EVAL_TO_ERROR_MAYBE 2
|
||||||
@@ -5158,7 +5158,7 @@ static uint32_t exprRl(GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) {
|
|||||||
case AST_NODE_WHILE_SIMPLE:
|
case AST_NODE_WHILE_SIMPLE:
|
||||||
case AST_NODE_WHILE_CONT:
|
case AST_NODE_WHILE_CONT:
|
||||||
case AST_NODE_WHILE:
|
case AST_NODE_WHILE:
|
||||||
return rvalue(gz, rl, whileExpr(gz, scope, node, false), node);
|
return whileExpr(gz, scope, rlBr(rl), node, false);
|
||||||
// error_value (AstGen.zig:1005).
|
// error_value (AstGen.zig:1005).
|
||||||
case AST_NODE_ERROR_VALUE: {
|
case AST_NODE_ERROR_VALUE: {
|
||||||
uint32_t error_token = ag->tree->nodes.main_tokens[node] + 2;
|
uint32_t error_token = ag->tree->nodes.main_tokens[node] + 2;
|
||||||
@@ -6299,26 +6299,84 @@ static uint32_t orelseCatchExpr(GenZir* gz, Scope* scope, ResultLoc rl,
|
|||||||
return block_inst + ZIR_REF_START_INDEX;
|
return block_inst + ZIR_REF_START_INDEX;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- whileExpr (AstGen.zig:6529-6805) ---
|
// --- whileExpr (AstGen.zig:6529-6817) ---
|
||||||
// Handles while_simple.
|
// Handles while_simple, while_cont, while.
|
||||||
// Structure: loop { cond_block { cond, condbr }, repeat }
|
// Structure: loop { cond_block { cond, condbr }, repeat }
|
||||||
// condbr → then { continue_block { body, break continue }, break cond }
|
// condbr → then { [payload], continue_block { [cont_expr], body,
|
||||||
// → else { break loop }
|
// break continue }, break cond }
|
||||||
|
// → else { [err_capture], else_body / break loop }
|
||||||
|
|
||||||
static uint32_t whileExpr(
|
static uint32_t whileExpr(
|
||||||
GenZir* gz, Scope* scope, uint32_t node, bool is_statement) {
|
GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node, bool is_statement) {
|
||||||
AstGenCtx* ag = gz->astgen;
|
AstGenCtx* ag = gz->astgen;
|
||||||
const Ast* tree = ag->tree;
|
const Ast* tree = ag->tree;
|
||||||
|
AstNodeTag node_tag = tree->nodes.tags[node];
|
||||||
AstData nd = tree->nodes.datas[node];
|
AstData nd = tree->nodes.datas[node];
|
||||||
|
|
||||||
|
// Compute break_rl from rl (AstGen.zig:6540-6548).
|
||||||
|
bool need_rl = nodesNeedRlContains(ag, node);
|
||||||
|
ResultLoc break_rl = breakResultInfo(gz, rl, node, need_rl);
|
||||||
|
bool need_result_rvalue = (break_rl.tag != rl.tag);
|
||||||
|
|
||||||
// Detect inline keyword (AstGen.zig:6558).
|
// Detect inline keyword (AstGen.zig:6558).
|
||||||
uint32_t main_token = tree->nodes.main_tokens[node];
|
uint32_t main_token = tree->nodes.main_tokens[node];
|
||||||
bool is_inline = (main_token > 0
|
bool is_inline = (main_token > 0
|
||||||
&& tree->tokens.tags[main_token - 1] == TOKEN_KEYWORD_INLINE);
|
&& tree->tokens.tags[main_token - 1] == TOKEN_KEYWORD_INLINE);
|
||||||
|
|
||||||
// WHILE_SIMPLE: lhs = cond_expr, rhs = body.
|
// Compute label_token (AstGen.zig fullWhileComponents:2310-2317).
|
||||||
|
uint32_t label_token = UINT32_MAX;
|
||||||
|
{
|
||||||
|
uint32_t tok_i = main_token;
|
||||||
|
if (is_inline)
|
||||||
|
tok_i = main_token - 1;
|
||||||
|
if (tok_i >= 2 && tree->tokens.tags[tok_i - 2] == TOKEN_IDENTIFIER
|
||||||
|
&& tree->tokens.tags[tok_i - 1] == TOKEN_COLON)
|
||||||
|
label_token = tok_i - 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract AST nodes depending on node type (Ast.zig:1925-1958).
|
||||||
uint32_t cond_node = nd.lhs;
|
uint32_t cond_node = nd.lhs;
|
||||||
uint32_t body_node = nd.rhs;
|
uint32_t body_node;
|
||||||
|
uint32_t else_node = 0;
|
||||||
|
uint32_t cont_expr = 0; // 0 = none
|
||||||
|
if (node_tag == AST_NODE_WHILE_SIMPLE) {
|
||||||
|
body_node = nd.rhs;
|
||||||
|
} else if (node_tag == AST_NODE_WHILE_CONT) {
|
||||||
|
// WhileCont[rhs]: { cont_expr, then_expr }
|
||||||
|
cont_expr = tree->extra_data.arr[nd.rhs];
|
||||||
|
body_node = tree->extra_data.arr[nd.rhs + 1];
|
||||||
|
} else {
|
||||||
|
// AST_NODE_WHILE: While[rhs]: { cont_expr, then_expr, else_expr }
|
||||||
|
// cont_expr is stored via OPT(): UINT32_MAX means none.
|
||||||
|
uint32_t raw_cont = tree->extra_data.arr[nd.rhs];
|
||||||
|
cont_expr = (raw_cont == UINT32_MAX) ? 0 : raw_cont;
|
||||||
|
body_node = tree->extra_data.arr[nd.rhs + 1];
|
||||||
|
else_node = tree->extra_data.arr[nd.rhs + 2];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detect payload capture (Ast.zig fullWhileComponents:2318-2321).
|
||||||
|
uint32_t payload_token = 0;
|
||||||
|
{
|
||||||
|
uint32_t last_cond_tok = lastToken(tree, cond_node);
|
||||||
|
if (last_cond_tok + 2 < tree->tokens.len
|
||||||
|
&& tree->tokens.tags[last_cond_tok + 2] == TOKEN_PIPE) {
|
||||||
|
payload_token = last_cond_tok + 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detect error token (Ast.zig fullWhileComponents:2322-2329).
|
||||||
|
uint32_t error_token = 0;
|
||||||
|
if (else_node != 0) {
|
||||||
|
uint32_t else_tok = lastToken(tree, body_node) + 1;
|
||||||
|
if (else_tok + 1 < tree->tokens.len
|
||||||
|
&& tree->tokens.tags[else_tok + 1] == TOKEN_PIPE) {
|
||||||
|
error_token = else_tok + 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detect payload_is_ref (AstGen.zig:6574-6577).
|
||||||
|
bool payload_is_ref = (payload_token != 0
|
||||||
|
&& tree->tokens.tags[payload_token] == TOKEN_ASTERISK);
|
||||||
|
|
||||||
// Create loop instruction (AstGen.zig:6562-6564).
|
// Create loop instruction (AstGen.zig:6562-6564).
|
||||||
ZirInstTag loop_tag = is_inline ? ZIR_INST_BLOCK_INLINE : ZIR_INST_LOOP;
|
ZirInstTag loop_tag = is_inline ? ZIR_INST_BLOCK_INLINE : ZIR_INST_LOOP;
|
||||||
@@ -6327,12 +6385,44 @@ static uint32_t whileExpr(
|
|||||||
|
|
||||||
GenZir loop_scope = makeSubBlock(gz, scope);
|
GenZir loop_scope = makeSubBlock(gz, scope);
|
||||||
loop_scope.is_inline = is_inline;
|
loop_scope.is_inline = is_inline;
|
||||||
|
loop_scope.break_result_info = break_rl;
|
||||||
|
|
||||||
// Evaluate condition in cond_scope (AstGen.zig:6571-6607).
|
// Evaluate condition in cond_scope (AstGen.zig:6571-6607).
|
||||||
GenZir cond_scope = makeSubBlock(&loop_scope, &loop_scope.base);
|
GenZir cond_scope = makeSubBlock(gz, &loop_scope.base);
|
||||||
|
|
||||||
// Emit debug node for the condition expression (AstGen.zig:6579).
|
// Emit debug node for the condition expression (AstGen.zig:6579).
|
||||||
emitDbgNode(&cond_scope, cond_node);
|
emitDbgNode(gz, cond_node);
|
||||||
uint32_t cond = expr(&cond_scope, &cond_scope.base, cond_node);
|
|
||||||
|
uint32_t cond_inst; // the value (optional/err-union/bool)
|
||||||
|
uint32_t bool_bit; // the boolean for condbr
|
||||||
|
if (error_token != 0) {
|
||||||
|
// Error union condition (AstGen.zig:6584-6591).
|
||||||
|
ResultLoc cond_rl = payload_is_ref ? RL_REF_VAL : RL_NONE_VAL;
|
||||||
|
cond_inst
|
||||||
|
= fullBodyExpr(&cond_scope, &cond_scope.base, cond_rl, cond_node);
|
||||||
|
ZirInstTag cond_tag
|
||||||
|
= payload_is_ref ? ZIR_INST_IS_NON_ERR_PTR : ZIR_INST_IS_NON_ERR;
|
||||||
|
bool_bit = addUnNode(&cond_scope, cond_tag, cond_inst, cond_node);
|
||||||
|
} else if (payload_token != 0) {
|
||||||
|
// Optional condition (AstGen.zig:6592-6599).
|
||||||
|
ResultLoc cond_rl = payload_is_ref ? RL_REF_VAL : RL_NONE_VAL;
|
||||||
|
cond_inst
|
||||||
|
= fullBodyExpr(&cond_scope, &cond_scope.base, cond_rl, cond_node);
|
||||||
|
ZirInstTag cond_tag
|
||||||
|
= payload_is_ref ? ZIR_INST_IS_NON_NULL_PTR : ZIR_INST_IS_NON_NULL;
|
||||||
|
bool_bit = addUnNode(&cond_scope, cond_tag, cond_inst, cond_node);
|
||||||
|
} else {
|
||||||
|
// Bool condition (AstGen.zig:6600-6606).
|
||||||
|
ResultLoc coerced_bool_ri = {
|
||||||
|
.tag = RL_COERCED_TY,
|
||||||
|
.data = ZIR_REF_BOOL_TYPE,
|
||||||
|
.src_node = 0,
|
||||||
|
.ctx = RI_CTX_NONE,
|
||||||
|
};
|
||||||
|
cond_inst = fullBodyExpr(
|
||||||
|
&cond_scope, &cond_scope.base, coerced_bool_ri, cond_node);
|
||||||
|
bool_bit = cond_inst;
|
||||||
|
}
|
||||||
|
|
||||||
// Create condbr + cond_block (AstGen.zig:6609-6615).
|
// Create condbr + cond_block (AstGen.zig:6609-6615).
|
||||||
ZirInstTag condbr_tag
|
ZirInstTag condbr_tag
|
||||||
@@ -6343,10 +6433,86 @@ static uint32_t whileExpr(
|
|||||||
setBlockBody(ag, &cond_scope, cond_block); // unstacks cond_scope
|
setBlockBody(ag, &cond_scope, cond_block); // unstacks cond_scope
|
||||||
gzAppendInstruction(&loop_scope, cond_block);
|
gzAppendInstruction(&loop_scope, cond_block);
|
||||||
|
|
||||||
// Create continue_block (AstGen.zig:6694).
|
// Payload handling (AstGen.zig:6623-6690).
|
||||||
uint32_t continue_block = makeBlockInst(ag, block_tag, &loop_scope, node);
|
// Create payload instructions in the global inst array but don't add to
|
||||||
|
// any scope's scratch area yet. then_scope and continue_scope are created
|
||||||
|
// after loop_scope is finalized (to avoid scratch array overlap).
|
||||||
|
uint32_t dbg_var_name = 0;
|
||||||
|
uint32_t dbg_var_inst = 0;
|
||||||
|
uint32_t opt_payload_raw_inst = UINT32_MAX; // raw inst index, not ref
|
||||||
|
uint32_t payload_ref = 0;
|
||||||
|
uint32_t payload_ident_token = 0;
|
||||||
|
uint32_t payload_ident_name = 0;
|
||||||
|
bool payload_has_scope = false; // true if we need a ScopeLocalVal
|
||||||
|
|
||||||
// Add repeat to loop_scope (AstGen.zig:6696-6697).
|
if (error_token != 0 && payload_token != 0) {
|
||||||
|
// Error union with payload: makeUnNode (AstGen.zig:6628-6655).
|
||||||
|
ZirInstTag unwrap_tag = payload_is_ref
|
||||||
|
? ZIR_INST_ERR_UNION_PAYLOAD_UNSAFE_PTR
|
||||||
|
: ZIR_INST_ERR_UNION_PAYLOAD_UNSAFE;
|
||||||
|
ensureInstCapacity(ag, 1);
|
||||||
|
uint32_t raw_idx = ag->inst_len;
|
||||||
|
ag->inst_tags[raw_idx] = unwrap_tag;
|
||||||
|
ZirInstData d;
|
||||||
|
d.un_node.src_node = (int32_t)cond_node - (int32_t)gz->decl_node_index;
|
||||||
|
d.un_node.operand = cond_inst;
|
||||||
|
ag->inst_datas[raw_idx] = d;
|
||||||
|
ag->inst_len++;
|
||||||
|
payload_ref = raw_idx + ZIR_REF_START_INDEX;
|
||||||
|
opt_payload_raw_inst = raw_idx;
|
||||||
|
payload_ident_token = payload_token + (payload_is_ref ? 1u : 0u);
|
||||||
|
if (tokenIsUnderscore(tree, payload_ident_token)) {
|
||||||
|
if (payload_is_ref) {
|
||||||
|
SET_ERROR(ag);
|
||||||
|
return ZIR_REF_VOID_VALUE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
payload_ident_name = identAsString(ag, payload_ident_token);
|
||||||
|
payload_has_scope = true;
|
||||||
|
}
|
||||||
|
} else if (error_token != 0) {
|
||||||
|
// Error union without payload (AstGen.zig:6656-6658).
|
||||||
|
ensureInstCapacity(ag, 1);
|
||||||
|
uint32_t raw_idx = ag->inst_len;
|
||||||
|
ag->inst_tags[raw_idx] = ZIR_INST_ENSURE_ERR_UNION_PAYLOAD_VOID;
|
||||||
|
ZirInstData d;
|
||||||
|
d.un_node.src_node = (int32_t)node - (int32_t)gz->decl_node_index;
|
||||||
|
d.un_node.operand = cond_inst;
|
||||||
|
ag->inst_datas[raw_idx] = d;
|
||||||
|
ag->inst_len++;
|
||||||
|
opt_payload_raw_inst = raw_idx;
|
||||||
|
} else if (payload_token != 0) {
|
||||||
|
// Optional with payload: makeUnNode (AstGen.zig:6660-6686).
|
||||||
|
ZirInstTag unwrap_tag = payload_is_ref
|
||||||
|
? ZIR_INST_OPTIONAL_PAYLOAD_UNSAFE_PTR
|
||||||
|
: ZIR_INST_OPTIONAL_PAYLOAD_UNSAFE;
|
||||||
|
ensureInstCapacity(ag, 1);
|
||||||
|
uint32_t raw_idx = ag->inst_len;
|
||||||
|
ag->inst_tags[raw_idx] = unwrap_tag;
|
||||||
|
ZirInstData d;
|
||||||
|
d.un_node.src_node = (int32_t)cond_node - (int32_t)gz->decl_node_index;
|
||||||
|
d.un_node.operand = cond_inst;
|
||||||
|
ag->inst_datas[raw_idx] = d;
|
||||||
|
ag->inst_len++;
|
||||||
|
payload_ref = raw_idx + ZIR_REF_START_INDEX;
|
||||||
|
opt_payload_raw_inst = raw_idx;
|
||||||
|
payload_ident_token = payload_token + (payload_is_ref ? 1u : 0u);
|
||||||
|
if (tokenIsUnderscore(tree, payload_ident_token)) {
|
||||||
|
if (payload_is_ref) {
|
||||||
|
SET_ERROR(ag);
|
||||||
|
return ZIR_REF_VOID_VALUE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
payload_ident_name = identAsString(ag, payload_ident_token);
|
||||||
|
payload_has_scope = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create continue_block (AstGen.zig:6695).
|
||||||
|
// makeBlockInst doesn't add to scratch.
|
||||||
|
uint32_t continue_block_inst = makeBlockInst(ag, block_tag, gz, node);
|
||||||
|
|
||||||
|
// Add repeat to loop_scope (AstGen.zig:6697-6698).
|
||||||
{
|
{
|
||||||
ZirInstTag repeat_tag
|
ZirInstTag repeat_tag
|
||||||
= is_inline ? ZIR_INST_REPEAT_INLINE : ZIR_INST_REPEAT;
|
= is_inline ? ZIR_INST_REPEAT_INLINE : ZIR_INST_REPEAT;
|
||||||
@@ -6356,30 +6522,70 @@ static uint32_t whileExpr(
|
|||||||
addInstruction(&loop_scope, repeat_tag, repeat_data);
|
addInstruction(&loop_scope, repeat_tag, repeat_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set loop body and configure break/continue (AstGen.zig:6699-6701).
|
// Set loop body and configure break/continue (AstGen.zig:6700-6708).
|
||||||
setBlockBody(ag, &loop_scope, loop_inst); // unstacks loop_scope
|
setBlockBody(ag, &loop_scope, loop_inst); // unstacks loop_scope
|
||||||
loop_scope.break_block = loop_inst;
|
loop_scope.break_block = loop_inst;
|
||||||
loop_scope.continue_block = continue_block;
|
loop_scope.continue_block = continue_block_inst;
|
||||||
|
if (label_token != UINT32_MAX) {
|
||||||
|
loop_scope.label_token = label_token;
|
||||||
|
loop_scope.label_block_inst = loop_inst;
|
||||||
|
}
|
||||||
|
|
||||||
// Stack then_scope (AstGen.zig:6708-6709).
|
// Now create then_scope (AstGen.zig:6617-6621, 6711).
|
||||||
|
// loop_scope is unstacked, scratch is clean.
|
||||||
GenZir then_scope = makeSubBlock(gz, &cond_scope.base);
|
GenZir then_scope = makeSubBlock(gz, &cond_scope.base);
|
||||||
|
Scope* then_sub_scope = &then_scope.base;
|
||||||
|
ScopeLocalVal payload_val_scope;
|
||||||
|
memset(&payload_val_scope, 0, sizeof(payload_val_scope));
|
||||||
|
|
||||||
// Add continue_block to then_scope (AstGen.zig:6716).
|
if (payload_has_scope) {
|
||||||
gzAppendInstruction(&then_scope, continue_block);
|
payload_val_scope = (ScopeLocalVal) {
|
||||||
|
.base = { .tag = SCOPE_LOCAL_VAL },
|
||||||
|
.parent = &then_scope.base,
|
||||||
|
.gen_zir = &then_scope,
|
||||||
|
.inst = payload_ref,
|
||||||
|
.token_src = payload_ident_token,
|
||||||
|
.name = payload_ident_name,
|
||||||
|
};
|
||||||
|
dbg_var_name = payload_ident_name;
|
||||||
|
dbg_var_inst = payload_ref;
|
||||||
|
then_sub_scope = &payload_val_scope.base;
|
||||||
|
}
|
||||||
|
|
||||||
// Create continue_scope inside then_scope (AstGen.zig:6725).
|
// Add payload instruction to then_scope (AstGen.zig:6714-6716).
|
||||||
GenZir continue_scope = makeSubBlock(&then_scope, &then_scope.base);
|
if (opt_payload_raw_inst != UINT32_MAX)
|
||||||
|
gzAppendInstruction(&then_scope, opt_payload_raw_inst);
|
||||||
|
// Add dbg_var_val for payload (AstGen.zig:6717).
|
||||||
|
if (dbg_var_name != 0)
|
||||||
|
addDbgVar(
|
||||||
|
&then_scope, ZIR_INST_DBG_VAR_VAL, dbg_var_name, dbg_var_inst);
|
||||||
|
// Add continue_block to then_scope (AstGen.zig:6718).
|
||||||
|
gzAppendInstruction(&then_scope, continue_block_inst);
|
||||||
|
|
||||||
// Execute body (AstGen.zig:6727-6730).
|
// Emit continue expression if present (AstGen.zig:6723-6725).
|
||||||
emitDbgNode(&continue_scope, body_node);
|
// Upstream: unusedResultExpr = emitDbgNode + expr + addEnsureResult.
|
||||||
fullBodyExpr(
|
if (cont_expr != 0) {
|
||||||
&continue_scope, &continue_scope.base, RL_NONE_VAL, body_node);
|
emitDbgNode(&then_scope, cont_expr);
|
||||||
|
uint32_t cont_result = expr(&then_scope, then_sub_scope, cont_expr);
|
||||||
|
addEnsureResult(&then_scope, cont_result, cont_expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create continue_scope (AstGen.zig:6692-6694, 6727).
|
||||||
|
GenZir continue_scope = makeSubBlock(gz, then_sub_scope);
|
||||||
|
|
||||||
|
// Execute body (AstGen.zig:6728-6731).
|
||||||
|
uint32_t then_node = body_node;
|
||||||
|
emitDbgNode(&continue_scope, then_node);
|
||||||
|
uint32_t unused_result = fullBodyExpr(
|
||||||
|
&continue_scope, &continue_scope.base, RL_NONE_VAL, then_node);
|
||||||
|
addEnsureResult(&continue_scope, unused_result, then_node);
|
||||||
|
|
||||||
// Break continue_block if not noreturn (AstGen.zig:6735-6747).
|
// Break continue_block if not noreturn (AstGen.zig:6735-6747).
|
||||||
|
ZirInstTag break_tag = is_inline ? ZIR_INST_BREAK_INLINE : ZIR_INST_BREAK;
|
||||||
if (!endsWithNoReturn(&continue_scope)) {
|
if (!endsWithNoReturn(&continue_scope)) {
|
||||||
// dbg_stmt + dbg_empty_stmt (AstGen.zig:6737-6745).
|
// dbg_stmt + dbg_empty_stmt (AstGen.zig:6736-6745).
|
||||||
advanceSourceCursor(
|
advanceSourceCursor(
|
||||||
ag, tree->tokens.starts[lastToken(tree, body_node)]);
|
ag, tree->tokens.starts[lastToken(tree, then_node)]);
|
||||||
emitDbgStmt(gz, ag->source_line - gz->decl_line, ag->source_column);
|
emitDbgStmt(gz, ag->source_line - gz->decl_line, ag->source_column);
|
||||||
{
|
{
|
||||||
ZirInstData ext_data;
|
ZirInstData ext_data;
|
||||||
@@ -6388,36 +6594,78 @@ static uint32_t whileExpr(
|
|||||||
ext_data.extended.operand = 0;
|
ext_data.extended.operand = 0;
|
||||||
addInstruction(gz, ZIR_INST_EXTENDED, ext_data);
|
addInstruction(gz, ZIR_INST_EXTENDED, ext_data);
|
||||||
}
|
}
|
||||||
ZirInstTag break_tag
|
addBreak(&continue_scope, break_tag, continue_block_inst,
|
||||||
= is_inline ? ZIR_INST_BREAK_INLINE : ZIR_INST_BREAK;
|
|
||||||
addBreak(&continue_scope, break_tag, continue_block,
|
|
||||||
ZIR_REF_VOID_VALUE, AST_NODE_OFFSET_NONE);
|
ZIR_REF_VOID_VALUE, AST_NODE_OFFSET_NONE);
|
||||||
}
|
}
|
||||||
setBlockBody(ag, &continue_scope, continue_block);
|
setBlockBody(ag, &continue_scope, continue_block_inst);
|
||||||
|
// Break cond_block from then_scope (AstGen.zig:6749).
|
||||||
// Break cond_block from then_scope (AstGen.zig:7064).
|
|
||||||
{
|
|
||||||
ZirInstTag break_tag
|
|
||||||
= is_inline ? ZIR_INST_BREAK_INLINE : ZIR_INST_BREAK;
|
|
||||||
addBreak(&then_scope, break_tag, cond_block, ZIR_REF_VOID_VALUE,
|
addBreak(&then_scope, break_tag, cond_block, ZIR_REF_VOID_VALUE,
|
||||||
AST_NODE_OFFSET_NONE);
|
AST_NODE_OFFSET_NONE);
|
||||||
|
|
||||||
|
// Else scope (AstGen.zig:6751-6797).
|
||||||
|
GenZir else_scope = makeSubBlock(gz, &cond_scope.base);
|
||||||
|
|
||||||
|
if (else_node != 0) {
|
||||||
|
Scope* else_sub_scope = &else_scope.base;
|
||||||
|
ScopeLocalVal error_val_scope;
|
||||||
|
memset(&error_val_scope, 0, sizeof(error_val_scope));
|
||||||
|
|
||||||
|
if (error_token != 0) {
|
||||||
|
// Error capture: else |err| (AstGen.zig:6756-6776).
|
||||||
|
ZirInstTag err_tag = payload_is_ref ? ZIR_INST_ERR_UNION_CODE_PTR
|
||||||
|
: ZIR_INST_ERR_UNION_CODE;
|
||||||
|
uint32_t err_inst
|
||||||
|
= addUnNode(&else_scope, err_tag, cond_inst, cond_node);
|
||||||
|
if (tokenIsUnderscore(tree, error_token)) {
|
||||||
|
// Discard |_| — else_sub_scope stays as &else_scope.base
|
||||||
|
} else {
|
||||||
|
uint32_t err_name = identAsString(ag, error_token);
|
||||||
|
error_val_scope = (ScopeLocalVal) {
|
||||||
|
.base = { .tag = SCOPE_LOCAL_VAL },
|
||||||
|
.parent = &else_scope.base,
|
||||||
|
.gen_zir = &else_scope,
|
||||||
|
.inst = err_inst,
|
||||||
|
.token_src = error_token,
|
||||||
|
.name = err_name,
|
||||||
|
};
|
||||||
|
addDbgVar(
|
||||||
|
&else_scope, ZIR_INST_DBG_VAR_VAL, err_name, err_inst);
|
||||||
|
else_sub_scope = &error_val_scope.base;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Else scope: break loop with void (AstGen.zig:6785-6788).
|
// Remove continue/break blocks so control flow applies to outer
|
||||||
GenZir else_scope = makeSubBlock(gz, &cond_scope.base);
|
// loops (AstGen.zig:6783-6784).
|
||||||
{
|
loop_scope.continue_block = UINT32_MAX;
|
||||||
ZirInstTag break_tag
|
loop_scope.break_block = UINT32_MAX;
|
||||||
= is_inline ? ZIR_INST_BREAK_INLINE : ZIR_INST_BREAK;
|
uint32_t else_result = fullBodyExpr(&else_scope, else_sub_scope,
|
||||||
addBreak(&else_scope, break_tag, loop_inst, ZIR_REF_VOID_VALUE,
|
loop_scope.break_result_info, else_node);
|
||||||
|
if (is_statement) {
|
||||||
|
addEnsureResult(&else_scope, else_result, else_node);
|
||||||
|
}
|
||||||
|
if (!endsWithNoReturn(&else_scope)) {
|
||||||
|
addBreak(&else_scope, break_tag, loop_inst, else_result,
|
||||||
|
(int32_t)else_node - (int32_t)gz->decl_node_index);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// No else: break with void (AstGen.zig:6794-6796).
|
||||||
|
uint32_t void_result
|
||||||
|
= rvalue(&else_scope, rl, ZIR_REF_VOID_VALUE, node);
|
||||||
|
addBreak(&else_scope, break_tag, loop_inst, void_result,
|
||||||
AST_NODE_OFFSET_NONE);
|
AST_NODE_OFFSET_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wire up condbr (AstGen.zig:6795).
|
// Wire up condbr (AstGen.zig:6805).
|
||||||
setCondBrPayload(ag, condbr, cond, &then_scope, &else_scope);
|
setCondBrPayload(ag, condbr, bool_bit, &then_scope, &else_scope);
|
||||||
|
|
||||||
uint32_t result = loop_inst + ZIR_REF_START_INDEX;
|
// Apply rvalue if needed (AstGen.zig:6807-6810).
|
||||||
|
uint32_t result;
|
||||||
|
if (need_result_rvalue)
|
||||||
|
result = rvalue(gz, rl, loop_inst + ZIR_REF_START_INDEX, node);
|
||||||
|
else
|
||||||
|
result = loop_inst + ZIR_REF_START_INDEX;
|
||||||
|
|
||||||
// Emit ensure_result_used when used as statement (AstGen.zig:6812-6813).
|
// Emit ensure_result_used when used as statement (AstGen.zig:6812-6814).
|
||||||
if (is_statement) {
|
if (is_statement) {
|
||||||
addUnNode(gz, ZIR_INST_ENSURE_RESULT_USED, result, node);
|
addUnNode(gz, ZIR_INST_ENSURE_RESULT_USED, result, node);
|
||||||
}
|
}
|
||||||
@@ -7736,7 +7984,7 @@ static void blockExprStmts(GenZir* gz, Scope* scope,
|
|||||||
case AST_NODE_WHILE_SIMPLE:
|
case AST_NODE_WHILE_SIMPLE:
|
||||||
case AST_NODE_WHILE_CONT:
|
case AST_NODE_WHILE_CONT:
|
||||||
case AST_NODE_WHILE:
|
case AST_NODE_WHILE:
|
||||||
(void)whileExpr(gz, cur_scope, inner_node, true);
|
(void)whileExpr(gz, cur_scope, RL_NONE_VAL, inner_node, true);
|
||||||
break;
|
break;
|
||||||
case AST_NODE_FOR_SIMPLE:
|
case AST_NODE_FOR_SIMPLE:
|
||||||
case AST_NODE_FOR:
|
case AST_NODE_FOR:
|
||||||
|
|||||||
Reference in New Issue
Block a user