stage0: refactor globals into structs matching Zig architecture
Eliminates all 39 mutable static globals across sema.c (37) and intern_pool.c (2). State is now held in properly-typed structs passed as parameters, mirroring the Zig reference implementation layout. New files matching Zig src/ layout: - compilation.h: CompilationConfig + Compilation (matches Compilation.zig) - zcu.h/zcu.c: ZcuFile, ZcuNamespace, Zcu, zcuInit/zcuDeinit (matches Zcu.zig) - zcu_per_thread.h: forward declarations for PerThread-style functions Key changes: - InternPool gains navs[] (dynamically allocated) + nav_count/nav_cap; Nav functions now take InternPool* (was implicit via globals) - Sema gains Zcu* zcu; semaInit now takes Zcu* instead of InternPool* - All module-level state (files, namespaces, memoized state, config) moved from static globals into Zcu struct - zig0.c creates Compilation + Zcu before semaInit - Test files updated to use zcuInit/zcuDeinit API Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -16,6 +16,7 @@ const zig0_headers = &[_][]const u8{
|
||||
"ast.h",
|
||||
"astgen.h",
|
||||
"common.h",
|
||||
"compilation.h",
|
||||
"intern_pool.h",
|
||||
"parser.h",
|
||||
"sema.h",
|
||||
@@ -24,6 +25,8 @@ const zig0_headers = &[_][]const u8{
|
||||
"verbose_air.h",
|
||||
"verbose_intern_pool.h",
|
||||
"wyhash.h",
|
||||
"zcu.h",
|
||||
"zcu_per_thread.h",
|
||||
"zir.h",
|
||||
};
|
||||
const zig0_c_lib_files = &[_][]const u8{
|
||||
@@ -40,6 +43,7 @@ const zig0_c_lib_files = &[_][]const u8{
|
||||
"verbose_intern_pool.c",
|
||||
"wyhash.c",
|
||||
"zig0.c",
|
||||
"zcu.c",
|
||||
"zir.c",
|
||||
};
|
||||
const zig0_all_c_files = zig0_c_lib_files ++ &[_][]const u8{"main.c"};
|
||||
|
||||
20
stage0/compilation.h
Normal file
20
stage0/compilation.h
Normal file
@@ -0,0 +1,20 @@
|
||||
// compilation.h — ported from src/Compilation.zig (Config subset we use)
|
||||
#ifndef _ZIG0_COMPILATION_H__
|
||||
#define _ZIG0_COMPILATION_H__
|
||||
#include <stdbool.h>
|
||||
|
||||
// Matches Compilation.Config (the fields relevant to stage0).
|
||||
typedef struct {
|
||||
const char* module_root; // was: s_global_module_root
|
||||
const char* target_cpu_arch; // was: s_target_cpu_arch_name ("wasm32")
|
||||
const char* target_cpu_model; // was: s_target_cpu_model_name ("lime1")
|
||||
const char* object_format; // was: s_config_object_format ("wasm")
|
||||
const char* link_mode; // was: s_config_link_mode ("static")
|
||||
bool is_test; // was: s_config_is_test
|
||||
} CompilationConfig;
|
||||
|
||||
// Matches Compilation struct (minimal subset).
|
||||
typedef struct Compilation {
|
||||
CompilationConfig config;
|
||||
} Compilation;
|
||||
#endif
|
||||
@@ -443,6 +443,8 @@ InternPool ipInit(void) {
|
||||
ip.string_bytes_cap = IP_STRING_INITIAL_CAP;
|
||||
ip.extra = ARR_INIT(uint32_t, IP_EXTRA_INITIAL_CAP);
|
||||
ip.extra_cap = IP_EXTRA_INITIAL_CAP;
|
||||
ip.navs = ARR_INIT(Nav, 64);
|
||||
ip.nav_cap = 64;
|
||||
|
||||
// Index 0: u0_type
|
||||
ipAppendItem(&ip, ipMakeIntType(0, 0));
|
||||
@@ -685,10 +687,12 @@ void ipDeinit(InternPool* ip) {
|
||||
free(ip->hash_table);
|
||||
free(ip->string_bytes);
|
||||
free(ip->extra);
|
||||
free(ip->navs);
|
||||
ip->items = NULL;
|
||||
ip->hash_table = NULL;
|
||||
ip->string_bytes = NULL;
|
||||
ip->extra = NULL;
|
||||
ip->navs = NULL;
|
||||
ip->items_len = 0;
|
||||
ip->items_cap = 0;
|
||||
ip->hash_cap = 0;
|
||||
@@ -696,6 +700,8 @@ void ipDeinit(InternPool* ip) {
|
||||
ip->string_bytes_cap = 0;
|
||||
ip->extra_len = 0;
|
||||
ip->extra_cap = 0;
|
||||
ip->nav_count = 0;
|
||||
ip->nav_cap = 0;
|
||||
}
|
||||
|
||||
InternPoolIndex ipIntern(InternPool* ip, InternPoolKey key) {
|
||||
@@ -1008,14 +1014,19 @@ InternPoolIndex ipTypeOf(const InternPool* ip, InternPoolIndex index) {
|
||||
// --- Nav management ---
|
||||
// Ported from InternPool.createDeclNav / InternPool.getNav.
|
||||
|
||||
static Nav s_navs[IP_MAX_NAVS];
|
||||
static uint32_t s_num_navs;
|
||||
|
||||
uint32_t ipCreateDeclNav(uint32_t name, uint32_t fqn, uint32_t zir_index,
|
||||
uint32_t namespace_idx, bool is_pub, bool is_const) {
|
||||
assert(s_num_navs < IP_MAX_NAVS);
|
||||
uint32_t idx = s_num_navs++;
|
||||
Nav* nav = &s_navs[idx];
|
||||
uint32_t ipCreateDeclNav(InternPool* ip, uint32_t name, uint32_t fqn,
|
||||
uint32_t zir_index, uint32_t namespace_idx, bool is_pub, bool is_const) {
|
||||
assert(ip->nav_count < IP_MAX_NAVS);
|
||||
if (ip->nav_count >= ip->nav_cap) {
|
||||
uint32_t new_cap = ip->nav_cap * 2;
|
||||
Nav* new_navs = realloc(ip->navs, new_cap * sizeof(Nav));
|
||||
if (!new_navs)
|
||||
exit(1);
|
||||
ip->navs = new_navs;
|
||||
ip->nav_cap = new_cap;
|
||||
}
|
||||
uint32_t idx = ip->nav_count++;
|
||||
Nav* nav = &ip->navs[idx];
|
||||
memset(nav, 0, sizeof(*nav));
|
||||
nav->name = name;
|
||||
nav->fqn = fqn;
|
||||
@@ -1028,14 +1039,14 @@ uint32_t ipCreateDeclNav(uint32_t name, uint32_t fqn, uint32_t zir_index,
|
||||
return idx;
|
||||
}
|
||||
|
||||
Nav* ipGetNav(uint32_t nav_index) {
|
||||
assert(nav_index < s_num_navs);
|
||||
return &s_navs[nav_index];
|
||||
Nav* ipGetNav(InternPool* ip, uint32_t nav_index) {
|
||||
assert(nav_index < ip->nav_count);
|
||||
return &ip->navs[nav_index];
|
||||
}
|
||||
|
||||
void ipResetNavs(void) { s_num_navs = 0; }
|
||||
void ipResetNavs(InternPool* ip) { ip->nav_count = 0; }
|
||||
|
||||
uint32_t ipNavCount(void) { return s_num_navs; }
|
||||
uint32_t ipNavCount(const InternPool* ip) { return ip->nav_count; }
|
||||
|
||||
// --- String interning ---
|
||||
// Add a null-terminated string to the IP string table. Returns the
|
||||
|
||||
@@ -423,6 +423,24 @@ typedef struct {
|
||||
} data;
|
||||
} InternPoolKey;
|
||||
|
||||
// --- Nav (declaration entry) ---
|
||||
// Ported from InternPool.Nav. Navs are stored in a separate list from
|
||||
// IP items — they do NOT consume IP indices. However, ptr_nav entries
|
||||
// (pointers TO Navs) DO consume IP indices.
|
||||
|
||||
typedef struct {
|
||||
uint32_t name; // NullTerminatedString index into IP string_bytes
|
||||
uint32_t fqn; // fully qualified name string index
|
||||
uint32_t zir_index; // ZIR instruction index of declaration
|
||||
uint32_t namespace_idx; // owning namespace index
|
||||
InternPoolIndex resolved_type; // IP_INDEX_NONE if unresolved
|
||||
InternPoolIndex resolved_val; // IP_INDEX_NONE if unresolved
|
||||
bool is_pub;
|
||||
bool is_const;
|
||||
} Nav;
|
||||
|
||||
#define IP_MAX_NAVS 16384
|
||||
|
||||
// --- InternPool struct ---
|
||||
|
||||
typedef struct {
|
||||
@@ -449,26 +467,14 @@ typedef struct {
|
||||
uint32_t skip_dedup_end;
|
||||
uint32_t cc_keep_start;
|
||||
uint32_t cc_keep_end;
|
||||
// Nav storage (ported from InternPool.zig Nav storage).
|
||||
// Navs do NOT consume IP indices; ptr_nav entries (pointers to navs)
|
||||
// do consume IP indices. Dynamically allocated (like items/extra).
|
||||
Nav* navs;
|
||||
uint32_t nav_count;
|
||||
uint32_t nav_cap;
|
||||
} InternPool;
|
||||
|
||||
// --- Nav (declaration entry) ---
|
||||
// Ported from InternPool.Nav. Navs are stored in a separate list from
|
||||
// IP items — they do NOT consume IP indices. However, ptr_nav entries
|
||||
// (pointers TO Navs) DO consume IP indices.
|
||||
|
||||
typedef struct {
|
||||
uint32_t name; // NullTerminatedString index into IP string_bytes
|
||||
uint32_t fqn; // fully qualified name string index
|
||||
uint32_t zir_index; // ZIR instruction index of declaration
|
||||
uint32_t namespace_idx; // owning namespace index
|
||||
InternPoolIndex resolved_type; // IP_INDEX_NONE if unresolved
|
||||
InternPoolIndex resolved_val; // IP_INDEX_NONE if unresolved
|
||||
bool is_pub;
|
||||
bool is_const;
|
||||
} Nav;
|
||||
|
||||
#define IP_MAX_NAVS 16384
|
||||
|
||||
// --- Function declarations ---
|
||||
|
||||
InternPool ipInit(void);
|
||||
@@ -479,11 +485,11 @@ InternPoolKey ipIndexToKey(const InternPool* ip, InternPoolIndex index);
|
||||
InternPoolIndex ipTypeOf(const InternPool* ip, InternPoolIndex index);
|
||||
|
||||
// Nav management (ported from InternPool.createDeclNav)
|
||||
uint32_t ipCreateDeclNav(uint32_t name, uint32_t fqn, uint32_t zir_index,
|
||||
uint32_t namespace_idx, bool is_pub, bool is_const);
|
||||
Nav* ipGetNav(uint32_t nav_index);
|
||||
void ipResetNavs(void);
|
||||
uint32_t ipNavCount(void);
|
||||
uint32_t ipCreateDeclNav(InternPool* ip, uint32_t name, uint32_t fqn,
|
||||
uint32_t zir_index, uint32_t namespace_idx, bool is_pub, bool is_const);
|
||||
Nav* ipGetNav(InternPool* ip, uint32_t nav_index);
|
||||
void ipResetNavs(InternPool* ip);
|
||||
uint32_t ipNavCount(const InternPool* ip);
|
||||
|
||||
// String interning: add a null-terminated string to the IP string table.
|
||||
// Returns the NullTerminatedString index (offset into string_bytes).
|
||||
|
||||
1687
stage0/sema.c
1687
stage0/sema.c
File diff suppressed because it is too large
Load Diff
@@ -10,6 +10,11 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// Forward declaration — full definition in zcu.h, included by sema.c.
|
||||
struct Zcu;
|
||||
|
||||
#define MAX_EXPORTED_DECL_NAMES 16
|
||||
|
||||
// --- InstMap ---
|
||||
// Maps ZIR instruction index -> AIR instruction ref.
|
||||
// Uses a flat array indexed by ZIR instruction index minus a start offset.
|
||||
@@ -109,24 +114,6 @@ typedef struct {
|
||||
uint32_t runtime_index;
|
||||
} ComptimeAlloc;
|
||||
|
||||
// --- SemaNamespace ---
|
||||
// Groups declarations by owning type (file root struct, etc.).
|
||||
// Ported from Zcu.Namespace.
|
||||
|
||||
#define SEMA_NS_MAX_NAVS 1024
|
||||
#define SEMA_NS_MAX_COMPTIME 64
|
||||
|
||||
typedef struct {
|
||||
InternPoolIndex owner_type; // type_struct IP index
|
||||
uint32_t file_idx; // index into loaded modules
|
||||
uint32_t pub_navs[SEMA_NS_MAX_NAVS];
|
||||
uint32_t pub_nav_count;
|
||||
uint32_t priv_navs[SEMA_NS_MAX_NAVS];
|
||||
uint32_t priv_nav_count;
|
||||
uint32_t comptime_decls[SEMA_NS_MAX_COMPTIME]; // ZIR inst indices
|
||||
uint32_t comptime_decl_count;
|
||||
} SemaNamespace;
|
||||
|
||||
// --- SemaFuncAir ---
|
||||
// Per-function Air result, produced during sema analysis.
|
||||
|
||||
@@ -164,7 +151,8 @@ typedef struct {
|
||||
// generation.
|
||||
|
||||
typedef struct Sema {
|
||||
InternPool* ip;
|
||||
InternPool* ip; // points to zcu->ip for convenient access
|
||||
struct Zcu* zcu; // owning Zcu (set by semaInit)
|
||||
Zir code;
|
||||
uint8_t* air_inst_tags; // AirInstTag stored as uint8_t (matches Zig u8)
|
||||
AirInstData* air_inst_datas;
|
||||
@@ -194,6 +182,7 @@ typedef struct Sema {
|
||||
// Populated by analyzeBodyInner when processing comptime blocks
|
||||
// that contain @export. Used by zirFunc to decide whether to analyze
|
||||
// non-declaration-level-exported functions.
|
||||
uint32_t exported_decl_names[MAX_EXPORTED_DECL_NAMES];
|
||||
uint32_t num_exported_decl_names;
|
||||
// Declaration table: maps string_bytes index (name) to the ZIR
|
||||
// declaration instruction index. Built by zirStructDecl.
|
||||
@@ -204,10 +193,6 @@ typedef struct Sema {
|
||||
// Source directory for resolving relative imports.
|
||||
// Set by the caller before semaAnalyze. NULL = no import resolution.
|
||||
const char* source_dir;
|
||||
// Module root directory for resolving non-relative imports
|
||||
// (e.g. @import("std") → <module_root>/lib/std/std.zig).
|
||||
// Set by the caller before semaAnalyze. NULL = no std resolution.
|
||||
const char* module_root;
|
||||
// Root FQN prefix for function name construction.
|
||||
// Function names are "{root_fqn}.funcName" (e.g. "empty_void_function.f").
|
||||
// Must match the Zig compiler's module naming (filename stem).
|
||||
@@ -287,7 +272,7 @@ typedef struct Sema {
|
||||
|
||||
// --- Function declarations ---
|
||||
|
||||
void semaInit(Sema* sema, InternPool* ip, Zir code);
|
||||
void semaInit(Sema* sema, struct Zcu* zcu, Zir code);
|
||||
void semaDeinit(Sema* sema);
|
||||
SemaFuncAirList semaAnalyze(Sema* sema);
|
||||
void semaFuncAirListDeinit(SemaFuncAirList* list);
|
||||
|
||||
@@ -5,6 +5,7 @@ const std = @import("std");
|
||||
pub const c = @cImport({
|
||||
@cInclude("astgen.h");
|
||||
@cInclude("sema.h");
|
||||
@cInclude("zcu.h");
|
||||
});
|
||||
|
||||
// Helper to convert C #define integer constants (c_int) to u32 for comparison
|
||||
@@ -167,14 +168,14 @@ test "intern_pool: pointer types" {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const SemaCheckResult = struct {
|
||||
c_ip: c.InternPool,
|
||||
c_zcu: *c.Zcu,
|
||||
c_sema: c.Sema,
|
||||
c_func_air_list: c.SemaFuncAirList,
|
||||
|
||||
fn deinit(self: *SemaCheckResult) void {
|
||||
c.semaFuncAirListDeinit(&self.c_func_air_list);
|
||||
c.semaDeinit(&self.c_sema);
|
||||
c.ipDeinit(&self.c_ip);
|
||||
c.zcuDeinit(self.c_zcu);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -184,8 +185,16 @@ fn semaCheck(source: [:0]const u8) !SemaCheckResult {
|
||||
var c_zir = c.astGen(&c_ast);
|
||||
defer c.zirDeinit(&c_zir);
|
||||
var result: SemaCheckResult = undefined;
|
||||
result.c_ip = c.ipInit();
|
||||
c.semaInit(&result.c_sema, &result.c_ip, c_zir);
|
||||
var comp: c.Compilation = .{ .config = .{
|
||||
.module_root = null,
|
||||
.target_cpu_arch = "wasm32",
|
||||
.target_cpu_model = "lime1",
|
||||
.object_format = "wasm",
|
||||
.link_mode = "static",
|
||||
.is_test = false,
|
||||
} };
|
||||
result.c_zcu = c.zcuInit(&comp);
|
||||
c.semaInit(&result.c_sema, result.c_zcu, c_zir);
|
||||
result.c_func_air_list = c.semaAnalyze(&result.c_sema);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -68,29 +68,34 @@ fn stagesCheck(gpa: Allocator, comptime path: []const u8, source: [:0]const u8)
|
||||
var module_root_buf: [std.fs.max_path_bytes:0]u8 = undefined;
|
||||
const module_root_path = std.fmt.bufPrintZ(&module_root_buf, "{s}", .{abs_repo_root}) catch unreachable;
|
||||
|
||||
var c_ip = sc.ipInit();
|
||||
defer sc.ipDeinit(&c_ip);
|
||||
var comp: sc.Compilation = .{ .config = .{
|
||||
.module_root = module_root_path.ptr,
|
||||
.target_cpu_arch = "wasm32",
|
||||
.target_cpu_model = "lime1",
|
||||
.object_format = "wasm",
|
||||
.link_mode = "static",
|
||||
.is_test = false,
|
||||
} };
|
||||
const c_zcu = sc.zcuInit(&comp);
|
||||
defer sc.zcuDeinit(c_zcu);
|
||||
var c_sema: sc.Sema = undefined;
|
||||
sc.semaInit(&c_sema, &c_ip, @bitCast(c_zir));
|
||||
sc.semaInit(&c_sema, c_zcu, @bitCast(c_zir));
|
||||
defer sc.semaDeinit(&c_sema);
|
||||
// Pre-generated AIR uses ReleaseSmall (strip=true), so match it.
|
||||
c_sema.strip = true;
|
||||
// Set source_dir, module_root, root_fqn based on path prefix.
|
||||
// Set source_dir, root_fqn based on path prefix.
|
||||
if (comptime std.mem.startsWith(u8, path, "stage0/")) {
|
||||
// Sema unit tests: set module_root to enable std/start/builtin
|
||||
// loading, matching the Zig compiler which always creates std
|
||||
// even with std_mod=null (Compilation.zig line 2196).
|
||||
c_sema.source_dir = source_dir_path.ptr;
|
||||
c_sema.module_root = module_root_path.ptr;
|
||||
c_sema.root_fqn = comptime sema_test.pathStem(path);
|
||||
} else if (comptime std.mem.startsWith(u8, path, "lib/std/")) {
|
||||
c_sema.source_dir = source_dir_path.ptr;
|
||||
c_sema.module_root = module_root_path.ptr;
|
||||
c_sema.root_fqn = "std";
|
||||
c_sema.module_prefix = sema_test.pathToModulePrefix(path);
|
||||
} else {
|
||||
c_sema.source_dir = source_dir_path.ptr;
|
||||
c_sema.module_root = module_root_path.ptr;
|
||||
c_sema.root_fqn = comptime sema_test.pathStem(path);
|
||||
}
|
||||
var c_func_air_list = sc.semaAnalyze(&c_sema);
|
||||
|
||||
30
stage0/zcu.c
Normal file
30
stage0/zcu.c
Normal file
@@ -0,0 +1,30 @@
|
||||
#include "zcu.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
Zcu* zcuInit(Compilation* comp) {
|
||||
Zcu* zcu = (Zcu*)calloc(1, sizeof(Zcu));
|
||||
if (!zcu)
|
||||
exit(1);
|
||||
zcu->ip = ipInit();
|
||||
zcu->comp = comp;
|
||||
// Initialize sentinel values.
|
||||
zcu->std_file_idx = UINT32_MAX;
|
||||
zcu->builtin_file_idx = UINT32_MAX;
|
||||
zcu->cg_builtin_ns_idx = UINT32_MAX;
|
||||
zcu->cg_builtin_nav = UINT32_MAX;
|
||||
return zcu;
|
||||
}
|
||||
|
||||
void zcuDeinit(Zcu* zcu) {
|
||||
// Free loaded file ASTs and ZIRs.
|
||||
for (uint32_t i = 0; i < zcu->num_files; i++) {
|
||||
ZcuFile* f = &zcu->files[i];
|
||||
if (f->has_zir) {
|
||||
zirDeinit(&f->zir);
|
||||
astDeinit(&f->ast);
|
||||
}
|
||||
}
|
||||
ipDeinit(&zcu->ip);
|
||||
// zcuAlloc uses calloc; free the struct itself.
|
||||
free(zcu);
|
||||
}
|
||||
109
stage0/zcu.h
Normal file
109
stage0/zcu.h
Normal file
@@ -0,0 +1,109 @@
|
||||
// zcu.h — ported from src/Zcu.zig + src/Zcu/PerThread.zig.
|
||||
// Holds all module-level state for a compilation unit.
|
||||
#ifndef _ZIG0_ZCU_H__
|
||||
#define _ZIG0_ZCU_H__
|
||||
|
||||
#include "ast.h"
|
||||
#include "compilation.h"
|
||||
#include "intern_pool.h"
|
||||
#include "zir.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// --- ZcuFile (matches Zcu.File) ---
|
||||
// Per-source-file state.
|
||||
|
||||
#define ZCU_MAX_FILES 512
|
||||
|
||||
typedef struct {
|
||||
char path[1024]; // canonical file path
|
||||
char source_dir[1024]; // directory containing this file
|
||||
Zir zir; // parsed ZIR (inst_len>0 if loaded)
|
||||
Ast ast; // AST (kept alive to own source memory)
|
||||
bool has_zir; // true if zir/ast are populated
|
||||
bool analyzed; // true if createFileRootStructC has been called
|
||||
} ZcuFile;
|
||||
|
||||
// --- ZcuNamespace (matches Zcu.Namespace) ---
|
||||
|
||||
#define ZCU_NS_MAX_NAVS 1024
|
||||
#define ZCU_NS_MAX_COMPTIME 64
|
||||
#define ZCU_MAX_NAMESPACES 512
|
||||
|
||||
typedef struct {
|
||||
InternPoolIndex owner_type; // type_struct IP index
|
||||
uint32_t file_idx; // index into files[]
|
||||
uint32_t pub_navs[ZCU_NS_MAX_NAVS];
|
||||
uint32_t pub_nav_count;
|
||||
uint32_t priv_navs[ZCU_NS_MAX_NAVS];
|
||||
uint32_t priv_nav_count;
|
||||
uint32_t comptime_decls[ZCU_NS_MAX_COMPTIME]; // ZIR inst indices
|
||||
uint32_t comptime_decl_count;
|
||||
} ZcuNamespace;
|
||||
|
||||
// --- Zcu struct (matches Zcu.zig) ---
|
||||
// Heap-allocated (use zcuInit/zcuDeinit); too large for stack.
|
||||
|
||||
#define NUM_BUILTIN_DECL_MAIN 36
|
||||
|
||||
typedef struct Zcu {
|
||||
InternPool ip; // owns IP; matches Zcu.intern_pool
|
||||
|
||||
// --- File management (matches Zcu.import_table / Zcu.File) ---
|
||||
ZcuFile files[ZCU_MAX_FILES]; // matches Zcu.files
|
||||
uint32_t num_files;
|
||||
uint32_t root_file_idx;
|
||||
uint32_t std_file_idx;
|
||||
uint32_t builtin_file_idx;
|
||||
|
||||
// --- Builtin namespace/nav ---
|
||||
uint32_t cg_builtin_ns_idx; // compiler-generated builtin namespace
|
||||
uint32_t cg_builtin_nav;
|
||||
|
||||
// --- Struct type hashing (C-specific) ---
|
||||
uint32_t next_struct_hash; // unique hash counter for struct types
|
||||
|
||||
// --- Analysis state ---
|
||||
bool in_main_analysis;
|
||||
uint32_t enum_force_intern_threshold;
|
||||
|
||||
// --- Namespaces (matches Zcu.Namespace storage) ---
|
||||
ZcuNamespace namespaces[ZCU_MAX_NAMESPACES];
|
||||
uint32_t num_namespaces;
|
||||
InternPoolIndex file_root_types[ZCU_MAX_FILES];
|
||||
uint32_t file_namespaces[ZCU_MAX_FILES];
|
||||
|
||||
// --- Type/layout resolution tracking ---
|
||||
bool struct_layout_resolved[4096];
|
||||
bool struct_fully_resolved[4096];
|
||||
bool union_fully_resolved[4096];
|
||||
InternPoolIndex union_tag_enums[256];
|
||||
InternPoolIndex union_tag_types[256];
|
||||
uint32_t num_union_tag_enums;
|
||||
|
||||
// --- Memoized builtin state (matches Zcu.builtin_decl_values) ---
|
||||
bool memoized_main_resolved;
|
||||
bool full_memoized_resolved;
|
||||
InternPoolIndex builtin_decl_values[NUM_BUILTIN_DECL_MAIN];
|
||||
|
||||
// --- Preamble IP range tracking (C-specific shard simulation) ---
|
||||
uint32_t preamble_memoized_start;
|
||||
uint32_t preamble_memoized_end;
|
||||
uint32_t preamble_cc_start;
|
||||
uint32_t preamble_cc_end;
|
||||
uint32_t preamble_builtin_navs[5];
|
||||
uint32_t preamble_builtin_nav_count;
|
||||
|
||||
// --- Compilation config ---
|
||||
Compilation* comp; // back-pointer; matches Zcu.comp in Zig
|
||||
} Zcu;
|
||||
|
||||
// --- Function declarations ---
|
||||
|
||||
// Allocate and initialize a Zcu on the heap (too large for stack).
|
||||
Zcu* zcuInit(Compilation* comp);
|
||||
|
||||
// Free all resources including the struct itself (matches zcuInit).
|
||||
void zcuDeinit(Zcu* zcu);
|
||||
|
||||
#endif
|
||||
67
stage0/zcu_per_thread.h
Normal file
67
stage0/zcu_per_thread.h
Normal file
@@ -0,0 +1,67 @@
|
||||
// zcu_per_thread.h — ported from src/Zcu/PerThread.zig.
|
||||
// Functions for per-thread analysis orchestration.
|
||||
#ifndef _ZIG0_ZCU_PER_THREAD_H__
|
||||
#define _ZIG0_ZCU_PER_THREAD_H__
|
||||
|
||||
#include "zcu.h"
|
||||
#include "zir.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// Forward declaration: avoid including sema.h here.
|
||||
struct Sema;
|
||||
|
||||
// These match PerThread.zig functions (taking Sema* for Zcu access):
|
||||
|
||||
// Load, parse, and analyze an imported file. Returns the file index,
|
||||
// or UINT32_MAX on failure. (matches PerThread.ensureFileAnalyzed)
|
||||
uint32_t ensureFileAnalyzedC(struct Sema* sema, const char* full_path);
|
||||
|
||||
// Create the root struct type for a file. (matches
|
||||
// PerThread.createFileRootStruct)
|
||||
InternPoolIndex createFileRootStructC(
|
||||
struct Sema* sema, uint32_t file_idx, const Zir* zir);
|
||||
|
||||
// Scan a namespace, building its Nav list. (matches PerThread.scanNamespace)
|
||||
void scanNamespaceC(struct Sema* sema, uint32_t ns_idx,
|
||||
const uint32_t* decl_insts, uint32_t decls_len, const Zir* zir);
|
||||
|
||||
// Analyze a nav declaration's value. (matches PerThread.analyzeNavVal)
|
||||
InternPoolIndex analyzeNavValC(struct Sema* sema, uint32_t nav_idx);
|
||||
|
||||
// Resolve memoized state for .main builtins. (matches
|
||||
// PerThread.analyzeMemoizedState)
|
||||
void analyzeMemoizedStateC(struct Sema* sema);
|
||||
|
||||
// Ensure a Nav's value is up to date.
|
||||
InternPoolIndex ensureNavValUpToDate(struct Sema* sema, uint32_t nav_idx);
|
||||
|
||||
// Resolve all 36 .main-stage builtins. (matches
|
||||
// PerThread.ensureFullMemoizedState)
|
||||
void ensureFullMemoizedStateC(struct Sema* sema);
|
||||
|
||||
// Handle @import. (matches PerThread.importFile / doImport)
|
||||
uint32_t doImport(
|
||||
struct Sema* sema, const char* source_dir, const char* import_string);
|
||||
|
||||
// Resolve struct layout (field offsets).
|
||||
bool resolveStructLayoutC(struct Sema* sema, uint32_t nav_idx);
|
||||
|
||||
// Resolve struct fully (field types).
|
||||
void resolveStructFullyC(struct Sema* sema, uint32_t nav_idx);
|
||||
|
||||
// Resolve union fully (field types + tag enum).
|
||||
void resolveUnionFullyC(struct Sema* sema, uint32_t nav_idx);
|
||||
|
||||
// Find namespace index for a type IP index.
|
||||
uint32_t findNamespaceForType(struct Sema* sema, InternPoolIndex type_ip);
|
||||
|
||||
// Find a nav in a namespace by name. Returns UINT32_MAX if not found.
|
||||
uint32_t findNavInNamespace(
|
||||
struct Sema* sema, uint32_t ns_idx, const char* name);
|
||||
|
||||
// Analyze a comptime block at file scope.
|
||||
void analyzeComptimeUnit(
|
||||
struct Sema* sema, uint32_t file_idx, uint32_t comptime_decl);
|
||||
|
||||
#endif
|
||||
@@ -1,9 +1,11 @@
|
||||
#include "ast.h"
|
||||
#include "astgen.h"
|
||||
#include "compilation.h"
|
||||
#include "intern_pool.h"
|
||||
#include "sema.h"
|
||||
#include "verbose_air.h"
|
||||
#include "verbose_intern_pool.h"
|
||||
#include "zcu.h"
|
||||
#include "zir.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
@@ -44,19 +46,25 @@ static int zig0Run(const char* program, const char* source_dir,
|
||||
fprintf(stderr, "zir: %u instructions, %u extra, %u string bytes\n",
|
||||
zir.inst_len, zir.extra_len, zir.string_bytes_len);
|
||||
|
||||
InternPool ip = ipInit();
|
||||
Compilation comp;
|
||||
comp.config.module_root = module_root;
|
||||
comp.config.target_cpu_arch = "wasm32";
|
||||
comp.config.target_cpu_model = "lime1";
|
||||
comp.config.object_format = "wasm";
|
||||
comp.config.link_mode = "static";
|
||||
comp.config.is_test = false;
|
||||
Zcu* zcu = zcuInit(&comp);
|
||||
Sema sema;
|
||||
semaInit(&sema, &ip, zir);
|
||||
semaInit(&sema, zcu, zir);
|
||||
sema.source_dir = source_dir;
|
||||
sema.module_root = module_root;
|
||||
SemaFuncAirList func_airs = semaAnalyze(&sema);
|
||||
if (verbose_intern_pool)
|
||||
verboseIpPrint(stderr, &ip);
|
||||
verboseIpPrint(stderr, &zcu->ip);
|
||||
if (verbose_air)
|
||||
verboseAirPrint(stderr, &func_airs, &ip);
|
||||
verboseAirPrint(stderr, &func_airs, &zcu->ip);
|
||||
semaDeinit(&sema);
|
||||
semaFuncAirListDeinit(&func_airs);
|
||||
ipDeinit(&ip);
|
||||
zcuDeinit(zcu);
|
||||
zirDeinit(&zir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user