chore: Phase 25.1 完了 - LoopForm v2/Stage1 CLI/環境変数削減 + Phase 26-D からの変更
Phase 25.1 完了成果: - ✅ LoopForm v2 テスト・ドキュメント・コメント完備 - 4ケース(A/B/C/D)完全テストカバレッジ - 最小再現ケース作成(SSAバグ調査用) - SSOT文書作成(loopform_ssot.md) - 全ソースに [LoopForm] コメントタグ追加 - ✅ Stage-1 CLI デバッグ環境構築 - stage1_cli.hako 実装 - stage1_bridge.rs ブリッジ実装 - デバッグツール作成(stage1_debug.sh/stage1_minimal.sh) - アーキテクチャ改善提案文書 - ✅ 環境変数削減計画策定 - 25変数の完全調査・分類 - 6段階削減ロードマップ(25→5、80%削減) - 即時削除可能変数特定(NYASH_CONFIG/NYASH_DEBUG) Phase 26-D からの累積変更: - PHI実装改善(ExitPhiBuilder/HeaderPhiBuilder等) - MIRビルダーリファクタリング - 型伝播・最適化パス改善 - その他約300ファイルの累積変更 🎯 技術的成果: - SSAバグ根本原因特定(条件分岐内loop変数変更) - Region+next_iパターン適用完了(UsingCollectorBox等) - LoopFormパターン文書化・テスト化完了 - セルフホスティング基盤強化 Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: ChatGPT <noreply@openai.com> Co-Authored-By: Task Assistant <task@anthropic.com>
This commit is contained in:
@ -1,8 +1,8 @@
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::fs;
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
use std::ffi::{CString, CStr};
|
||||
|
||||
pub struct Opts {
|
||||
pub out: Option<PathBuf>,
|
||||
@ -13,9 +13,13 @@ pub struct Opts {
|
||||
|
||||
fn resolve_ny_llvmc() -> PathBuf {
|
||||
if let Ok(s) = std::env::var("NYASH_NY_LLVM_COMPILER") {
|
||||
if !s.is_empty() { return PathBuf::from(s); }
|
||||
if !s.is_empty() {
|
||||
return PathBuf::from(s);
|
||||
}
|
||||
}
|
||||
if let Ok(p) = which::which("ny-llvmc") {
|
||||
return p;
|
||||
}
|
||||
if let Ok(p) = which::which("ny-llvmc") { return p; }
|
||||
PathBuf::from("target/release/ny-llvmc")
|
||||
}
|
||||
|
||||
@ -25,7 +29,10 @@ pub fn mir_json_to_object(mir_json: &str, opts: Opts) -> Result<PathBuf, String>
|
||||
// Optional provider selection (C-API) — guarded by env flags
|
||||
// NYASH_LLVM_USE_CAPI=1 and HAKO_V1_EXTERN_PROVIDER_C_ABI=1
|
||||
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")
|
||||
&& std::env::var("HAKO_V1_EXTERN_PROVIDER_C_ABI")
|
||||
.ok()
|
||||
.as_deref()
|
||||
== Some("1")
|
||||
{
|
||||
// Basic shape check first
|
||||
if !mir_json.contains("\"functions\"") || !mir_json.contains("\"blocks\"") {
|
||||
@ -37,11 +44,19 @@ pub fn mir_json_to_object(mir_json: &str, opts: Opts) -> Result<PathBuf, String>
|
||||
let tmp_dir = std::env::temp_dir();
|
||||
let in_path = tmp_dir.join("hako_llvm_in.json");
|
||||
{
|
||||
let mut f = fs::File::create(&in_path).map_err(|e| format!("[llvmemit/tmp/write-failed] {}", e))?;
|
||||
f.write_all(mir_json.as_bytes()).map_err(|e| format!("[llvmemit/tmp/write-failed] {}", e))?;
|
||||
let mut f = fs::File::create(&in_path)
|
||||
.map_err(|e| format!("[llvmemit/tmp/write-failed] {}", e))?;
|
||||
f.write_all(mir_json.as_bytes())
|
||||
.map_err(|e| format!("[llvmemit/tmp/write-failed] {}", e))?;
|
||||
}
|
||||
let out_path = if let Some(p) = opts.out.clone() {
|
||||
p
|
||||
} else {
|
||||
tmp_dir.join("hako_llvm_out.o")
|
||||
};
|
||||
if let Some(parent) = out_path.parent() {
|
||||
let _ = fs::create_dir_all(parent);
|
||||
}
|
||||
let out_path = if let Some(p) = opts.out.clone() { p } else { tmp_dir.join("hako_llvm_out.o") };
|
||||
if let Some(parent) = out_path.parent() { let _ = fs::create_dir_all(parent); }
|
||||
match compile_via_capi(&in_path, &out_path) {
|
||||
Ok(()) => return Ok(out_path),
|
||||
Err(e) => {
|
||||
@ -74,26 +89,41 @@ pub fn mir_json_to_object(mir_json: &str, opts: Opts) -> Result<PathBuf, String>
|
||||
let tmp_dir = std::env::temp_dir();
|
||||
let in_path = tmp_dir.join("hako_llvm_in.json");
|
||||
{
|
||||
let mut f = fs::File::create(&in_path).map_err(|e| format!("[llvmemit/tmp/write-failed] {}", e))?;
|
||||
f.write_all(mir_json.as_bytes()).map_err(|e| format!("[llvmemit/tmp/write-failed] {}", e))?;
|
||||
let mut f =
|
||||
fs::File::create(&in_path).map_err(|e| format!("[llvmemit/tmp/write-failed] {}", e))?;
|
||||
f.write_all(mir_json.as_bytes())
|
||||
.map_err(|e| format!("[llvmemit/tmp/write-failed] {}", e))?;
|
||||
}
|
||||
|
||||
// Output path
|
||||
let out_path = if let Some(p) = opts.out.clone() { p } else { tmp_dir.join("hako_llvm_out.o") };
|
||||
if let Some(parent) = out_path.parent() { let _ = fs::create_dir_all(parent); }
|
||||
let out_path = if let Some(p) = opts.out.clone() {
|
||||
p
|
||||
} else {
|
||||
tmp_dir.join("hako_llvm_out.o")
|
||||
};
|
||||
if let Some(parent) = out_path.parent() {
|
||||
let _ = fs::create_dir_all(parent);
|
||||
}
|
||||
|
||||
// Build command: ny-llvmc --in <json> --emit obj --out <out>
|
||||
let mut cmd = Command::new(&ny_llvmc);
|
||||
cmd.arg("--in").arg(&in_path)
|
||||
.arg("--emit").arg("obj")
|
||||
.arg("--out").arg(&out_path);
|
||||
if let Some(nyrt) = opts.nyrt.as_ref() { cmd.arg("--nyrt").arg(nyrt); }
|
||||
cmd.arg("--in")
|
||||
.arg(&in_path)
|
||||
.arg("--emit")
|
||||
.arg("obj")
|
||||
.arg("--out")
|
||||
.arg(&out_path);
|
||||
if let Some(nyrt) = opts.nyrt.as_ref() {
|
||||
cmd.arg("--nyrt").arg(nyrt);
|
||||
}
|
||||
if let Some(level) = opts.opt_level.as_ref() {
|
||||
cmd.env("HAKO_LLVM_OPT_LEVEL", level);
|
||||
cmd.env("NYASH_LLVM_OPT_LEVEL", level);
|
||||
}
|
||||
|
||||
let status = cmd.status().map_err(|e| format!("[llvmemit/spawn/error] {}", e))?;
|
||||
let status = cmd
|
||||
.status()
|
||||
.map_err(|e| format!("[llvmemit/spawn/error] {}", e))?;
|
||||
if !status.success() {
|
||||
let code = status.code().unwrap_or(1);
|
||||
let tag = format!("[llvmemit/ny-llvmc/failed status={}]", code);
|
||||
@ -121,19 +151,28 @@ fn compile_via_capi(json_in: &Path, obj_out: &Path) -> Result<(), String> {
|
||||
unsafe {
|
||||
// Resolve library path
|
||||
let mut candidates: Vec<PathBuf> = Vec::new();
|
||||
if let Ok(p) = std::env::var("HAKO_AOT_FFI_LIB") { if !p.is_empty() { candidates.push(PathBuf::from(p)); } }
|
||||
if let Ok(p) = std::env::var("HAKO_AOT_FFI_LIB") {
|
||||
if !p.is_empty() {
|
||||
candidates.push(PathBuf::from(p));
|
||||
}
|
||||
}
|
||||
candidates.push(PathBuf::from("target/release/libhako_llvmc_ffi.so"));
|
||||
candidates.push(PathBuf::from("lib/libhako_llvmc_ffi.so"));
|
||||
let lib_path = candidates.into_iter().find(|p| p.exists())
|
||||
let lib_path = candidates
|
||||
.into_iter()
|
||||
.find(|p| p.exists())
|
||||
.ok_or_else(|| "FFI library not found (set HAKO_AOT_FFI_LIB)".to_string())?;
|
||||
let lib = Library::new(lib_path).map_err(|e| format!("dlopen failed: {}", e))?;
|
||||
// Symbol: int hako_llvmc_compile_json(const char*, const char*, char**)
|
||||
type CompileFn = unsafe extern "C" fn(*const c_char, *const c_char, *mut *mut c_char) -> c_int;
|
||||
type CompileFn =
|
||||
unsafe extern "C" fn(*const c_char, *const c_char, *mut *mut c_char) -> c_int;
|
||||
let func: libloading::Symbol<CompileFn> = lib
|
||||
.get(b"hako_llvmc_compile_json\0")
|
||||
.map_err(|e| format!("dlsym failed: {}", e))?;
|
||||
let cin = CString::new(json_in.to_string_lossy().as_bytes()).map_err(|_| "invalid json path".to_string())?;
|
||||
let cout = CString::new(obj_out.to_string_lossy().as_bytes()).map_err(|_| "invalid out path".to_string())?;
|
||||
let cin = CString::new(json_in.to_string_lossy().as_bytes())
|
||||
.map_err(|_| "invalid json path".to_string())?;
|
||||
let cout = CString::new(obj_out.to_string_lossy().as_bytes())
|
||||
.map_err(|_| "invalid out path".to_string())?;
|
||||
let mut err_ptr: *mut c_char = std::ptr::null_mut();
|
||||
// Avoid recursive FFI-in-FFI: force inner AOT to use CLI path
|
||||
let prev = std::env::var("HAKO_AOT_USE_FFI").ok();
|
||||
@ -156,17 +195,31 @@ fn compile_via_capi(json_in: &Path, obj_out: &Path) -> Result<(), String> {
|
||||
);
|
||||
}
|
||||
|
||||
let rc = func(cin.as_ptr(), cout.as_ptr(), &mut err_ptr as *mut *mut c_char);
|
||||
if let Some(v) = prev { std::env::set_var("HAKO_AOT_USE_FFI", v); } else { std::env::remove_var("HAKO_AOT_USE_FFI"); }
|
||||
let rc = func(
|
||||
cin.as_ptr(),
|
||||
cout.as_ptr(),
|
||||
&mut err_ptr as *mut *mut c_char,
|
||||
);
|
||||
if let Some(v) = prev {
|
||||
std::env::set_var("HAKO_AOT_USE_FFI", v);
|
||||
} else {
|
||||
std::env::remove_var("HAKO_AOT_USE_FFI");
|
||||
}
|
||||
if rc != 0 {
|
||||
let msg = if !err_ptr.is_null() { CStr::from_ptr(err_ptr).to_string_lossy().to_string() } else { "compile failed".to_string() };
|
||||
let msg = if !err_ptr.is_null() {
|
||||
CStr::from_ptr(err_ptr).to_string_lossy().to_string()
|
||||
} else {
|
||||
"compile failed".to_string()
|
||||
};
|
||||
// Free error string (allocated by C side)
|
||||
if !err_ptr.is_null() {
|
||||
free(err_ptr as *mut c_void);
|
||||
}
|
||||
return Err(msg);
|
||||
}
|
||||
if !obj_out.exists() { return Err("object not produced".into()); }
|
||||
if !obj_out.exists() {
|
||||
return Err("object not produced".into());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@ -177,13 +230,19 @@ fn compile_via_capi(_json_in: &Path, _obj_out: &Path) -> Result<(), String> {
|
||||
}
|
||||
|
||||
/// Link an object to an executable via C-API FFI bundle.
|
||||
pub fn link_object_capi(obj_in: &Path, exe_out: &Path, extra_ldflags: Option<&str>) -> Result<(), String> {
|
||||
pub fn link_object_capi(
|
||||
obj_in: &Path,
|
||||
exe_out: &Path,
|
||||
extra_ldflags: Option<&str>,
|
||||
) -> Result<(), String> {
|
||||
// Compute effective ldflags
|
||||
let mut eff: Option<String> = extra_ldflags.map(|s| s.to_string());
|
||||
let empty = eff.as_deref().map(|s| s.trim().is_empty()).unwrap_or(true);
|
||||
if empty {
|
||||
if let Ok(s) = std::env::var("HAKO_AOT_LDFLAGS") {
|
||||
if !s.trim().is_empty() { eff = Some(s); }
|
||||
if !s.trim().is_empty() {
|
||||
eff = Some(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
if eff.is_none() {
|
||||
@ -224,35 +283,68 @@ fn link_via_capi(obj_in: &Path, exe_out: &Path, extra_ldflags: Option<&str>) ->
|
||||
|
||||
unsafe {
|
||||
let mut candidates: Vec<PathBuf> = Vec::new();
|
||||
if let Ok(p) = std::env::var("HAKO_AOT_FFI_LIB") { if !p.is_empty() { candidates.push(PathBuf::from(p)); } }
|
||||
if let Ok(p) = std::env::var("HAKO_AOT_FFI_LIB") {
|
||||
if !p.is_empty() {
|
||||
candidates.push(PathBuf::from(p));
|
||||
}
|
||||
}
|
||||
candidates.push(PathBuf::from("target/release/libhako_llvmc_ffi.so"));
|
||||
candidates.push(PathBuf::from("lib/libhako_llvmc_ffi.so"));
|
||||
let lib_path = candidates.into_iter().find(|p| p.exists())
|
||||
let lib_path = candidates
|
||||
.into_iter()
|
||||
.find(|p| p.exists())
|
||||
.ok_or_else(|| "FFI library not found (set HAKO_AOT_FFI_LIB)".to_string())?;
|
||||
let lib = Library::new(lib_path).map_err(|e| format!("dlopen failed: {}", e))?;
|
||||
// int hako_llvmc_link_obj(const char*, const char*, const char*, char**)
|
||||
type LinkFn = unsafe extern "C" fn(*const c_char, *const c_char, *const c_char, *mut *mut c_char) -> c_int;
|
||||
type LinkFn = unsafe extern "C" fn(
|
||||
*const c_char,
|
||||
*const c_char,
|
||||
*const c_char,
|
||||
*mut *mut c_char,
|
||||
) -> c_int;
|
||||
let func: libloading::Symbol<LinkFn> = lib
|
||||
.get(b"hako_llvmc_link_obj\0")
|
||||
.map_err(|e| format!("dlsym failed: {}", e))?;
|
||||
let cobj = CString::new(obj_in.to_string_lossy().as_bytes()).map_err(|_| "invalid obj path".to_string())?;
|
||||
let cexe = CString::new(exe_out.to_string_lossy().as_bytes()).map_err(|_| "invalid exe path".to_string())?;
|
||||
let cobj = CString::new(obj_in.to_string_lossy().as_bytes())
|
||||
.map_err(|_| "invalid obj path".to_string())?;
|
||||
let cexe = CString::new(exe_out.to_string_lossy().as_bytes())
|
||||
.map_err(|_| "invalid exe path".to_string())?;
|
||||
let ldflags_owned;
|
||||
let cflags_ptr = if let Some(s) = extra_ldflags { ldflags_owned = CString::new(s).map_err(|_| "invalid ldflags".to_string())?; ldflags_owned.as_ptr() } else { std::ptr::null() };
|
||||
let cflags_ptr = if let Some(s) = extra_ldflags {
|
||||
ldflags_owned = CString::new(s).map_err(|_| "invalid ldflags".to_string())?;
|
||||
ldflags_owned.as_ptr()
|
||||
} else {
|
||||
std::ptr::null()
|
||||
};
|
||||
let mut err_ptr: *mut c_char = std::ptr::null_mut();
|
||||
// Avoid recursive FFI-in-FFI
|
||||
let prev = std::env::var("HAKO_AOT_USE_FFI").ok();
|
||||
std::env::set_var("HAKO_AOT_USE_FFI", "0");
|
||||
let rc = func(cobj.as_ptr(), cexe.as_ptr(), cflags_ptr, &mut err_ptr as *mut *mut c_char);
|
||||
if let Some(v) = prev { std::env::set_var("HAKO_AOT_USE_FFI", v); } else { std::env::remove_var("HAKO_AOT_USE_FFI"); }
|
||||
let rc = func(
|
||||
cobj.as_ptr(),
|
||||
cexe.as_ptr(),
|
||||
cflags_ptr,
|
||||
&mut err_ptr as *mut *mut c_char,
|
||||
);
|
||||
if let Some(v) = prev {
|
||||
std::env::set_var("HAKO_AOT_USE_FFI", v);
|
||||
} else {
|
||||
std::env::remove_var("HAKO_AOT_USE_FFI");
|
||||
}
|
||||
if rc != 0 {
|
||||
let msg = if !err_ptr.is_null() { CStr::from_ptr(err_ptr).to_string_lossy().to_string() } else { "link failed".to_string() };
|
||||
let msg = if !err_ptr.is_null() {
|
||||
CStr::from_ptr(err_ptr).to_string_lossy().to_string()
|
||||
} else {
|
||||
"link failed".to_string()
|
||||
};
|
||||
if !err_ptr.is_null() {
|
||||
free(err_ptr as *mut c_void);
|
||||
}
|
||||
return Err(msg);
|
||||
}
|
||||
if !exe_out.exists() { return Err("exe not produced".into()); }
|
||||
if !exe_out.exists() {
|
||||
return Err("exe not produced".into());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@ -263,21 +355,31 @@ fn link_via_capi(_obj_in: &Path, _exe_out: &Path, _extra: Option<&str>) -> Resul
|
||||
}
|
||||
|
||||
fn resolve_python3() -> Option<PathBuf> {
|
||||
if let Ok(p) = which::which("python3") { return Some(p); }
|
||||
if let Ok(p) = which::which("python") { return Some(p); }
|
||||
if let Ok(p) = which::which("python3") {
|
||||
return Some(p);
|
||||
}
|
||||
if let Ok(p) = which::which("python") {
|
||||
return Some(p);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn resolve_llvmlite_harness() -> Option<PathBuf> {
|
||||
if let Ok(root) = std::env::var("NYASH_ROOT") {
|
||||
let p = PathBuf::from(root).join("tools/llvmlite_harness.py");
|
||||
if p.exists() { return Some(p); }
|
||||
if p.exists() {
|
||||
return Some(p);
|
||||
}
|
||||
}
|
||||
let p = PathBuf::from("tools/llvmlite_harness.py");
|
||||
if p.exists() { return Some(p); }
|
||||
if p.exists() {
|
||||
return Some(p);
|
||||
}
|
||||
// Also try repo-relative (target may run elsewhere)
|
||||
let p2 = PathBuf::from("../tools/llvmlite_harness.py");
|
||||
if p2.exists() { return Some(p2); }
|
||||
if p2.exists() {
|
||||
return Some(p2);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
@ -303,17 +405,27 @@ fn mir_json_to_object_llvmlite(mir_json: &str, opts: &Opts) -> Result<PathBuf, S
|
||||
let tmp_dir = std::env::temp_dir();
|
||||
let in_path = tmp_dir.join("hako_llvm_in.json");
|
||||
{
|
||||
let mut f = fs::File::create(&in_path).map_err(|e| format!("[llvmemit/tmp/write-failed] {}", e))?;
|
||||
f.write_all(mir_json.as_bytes()).map_err(|e| format!("[llvmemit/tmp/write-failed] {}", e))?;
|
||||
let mut f =
|
||||
fs::File::create(&in_path).map_err(|e| format!("[llvmemit/tmp/write-failed] {}", e))?;
|
||||
f.write_all(mir_json.as_bytes())
|
||||
.map_err(|e| format!("[llvmemit/tmp/write-failed] {}", e))?;
|
||||
}
|
||||
let out_path = if let Some(p) = opts.out.clone() {
|
||||
p
|
||||
} else {
|
||||
tmp_dir.join("hako_llvm_out.o")
|
||||
};
|
||||
if let Some(parent) = out_path.parent() {
|
||||
let _ = fs::create_dir_all(parent);
|
||||
}
|
||||
let out_path = if let Some(p) = opts.out.clone() { p } else { tmp_dir.join("hako_llvm_out.o") };
|
||||
if let Some(parent) = out_path.parent() { let _ = fs::create_dir_all(parent); }
|
||||
|
||||
// Run: python3 tools/llvmlite_harness.py --in <json> --out <out>
|
||||
let status = Command::new(&py)
|
||||
.arg(&harness)
|
||||
.arg("--in").arg(&in_path)
|
||||
.arg("--out").arg(&out_path)
|
||||
.arg("--in")
|
||||
.arg(&in_path)
|
||||
.arg("--out")
|
||||
.arg(&out_path)
|
||||
.status()
|
||||
.map_err(|e| format!("[llvmemit/llvmlite/spawn/error] {}", e))?;
|
||||
if !status.success() {
|
||||
|
||||
@ -11,7 +11,10 @@ pub fn program_json_to_mir_json(program_json: &str) -> Result<String, String> {
|
||||
}
|
||||
|
||||
/// Convert Program(JSON v0) to MIR(JSON v0) with using imports support.
|
||||
pub fn program_json_to_mir_json_with_imports(program_json: &str, imports: HashMap<String, String>) -> Result<String, String> {
|
||||
pub fn program_json_to_mir_json_with_imports(
|
||||
program_json: &str,
|
||||
imports: HashMap<String, String>,
|
||||
) -> Result<String, String> {
|
||||
// Basic header check
|
||||
if !program_json.contains("\"version\"") || !program_json.contains("\"kind\"") {
|
||||
let tag = "[mirbuilder/input/invalid] missing version/kind keys";
|
||||
@ -20,14 +23,15 @@ pub fn program_json_to_mir_json_with_imports(program_json: &str, imports: HashMa
|
||||
}
|
||||
|
||||
// Parse Program(JSON v0) into a MIR Module with imports
|
||||
let module = match runner::json_v0_bridge::parse_json_v0_to_module_with_imports(program_json, imports) {
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
let tag = format!("[mirbuilder/parse/error] {}", e);
|
||||
eprintln!("{}", tag);
|
||||
return Err(tag);
|
||||
}
|
||||
};
|
||||
let module =
|
||||
match runner::json_v0_bridge::parse_json_v0_to_module_with_imports(program_json, imports) {
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
let tag = format!("[mirbuilder/parse/error] {}", e);
|
||||
eprintln!("{}", tag);
|
||||
return Err(tag);
|
||||
}
|
||||
};
|
||||
|
||||
// Emit MIR(JSON) to a temporary file (reuse existing emitter), then read back
|
||||
let tmp_dir = std::env::temp_dir();
|
||||
@ -57,8 +61,12 @@ pub fn program_json_to_mir_json_with_imports(program_json: &str, imports: HashMa
|
||||
if let Some(funcs) = m.get("functions").cloned() {
|
||||
let v1 = serde_json::json!({"schema_version":"1.0","functions": funcs});
|
||||
serde_json::to_string(&v1).unwrap_or(s0)
|
||||
} else { s0 }
|
||||
} else { s0 }
|
||||
} else {
|
||||
s0
|
||||
}
|
||||
} else {
|
||||
s0
|
||||
}
|
||||
}
|
||||
_ => s0,
|
||||
};
|
||||
@ -128,7 +136,10 @@ mod tests {
|
||||
|
||||
let mir_json = result.unwrap();
|
||||
// MIR JSON should contain functions
|
||||
assert!(mir_json.contains("functions"), "MIR JSON should contain functions");
|
||||
assert!(
|
||||
mir_json.contains("functions"),
|
||||
"MIR JSON should contain functions"
|
||||
);
|
||||
eprintln!("[test] MIR JSON generated successfully with MatI64 imports");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,2 @@
|
||||
pub mod mir_builder;
|
||||
pub mod llvm_codegen;
|
||||
|
||||
pub mod mir_builder;
|
||||
|
||||
Reference in New Issue
Block a user