Files
hakorune/lang/c-abi/shims/hako_aot.c
nyash-codex 0455307418 refactor(phase-a): remove Cranelift/JIT backend legacy code (~373 lines)
Phase A cleanup - Safe deletions with zero risk:

## Deleted Files (6 files, 373 lines total)
1. Cranelift/JIT Backend (321 lines):
   - src/runner/modes/cranelift.rs (45 lines)
   - src/runner/modes/aot.rs (55 lines)
   - src/runner/jit_direct.rs (152 lines)
   - src/tests/core13_smoke_jit.rs (42 lines)
   - src/tests/core13_smoke_jit_map.rs (27 lines)

2. Legacy MIR Builder (52 lines):
   - src/mir/builder/exprs_legacy.rs
   - Functionality inlined into exprs.rs (control flow constructs)

## Module Reference Cleanup
- src/backend/mod.rs: Removed cranelift feature gate exports
- src/runner/mod.rs: Removed jit_direct module reference
- src/runner/modes/mod.rs: Removed aot module reference
- src/mir/builder.rs: Removed exprs_legacy module

## Impact Analysis
- Build: Success (cargo build --release)
- Tests: All passing
- Risk Level: None (feature already archived, code unused)
- Related: Phase 15 JIT archival (archive/jit-cranelift/)

## BID Copilot Status
- Already removed in previous cleanup
- Not part of this commit

Total Reduction: 373 lines (~0.4% of codebase)
Next: Phase B - Dead code investigation

Related: #phase-21.0-cleanup
Part of: Legacy Code Cleanup Initiative
2025-11-06 22:34:18 +09:00

