core: Add LLVM options to CodeGen options

This commit is contained in:
David Mak 2023-09-06 17:50:17 +08:00
parent a335a317c5
commit 297d07f116
5 changed files with 63 additions and 19 deletions

View File

@ -12,7 +12,7 @@ use inkwell::{
targets::*,
OptimizationLevel,
};
use nac3core::codegen::gen_func_impl;
use nac3core::codegen::{CodeGenLLVMOptions, gen_func_impl};
use nac3core::toplevel::builtins::get_exn_constructor;
use nac3core::typecheck::typedef::{TypeEnum, Unifier};
use nac3parser::{
@ -97,7 +97,8 @@ struct Nac3 {
top_levels: Vec<TopLevelComponent>,
string_store: Arc<RwLock<HashMap<String, i32>>>,
exception_ids: Arc<RwLock<HashMap<usize, usize>>>,
deferred_eval_store: DeferredEvaluationStore
deferred_eval_store: DeferredEvaluationStore,
llvm_options: CodeGenLLVMOptions,
}
create_exception!(nac3artiq, CompileError, exceptions::PyException);
@ -551,6 +552,7 @@ impl Nac3 {
unifier_index: instance.unifier_id,
calls: instance.calls,
id: 0,
llvm_options: self.llvm_options,
};
let mut store = ConcreteTypeStore::new();
@ -568,6 +570,7 @@ impl Nac3 {
unifier_index: instance.unifier_id,
calls: Arc::new(Default::default()),
id: 0,
llvm_options: self.llvm_options,
};
let membuffers: Arc<Mutex<Vec<Vec<u8>>>> = Default::default();
@ -885,6 +888,10 @@ impl Nac3 {
string_store: Default::default(),
exception_ids: Default::default(),
deferred_eval_store: DeferredEvaluationStore::new(),
llvm_options: CodeGenLLVMOptions {
opt_level: OptimizationLevel::Default,
emit_llvm: false,
}
})
}

View File

