Compare commits
10 Commits
4996dd7f41
...
47d9f8d5c6
Author | SHA1 | Date |
---|---|---|
|
47d9f8d5c6 | |
|
bc1383e956 | |
|
41ad8a9282 | |
|
bf443d7704 | |
|
960f6c3329 | |
|
35803958ff | |
|
3d5942987b | |
|
e9ef7a2af5 | |
|
2c89ff0687 | |
|
1b6e0e386c |
|
@ -8,7 +8,7 @@ use std::sync::Arc;
|
|||
use inkwell::{
|
||||
memory_buffer::MemoryBuffer,
|
||||
module::{Linkage, Module},
|
||||
passes::{PassManager, PassManagerBuilder},
|
||||
passes::PassBuilderOptions,
|
||||
targets::*,
|
||||
OptimizationLevel,
|
||||
};
|
||||
|
@ -654,12 +654,16 @@ impl Nac3 {
|
|||
global_option = global.get_next_global();
|
||||
}
|
||||
|
||||
let builder = PassManagerBuilder::create();
|
||||
builder.set_optimization_level(OptimizationLevel::Aggressive);
|
||||
let passes = PassManager::create(());
|
||||
builder.set_inliner_with_threshold(255);
|
||||
builder.populate_module_pass_manager(&passes);
|
||||
passes.run_on(&main);
|
||||
let target_machine = self.llvm_options.target
|
||||
.create_target_machine(self.llvm_options.opt_level)
|
||||
.expect("couldn't create target machine");
|
||||
|
||||
let pass_options = PassBuilderOptions::create();
|
||||
pass_options.set_merge_functions(true);
|
||||
let result = main.run_passes("default<O3>", &target_machine, pass_options);
|
||||
if let Err(err) = result {
|
||||
panic!("Failed to run optimization for module `main`: {}", err.to_string());
|
||||
}
|
||||
|
||||
link_fn(&main)
|
||||
}
|
||||
|
|
|
@ -59,6 +59,8 @@ pub fn get_subst_key(
|
|||
}
|
||||
|
||||
impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
||||
/// Builds a sequence of `getelementptr` and `load` instructions which stores the value of a
|
||||
/// struct field into an LLVM value.
|
||||
pub fn build_gep_and_load(
|
||||
&mut self,
|
||||
ptr: PointerValue<'ctx>,
|
||||
|
@ -196,6 +198,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
|||
)
|
||||
}
|
||||
|
||||
/// Generates an LLVM variable for a [constant value][value] with a given [type][ty].
|
||||
pub fn gen_const(
|
||||
&mut self,
|
||||
generator: &mut dyn CodeGenerator,
|
||||
|
@ -257,6 +260,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Generates a binary operation `op` between two integral operands `lhs` and `rhs`.
|
||||
pub fn gen_int_ops(
|
||||
&mut self,
|
||||
generator: &mut dyn CodeGenerator,
|
||||
|
@ -301,6 +305,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Generates a binary operation `op` between two floating-point operands `lhs` and `rhs`.
|
||||
pub fn gen_float_ops(
|
||||
&mut self,
|
||||
op: &Operator,
|
||||
|
@ -423,6 +428,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Helper function for generating a LLVM variable storing a [String].
|
||||
pub fn gen_string<S: Into<String>>(
|
||||
&mut self,
|
||||
generator: &mut dyn CodeGenerator,
|
||||
|
@ -522,6 +528,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// See [CodeGenerator::gen_constructor].
|
||||
pub fn gen_constructor<'ctx, 'a, G: CodeGenerator>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -553,6 +560,7 @@ pub fn gen_constructor<'ctx, 'a, G: CodeGenerator>(
|
|||
}
|
||||
}
|
||||
|
||||
/// See [CodeGenerator::gen_func_instance].
|
||||
pub fn gen_func_instance<'ctx, 'a>(
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
obj: Option<(Type, ValueEnum<'ctx>)>,
|
||||
|
@ -629,6 +637,7 @@ pub fn gen_func_instance<'ctx, 'a>(
|
|||
}
|
||||
}
|
||||
|
||||
/// See [CodeGenerator::gen_call].
|
||||
pub fn gen_call<'ctx, 'a, G: CodeGenerator>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -788,6 +797,8 @@ pub fn gen_call<'ctx, 'a, G: CodeGenerator>(
|
|||
Ok(ctx.build_call_or_invoke(fun_val, ¶m_vals, "call"))
|
||||
}
|
||||
|
||||
/// Generates three LLVM variables representing the start, stop, and step values of a [range] class
|
||||
/// respectively.
|
||||
pub fn destructure_range<'ctx, 'a>(
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
range: PointerValue<'ctx>,
|
||||
|
@ -805,7 +816,8 @@ pub fn destructure_range<'ctx, 'a>(
|
|||
(start, end, step)
|
||||
}
|
||||
|
||||
/// Allocates a List structure with the given [type][ty] and [length].
|
||||
/// Allocates a List structure with the given [type][ty] and [length]. The name of the resulting
|
||||
/// LLVM value is `{name}.addr`, or `list.addr` if [name] is not specified.
|
||||
///
|
||||
/// Returns an instance of [PointerValue] pointing to the List structure. The List structure is
|
||||
/// defined as `type { ty*, size_t }` in LLVM, where the first element stores the pointer to the
|
||||
|
@ -855,6 +867,7 @@ pub fn allocate_list<'ctx, 'a, G: CodeGenerator>(
|
|||
arr_str_ptr
|
||||
}
|
||||
|
||||
/// Generates LLVM IR for a [list comprehension expression][expr].
|
||||
pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -1024,6 +1037,13 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>(
|
|||
}
|
||||
}
|
||||
|
||||
/// Generates LLVM IR for a [binary operator expression][expr].
|
||||
///
|
||||
/// * `left` - The left-hand side of the binary operator.
|
||||
/// * `op` - The operator applied on the operands.
|
||||
/// * `right` - The right-hand side of the binary operator.
|
||||
/// * `loc` - The location of the full expression.
|
||||
/// * `is_aug_assign` - Whether the binary operator expression is also an assignment operator.
|
||||
pub fn gen_binop_expr<'ctx, 'a, G: CodeGenerator>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -1120,6 +1140,7 @@ pub fn gen_binop_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
}
|
||||
}
|
||||
|
||||
/// See [CodeGenerator::gen_expr].
|
||||
pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -1191,7 +1212,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
elements[0].get_type()
|
||||
};
|
||||
let length = generator.get_size_type(ctx.ctx).const_int(elements.len() as u64, false);
|
||||
let arr_str_ptr = allocate_list(generator, ctx, ty, length, Some("list.addr"));
|
||||
let arr_str_ptr = allocate_list(generator, ctx, ty, length, Some("list"));
|
||||
let arr_ptr = ctx.build_gep_and_load(arr_str_ptr, &[zero, zero], Some("list.ptr.addr"))
|
||||
.into_pointer_value();
|
||||
unsafe {
|
||||
|
@ -1631,7 +1652,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
.into_int_value(),
|
||||
step,
|
||||
);
|
||||
let res_array_ret = allocate_list(generator, ctx, ty, length, Some("ret.addr"));
|
||||
let res_array_ret = allocate_list(generator, ctx, ty, length, Some("ret"));
|
||||
let res_ind =
|
||||
handle_slice_indices(&None, &None, &None, ctx, generator, res_array_ret)?;
|
||||
list_slice_assignment(
|
||||
|
|
|
@ -181,7 +181,7 @@ pub trait CodeGenerator {
|
|||
gen_stmt(self, ctx, stmt)
|
||||
}
|
||||
|
||||
/// Converts the value of [a boolean-like value][bool_value] into an `i1`.
|
||||
/// See [bool_to_i1].
|
||||
fn bool_to_i1<'ctx, 'a>(
|
||||
&self,
|
||||
ctx: &CodeGenContext<'ctx, 'a>,
|
||||
|
@ -190,7 +190,7 @@ pub trait CodeGenerator {
|
|||
bool_to_i1(&ctx.builder, bool_value)
|
||||
}
|
||||
|
||||
/// Converts the value of [a boolean-like value][bool_value] into an `i8`.
|
||||
/// See [bool_to_i8].
|
||||
fn bool_to_i8<'ctx, 'a>(
|
||||
&self,
|
||||
ctx: &CodeGenContext<'ctx, 'a>,
|
||||
|
|
|
@ -16,7 +16,7 @@ use inkwell::{
|
|||
builder::Builder,
|
||||
context::Context,
|
||||
module::Module,
|
||||
passes::{PassManager, PassManagerBuilder},
|
||||
passes::PassBuilderOptions,
|
||||
targets::{CodeModel, RelocMode, Target, TargetMachine, TargetTriple},
|
||||
types::{AnyType, BasicType, BasicTypeEnum},
|
||||
values::{BasicValueEnum, FunctionValue, IntValue, PhiValue, PointerValue},
|
||||
|
@ -33,7 +33,6 @@ use std::sync::{
|
|||
Arc,
|
||||
};
|
||||
use std::thread;
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
pub mod concrete_type;
|
||||
pub mod expr;
|
||||
|
@ -55,12 +54,6 @@ pub struct StaticValueStore {
|
|||
|
||||
pub type VarValue<'ctx> = (PointerValue<'ctx>, Option<Arc<dyn StaticValue + Send + Sync>>, i64);
|
||||
|
||||
lazy_static!(
|
||||
// HACK: The Mutex is a work-around for issue
|
||||
// https://git.m-labs.hk/M-Labs/nac3/issues/275
|
||||
static ref PASSES_INIT_LOCK: Mutex<AtomicBool> = Mutex::new(AtomicBool::new(true));
|
||||
);
|
||||
|
||||
/// Additional options for LLVM during codegen.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct CodeGenLLVMOptions {
|
||||
|
@ -303,23 +296,11 @@ 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(self.llvm_options.opt_level);
|
||||
pass_builder.populate_function_pass_manager(&passes);
|
||||
}
|
||||
|
||||
let mut errors = HashSet::new();
|
||||
while let Some(task) = self.receiver.recv().unwrap() {
|
||||
match gen_func(&context, generator, self, builder, module, task) {
|
||||
Ok(result) => {
|
||||
builder = result.0;
|
||||
passes.run_on(&result.2);
|
||||
module = result.1;
|
||||
}
|
||||
Err((old_builder, e)) => {
|
||||
|
@ -342,6 +323,19 @@ impl WorkerRegistry {
|
|||
panic!("{}", err.to_string())
|
||||
}
|
||||
|
||||
let pass_options = PassBuilderOptions::create();
|
||||
let target_machine = self.llvm_options.target.create_target_machine(
|
||||
self.llvm_options.opt_level
|
||||
).expect(format!("could not create target machine from properties {:?}", self.llvm_options.target).as_str());
|
||||
let passes = format!("default<O{}>", self.llvm_options.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 `{}`: {}",
|
||||
module.get_name().to_str().unwrap(),
|
||||
err.to_string());
|
||||
}
|
||||
|
||||
f.run(&module);
|
||||
let mut lock = self.task_count.lock();
|
||||
*lock += 1;
|
||||
|
@ -363,7 +357,7 @@ pub struct CodeGenTask {
|
|||
|
||||
/// Retrieves the [LLVM type][BasicTypeEnum] corresponding to the [Type].
|
||||
///
|
||||
/// This function is used to obtain the in-memory representation of [ty], e.g. a `bool` variable
|
||||
/// This function is used to obtain the in-memory representation of `ty`, e.g. a `bool` variable
|
||||
/// would be represented by an `i8`.
|
||||
fn get_llvm_type<'ctx>(
|
||||
ctx: &'ctx Context,
|
||||
|
@ -478,7 +472,7 @@ fn get_llvm_type<'ctx>(
|
|||
|
||||
/// Retrieves the [LLVM type][BasicTypeEnum] corresponding to the [Type].
|
||||
///
|
||||
/// This function is used mainly to obtain the ABI representation of [ty], e.g. a `bool` is
|
||||
/// This function is used mainly to obtain the ABI representation of `ty`, e.g. a `bool` is
|
||||
/// would be represented by an `i1`.
|
||||
///
|
||||
/// The difference between the in-memory representation (as returned by [get_llvm_type]) and the
|
||||
|
@ -517,6 +511,7 @@ fn need_sret<'ctx>(ctx: &'ctx Context, ty: BasicTypeEnum<'ctx>) -> bool {
|
|||
need_sret_impl(ctx, ty, true)
|
||||
}
|
||||
|
||||
/// Implementation for generating LLVM IR for a function.
|
||||
pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenContext) -> Result<(), String>> (
|
||||
context: &'ctx Context,
|
||||
generator: &mut G,
|
||||
|
@ -841,6 +836,15 @@ pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenConte
|
|||
Ok((builder, module, fn_val))
|
||||
}
|
||||
|
||||
/// Generates LLVM IR for a function.
|
||||
///
|
||||
/// * `context` - The [LLVM Context][Context] used in generating the function body.
|
||||
/// * `generator` - The [CodeGenerator] for generating various program constructs.
|
||||
/// * `registry` - The [WorkerRegistry] responsible for monitoring this function generation task.
|
||||
/// * `builder` - The [Builder] used for generating LLVM IR.
|
||||
/// * `module` - The [Module] of which the generated LLVM function will be inserted into.
|
||||
/// * `task` - The [CodeGenTask] associated with this function generation task.
|
||||
///
|
||||
pub fn gen_func<'ctx, G: CodeGenerator>(
|
||||
context: &'ctx Context,
|
||||
generator: &mut G,
|
||||
|
@ -858,7 +862,7 @@ pub fn gen_func<'ctx, G: CodeGenerator>(
|
|||
})
|
||||
}
|
||||
|
||||
/// Converts the value of [a boolean-like value][bool_value] into an `i1`.
|
||||
/// Converts the value of a boolean-like value `bool_value` into an `i1`.
|
||||
fn bool_to_i1<'ctx>(builder: &Builder<'ctx>, bool_value: IntValue<'ctx>) -> IntValue<'ctx> {
|
||||
if bool_value.get_type().get_bit_width() != 1 {
|
||||
builder.build_int_compare(
|
||||
|
@ -872,7 +876,7 @@ fn bool_to_i1<'ctx>(builder: &Builder<'ctx>, bool_value: IntValue<'ctx>) -> IntV
|
|||
}
|
||||
}
|
||||
|
||||
/// Converts the value of [a boolean-like value][bool_value] into an `i8`.
|
||||
/// Converts the value of a boolean-like value `bool_value` into an `i8`.
|
||||
fn bool_to_i8<'ctx>(
|
||||
builder: &Builder<'ctx>,
|
||||
ctx: &'ctx Context,
|
||||
|
|
|
@ -21,6 +21,7 @@ use nac3parser::ast::{
|
|||
};
|
||||
use std::convert::TryFrom;
|
||||
|
||||
/// See [CodeGenerator::gen_var_alloc].
|
||||
pub fn gen_var<'ctx, 'a>(
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
ty: BasicTypeEnum<'ctx>,
|
||||
|
@ -35,6 +36,7 @@ pub fn gen_var<'ctx, 'a>(
|
|||
Ok(ptr)
|
||||
}
|
||||
|
||||
/// See [CodeGenerator::gen_store_target].
|
||||
pub fn gen_store_target<'ctx, 'a, G: CodeGenerator>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -144,6 +146,7 @@ pub fn gen_store_target<'ctx, 'a, G: CodeGenerator>(
|
|||
})
|
||||
}
|
||||
|
||||
/// See [CodeGenerator::gen_assign].
|
||||
pub fn gen_assign<'ctx, 'a, G: CodeGenerator>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -214,13 +217,21 @@ pub fn gen_assign<'ctx, 'a, G: CodeGenerator>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Generates a sequence of IR which checks whether [value] does not exceed the upper bound of the
|
||||
/// range as defined by [stop] and [step].
|
||||
/// Generates a sequence of IR which checks whether `value` does not exceed the upper bound of the
|
||||
/// range as defined by `stop` and `step`.
|
||||
///
|
||||
/// Note that the generated IR will **not** check whether value is part of the range or whether
|
||||
/// value exceeds the lower bound of the range (as evident by the missing `start` argument).
|
||||
///
|
||||
/// Returns an [IntValue] representing the result of whether the [value] is in the range.
|
||||
/// The generated IR is equivalent to the following Rust code:
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// let sign = step > 0;
|
||||
/// let (lo, hi) = if sign { (value, stop) } else { (stop, value) };
|
||||
/// let cmp = lo < hi;
|
||||
/// ```
|
||||
///
|
||||
/// Returns an `i1` [IntValue] representing the result of whether the `value` is in the range.
|
||||
fn gen_in_range_check<'ctx, 'a>(
|
||||
ctx: &CodeGenContext<'ctx, 'a>,
|
||||
value: IntValue<'ctx>,
|
||||
|
@ -234,6 +245,7 @@ fn gen_in_range_check<'ctx, 'a>(
|
|||
ctx.builder.build_int_compare(IntPredicate::SLT, lo, hi, "cmp")
|
||||
}
|
||||
|
||||
/// See [CodeGenerator::gen_for].
|
||||
pub fn gen_for<'ctx, 'a, G: CodeGenerator>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -384,6 +396,7 @@ pub fn gen_for<'ctx, 'a, G: CodeGenerator>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// See [CodeGenerator::gen_while].
|
||||
pub fn gen_while<'ctx, 'a, G: CodeGenerator>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -447,6 +460,7 @@ pub fn gen_while<'ctx, 'a, G: CodeGenerator>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// See [CodeGenerator::gen_if].
|
||||
pub fn gen_if<'ctx, 'a, G: CodeGenerator>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -535,6 +549,8 @@ pub fn final_proxy<'ctx, 'a>(
|
|||
final_paths.push(block);
|
||||
}
|
||||
|
||||
/// Inserts the declaration of the builtin function with the specified `symbol` name, and returns
|
||||
/// the function.
|
||||
pub fn get_builtins<'ctx, 'a>(
|
||||
generator: &mut dyn CodeGenerator,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -632,6 +648,10 @@ pub fn exn_constructor<'ctx, 'a>(
|
|||
Ok(Some(zelf.into()))
|
||||
}
|
||||
|
||||
/// Generates IR for a `raise` statement.
|
||||
///
|
||||
/// * `exception` - The exception thrown by the `raise` statement.
|
||||
/// * `loc` - The location where the exception is raised from.
|
||||
pub fn gen_raise<'ctx, 'a>(
|
||||
generator: &mut dyn CodeGenerator,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -683,6 +703,7 @@ pub fn gen_raise<'ctx, 'a>(
|
|||
ctx.builder.build_unreachable();
|
||||
}
|
||||
|
||||
/// Generates IR for a `try` statement.
|
||||
pub fn gen_try<'ctx, 'a, G: CodeGenerator>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -1005,6 +1026,7 @@ pub fn gen_try<'ctx, 'a, G: CodeGenerator>(
|
|||
}
|
||||
}
|
||||
|
||||
/// See [CodeGenerator::gen_with].
|
||||
pub fn gen_with<'ctx, 'a, G: CodeGenerator>(
|
||||
_: &mut G,
|
||||
_: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -1014,6 +1036,7 @@ pub fn gen_with<'ctx, 'a, G: CodeGenerator>(
|
|||
Err(format!("With statement with custom types is not yet supported (at {})", stmt.location))
|
||||
}
|
||||
|
||||
/// Generates IR for a `return` statement.
|
||||
pub fn gen_return<'ctx, 'a, G: CodeGenerator>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -1062,6 +1085,7 @@ pub fn gen_return<'ctx, 'a, G: CodeGenerator>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// See [CodeGenerator::gen_stmt].
|
||||
pub fn gen_stmt<'ctx, 'a, G: CodeGenerator>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -1153,6 +1177,7 @@ pub fn gen_stmt<'ctx, 'a, G: CodeGenerator>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Generates IR for a block statement contains `stmts`.
|
||||
pub fn gen_block<'ctx, 'a, 'b, G: CodeGenerator, I: Iterator<Item = &'b Stmt<Option<Type>>>>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
|
|
@ -59,6 +59,7 @@ impl Display for SymbolValue {
|
|||
}
|
||||
|
||||
pub trait StaticValue {
|
||||
/// Returns a unique identifier for this value.
|
||||
fn get_unique_identifier(&self) -> u64;
|
||||
|
||||
fn get_const_obj<'ctx, 'a>(
|
||||
|
@ -67,6 +68,7 @@ pub trait StaticValue {
|
|||
generator: &mut dyn CodeGenerator,
|
||||
) -> BasicValueEnum<'ctx>;
|
||||
|
||||
/// Converts this value to a LLVM [BasicValueEnum].
|
||||
fn to_basic_value_enum<'ctx, 'a>(
|
||||
&self,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -74,12 +76,14 @@ pub trait StaticValue {
|
|||
expected_ty: Type,
|
||||
) -> Result<BasicValueEnum<'ctx>, String>;
|
||||
|
||||
/// Returns a field within this value.
|
||||
fn get_field<'ctx, 'a>(
|
||||
&self,
|
||||
name: StrRef,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
) -> Option<ValueEnum<'ctx>>;
|
||||
|
||||
/// Returns a single element of this tuple.
|
||||
fn get_tuple_element<'ctx>(&self, index: u32) -> Option<ValueEnum<'ctx>>;
|
||||
}
|
||||
|
||||
|
|
|
@ -79,12 +79,12 @@ pub extern "C" fn __nac3_personality(_state: u32, _exception_object: u32, _conte
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn __nac3_raise(_state: u32, _exception_object: u32, _context: u32) -> u32 {
|
||||
pub extern "C" fn __nac3_raise(state: u32, exception_object: u32, context: u32) -> u32 {
|
||||
writeln!(io::stderr(),
|
||||
"__nac3_raise(state: {:#010x}, _exception_object: {:#010x}, _context: {:#010x})",
|
||||
_state,
|
||||
_exception_object,
|
||||
_context
|
||||
state,
|
||||
exception_object,
|
||||
context
|
||||
).unwrap();
|
||||
exit(101);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use clap::Parser;
|
||||
use inkwell::{
|
||||
memory_buffer::MemoryBuffer,
|
||||
passes::{PassManager, PassManagerBuilder},
|
||||
passes::PassBuilderOptions,
|
||||
targets::*,
|
||||
OptimizationLevel,
|
||||
};
|
||||
|
@ -364,16 +364,17 @@ fn main() {
|
|||
function_iter = func.get_next_function();
|
||||
}
|
||||
|
||||
let builder = PassManagerBuilder::create();
|
||||
builder.set_optimization_level(OptimizationLevel::Aggressive);
|
||||
let passes = PassManager::create(());
|
||||
builder.set_inliner_with_threshold(255);
|
||||
builder.populate_module_pass_manager(&passes);
|
||||
passes.run_on(&main);
|
||||
|
||||
let target_machine = llvm_options.target
|
||||
.create_target_machine(llvm_options.opt_level)
|
||||
.expect("couldn't create target machine");
|
||||
|
||||
let pass_options = PassBuilderOptions::create();
|
||||
pass_options.set_merge_functions(true);
|
||||
let result = main.run_passes("default<O3>", &target_machine, pass_options);
|
||||
if let Err(err) = result {
|
||||
panic!("Failed to run optimization for module `main`: {}", err.to_string());
|
||||
}
|
||||
|
||||
target_machine
|
||||
.write_to_file(&main, FileType::Object, Path::new("module.o"))
|
||||
.expect("couldn't write module to file");
|
||||
|
|
Loading…
Reference in New Issue