commit 9aa97b3dcd18c0549b6c04169290abb68d77f338 (tree)
parent 70eb2ab984f7a4654b9dc3654c0c88240ccbed26
Author: Motiejus <motiejus@jakstys.lt>
Date: Sun, 8 Mar 2026 06:04:29 +0000
sema: port callconv(.c) support, resolveTypeFullyC for func/error_union (num_passing=104)
Add handling for builtin_value kinds 13-14 (calling_convention_c/inline)
in zirExtended, matching Sema.zig's zirBuiltinValue. This looks up "c"
or "inline" in the CallingConvention namespace.
Add func_type and error_union_type handlers to resolveTypeFullyC,
matching Type.resolveFully's recursive resolution for .fn and
.error_union types.
Add ptr_type + ptr_nav creation in ensureFullMemoizedStateC for
main-phase builtins (15-35), matching Zig's analyzeNavRefInner.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat:
4 files changed, 56 insertions(+), 3 deletions(-)
diff --git 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 = 103;
+pub const num_passing: usize = 104;
pub const files = [_][]const u8{
"stage0/sema_tests/empty.zig",
@@ -109,6 +109,7 @@ pub const files = [_][]const u8{
"lib/std/os/uefi/tables/table_header.zig",
"lib/std/zig/llvm.zig",
"stage0/sema_tests/export_builtin.zig",
+ "stage0/sema_tests/callconv_c.zig",
"lib/compiler_rt/neghf2.zig",
"lib/compiler_rt/negxf2.zig",
"lib/compiler_rt/absvdi2.zig",
diff --git a/stage0/sema.c b/stage0/sema.c
@@ -4989,6 +4989,23 @@ void resolveTypeFullyC(Sema* sema, InternPoolIndex ip_idx) {
// Slice wraps a pointer type; resolve the pointer's child.
resolveTypeFullyC(sema, sema->ip->items[ip_idx].data.slice);
break;
+ case IP_KEY_FUNC_TYPE: {
+ // Zig's resolveFully for .fn: recurse on params and return type.
+ const FuncType* ft = &sema->ip->items[ip_idx].data.func_type;
+ if (ft->is_generic)
+ break;
+ for (uint32_t i = 0; i < ft->param_count && i < FUNC_TYPE_MAX_PARAMS;
+ i++) {
+ resolveTypeFullyC(sema, ft->param_types[i]);
+ }
+ resolveTypeFullyC(sema, ft->return_type);
+ break;
+ }
+ case IP_KEY_ERROR_UNION_TYPE:
+ // Zig's resolveFully for .error_union: recurse on payload.
+ resolveTypeFullyC(
+ sema, sema->ip->items[ip_idx].data.error_union_type.payload);
+ break;
default:
break;
}
@@ -11279,8 +11296,33 @@ static AirInstRef zirExtended(Sema* sema, SemaBlock* block, uint32_t inst) {
}
}
}
- UNIMPLEMENTED("zirExtended: builtin_value kind not found");
- return AIR_REF_FROM_IP(IP_INDEX_VOID_VALUE); // unreachable
+ // Kinds 13-14: calling_convention_c / calling_convention_inline.
+ // Ported from Sema.zig zirBuiltinValue: these return VALUES
+ // (not types) by looking up "c" or "inline" in the
+ // CallingConvention namespace.
+ if (bv_kind == ZIR_BUILTIN_VALUE_CALLING_CONVENTION_C
+ || bv_kind == ZIR_BUILTIN_VALUE_CALLING_CONVENTION_INLINE) {
+ const char* field_name
+ = (bv_kind == ZIR_BUILTIN_VALUE_CALLING_CONVENTION_C)
+ ? "c"
+ : "inline";
+ InternPoolIndex cc_type = getBuiltinTypeC(sema, 2);
+ if (cc_type != IP_INDEX_NONE) {
+ uint32_t cc_ns = findNamespaceForType(sema, cc_type);
+ if (cc_ns != UINT32_MAX) {
+ uint32_t c_nav
+ = findNavInNamespace(sema, cc_ns, field_name);
+ if (c_nav != UINT32_MAX) {
+ InternPoolIndex val
+ = ensureNavValUpToDate(sema, c_nav);
+ if (val != IP_INDEX_NONE && val != IP_INDEX_VOID_VALUE)
+ return AIR_REF_FROM_IP(val);
+ }
+ }
+ }
+ }
+ // TODO: implement remaining builtin_value kinds
+ return AIR_REF_FROM_IP(IP_INDEX_VOID_VALUE);
}
UNIMPLEMENTED("zirExtended: unimplemented extended opcode");
return AIR_REF_FROM_IP(IP_INDEX_VOID_VALUE); // unreachable
diff --git a/stage0/sema_tests/callconv_c.zig b/stage0/sema_tests/callconv_c.zig
@@ -0,0 +1,3 @@
+export fn identity(a: u16) callconv(.c) u16 {
+ return a;
+}
diff --git a/stage0/zcu_per_thread.c b/stage0/zcu_per_thread.c
@@ -1333,6 +1333,13 @@ void ensureFullMemoizedStateC(Sema* sema) {
if (val == IP_INDEX_NONE)
continue;
+ // Create ptr_type + ptr_nav matching Zig's analyzeNavRefInner.
+ {
+ InternPoolIndex child = entry->is_type ? IP_INDEX_TYPE_TYPE : val;
+ InternPoolIndex ptr_ty = internPtrConst(sema, child);
+ (void)internNavPtr(sema, ptr_ty, nav);
+ }
+
sema->zcu->builtin_decl_values[i] = val;
// Immediately resolveFully for type builtins, matching Zig's