astgen: implement RL_REF_COERCED_TY result location
Add RL_REF_COERCED_TY to the result location enum, matching the upstream
ref_coerced_ty variant. This carries a pointer type through the result
location so that array init and struct init expressions can generate
validate_array_init_ref_ty and struct_init_empty_ref_result instructions.
- Use RL_REF_COERCED_TY in address_of when result type is available
- Handle in arrayInitDotExpr to emit validate_array_init_ref_ty
- Handle in structInitExpr for empty .{} to emit struct_init_empty_ref_result
- Add RL_IS_REF() macro for checking both RL_REF and RL_REF_COERCED_TY
- Update rvalue to treat RL_REF_COERCED_TY like RL_REF
tokenizer_test.zig corpus: instructions now match (7026). Extra and
string_bytes still have diffs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
64
astgen.c
64
astgen.c
@@ -172,6 +172,7 @@ typedef enum {
|
||||
RL_COERCED_TY, // Coerce to specific type, result is the coercion.
|
||||
RL_PTR, // Store result to typed pointer. data=alloc inst, src_node=node.
|
||||
RL_INFERRED_PTR, // Store result to inferred pointer. data=alloc inst.
|
||||
RL_REF_COERCED_TY, // Ref with pointer type. data=ptr_ty_inst.
|
||||
} ResultLocTag;
|
||||
|
||||
typedef struct {
|
||||
@@ -185,6 +186,8 @@ typedef struct {
|
||||
#define RL_REF_VAL ((ResultLoc) { .tag = RL_REF, .data = 0, .src_node = 0 })
|
||||
#define RL_DISCARD_VAL \
|
||||
((ResultLoc) { .tag = RL_DISCARD, .data = 0, .src_node = 0 })
|
||||
#define RL_IS_REF(rl) \
|
||||
((rl).tag == RL_REF || (rl).tag == RL_REF_COERCED_TY)
|
||||
|
||||
// --- Scope types (AstGen.zig:11621-11768) ---
|
||||
|
||||
@@ -1515,7 +1518,8 @@ static uint32_t rvalue(
|
||||
// ensure_result_non_error (AstGen.zig:11071-11074).
|
||||
addUnNode(gz, ZIR_INST_ENSURE_RESULT_NON_ERROR, result, node);
|
||||
return ZIR_REF_VOID_VALUE;
|
||||
case RL_REF: {
|
||||
case RL_REF:
|
||||
case RL_REF_COERCED_TY: {
|
||||
AstGenCtx* ag = gz->astgen;
|
||||
uint32_t src_token = firstToken(ag->tree, node);
|
||||
// If result is not an instruction index (e.g. a well-known ref),
|
||||
@@ -2315,7 +2319,7 @@ static uint32_t identifierExpr(
|
||||
case SCOPE_LOCAL_PTR: {
|
||||
ScopeLocalPtr* lp = (ScopeLocalPtr*)s;
|
||||
if (lp->name == name_str) {
|
||||
if (rl.tag == RL_REF)
|
||||
if (RL_IS_REF(rl))
|
||||
return lp->ptr;
|
||||
return addUnNode(gz, ZIR_INST_LOAD, lp->ptr, node);
|
||||
}
|
||||
@@ -2349,7 +2353,7 @@ decl_table:
|
||||
for (uint32_t i = 0; i < ag->decl_table_len; i++) {
|
||||
if (ag->decl_names[i] == name_str) {
|
||||
ZirInstTag itag
|
||||
= (rl.tag == RL_REF) ? ZIR_INST_DECL_REF : ZIR_INST_DECL_VAL;
|
||||
= (RL_IS_REF(rl)) ? ZIR_INST_DECL_REF : ZIR_INST_DECL_VAL;
|
||||
ZirInstData data;
|
||||
data.str_tok.start = name_str;
|
||||
data.str_tok.src_tok = tokenIndexToRelative(gz, ident_token);
|
||||
@@ -2379,7 +2383,7 @@ static uint32_t fieldAccessExpr(
|
||||
|
||||
// Evaluate the LHS object expression (AstGen.zig:6181).
|
||||
// For .ref rl, LHS is also evaluated with .ref (AstGen.zig:6161).
|
||||
ResultLoc lhs_rl = (rl.tag == RL_REF) ? RL_REF_VAL : RL_NONE_VAL;
|
||||
ResultLoc lhs_rl = (RL_IS_REF(rl)) ? RL_REF_VAL : RL_NONE_VAL;
|
||||
uint32_t lhs = exprRl(gz, scope, lhs_rl, object_node);
|
||||
|
||||
// Emit dbg_stmt for the dot token (AstGen.zig:6183-6184).
|
||||
@@ -2398,13 +2402,13 @@ static uint32_t fieldAccessExpr(
|
||||
|
||||
// .ref → field_ptr, else → field_val (AstGen.zig:6160-6164).
|
||||
ZirInstTag ftag
|
||||
= (rl.tag == RL_REF) ? ZIR_INST_FIELD_PTR : ZIR_INST_FIELD_VAL;
|
||||
= (RL_IS_REF(rl)) ? ZIR_INST_FIELD_PTR : ZIR_INST_FIELD_VAL;
|
||||
ZirInstData data;
|
||||
data.pl_node.src_node = (int32_t)node - (int32_t)gz->decl_node_index;
|
||||
data.pl_node.payload_index = payload_index;
|
||||
uint32_t access = addInstruction(gz, ftag, data);
|
||||
// For ref, return directly; otherwise apply rvalue (AstGen.zig:6161-6164).
|
||||
if (rl.tag == RL_REF)
|
||||
if (RL_IS_REF(rl))
|
||||
return access;
|
||||
return rvalue(gz, rl, access, node);
|
||||
}
|
||||
@@ -2561,7 +2565,7 @@ static uint32_t arrayInitExpr(
|
||||
gz, ZIR_INST_ARRAY_TYPE, type_expr_node, len_inst, elem_type);
|
||||
|
||||
// arrayInitExprTyped (AstGen.zig:1598-1642).
|
||||
bool is_ref = (rl.tag == RL_REF);
|
||||
bool is_ref = (RL_IS_REF(rl));
|
||||
uint32_t operands_len = elem_count + 1;
|
||||
ensureExtraCapacity(ag, 1 + operands_len);
|
||||
uint32_t payload_index = ag->extra_len;
|
||||
@@ -3028,6 +3032,10 @@ static uint32_t structInitExpr(
|
||||
|
||||
if (type_expr_node == 0 && fields_len == 0) {
|
||||
// .{} — depends on result location (AstGen.zig:1687-1698).
|
||||
if (rl.tag == RL_REF_COERCED_TY) {
|
||||
return addUnNode(gz, ZIR_INST_STRUCT_INIT_EMPTY_REF_RESULT,
|
||||
rl.data, node);
|
||||
}
|
||||
if (rl.tag == RL_TY || rl.tag == RL_COERCED_TY) {
|
||||
return addUnNode(
|
||||
gz, ZIR_INST_STRUCT_INIT_EMPTY_RESULT, rl.data, node);
|
||||
@@ -3135,7 +3143,7 @@ static uint32_t structInitExpr(
|
||||
ag->extra[items_start + i * 2 + 1] = init_ref;
|
||||
}
|
||||
|
||||
bool is_ref = (rl.tag == RL_REF);
|
||||
bool is_ref = (RL_IS_REF(rl));
|
||||
ZirInstTag init_tag
|
||||
= is_ref ? ZIR_INST_STRUCT_INIT_REF : ZIR_INST_STRUCT_INIT;
|
||||
return addPlNodePayloadIndex(gz, init_tag, node, payload_index);
|
||||
@@ -3277,7 +3285,10 @@ static uint32_t exprRl(GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) {
|
||||
if (res_ty != 0) {
|
||||
addUnTok(gz, ZIR_INST_VALIDATE_REF_TY, res_ty,
|
||||
firstToken(ag->tree, node));
|
||||
operand_rl = RL_REF_VAL; // simplified: skip ref_coerced_ty
|
||||
// Pass ref_coerced_ty so init expressions can use the type
|
||||
// (AstGen.zig:958).
|
||||
operand_rl = (ResultLoc) { .tag = RL_REF_COERCED_TY,
|
||||
.data = res_ty, .src_node = 0 };
|
||||
} else {
|
||||
operand_rl = RL_REF_VAL;
|
||||
}
|
||||
@@ -3453,7 +3464,7 @@ static uint32_t exprRl(GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) {
|
||||
case AST_NODE_DEREF: {
|
||||
uint32_t lhs = expr(gz, scope, nd.lhs);
|
||||
addUnNode(gz, ZIR_INST_VALIDATE_DEREF, lhs, node);
|
||||
if (rl.tag == RL_REF)
|
||||
if (RL_IS_REF(rl))
|
||||
return lhs;
|
||||
return rvalue(gz, rl, addUnNode(gz, ZIR_INST_LOAD, lhs, node), node);
|
||||
}
|
||||
@@ -3487,7 +3498,7 @@ static uint32_t exprRl(GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) {
|
||||
}
|
||||
// arrayAccess (AstGen.zig:6192-6221).
|
||||
case AST_NODE_ARRAY_ACCESS: {
|
||||
if (rl.tag == RL_REF) {
|
||||
if (RL_IS_REF(rl)) {
|
||||
uint32_t lhs = exprRl(gz, scope, RL_REF_VAL, nd.lhs);
|
||||
advanceSourceCursorToMainToken(ag, node);
|
||||
uint32_t rhs = expr(gz, scope, nd.rhs);
|
||||
@@ -4141,6 +4152,37 @@ static uint32_t arrayInitDotExpr(
|
||||
gz, ZIR_INST_ARRAY_INIT_ANON, node, payload_index);
|
||||
return rvalue(gz, rl, result, node);
|
||||
}
|
||||
case RL_REF_COERCED_TY: {
|
||||
// validate_array_init_ref_ty + arrayInitExprTyped
|
||||
// (AstGen.zig:1527-1532).
|
||||
uint32_t ptr_ty_inst = rl.data;
|
||||
ensureExtraCapacity(ag, 2);
|
||||
uint32_t val_payload = ag->extra_len;
|
||||
ag->extra[ag->extra_len++] = ptr_ty_inst;
|
||||
ag->extra[ag->extra_len++] = elem_count;
|
||||
uint32_t dest_arr_ty_inst = addPlNodePayloadIndex(
|
||||
gz, ZIR_INST_VALIDATE_ARRAY_INIT_REF_TY, node, val_payload);
|
||||
|
||||
// arrayInitExprTyped with elem_ty=none, is_ref=true.
|
||||
uint32_t operands_len = elem_count + 1;
|
||||
ensureExtraCapacity(ag, 1 + operands_len);
|
||||
uint32_t ai_payload = ag->extra_len;
|
||||
ag->extra[ag->extra_len++] = operands_len;
|
||||
ag->extra[ag->extra_len++] = dest_arr_ty_inst;
|
||||
uint32_t extra_start2 = ag->extra_len;
|
||||
ag->extra_len += elem_count;
|
||||
for (uint32_t i = 0; i < elem_count; i++) {
|
||||
uint32_t elem_ty = addPlNodeBin(gz,
|
||||
ZIR_INST_ARRAY_INIT_ELEM_TYPE, elements[i],
|
||||
dest_arr_ty_inst, i);
|
||||
ResultLoc elem_rl = { .tag = RL_COERCED_TY, .data = elem_ty,
|
||||
.src_node = 0 };
|
||||
uint32_t elem_ref = exprRl(gz, scope, elem_rl, elements[i]);
|
||||
ag->extra[extra_start2 + i] = elem_ref;
|
||||
}
|
||||
return addPlNodePayloadIndex(
|
||||
gz, ZIR_INST_ARRAY_INIT_REF, node, ai_payload);
|
||||
}
|
||||
case RL_PTR:
|
||||
// TODO: arrayInitExprPtr (AstGen.zig:1541-1543).
|
||||
// For now, fall through to anon + rvalue.
|
||||
|
||||
@@ -994,7 +994,6 @@ test "astgen: corpus test_all.zig" {
|
||||
// }
|
||||
|
||||
test "astgen: corpus tokenizer_test.zig" {
|
||||
if (true) return error.SkipZigTest; // TODO: 428 inst diff from ref_coerced_ty RL
|
||||
const gpa = std.testing.allocator;
|
||||
try corpusCheck(gpa, "tokenizer_test.zig", @embedFile("tokenizer_test.zig"));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user