llvm(py): introduce BuildCtx + trace hub; refactor if-merge prepass + PHI wiring into module; unify logs; ctx-enable compare/ret/call/boxcall/externcall/typeop/newbox/safepoint; curated smoke option for if-merge; README updates; keep behavior stable
This commit is contained in:
@ -115,21 +115,27 @@ pub(crate) fn execute_file_with_backend(runner: &NyashRunner, filename: &str) {
|
||||
if std::env::var("NYASH_CLI_VERBOSE").ok().as_deref() == Some("1") {
|
||||
println!("🚀 Nyash VM Backend - Executing file: {} 🚀", filename);
|
||||
}
|
||||
runner.execute_vm_mode(filename);
|
||||
#[cfg(feature = "vm-legacy")]
|
||||
{
|
||||
runner.execute_vm_mode(filename);
|
||||
}
|
||||
#[cfg(not(feature = "vm-legacy"))]
|
||||
{
|
||||
// Legacy VM is disabled; use PyVM harness instead.
|
||||
super::modes::pyvm::execute_pyvm_only(runner, filename);
|
||||
}
|
||||
}
|
||||
"interpreter" => {
|
||||
eprintln!("⚠ interpreter backend is legacy and deprecated. Use 'vm' (PyVM/LLVM) instead.");
|
||||
if std::env::var("NYASH_VM_USE_PY").ok().as_deref() == Some("1") {
|
||||
if std::env::var("NYASH_CLI_VERBOSE").ok().as_deref() == Some("1") {
|
||||
println!("👉 Redirecting to VM backend (PyVM) as requested by NYASH_VM_USE_PY=1");
|
||||
}
|
||||
runner.execute_vm_mode(filename);
|
||||
} else {
|
||||
if std::env::var("NYASH_CLI_VERBOSE").ok().as_deref() == Some("1") {
|
||||
println!("👉 Redirecting to VM backend");
|
||||
}
|
||||
#[cfg(feature = "vm-legacy")]
|
||||
{
|
||||
runner.execute_vm_mode(filename);
|
||||
}
|
||||
#[cfg(not(feature = "vm-legacy"))]
|
||||
{
|
||||
// Legacy VM disabled; route to PyVM-only runner
|
||||
super::modes::pyvm::execute_pyvm_only(runner, filename);
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "cranelift-jit")]
|
||||
"jit-direct" => {
|
||||
|
||||
@ -18,6 +18,10 @@ pub fn emit_mir_json_for_harness(
|
||||
let mut insts = Vec::new();
|
||||
// PHI first(オプション)
|
||||
for inst in &bb.instructions {
|
||||
if let I::Copy { dst, src } = inst {
|
||||
insts.push(json!({"op":"copy","dst": dst.as_u32(), "src": src.as_u32()}));
|
||||
continue;
|
||||
}
|
||||
if let I::Phi { dst, inputs } = inst {
|
||||
let incoming: Vec<_> = inputs
|
||||
.iter()
|
||||
@ -47,6 +51,13 @@ pub fn emit_mir_json_for_harness(
|
||||
// Non-PHI
|
||||
for inst in &bb.instructions {
|
||||
match inst {
|
||||
I::Copy { dst, src } => {
|
||||
insts.push(json!({
|
||||
"op": "copy",
|
||||
"dst": dst.as_u32(),
|
||||
"src": src.as_u32()
|
||||
}));
|
||||
}
|
||||
I::UnaryOp { dst, op, operand } => {
|
||||
let kind = match op {
|
||||
nyash_rust::mir::UnaryOp::Neg => "neg",
|
||||
@ -296,6 +307,13 @@ pub fn emit_mir_json_for_harness_bin(
|
||||
}
|
||||
for inst in &bb.instructions {
|
||||
match inst {
|
||||
I::Copy { dst, src } => {
|
||||
insts.push(json!({
|
||||
"op": "copy",
|
||||
"dst": dst.as_u32(),
|
||||
"src": src.as_u32()
|
||||
}));
|
||||
}
|
||||
I::Const { dst, value } => match value {
|
||||
crate::mir::ConstValue::Integer(i) => {
|
||||
insts.push(json!({"op":"const","dst": dst.as_u32(), "value": {"type": "i64", "value": i}}));
|
||||
|
||||
@ -413,8 +413,17 @@ impl NyashRunner {
|
||||
println!("====================================");
|
||||
println!("Running {} iterations per test...", self.config.iterations);
|
||||
println!();
|
||||
|
||||
self.execute_benchmark_mode();
|
||||
#[cfg(feature = "vm-legacy")]
|
||||
{
|
||||
self.execute_benchmark_mode();
|
||||
}
|
||||
#[cfg(not(feature = "vm-legacy"))]
|
||||
{
|
||||
eprintln!(
|
||||
"❌ Benchmark mode requires VM backend. Rebuild with --features vm-legacy."
|
||||
);
|
||||
std::process::exit(1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -236,3 +236,4 @@ impl NyashRunner {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
#![cfg(feature = "vm-legacy")]
|
||||
|
||||
@ -101,4 +101,4 @@ impl NyashRunner {
|
||||
let _ = runtime; // reserved for future GC/safepoint integration
|
||||
}
|
||||
}
|
||||
|
||||
#![cfg(feature = "interpreter-legacy")]
|
||||
|
||||
@ -1,8 +1,12 @@
|
||||
#[cfg(feature = "vm-legacy")]
|
||||
pub mod bench;
|
||||
#[cfg(feature = "interpreter-legacy")]
|
||||
pub mod interpreter;
|
||||
pub mod llvm;
|
||||
pub mod mir;
|
||||
#[cfg(feature = "vm-legacy")]
|
||||
pub mod vm;
|
||||
pub mod pyvm;
|
||||
|
||||
#[cfg(feature = "cranelift-jit")]
|
||||
pub mod aot;
|
||||
|
||||
102
src/runner/modes/pyvm.rs
Normal file
102
src/runner/modes/pyvm.rs
Normal file
@ -0,0 +1,102 @@
|
||||
use super::super::NyashRunner;
|
||||
use nyash_rust::{mir::MirCompiler, parser::NyashParser};
|
||||
use std::{fs, process};
|
||||
|
||||
/// Execute using PyVM only (no Rust VM runtime). Emits MIR(JSON) and invokes tools/pyvm_runner.py.
|
||||
pub fn execute_pyvm_only(_runner: &NyashRunner, filename: &str) {
|
||||
// Read the file
|
||||
let code = match fs::read_to_string(filename) {
|
||||
Ok(content) => content,
|
||||
Err(e) => {
|
||||
eprintln!("❌ Error reading file {}: {}", filename, e);
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
// Parse to AST
|
||||
let ast = match NyashParser::parse_from_string(&code) {
|
||||
Ok(ast) => ast,
|
||||
Err(e) => {
|
||||
eprintln!("❌ Parse error: {}", e);
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
// Compile to MIR (respect default optimizer setting)
|
||||
let mut mir_compiler = MirCompiler::with_options(true);
|
||||
let mut compile_result = match mir_compiler.compile(ast) {
|
||||
Ok(result) => result,
|
||||
Err(e) => {
|
||||
eprintln!("❌ MIR compilation error: {}", e);
|
||||
process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
// Optional: VM-only escape analysis elision pass retained for parity with VM path
|
||||
if std::env::var("NYASH_VM_ESCAPE_ANALYSIS").ok().as_deref() == Some("1") {
|
||||
let removed = nyash_rust::mir::passes::escape::escape_elide_barriers_vm(&mut compile_result.module);
|
||||
if removed > 0 && std::env::var("NYASH_CLI_VERBOSE").ok().as_deref() == Some("1") {
|
||||
eprintln!("[PyVM] escape_elide_barriers: removed {} barriers", removed);
|
||||
}
|
||||
}
|
||||
|
||||
// Emit MIR JSON for PyVM harness
|
||||
let tmp_dir = std::path::Path::new("tmp");
|
||||
let _ = std::fs::create_dir_all(tmp_dir);
|
||||
let mir_json_path = tmp_dir.join("nyash_pyvm_mir.json");
|
||||
if let Err(e) = crate::runner::mir_json_emit::emit_mir_json_for_harness(
|
||||
&compile_result.module,
|
||||
&mir_json_path,
|
||||
) {
|
||||
eprintln!("❌ PyVM MIR JSON emit error: {}", e);
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
// Pick entry: prefer Main.main or main
|
||||
let entry = if compile_result.module.functions.contains_key("Main.main") {
|
||||
"Main.main"
|
||||
} else if compile_result.module.functions.contains_key("main") {
|
||||
"main"
|
||||
} else {
|
||||
"Main.main"
|
||||
};
|
||||
|
||||
// Locate python3 and run harness
|
||||
let py = which::which("python3").ok();
|
||||
if let Some(py3) = py {
|
||||
let runner = std::path::Path::new("tools/pyvm_runner.py");
|
||||
if !runner.exists() {
|
||||
eprintln!("❌ PyVM runner not found: {}", runner.display());
|
||||
process::exit(1);
|
||||
}
|
||||
if std::env::var("NYASH_CLI_VERBOSE").ok().as_deref() == Some("1") {
|
||||
eprintln!(
|
||||
"[Runner/PyVM] {} (mir={})",
|
||||
filename,
|
||||
mir_json_path.display()
|
||||
);
|
||||
}
|
||||
let status = std::process::Command::new(py3)
|
||||
.args([
|
||||
runner.to_string_lossy().as_ref(),
|
||||
"--in",
|
||||
&mir_json_path.display().to_string(),
|
||||
"--entry",
|
||||
entry,
|
||||
])
|
||||
.status()
|
||||
.map_err(|e| format!("spawn pyvm: {}", e))
|
||||
.unwrap();
|
||||
let code = status.code().unwrap_or(1);
|
||||
if !status.success() {
|
||||
if std::env::var("NYASH_CLI_VERBOSE").ok().as_deref() == Some("1") {
|
||||
eprintln!("❌ PyVM failed (status={})", code);
|
||||
}
|
||||
}
|
||||
process::exit(code);
|
||||
} else {
|
||||
eprintln!("❌ python3 not found in PATH. Install Python 3 to use PyVM.");
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user