Files
zig/stage0/zig0.c
Motiejus Jakštys 98162fef92 stage0: increase IP_MAX_NAVS and fix zig0 module_root for relative paths
Increase IP_MAX_NAVS from 4096 to 16384 to support loading larger
module trees (e.g. std). Fix zig0.c module_root derivation to handle
relative paths like "lib/compiler_rt" which lack a leading "/lib/".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 23:23:23 +00:00

144 lines
4.2 KiB
C

#include "ast.h"
#include "astgen.h"
#include "intern_pool.h"
#include "sema.h"
#include "verbose_air.h"
#include "verbose_intern_pool.h"
#include "zir.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// API:
// - code = 0: program successfully terminated.
// - code = 1: panicked, panic message in msg. Caller should free msg.
// - code = 2: interpreter error, error in msg. Caller should free msg.
static int zig0Run(const char* program, const char* source_dir,
const char* module_root, bool verbose_air, bool verbose_intern_pool,
char** msg) {
uint32_t len = (uint32_t)strlen(program);
Ast ast = astParse(program, len);
if (ast.has_error) {
*msg = ast.err_msg;
ast.err_msg = NULL;
astDeinit(&ast);
return 2;
}
fprintf(stderr, "tokens: %u, nodes: %u, first token: %s\n", ast.tokens.len,
ast.nodes.len, tokenizerGetTagString(ast.tokens.tags[0]));
Zir zir = astGen(&ast);
astDeinit(&ast);
if (zir.has_compile_errors) {
const char err[] = "astgen failed";
*msg = malloc(sizeof(err));
memcpy(*msg, err, sizeof(err));
zirDeinit(&zir);
return 2;
}
fprintf(stderr, "zir: %u instructions, %u extra, %u string bytes\n",
zir.inst_len, zir.extra_len, zir.string_bytes_len);
InternPool ip = ipInit();
Sema sema;
semaInit(&sema, &ip, zir);
sema.source_dir = source_dir;
sema.module_root = module_root;
SemaFuncAirList func_airs = semaAnalyze(&sema);
if (verbose_intern_pool)
verboseIpPrint(stderr, &ip);
if (verbose_air)
verboseAirPrint(stderr, &func_airs, &ip);
semaDeinit(&sema);
semaFuncAirListDeinit(&func_airs);
ipDeinit(&ip);
zirDeinit(&zir);
return 0;
}
// API: run and:
// code = 3: abnormal error, expect something in stderr.
int zig0RunFile(const char* fname, bool verbose_air, bool verbose_intern_pool,
char** msg) {
FILE* f = fopen(fname, "r");
if (f == NULL) {
perror("fopen");
return 3;
}
fseek(f, 0, SEEK_END);
long fsizel = ftell(f);
if (fsizel == -1) {
perror("ftell");
fclose(f);
return 3;
}
unsigned long fsize = (unsigned long)fsizel;
fseek(f, 0, SEEK_SET);
char* program = malloc(fsize + 1);
if (program == NULL) {
perror("malloc");
fclose(f);
return 3;
}
size_t bytes_read = fread(program, 1, fsize, f);
if (bytes_read < fsize) {
if (ferror(f)) {
perror("fread");
} else {
fprintf(stderr, "Unexpected end of file\n");
}
free(program);
fclose(f);
return 3;
}
fclose(f);
program[fsize] = 0;
// Compute source_dir (dirname of fname) for import resolution.
char source_dir[1024] = { 0 };
{
const char* last_slash = strrchr(fname, '/');
if (last_slash) {
size_t len = (size_t)(last_slash - fname);
if (len >= sizeof(source_dir))
len = sizeof(source_dir) - 1;
memcpy(source_dir, fname, len);
source_dir[len] = '\0';
}
}
// Derive module_root: walk up from source_dir to find the repo root.
// For paths like .../lib/compiler_rt/neghf2.zig, module_root is the
// directory containing "lib/". Heuristic: strip /lib/... suffix.
// Also handles relative paths like "lib/compiler_rt" (no leading /).
char module_root[1024] = { 0 };
{
const char* lib_pos = strstr(source_dir, "/lib/");
if (lib_pos) {
size_t len = (size_t)(lib_pos - source_dir);
if (len >= sizeof(module_root))
len = sizeof(module_root) - 1;
memcpy(module_root, source_dir, len);
module_root[len] = '\0';
} else if (strncmp(source_dir, "lib/", 4) == 0
|| strncmp(source_dir, "lib", 4) == 0) {
// Relative path starting with "lib/" — module_root is "."
module_root[0] = '.';
module_root[1] = '\0';
}
}
int code
= zig0Run(program, source_dir, module_root[0] ? module_root : NULL,
verbose_air, verbose_intern_pool, msg);
free(program);
return code;
}