Phase 21.7 normalization: optimization pre-work + bench harness expansion
- Add opt-in optimizations (defaults OFF) - Ret purity verifier: NYASH_VERIFY_RET_PURITY=1 - strlen FAST enhancement for const handles - FAST_INT gate for same-BB SSA optimization - length cache for string literals in llvmlite - Expand bench harness (tools/perf/microbench.sh) - Add branch/call/stringchain/arraymap/chip8/kilo cases - Auto-calculate ratio vs C reference - Document in benchmarks/README.md - Compiler health improvements - Unify PHI insertion to insert_phi_at_head() - Add NYASH_LLVM_SKIP_BUILD=1 for build reuse - Runtime & safety enhancements - Clarify Rust/Hako ownership boundaries - Strengthen receiver localization (LocalSSA/pin/after-PHIs) - Stop excessive PluginInvoke→BoxCall rewrites - Update CURRENT_TASK.md, docs, and canaries 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
115
src/backend/mir_interpreter/handlers/calls/global.rs
Normal file
115
src/backend/mir_interpreter/handlers/calls/global.rs
Normal file
@ -0,0 +1,115 @@
|
||||
use super::*;
|
||||
|
||||
impl MirInterpreter {
|
||||
pub(super) fn execute_global_function(
|
||||
&mut self,
|
||||
func_name: &str,
|
||||
args: &[ValueId],
|
||||
) -> Result<VMValue, VMError> {
|
||||
// Normalize arity suffix for extern-like dispatch, but keep original name
|
||||
// for module-local function table lookup (functions may carry arity suffix).
|
||||
let base = super::super::utils::normalize_arity_suffix(func_name);
|
||||
// Module-local/global function: execute by function table if present (use original name)
|
||||
if let Some(func) = self.functions.get(func_name).cloned() {
|
||||
let mut argv: Vec<VMValue> = Vec::with_capacity(args.len());
|
||||
for a in args { argv.push(self.reg_load(*a)?); }
|
||||
return self.exec_function_inner(&func, Some(&argv));
|
||||
}
|
||||
|
||||
match base {
|
||||
// Console-like globals
|
||||
"print" | "nyash.builtin.print" => {
|
||||
// Reuse extern handler for consistency with other console names
|
||||
return self.execute_extern_function("print", args);
|
||||
}
|
||||
"error" => {
|
||||
if let Some(arg_id) = args.get(0) {
|
||||
let val = self.reg_load(*arg_id)?;
|
||||
eprintln!("Error: {}", val.to_string());
|
||||
}
|
||||
return Ok(VMValue::Void);
|
||||
}
|
||||
"panic" => {
|
||||
return self.execute_extern_function("panic", args);
|
||||
}
|
||||
"exit" => {
|
||||
return self.execute_extern_function("exit", args);
|
||||
}
|
||||
"env.get" => {
|
||||
// Route env.get global to extern handler
|
||||
return self.execute_extern_function("env.get", args);
|
||||
}
|
||||
"hostbridge.extern_invoke" => {
|
||||
// SSOT: delegate to extern dispatcher (provider)
|
||||
return self.execute_extern_function("hostbridge.extern_invoke", args);
|
||||
}
|
||||
// LLVM harness providers (direct)
|
||||
"env.mirbuilder.emit" | "env.mirbuilder.emit/1" => {
|
||||
if let Some(a0) = args.get(0) {
|
||||
let s = self.reg_load(*a0)?.to_string();
|
||||
match crate::host_providers::mir_builder::program_json_to_mir_json(&s) {
|
||||
Ok(out) => Ok(VMValue::String(out)),
|
||||
Err(e) => Err(self.err_with_context("env.mirbuilder.emit", &e.to_string())),
|
||||
}
|
||||
} else {
|
||||
Err(self.err_invalid("env.mirbuilder.emit expects 1 arg"))
|
||||
}
|
||||
}
|
||||
"env.codegen.emit_object" | "env.codegen.emit_object/1" => {
|
||||
if let Some(a0) = args.get(0) {
|
||||
let s = self.reg_load(*a0)?.to_string();
|
||||
let opts = crate::host_providers::llvm_codegen::Opts {
|
||||
out: None,
|
||||
nyrt: std::env::var("NYASH_EMIT_EXE_NYRT").ok().map(std::path::PathBuf::from),
|
||||
opt_level: std::env::var("HAKO_LLVM_OPT_LEVEL").ok().or(Some("0".to_string())),
|
||||
timeout_ms: None,
|
||||
};
|
||||
match crate::host_providers::llvm_codegen::mir_json_to_object(&s, opts) {
|
||||
Ok(p) => Ok(VMValue::String(p.to_string_lossy().into_owned())),
|
||||
Err(e) => Err(self.err_with_context("env.codegen.emit_object", &e.to_string())),
|
||||
}
|
||||
} else {
|
||||
Err(self.err_invalid("env.codegen.emit_object expects 1 arg"))
|
||||
}
|
||||
}
|
||||
"env.codegen.link_object" | "env.codegen.link_object/3" => {
|
||||
// C-API route only; args[2] is expected to be an ArrayBox [obj_path, exe_out?]
|
||||
if std::env::var("NYASH_LLVM_USE_CAPI").ok().as_deref() != Some("1") ||
|
||||
std::env::var("HAKO_V1_EXTERN_PROVIDER_C_ABI").ok().as_deref() != Some("1") {
|
||||
return Err(self.err_invalid("env.codegen.link_object: C-API route disabled"));
|
||||
}
|
||||
if args.len() < 3 { return Err(self.err_arg_count("env.codegen.link_object", 3, args.len())); }
|
||||
let v = self.reg_load(args[2])?;
|
||||
let (obj_path, exe_out) = match v {
|
||||
VMValue::BoxRef(b) => {
|
||||
if let Some(ab) = b.as_any().downcast_ref::<crate::boxes::array::ArrayBox>() {
|
||||
let idx0: Box<dyn crate::box_trait::NyashBox> = Box::new(crate::box_trait::IntegerBox::new(0));
|
||||
let elem0 = ab.get(idx0).to_string_box().value;
|
||||
let mut exe: Option<String> = None;
|
||||
let idx1: Box<dyn crate::box_trait::NyashBox> = Box::new(crate::box_trait::IntegerBox::new(1));
|
||||
let e1 = ab.get(idx1).to_string_box().value;
|
||||
if !e1.is_empty() { exe = Some(e1); }
|
||||
(elem0, exe)
|
||||
} else { (b.to_string_box().value, None) }
|
||||
}
|
||||
_ => (v.to_string(), None),
|
||||
};
|
||||
let extra = std::env::var("HAKO_AOT_LDFLAGS").ok();
|
||||
let obj = std::path::PathBuf::from(obj_path);
|
||||
let exe = exe_out.map(std::path::PathBuf::from).unwrap_or_else(|| std::env::temp_dir().join("hako_link_out.exe"));
|
||||
match crate::host_providers::llvm_codegen::link_object_capi(&obj, &exe, extra.as_deref()) {
|
||||
Ok(()) => Ok(VMValue::String(exe.to_string_lossy().into_owned())),
|
||||
Err(e) => Err(self.err_with_context("env.codegen.link_object", &e.to_string()))
|
||||
}
|
||||
}
|
||||
"nyash.builtin.error" => {
|
||||
if let Some(arg_id) = args.get(0) {
|
||||
let val = self.reg_load(*arg_id)?;
|
||||
eprintln!("Error: {}", val.to_string());
|
||||
}
|
||||
Ok(VMValue::Void)
|
||||
}
|
||||
_ => Err(self.err_with_context("global function", &format!("Unknown: {}", func_name))),
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user