core: Add use_demo_lib option
Allows injecting calls to demo library functions for debugging.
This commit is contained in:
parent
520e1adc56
commit
4d0d4e0eae
|
@ -14,7 +14,7 @@ use inkwell::{
|
|||
OptimizationLevel,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use nac3core::codegen::{CodeGenLLVMOptions, CodeGenTargetMachineOptions, gen_func_impl};
|
||||
use nac3core::codegen::{CodeGenLLVMOptions, CodeGenOptions, CodeGenTargetMachineOptions, gen_func_impl};
|
||||
use nac3core::toplevel::builtins::get_exn_constructor;
|
||||
use nac3core::typecheck::typedef::{TypeEnum, Unifier, VarMap};
|
||||
use nac3parser::{
|
||||
|
@ -113,8 +113,8 @@ struct Nac3 {
|
|||
string_store: Arc<RwLock<HashMap<String, i32>>>,
|
||||
exception_ids: Arc<RwLock<HashMap<usize, usize>>>,
|
||||
deferred_eval_store: DeferredEvaluationStore,
|
||||
/// LLVM-related options for code generation.
|
||||
llvm_options: CodeGenLLVMOptions,
|
||||
/// Options for code generation.
|
||||
codegen_options: CodeGenOptions,
|
||||
}
|
||||
|
||||
create_exception!(nac3artiq, CompileError, exceptions::PyException);
|
||||
|
@ -607,7 +607,7 @@ impl Nac3 {
|
|||
let (registry, handles) = WorkerRegistry::create_workers(
|
||||
threads,
|
||||
top_level.clone(),
|
||||
&self.llvm_options,
|
||||
&self.codegen_options,
|
||||
&f
|
||||
);
|
||||
registry.add_task(task);
|
||||
|
@ -674,13 +674,13 @@ impl Nac3 {
|
|||
global_option = global.get_next_global();
|
||||
}
|
||||
|
||||
let target_machine = self.llvm_options.target
|
||||
.create_target_machine(self.llvm_options.opt_level)
|
||||
let target_machine = self.codegen_options.llvm.target
|
||||
.create_target_machine(self.codegen_options.llvm.opt_level)
|
||||
.expect("couldn't create target machine");
|
||||
|
||||
let pass_options = PassBuilderOptions::create();
|
||||
pass_options.set_merge_functions(true);
|
||||
let passes = format!("default<O{}>", self.llvm_options.opt_level as u32);
|
||||
let passes = format!("default<O{}>", self.codegen_options.llvm.opt_level as u32);
|
||||
let result = main.run_passes(passes.as_str(), &target_machine, pass_options);
|
||||
if let Err(err) = result {
|
||||
panic!("Failed to run optimization for module `main`: {}", err.to_string());
|
||||
|
@ -733,7 +733,7 @@ impl Nac3 {
|
|||
/// target [isa].
|
||||
fn get_llvm_target_machine(&self) -> TargetMachine {
|
||||
Nac3::get_llvm_target_options(self.isa)
|
||||
.create_target_machine(self.llvm_options.opt_level)
|
||||
.create_target_machine(self.codegen_options.llvm.opt_level)
|
||||
.expect("couldn't create target machine")
|
||||
}
|
||||
}
|
||||
|
@ -908,10 +908,13 @@ impl Nac3 {
|
|||
string_store: Arc::default(),
|
||||
exception_ids: Arc::default(),
|
||||
deferred_eval_store: DeferredEvaluationStore::new(),
|
||||
llvm_options: CodeGenLLVMOptions {
|
||||
codegen_options: CodeGenOptions {
|
||||
use_demo_lib: false,
|
||||
llvm: CodeGenLLVMOptions {
|
||||
opt_level: OptimizationLevel::Default,
|
||||
target: Nac3::get_llvm_target_options(isa),
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -738,7 +738,7 @@ pub fn call_numpy_min<'ctx, G: CodeGenerator + ?Sized>(
|
|||
|
||||
let n = NDArrayValue::from_ptr_val(n, llvm_usize, None);
|
||||
let n_sz = irrt::call_ndarray_calc_size(generator, ctx, &n.dim_sizes());
|
||||
if ctx.registry.llvm_options.opt_level == OptimizationLevel::None {
|
||||
if ctx.registry.codegen_options.llvm.opt_level == OptimizationLevel::None {
|
||||
let n_sz_eqz = ctx.builder
|
||||
.build_int_compare(
|
||||
IntPredicate::NE,
|
||||
|
@ -956,7 +956,7 @@ pub fn call_numpy_max<'ctx, G: CodeGenerator + ?Sized>(
|
|||
|
||||
let n = NDArrayValue::from_ptr_val(n, llvm_usize, None);
|
||||
let n_sz = irrt::call_ndarray_calc_size(generator, ctx, &n.dim_sizes());
|
||||
if ctx.registry.llvm_options.opt_level == OptimizationLevel::None {
|
||||
if ctx.registry.codegen_options.llvm.opt_level == OptimizationLevel::None {
|
||||
let n_sz_eqz = ctx.builder
|
||||
.build_int_compare(
|
||||
IntPredicate::NE,
|
||||
|
|
|
@ -0,0 +1,316 @@
|
|||
use inkwell::attributes::{Attribute, AttributeLoc};
|
||||
use inkwell::values::{BasicValueEnum, CallSiteValue, FloatValue, IntValue, PointerValue};
|
||||
use itertools::Either;
|
||||
|
||||
use crate::codegen::{CodeGenContext, CodeGenerator};
|
||||
|
||||
/// Invokes `dbl_nan` in the demo library.
|
||||
pub fn call_dbl_nan<'ctx>(ctx: &mut CodeGenContext<'ctx, '_>) -> FloatValue<'ctx> {
|
||||
const FN_NAME: &str = "dbl_nan";
|
||||
|
||||
assert!(ctx.registry.codegen_options.use_demo_lib);
|
||||
|
||||
let llvm_f64 = ctx.ctx.f64_type();
|
||||
|
||||
let extern_fn = ctx.module.get_function(FN_NAME).unwrap_or_else(|| {
|
||||
let fn_type = llvm_f64.fn_type(&[], false);
|
||||
let func = ctx.module.add_function(FN_NAME, fn_type, None);
|
||||
for attr in [
|
||||
"mustprogress",
|
||||
"nofree",
|
||||
"norecurse",
|
||||
"nosync",
|
||||
"nounwind",
|
||||
"sspstrong",
|
||||
"willreturn",
|
||||
"readnone",
|
||||
] {
|
||||
func.add_attribute(
|
||||
AttributeLoc::Function,
|
||||
ctx.ctx.create_enum_attribute(Attribute::get_named_enum_kind_id(attr), 0)
|
||||
);
|
||||
}
|
||||
|
||||
func
|
||||
});
|
||||
|
||||
ctx.builder
|
||||
.build_call(extern_fn, &[], "")
|
||||
.map(CallSiteValue::try_as_basic_value)
|
||||
.map(|v| v.map_left(BasicValueEnum::into_float_value))
|
||||
.map(Either::unwrap_left)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
/// Invokes `dbl_inf` in the demo library.
|
||||
pub fn call_dbl_inf<'ctx>(ctx: &mut CodeGenContext<'ctx, '_>) -> FloatValue<'ctx> {
|
||||
const FN_NAME: &str = "dbl_inf";
|
||||
|
||||
assert!(ctx.registry.codegen_options.use_demo_lib);
|
||||
|
||||
let llvm_f64 = ctx.ctx.f64_type();
|
||||
|
||||
let extern_fn = ctx.module.get_function(FN_NAME).unwrap_or_else(|| {
|
||||
let fn_type = llvm_f64.fn_type(&[], false);
|
||||
let func = ctx.module.add_function(FN_NAME, fn_type, None);
|
||||
for attr in [
|
||||
"mustprogress",
|
||||
"nofree",
|
||||
"norecurse",
|
||||
"nosync",
|
||||
"nounwind",
|
||||
"sspstrong",
|
||||
"willreturn",
|
||||
"readnone",
|
||||
] {
|
||||
func.add_attribute(
|
||||
AttributeLoc::Function,
|
||||
ctx.ctx.create_enum_attribute(Attribute::get_named_enum_kind_id(attr), 0)
|
||||
);
|
||||
}
|
||||
|
||||
func
|
||||
});
|
||||
|
||||
ctx.builder
|
||||
.build_call(extern_fn, &[], "")
|
||||
.map(CallSiteValue::try_as_basic_value)
|
||||
.map(|v| v.map_left(BasicValueEnum::into_float_value))
|
||||
.map(Either::unwrap_left)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
/// Invokes `output_bool` in the demo library.
|
||||
pub fn call_output_bool<'ctx>(ctx: &mut CodeGenContext<'ctx, '_>, value: IntValue<'ctx>) {
|
||||
const FN_NAME: &str = "output_bool";
|
||||
|
||||
if ctx.registry.codegen_options.use_demo_lib {
|
||||
let llvm_void = ctx.ctx.void_type();
|
||||
let llvm_i1 = ctx.ctx.bool_type();
|
||||
|
||||
debug_assert_eq!(value.get_type().get_bit_width(), llvm_i1.get_bit_width());
|
||||
|
||||
let extern_fn = ctx.module.get_function(FN_NAME).unwrap_or_else(|| {
|
||||
let fn_type = llvm_void.fn_type(&[llvm_i1.into()], false);
|
||||
let func = ctx.module.add_function(FN_NAME, fn_type, None);
|
||||
for attr in [
|
||||
"nofree",
|
||||
"nounwind",
|
||||
"sspstrong",
|
||||
] {
|
||||
func.add_attribute(
|
||||
AttributeLoc::Function,
|
||||
ctx.ctx.create_enum_attribute(Attribute::get_named_enum_kind_id(attr), 0)
|
||||
);
|
||||
}
|
||||
|
||||
func
|
||||
});
|
||||
|
||||
ctx.builder
|
||||
.build_call(extern_fn, &[value.into()], "")
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
/// Invokes `output_int32` in the demo library.
|
||||
pub fn call_output_int32<'ctx>(ctx: &mut CodeGenContext<'ctx, '_>, value: IntValue<'ctx>) {
|
||||
const FN_NAME: &str = "output_int32";
|
||||
|
||||
if ctx.registry.codegen_options.use_demo_lib {
|
||||
let llvm_void = ctx.ctx.void_type();
|
||||
let llvm_i32 = ctx.ctx.i32_type();
|
||||
|
||||
debug_assert_eq!(value.get_type().get_bit_width(), llvm_i32.get_bit_width());
|
||||
|
||||
let extern_fn = ctx.module.get_function(FN_NAME).unwrap_or_else(|| {
|
||||
let fn_type = llvm_void.fn_type(&[llvm_i32.into()], false);
|
||||
let func = ctx.module.add_function(FN_NAME, fn_type, None);
|
||||
for attr in [
|
||||
"nofree",
|
||||
"nounwind",
|
||||
"sspstrong",
|
||||
] {
|
||||
func.add_attribute(
|
||||
AttributeLoc::Function,
|
||||
ctx.ctx.create_enum_attribute(Attribute::get_named_enum_kind_id(attr), 0)
|
||||
);
|
||||
}
|
||||
|
||||
func
|
||||
});
|
||||
|
||||
ctx.builder
|
||||
.build_call(extern_fn, &[value.into()], "")
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
/// Invokes `output_int64` in the demo library.
|
||||
pub fn call_output_int64<'ctx>(ctx: &mut CodeGenContext<'ctx, '_>, value: IntValue<'ctx>) {
|
||||
const FN_NAME: &str = "output_int64";
|
||||
|
||||
if ctx.registry.codegen_options.use_demo_lib {
|
||||
let llvm_void = ctx.ctx.void_type();
|
||||
let llvm_i64 = ctx.ctx.i64_type();
|
||||
|
||||
debug_assert_eq!(value.get_type().get_bit_width(), llvm_i64.get_bit_width());
|
||||
|
||||
let extern_fn = ctx.module.get_function(FN_NAME).unwrap_or_else(|| {
|
||||
let fn_type = llvm_void.fn_type(&[llvm_i64.into()], false);
|
||||
let func = ctx.module.add_function(FN_NAME, fn_type, None);
|
||||
for attr in [
|
||||
"nofree",
|
||||
"nounwind",
|
||||
"sspstrong",
|
||||
] {
|
||||
func.add_attribute(
|
||||
AttributeLoc::Function,
|
||||
ctx.ctx.create_enum_attribute(Attribute::get_named_enum_kind_id(attr), 0)
|
||||
);
|
||||
}
|
||||
|
||||
func
|
||||
});
|
||||
|
||||
ctx.builder
|
||||
.build_call(extern_fn, &[value.into()], "")
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
/// Invokes `output_uint32` in the demo library.
|
||||
pub fn call_output_uint32<'ctx>(ctx: &mut CodeGenContext<'ctx, '_>, value: IntValue<'ctx>) {
|
||||
const FN_NAME: &str = "output_uint32";
|
||||
|
||||
if ctx.registry.codegen_options.use_demo_lib {
|
||||
let llvm_void = ctx.ctx.void_type();
|
||||
let llvm_i32 = ctx.ctx.i32_type();
|
||||
|
||||
debug_assert_eq!(value.get_type().get_bit_width(), llvm_i32.get_bit_width());
|
||||
|
||||
let extern_fn = ctx.module.get_function(FN_NAME).unwrap_or_else(|| {
|
||||
let fn_type = llvm_void.fn_type(&[llvm_i32.into()], false);
|
||||
let func = ctx.module.add_function(FN_NAME, fn_type, None);
|
||||
for attr in [
|
||||
"nofree",
|
||||
"nounwind",
|
||||
"sspstrong",
|
||||
] {
|
||||
func.add_attribute(
|
||||
AttributeLoc::Function,
|
||||
ctx.ctx.create_enum_attribute(Attribute::get_named_enum_kind_id(attr), 0)
|
||||
);
|
||||
}
|
||||
|
||||
func
|
||||
});
|
||||
|
||||
ctx.builder
|
||||
.build_call(extern_fn, &[value.into()], "")
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
/// Invokes `output_uint64` in the demo library.
|
||||
pub fn call_output_uint64<'ctx>(ctx: &mut CodeGenContext<'ctx, '_>, value: IntValue<'ctx>) {
|
||||
const FN_NAME: &str = "output_uint64";
|
||||
|
||||
if ctx.registry.codegen_options.use_demo_lib {
|
||||
let llvm_void = ctx.ctx.void_type();
|
||||
let llvm_i64 = ctx.ctx.i64_type();
|
||||
|
||||
debug_assert_eq!(value.get_type().get_bit_width(), llvm_i64.get_bit_width());
|
||||
|
||||
let extern_fn = ctx.module.get_function(FN_NAME).unwrap_or_else(|| {
|
||||
let fn_type = llvm_void.fn_type(&[llvm_i64.into()], false);
|
||||
let func = ctx.module.add_function(FN_NAME, fn_type, None);
|
||||
for attr in [
|
||||
"nofree",
|
||||
"nounwind",
|
||||
"sspstrong",
|
||||
] {
|
||||
func.add_attribute(
|
||||
AttributeLoc::Function,
|
||||
ctx.ctx.create_enum_attribute(Attribute::get_named_enum_kind_id(attr), 0)
|
||||
);
|
||||
}
|
||||
|
||||
func
|
||||
});
|
||||
|
||||
ctx.builder
|
||||
.build_call(extern_fn, &[value.into()], "")
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
/// Invokes `output_float64` in the demo library.
|
||||
pub fn call_output_float64<'ctx>(ctx: &mut CodeGenContext<'ctx, '_>, value: FloatValue<'ctx>) {
|
||||
const FN_NAME: &str = "output_float64";
|
||||
|
||||
if ctx.registry.codegen_options.use_demo_lib {
|
||||
let llvm_void = ctx.ctx.void_type();
|
||||
let llvm_f64 = ctx.ctx.f64_type();
|
||||
|
||||
debug_assert_eq!(value.get_type(), llvm_f64);
|
||||
|
||||
let extern_fn = ctx.module.get_function(FN_NAME).unwrap_or_else(|| {
|
||||
let fn_type = llvm_void.fn_type(&[llvm_f64.into()], false);
|
||||
let func = ctx.module.add_function(FN_NAME, fn_type, None);
|
||||
for attr in [
|
||||
"nofree",
|
||||
"nounwind",
|
||||
"sspstrong",
|
||||
] {
|
||||
func.add_attribute(
|
||||
AttributeLoc::Function,
|
||||
ctx.ctx.create_enum_attribute(Attribute::get_named_enum_kind_id(attr), 0)
|
||||
);
|
||||
}
|
||||
|
||||
func
|
||||
});
|
||||
|
||||
ctx.builder
|
||||
.build_call(extern_fn, &[value.into()], "")
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
/// Invokes `output_str` in the demo library.
|
||||
pub fn call_output_str<'ctx>(
|
||||
generator: &mut dyn CodeGenerator,
|
||||
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||
value: PointerValue<'ctx>,
|
||||
) {
|
||||
const FN_NAME: &str = "output_str";
|
||||
|
||||
if ctx.registry.codegen_options.use_demo_lib {
|
||||
let llvm_void = ctx.ctx.void_type();
|
||||
let llvm_str = ctx.get_llvm_type(generator, ctx.primitives.str).into_pointer_type();
|
||||
|
||||
debug_assert_eq!(value.get_type(), llvm_str);
|
||||
|
||||
let extern_fn = ctx.module.get_function(FN_NAME).unwrap_or_else(|| {
|
||||
let fn_type = llvm_void.fn_type(&[llvm_str.into()], false);
|
||||
let func = ctx.module.add_function(FN_NAME, fn_type, None);
|
||||
for attr in [
|
||||
"nofree",
|
||||
"nounwind",
|
||||
"sspstrong",
|
||||
] {
|
||||
func.add_attribute(
|
||||
AttributeLoc::Function,
|
||||
ctx.ctx.create_enum_attribute(Attribute::get_named_enum_kind_id(attr), 0)
|
||||
);
|
||||
}
|
||||
|
||||
func
|
||||
});
|
||||
|
||||
ctx.builder
|
||||
.build_call(extern_fn, &[value.into()], "")
|
||||
.unwrap();
|
||||
}
|
||||
}
|
|
@ -42,6 +42,7 @@ use std::thread;
|
|||
pub mod builtin_fns;
|
||||
pub mod classes;
|
||||
pub mod concrete_type;
|
||||
pub mod demo_fns;
|
||||
pub mod expr;
|
||||
pub mod extern_fns;
|
||||
mod generator;
|
||||
|
@ -64,6 +65,16 @@ pub struct StaticValueStore {
|
|||
|
||||
pub type VarValue<'ctx> = (PointerValue<'ctx>, Option<Arc<dyn StaticValue + Send + Sync>>, i64);
|
||||
|
||||
/// Additional options for codegen.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct CodeGenOptions {
|
||||
/// Whether to use the demo library during codegen.
|
||||
pub use_demo_lib: bool,
|
||||
|
||||
/// Options related to LLVM codegen.
|
||||
pub llvm: CodeGenLLVMOptions,
|
||||
}
|
||||
|
||||
/// Additional options for LLVM during codegen.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct CodeGenLLVMOptions {
|
||||
|
@ -245,8 +256,8 @@ pub struct WorkerRegistry {
|
|||
top_level_ctx: Arc<TopLevelContext>,
|
||||
static_value_store: Arc<Mutex<StaticValueStore>>,
|
||||
|
||||
/// LLVM-related options for code generation.
|
||||
pub llvm_options: CodeGenLLVMOptions,
|
||||
/// Code generation options.
|
||||
pub codegen_options: CodeGenOptions,
|
||||
}
|
||||
|
||||
impl WorkerRegistry {
|
||||
|
@ -256,7 +267,7 @@ impl WorkerRegistry {
|
|||
pub fn create_workers<G: CodeGenerator + Send + 'static>(
|
||||
generators: Vec<Box<G>>,
|
||||
top_level_ctx: Arc<TopLevelContext>,
|
||||
llvm_options: &CodeGenLLVMOptions,
|
||||
codegen_options: &CodeGenOptions,
|
||||
f: &Arc<WithCall>,
|
||||
) -> (Arc<WorkerRegistry>, Vec<thread::JoinHandle<()>>) {
|
||||
let (sender, receiver) = unbounded();
|
||||
|
@ -277,7 +288,7 @@ impl WorkerRegistry {
|
|||
task_count,
|
||||
wait_condvar,
|
||||
top_level_ctx,
|
||||
llvm_options: llvm_options.clone(),
|
||||
codegen_options: codegen_options.clone(),
|
||||
});
|
||||
|
||||
let mut handles = Vec::new();
|
||||
|
@ -382,11 +393,12 @@ impl WorkerRegistry {
|
|||
|
||||
let pass_options = PassBuilderOptions::create();
|
||||
let target_machine = self
|
||||
.llvm_options
|
||||
.codegen_options
|
||||
.llvm
|
||||
.target
|
||||
.create_target_machine(self.llvm_options.opt_level)
|
||||
.unwrap_or_else(|| panic!("could not create target machine from properties {:?}", self.llvm_options.target));
|
||||
let passes = format!("default<O{}>", self.llvm_options.opt_level as u32);
|
||||
.create_target_machine(self.codegen_options.llvm.opt_level)
|
||||
.unwrap_or_else(|| panic!("could not create target machine from properties {:?}", self.codegen_options.llvm.target));
|
||||
let passes = format!("default<O{}>", self.codegen_options.llvm.opt_level as u32);
|
||||
let result = module.run_passes(passes.as_str(), &target_machine, pass_options);
|
||||
if let Err(err) = result {
|
||||
panic!("Failed to run optimization for module `{}`: {}",
|
||||
|
@ -828,7 +840,7 @@ pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenConte
|
|||
),
|
||||
/* directory */ "",
|
||||
/* producer */ "NAC3",
|
||||
/* is_optimized */ registry.llvm_options.opt_level != OptimizationLevel::None,
|
||||
/* is_optimized */ registry.codegen_options.llvm.opt_level != OptimizationLevel::None,
|
||||
/* compiler command line flags */ "",
|
||||
/* runtime_ver */ 0,
|
||||
/* split_name */ "",
|
||||
|
@ -863,7 +875,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 */ registry.llvm_options.opt_level != OptimizationLevel::None,
|
||||
/* is_optimized */ registry.codegen_options.llvm.opt_level != OptimizationLevel::None,
|
||||
);
|
||||
fn_val.set_subprogram(func_scope);
|
||||
|
||||
|
|
|
@ -937,7 +937,7 @@ pub fn ndarray_matmul_2d<'ctx, G: CodeGenerator>(
|
|||
}
|
||||
}
|
||||
|
||||
if ctx.registry.llvm_options.opt_level == OptimizationLevel::None {
|
||||
if ctx.registry.codegen_options.llvm.opt_level == OptimizationLevel::None {
|
||||
let lhs_dim1 = unsafe {
|
||||
lhs.dim_sizes().get_typed_unchecked(ctx, generator, &llvm_usize.const_int(1, false), None)
|
||||
};
|
||||
|
|
|
@ -12,7 +12,7 @@ use std::collections::HashSet;
|
|||
|
||||
use nac3core::{
|
||||
codegen::{
|
||||
concrete_type::ConcreteTypeStore, irrt::load_irrt, CodeGenLLVMOptions,
|
||||
concrete_type::ConcreteTypeStore, irrt::load_irrt, CodeGenLLVMOptions, CodeGenOptions,
|
||||
CodeGenTargetMachineOptions, CodeGenTask, DefaultCodeGenerator, WithCall, WorkerRegistry,
|
||||
},
|
||||
symbol_resolver::SymbolResolver,
|
||||
|
@ -68,6 +68,11 @@ struct CommandLineArgs {
|
|||
/// Additional target features to enable/disable, specified using the `+`/`-` prefixes.
|
||||
#[arg(long)]
|
||||
target_features: Option<String>,
|
||||
|
||||
/// Enables the demo library for use in compiled executables. This requires `demo.o` to be
|
||||
/// present when linking the executable.
|
||||
#[arg(long, default_value_t = false)]
|
||||
fuse_demo_lib: bool,
|
||||
}
|
||||
|
||||
fn handle_typevar_definition(
|
||||
|
@ -258,6 +263,7 @@ fn main() {
|
|||
triple,
|
||||
mcpu,
|
||||
target_features,
|
||||
fuse_demo_lib,
|
||||
} = cli;
|
||||
|
||||
Target::initialize_all(&InitializationConfig::default());
|
||||
|
@ -371,7 +377,9 @@ fn main() {
|
|||
instance_to_stmt[""].clone()
|
||||
};
|
||||
|
||||
let llvm_options = CodeGenLLVMOptions {
|
||||
let codegen_options = CodeGenOptions {
|
||||
use_demo_lib: fuse_demo_lib,
|
||||
llvm: CodeGenLLVMOptions {
|
||||
opt_level,
|
||||
target: CodeGenTargetMachineOptions {
|
||||
triple,
|
||||
|
@ -380,6 +388,7 @@ fn main() {
|
|||
reloc_mode: RelocMode::PIC,
|
||||
..host_target_machine
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
let task = CodeGenTask {
|
||||
|
@ -405,7 +414,7 @@ fn main() {
|
|||
let threads = (0..threads)
|
||||
.map(|i| Box::new(DefaultCodeGenerator::new(format!("module{i}"), SIZE_T)))
|
||||
.collect();
|
||||
let (registry, handles) = WorkerRegistry::create_workers(threads, top_level, &llvm_options, &f);
|
||||
let (registry, handles) = WorkerRegistry::create_workers(threads, top_level, &codegen_options, &f);
|
||||
registry.add_task(task);
|
||||
registry.wait_tasks_complete(handles);
|
||||
|
||||
|
@ -444,8 +453,8 @@ fn main() {
|
|||
function_iter = func.get_next_function();
|
||||
}
|
||||
|
||||
let target_machine = llvm_options.target
|
||||
.create_target_machine(llvm_options.opt_level)
|
||||
let target_machine = codegen_options.llvm.target
|
||||
.create_target_machine(codegen_options.llvm.opt_level)
|
||||
.expect("couldn't create target machine");
|
||||
|
||||
let pass_options = PassBuilderOptions::create();
|
||||
|
|
Loading…
Reference in New Issue