astgen: enable array_list.zig corpus test
Fix multiple bugs found via the array_list.zig corpus test: - Fix anytype param ref/index double-conversion (addStrTok returns a ref, don't add ZIR_REF_START_INDEX again) - Implement is_generic param tracking via is_used_or_discarded pointer in ScopeLocalVal - Fix globalVarDecl declaration src_line: use type_gz.decl_line instead of ag->source_line (which was advanced by init expression) - Fix cppcheck warning: remove redundant (0u << 2) in bitmask - Implement fetchRemoveRefEntries and ret_param_refs in addFunc - Add func_fancy case to buildHashSkipMask in test - Fix valgrind: zero elem_val_imm padding, skip addNodeExtended undefined small field, handle more padding-sensitive tags Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
183
stage0/astgen.c
183
stage0/astgen.c
@@ -296,6 +296,7 @@ typedef struct {
|
||||
uint32_t inst; // ZirInstRef
|
||||
uint32_t token_src; // Ast.TokenIndex
|
||||
uint32_t name; // NullTerminatedString (string table index)
|
||||
bool* is_used_or_discarded; // NULL if not tracking (AstGen.zig:11691)
|
||||
} ScopeLocalVal;
|
||||
|
||||
// Scope.LocalPtr (AstGen.zig:11704).
|
||||
@@ -1660,6 +1661,32 @@ static uint32_t countBodyLenAfterFixups(
|
||||
return countBodyLenAfterFixupsExtraRefs(ag, body, body_len, NULL, 0);
|
||||
}
|
||||
|
||||
// Mirrors fetchRemoveRefEntries (AstGen.zig:14066-14074).
|
||||
// For each param_inst, removes its ref_table entry (if present) and saves
|
||||
// the value. Returns the number of entries removed.
|
||||
static uint32_t fetchRemoveRefEntries(AstGenCtx* ag,
|
||||
const uint32_t* param_insts, uint32_t param_insts_len, uint32_t* result,
|
||||
uint32_t result_cap) {
|
||||
uint32_t count = 0;
|
||||
for (uint32_t i = 0; i < param_insts_len; i++) {
|
||||
uint32_t ref_inst;
|
||||
if (refTableFetchRemove(ag, param_insts[i], &ref_inst)) {
|
||||
if (count < result_cap)
|
||||
result[count] = ref_inst;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
// Mirrors appendBodyWithFixups (AstGen.zig:13649-13657).
|
||||
static void appendBodyWithFixups(
|
||||
AstGenCtx* ag, const uint32_t* body, uint32_t body_len) {
|
||||
for (uint32_t i = 0; i < body_len; i++) {
|
||||
appendPossiblyRefdBodyInst(ag, body[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Mirrors GenZir.setBlockBody (AstGen.zig:11949).
|
||||
// Writes Block payload (body_len + instruction indices) to extra.
|
||||
// Sets the instruction's payload_index. Unstacks gz.
|
||||
@@ -2497,6 +2524,7 @@ static uint32_t rvalue(
|
||||
// elem_val_imm: operand=result, idx=i.
|
||||
uint32_t elem_inst = reserveInstructionIndex(gz->astgen);
|
||||
gz->astgen->inst_tags[elem_inst] = ZIR_INST_ELEM_VAL_IMM;
|
||||
memset(&gz->astgen->inst_datas[elem_inst], 0, sizeof(ZirInstData));
|
||||
gz->astgen->inst_datas[elem_inst].elem_val_imm.operand = result;
|
||||
gz->astgen->inst_datas[elem_inst].elem_val_imm.idx = i;
|
||||
gzAppendInstruction(gz, elem_inst);
|
||||
@@ -3837,6 +3865,9 @@ static uint32_t localVarRef(GenZir* gz, Scope* scope, ResultLoc rl,
|
||||
case SCOPE_LOCAL_VAL: {
|
||||
ScopeLocalVal* lv = (ScopeLocalVal*)s;
|
||||
if (lv->name == name_str) {
|
||||
// Track usage for generic detection (AstGen.zig:8399).
|
||||
if (lv->is_used_or_discarded != NULL)
|
||||
*lv->is_used_or_discarded = true;
|
||||
// Locals cannot shadow, no ambiguity check needed.
|
||||
uint32_t value_inst;
|
||||
if (num_namespaces_out != 0) {
|
||||
@@ -9744,6 +9775,7 @@ static void varDecl(GenZir* gz, Scope* scope, uint32_t node,
|
||||
|
||||
// Extract type_node and init_node based on variant.
|
||||
uint32_t type_node = 0;
|
||||
uint32_t align_node = 0;
|
||||
uint32_t init_node = 0;
|
||||
|
||||
if (tag == AST_NODE_SIMPLE_VAR_DECL) {
|
||||
@@ -9753,13 +9785,14 @@ static void varDecl(GenZir* gz, Scope* scope, uint32_t node,
|
||||
} else if (tag == AST_NODE_LOCAL_VAR_DECL) {
|
||||
// lhs = extra_data index, rhs = init.
|
||||
// extra: {type_node, align_node, addrspace_node, section_node}
|
||||
// Simplified: just extract type_node.
|
||||
uint32_t extra_idx = nd.lhs;
|
||||
type_node = tree->extra_data.arr[extra_idx]; // type_node
|
||||
align_node = tree->extra_data.arr[extra_idx + 1]; // align_node
|
||||
init_node = nd.rhs;
|
||||
} else if (tag == AST_NODE_ALIGNED_VAR_DECL) {
|
||||
// lhs = align expr, rhs = init.
|
||||
// No type node in this variant.
|
||||
align_node = nd.lhs;
|
||||
init_node = nd.rhs;
|
||||
} else {
|
||||
// global_var_decl or unknown — bail.
|
||||
@@ -9773,6 +9806,18 @@ static void varDecl(GenZir* gz, Scope* scope, uint32_t node,
|
||||
return;
|
||||
}
|
||||
|
||||
// Evaluate alignment expression (AstGen.zig:3227-3230).
|
||||
uint32_t align_inst = ZIR_REF_NONE;
|
||||
if (align_node != 0) {
|
||||
ResultLoc align_rl = { .tag = RL_COERCED_TY,
|
||||
.data = ZIR_REF_U29_TYPE,
|
||||
.src_node = 0,
|
||||
.ctx = RI_CTX_NONE,
|
||||
.components = NULL,
|
||||
.components_len = 0 };
|
||||
align_inst = exprRl(gz, scope, align_rl, align_node);
|
||||
}
|
||||
|
||||
if (is_const) {
|
||||
// --- CONST path (AstGen.zig:3232-3340) ---
|
||||
|
||||
@@ -9823,6 +9868,7 @@ static void varDecl(GenZir* gz, Scope* scope, uint32_t node,
|
||||
val_out->inst = init_ref;
|
||||
val_out->token_src = name_token;
|
||||
val_out->name = ident_name;
|
||||
val_out->is_used_or_discarded = NULL;
|
||||
*scope_out = &val_out->base;
|
||||
} else {
|
||||
// Alloc path (AstGen.zig:3277-3340).
|
||||
@@ -9906,20 +9952,58 @@ static void varDecl(GenZir* gz, Scope* scope, uint32_t node,
|
||||
bool resolve_inferred = false;
|
||||
|
||||
if (type_node != 0) {
|
||||
// Typed var: alloc_mut (AstGen.zig:3361-3375).
|
||||
// Typed var: alloc_mut (AstGen.zig:3346-3365).
|
||||
uint32_t type_ref = typeExpr(gz, scope, type_node);
|
||||
ZirInstTag alloc_tag = is_comptime ? ZIR_INST_ALLOC_COMPTIME_MUT
|
||||
: ZIR_INST_ALLOC_MUT;
|
||||
alloc_ref = addUnNode(gz, alloc_tag, type_ref, node);
|
||||
if (align_inst == ZIR_REF_NONE) {
|
||||
ZirInstTag alloc_tag = is_comptime
|
||||
? ZIR_INST_ALLOC_COMPTIME_MUT
|
||||
: ZIR_INST_ALLOC_MUT;
|
||||
alloc_ref = addUnNode(gz, alloc_tag, type_ref, node);
|
||||
} else {
|
||||
// addAllocExtended (AstGen.zig:12781-12830).
|
||||
ensureExtraCapacity(ag, 3); // src_node + type + align
|
||||
uint32_t payload_index = ag->extra_len;
|
||||
int32_t src_off = (int32_t)node - (int32_t)gz->decl_node_index;
|
||||
memcpy(&ag->extra[ag->extra_len], &src_off, sizeof(uint32_t));
|
||||
ag->extra_len++;
|
||||
ag->extra[ag->extra_len++] = type_ref;
|
||||
ag->extra[ag->extra_len++] = align_inst;
|
||||
// small: has_type=1, has_align=1, is_const=0, is_comptime
|
||||
uint16_t small = (uint16_t)(1u | (1u << 1)
|
||||
| ((is_comptime ? 1u : 0u) << 3));
|
||||
ZirInstData edata;
|
||||
edata.extended.opcode = (uint16_t)ZIR_EXT_ALLOC;
|
||||
edata.extended.small = small;
|
||||
edata.extended.operand = payload_index;
|
||||
alloc_ref = addInstruction(gz, ZIR_INST_EXTENDED, edata);
|
||||
}
|
||||
} else {
|
||||
// Inferred type var: alloc_inferred_mut
|
||||
// (AstGen.zig:3384-3392).
|
||||
ZirInstTag alloc_tag = is_comptime
|
||||
? ZIR_INST_ALLOC_INFERRED_COMPTIME_MUT
|
||||
: ZIR_INST_ALLOC_INFERRED_MUT;
|
||||
ZirInstData adata;
|
||||
adata.node = (int32_t)node - (int32_t)gz->decl_node_index;
|
||||
alloc_ref = addInstruction(gz, alloc_tag, adata);
|
||||
// (AstGen.zig:3366-3385).
|
||||
if (align_inst == ZIR_REF_NONE) {
|
||||
ZirInstTag alloc_tag = is_comptime
|
||||
? ZIR_INST_ALLOC_INFERRED_COMPTIME_MUT
|
||||
: ZIR_INST_ALLOC_INFERRED_MUT;
|
||||
ZirInstData adata;
|
||||
adata.node = (int32_t)node - (int32_t)gz->decl_node_index;
|
||||
alloc_ref = addInstruction(gz, alloc_tag, adata);
|
||||
} else {
|
||||
// addAllocExtended without type (AstGen.zig:12781-12830).
|
||||
ensureExtraCapacity(ag, 2); // src_node + align
|
||||
uint32_t payload_index = ag->extra_len;
|
||||
int32_t src_off = (int32_t)node - (int32_t)gz->decl_node_index;
|
||||
memcpy(&ag->extra[ag->extra_len], &src_off, sizeof(uint32_t));
|
||||
ag->extra_len++;
|
||||
ag->extra[ag->extra_len++] = align_inst;
|
||||
// small: has_type=0, has_align=1, is_const=0, is_comptime
|
||||
uint16_t small
|
||||
= (uint16_t)((1u << 1) | ((is_comptime ? 1u : 0u) << 3));
|
||||
ZirInstData edata;
|
||||
edata.extended.opcode = (uint16_t)ZIR_EXT_ALLOC;
|
||||
edata.extended.small = small;
|
||||
edata.extended.operand = payload_index;
|
||||
alloc_ref = addInstruction(gz, ZIR_INST_EXTENDED, edata);
|
||||
}
|
||||
resolve_inferred = true;
|
||||
}
|
||||
|
||||
@@ -11222,7 +11306,7 @@ static uint32_t lastToken(const Ast* tree, uint32_t node) {
|
||||
// Creates a param instruction with pl_tok data and type body in extra.
|
||||
|
||||
static uint32_t addParam(GenZir* gz, GenZir* param_gz, ZirInstTag tag,
|
||||
uint32_t abs_tok_index, uint32_t name) {
|
||||
uint32_t abs_tok_index, uint32_t name, bool is_generic) {
|
||||
AstGenCtx* ag = gz->astgen;
|
||||
|
||||
uint32_t body_len = gzInstructionsLen(param_gz);
|
||||
@@ -11232,7 +11316,8 @@ static uint32_t addParam(GenZir* gz, GenZir* param_gz, ZirInstTag tag,
|
||||
ensureExtraCapacity(ag, 2 + body_len);
|
||||
uint32_t payload_index = ag->extra_len;
|
||||
ag->extra[ag->extra_len++] = name;
|
||||
ag->extra[ag->extra_len++] = body_len & 0x7FFFFFFFu; // is_generic = false
|
||||
ag->extra[ag->extra_len++]
|
||||
= (body_len & 0x7FFFFFFFu) | (is_generic ? 0x80000000u : 0u);
|
||||
for (uint32_t i = 0; i < body_len; i++) {
|
||||
ag->extra[ag->extra_len++] = param_body[i];
|
||||
}
|
||||
@@ -11272,7 +11357,9 @@ static uint32_t addFunc(GenZir* gz, uint32_t src_node, uint32_t block_node,
|
||||
uint32_t param_block, uint32_t ret_ref, const uint32_t* ret_body,
|
||||
uint32_t ret_body_len, const uint32_t* body, uint32_t body_len,
|
||||
const uint32_t* param_insts, uint32_t param_insts_len,
|
||||
uint32_t lbrace_line, uint32_t lbrace_column, bool is_inferred_error) {
|
||||
uint32_t lbrace_line, uint32_t lbrace_column, bool is_inferred_error,
|
||||
bool ret_ty_is_generic, const uint32_t* ret_param_refs,
|
||||
uint32_t ret_param_refs_len) {
|
||||
AstGenCtx* ag = gz->astgen;
|
||||
const Ast* tree = ag->tree;
|
||||
uint32_t rbrace_tok = lastToken(tree, block_node);
|
||||
@@ -11282,18 +11369,20 @@ static uint32_t addFunc(GenZir* gz, uint32_t src_node, uint32_t block_node,
|
||||
uint32_t rbrace_column = ag->source_column;
|
||||
|
||||
// Build Func payload (Zir.Inst.Func: ret_ty, param_block, body_len).
|
||||
// (AstGen.zig:12187-12194)
|
||||
// (AstGen.zig:12182-12194)
|
||||
uint32_t ret_ty_packed_len;
|
||||
if (ret_body_len > 0) {
|
||||
ret_ty_packed_len = ret_body_len; // body-based return type
|
||||
ret_ty_packed_len
|
||||
= countBodyLenAfterFixups(ag, ret_param_refs, ret_param_refs_len)
|
||||
+ countBodyLenAfterFixups(ag, ret_body, ret_body_len);
|
||||
} else if (ret_ref != ZIR_REF_NONE) {
|
||||
ret_ty_packed_len = 1; // simple Ref
|
||||
} else {
|
||||
ret_ty_packed_len = 0; // void return
|
||||
}
|
||||
// Pack RetTy: body_len:u31 | is_generic:bool(u1) = just body_len.
|
||||
uint32_t ret_ty_packed
|
||||
= ret_ty_packed_len & 0x7FFFFFFFu; // is_generic=false
|
||||
// Pack RetTy: body_len:u31 | is_generic:bool(u1).
|
||||
uint32_t ret_ty_packed = (ret_ty_packed_len & 0x7FFFFFFFu)
|
||||
| (ret_ty_is_generic ? 0x80000000u : 0u);
|
||||
|
||||
uint32_t fixup_body_len = countBodyLenAfterFixupsExtraRefs(
|
||||
ag, body, body_len, param_insts, param_insts_len);
|
||||
@@ -11303,10 +11392,11 @@ static uint32_t addFunc(GenZir* gz, uint32_t src_node, uint32_t block_node,
|
||||
ag->extra[ag->extra_len++] = param_block; // Func.param_block
|
||||
ag->extra[ag->extra_len++] = fixup_body_len; // Func.body_len
|
||||
|
||||
// Trailing ret_ty: either body instructions or a single ref.
|
||||
// Trailing ret_ty: either body instructions (with ret_param_refs
|
||||
// prepended) or a single ref. (AstGen.zig:12196-12204)
|
||||
if (ret_body_len > 0) {
|
||||
for (uint32_t i = 0; i < ret_body_len; i++)
|
||||
ag->extra[ag->extra_len++] = ret_body[i];
|
||||
appendBodyWithFixups(ag, ret_param_refs, ret_param_refs_len);
|
||||
appendBodyWithFixups(ag, ret_body, ret_body_len);
|
||||
} else if (ret_ref != ZIR_REF_NONE) {
|
||||
ag->extra[ag->extra_len++] = ret_ref;
|
||||
}
|
||||
@@ -11346,7 +11436,9 @@ static uint32_t addFuncFancy(GenZir* gz, uint32_t src_node,
|
||||
const uint32_t* cc_body, uint32_t cc_body_len, const uint32_t* body,
|
||||
uint32_t body_len, const uint32_t* param_insts, uint32_t param_insts_len,
|
||||
uint32_t lbrace_line, uint32_t lbrace_column, bool is_var_args,
|
||||
bool is_inferred_error, bool is_noinline, uint32_t noalias_bits) {
|
||||
bool is_inferred_error, bool is_noinline, uint32_t noalias_bits,
|
||||
bool ret_ty_is_generic, const uint32_t* ret_param_refs,
|
||||
uint32_t ret_param_refs_len) {
|
||||
AstGenCtx* ag = gz->astgen;
|
||||
const Ast* tree = ag->tree;
|
||||
uint32_t rbrace_tok = lastToken(tree, block_node);
|
||||
@@ -11367,11 +11459,11 @@ static uint32_t addFuncFancy(GenZir* gz, uint32_t src_node,
|
||||
}
|
||||
|
||||
// Calculate ret extra len (AstGen.zig:12231-12236).
|
||||
// Note: ret_param_refs are empty (no generic tracking yet).
|
||||
uint32_t ret_extra_len = 0;
|
||||
if (ret_body_len > 0) {
|
||||
ret_extra_len
|
||||
= countBodyLenAfterFixups(ag, ret_body, ret_body_len) + 1;
|
||||
= countBodyLenAfterFixups(ag, ret_param_refs, ret_param_refs_len)
|
||||
+ countBodyLenAfterFixups(ag, ret_body, ret_body_len) + 1;
|
||||
} else if (ret_ref != ZIR_REF_NONE) {
|
||||
ret_extra_len = 1;
|
||||
}
|
||||
@@ -11403,7 +11495,8 @@ static uint32_t addFuncFancy(GenZir* gz, uint32_t src_node,
|
||||
bits |= (1u << 6); // has_ret_ty_body
|
||||
if (noalias_bits != 0)
|
||||
bits |= (1u << 7); // has_any_noalias
|
||||
// bit 8 = ret_ty_is_generic (false for now, no generic tracking)
|
||||
if (ret_ty_is_generic)
|
||||
bits |= (1u << 8); // ret_ty_is_generic
|
||||
ag->extra[ag->extra_len++] = bits;
|
||||
|
||||
// Trailing cc (AstGen.zig:12143-12151).
|
||||
@@ -11417,12 +11510,12 @@ static uint32_t addFuncFancy(GenZir* gz, uint32_t src_node,
|
||||
}
|
||||
|
||||
// Trailing ret_ty (AstGen.zig:12152-12164).
|
||||
// Note: no ret_param_refs (generic tracking not implemented).
|
||||
if (ret_body_len > 0) {
|
||||
ag->extra[ag->extra_len++]
|
||||
= countBodyLenAfterFixups(ag, ret_body, ret_body_len);
|
||||
for (uint32_t i = 0; i < ret_body_len; i++)
|
||||
appendPossiblyRefdBodyInst(ag, ret_body[i]);
|
||||
= countBodyLenAfterFixups(ag, ret_param_refs, ret_param_refs_len)
|
||||
+ countBodyLenAfterFixups(ag, ret_body, ret_body_len);
|
||||
appendBodyWithFixups(ag, ret_param_refs, ret_param_refs_len);
|
||||
appendBodyWithFixups(ag, ret_body, ret_body_len);
|
||||
} else if (ret_ref != ZIR_REF_NONE) {
|
||||
ag->extra[ag->extra_len++] = ret_ref;
|
||||
}
|
||||
@@ -11573,7 +11666,7 @@ static void testDecl(AstGenCtx* ag, GenZir* gz, Scope* scope,
|
||||
// Create func instruction (AstGen.zig:4874-4897).
|
||||
uint32_t func_ref = addFunc(&decl_block, node, body_node, decl_inst,
|
||||
ZIR_REF_ANYERROR_VOID_ERROR_UNION_TYPE, NULL, 0, fn_body, fn_body_len,
|
||||
NULL, 0, lbrace_line, lbrace_column, false);
|
||||
NULL, 0, lbrace_line, lbrace_column, false, false, NULL, 0);
|
||||
|
||||
// break_inline returning func to declaration (AstGen.zig:4899).
|
||||
makeBreakInline(&decl_block, decl_inst, func_ref, AST_NODE_OFFSET_NONE);
|
||||
@@ -11750,6 +11843,8 @@ static void fnDecl(AstGenCtx* ag, GenZir* gz, Scope* scope,
|
||||
uint32_t param_insts_len = 0;
|
||||
// noalias_bits tracking (AstGen.zig:4259).
|
||||
uint32_t noalias_bits = 0;
|
||||
// Generic parameter/return type tracking (AstGen.zig:4257).
|
||||
bool any_param_used = false;
|
||||
// is_var_args detection (AstGen.zig:4261).
|
||||
bool is_var_args = false;
|
||||
|
||||
@@ -11890,11 +11985,13 @@ static void fnDecl(AstGenCtx* ag, GenZir* gz, Scope* scope,
|
||||
: ZIR_INST_PARAM_ANYTYPE;
|
||||
uint32_t anytype_inst = addStrTok(
|
||||
&decl_gz, anytype_tag, param_name_str, anytype_name_token);
|
||||
param_inst_ref = anytype_inst + ZIR_REF_START_INDEX;
|
||||
param_inst_ref = anytype_inst; // already a ref (toRef())
|
||||
if (param_insts_len < 32)
|
||||
param_insts[param_insts_len++] = anytype_inst;
|
||||
param_insts[param_insts_len++]
|
||||
= anytype_inst - ZIR_REF_START_INDEX; // toIndex()
|
||||
} else {
|
||||
// Type-expression parameter (AstGen.zig:4330-4344).
|
||||
any_param_used = false; // reset before evaluating type body
|
||||
GenZir param_gz = makeSubBlock(&decl_gz, params_scope);
|
||||
uint32_t param_type_ref = fullBodyExpr(
|
||||
¶m_gz, params_scope, coerced_type_ri, param_type_node);
|
||||
@@ -11907,6 +12004,7 @@ static void fnDecl(AstGenCtx* ag, GenZir* gz, Scope* scope,
|
||||
uint32_t param_inst_expected = ag->inst_len + 1;
|
||||
makeBreakInline(¶m_gz, param_inst_expected, param_type_ref,
|
||||
(int32_t)param_type_node - (int32_t)param_gz.decl_node_index);
|
||||
bool param_type_is_generic = any_param_used;
|
||||
|
||||
// Create param instruction (AstGen.zig:4341-4343).
|
||||
ZirInstTag param_tag
|
||||
@@ -11915,7 +12013,7 @@ static void fnDecl(AstGenCtx* ag, GenZir* gz, Scope* scope,
|
||||
? name_token
|
||||
: tree->nodes.main_tokens[param_type_node];
|
||||
uint32_t param_inst = addParam(&decl_gz, ¶m_gz, param_tag,
|
||||
name_tok_for_src, param_name_str);
|
||||
name_tok_for_src, param_name_str, param_type_is_generic);
|
||||
(void)param_inst_expected;
|
||||
param_inst_ref = param_inst + ZIR_REF_START_INDEX;
|
||||
if (param_insts_len < 32)
|
||||
@@ -11931,12 +12029,14 @@ static void fnDecl(AstGenCtx* ag, GenZir* gz, Scope* scope,
|
||||
lv->inst = param_inst_ref;
|
||||
lv->token_src = name_token;
|
||||
lv->name = param_name_str;
|
||||
lv->is_used_or_discarded = &any_param_used;
|
||||
params_scope = &lv->base;
|
||||
}
|
||||
param_type_i++;
|
||||
}
|
||||
|
||||
// --- Return type (AstGen.zig:4369-4383) ---
|
||||
any_param_used = false; // reset for return type generic detection
|
||||
GenZir ret_gz = makeSubBlock(&decl_gz, params_scope);
|
||||
uint32_t ret_ref = ZIR_REF_NONE;
|
||||
if (return_type_node != 0) {
|
||||
@@ -11952,6 +12052,11 @@ static void fnDecl(AstGenCtx* ag, GenZir* gz, Scope* scope,
|
||||
makeBreakInline(&ret_gz, 0, ret_ref, AST_NODE_OFFSET_NONE);
|
||||
}
|
||||
}
|
||||
// Fetch ref entries for params used in return type (AstGen.zig:4384).
|
||||
uint32_t ret_param_refs[32];
|
||||
uint32_t ret_param_refs_len = fetchRemoveRefEntries(
|
||||
ag, param_insts, param_insts_len, ret_param_refs, 32);
|
||||
bool ret_ty_is_generic = any_param_used;
|
||||
// Map void_type → .none (AstGen.zig:12054).
|
||||
if (ret_ref == ZIR_REF_VOID_TYPE)
|
||||
ret_ref = ZIR_REF_NONE;
|
||||
@@ -12124,11 +12229,13 @@ static void fnDecl(AstGenCtx* ag, GenZir* gz, Scope* scope,
|
||||
ret_body, ret_body_len, cc_ref, cc_body, cc_body_len, fn_body,
|
||||
fn_body_len, param_insts, param_insts_len, lbrace_line,
|
||||
lbrace_column, is_var_args, is_inferred_error, is_noinline,
|
||||
noalias_bits);
|
||||
noalias_bits, ret_ty_is_generic, ret_param_refs,
|
||||
ret_param_refs_len);
|
||||
} else {
|
||||
func_ref = addFunc(&decl_gz, node, body_node, decl_inst, ret_ref,
|
||||
ret_body, ret_body_len, fn_body, fn_body_len, param_insts,
|
||||
param_insts_len, lbrace_line, lbrace_column, is_inferred_error);
|
||||
param_insts_len, lbrace_line, lbrace_column, is_inferred_error,
|
||||
ret_ty_is_generic, ret_param_refs, ret_param_refs_len);
|
||||
}
|
||||
|
||||
// Patch ret_body break_inline to point to func instruction
|
||||
@@ -12621,7 +12728,7 @@ static void globalVarDecl(AstGenCtx* ag, GenZir* gz, Scope* scope,
|
||||
has_special_body, has_lib_name);
|
||||
|
||||
setDeclaration(ag, decl_inst,
|
||||
(SetDeclArgs) { .src_line = ag->source_line,
|
||||
(SetDeclArgs) { .src_line = type_gz.decl_line,
|
||||
.src_column = decl_column,
|
||||
.id = decl_id,
|
||||
.name = name_str,
|
||||
|
||||
@@ -81,6 +81,40 @@ fn buildHashSkipMask(gpa: Allocator, ref: Zir) ![]bool {
|
||||
}
|
||||
}
|
||||
},
|
||||
.func_fancy => {
|
||||
// FuncFancy: param_block(1) + body_len(1) + bits(1)
|
||||
// + trailing cc + ret_ty + noalias + body + SrcLocs(3) + proto_hash(4).
|
||||
const pi = ref_datas[i].pl_node.payload_index;
|
||||
const body_len: u32 = ref.extra[pi + 1];
|
||||
const bits: u32 = ref.extra[pi + 2];
|
||||
var ei: u32 = pi + 3;
|
||||
const has_cc_ref: bool = (bits & (1 << 3)) != 0;
|
||||
const has_cc_body: bool = (bits & (1 << 4)) != 0;
|
||||
const has_ret_ty_ref: bool = (bits & (1 << 5)) != 0;
|
||||
const has_ret_ty_body: bool = (bits & (1 << 6)) != 0;
|
||||
const has_any_noalias: bool = (bits & (1 << 7)) != 0;
|
||||
if (has_cc_body) {
|
||||
const cc_body_len = ref.extra[ei];
|
||||
ei += 1 + cc_body_len;
|
||||
} else if (has_cc_ref) {
|
||||
ei += 1;
|
||||
}
|
||||
if (has_ret_ty_body) {
|
||||
const ret_body_len = ref.extra[ei];
|
||||
ei += 1 + ret_body_len;
|
||||
} else if (has_ret_ty_ref) {
|
||||
ei += 1;
|
||||
}
|
||||
if (has_any_noalias) ei += 1;
|
||||
// body + SrcLocs(3) + proto_hash(4)
|
||||
if (body_len > 0) {
|
||||
const hash_start = ei + body_len + 3;
|
||||
for (0..4) |j| {
|
||||
if (hash_start + j < ref_extra_len)
|
||||
skip[hash_start + j] = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
@@ -300,7 +334,35 @@ fn expectEqualZir(gpa: Allocator, ref: Zir, got: c.Zir) !void {
|
||||
|
||||
// 3. Compare instruction data field-by-field.
|
||||
for (0..ref_len) |i| {
|
||||
try expectEqualData(i, ref_tags[i], ref_datas[i], got.inst_datas[i]);
|
||||
expectEqualData(i, ref_tags[i], ref_datas[i], got.inst_datas[i]) catch {
|
||||
// Print nearest declaration for context.
|
||||
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;
|
||||
}
|
||||
}
|
||||
// Print what tags are at the operand positions if break_inline.
|
||||
if (ref_tags[i] == .break_inline) {
|
||||
const r_op = @intFromEnum(ref_datas[i].@"break".operand);
|
||||
const g_op = got.inst_datas[i].break_data.operand;
|
||||
if (r_op >= 124 and r_op - 124 < ref_len) {
|
||||
std.debug.print(" ref operand inst[{d}] tag={d}\n", .{
|
||||
r_op - 124, @intFromEnum(ref_tags[r_op - 124]),
|
||||
});
|
||||
}
|
||||
if (g_op >= 124 and g_op - 124 < ref_len) {
|
||||
std.debug.print(" got operand inst[{d}] tag={d}\n", .{
|
||||
g_op - 124, @intFromEnum(ref_tags[g_op - 124]),
|
||||
});
|
||||
}
|
||||
}
|
||||
return error.TestExpectedEqual;
|
||||
};
|
||||
}
|
||||
// 4. Compare string bytes.
|
||||
const ref_sb_len: u32 = @intCast(ref.string_bytes.len);
|
||||
@@ -370,6 +432,17 @@ fn expectEqualData(
|
||||
.enum_decl,
|
||||
.union_decl,
|
||||
.opaque_decl,
|
||||
// addNodeExtended sets small = undefined (AstGen.zig:12775).
|
||||
.this,
|
||||
.ret_addr,
|
||||
.error_return_trace,
|
||||
.frame,
|
||||
.frame_address,
|
||||
.breakpoint,
|
||||
.disable_instrumentation,
|
||||
.disable_intrinsics,
|
||||
.in_comptime,
|
||||
.c_va_start,
|
||||
=> true,
|
||||
else => false,
|
||||
};
|
||||
@@ -522,6 +595,7 @@ fn expectEqualData(
|
||||
},
|
||||
.func,
|
||||
.func_inferred,
|
||||
.func_fancy,
|
||||
.array_type,
|
||||
.array_type_sentinel,
|
||||
.array_cat,
|
||||
@@ -678,6 +752,10 @@ fn expectEqualData(
|
||||
.@"unreachable",
|
||||
// .save_err_ret_index data format (operand only):
|
||||
.save_err_ret_index,
|
||||
// .float data format (f32 = 4 bytes, second word is padding):
|
||||
.float,
|
||||
// .elem_val_imm data format (u32 + u8, 3 bytes padding):
|
||||
.elem_val_imm,
|
||||
=> true,
|
||||
else => false,
|
||||
};
|
||||
@@ -853,7 +931,6 @@ test "astgen: corpus astgen_test.zig" {
|
||||
}
|
||||
|
||||
test "astgen: corpus array_list.zig" {
|
||||
if (true) return error.SkipZigTest; // TODO: +2 ALLOC_MUT / -2 EXTENDED tag mismatch at [6639]
|
||||
const gpa = std.testing.allocator;
|
||||
try corpusCheck(gpa, @embedFile("../lib/std/array_list.zig"));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user