Use nodeIndexToRelative(decl_node) = node - proto_node for the
break_inline returning func to declaration, matching upstream
AstGen.zig:4495. Previously used AST_NODE_OFFSET_NONE which
produced incorrect extra data values.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Handle anonymous struct init (.{.a = b}) when the result location has
a type (RL_TY/RL_COERCED_TY). Emit validate_struct_init_result_ty and
struct_init_field_type instructions, matching upstream AstGen.zig:
1706-1731 and structInitExprTyped.
Also add validate_struct_init_result_ty to test comparison functions
and fix char literal escape sequences.
build.zig corpus: improved from 25 to 3 inst diff (remaining:
as_node coercion in rvalue).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
astgen_test.zig corpus: extra_len and string_bytes diffs remain.
tokenizer_test.zig/build.zig: need ref_coerced_ty result location.
Both issues require significant architectural work in the AstRlAnnotate
pre-pass to properly support typed result locations (ref_coerced_ty,
coerced_ty) that generate different instruction sequences.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add escape sequence handling to strLitAsString (\n, \r, \t, \\, \',
\", \xNN). Previously copied string content byte-for-byte.
- Fix strLitAsString quote scanning to skip escaped quotes (\\").
- Handle @"..." quoted identifiers in identAsString.
- Add test name and field name strings to scanContainer to match
upstream string table insertion order.
- Skip dedup against reserved index 0 in strLitAsString to match
upstream hash table behavior.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Port the emitDbgNode(parent_gz, cond_expr) call from upstream
AstGen.zig:6335 into ifExpr. This emits a DBG_STMT instruction
before evaluating the if condition, matching the reference output.
Enable astgen_test.zig corpus test (still has extra_len and
string_bytes mismatches to fix).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add corpus tests for tokenizer_test.zig and astgen_test.zig, skipped
pending fixes:
- tokenizer_test.zig: needs ref_coerced_ty result location (428 inst diff)
- astgen_test.zig: 1 missing dbg_stmt, extra_len mismatch (375 extra diff)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix arrayInitExpr for [_]T{...} patterns to use elem_type as the
coercion target for each element expression (RL_COERCED_TY), matching
upstream AstGen.zig:1598-1642. Previously used RL_NONE_VAL which
produced different instruction sequences.
Add struct init typed and enum decl isolated tests.
Note: build.zig corpus still needs ref_coerced_ty result location
support and fn body ordering fixes — left as TODO.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add enumDeclInner and setEnum, ported from upstream AstGen.zig:5508-5729.
Dispatch in containerDecl based on main_token keyword (struct vs enum).
Fix fnDecl to pass proto_node (not fn_decl node) to makeDeclaration,
matching upstream AstGen.zig:4090.
Improve is_pub detection in fnDecl to use token tags instead of string
comparison.
Add func/func_inferred proto_hash to the test hash skip mask, and
enum_decl fields_hash skipping.
Tests added: enum decl.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rewrite globalVarDecl to properly handle extern/export/pub/threadlocal
variables with type/align/linksection/addrspace bodies. Port the full
Declaration extra data layout from upstream AstGen.zig:13883, including
lib_name, type_body, and special bodies fields.
Add extractVarDecl to decode all VarDecl node types (global, local,
simple, aligned) and computeVarDeclId to select the correct
Declaration.Flags.Id.
Fix firstToken to scan backwards for modifier tokens (extern, export,
pub, threadlocal, comptime) on var decl nodes, matching upstream
Ast.zig:634-643.
Test added: extern var.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Port errorSetDecl from upstream AstGen.zig:5905-5955. Replaces the
SET_ERROR placeholder at the ERROR_SET_DECL case. Loops tokens between
lbrace and rbrace, collecting identifier strings into the ErrorSetDecl
payload.
Also add error_set_decl to the test comparison functions.
Tests added: empty error set, error set with members.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Port WipMembers, field processing loop, nodeImpliesMoreThanOnePossibleValue,
and nodeImpliesComptimeOnly from upstream AstGen.zig. Struct fields are now
properly emitted with type expressions, default values, alignment, and
comptime annotations.
Also fix structDeclInner to add the reserved instruction to the GenZir
body (matching upstream gz.reserveInstructionIndex behavior) and use
AST_NODE_OFFSET_NONE for break_inline src_node in field bodies.
Tests added: single field, multiple fields, field with default, field
with alignment, comptime field.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
test_all.zig is 5 lines of @import statements and already produces
matching ZIR. Enable it as a standalone corpus test while keeping
the full corpus test skipped.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- continue: emit check_comptime_control_flow and
restore_err_ret_index_unconditional (matching AstGen.zig:2328-2334)
- forExpr: set loop_scope.continue_block = cond_block
(matching AstGen.zig:6974), allowing continue inside for loops
to target the correct scope
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- 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>
- Add genDefers() with DEFER_NORMAL_ONLY/DEFER_BOTH_SANS_ERR modes
- Add countDefers() for checking defer types in scope chain
- Add genDefers calls to breakExpr, continueExpr, retExpr, tryExpr
- Add fn_block tracking to AstGenCtx (set in fnDecl/testDecl)
- Add return error.Foo fast path using ret_err_value instruction
- Fix fullBodyExpr scope: pass &body_gz.base instead of params_scope
- Fix blockExprStmts: guard genDefers with noreturn_stmt check
- Fix retExpr MAYBE path: correct dbg_stmt/restore ordering
- Save/restore fn_block in containerDecl (set NULL for nested structs)
- addEnsureResult now returns bool indicating noreturn
First ZIR tag mismatch moved from inst[211] to inst[428].
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Port several AstGen.zig patterns to C:
- Thread ResultLoc through fullBodyExpr, ifExpr, switchExpr, callExpr,
calleeExpr (for proper type coercion and decl_literal handling)
- Add rlBr() and breakResultInfo() helpers mirroring upstream ri.br()
and setBreakResultInfo
- Implement labeled blocks with label on GenZir (matching upstream),
restoreErrRetIndex before break, and break_result_info
- Fix breakExpr to emit restoreErrRetIndex and use break_result_info
for value/void breaks (AstGen.zig:2150-2237)
- Add setBlockComptimeBody with comptime_reason field (was using
setBlockBody which omitted the reason, causing wrong extra layout)
- Add comptime_reason parameter to comptimeExpr with correct reasons
for type/array_sentinel/switch_item/comptime_keyword contexts
- Handle enum_literal in calleeExpr (decl_literal_no_coerce)
- Fix decl_literal rvalue wrapping for ty/coerced_ty result locs
All 5 corpus files now pass byte-by-byte ZIR comparison.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Port scope chain infrastructure, function parameters, local var_decl,
control flow (if/for/while/switch/orelse/catch/defer), labeled blocks,
break/continue, comparison/boolean/unary operators, array access,
field access rvalue, rvalue type coercion optimization, and many
builtins from upstream AstGen.zig. test_all.zig corpus passes;
4 remaining corpus files still have mismatches (WIP).
Also fix cppcheck/lint issues: safe realloc pattern, null checks,
const correctness, enable inline suppressions, comment out test
debug output for clean `zig build`.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Valgrind 3.26.0 cannot decode AVX-512 instructions. On AVX-512 capable
CPUs (e.g. Zen 4), Zig's standard library emits these instructions when
targeting native, causing immediate crashes. Subtract avx512f from the
CPU features when -Dvalgrind is set.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Compare the C parser's AST against Zig's std.zig.Ast.parse() output in
every testParse call. This catches structural mismatches (tokens, nodes,
extra_data) without needing a separate corpus.
Also fix two C parser bugs found by the new check:
- Empty anonymous init `.{}` now uses struct_init_dot_two (not
array_init_dot_two), matching the Zig parser.
- for-type-expr with single input and no else now emits for_simple
(not for with extra_data), matching the Zig parser's parseFor.
Skip the check under valgrind since Zig's tokenizer uses AVX-512.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Introduce zir.h/zir.c with ZIR instruction types (269 tags, 56 extended
opcodes, 8-byte Data union) ported from lib/std/zig/Zir.zig, and
astgen.h/astgen.c implementing the empty-container fast path that produces
correct ZIR for empty source files.
The test infrastructure in astgen_test.zig compares C astGen() output
field-by-field against Zig's std.zig.AstGen.generate() using tag-based
dispatch, avoiding raw byte comparison since Zig's Data union has no
guaranteed in-memory layout.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix 11 divergences where parser.c differed from Parse.zig in logic or
structure, not justified by C vs Zig language differences:
- parseContainerMembers: set trailing=false after test decl, add
field_state tracking (A1, A2)
- expectStatement: guard defer/errdefer behind allow_defer_var (A3)
- expectVarDeclExprStatement: wrap assignment in comptime node when
comptime_token is set (A4)
- parseBlock: guard semicolon check with statements_len != 0 (A5)
- parseLabeledStatement: add parseSwitchExpr call (A6)
- parseWhileStatement: restructure with else_required and early
returns to match upstream control flow (A7)
- parseForStatement: restructure with else_required/has_else and
early returns to match upstream control flow (A8)
- parseFnProto: fail when return_type_expr is missing (A9)
- expectTopLevelDecl: track is_extern, reject extern fn body (A10)
- parsePrefixExpr: remove TOKEN_KEYWORD_AWAIT case (A11)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reorder function definitions so they follow the same order as upstream
zig/lib/std/zig/Parse.zig, making cross-referencing easier. Move
OperInfo and NodeContainerField typedefs to the header section, and add
forward declarations for parseParamDeclList and operTable that are now
needed due to the new ordering.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rename assignOpTag to assignOpNode to match upstream. Extract inlined
code into separate functions to match upstream's structure:
expectTestDecl, expectIfStatement, expectParamDecl, parseSwitchProngList.
Add parseSingleAssignExpr for upstream API surface alignment.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Introduce a fail(p, "msg") inline function that stores the error message
in a buffer and longjmps, replacing ~52 fprintf(stderr,...)+longjmp pairs.
The error message is propagated through Ast.err_msg so callers can decide
whether/how to display it. Also add forward declarations for all static
functions and move PtrModifiers typedef to the type definitions section.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>