diff --git a/stage0/corpus.zig b/stage0/corpus.zig index e8441d7296..4037d74f88 100644 --- a/stage0/corpus.zig +++ b/stage0/corpus.zig @@ -3,7 +3,7 @@ /// `num_passing` controls how many files are tested and pre-generated. /// Both build.zig and stages_test.zig import this file. /// To enable more tests: just increment `num_passing`. -pub const num_passing: usize = 30; +pub const num_passing: usize = 31; pub const files = [_][]const u8{ "stage0/sema_tests/empty.zig", diff --git a/stage0/sema.c b/stage0/sema.c index 62fb26ffd2..57f1069673 100644 --- a/stage0/sema.c +++ b/stage0/sema.c @@ -8444,8 +8444,11 @@ static void zirFunc(Sema* sema, SemaBlock* block, uint32_t inst) { ret_ty = resolved; } - // Count parameters from param_block (not the function body). + // Count parameters and resolve their types from param_block. // Ported from Zir.getParamBody, matching ensureNavValUpToDate. + // Param types must be resolved BEFORE func_type creation to + // match the Zig compiler's funcCommon ordering (param type + // IP entries precede func_type in the intern pool). uint32_t param_count = 0; { uint32_t pi = sema->code.inst_datas[inst].pl_node.payload_index; @@ -8454,11 +8457,32 @@ static void zirFunc(Sema* sema, SemaBlock* block, uint32_t inst) { uint32_t pb_len = 0; getParamBody(sema, pb_inst, &pb_body, &pb_len); for (uint32_t pbi = 0; pbi < pb_len; pbi++) { - ZirInstTag ptag = sema->code.inst_tags[pb_body[pbi]]; - if (ptag == ZIR_INST_PARAM || ptag == ZIR_INST_PARAM_COMPTIME - || ptag == ZIR_INST_PARAM_ANYTYPE - || ptag == ZIR_INST_PARAM_ANYTYPE_COMPTIME) { - param_count++; + uint32_t param_inst = pb_body[pbi]; + ZirInstTag ptag = sema->code.inst_tags[param_inst]; + if (ptag != ZIR_INST_PARAM && ptag != ZIR_INST_PARAM_COMPTIME + && ptag != ZIR_INST_PARAM_ANYTYPE + && ptag != ZIR_INST_PARAM_ANYTYPE_COMPTIME) + continue; + param_count++; + // Resolve param type to create IP entries in the + // correct order (before func_type). + uint32_t pp + = sema->code.inst_datas[param_inst].pl_tok.payload_index; + uint32_t type_packed = sema->code.extra[pp + 1]; + uint32_t type_body_len = type_packed & 0x7FFFFFFF; + if (type_body_len == 1) { + // break_inline with operand = type ref. + uint32_t bi2 = sema->code.extra[pp + 2]; + if (sema->code.inst_tags[bi2] == ZIR_INST_BREAK_INLINE) { + ZirInstRef tref + = sema->code.inst_datas[bi2].break_data.operand; + (void)resolveZirTypeRef( + &sema->code, tref, ns_idx, sema->file_idx); + } + } else if (type_body_len == 2) { + uint32_t ti = sema->code.extra[pp + 2]; + (void)resolveZirTypeInst( + &sema->code, ti, ns_idx, sema->file_idx); } } } @@ -8538,13 +8562,18 @@ static void zirFunc(Sema* sema, SemaBlock* block, uint32_t inst) { } // Create function type IP entry. + // Use ipForceIntern because the C sema's func_type key doesn't + // include actual parameter types (only param_count), so ipIntern + // would incorrectly deduplicate functions with different param + // types but the same (ret, param_count, cc). The upstream Zig IP + // includes param types in the key, avoiding this false dedup. InternPoolKey ftype_key; memset(&ftype_key, 0, sizeof(ftype_key)); ftype_key.tag = IP_KEY_FUNC_TYPE; ftype_key.data.func_type.return_type = ret_ty; ftype_key.data.func_type.param_count = param_count; ftype_key.data.func_type.cc = cc; - InternPoolIndex func_type_ip = ipIntern(sema->ip, ftype_key); + InternPoolIndex func_type_ip = ipForceIntern(sema->ip, ftype_key); // Create func_decl entry (must follow func_type immediately). // Find the nav for this function declaration.