@ -601,6 +601,7 @@ pub fn gen_func_instance<'ctx, 'a>(
store,
unifier_index: instance.unifier_id,
id,
llvm_options: ctx.llvm_options,
});
Ok(symbol)
} else {

View File

@ -59,6 +59,15 @@ lazy_static!(
static ref PASSES_INIT_LOCK: Mutex<AtomicBool> = Mutex::new(AtomicBool::new(true));
);
/// Additional options for LLVM during codegen.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct CodeGenLLVMOptions {
/// The optimization level to apply on the generated LLVM IR.
pub opt_level: OptimizationLevel,
/// Whether to output the LLVM IR after generation is complete.
pub emit_llvm: bool,
}
pub struct CodeGenContext<'ctx, 'a> {
pub ctx: &'ctx Context,
pub builder: Builder<'ctx>,
@ -89,6 +98,8 @@ pub struct CodeGenContext<'ctx, 'a> {
Option<(Vec<Option<BasicValueEnum<'ctx>>>, BasicBlock<'ctx>, PhiValue<'ctx>)>,
pub need_sret: bool,
pub current_loc: Location,
/// Additional LLVM options for Codegen
pub llvm_options: CodeGenLLVMOptions,
}
impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
@ -225,24 +236,32 @@ impl WorkerRegistry {
context.i32_type().const_int(4, false),
);
let passes = PassManager::create(&module);
// HACK: This critical section is a work-around for issue
// https://git.m-labs.hk/M-Labs/nac3/issues/275
{
let _data = PASSES_INIT_LOCK.lock();
let pass_builder = PassManagerBuilder::create();
pass_builder.set_optimization_level(OptimizationLevel::Default);
pass_builder.populate_function_pass_manager(&passes);
}
let mut errors = HashSet::new();
while let Some(task) = self.receiver.recv().unwrap() {
let passes = PassManager::create(&module);
// HACK: This critical section is a work-around for issue
// https://git.m-labs.hk/M-Labs/nac3/issues/275
{
let _data = PASSES_INIT_LOCK.lock();
let pass_builder = PassManagerBuilder::create();
pass_builder.set_optimization_level(task.llvm_options.opt_level);
pass_builder.populate_function_pass_manager(&passes);
}
let emit_llvm = task.llvm_options.emit_llvm;
match gen_func(&context, generator, self, builder, module, task) {
Ok(result) => {
builder = result.0;
passes.run_on(&result.2);
module = result.1;
if emit_llvm {
println!("LLVM IR for {}", module.get_name().to_str().unwrap());
println!("{}", module.to_string());
println!();
}
}
Err((old_builder, e)) => {
builder = old_builder;
@ -264,6 +283,7 @@ impl WorkerRegistry {
println!("{}", err.to_string());
panic!()
}
f.run(&module);
let mut lock = self.task_count.lock();
*lock += 1;
@ -281,6 +301,8 @@ pub struct CodeGenTask {
pub unifier_index: usize,
pub resolver: Arc<dyn SymbolResolver + Send + Sync>,
pub id: usize,
/// Additional LLVM options for Codegen
pub llvm_options: CodeGenLLVMOptions,
}
fn get_llvm_type<'ctx>(
@ -624,7 +646,7 @@ pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenConte
),
/* directory */ "",
/* producer */ "NAC3",
/* is_optimized */ true,
/* is_optimized */ task.llvm_options.opt_level != OptimizationLevel::None,
/* compiler command line flags */ "",
/* runtime_ver */ 0,
/* split_name */ "",
@ -659,7 +681,7 @@ pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenConte
/* is_definition */ true,
/* scope_line */ row as u32,
/* flags */ inkwell::debug_info::DIFlags::PUBLIC,
/* is_optimized */ true,
/* is_optimized */ task.llvm_options.opt_level != OptimizationLevel::None,
);
fn_val.set_subprogram(func_scope);
@ -686,6 +708,7 @@ pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenConte
need_sret: has_sret,
current_loc: Default::default(),
debug_info: (dibuilder, compile_unit, func_scope.as_debug_info_scope()),
llvm_options: task.llvm_options,
};
let loc = code_gen_context.debug_info.0.create_debug_location(

View File

@ -1,7 +1,7 @@
use crate::{
codegen::{
concrete_type::ConcreteTypeStore, CodeGenContext, CodeGenTask, DefaultCodeGenerator,
WithCall, WorkerRegistry,
concrete_type::ConcreteTypeStore, CodeGenContext, CodeGenLLVMOptions, CodeGenTask,
DefaultCodeGenerator, WithCall, WorkerRegistry,
},
symbol_resolver::{SymbolResolver, ValueEnum},
toplevel::{
@ -13,6 +13,7 @@ use crate::{
},
};
use indoc::indoc;
use inkwell::OptimizationLevel;
use nac3parser::{
ast::{fold::Fold, StrRef},
parser::parse_program,
@ -157,6 +158,10 @@ fn test_primitives() {
store,
signature,
id: 0,
llvm_options: CodeGenLLVMOptions {
opt_level: OptimizationLevel::Default,
emit_llvm: false,
},
};
let f = Arc::new(WithCall::new(Box::new(|module| {
// the following IR is equivalent to
@ -355,6 +360,10 @@ fn test_simple_call() {
signature,
store,
id: 0,
llvm_options: CodeGenLLVMOptions {
opt_level: OptimizationLevel::Default,
emit_llvm: false,
},
};
let f = Arc::new(WithCall::new(Box::new(|module| {
let expected = indoc! {"

View File

@ -10,8 +10,8 @@ use std::{borrow::Borrow, collections::HashMap, fs, path::Path, sync::Arc};
use nac3core::{
codegen::{
concrete_type::ConcreteTypeStore, irrt::load_irrt, CodeGenTask, DefaultCodeGenerator,
WithCall, WorkerRegistry,
concrete_type::ConcreteTypeStore, irrt::load_irrt, CodeGenLLVMOptions, CodeGenTask,
DefaultCodeGenerator, WithCall, WorkerRegistry,
},
symbol_resolver::SymbolResolver,
toplevel::{
@ -265,6 +265,10 @@ fn main() {
unifier_index: instance.unifier_id,
calls: instance.calls,
id: 0,
llvm_options: CodeGenLLVMOptions {
opt_level: OptimizationLevel::Default,
emit_llvm: false,
},
};
let membuffers: Arc<Mutex<Vec<Vec<u8>>>> = Default::default();