smokes: add curated LLVM runner; archive legacy smokes; PHI-off unified across Bridge/Builder; LLVM resolver tracing; minimal Throw lowering; config env getters; dev profile and root cleaner; docs updated; CI workflow runs curated LLVM (PHI-on/off)

This commit is contained in:
Selfhosting Dev
2025-09-16 23:49:36 +09:00
parent 97a76c0571
commit 5c9213cd03
104 changed files with 8094 additions and 2930 deletions

View File

@ -24,28 +24,47 @@ fn main() {
// Read stdin to tmp/ny_mir_builder_input.json for re-use
let mut buf = Vec::new();
io::stdin().read_to_end(&mut buf).expect("read stdin");
if buf.is_empty() { eprintln!("error: no input on stdin"); std::process::exit(2); }
let cwd_tmp = Path::new("tmp"); let _ = fs::create_dir_all(cwd_tmp);
if buf.is_empty() {
eprintln!("error: no input on stdin");
std::process::exit(2);
}
let cwd_tmp = Path::new("tmp");
let _ = fs::create_dir_all(cwd_tmp);
let cwd_path = cwd_tmp.join("ny_mir_builder_input.json");
fs::write(&cwd_path, &buf).expect("write cwd tmp json");
cwd_path
} else {
let p = PathBuf::from(matches.get_one::<String>("in").unwrap());
if !p.exists() { eprintln!("error: input not found: {}", p.display()); std::process::exit(2); }
if !p.exists() {
eprintln!("error: input not found: {}", p.display());
std::process::exit(2);
}
p
};
let emit = matches.get_one::<String>("emit").unwrap().as_str();
let out_path = matches.get_one::<String>("out").map(|s| s.to_string()).unwrap_or_else(|| match emit {
"obj" => format!("{}/target/aot_objects/a.o", std::env::current_dir().unwrap().display()),
"ll" => format!("{}/target/aot_objects/a.ll", std::env::current_dir().unwrap().display()),
"exe" => "a.out".to_string(),
"json" => "/dev/stdout".to_string(),
_ => unreachable!(),
});
let out_path = matches
.get_one::<String>("out")
.map(|s| s.to_string())
.unwrap_or_else(|| match emit {
"obj" => format!(
"{}/target/aot_objects/a.o",
std::env::current_dir().unwrap().display()
),
"ll" => format!(
"{}/target/aot_objects/a.ll",
std::env::current_dir().unwrap().display()
),
"exe" => "a.out".to_string(),
"json" => "/dev/stdout".to_string(),
_ => unreachable!(),
});
let verify = matches.get_flag("verify_llvm");
let quiet = matches.get_flag("quiet");
let nyrt_dir = matches.get_one::<String>("nyrt").map(|s| s.to_string()).unwrap_or("crates/nyrt".to_string());
let nyrt_dir = matches
.get_one::<String>("nyrt")
.map(|s| s.to_string())
.unwrap_or("crates/nyrt".to_string());
// Determine sibling nyash binary path (target dir)
let nyash_bin = current_dir_bin("nyash");
@ -56,47 +75,74 @@ fn main() {
} else {
fs::copy(&in_file, &out_path).expect("copy json");
}
if !quiet { println!("OK json:{}", out_path); }
if !quiet {
println!("OK json:{}", out_path);
}
return;
}
// Ensure build dirs
let aot_dir = Path::new("target/aot_objects"); let _ = fs::create_dir_all(aot_dir);
let aot_dir = Path::new("target/aot_objects");
let _ = fs::create_dir_all(aot_dir);
match emit {
"ll" => {
std::env::set_var("NYASH_LLVM_DUMP_LL", "1");
std::env::set_var("NYASH_LLVM_LL_OUT", &out_path);
if verify { std::env::set_var("NYASH_LLVM_VERIFY", "1"); }
if verify {
std::env::set_var("NYASH_LLVM_VERIFY", "1");
}
std::env::set_var("NYASH_LLVM_USE_HARNESS", "1");
run_nyash_pipe(&nyash_bin, &in_file);
if !Path::new(&out_path).exists() { eprintln!("error: failed to produce {}", out_path); std::process::exit(4); }
if !quiet { println!("OK ll:{}", out_path); }
if !Path::new(&out_path).exists() {
eprintln!("error: failed to produce {}", out_path);
std::process::exit(4);
}
if !quiet {
println!("OK ll:{}", out_path);
}
}
"obj" => {
std::env::set_var("NYASH_LLVM_OBJ_OUT", &out_path);
if verify { std::env::set_var("NYASH_LLVM_VERIFY", "1"); }
if verify {
std::env::set_var("NYASH_LLVM_VERIFY", "1");
}
std::env::set_var("NYASH_LLVM_USE_HARNESS", "1");
// remove stale
let _ = fs::remove_file(&out_path);
run_nyash_pipe(&nyash_bin, &in_file);
if !Path::new(&out_path).exists() { eprintln!("error: failed to produce {}", out_path); std::process::exit(4); }
if !quiet { println!("OK obj:{}", out_path); }
if !Path::new(&out_path).exists() {
eprintln!("error: failed to produce {}", out_path);
std::process::exit(4);
}
if !quiet {
println!("OK obj:{}", out_path);
}
}
"exe" => {
let obj_path = format!("{}/target/aot_objects/__tmp_mir_builder.o", std::env::current_dir().unwrap().display());
let obj_path = format!(
"{}/target/aot_objects/__tmp_mir_builder.o",
std::env::current_dir().unwrap().display()
);
std::env::set_var("NYASH_LLVM_OBJ_OUT", &obj_path);
if verify { std::env::set_var("NYASH_LLVM_VERIFY", "1"); }
if verify {
std::env::set_var("NYASH_LLVM_VERIFY", "1");
}
std::env::set_var("NYASH_LLVM_USE_HARNESS", "1");
let _ = fs::remove_file(&obj_path);
run_nyash_pipe(&nyash_bin, &in_file);
if !Path::new(&obj_path).exists() { eprintln!("error: failed to produce object {}", obj_path); std::process::exit(4); }
if !Path::new(&obj_path).exists() {
eprintln!("error: failed to produce object {}", obj_path);
std::process::exit(4);
}
// Link with NyRT
if let Err(e) = link_exe(&obj_path, &out_path, &nyrt_dir) {
eprintln!("error: link failed: {}", e);
std::process::exit(5);
}
if !quiet { println!("OK exe:{}", out_path); }
if !quiet {
println!("OK exe:{}", out_path);
}
}
_ => unreachable!(),
}
@ -108,17 +154,23 @@ fn current_dir_bin(name: &str) -> PathBuf {
if let Ok(cur) = std::env::current_exe() {
if let Some(dir) = cur.parent() {
let cand = dir.join(name);
if cand.exists() { return cand; }
if cand.exists() {
return cand;
}
#[cfg(windows)]
{
let cand = dir.join(format!("{}.exe", name));
if cand.exists() { return cand; }
if cand.exists() {
return cand;
}
}
}
}
// Fallback to target/release
let cand = PathBuf::from("target/release").join(name);
if cand.exists() { return cand; }
if cand.exists() {
return cand;
}
#[cfg(windows)]
{
let cand = PathBuf::from("target/release").join(format!("{}.exe", name));
@ -157,10 +209,17 @@ fn link_exe(obj_path: &str, out_path: &str, nyrt_dir: &str) -> Result<(), String
args.push(obj_path.to_string());
// Provide LIBPATH and library name (prefer nyrt.lib)
args.push(format!("/LIBPATH:{}", nyrt_release));
if std::path::Path::new(&lib_nyrt_lib).exists() { args.push("nyrt.lib".to_string()); }
if std::path::Path::new(&lib_nyrt_lib).exists() {
args.push("nyrt.lib".to_string());
}
// lld-link cannot consume .a directly; rely on .lib
let status = PCommand::new("lld-link").args(args.iter().map(|s| s.as_str())).status().map_err(|e| e.to_string())?;
if status.success() { return Ok(()); }
let status = PCommand::new("lld-link")
.args(args.iter().map(|s| s.as_str()))
.status()
.map_err(|e| e.to_string())?;
if status.success() {
return Ok(());
}
return Err(format!("lld-link failed: status {:?}", status.code()));
}
if which::which("link").is_ok() {
@ -168,9 +227,16 @@ fn link_exe(obj_path: &str, out_path: &str, nyrt_dir: &str) -> Result<(), String
args.push(format!("/OUT:{}", out_path));
args.push(obj_path.to_string());
args.push(format!("/LIBPATH:{}", nyrt_release));
if std::path::Path::new(&lib_nyrt_lib).exists() { args.push("nyrt.lib".to_string()); }
let status = PCommand::new("link").args(args.iter().map(|s| s.as_str())).status().map_err(|e| e.to_string())?;
if status.success() { return Ok(()); }
if std::path::Path::new(&lib_nyrt_lib).exists() {
args.push("nyrt.lib".to_string());
}
let status = PCommand::new("link")
.args(args.iter().map(|s| s.as_str()))
.status()
.map_err(|e| e.to_string())?;
if status.success() {
return Ok(());
}
return Err(format!("link.exe failed: status {:?}", status.code()));
}
// Fallback: try cc with MinGW-like flags
@ -178,8 +244,11 @@ fn link_exe(obj_path: &str, out_path: &str, nyrt_dir: &str) -> Result<(), String
.args([obj_path])
.args(["-L", &format!("{}/target/release", nyrt_dir)])
.args(["-lnyrt", "-o", out_path])
.status().map_err(|e| e.to_string())?;
if status.success() { return Ok(()); }
.status()
.map_err(|e| e.to_string())?;
if status.success() {
return Ok(());
}
return Err(format!("cc link failed: status {:?}", status.code()));
}
#[cfg(not(target_os = "windows"))]
@ -190,7 +259,12 @@ fn link_exe(obj_path: &str, out_path: &str, nyrt_dir: &str) -> Result<(), String
.args(["-L", &format!("{}/target/release", nyrt_dir)])
.args(["-Wl,--whole-archive", "-lnyrt", "-Wl,--no-whole-archive"])
.args(["-lpthread", "-ldl", "-lm", "-o", out_path])
.status().map_err(|e| e.to_string())?;
if status.success() { Ok(()) } else { Err(format!("cc failed: status {:?}", status.code())) }
.status()
.map_err(|e| e.to_string())?;
if status.success() {
Ok(())
} else {
Err(format!("cc failed: status {:?}", status.code()))
}
}
}

