Files
zig/astgen.c
Motiejus Jakštys 5fb7a1ab9c Add astgen scaffolding with ZIR data structures and first passing test
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>
2026-02-11 18:37:07 +00:00

70 lines
2.3 KiB
C

#include "astgen.h"
#include "common.h"
#include <stdlib.h>
#include <string.h>
// Blake3("auto") truncated to 128 bits, as 4 x uint32_t (LE).
// This is std.zig.hashSrc("auto") used for the fields_hash of
// an empty auto-layout struct.
static const uint32_t HASH_AUTO[4]
= { 0x8e48032fu, 0x49f070dfu, 0x17991ae1u, 0xa6c4651au };
// StructDecl.Small packed struct layout (all zero for empty auto):
// bits 0-5: booleans (has_captures/fields/decls_len, has_backing_int,
// known_non_opv, known_comptime_only)
// bits 6-7: name_strategy (parent=0)
// bits 8-9: layout (auto=0)
// bits 10-12: booleans (any_default_inits/comptime_fields/aligned_fields)
// bits 13-15: padding
Zir astGen(const Ast* ast) {
Zir zir;
memset(&zir, 0, sizeof(zir));
// Allocate instruction arrays (1 instruction: root struct_decl).
zir.inst_cap = 1;
zir.inst_tags = ARR_INIT(ZirInstTag, 1);
zir.inst_datas = ARR_INIT(ZirInstData, 1);
// Allocate extra: 2 reserved + 6 StructDecl payload = 8.
zir.extra_cap = 8;
zir.extra = ARR_INIT(uint32_t, 8);
// Allocate string_bytes: 1 byte (reserved index 0).
zir.string_bytes_cap = 1;
zir.string_bytes = ARR_INIT(uint8_t, 1);
zir.string_bytes[0] = 0;
zir.string_bytes_len = 1;
// Reserved extra slots.
zir.extra[ZIR_EXTRA_COMPILE_ERRORS] = 0;
zir.extra[ZIR_EXTRA_IMPORTS] = 0;
zir.extra_len = ZIR_EXTRA_RESERVED_COUNT;
// StructDecl payload at extra[2..7]:
// fields_hash[0..3], src_line, src_node
uint32_t payload_index = zir.extra_len;
zir.extra[zir.extra_len++] = HASH_AUTO[0];
zir.extra[zir.extra_len++] = HASH_AUTO[1];
zir.extra[zir.extra_len++] = HASH_AUTO[2];
zir.extra[zir.extra_len++] = HASH_AUTO[3];
zir.extra[zir.extra_len++] = 0; // src_line
zir.extra[zir.extra_len++] = 0; // src_node (root)
// Instruction 0: extended/struct_decl.
ZirInstData data;
memset(&data, 0, sizeof(data));
data.extended.opcode = (uint16_t)ZIR_EXT_STRUCT_DECL;
data.extended.small = 0; // all flags zero for empty auto struct
data.extended.operand = payload_index;
zir.inst_tags[0] = ZIR_INST_EXTENDED;
zir.inst_datas[0] = data;
zir.inst_len = 1;
zir.has_compile_errors = false;
(void)ast;
return zir;
}