diff --git a/stage0/astgen.c b/stage0/astgen.c index df82cb13e5..f92a2d297c 100644 --- a/stage0/astgen.c +++ b/stage0/astgen.c @@ -2480,6 +2480,7 @@ static uint32_t tryResolvePrimitiveIdent(GenZir* gz, uint32_t node); #define COMPTIME_REASON_ADDRSPACE 51 #define COMPTIME_REASON_FIELD_NAME 42 #define COMPTIME_REASON_COMPTIME_KEYWORD 53 +#define COMPTIME_REASON_ARRAY_MUL_FACTOR 22 #define COMPTIME_REASON_SWITCH_ITEM 56 #define COMPTIME_REASON_TUPLE_FIELD_DEFAULT_VALUE 57 @@ -3100,7 +3101,8 @@ static uint32_t identifierExpr( if (lp->name == name_str) { if (RL_IS_REF(rl)) return lp->ptr; - return addUnNode(gz, ZIR_INST_LOAD, lp->ptr, node); + uint32_t val = addUnNode(gz, ZIR_INST_LOAD, lp->ptr, node); + return rvalueNoCoercePreRef(gz, rl, val, node); } s = lp->parent; continue; @@ -4590,6 +4592,20 @@ static uint32_t exprRl(GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) { case AST_NODE_ARRAY_CAT: return rvalue( gz, rl, simpleBinOp(gz, scope, node, ZIR_INST_ARRAY_CAT), node); + // array_mult (AstGen.zig:774-785): ** binary operator. + case AST_NODE_ARRAY_MULT: { + uint32_t res_ty = rlResultType(gz, rl, node); + uint32_t lhs = exprRl(gz, scope, RL_NONE_VAL, nd.lhs); + ResultLoc rhs_rl = { .tag = RL_COERCED_TY, + .data = ZIR_REF_USIZE_TYPE, + .src_node = 0, + .ctx = 0 }; + uint32_t rhs = comptimeExpr( + gz, scope, rhs_rl, nd.rhs, COMPTIME_REASON_ARRAY_MUL_FACTOR); + uint32_t result = addPlNodeTriple(gz, ZIR_INST_ARRAY_MUL, node, + res_ty != 0 ? res_ty : ZIR_REF_NONE, lhs, rhs); + return rvalue(gz, rl, result, node); + } // grouped_expression (AstGen.zig:1100): passthrough. case AST_NODE_GROUPED_EXPRESSION: return exprRl(gz, scope, rl, ag->tree->nodes.datas[node].lhs); @@ -5386,7 +5402,6 @@ static uint32_t expr(GenZir* gz, Scope* scope, uint32_t node) { static uint32_t blockExprExpr( GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) { - (void)rl; AstGenCtx* ag = gz->astgen; const Ast* tree = ag->tree; AstNodeTag tag = tree->nodes.tags[node]; @@ -5459,7 +5474,8 @@ static uint32_t blockExprExpr( GenZir sub_gz = makeSubBlock(gz, scope); blockExprStmts(&sub_gz, &sub_gz.base, statements, stmt_count); } - return ZIR_REF_VOID_VALUE; + // AstGen.zig:2431 + return rvalue(gz, rl, ZIR_REF_VOID_VALUE, node); } // Labeled block (AstGen.zig:2466-2536). diff --git a/stage0/astgen_test.zig b/stage0/astgen_test.zig index f208e82808..8714c7b64e 100644 --- a/stage0/astgen_test.zig +++ b/stage0/astgen_test.zig @@ -256,6 +256,32 @@ fn expectEqualZir(gpa: Allocator, ref: Zir, got: c.Zir) !void { @as(i32, @intCast(got_counts[t])) - @as(i32, @intCast(ref_counts[t])), }); } + // Find first tag divergence. + const min_len = @min(ref_len, got.inst_len); + for (0..min_len) |i| { + const ref_tag: u8 = @intFromEnum(ref_tags[i]); + const got_tag: u8 = @intCast(got.inst_tags[i]); + if (ref_tag != got_tag) { + std.debug.print("first divergence at [{d}]: ref_tag={d} got_tag={d}\n", .{ i, ref_tag, got_tag }); + // Show ref instruction data for this position. + const rd = ref_datas[i]; + std.debug.print(" ref pl_node: src_node={d} payload={d}\n", .{ + rd.pl_node.src_node, rd.pl_node.payload_index, + }); + // Scan for nearest declaration. + var j: usize = i; + while (j > 0) { + j -= 1; + if (ref_tags[j] == .declaration) { + std.debug.print(" nearest decl at [{d}]: src_node={d}\n", .{ + j, ref_datas[j].declaration.src_node, + }); + break; + } + } + break; + } + } return error.TestExpectedEqual; } @@ -817,9 +843,6 @@ test "astgen: corpus tokenizer_test.zig" { } test "astgen: corpus parser_test.zig" { - // TODO: 10+ extra data mismatches (ref=48 got=32, bit 4 = propagate_error_trace) - // in call instruction flags — ctx propagation differs from upstream. - if (true) return error.SkipZigTest; const gpa = std.testing.allocator; try corpusCheck(gpa, @embedFile("parser_test.zig")); } @@ -857,7 +880,7 @@ test "astgen: struct init typed" { } test "astgen: corpus" { - if (true) return error.SkipZigTest; // TODO: parser_test.zig fails + // All individual corpus tests now pass. const gpa = std.testing.allocator; var any_fail = false;