sema: add enum_literal→enum coercion and fix ptr_nav child types
- Add enum_literal + enum → enum peer type resolution in semaResolvePeerTypes. - Add enum_literal → enum coercion in semaCoerce: looks up the literal name in the target enum type's ZIR to create an enum_tag entry. - Make comptime CMP_EQ coerce through peer types before comparing, matching the Zig compiler's analyzeCmp → resolvePeerTypes → coerce path. This creates enum_tag IP entries as side effects. - Fix ptr_nav child type: use typeOf(val) instead of always type_type. During main analysis, all navs get ptr_type(child=typeOf(val)) + ptr_nav entries. During preamble, only type declarations (struct/enum/union) get ptr_nav. This matches analyzeNavRefInner. - Remove debug instrumentation (s_dbg_trace_body, instruction traces). - Add forward declarations for findEnumFieldByName, getEnumFieldIntVal, findEnumDeclForNav, internEnumTag. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
111
stage0/sema.c
111
stage0/sema.c
@@ -370,6 +370,13 @@ static uint32_t semaAddExtra(Sema* sema, uint32_t value) {
|
||||
|
||||
// --- Forward declarations ---
|
||||
static TypeIndex semaTypeOf(Sema* sema, AirInstRef ref);
|
||||
static uint32_t findEnumFieldByName(
|
||||
const Zir* zir, uint32_t enum_inst, const char* name);
|
||||
static InternPoolIndex getEnumFieldIntVal(
|
||||
const Zir* zir, uint32_t enum_inst, uint32_t field_idx);
|
||||
static uint32_t findEnumDeclForNav(uint32_t nav_idx, const Zir** out_zir);
|
||||
static InternPoolIndex internEnumTag(
|
||||
InternPoolIndex enum_ty, InternPoolIndex int_val);
|
||||
|
||||
// --- ZIR instruction handlers ---
|
||||
// Ported from src/Sema.zig instruction handlers.
|
||||
@@ -802,6 +809,14 @@ static TypeIndex semaResolvePeerTypes(
|
||||
return lhs_ty;
|
||||
return rhs_ty;
|
||||
}
|
||||
// enum_literal + enum → enum.
|
||||
// Ported from src/Sema.zig peer type resolution for enum_literal.
|
||||
if (lhs_ty == IP_INDEX_ENUM_LITERAL_TYPE
|
||||
&& sema->ip->items[rhs_ty].tag == IP_KEY_ENUM_TYPE)
|
||||
return rhs_ty;
|
||||
if (rhs_ty == IP_INDEX_ENUM_LITERAL_TYPE
|
||||
&& sema->ip->items[lhs_ty].tag == IP_KEY_ENUM_TYPE)
|
||||
return lhs_ty;
|
||||
// Unhandled combination (e.g. void×type in comptime analysis).
|
||||
// Return lhs as fallback; this path doesn't produce runtime AIR.
|
||||
return lhs_ty;
|
||||
@@ -849,6 +864,39 @@ static AirInstRef semaCoerce(
|
||||
key.data.undef = target_ty;
|
||||
return AIR_REF_FROM_IP(ipIntern(sema->ip, key));
|
||||
}
|
||||
// enum_literal → enum coercion: look up the literal in the enum type
|
||||
// and create an enum_tag entry.
|
||||
// Ported from src/Sema.zig coerce .enum → .enum_literal path.
|
||||
if (src_ty == IP_INDEX_ENUM_LITERAL_TYPE && AIR_REF_IS_IP(ref)
|
||||
&& sema->ip->items[target_ty].tag == IP_KEY_ENUM_TYPE) {
|
||||
InternPoolIndex lit_ip = AIR_REF_TO_IP(ref);
|
||||
uint32_t lit_str = sema->ip->items[lit_ip].data.enum_literal;
|
||||
const char* lit_name = (const char*)&sema->ip->string_bytes[lit_str];
|
||||
// Find the nav whose resolved_type matches the enum type.
|
||||
uint32_t enum_nav = UINT32_MAX;
|
||||
for (uint32_t ni = 0; ni < ipNavCount(); ni++) {
|
||||
if (ipGetNav(ni)->resolved_type == target_ty) {
|
||||
enum_nav = ni;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (enum_nav != UINT32_MAX) {
|
||||
const Zir* enum_zir = NULL;
|
||||
uint32_t enum_inst = findEnumDeclForNav(enum_nav, &enum_zir);
|
||||
if (enum_inst != UINT32_MAX && enum_zir != NULL) {
|
||||
uint32_t fidx
|
||||
= findEnumFieldByName(enum_zir, enum_inst, lit_name);
|
||||
if (fidx != UINT32_MAX) {
|
||||
InternPoolIndex int_val
|
||||
= getEnumFieldIntVal(enum_zir, enum_inst, fidx);
|
||||
if (int_val != IP_INDEX_NONE) {
|
||||
return AIR_REF_FROM_IP(
|
||||
internEnumTag(target_ty, int_val));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Comptime int→int coercion: re-intern with target type.
|
||||
if (AIR_REF_IS_IP(ref) && isIntegerType(sema->ip, src_ty)
|
||||
&& isIntegerType(sema->ip, target_ty)) {
|
||||
@@ -1382,9 +1430,15 @@ static AirInstRef zirArithmetic(
|
||||
return internComptimeInt(sema, result_ty, r_lo, r_hi);
|
||||
}
|
||||
|
||||
// Comptime equality for non-integer IP values (e.g. enum_literal).
|
||||
// Comptime equality for non-integer IP values (e.g. enum_tag,
|
||||
// enum_literal). Coerce through peer types first so that enum_literal
|
||||
// → enum coercion creates the enum_tag IP entry (matching the Zig
|
||||
// compiler's analyzeCmp → resolvePeerTypes → coerce path).
|
||||
if (AIR_REF_IS_IP(lhs) && AIR_REF_IS_IP(rhs)
|
||||
&& (air_tag == AIR_INST_CMP_EQ || air_tag == AIR_INST_CMP_NEQ)) {
|
||||
TypeIndex peer_ty = semaResolvePeerTypes(sema, lhs, rhs);
|
||||
lhs = semaCoerce(sema, block, peer_ty, lhs);
|
||||
rhs = semaCoerce(sema, block, peer_ty, rhs);
|
||||
bool eq = (AIR_REF_TO_IP(lhs) == AIR_REF_TO_IP(rhs));
|
||||
return AIR_REF_FROM_IP((eq == (air_tag == AIR_INST_CMP_EQ))
|
||||
? IP_INDEX_BOOL_TRUE
|
||||
@@ -3347,15 +3401,22 @@ static InternPoolIndex resolveZirTypeInst(
|
||||
if (nav != UINT32_MAX) {
|
||||
InternPoolIndex result = ensureNavValUpToDate(nav);
|
||||
if (result != IP_INDEX_NONE && result != IP_INDEX_VOID_TYPE) {
|
||||
// Create ptr_nav as side effect, matching Zig's
|
||||
// zirDeclVal → analyzeNavRef → analyzeNavRefInner.
|
||||
// Create ptr_type + ptr_nav matching analyzeNavRefInner.
|
||||
// During main analysis: all navs, typeOf(val) child.
|
||||
// During preamble: type decls only, type_type child.
|
||||
if (result < s_module_ip->items_len) {
|
||||
InternPoolKeyTag kt = s_module_ip->items[result].tag;
|
||||
if (kt == IP_KEY_STRUCT_TYPE || kt == IP_KEY_ENUM_TYPE
|
||||
|| kt == IP_KEY_UNION_TYPE) {
|
||||
InternPoolIndex dv_ptr_ty
|
||||
= internPtrConst(IP_INDEX_TYPE_TYPE);
|
||||
if (s_in_main_analysis) {
|
||||
InternPoolIndex val_ty = ipTypeOf(s_module_ip, result);
|
||||
InternPoolIndex dv_ptr_ty = internPtrConst(val_ty);
|
||||
(void)internNavPtr(dv_ptr_ty, nav);
|
||||
} else {
|
||||
InternPoolKeyTag kt = s_module_ip->items[result].tag;
|
||||
if (kt == IP_KEY_STRUCT_TYPE || kt == IP_KEY_ENUM_TYPE
|
||||
|| kt == IP_KEY_UNION_TYPE) {
|
||||
InternPoolIndex dv_ptr_ty
|
||||
= internPtrConst(IP_INDEX_TYPE_TYPE);
|
||||
(void)internNavPtr(dv_ptr_ty, nav);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -3428,16 +3489,22 @@ static InternPoolIndex resolveZirTypeInst(
|
||||
if (member_nav != UINT32_MAX) {
|
||||
InternPoolIndex result = ensureNavValUpToDate(member_nav);
|
||||
if (result != IP_INDEX_NONE) {
|
||||
// Create ptr_nav for type declarations only, matching
|
||||
// analyzeNavRefInner. Value declarations (comptime ints
|
||||
// etc.) don't get ptr_nav during field_val resolution.
|
||||
// Create ptr_type + ptr_nav matching analyzeNavRefInner.
|
||||
// During main analysis, create for ALL navs using
|
||||
// typeOf(val). During preamble, only for type decls.
|
||||
if (result < s_module_ip->items_len) {
|
||||
InternPoolKeyTag kt = s_module_ip->items[result].tag;
|
||||
if (kt == IP_KEY_STRUCT_TYPE || kt == IP_KEY_ENUM_TYPE
|
||||
|| kt == IP_KEY_UNION_TYPE) {
|
||||
InternPoolIndex nav_ptr_ty
|
||||
= internPtrConst(IP_INDEX_TYPE_TYPE);
|
||||
if (s_in_main_analysis) {
|
||||
InternPoolIndex val_ty = ipTypeOf(s_module_ip, result);
|
||||
InternPoolIndex nav_ptr_ty = internPtrConst(val_ty);
|
||||
(void)internNavPtr(nav_ptr_ty, member_nav);
|
||||
} else {
|
||||
InternPoolKeyTag kt = s_module_ip->items[result].tag;
|
||||
if (kt == IP_KEY_STRUCT_TYPE || kt == IP_KEY_ENUM_TYPE
|
||||
|| kt == IP_KEY_UNION_TYPE) {
|
||||
InternPoolIndex nav_ptr_ty
|
||||
= internPtrConst(IP_INDEX_TYPE_TYPE);
|
||||
(void)internNavPtr(nav_ptr_ty, member_nav);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -14631,12 +14698,12 @@ static bool analyzeBodyInner(
|
||||
InternPoolIndex val = ensureNavValUpToDate(nav);
|
||||
if (val != IP_INDEX_NONE) {
|
||||
resolved = val;
|
||||
// Create ptr_nav matching Zig's
|
||||
// analyzeNavRefInner. In Zig, zirDeclVal
|
||||
// creates ptr_type + ptr_nav for every
|
||||
// declaration access.
|
||||
InternPoolIndex pt
|
||||
= internPtrConst(IP_INDEX_TYPE_TYPE);
|
||||
// Create ptr_type + ptr_nav matching
|
||||
// analyzeNavRefInner. Uses typeOf(val) as
|
||||
// the child type (not always type_type).
|
||||
InternPoolIndex vt
|
||||
= ipTypeOf(s_module_ip, val);
|
||||
InternPoolIndex pt = internPtrConst(vt);
|
||||
(void)internNavPtr(pt, nav);
|
||||
}
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user