forked from M-Labs/nac3
core: Add LLVM options to WorkerRegistry
This commit is contained in:
parent
39724de598
commit
3993a5cf3f
|
@ -12,7 +12,7 @@ use inkwell::{
|
||||||
targets::*,
|
targets::*,
|
||||||
OptimizationLevel,
|
OptimizationLevel,
|
||||||
};
|
};
|
||||||
use nac3core::codegen::gen_func_impl;
|
use nac3core::codegen::{CodeGenLLVMOptions, gen_func_impl};
|
||||||
use nac3core::toplevel::builtins::get_exn_constructor;
|
use nac3core::toplevel::builtins::get_exn_constructor;
|
||||||
use nac3core::typecheck::typedef::{TypeEnum, Unifier};
|
use nac3core::typecheck::typedef::{TypeEnum, Unifier};
|
||||||
use nac3parser::{
|
use nac3parser::{
|
||||||
|
@ -97,7 +97,9 @@ struct Nac3 {
|
||||||
top_levels: Vec<TopLevelComponent>,
|
top_levels: Vec<TopLevelComponent>,
|
||||||
string_store: Arc<RwLock<HashMap<String, i32>>>,
|
string_store: Arc<RwLock<HashMap<String, i32>>>,
|
||||||
exception_ids: Arc<RwLock<HashMap<usize, usize>>>,
|
exception_ids: Arc<RwLock<HashMap<usize, usize>>>,
|
||||||
deferred_eval_store: DeferredEvaluationStore
|
deferred_eval_store: DeferredEvaluationStore,
|
||||||
|
/// LLVM-related options for code generation.
|
||||||
|
llvm_options: CodeGenLLVMOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
create_exception!(nac3artiq, CompileError, exceptions::PyException);
|
create_exception!(nac3artiq, CompileError, exceptions::PyException);
|
||||||
|
@ -588,7 +590,12 @@ impl Nac3 {
|
||||||
|
|
||||||
let membuffer = membuffers.clone();
|
let membuffer = membuffers.clone();
|
||||||
py.allow_threads(|| {
|
py.allow_threads(|| {
|
||||||
let (registry, handles) = WorkerRegistry::create_workers(threads, top_level.clone(), f);
|
let (registry, handles) = WorkerRegistry::create_workers(
|
||||||
|
threads,
|
||||||
|
top_level.clone(),
|
||||||
|
&self.llvm_options,
|
||||||
|
f
|
||||||
|
);
|
||||||
registry.add_task(task);
|
registry.add_task(task);
|
||||||
registry.wait_tasks_complete(handles);
|
registry.wait_tasks_complete(handles);
|
||||||
|
|
||||||
|
@ -681,7 +688,7 @@ impl Nac3 {
|
||||||
&triple,
|
&triple,
|
||||||
"",
|
"",
|
||||||
&features,
|
&features,
|
||||||
OptimizationLevel::Default,
|
self.llvm_options.opt_level,
|
||||||
RelocMode::PIC,
|
RelocMode::PIC,
|
||||||
CodeModel::Default,
|
CodeModel::Default,
|
||||||
)
|
)
|
||||||
|
@ -885,6 +892,10 @@ impl Nac3 {
|
||||||
string_store: Default::default(),
|
string_store: Default::default(),
|
||||||
exception_ids: Default::default(),
|
exception_ids: Default::default(),
|
||||||
deferred_eval_store: DeferredEvaluationStore::new(),
|
deferred_eval_store: DeferredEvaluationStore::new(),
|
||||||
|
llvm_options: CodeGenLLVMOptions {
|
||||||
|
opt_level: OptimizationLevel::Default,
|
||||||
|
emit_llvm: false,
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -132,12 +132,15 @@ pub struct WorkerRegistry {
|
||||||
wait_condvar: Condvar,
|
wait_condvar: Condvar,
|
||||||
top_level_ctx: Arc<TopLevelContext>,
|
top_level_ctx: Arc<TopLevelContext>,
|
||||||
static_value_store: Arc<Mutex<StaticValueStore>>,
|
static_value_store: Arc<Mutex<StaticValueStore>>,
|
||||||
|
/// LLVM-related options for code generation.
|
||||||
|
llvm_options: CodeGenLLVMOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WorkerRegistry {
|
impl WorkerRegistry {
|
||||||
pub fn create_workers<G: CodeGenerator + Send + 'static>(
|
pub fn create_workers<G: CodeGenerator + Send + 'static>(
|
||||||
generators: Vec<Box<G>>,
|
generators: Vec<Box<G>>,
|
||||||
top_level_ctx: Arc<TopLevelContext>,
|
top_level_ctx: Arc<TopLevelContext>,
|
||||||
|
llvm_options: &CodeGenLLVMOptions,
|
||||||
f: Arc<WithCall>,
|
f: Arc<WithCall>,
|
||||||
) -> (Arc<WorkerRegistry>, Vec<thread::JoinHandle<()>>) {
|
) -> (Arc<WorkerRegistry>, Vec<thread::JoinHandle<()>>) {
|
||||||
let (sender, receiver) = unbounded();
|
let (sender, receiver) = unbounded();
|
||||||
|
@ -158,6 +161,7 @@ impl WorkerRegistry {
|
||||||
task_count,
|
task_count,
|
||||||
wait_condvar,
|
wait_condvar,
|
||||||
top_level_ctx,
|
top_level_ctx,
|
||||||
|
llvm_options: llvm_options.clone(),
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut handles = Vec::new();
|
let mut handles = Vec::new();
|
||||||
|
@ -242,7 +246,7 @@ impl WorkerRegistry {
|
||||||
{
|
{
|
||||||
let _data = PASSES_INIT_LOCK.lock();
|
let _data = PASSES_INIT_LOCK.lock();
|
||||||
let pass_builder = PassManagerBuilder::create();
|
let pass_builder = PassManagerBuilder::create();
|
||||||
pass_builder.set_optimization_level(OptimizationLevel::Default);
|
pass_builder.set_optimization_level(self.llvm_options.opt_level);
|
||||||
pass_builder.populate_function_pass_manager(&passes);
|
pass_builder.populate_function_pass_manager(&passes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,6 +278,13 @@ impl WorkerRegistry {
|
||||||
println!("{}", err.to_string());
|
println!("{}", err.to_string());
|
||||||
panic!()
|
panic!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.llvm_options.emit_llvm {
|
||||||
|
println!("LLVM IR for {}", module.get_name().to_str().unwrap());
|
||||||
|
println!("{}", module.to_string());
|
||||||
|
println!();
|
||||||
|
}
|
||||||
|
|
||||||
f.run(&module);
|
f.run(&module);
|
||||||
let mut lock = self.task_count.lock();
|
let mut lock = self.task_count.lock();
|
||||||
*lock += 1;
|
*lock += 1;
|
||||||
|
@ -634,7 +645,7 @@ pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenConte
|
||||||
),
|
),
|
||||||
/* directory */ "",
|
/* directory */ "",
|
||||||
/* producer */ "NAC3",
|
/* producer */ "NAC3",
|
||||||
/* is_optimized */ true,
|
/* is_optimized */ registry.llvm_options.opt_level != OptimizationLevel::None,
|
||||||
/* compiler command line flags */ "",
|
/* compiler command line flags */ "",
|
||||||
/* runtime_ver */ 0,
|
/* runtime_ver */ 0,
|
||||||
/* split_name */ "",
|
/* split_name */ "",
|
||||||
|
@ -669,7 +680,7 @@ pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenConte
|
||||||
/* is_definition */ true,
|
/* is_definition */ true,
|
||||||
/* scope_line */ row as u32,
|
/* scope_line */ row as u32,
|
||||||
/* flags */ inkwell::debug_info::DIFlags::PUBLIC,
|
/* flags */ inkwell::debug_info::DIFlags::PUBLIC,
|
||||||
/* is_optimized */ true,
|
/* is_optimized */ registry.llvm_options.opt_level != OptimizationLevel::None,
|
||||||
);
|
);
|
||||||
fn_val.set_subprogram(func_scope);
|
fn_val.set_subprogram(func_scope);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
codegen::{
|
codegen::{
|
||||||
concrete_type::ConcreteTypeStore, CodeGenContext, CodeGenTask, DefaultCodeGenerator,
|
concrete_type::ConcreteTypeStore, CodeGenContext, CodeGenLLVMOptions, CodeGenTask,
|
||||||
WithCall, WorkerRegistry,
|
DefaultCodeGenerator, WithCall, WorkerRegistry,
|
||||||
},
|
},
|
||||||
symbol_resolver::{SymbolResolver, ValueEnum},
|
symbol_resolver::{SymbolResolver, ValueEnum},
|
||||||
toplevel::{
|
toplevel::{
|
||||||
|
@ -13,6 +13,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use indoc::indoc;
|
use indoc::indoc;
|
||||||
|
use inkwell::OptimizationLevel;
|
||||||
use nac3parser::{
|
use nac3parser::{
|
||||||
ast::{fold::Fold, StrRef},
|
ast::{fold::Fold, StrRef},
|
||||||
parser::parse_program,
|
parser::parse_program,
|
||||||
|
@ -220,7 +221,17 @@ fn test_primitives() {
|
||||||
.trim();
|
.trim();
|
||||||
assert_eq!(expected, module.print_to_string().to_str().unwrap().trim());
|
assert_eq!(expected, module.print_to_string().to_str().unwrap().trim());
|
||||||
})));
|
})));
|
||||||
let (registry, handles) = WorkerRegistry::create_workers(threads, top_level, f);
|
|
||||||
|
let llvm_options = CodeGenLLVMOptions {
|
||||||
|
opt_level: OptimizationLevel::Default,
|
||||||
|
emit_llvm: false,
|
||||||
|
};
|
||||||
|
let (registry, handles) = WorkerRegistry::create_workers(
|
||||||
|
threads,
|
||||||
|
top_level,
|
||||||
|
&llvm_options,
|
||||||
|
f
|
||||||
|
);
|
||||||
registry.add_task(task);
|
registry.add_task(task);
|
||||||
registry.wait_tasks_complete(handles);
|
registry.wait_tasks_complete(handles);
|
||||||
}
|
}
|
||||||
|
@ -395,7 +406,17 @@ fn test_simple_call() {
|
||||||
.trim();
|
.trim();
|
||||||
assert_eq!(expected, module.print_to_string().to_str().unwrap().trim());
|
assert_eq!(expected, module.print_to_string().to_str().unwrap().trim());
|
||||||
})));
|
})));
|
||||||
let (registry, handles) = WorkerRegistry::create_workers(threads, top_level, f);
|
|
||||||
|
let llvm_options = CodeGenLLVMOptions {
|
||||||
|
opt_level: OptimizationLevel::Default,
|
||||||
|
emit_llvm: false,
|
||||||
|
};
|
||||||
|
let (registry, handles) = WorkerRegistry::create_workers(
|
||||||
|
threads,
|
||||||
|
top_level,
|
||||||
|
&llvm_options,
|
||||||
|
f
|
||||||
|
);
|
||||||
registry.add_task(task);
|
registry.add_task(task);
|
||||||
registry.wait_tasks_complete(handles);
|
registry.wait_tasks_complete(handles);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,8 +10,8 @@ use std::{borrow::Borrow, collections::HashMap, fs, path::Path, sync::Arc};
|
||||||
|
|
||||||
use nac3core::{
|
use nac3core::{
|
||||||
codegen::{
|
codegen::{
|
||||||
concrete_type::ConcreteTypeStore, irrt::load_irrt, CodeGenTask, DefaultCodeGenerator,
|
concrete_type::ConcreteTypeStore, irrt::load_irrt, CodeGenLLVMOptions, CodeGenTask,
|
||||||
WithCall, WorkerRegistry,
|
DefaultCodeGenerator, WithCall, WorkerRegistry,
|
||||||
},
|
},
|
||||||
symbol_resolver::SymbolResolver,
|
symbol_resolver::SymbolResolver,
|
||||||
toplevel::{
|
toplevel::{
|
||||||
|
@ -255,6 +255,10 @@ fn main() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let llvm_options = CodeGenLLVMOptions {
|
||||||
|
opt_level: OptimizationLevel::Default,
|
||||||
|
emit_llvm: false,
|
||||||
|
};
|
||||||
let task = CodeGenTask {
|
let task = CodeGenTask {
|
||||||
subst: Default::default(),
|
subst: Default::default(),
|
||||||
symbol_name: "run".to_string(),
|
symbol_name: "run".to_string(),
|
||||||
|
@ -278,7 +282,7 @@ fn main() {
|
||||||
let threads = (0..threads)
|
let threads = (0..threads)
|
||||||
.map(|i| Box::new(DefaultCodeGenerator::new(format!("module{}", i), 64)))
|
.map(|i| Box::new(DefaultCodeGenerator::new(format!("module{}", i), 64)))
|
||||||
.collect();
|
.collect();
|
||||||
let (registry, handles) = WorkerRegistry::create_workers(threads, top_level, f);
|
let (registry, handles) = WorkerRegistry::create_workers(threads, top_level, &llvm_options, f);
|
||||||
registry.add_task(task);
|
registry.add_task(task);
|
||||||
registry.wait_tasks_complete(handles);
|
registry.wait_tasks_complete(handles);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue