WIP: Separately compile irrt32+irrt64

This commit is contained in:
2026-04-30 16:15:35 +08:00
parent d2d3c5f36b
commit e18099b57e
4 changed files with 40 additions and 40 deletions

View File

@@ -1135,7 +1135,7 @@ impl Nac3 {
// Process IRRT
context_ref!(context);
let irrt = load_irrt(context, resolver.as_ref());
let irrt = load_irrt(context, &self.codegen_options.target, resolver.as_ref());
let fun_signature =
FunSignature { args: vec![], ret: self.primitive.none, vars: VarMap::new() };

View File

@@ -25,20 +25,6 @@ fn compile_irrt(target: &str, flags: &[&str]) -> String {
std::str::from_utf8(&output.stdout).unwrap().replace("\r\n", "\n")
}
// Returns true if an IR `define` block is a 64-bit IRRT function.
// extern "C" 64-bit functions end with "64" (e.g. __nac3_ndarray_len64).
// C++ template helpers using _BitInt(64) are mangled by Clang as "IDB64".
fn is_64bit_define(block: &str, name_re: &Regex) -> bool {
if !block.starts_with("define") {
return false;
}
if let Some(cap) = name_re.captures(block) {
let name = &cap[1];
return name.ends_with("64") || name.contains("IDB64");
}
false
}
fn main() {
// For debugging
// Doing `DEBUG_DUMP_IRRT=1 cargo build -p nac3core` dumps the LLVM IR generated
@@ -90,7 +76,8 @@ fn main() {
let wasm32_output = compile_irrt("wasm32", &flags);
let wasm64_output = compile_irrt("wasm64", &flags);
let mut filtered_output = String::with_capacity(wasm32_output.len() + wasm64_output.len());
let mut wasm32_filtered_output = String::with_capacity(wasm32_output.len());
let mut wasm64_filtered_output = String::with_capacity(wasm64_output.len());
// Filter out irrelevant IR
//
@@ -115,36 +102,28 @@ fn main() {
_ => unreachable!(),
};
// Regex to extract the function name from a `define` block header
let name_re = Regex::new(r"@(\w+)\(").unwrap();
// From wasm32: keep everything except 64-bit define blocks
for f in regex_filter.captures_iter(&wasm32_output) {
assert_eq!(f.len(), 1);
if is_64bit_define(&f[0], &name_re) {
continue;
}
filtered_output.push_str(&f[0]);
filtered_output.push('\n');
wasm32_filtered_output.push_str(&f[0]);
wasm32_filtered_output.push('\n');
}
// From wasm64: keep only 64-bit define blocks
for f in regex_filter.captures_iter(&wasm64_output) {
assert_eq!(f.len(), 1);
if is_64bit_define(&f[0], &name_re) {
filtered_output.push_str(&f[0]);
filtered_output.push('\n');
}
wasm64_filtered_output.push_str(&f[0]);
wasm64_filtered_output.push('\n');
}
let filtered_output = match env::var("PROFILE").as_deref() {
let regex_filter = match env::var("PROFILE").as_deref() {
Ok("debug") => Regex::new("(\"target-features\"=\".*\")").unwrap(),
Ok("release") => {
Regex::new("(#\\d+)|(, *![0-9A-Za-z.]+)|(![0-9A-Za-z.]+)|(!\".*?\")").unwrap()
}
_ => unreachable!(),
}
.replace_all(&filtered_output, "");
};
let wasm32_filtered_output = regex_filter.replace_all(&wasm32_filtered_output, "");
let wasm64_filtered_output = regex_filter.replace_all(&wasm64_filtered_output, "");
if env::var(DEBUG_DUMP_IRRT).is_ok() {
let mut file = File::create(out_dir.join("irrt-wasm32.ll")).unwrap();
@@ -153,16 +132,28 @@ fn main() {
let mut file = File::create(out_dir.join("irrt-wasm64.ll")).unwrap();
file.write_all(wasm64_output.as_bytes()).unwrap();
let mut file = File::create(out_dir.join("irrt-filtered.ll")).unwrap();
file.write_all(filtered_output.as_bytes()).unwrap();
let mut file = File::create(out_dir.join("irrt-wasm32-filtered.ll")).unwrap();
file.write_all(wasm32_filtered_output.as_bytes()).unwrap();
let mut file = File::create(out_dir.join("irrt-wasm64-filtered.ll")).unwrap();
file.write_all(wasm64_filtered_output.as_bytes()).unwrap();
}
let mut llvm_as = Command::new("llvm-as-irrt")
.stdin(Stdio::piped())
.arg("-o")
.arg(out_dir.join("irrt.bc"))
.arg(out_dir.join("irrt32.bc"))
.spawn()
.unwrap();
llvm_as.stdin.as_mut().unwrap().write_all(filtered_output.as_bytes()).unwrap();
llvm_as.stdin.as_mut().unwrap().write_all(wasm32_filtered_output.as_bytes()).unwrap();
assert!(llvm_as.wait().unwrap().success());
let mut llvm_as = Command::new("llvm-as-irrt")
.stdin(Stdio::piped())
.arg("-o")
.arg(out_dir.join("irrt64.bc"))
.spawn()
.unwrap();
llvm_as.stdin.as_mut().unwrap().write_all(wasm64_filtered_output.as_bytes()).unwrap();
assert!(llvm_as.wait().unwrap().success());
}

View File

@@ -9,7 +9,7 @@ use inkwell::{
use nac3parser::ast::Expr;
use crate::{
codegen::{CodeGenContext, CodeGenerator},
codegen::{CodeGenContext, CodeGenerator, TargetMachineOptions},
symbol_resolver::SymbolResolver,
typecheck::typedef::Type,
};
@@ -31,10 +31,19 @@ mod string;
#[must_use]
pub fn load_irrt<'ctx>(
ctx: ContextRef<'ctx>,
target: &TargetMachineOptions,
symbol_resolver: &dyn SymbolResolver,
) -> Module<'ctx> {
let target = target.create_target_machine();
let size_t = ctx.ptr_sized_int_type(&target.get_target_data(), None);
let bitcode_buf = MemoryBuffer::create_from_memory_range(
include_bytes!(concat!(env!("OUT_DIR"), "/irrt.bc")),
if size_t == ctx.i64_type() {
include_bytes!(concat!(env!("OUT_DIR"), "/irrt64.bc"))
} else if size_t == ctx.i32_type() {
include_bytes!(concat!(env!("OUT_DIR"), "/irrt32.bc"))
} else {
unreachable!("Unsupported size_t type bit width, must be either 32-bit or 64-bit")
},
"irrt_bitcode_buffer",
);
let irrt_mod = Module::parse_bitcode_from_buffer(&bitcode_buf, ctx).unwrap();

View File

@@ -330,7 +330,7 @@ fn main() {
context_ref!(context);
let irrt = load_irrt(context, resolver.as_ref());
let irrt = load_irrt(context, &target, resolver.as_ref());
emit_llvm(&irrt, "irrt");
// Process the Python script