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>
70 lines
2.3 KiB
C
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;
|
|
}
|