217 lines
10 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// hako_aot.c — Small standalone AOT CABI
// Notes: duplicates minimal TLS + memory + AOT compile/link from kernel shim,
// so it can be linked independently as libhako_aot.{so|dylib|dll}.
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#if defined(_WIN32)
#include <process.h>
#define GETPID _getpid
#else
#include <unistd.h>
#define GETPID getpid
#endif
struct hako_ctx;
// ---- Diagnostics (threadlocal short message)
#if defined(_MSC_VER)
__declspec(thread) static const char* hako_tls_last_error = "OK";
#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
static _Thread_local const char* hako_tls_last_error = "OK";
#else
static __thread const char* hako_tls_last_error = "OK";
#endif
const char* hako_last_error(struct hako_ctx* ctx) {
(void)ctx; return hako_tls_last_error ? hako_tls_last_error : "OK";
}
void hako_set_last_error(const char* short_msg) {
hako_tls_last_error = short_msg ? short_msg : "OK";
}
// Diagnostics helpers
#include "../include/hako_diag.h"
// ---- Memory (libc)
void* hako_mem_alloc(uint64_t size) {
if (size == 0) size = 1; void* p = malloc((size_t)size);
if (!p) hako_set_last_error("OOM"); return p;
}
void* hako_mem_realloc(void* ptr, uint64_t new_size) {
if (new_size == 0) new_size = 1; void* p = realloc(ptr, (size_t)new_size);
if (!p) hako_set_last_error("OOM"); return p;
}
void hako_mem_free(void* ptr) { if (ptr) free(ptr); }
// ---- Helpers
static int set_err(char** err_out, const char* msg) {
if (err_out) {
if (msg) {
size_t n = strlen(msg); char* p = (char*)hako_mem_alloc((uint64_t)n + 1);
if (p) { memcpy(p, msg, n); p[n] = '\0'; *err_out = p; }
} else { *err_out = NULL; }
}
return -1;
}
static int file_exists(const char* p) {
if (!p) return 0; FILE* f = fopen(p, "rb"); if (!f) return 0; fclose(f); return 1;
}
static const char* tmp_dir_fallback(void) {
const char* t = getenv("TMPDIR"); if (!t||!*t) t = getenv("TMP"); if (!t||!*t) t = getenv("TEMP"); if (!t||!*t) t = "/tmp"; return t;
}
static char* read_first_line(const char* path) {
if (!path) return NULL; FILE* f = fopen(path, "rb"); if (!f) return NULL;
char buf[512]; size_t n=0; int c; while (n<sizeof(buf)-1 && (c=fgetc(f))!=EOF) { if (c=='\n'||c=='\r') break; buf[n++]=(char)c; }
buf[n]='\0'; fclose(f); if (!n) return NULL; char* out=(char*)hako_mem_alloc((uint64_t)n+1); if (!out) return NULL; memcpy(out,buf,n+1); return out;
}
// ---- AOT: compile JSON → object (ny-llvmc)
// ---- Optional FFI (dlopen)
#if !defined(_WIN32)
#include <dlfcn.h>
static void* open_ffi_lib(void) {
const char* lib = getenv("HAKO_AOT_FFI_LIB");
char buf[1024];
if (!lib || !*lib) {
// Try dev default
snprintf(buf, sizeof(buf), "%s", "target/release/libhako_llvmc_ffi.so");
lib = buf;
}
void* h = dlopen(lib, RTLD_NOW);
if (!h && (!getenv("HAKO_AOT_FFI_LIB") || !*getenv("HAKO_AOT_FFI_LIB"))) {
// Try dist-style: lib/libhako_llvmc_ffi.so (if running from dist root)
snprintf(buf, sizeof(buf), "%s", "lib/libhako_llvmc_ffi.so");
h = dlopen(buf, RTLD_NOW);
}
return h;
}
static int try_ffi_compile(const char* json_in, const char* obj_out, char** err_out) {
void* h = open_ffi_lib();
if (!h) { HAKO_FAIL_WITH(err_out, "UNSUPPORTED", "FFI library not found"); }
typedef int (*ffi_compile_fn)(const char*, const char*, char**);
ffi_compile_fn fn = (ffi_compile_fn)dlsym(h, "hako_llvmc_compile_json");
if (!fn) { dlclose(h); HAKO_FAIL_WITH(err_out, "UNSUPPORTED", "FFI symbol missing: hako_llvmc_compile_json"); }
int rc = fn(json_in, obj_out, err_out);
dlclose(h);
return rc;
}
static int try_ffi_link(const char* obj_in, const char* exe_out, const char* extra_ldflags, char** err_out) {
void* h = open_ffi_lib();
if (!h) { HAKO_FAIL_WITH(err_out, "UNSUPPORTED", "FFI library not found"); }
typedef int (*ffi_link_fn)(const char*, const char*, const char*, char**);
ffi_link_fn fn = (ffi_link_fn)dlsym(h, "hako_llvmc_link_obj");
if (!fn) { dlclose(h); HAKO_FAIL_WITH(err_out, "UNSUPPORTED", "FFI symbol missing: hako_llvmc_link_obj"); }
int rc = fn(obj_in, exe_out, extra_ldflags, err_out);
dlclose(h);
return rc;
}
#else
static int try_ffi_compile(const char* json_in, const char* obj_out, char** err_out) {
(void)json_in; (void)obj_out; (void)err_out; hako_set_last_error("UNSUPPORTED"); return set_err(err_out, "FFI unsupported on this platform");
}
static int try_ffi_link(const char* obj_in, const char* exe_out, const char* extra_ldflags, char** err_out) {
(void)obj_in; (void)exe_out; (void)extra_ldflags; (void)err_out; hako_set_last_error("UNSUPPORTED"); return set_err(err_out, "FFI unsupported on this platform");
}
#endif
int hako_aot_compile_json(const char* json_in, const char* obj_out, char** err_out) {
const char* use_ffi = getenv("HAKO_AOT_USE_FFI");
if (use_ffi && (*use_ffi=='1' || strcasecmp(use_ffi, "true")==0 || strcasecmp(use_ffi, "on")==0)) {
return try_ffi_compile(json_in, obj_out, err_out);
}
// Inject opt_level defaults when falling back to CLI (insurance for Python harness)
if (!getenv("HAKO_LLVM_OPT_LEVEL")) {
setenv("HAKO_LLVM_OPT_LEVEL", "0", 1);
}
if (!getenv("NYASH_LLVM_OPT_LEVEL")) {
setenv("NYASH_LLVM_OPT_LEVEL", "0", 1);
}
if (!json_in || !*json_in || !obj_out || !*obj_out) { HAKO_FAIL_WITH(err_out, "VALIDATION", "invalid args"); }
const char* llvmc = getenv("NYASH_NY_LLVM_COMPILER"); if (!llvmc || !*llvmc) { llvmc = "target/release/ny-llvmc"; }
if (!file_exists(llvmc)) { HAKO_FAIL_WITH(err_out, "NOT_FOUND", "ny-llvmc not found (NYASH_NY_LLVM_COMPILER)"); }
char logpath[1024]; snprintf(logpath, sizeof(logpath), "%s/hako_aot_compile_%ld.log", tmp_dir_fallback(), (long)GETPID());
char cmd[4096]; int n = snprintf(cmd, sizeof(cmd), "\"%s\" --in \"%s\" --emit obj --out \"%s\" 2> \"%s\"", llvmc, json_in, obj_out, logpath);
if (n <= 0 || (size_t)n >= sizeof(cmd)) { HAKO_FAIL_WITH(err_out, "VALIDATION", "command too long"); }
if (getenv("HAKO_AOT_DEBUG")) { fprintf(stderr, "[hako_aot] link cmd: %s\n", cmd); }
// Prepend command line to log for easier diagnostics (first line)
{
FILE* lf = fopen(logpath, "wb");
if (lf) { fprintf(lf, "%s\n", cmd); fclose(lf); }
}
int rc = system(cmd);
if (rc != 0) { hako_set_last_error("FAILED"); char* first = read_first_line(logpath); if (first) { set_err(err_out, first); hako_mem_free(first); } else { set_err(err_out, "COMPILE_FAILED"); } remove(logpath); return -1; }
hako_set_last_error(NULL); if (!file_exists(obj_out)) { HAKO_FAIL_WITH(err_out, "FAILED", "object not produced"); }
remove(logpath); return 0;
}
// ---- AOT: link object → exe
static const char* resolve_nyrt_dir(char* buf, size_t buflen) {
const char* hint = getenv("NYASH_EMIT_EXE_NYRT"); if (hint && *hint) { snprintf(buf, buflen, "%s", hint); return buf; }
const char* a = "target/release"; const char* b = "crates/hako_kernel/target/release"; char pa[1024], pb[1024];
snprintf(pa, sizeof(pa), "%s/libhako_kernel.a", a); snprintf(pb, sizeof(pb), "%s/libhako_kernel.a", b);
if (file_exists(pa) || file_exists(pb)) { snprintf(buf, buflen, "%s", file_exists(pa) ? a : b); return buf; }
snprintf(pa, sizeof(pa), "%s/libnyash_kernel.a", a); snprintf(pb, sizeof(pb), "%s/libnyash_kernel.a", b);
if (file_exists(pa) || file_exists(pb)) { snprintf(buf, buflen, "%s", file_exists(pa) ? a : b); return buf; }
return NULL;
}
int hako_aot_link_obj(const char* obj_in, const char* exe_out, const char* extra_ldflags, char** err_out) {
const char* use_ffi = getenv("HAKO_AOT_USE_FFI");
if (use_ffi && (*use_ffi=='1' || strcasecmp(use_ffi, "true")==0 || strcasecmp(use_ffi, "on")==0)) {
return try_ffi_link(obj_in, exe_out, extra_ldflags, err_out);
}
if (!obj_in || !*obj_in || !exe_out || !*exe_out) { HAKO_FAIL_WITH(err_out, "VALIDATION", "invalid args"); }
if (!file_exists(obj_in)) { HAKO_FAIL_WITH(err_out, "VALIDATION", "object not found"); }
char dirbuf[1024]; const char* dir = resolve_nyrt_dir(dirbuf, sizeof(dirbuf)); if (!dir) { HAKO_FAIL_WITH(err_out, "NOT_FOUND", "libhako_kernel.a not found (NYASH_EMIT_EXE_NYRT)"); }
char lib_a[1024]; snprintf(lib_a, sizeof(lib_a), "%s/libhako_kernel.a", dir); char lib_legacy[1024]; snprintf(lib_legacy, sizeof(lib_legacy), "%s/libnyash_kernel.a", dir);
const char* lib = file_exists(lib_a) ? lib_a : lib_legacy; const char* linker = getenv("CC"); if (!linker || !*linker) linker = "cc";
const char* os_libs = "";
#if defined(__linux__)
os_libs = "-ldl -lpthread -lm";
#elif defined(__APPLE__)
os_libs = "";
#elif defined(_WIN32) || defined(__MINGW32__) || defined(__MINGW64__)
os_libs = "-lws2_32 -lbcrypt";
#endif
char logpath[1024]; snprintf(logpath, sizeof(logpath), "%s/hako_aot_link_%ld.log", tmp_dir_fallback(), (long)GETPID());
// Prefer static core, but also link optional shim shared lib when available (provides hako_console_*)
char shim_flag[1024] = "";
#if defined(__linux__) || defined(__APPLE__)
char shim_so[1024];
#if defined(__APPLE__)
snprintf(shim_so, sizeof(shim_so), "%s/libhako_kernel_shim.dylib", dir);
#else
snprintf(shim_so, sizeof(shim_so), "%s/libhako_kernel_shim.so", dir);
#endif
if (file_exists(shim_so)) {
// Add -L and -Wl,-rpath to locate the shim at runtime, and -l link flag
snprintf(shim_flag, sizeof(shim_flag), " -L\"%s\" -Wl,-rpath,\"%s\" -lhako_kernel_shim", dir, dir);
}
#endif
const char* pie_avoid = "";
#if defined(__linux__)
pie_avoid = " -no-pie";
#endif
char cmd[8192]; int n = snprintf(cmd, sizeof(cmd), "\"%s\"%s -o \"%s\" \"%s\" -Wl,--whole-archive \"%s\" -Wl,--no-whole-archive%s %s 2> \"%s\"", linker, pie_avoid, exe_out, obj_in, lib, shim_flag, os_libs, logpath);
if (n <= 0) { HAKO_FAIL_WITH(err_out, "VALIDATION", "command too long"); }
if (extra_ldflags && *extra_ldflags) { size_t cur=strlen(cmd); size_t rem=sizeof(cmd)-cur-1; if (rem>0) { strncat(cmd, " ", rem); cur++; rem=sizeof(cmd)-cur-1; } if (rem>0) { strncat(cmd, extra_ldflags, rem); } }
// ENV override: HAKO_AOT_LDFLAGS appended at the end (dev convenience)
{
const char* env_ld = getenv("HAKO_AOT_LDFLAGS");
if (env_ld && *env_ld) {
size_t cur=strlen(cmd); size_t rem=sizeof(cmd)-cur-1; if (rem>0) { strncat(cmd, " ", rem); cur++; rem=sizeof(cmd)-cur-1; }
if (rem>0) { strncat(cmd, env_ld, rem); }
}
}
int rc = system(cmd);
if (rc != 0) { hako_set_last_error("FAILED"); char* first=read_first_line(logpath); if (first){ set_err(err_out, first); hako_mem_free(first);} else { set_err(err_out, "LINK_FAILED"); } remove(logpath); return -1; }
hako_set_last_error(NULL); remove(logpath); return 0;
}