View File

@ -5,13 +5,13 @@ use nyash_rust::runtime::{get_global_loader_v2, init_global_loader_v2};
fn main() {
env_logger::init();
println!("=== v2 Plugin Loader Test (Phase 12 prep) ===\n");
// Load configuration
let config_path = "test_nyash_v2.toml";
println!("Loading configuration from: {}", config_path);
let config = match NyashConfigV2::from_file(config_path) {
Ok(cfg) => cfg,
Err(e) => {
@ -19,10 +19,10 @@ fn main() {
return;
}
};
println!("Configuration loaded successfully!");
println!("Is v2 format: {}", config.is_v2_format());
if let Some(libs) = &config.plugins.libraries {
println!("\nLibraries found:");
for (name, lib) in libs {
@ -30,7 +30,7 @@ fn main() {
println!(" Provides: {:?}", lib.provides);
}
}
// Initialize and load plugins
println!("\nLoading plugins...");
if let Err(e) = init_global_loader_v2(config_path) {
@ -39,12 +39,14 @@ fn main() {
}
let loader = get_global_loader_v2();
let loader = loader.read().unwrap();
// Test box type resolution
println!("\nTesting box type resolution:");
for box_type in ["StringBox", "FileBox", "MapBox"] {
match config.find_library_for_box(box_type) {
Some((name, lib)) => println!(" {} -> library: {} (path={})", box_type, name, lib.path),
Some((name, lib)) => {
println!(" {} -> library: {} (path={})", box_type, name, lib.path)
}
None => println!(" {} -> not found in config", box_type),
}
}
@ -55,12 +57,13 @@ fn main() {
} else {
println!("create_box(StringBox) not available or failed (ok for stub)");
}
// Simple reverse host-call exercise (simulate plugin calling host via C ABI by-slot)
println!("\nReverse host-call (by-slot) quick test:");
// Create ArrayBox and obtain HostHandle
let mut arr = nyash_rust::boxes::ArrayBox::new();
arr.push(Box::new(nyash_rust::box_trait::StringBox::new("init")) as Box<dyn nyash_rust::box_trait::NyashBox>);
arr.push(Box::new(nyash_rust::box_trait::StringBox::new("init"))
as Box<dyn nyash_rust::box_trait::NyashBox>);
let handle = nyash_rust::runtime::host_handles::to_handle_box(Box::new(arr));
// Call Array.set(0, "hello") via slot=101
let mut tlv = nyash_rust::runtime::plugin_ffi_common::encode_tlv_header(2);
@ -68,21 +71,44 @@ fn main() {
nyash_rust::runtime::plugin_ffi_common::encode::string(&mut tlv, "hello");
let mut out = vec![0u8; 256];
let mut out_len: usize = out.len();
let code = unsafe { nyash_rust::runtime::host_api::nyrt_host_call_slot(handle, 101, tlv.as_ptr(), tlv.len(), out.as_mut_ptr(), &mut out_len) };
let code = unsafe {
nyash_rust::runtime::host_api::nyrt_host_call_slot(
handle,
101,
tlv.as_ptr(),
tlv.len(),
out.as_mut_ptr(),
&mut out_len,
)
};
println!(" set(slot=101) -> code={}, out_len={}", code, out_len);
// Call Array.get(0) via slot=100 and decode
let mut tlv2 = nyash_rust::runtime::plugin_ffi_common::encode_tlv_header(1);
nyash_rust::runtime::plugin_ffi_common::encode::i64(&mut tlv2, 0);
let mut out2 = vec![0u8; 256];
let mut out2_len: usize = out2.len();
let code2 = unsafe { nyash_rust::runtime::host_api::nyrt_host_call_slot(handle, 100, tlv2.as_ptr(), tlv2.len(), out2.as_mut_ptr(), &mut out2_len) };
let code2 = unsafe {
nyash_rust::runtime::host_api::nyrt_host_call_slot(
handle,
100,
tlv2.as_ptr(),
tlv2.len(),
out2.as_mut_ptr(),
&mut out2_len,
)
};
if code2 == 0 {
if let Some((tag, _sz, payload)) = nyash_rust::runtime::plugin_ffi_common::decode::tlv_first(&out2[..out2_len]) {
if tag == 6 || tag == 7 { // string/bytes
if let Some((tag, _sz, payload)) =
nyash_rust::runtime::plugin_ffi_common::decode::tlv_first(&out2[..out2_len])
{
if tag == 6 || tag == 7 {
// string/bytes
let s = nyash_rust::runtime::plugin_ffi_common::decode::string(payload);
println!(" get(slot=100) -> tag={}, value='{}'", tag, s);
} else if tag == 3 { // i64
let v = nyash_rust::runtime::plugin_ffi_common::decode::i32(payload).unwrap_or_default();
} else if tag == 3 {
// i64
let v = nyash_rust::runtime::plugin_ffi_common::decode::i32(payload)
.unwrap_or_default();
println!(" get(slot=100) -> tag={}, i32={}", tag, v);
} else {
println!(" get(slot=100) -> tag={}, size={}", tag, _sz);
@ -102,16 +128,36 @@ fn main() {
nyash_rust::runtime::plugin_ffi_common::encode::string(&mut tlv_set, "v");
let mut out_s = vec![0u8; 256];
let mut out_s_len: usize = out_s.len();
let code_s = unsafe { nyash_rust::runtime::host_api::nyrt_host_call_slot(map_h, 204, tlv_set.as_ptr(), tlv_set.len(), out_s.as_mut_ptr(), &mut out_s_len) };
let code_s = unsafe {
nyash_rust::runtime::host_api::nyrt_host_call_slot(
map_h,
204,
tlv_set.as_ptr(),
tlv_set.len(),
out_s.as_mut_ptr(),
&mut out_s_len,
)
};
println!(" set(slot=204) -> code={}, out_len={}", code_s, out_s_len);
// get("k") → slot=203
let mut tlv_get = nyash_rust::runtime::plugin_ffi_common::encode_tlv_header(1);
nyash_rust::runtime::plugin_ffi_common::encode::string(&mut tlv_get, "k");
let mut out_g = vec![0u8; 256];
let mut out_g_len: usize = out_g.len();
let code_g = unsafe { nyash_rust::runtime::host_api::nyrt_host_call_slot(map_h, 203, tlv_get.as_ptr(), tlv_get.len(), out_g.as_mut_ptr(), &mut out_g_len) };
let code_g = unsafe {
nyash_rust::runtime::host_api::nyrt_host_call_slot(
map_h,
203,
tlv_get.as_ptr(),
tlv_get.len(),
out_g.as_mut_ptr(),
&mut out_g_len,
)
};
if code_g == 0 {
if let Some((tag, _sz, payload)) = nyash_rust::runtime::plugin_ffi_common::decode::tlv_first(&out_g[..out_g_len]) {
if let Some((tag, _sz, payload)) =
nyash_rust::runtime::plugin_ffi_common::decode::tlv_first(&out_g[..out_g_len])
{
if tag == 6 || tag == 7 {
let s = nyash_rust::runtime::plugin_ffi_common::decode::string(payload);
println!(" get(slot=203) -> '{}'", s);
@ -123,13 +169,37 @@ fn main() {
// has("k") → slot=202
let mut out_hb = vec![0u8; 16];
let mut out_hb_len: usize = out_hb.len();
let code_hb = unsafe { nyash_rust::runtime::host_api::nyrt_host_call_slot(map_h, 202, tlv_get.as_ptr(), tlv_get.len(), out_hb.as_mut_ptr(), &mut out_hb_len) };
println!(" has(slot=202) -> code={}, out_len={}", code_hb, out_hb_len);
let code_hb = unsafe {
nyash_rust::runtime::host_api::nyrt_host_call_slot(
map_h,
202,
tlv_get.as_ptr(),
tlv_get.len(),
out_hb.as_mut_ptr(),
&mut out_hb_len,
)
};
println!(
" has(slot=202) -> code={}, out_len={}",
code_hb, out_hb_len
);
// size() → slot=200
let mut out_sz = vec![0u8; 32];
let mut out_sz_len: usize = out_sz.len();
let code_sz = unsafe { nyash_rust::runtime::host_api::nyrt_host_call_slot(map_h, 200, std::ptr::null(), 0, out_sz.as_mut_ptr(), &mut out_sz_len) };
println!(" size(slot=200) -> code={}, out_len={}", code_sz, out_sz_len);
let code_sz = unsafe {
nyash_rust::runtime::host_api::nyrt_host_call_slot(
map_h,
200,
std::ptr::null(),
0,
out_sz.as_mut_ptr(),
&mut out_sz_len,
)
};
println!(
" size(slot=200) -> code={}, out_len={}",
code_sz, out_sz_len
);
println!("\nTest completed!");
}