commit a5017bd6d050280d36ad86918a69fe10724ed2e0 (tree)
parent 0d07cad830b0dfef31516cf042ad5192ab30263f
Author: Motiejus Jakštys <motiejus@jakstys.lt>
Date: Thu, 26 Feb 2026 18:50:45 +0000
sema: prep work for cc body evaluation
- Add file_idx to Sema struct (tracks which loaded module the sema
operates on, needed by builtin_value resolution and cc body evaluation)
- Save cc body position/length in FuncZirInfo (needed to evaluate
calling convention bodies)
- Add builtin_value handler skeleton in zirExtended (returns void type
for now, will resolve CallingConvention/ExportOptions from std.builtin)
- Set mini_sema.file_idx in analyzeNavValC
- Add !fi.is_inline guard in zirFunc cc detection
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat:
2 files changed, 23 insertions(+), 9 deletions(-)
diff --git a/stage0/sema.c b/stage0/sema.c
@@ -91,6 +91,7 @@ void semaInit(Sema* sema, InternPool* ip, Zir code) {
sema->air_extra = ARR_INIT(uint32_t, SEMA_AIR_EXTRA_INITIAL_CAP);
sema->air_extra_cap = SEMA_AIR_EXTRA_INITIAL_CAP;
sema->func_index = IP_INDEX_NONE;
+ sema->file_idx = UINT32_MAX;
sema->fn_ret_ty = TYPE_NONE;
sema->branch_quota = SEMA_DEFAULT_BRANCH_QUOTA;
sema->allow_memoize = true;
@@ -1714,6 +1715,8 @@ typedef struct {
uint32_t ret_ty_body_len;
uint32_t ret_ty_ref_pos;
uint32_t param_block_pi; // offset from payload_index for param_block
+ uint32_t cc_body_pos; // position in code.extra of cc body instructions
+ uint32_t cc_body_len; // number of instructions in cc body
bool is_fancy;
bool has_cc_body; // for func_fancy: whether cc body is present
bool is_inline; // calling convention == .@"inline"
@@ -1738,12 +1741,13 @@ static FuncZirInfo parseFuncZir(Sema* sema, uint32_t inst) {
bool has_ret_ty_ref = (bits & (1u << 5)) != 0;
bool has_any_noalias = (bits & (1u << 7)) != 0;
if (info.has_cc_body) {
- uint32_t cc_body_len = sema->code.extra[extra_index];
+ info.cc_body_len = sema->code.extra[extra_index];
+ info.cc_body_pos = extra_index + 1;
// Check if CC body is calling_convention_inline.
// Inline functions have a cc body of [extended(builtin_value,
// CALLING_CONVENTION_INLINE), break_inline].
- if (cc_body_len >= 1) {
- uint32_t cc_inst = sema->code.extra[extra_index + 1];
+ if (info.cc_body_len >= 1) {
+ uint32_t cc_inst = sema->code.extra[info.cc_body_pos];
if (sema->code.inst_tags[cc_inst] == ZIR_INST_EXTENDED
&& sema->code.inst_datas[cc_inst].extended.opcode
== ZIR_EXT_BUILTIN_VALUE
@@ -1752,7 +1756,7 @@ static FuncZirInfo parseFuncZir(Sema* sema, uint32_t inst) {
info.is_inline = true;
}
}
- extra_index += 1 + cc_body_len;
+ extra_index += 1 + info.cc_body_len;
} else if (has_cc_ref) {
extra_index += 1;
}
@@ -4291,6 +4295,7 @@ static InternPoolIndex analyzeNavValC(uint32_t nav_idx) {
// cross-module declarations (e.g. @import("builtin").target).
Sema mini_sema;
semaInit(&mini_sema, s_module_ip, *zir);
+ mini_sema.file_idx = file_idx;
mini_sema.source_dir = s_loaded_modules[file_idx].source_dir;
mini_sema.module_root = s_global_module_root;
@@ -8903,9 +8908,8 @@ static void zirFunc(Sema* sema, SemaBlock* block, uint32_t inst) {
// Detect calling convention from func_fancy cc body.
uint8_t cc = 0; // default = .auto
- if (fi.is_fancy && fi.has_cc_body) {
- // C calling convention = 1 in the Zig enum
- cc = 1; // .c — simplified, will need proper resolution later
+ if (fi.is_fancy && fi.has_cc_body && !fi.is_inline) {
+ cc = 1; // .c — simplified for now
}
// Create function type IP entry.
@@ -10228,6 +10232,12 @@ static AirInstRef zirExtended(Sema* sema, SemaBlock* block, uint32_t inst) {
TypeIndex lhs_ty = semaTypeOf(sema, lhs);
return AIR_REF_FROM_IP(lhs_ty);
}
+ // builtin_value: return the type from std.builtin.
+ // Ported from src/Sema.zig builtinValue.
+ // TODO: resolve CallingConvention/ExportOptions from namespace
+ if (opcode == ZIR_EXT_BUILTIN_VALUE) {
+ return AIR_REF_FROM_IP(IP_INDEX_VOID_TYPE);
+ }
return AIR_REF_FROM_IP(IP_INDEX_VOID_TYPE);
}
@@ -11365,8 +11375,7 @@ static bool analyzeBodyInner(
continue;
// decl_val / decl_ref: reference to a module-level declaration.
- // Maps to void for now; the actual resolution happens in zirCall
- // when the callee is a decl_val/decl_ref.
+ // Returns the Nav's resolved value when available, void otherwise.
// When the declaration is an @import, lazily create a struct
// type for the imported module and recursively process its
// imports (matching Zig's ensureFileAnalyzed / scanNamespace).
@@ -12036,6 +12045,7 @@ SemaFuncAirList semaAnalyze(Sema* sema) {
root_mod->has_zir = true;
root_mod->analyzed = true;
s_root_file_idx = root_file_idx;
+ sema->file_idx = root_file_idx;
(void)createFileRootStructC(root_file_idx, &sema->code);
// Create ptr_nav for "root" in start.zig ($136),
@@ -12061,6 +12071,7 @@ SemaFuncAirList semaAnalyze(Sema* sema) {
s_loaded_modules[0].has_zir = true;
s_loaded_modules[0].analyzed = true;
s_root_file_idx = 0;
+ sema->file_idx = 0;
(void)createFileRootStructC(0, &sema->code);
resolveModuleDeclImports(0, 2);
}
diff --git a/stage0/sema.h b/stage0/sema.h
@@ -284,6 +284,9 @@ typedef struct Sema {
// When true, test declarations are analyzed (test blocks become
// analyzeable functions). Set by the caller before semaAnalyze.
bool is_test;
+ // File index into s_loaded_modules[] for this sema's module.
+ // Set by analyzeNavValC / semaAnalyze. UINT32_MAX = unknown.
+ uint32_t file_idx;
} Sema;
#define SEMA_DEFAULT_BRANCH_QUOTA 1000