2025-08-26 04:34:14 +09:00
|
|
|
|
use super::super::NyashRunner;
|
2025-09-01 23:44:34 +09:00
|
|
|
|
use nyash_rust::mir::passes::method_id_inject::inject_method_ids;
|
2025-09-17 07:43:07 +09:00
|
|
|
|
use nyash_rust::{
|
|
|
|
|
|
mir::{MirCompiler, MirInstruction},
|
|
|
|
|
|
parser::NyashParser,
|
|
|
|
|
|
};
|
2025-08-26 04:34:14 +09:00
|
|
|
|
use std::{fs, process};
|
|
|
|
|
|
|
|
|
|
|
|
impl NyashRunner {
|
|
|
|
|
|
/// Execute LLVM mode (split)
|
|
|
|
|
|
pub(crate) fn execute_llvm_mode(&self, filename: &str) {
|
2025-09-10 20:56:14 +09:00
|
|
|
|
// Initialize plugin host so method_id injection can resolve plugin calls
|
|
|
|
|
|
crate::runner_plugin_init::init_bid_plugins();
|
|
|
|
|
|
|
2025-11-08 00:46:34 +09:00
|
|
|
|
// Friendly plugin guard (non‑strict): unify diagnostics across modes
|
|
|
|
|
|
crate::runner::modes::common_util::plugin_guard::check_and_report(
|
|
|
|
|
|
false,
|
|
|
|
|
|
crate::config::env::env_bool("NYASH_JSON_ONLY"),
|
|
|
|
|
|
"llvm",
|
|
|
|
|
|
);
|
|
|
|
|
|
|
2025-08-26 04:34:14 +09:00
|
|
|
|
// Read the file
|
|
|
|
|
|
let code = match fs::read_to_string(filename) {
|
|
|
|
|
|
Ok(content) => content,
|
2025-09-17 07:43:07 +09:00
|
|
|
|
Err(e) => {
|
|
|
|
|
|
eprintln!("❌ Error reading file {}: {}", filename, e);
|
|
|
|
|
|
process::exit(1);
|
|
|
|
|
|
}
|
2025-08-26 04:34:14 +09:00
|
|
|
|
};
|
|
|
|
|
|
|
2025-09-26 14:34:42 +09:00
|
|
|
|
// Using handling (AST prelude merge like common/vm paths)
|
|
|
|
|
|
let use_ast = crate::config::env::using_ast_enabled();
|
|
|
|
|
|
let mut code_ref: &str = &code;
|
|
|
|
|
|
let cleaned_code_owned;
|
|
|
|
|
|
let mut prelude_asts: Vec<nyash_rust::ast::ASTNode> = Vec::new();
|
|
|
|
|
|
if crate::config::env::enable_using() {
|
|
|
|
|
|
match crate::runner::modes::common_util::resolve::resolve_prelude_paths_profiled(
|
|
|
|
|
|
self, &code, filename,
|
|
|
|
|
|
) {
|
|
|
|
|
|
Ok((clean, paths)) => {
|
|
|
|
|
|
cleaned_code_owned = clean;
|
|
|
|
|
|
code_ref = &cleaned_code_owned;
|
|
|
|
|
|
if !paths.is_empty() && !use_ast {
|
|
|
|
|
|
eprintln!("❌ using: AST prelude merge is disabled in this profile. Enable NYASH_USING_AST=1 or remove 'using' lines.");
|
|
|
|
|
|
std::process::exit(1);
|
|
|
|
|
|
}
|
2025-09-28 01:33:58 +09:00
|
|
|
|
if use_ast && !paths.is_empty() {
|
2025-11-21 06:25:17 +09:00
|
|
|
|
match crate::runner::modes::common_util::resolve::parse_preludes_to_asts(
|
|
|
|
|
|
self, &paths,
|
|
|
|
|
|
) {
|
2025-09-28 01:33:58 +09:00
|
|
|
|
Ok(v) => prelude_asts = v,
|
2025-11-21 06:25:17 +09:00
|
|
|
|
Err(e) => {
|
|
|
|
|
|
eprintln!("❌ {}", e);
|
|
|
|
|
|
std::process::exit(1);
|
|
|
|
|
|
}
|
2025-09-26 14:34:42 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
Err(e) => {
|
|
|
|
|
|
eprintln!("❌ {}", e);
|
|
|
|
|
|
process::exit(1);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// Pre-expand '@name[:T] = expr' sugar at line-head (same as common path)
|
2025-11-21 06:25:17 +09:00
|
|
|
|
let preexpanded_owned =
|
|
|
|
|
|
crate::runner::modes::common_util::resolve::preexpand_at_local(code_ref);
|
2025-09-26 14:34:42 +09:00
|
|
|
|
code_ref = &preexpanded_owned;
|
|
|
|
|
|
|
|
|
|
|
|
// Parse to AST (main)
|
|
|
|
|
|
let main_ast = match NyashParser::parse_from_string(code_ref) {
|
2025-08-26 04:34:14 +09:00
|
|
|
|
Ok(ast) => ast,
|
2025-09-17 07:43:07 +09:00
|
|
|
|
Err(e) => {
|
2025-11-21 06:25:17 +09:00
|
|
|
|
crate::runner::modes::common_util::diag::print_parse_error_with_context(
|
2025-11-24 14:17:02 +09:00
|
|
|
|
filename, code_ref, &e,
|
2025-11-21 06:25:17 +09:00
|
|
|
|
);
|
2025-11-14 13:36:20 +09:00
|
|
|
|
// Enhanced context: list merged prelude files if any (from text-merge path)
|
2025-11-21 06:25:17 +09:00
|
|
|
|
let preludes =
|
|
|
|
|
|
crate::runner::modes::common_util::resolve::clone_last_merged_preludes();
|
2025-11-14 13:36:20 +09:00
|
|
|
|
if !preludes.is_empty() {
|
|
|
|
|
|
eprintln!("[parse/context] merged prelude files ({}):", preludes.len());
|
|
|
|
|
|
let show = std::cmp::min(16, preludes.len());
|
|
|
|
|
|
for p in preludes.iter().take(show) {
|
|
|
|
|
|
eprintln!(" - {}", p);
|
|
|
|
|
|
}
|
|
|
|
|
|
if preludes.len() > show {
|
|
|
|
|
|
eprintln!(" ... ({} more)", preludes.len() - show);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-09-17 07:43:07 +09:00
|
|
|
|
process::exit(1);
|
|
|
|
|
|
}
|
2025-08-26 04:34:14 +09:00
|
|
|
|
};
|
2025-09-26 14:34:42 +09:00
|
|
|
|
// Merge preludes + main when enabled
|
|
|
|
|
|
let ast = if use_ast && !prelude_asts.is_empty() {
|
2025-11-21 06:25:17 +09:00
|
|
|
|
crate::runner::modes::common_util::resolve::merge_prelude_asts_with_main(
|
|
|
|
|
|
prelude_asts,
|
|
|
|
|
|
&main_ast,
|
|
|
|
|
|
)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
main_ast
|
|
|
|
|
|
};
|
2025-09-26 14:34:42 +09:00
|
|
|
|
// Macro expansion (env-gated) after merge
|
2025-09-19 22:27:59 +09:00
|
|
|
|
let ast = crate::r#macro::maybe_expand_and_dump(&ast, false);
|
2025-09-20 08:39:40 +09:00
|
|
|
|
let ast = crate::runner::modes::macro_child::normalize_core_pass(&ast);
|
2025-08-26 04:34:14 +09:00
|
|
|
|
|
|
|
|
|
|
// Compile to MIR
|
|
|
|
|
|
let mut mir_compiler = MirCompiler::new();
|
2025-11-24 14:17:02 +09:00
|
|
|
|
let compile_result = match crate::runner::modes::common_util::source_hint::compile_with_source_hint(
|
|
|
|
|
|
&mut mir_compiler,
|
|
|
|
|
|
ast,
|
|
|
|
|
|
Some(filename),
|
|
|
|
|
|
) {
|
2025-08-26 04:34:14 +09:00
|
|
|
|
Ok(result) => result,
|
2025-09-17 07:43:07 +09:00
|
|
|
|
Err(e) => {
|
|
|
|
|
|
eprintln!("❌ MIR compilation error: {}", e);
|
|
|
|
|
|
process::exit(1);
|
|
|
|
|
|
}
|
2025-08-26 04:34:14 +09:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
println!("📊 MIR Module compiled successfully!");
|
|
|
|
|
|
println!("📊 Functions: {}", compile_result.module.functions.len());
|
|
|
|
|
|
|
2025-09-01 23:44:34 +09:00
|
|
|
|
// Inject method_id for BoxCall/PluginInvoke where resolvable (by-id path)
|
|
|
|
|
|
#[allow(unused_mut)]
|
|
|
|
|
|
let mut module = compile_result.module.clone();
|
|
|
|
|
|
let injected = inject_method_ids(&mut module);
|
2025-11-21 06:25:17 +09:00
|
|
|
|
if injected > 0 {
|
|
|
|
|
|
crate::cli_v!("[LLVM] method_id injected: {} places", injected);
|
|
|
|
|
|
}
|
2025-09-01 23:44:34 +09:00
|
|
|
|
|
2025-11-27 02:58:38 +09:00
|
|
|
|
// Phase 32 L-4.3a: JoinIR LLVM experiment hook
|
|
|
|
|
|
// When NYASH_JOINIR_EXPERIMENT=1 and NYASH_JOINIR_LLVM_EXPERIMENT=1,
|
|
|
|
|
|
// try to lower MIR → JoinIR → MIR' for Main.skip/1 to fix PHI issues.
|
|
|
|
|
|
// JoinIR-converted functions are merged back into the original module.
|
|
|
|
|
|
#[cfg(feature = "llvm-harness")]
|
|
|
|
|
|
let module = if crate::config::env::joinir_experiment_enabled()
|
|
|
|
|
|
&& crate::config::env::joinir_llvm_experiment_enabled()
|
|
|
|
|
|
&& crate::config::env::llvm_use_harness()
|
|
|
|
|
|
{
|
|
|
|
|
|
use nyash_rust::mir::join_ir::lower_skip_ws_to_joinir;
|
|
|
|
|
|
use nyash_rust::mir::join_ir_vm_bridge::convert_joinir_to_mir;
|
|
|
|
|
|
|
|
|
|
|
|
eprintln!("[joinir/llvm] Attempting JoinIR path for LLVM execution");
|
|
|
|
|
|
|
|
|
|
|
|
// Try to lower Main.skip/1 to JoinIR
|
|
|
|
|
|
if module.functions.contains_key("Main.skip/1") {
|
|
|
|
|
|
match lower_skip_ws_to_joinir(&module) {
|
|
|
|
|
|
Some(join_module) => {
|
|
|
|
|
|
eprintln!(
|
|
|
|
|
|
"[joinir/llvm] ✅ Lowered to JoinIR ({} functions)",
|
|
|
|
|
|
join_module.functions.len()
|
|
|
|
|
|
);
|
|
|
|
|
|
// Convert JoinIR back to MIR' (with normalized PHI)
|
|
|
|
|
|
match convert_joinir_to_mir(&join_module) {
|
|
|
|
|
|
Ok(mir_from_joinir) => {
|
|
|
|
|
|
eprintln!(
|
|
|
|
|
|
"[joinir/llvm] ✅ Converted to MIR' ({} functions)",
|
|
|
|
|
|
mir_from_joinir.functions.len()
|
|
|
|
|
|
);
|
|
|
|
|
|
// Merge JoinIR functions into original module
|
|
|
|
|
|
// Strategy: Remove Main.skip/1 (PHI-problematic) and rename join_func_0 to Main.skip/1
|
|
|
|
|
|
let mut merged = module.clone();
|
|
|
|
|
|
|
|
|
|
|
|
// Remove the original PHI-problematic Main.skip/1
|
|
|
|
|
|
if merged.functions.remove("Main.skip/1").is_some() {
|
|
|
|
|
|
eprintln!("[joinir/llvm] Removed original Main.skip/1 (PHI-problematic)");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for (name, func) in mir_from_joinir.functions {
|
|
|
|
|
|
// Rename join_func_0 → Main.skip/1 to maintain call compatibility
|
|
|
|
|
|
let target_name = if name == "join_func_0" {
|
|
|
|
|
|
eprintln!("[joinir/llvm] Renaming {} → Main.skip/1", name);
|
|
|
|
|
|
"Main.skip/1".to_string()
|
|
|
|
|
|
} else {
|
|
|
|
|
|
eprintln!("[joinir/llvm] Adding JoinIR function: {}", name);
|
|
|
|
|
|
name
|
|
|
|
|
|
};
|
|
|
|
|
|
merged.functions.insert(target_name, func);
|
|
|
|
|
|
}
|
|
|
|
|
|
eprintln!(
|
|
|
|
|
|
"[joinir/llvm] ✅ Merged module ({} functions)",
|
|
|
|
|
|
merged.functions.len()
|
|
|
|
|
|
);
|
|
|
|
|
|
merged
|
|
|
|
|
|
}
|
|
|
|
|
|
Err(e) => {
|
|
|
|
|
|
eprintln!("[joinir/llvm] ❌ JoinIR→MIR conversion failed: {:?}", e);
|
|
|
|
|
|
eprintln!("[joinir/llvm] Falling back to original MIR");
|
|
|
|
|
|
module
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
None => {
|
|
|
|
|
|
eprintln!("[joinir/llvm] ❌ JoinIR lowering returned None");
|
|
|
|
|
|
eprintln!("[joinir/llvm] Falling back to original MIR");
|
|
|
|
|
|
module
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
eprintln!("[joinir/llvm] Main.skip/1 not found, using original MIR");
|
|
|
|
|
|
module
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
module
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2025-09-26 14:34:42 +09:00
|
|
|
|
// Dev/Test helper: allow executing via PyVM harness when requested
|
|
|
|
|
|
if std::env::var("SMOKES_USE_PYVM").ok().as_deref() == Some("1") {
|
|
|
|
|
|
match super::common_util::pyvm::run_pyvm_harness_lib(&module, "llvm-ast") {
|
2025-11-21 06:25:17 +09:00
|
|
|
|
Ok(code) => {
|
|
|
|
|
|
std::process::exit(code);
|
|
|
|
|
|
}
|
|
|
|
|
|
Err(e) => {
|
|
|
|
|
|
eprintln!("❌ PyVM harness error: {}", e);
|
|
|
|
|
|
std::process::exit(1);
|
|
|
|
|
|
}
|
2025-09-26 14:34:42 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-01 23:44:34 +09:00
|
|
|
|
// If explicit object path is requested, emit object only
|
2025-09-16 03:54:44 +09:00
|
|
|
|
if let Ok(_out_path) = std::env::var("NYASH_LLVM_OBJ_OUT") {
|
2025-09-14 00:44:28 +09:00
|
|
|
|
#[cfg(feature = "llvm-harness")]
|
2025-09-01 23:44:34 +09:00
|
|
|
|
{
|
2025-09-13 15:37:58 +09:00
|
|
|
|
// Harness path (optional): if NYASH_LLVM_USE_HARNESS=1, try Python/llvmlite first.
|
2025-09-19 02:07:38 +09:00
|
|
|
|
if crate::config::env::llvm_use_harness() {
|
2025-11-21 06:25:17 +09:00
|
|
|
|
if let Err(e) = crate::runner::modes::common_util::exec::llvmlite_emit_object(
|
|
|
|
|
|
&module, &_out_path, 20_000,
|
|
|
|
|
|
) {
|
2025-09-19 02:07:38 +09:00
|
|
|
|
eprintln!("❌ {}", e);
|
|
|
|
|
|
process::exit(1);
|
2025-09-13 15:37:58 +09:00
|
|
|
|
}
|
2025-09-19 02:07:38 +09:00
|
|
|
|
return;
|
2025-09-01 23:44:34 +09:00
|
|
|
|
}
|
|
|
|
|
|
// Verify object presence and size (>0)
|
2025-09-16 03:54:44 +09:00
|
|
|
|
match std::fs::metadata(&_out_path) {
|
2025-09-01 23:44:34 +09:00
|
|
|
|
Ok(meta) => {
|
|
|
|
|
|
if meta.len() == 0 {
|
2025-09-16 03:54:44 +09:00
|
|
|
|
eprintln!("❌ harness object is empty: {}", _out_path);
|
2025-09-01 23:44:34 +09:00
|
|
|
|
process::exit(1);
|
|
|
|
|
|
}
|
|
|
|
|
|
if std::env::var("NYASH_CLI_VERBOSE").ok().as_deref() == Some("1") {
|
2025-09-17 07:43:07 +09:00
|
|
|
|
eprintln!(
|
|
|
|
|
|
"[LLVM] object emitted: {} ({} bytes)",
|
|
|
|
|
|
_out_path,
|
|
|
|
|
|
meta.len()
|
|
|
|
|
|
);
|
2025-09-01 23:44:34 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
Err(e) => {
|
2025-09-17 07:43:07 +09:00
|
|
|
|
eprintln!(
|
|
|
|
|
|
"❌ harness output not found after emit: {} ({})",
|
|
|
|
|
|
_out_path, e
|
|
|
|
|
|
);
|
2025-09-14 00:44:28 +09:00
|
|
|
|
process::exit(1);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
#[cfg(all(not(feature = "llvm-harness"), feature = "llvm-inkwell-legacy"))]
|
|
|
|
|
|
{
|
|
|
|
|
|
use nyash_rust::backend::llvm_compile_to_object;
|
|
|
|
|
|
// Ensure parent directory exists for the object file
|
2025-09-16 03:54:44 +09:00
|
|
|
|
if let Some(parent) = std::path::Path::new(&_out_path).parent() {
|
2025-09-14 00:44:28 +09:00
|
|
|
|
let _ = std::fs::create_dir_all(parent);
|
|
|
|
|
|
}
|
2025-09-19 02:07:38 +09:00
|
|
|
|
crate::cli_v!(
|
|
|
|
|
|
"[Runner/LLVM] emitting object to {} (cwd={})",
|
|
|
|
|
|
_out_path,
|
|
|
|
|
|
std::env::current_dir()
|
|
|
|
|
|
.map(|p| p.display().to_string())
|
|
|
|
|
|
.unwrap_or_default()
|
|
|
|
|
|
);
|
2025-09-16 03:54:44 +09:00
|
|
|
|
if let Err(e) = llvm_compile_to_object(&module, &_out_path) {
|
2025-09-14 00:44:28 +09:00
|
|
|
|
eprintln!("❌ LLVM object emit error: {}", e);
|
|
|
|
|
|
process::exit(1);
|
|
|
|
|
|
}
|
2025-09-16 03:54:44 +09:00
|
|
|
|
match std::fs::metadata(&_out_path) {
|
2025-09-14 00:44:28 +09:00
|
|
|
|
Ok(meta) if meta.len() > 0 => {
|
2025-09-19 02:07:38 +09:00
|
|
|
|
crate::cli_v!(
|
|
|
|
|
|
"[LLVM] object emitted: {} ({} bytes)",
|
|
|
|
|
|
_out_path,
|
|
|
|
|
|
meta.len()
|
|
|
|
|
|
);
|
2025-09-01 23:44:34 +09:00
|
|
|
|
}
|
2025-09-17 07:43:07 +09:00
|
|
|
|
_ => {
|
|
|
|
|
|
eprintln!("❌ LLVM object not found or empty: {}", _out_path);
|
|
|
|
|
|
process::exit(1);
|
|
|
|
|
|
}
|
2025-09-01 23:44:34 +09:00
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2025-09-14 00:44:28 +09:00
|
|
|
|
#[cfg(all(not(feature = "llvm-harness"), not(feature = "llvm-inkwell-legacy")))]
|
2025-09-01 23:44:34 +09:00
|
|
|
|
{
|
|
|
|
|
|
eprintln!("❌ LLVM backend not available (object emit).");
|
|
|
|
|
|
process::exit(1);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-09-19 02:07:38 +09:00
|
|
|
|
// Execute via LLVM backend (harness preferred)
|
|
|
|
|
|
#[cfg(feature = "llvm-harness")]
|
|
|
|
|
|
{
|
|
|
|
|
|
if crate::config::env::llvm_use_harness() {
|
|
|
|
|
|
// Prefer producing a native executable via ny-llvmc, then execute it
|
|
|
|
|
|
let exe_out = "tmp/nyash_llvm_run";
|
|
|
|
|
|
let libs = std::env::var("NYASH_LLVM_EXE_LIBS").ok();
|
|
|
|
|
|
match crate::runner::modes::common_util::exec::ny_llvmc_emit_exe_lib(
|
|
|
|
|
|
&module,
|
|
|
|
|
|
exe_out,
|
|
|
|
|
|
None,
|
|
|
|
|
|
libs.as_deref(),
|
|
|
|
|
|
) {
|
|
|
|
|
|
Ok(()) => {
|
2025-11-21 06:25:17 +09:00
|
|
|
|
match crate::runner::modes::common_util::exec::run_executable(
|
|
|
|
|
|
exe_out,
|
|
|
|
|
|
&[],
|
|
|
|
|
|
20_000,
|
|
|
|
|
|
) {
|
2025-09-27 08:45:25 +09:00
|
|
|
|
Ok((code, _timed_out, stdout_text)) => {
|
|
|
|
|
|
// Forward program stdout so parity tests can compare outputs
|
2025-11-21 06:25:17 +09:00
|
|
|
|
if !stdout_text.is_empty() {
|
|
|
|
|
|
print!("{}", stdout_text);
|
|
|
|
|
|
}
|
2025-09-19 02:07:38 +09:00
|
|
|
|
println!("✅ LLVM (harness) execution completed (exit={})", code);
|
|
|
|
|
|
std::process::exit(code);
|
|
|
|
|
|
}
|
|
|
|
|
|
Err(e) => {
|
|
|
|
|
|
eprintln!("❌ run executable error: {}", e);
|
|
|
|
|
|
std::process::exit(1);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
Err(e) => {
|
|
|
|
|
|
eprintln!("❌ ny-llvmc emit-exe error: {}", e);
|
2025-11-21 06:25:17 +09:00
|
|
|
|
eprintln!(
|
|
|
|
|
|
" Hint: build ny-llvmc: cargo build -p nyash-llvm-compiler --release"
|
|
|
|
|
|
);
|
2025-09-19 02:07:38 +09:00
|
|
|
|
std::process::exit(1);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-26 04:34:14 +09:00
|
|
|
|
// Execute via LLVM backend (mock or real)
|
2025-09-14 00:44:28 +09:00
|
|
|
|
#[cfg(feature = "llvm-inkwell-legacy")]
|
2025-08-26 04:34:14 +09:00
|
|
|
|
{
|
|
|
|
|
|
use nyash_rust::backend::llvm_compile_and_execute;
|
|
|
|
|
|
let temp_path = "nyash_llvm_temp";
|
2025-09-01 23:44:34 +09:00
|
|
|
|
match llvm_compile_and_execute(&module, temp_path) {
|
2025-08-26 04:34:14 +09:00
|
|
|
|
Ok(result) => {
|
|
|
|
|
|
if let Some(int_result) = result.as_any().downcast_ref::<IntegerBox>() {
|
|
|
|
|
|
let exit_code = int_result.value;
|
|
|
|
|
|
println!("✅ LLVM execution completed!");
|
|
|
|
|
|
println!("📊 Exit code: {}", exit_code);
|
|
|
|
|
|
process::exit(exit_code as i32);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
println!("✅ LLVM execution completed (non-integer result)!");
|
|
|
|
|
|
println!("📊 Result: {}", result.to_string_box().value);
|
|
|
|
|
|
}
|
2025-09-17 07:43:07 +09:00
|
|
|
|
}
|
|
|
|
|
|
Err(e) => {
|
|
|
|
|
|
eprintln!("❌ LLVM execution error: {}", e);
|
|
|
|
|
|
process::exit(1);
|
|
|
|
|
|
}
|
2025-08-26 04:34:14 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-09-14 00:44:28 +09:00
|
|
|
|
#[cfg(all(not(feature = "llvm-inkwell-legacy")))]
|
2025-08-26 04:34:14 +09:00
|
|
|
|
{
|
|
|
|
|
|
println!("🔧 Mock LLVM Backend Execution:");
|
2025-09-14 00:44:28 +09:00
|
|
|
|
println!(" Build with --features llvm-inkwell-legacy for Rust/inkwell backend, or set NYASH_LLVM_OBJ_OUT and NYASH_LLVM_USE_HARNESS=1 for harness.");
|
2025-11-21 09:33:56 +09:00
|
|
|
|
// NamingBox SSOT: Select entry (arity-aware, Main.main → main fallback)
|
2025-11-24 14:17:02 +09:00
|
|
|
|
let entry =
|
|
|
|
|
|
crate::runner::modes::common_util::entry_selection::select_entry_function(&module);
|
2025-11-21 09:33:56 +09:00
|
|
|
|
if let Some(main_func) = module.functions.get(&entry) {
|
2025-08-26 04:34:14 +09:00
|
|
|
|
for (_bid, block) in &main_func.blocks {
|
|
|
|
|
|
for inst in &block.instructions {
|
|
|
|
|
|
match inst {
|
2025-09-17 07:43:07 +09:00
|
|
|
|
MirInstruction::Return { value: Some(_) } => {
|
|
|
|
|
|
println!("✅ Mock exit code: 42");
|
|
|
|
|
|
process::exit(42);
|
|
|
|
|
|
}
|
|
|
|
|
|
MirInstruction::Return { value: None } => {
|
|
|
|
|
|
println!("✅ Mock exit code: 0");
|
|
|
|
|
|
process::exit(0);
|
|
|
|
|
|
}
|
2025-08-26 04:34:14 +09:00
|
|
|
|
_ => {}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
println!("✅ Mock exit code: 0");
|
|
|
|
|
|
process::exit(0);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-09-13 15:37:58 +09:00
|
|
|
|
|
2025-09-14 04:51:33 +09:00
|
|
|
|
// emit_mir_json_for_harness moved to crate::runner::mir_json_emit
|