nac3artiq: enables inlining

This commit is contained in:
pca006132 2021-12-04 17:52:03 +08:00
parent 1f3aa48361
commit c98f367f90
1 changed files with 80 additions and 55 deletions

View File

@ -4,6 +4,7 @@ use std::process::Command;
use std::sync::Arc; use std::sync::Arc;
use inkwell::{ use inkwell::{
memory_buffer::MemoryBuffer,
passes::{PassManager, PassManagerBuilder}, passes::{PassManager, PassManagerBuilder},
targets::*, targets::*,
OptimizationLevel, OptimizationLevel,
@ -301,8 +302,8 @@ impl Nac3 {
.call0() .call0()
.unwrap() .unwrap()
.get_item("virtual") .get_item("virtual")
.unwrap(), .unwrap(),))
)).unwrap() .unwrap()
.extract() .extract()
.unwrap(), .unwrap(),
generic_alias: ( generic_alias: (
@ -521,12 +522,56 @@ impl Nac3 {
}; };
let isa = self.isa; let isa = self.isa;
let working_directory = self.working_directory.path().to_owned(); let working_directory = self.working_directory.path().to_owned();
let membuffers: Arc<Mutex<Vec<Vec<u8>>>> = Default::default();
let membuffer = membuffers.clone();
let f = Arc::new(WithCall::new(Box::new(move |module| { let f = Arc::new(WithCall::new(Box::new(move |module| {
let buffer = module.write_bitcode_to_memory();
let buffer = buffer.as_slice().into();
membuffer.lock().push(buffer);
})));
let thread_names: Vec<String> = (0..4).map(|_| "main".to_string()).collect();
let threads: Vec<_> = thread_names
.iter()
.map(|s| Box::new(ArtiqCodeGenerator::new(s.to_string(), self.time_fns)))
.collect();
py.allow_threads(|| {
let (registry, handles) = WorkerRegistry::create_workers(threads, top_level.clone(), f);
registry.add_task(task);
registry.wait_tasks_complete(handles);
});
let buffers = membuffers.lock();
let context = inkwell::context::Context::create();
let main = context
.create_module_from_ir(MemoryBuffer::create_from_memory_range(&buffers[0], "main"))
.unwrap();
for buffer in buffers.iter().skip(1) {
let other = context
.create_module_from_ir(MemoryBuffer::create_from_memory_range(buffer, "main"))
.unwrap();
main.link_in_module(other)
.map_err(|err| exceptions::PyRuntimeError::new_err(err.to_string()))?;
}
let mut function_iter = main.get_first_function();
while let Some(func) = function_iter {
if func.count_basic_blocks() > 0 && func.get_name().to_str().unwrap() != "__modinit__" {
func.set_linkage(inkwell::module::Linkage::Private);
}
function_iter = func.get_next_function();
}
let builder = PassManagerBuilder::create(); let builder = PassManagerBuilder::create();
builder.set_optimization_level(OptimizationLevel::Default); builder.set_optimization_level(OptimizationLevel::Aggressive);
let passes = PassManager::create(()); let passes = PassManager::create(());
builder.set_inliner_with_threshold(255);
builder.populate_module_pass_manager(&passes); builder.populate_module_pass_manager(&passes);
passes.run_on(module); passes.run_on(&main);
let (triple, features) = match isa { let (triple, features) = match isa {
Isa::Host => ( Isa::Host => (
@ -559,24 +604,8 @@ impl Nac3 {
) )
.expect("couldn't create target machine"); .expect("couldn't create target machine");
target_machine target_machine
.write_to_file( .write_to_file(&main, FileType::Object, &working_directory.join("module.o"))
module,
FileType::Object,
&working_directory.join(&format!("{}.o", module.get_name().to_str().unwrap())),
)
.expect("couldn't write module to file"); .expect("couldn't write module to file");
})));
let thread_names: Vec<String> = (0..4).map(|i| format!("module{}", i)).collect();
let threads: Vec<_> = thread_names
.iter()
.map(|s| Box::new(ArtiqCodeGenerator::new(s.to_string(), self.time_fns)))
.collect();
py.allow_threads(|| {
let (registry, handles) = WorkerRegistry::create_workers(threads, top_level.clone(), f);
registry.add_task(task);
registry.wait_tasks_complete(handles);
});
let mut linker_args = vec![ let mut linker_args = vec![
"-shared".to_string(), "-shared".to_string(),
@ -584,6 +613,10 @@ impl Nac3 {
"-x".to_string(), "-x".to_string(),
"-o".to_string(), "-o".to_string(),
filename.to_string(), filename.to_string(),
working_directory
.join("module.o")
.to_string_lossy()
.to_string(),
]; ];
if isa != Isa::Host { if isa != Isa::Host {
linker_args.push( linker_args.push(
@ -596,15 +629,7 @@ impl Nac3 {
.unwrap(), .unwrap(),
); );
} }
linker_args.extend(thread_names.iter().map(|name| {
let name_o = name.to_owned() + ".o";
self.working_directory
.path()
.join(name_o.as_str())
.to_str()
.unwrap()
.to_string()
}));
if let Ok(linker_status) = Command::new("ld.lld").args(linker_args).status() { if let Ok(linker_status) = Command::new("ld.lld").args(linker_args).status() {
if !linker_status.success() { if !linker_status.success() {
return Err(exceptions::PyRuntimeError::new_err( return Err(exceptions::PyRuntimeError::new_err(