forked from M-Labs/nac3
nac3artiq: enables inlining
This commit is contained in:
parent
1f3aa48361
commit
c98f367f90
|
@ -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(
|
||||||
|
|
Loading…
Reference in New Issue