mirror of
https://github.com/roc-lang/roc.git
synced 2024-09-19 23:07:33 +03:00
commit
7f2a0d6c26
@ -133,10 +133,14 @@ pub fn gen(src: &[u8], target: Triple, opt_level: OptLevel) -> Result<ReplOutput
|
||||
let (module_pass, function_pass) =
|
||||
roc_gen::llvm::build::construct_optimization_passes(module, opt_level);
|
||||
|
||||
let (dibuilder, compile_unit) = roc_gen::llvm::build::Env::new_debug_info(module);
|
||||
|
||||
// Compile and add all the Procs before adding main
|
||||
let env = roc_gen::llvm::build::Env {
|
||||
arena: &arena,
|
||||
builder: &builder,
|
||||
dibuilder: &dibuilder,
|
||||
compile_unit: &compile_unit,
|
||||
context: &context,
|
||||
interns,
|
||||
module,
|
||||
@ -176,6 +180,9 @@ pub fn gen(src: &[u8], target: Triple, opt_level: OptLevel) -> Result<ReplOutput
|
||||
|
||||
build_proc(&env, &mut layout_ids, scope.clone(), proc, fn_val);
|
||||
|
||||
// call finalize() before any code generation/verification
|
||||
env.dibuilder.finalize();
|
||||
|
||||
if fn_val.verify(true) {
|
||||
function_pass.run_on(&fn_val);
|
||||
} else {
|
||||
@ -208,6 +215,8 @@ pub fn gen(src: &[u8], target: Triple, opt_level: OptLevel) -> Result<ReplOutput
|
||||
&main_fn_layout,
|
||||
);
|
||||
|
||||
env.dibuilder.finalize();
|
||||
|
||||
// Uncomment this to see the module's un-optimized LLVM instruction output:
|
||||
// env.module.print_to_stderr();
|
||||
|
||||
|
@ -66,7 +66,12 @@ pub fn gen_from_mono_module(
|
||||
|
||||
let context = Context::create();
|
||||
let module = arena.alloc(module_from_builtins(&context, "app"));
|
||||
|
||||
// strip Zig debug stuff
|
||||
// module.strip_debug_info();
|
||||
|
||||
let builder = context.create_builder();
|
||||
let (dibuilder, compile_unit) = roc_gen::llvm::build::Env::new_debug_info(module);
|
||||
let (mpm, fpm) = roc_gen::llvm::build::construct_optimization_passes(module, opt_level);
|
||||
|
||||
let ptr_bytes = target.pointer_width().unwrap().bytes() as u32;
|
||||
@ -75,6 +80,8 @@ pub fn gen_from_mono_module(
|
||||
let env = roc_gen::llvm::build::Env {
|
||||
arena: &arena,
|
||||
builder: &builder,
|
||||
dibuilder: &dibuilder,
|
||||
compile_unit: &compile_unit,
|
||||
context: &context,
|
||||
interns: loaded.interns,
|
||||
module,
|
||||
@ -112,6 +119,9 @@ pub fn gen_from_mono_module(
|
||||
// println!("\n\nBuilding and then verifying function {:?}\n\n", proc);
|
||||
build_proc(&env, &mut layout_ids, scope.clone(), proc, fn_val);
|
||||
|
||||
// call finalize() before any code generation/verification
|
||||
env.dibuilder.finalize();
|
||||
|
||||
if fn_val.verify(true) {
|
||||
fpm.run_on(&fn_val);
|
||||
} else {
|
||||
@ -124,6 +134,8 @@ pub fn gen_from_mono_module(
|
||||
}
|
||||
}
|
||||
|
||||
env.dibuilder.finalize();
|
||||
|
||||
// Uncomment this to see the module's optimized LLVM instruction output:
|
||||
// env.module.print_to_stderr();
|
||||
|
||||
|
@ -17,6 +17,7 @@ use bumpalo::Bump;
|
||||
use inkwell::basic_block::BasicBlock;
|
||||
use inkwell::builder::Builder;
|
||||
use inkwell::context::Context;
|
||||
use inkwell::debug_info::{AsDIScope, DICompileUnit, DISubprogram, DebugInfoBuilder};
|
||||
use inkwell::memory_buffer::MemoryBuffer;
|
||||
use inkwell::module::{Linkage, Module};
|
||||
use inkwell::passes::{PassManager, PassManagerBuilder};
|
||||
@ -96,6 +97,8 @@ pub struct Env<'a, 'ctx, 'env> {
|
||||
pub arena: &'a Bump,
|
||||
pub context: &'ctx Context,
|
||||
pub builder: &'env Builder<'ctx>,
|
||||
pub dibuilder: &'env DebugInfoBuilder<'ctx>,
|
||||
pub compile_unit: &'env DICompileUnit<'ctx>,
|
||||
pub module: &'ctx Module<'ctx>,
|
||||
pub interns: Interns,
|
||||
pub ptr_bytes: u32,
|
||||
@ -178,6 +181,61 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> {
|
||||
],
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_debug_info(module: &Module<'ctx>) -> (DebugInfoBuilder<'ctx>, DICompileUnit<'ctx>) {
|
||||
module.create_debug_info_builder(
|
||||
true,
|
||||
/* language */ inkwell::debug_info::DWARFSourceLanguage::C,
|
||||
/* filename */ "roc_app",
|
||||
/* directory */ ".",
|
||||
/* producer */ "my llvm compiler frontend",
|
||||
/* is_optimized */ false,
|
||||
/* compiler command line flags */ "",
|
||||
/* runtime_ver */ 0,
|
||||
/* split_name */ "",
|
||||
/* kind */ inkwell::debug_info::DWARFEmissionKind::Full,
|
||||
/* dwo_id */ 0,
|
||||
/* split_debug_inling */ false,
|
||||
/* debug_info_for_profiling */ false,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_subprogram(&self, function_name: &str) -> DISubprogram<'ctx> {
|
||||
use inkwell::debug_info::DIFlagsConstants;
|
||||
|
||||
let dibuilder = self.dibuilder;
|
||||
let compile_unit = self.compile_unit;
|
||||
|
||||
let ditype = dibuilder
|
||||
.create_basic_type(
|
||||
"type_name",
|
||||
0_u64,
|
||||
0x00,
|
||||
inkwell::debug_info::DIFlags::PUBLIC,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let subroutine_type = dibuilder.create_subroutine_type(
|
||||
compile_unit.get_file(),
|
||||
/* return type */ Some(ditype.as_type()),
|
||||
/* parameter types */ &[],
|
||||
inkwell::debug_info::DIFlags::PUBLIC,
|
||||
);
|
||||
|
||||
dibuilder.create_function(
|
||||
/* scope */ compile_unit.as_debug_info_scope(),
|
||||
/* func name */ function_name,
|
||||
/* linkage_name */ None,
|
||||
/* file */ compile_unit.get_file(),
|
||||
/* line_no */ 0,
|
||||
/* DIType */ subroutine_type,
|
||||
/* is_local_to_unit */ true,
|
||||
/* is_definition */ true,
|
||||
/* scope_line */ 0,
|
||||
/* flags */ inkwell::debug_info::DIFlags::PUBLIC,
|
||||
/* is_optimized */ false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn module_from_builtins<'ctx>(ctx: &'ctx Context, module_name: &str) -> Module<'ctx> {
|
||||
@ -983,21 +1041,20 @@ pub fn allocate_with_refcount<'a, 'ctx, 'env>(
|
||||
let ctx = env.context;
|
||||
|
||||
let value_type = basic_type_from_layout(env.arena, ctx, layout, env.ptr_bytes);
|
||||
let value_bytes = layout.stack_size(env.ptr_bytes) as u64;
|
||||
let value_bytes = layout.stack_size(env.ptr_bytes);
|
||||
|
||||
let len_type = env.ptr_int();
|
||||
// bytes per element
|
||||
let bytes_len = len_type.const_int(value_bytes, false);
|
||||
|
||||
let extra_bytes = layout.alignment_bytes(env.ptr_bytes);
|
||||
let extra_bytes_intvalue = len_type.const_int(extra_bytes as u64, false);
|
||||
|
||||
let ptr = {
|
||||
let len = bytes_len;
|
||||
let len = builder.build_int_add(len, extra_bytes_intvalue, "add_alignment_space");
|
||||
let len = value_bytes as u64 + extra_bytes as u64;
|
||||
|
||||
// bytes per element
|
||||
let bytes_len = len_type.const_int(len, false);
|
||||
|
||||
env.builder
|
||||
.build_array_malloc(ctx.i8_type(), len, "create_ptr")
|
||||
.build_array_malloc(ctx.i8_type(), bytes_len, "create_ptr")
|
||||
.unwrap()
|
||||
|
||||
// TODO check if malloc returned null; if so, runtime error for OOM!
|
||||
@ -1006,15 +1063,33 @@ pub fn allocate_with_refcount<'a, 'ctx, 'env>(
|
||||
// We must return a pointer to the first element:
|
||||
let data_ptr = {
|
||||
let int_type = ptr_int(ctx, env.ptr_bytes);
|
||||
let ptr_as_int = builder.build_ptr_to_int(ptr, int_type, "calculate_data_ptr_pti");
|
||||
let incremented = builder.build_int_add(
|
||||
ptr_as_int,
|
||||
extra_bytes_intvalue,
|
||||
"calculate_data_ptr_increment",
|
||||
);
|
||||
let as_usize_ptr = cast_basic_basic(
|
||||
env.builder,
|
||||
ptr.into(),
|
||||
int_type.ptr_type(AddressSpace::Generic).into(),
|
||||
)
|
||||
.into_pointer_value();
|
||||
|
||||
let index = match extra_bytes {
|
||||
n if n == env.ptr_bytes => 1,
|
||||
n if n == 2 * env.ptr_bytes => 2,
|
||||
_ => unreachable!("invalid extra_bytes"),
|
||||
};
|
||||
|
||||
let index_intvalue = int_type.const_int(index, false);
|
||||
|
||||
let ptr_type = get_ptr_type(&value_type, AddressSpace::Generic);
|
||||
builder.build_int_to_ptr(incremented, ptr_type, "calculate_data_ptr")
|
||||
|
||||
unsafe {
|
||||
cast_basic_basic(
|
||||
env.builder,
|
||||
env.builder
|
||||
.build_in_bounds_gep(as_usize_ptr, &[index_intvalue], "get_data_ptr")
|
||||
.into(),
|
||||
ptr_type.into(),
|
||||
)
|
||||
.into_pointer_value()
|
||||
}
|
||||
};
|
||||
|
||||
let refcount_ptr = match extra_bytes {
|
||||
@ -1607,7 +1682,10 @@ fn expose_function_to_host<'a, 'ctx, 'env>(
|
||||
) {
|
||||
let c_function_name: String = format!("{}_exposed", roc_function.get_name().to_str().unwrap());
|
||||
|
||||
expose_function_to_host_help(env, roc_function, &c_function_name);
|
||||
let result = expose_function_to_host_help(env, roc_function, &c_function_name);
|
||||
|
||||
let subprogram = env.new_subprogram(&c_function_name);
|
||||
result.set_subprogram(subprogram);
|
||||
}
|
||||
|
||||
fn expose_function_to_host_help<'a, 'ctx, 'env>(
|
||||
@ -1633,6 +1711,9 @@ fn expose_function_to_host_help<'a, 'ctx, 'env>(
|
||||
env.module
|
||||
.add_function(c_function_name, c_function_type, Some(Linkage::External));
|
||||
|
||||
let subprogram = env.new_subprogram(c_function_name);
|
||||
c_function.set_subprogram(subprogram);
|
||||
|
||||
// STEP 2: build the exposed function's body
|
||||
let builder = env.builder;
|
||||
let context = env.context;
|
||||
@ -1641,6 +1722,23 @@ fn expose_function_to_host_help<'a, 'ctx, 'env>(
|
||||
|
||||
builder.position_at_end(entry);
|
||||
|
||||
let func_scope = c_function.get_subprogram().unwrap();
|
||||
let lexical_block = env.dibuilder.create_lexical_block(
|
||||
/* scope */ func_scope.as_debug_info_scope(),
|
||||
/* file */ env.compile_unit.get_file(),
|
||||
/* line_no */ 0,
|
||||
/* column_no */ 0,
|
||||
);
|
||||
|
||||
let loc = env.dibuilder.create_debug_location(
|
||||
env.context,
|
||||
/* line */ 0,
|
||||
/* column */ 0,
|
||||
/* current_scope */ lexical_block.as_debug_info_scope(),
|
||||
/* inlined_at */ None,
|
||||
);
|
||||
builder.set_current_debug_location(env.context, loc);
|
||||
|
||||
// drop the final argument, which is the pointer we write the result into
|
||||
let args = c_function.get_params();
|
||||
let output_arg_index = args.len() - 1;
|
||||
@ -1952,6 +2050,9 @@ pub fn build_proc_header<'a, 'ctx, 'env>(
|
||||
|
||||
fn_val.set_call_conventions(FAST_CALL_CONV);
|
||||
|
||||
let subprogram = env.new_subprogram(&fn_name);
|
||||
fn_val.set_subprogram(subprogram);
|
||||
|
||||
if env.exposed_to_host.contains(&symbol) {
|
||||
expose_function_to_host(env, fn_val);
|
||||
}
|
||||
@ -2091,6 +2192,24 @@ pub fn build_proc<'a, 'ctx, 'env>(
|
||||
|
||||
builder.position_at_end(entry);
|
||||
|
||||
let func_scope = fn_val.get_subprogram().unwrap();
|
||||
let lexical_block = env.dibuilder.create_lexical_block(
|
||||
/* scope */ func_scope.as_debug_info_scope(),
|
||||
/* file */ env.compile_unit.get_file(),
|
||||
/* line_no */ 0,
|
||||
/* column_no */ 0,
|
||||
);
|
||||
|
||||
let loc = env.dibuilder.create_debug_location(
|
||||
context,
|
||||
/* line */ 0,
|
||||
/* column */ 0,
|
||||
/* current_scope */ lexical_block.as_debug_info_scope(),
|
||||
/* inlined_at */ None,
|
||||
);
|
||||
|
||||
builder.set_current_debug_location(&context, loc);
|
||||
|
||||
// Add args to scope
|
||||
for (arg_val, (layout, arg_symbol)) in fn_val.get_param_iter().zip(args) {
|
||||
set_name(arg_val, arg_symbol.ident_string(&env.interns));
|
||||
|
@ -6,6 +6,7 @@ use crate::llvm::build_list::list_len;
|
||||
use crate::llvm::convert::{basic_type_from_layout, block_of_memory, ptr_int};
|
||||
use bumpalo::collections::Vec;
|
||||
use inkwell::context::Context;
|
||||
use inkwell::debug_info::AsDIScope;
|
||||
use inkwell::module::Linkage;
|
||||
use inkwell::values::{BasicValueEnum, FunctionValue, IntValue, PointerValue, StructValue};
|
||||
use inkwell::{AddressSpace, IntPredicate};
|
||||
@ -55,24 +56,22 @@ impl<'ctx> PointerToRefcount<'ctx> {
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
data_ptr: PointerValue<'ctx>,
|
||||
) -> Self {
|
||||
let builder = env.builder;
|
||||
// pointer to usize
|
||||
let refcount_type = ptr_int(env.context, env.ptr_bytes);
|
||||
|
||||
let ptr_as_int =
|
||||
cast_basic_basic(env.builder, data_ptr.into(), refcount_type.into()).into_int_value();
|
||||
let ptr_as_usize_ptr = cast_basic_basic(
|
||||
builder,
|
||||
data_ptr.into(),
|
||||
refcount_type.ptr_type(AddressSpace::Generic).into(),
|
||||
)
|
||||
.into_pointer_value();
|
||||
|
||||
// subtract offset, to access the refcount
|
||||
let refcount_ptr_as_int = env.builder.build_int_sub(
|
||||
ptr_as_int,
|
||||
refcount_type.const_int(env.ptr_bytes as u64, false),
|
||||
"make_refcount_ptr",
|
||||
);
|
||||
|
||||
let refcount_ptr = env.builder.build_int_to_ptr(
|
||||
refcount_ptr_as_int,
|
||||
refcount_type.ptr_type(AddressSpace::Generic),
|
||||
"get_refcount_ptr",
|
||||
);
|
||||
// get a pointer to index -1
|
||||
let index_intvalue = refcount_type.const_int((-1 as i64) as u64, false);
|
||||
let refcount_ptr = unsafe {
|
||||
builder.build_in_bounds_gep(ptr_as_usize_ptr, &[index_intvalue], "get_rc_ptr")
|
||||
};
|
||||
|
||||
Self {
|
||||
value: refcount_ptr,
|
||||
@ -132,6 +131,7 @@ impl<'ctx> PointerToRefcount<'ctx> {
|
||||
fn decrement<'a, 'env>(&self, env: &Env<'a, 'ctx, 'env>, layout: &Layout<'a>) {
|
||||
let context = env.context;
|
||||
let block = env.builder.get_insert_block().expect("to be in a function");
|
||||
let di_location = env.builder.get_current_debug_location().unwrap();
|
||||
|
||||
let alignment = layout.alignment_bytes(env.ptr_bytes);
|
||||
|
||||
@ -153,6 +153,9 @@ impl<'ctx> PointerToRefcount<'ctx> {
|
||||
// Because it's an internal-only function, it should use the fast calling convention.
|
||||
function_value.set_call_conventions(FAST_CALL_CONV);
|
||||
|
||||
let subprogram = env.new_subprogram(fn_name);
|
||||
function_value.set_subprogram(subprogram);
|
||||
|
||||
Self::_build_decrement_function_body(env, function_value, alignment);
|
||||
|
||||
function_value
|
||||
@ -162,6 +165,8 @@ impl<'ctx> PointerToRefcount<'ctx> {
|
||||
let refcount_ptr = self.value;
|
||||
|
||||
env.builder.position_at_end(block);
|
||||
env.builder
|
||||
.set_current_debug_location(env.context, di_location);
|
||||
let call = env
|
||||
.builder
|
||||
.build_call(function, &[refcount_ptr.into()], fn_name);
|
||||
@ -181,6 +186,24 @@ impl<'ctx> PointerToRefcount<'ctx> {
|
||||
let entry = ctx.append_basic_block(parent, "entry");
|
||||
builder.position_at_end(entry);
|
||||
|
||||
let subprogram = parent.get_subprogram().unwrap();
|
||||
let lexical_block = env.dibuilder.create_lexical_block(
|
||||
/* scope */ subprogram.as_debug_info_scope(),
|
||||
/* file */ env.compile_unit.get_file(),
|
||||
/* line_no */ 0,
|
||||
/* column_no */ 0,
|
||||
);
|
||||
|
||||
let loc = env.dibuilder.create_debug_location(
|
||||
&ctx,
|
||||
/* line */ 0,
|
||||
/* column */ 0,
|
||||
/* current_scope */ lexical_block.as_debug_info_scope(),
|
||||
/* inlined_at */ None,
|
||||
);
|
||||
|
||||
env.builder.set_current_debug_location(&ctx, loc);
|
||||
|
||||
let refcount_ptr = {
|
||||
let raw_refcount_ptr = parent.get_nth_param(0).unwrap();
|
||||
debug_assert!(raw_refcount_ptr.is_pointer_value());
|
||||
@ -490,6 +513,7 @@ pub fn build_inc_list<'a, 'ctx, 'env>(
|
||||
original_wrapper: StructValue<'ctx>,
|
||||
) {
|
||||
let block = env.builder.get_insert_block().expect("to be in a function");
|
||||
let di_location = env.builder.get_current_debug_location().unwrap();
|
||||
|
||||
let symbol = Symbol::INC;
|
||||
let fn_name = layout_ids
|
||||
@ -499,7 +523,7 @@ pub fn build_inc_list<'a, 'ctx, 'env>(
|
||||
let function = match env.module.get_function(fn_name.as_str()) {
|
||||
Some(function_value) => function_value,
|
||||
None => {
|
||||
let function_value = build_header(env, &layout, fn_name);
|
||||
let function_value = build_header(env, &layout, &fn_name);
|
||||
|
||||
build_inc_list_help(env, layout_ids, layout, function_value);
|
||||
|
||||
@ -508,6 +532,8 @@ pub fn build_inc_list<'a, 'ctx, 'env>(
|
||||
};
|
||||
|
||||
env.builder.position_at_end(block);
|
||||
env.builder
|
||||
.set_current_debug_location(env.context, di_location);
|
||||
let call = env
|
||||
.builder
|
||||
.build_call(function, &[original_wrapper.into()], "increment_list");
|
||||
@ -529,6 +555,23 @@ fn build_inc_list_help<'a, 'ctx, 'env>(
|
||||
|
||||
builder.position_at_end(entry);
|
||||
|
||||
let func_scope = fn_val.get_subprogram().unwrap();
|
||||
let lexical_block = env.dibuilder.create_lexical_block(
|
||||
/* scope */ func_scope.as_debug_info_scope(),
|
||||
/* file */ env.compile_unit.get_file(),
|
||||
/* line_no */ 0,
|
||||
/* column_no */ 0,
|
||||
);
|
||||
|
||||
let loc = env.dibuilder.create_debug_location(
|
||||
ctx,
|
||||
/* line */ 0,
|
||||
/* column */ 0,
|
||||
/* current_scope */ lexical_block.as_debug_info_scope(),
|
||||
/* inlined_at */ None,
|
||||
);
|
||||
builder.set_current_debug_location(&ctx, loc);
|
||||
|
||||
let mut scope = Scope::default();
|
||||
|
||||
// Add args to scope
|
||||
@ -586,6 +629,7 @@ pub fn build_dec_list<'a, 'ctx, 'env>(
|
||||
original_wrapper: StructValue<'ctx>,
|
||||
) {
|
||||
let block = env.builder.get_insert_block().expect("to be in a function");
|
||||
let di_location = env.builder.get_current_debug_location().unwrap();
|
||||
|
||||
let symbol = Symbol::DEC;
|
||||
let fn_name = layout_ids
|
||||
@ -595,7 +639,7 @@ pub fn build_dec_list<'a, 'ctx, 'env>(
|
||||
let function = match env.module.get_function(fn_name.as_str()) {
|
||||
Some(function_value) => function_value,
|
||||
None => {
|
||||
let function_value = build_header(env, &layout, fn_name);
|
||||
let function_value = build_header(env, &layout, &fn_name);
|
||||
|
||||
build_dec_list_help(env, layout_ids, layout, function_value);
|
||||
|
||||
@ -604,6 +648,8 @@ pub fn build_dec_list<'a, 'ctx, 'env>(
|
||||
};
|
||||
|
||||
env.builder.position_at_end(block);
|
||||
env.builder
|
||||
.set_current_debug_location(env.context, di_location);
|
||||
let call = env
|
||||
.builder
|
||||
.build_call(function, &[original_wrapper.into()], "decrement_list");
|
||||
@ -624,6 +670,23 @@ fn build_dec_list_help<'a, 'ctx, 'env>(
|
||||
|
||||
builder.position_at_end(entry);
|
||||
|
||||
let func_scope = fn_val.get_subprogram().unwrap();
|
||||
let lexical_block = env.dibuilder.create_lexical_block(
|
||||
/* scope */ func_scope.as_debug_info_scope(),
|
||||
/* file */ env.compile_unit.get_file(),
|
||||
/* line_no */ 0,
|
||||
/* column_no */ 0,
|
||||
);
|
||||
|
||||
let loc = env.dibuilder.create_debug_location(
|
||||
ctx,
|
||||
/* line */ 0,
|
||||
/* column */ 0,
|
||||
/* current_scope */ lexical_block.as_debug_info_scope(),
|
||||
/* inlined_at */ None,
|
||||
);
|
||||
builder.set_current_debug_location(&ctx, loc);
|
||||
|
||||
let mut scope = Scope::default();
|
||||
|
||||
// Add args to scope
|
||||
@ -685,6 +748,7 @@ pub fn build_inc_str<'a, 'ctx, 'env>(
|
||||
original_wrapper: StructValue<'ctx>,
|
||||
) {
|
||||
let block = env.builder.get_insert_block().expect("to be in a function");
|
||||
let di_location = env.builder.get_current_debug_location().unwrap();
|
||||
|
||||
let symbol = Symbol::INC;
|
||||
let fn_name = layout_ids
|
||||
@ -694,7 +758,7 @@ pub fn build_inc_str<'a, 'ctx, 'env>(
|
||||
let function = match env.module.get_function(fn_name.as_str()) {
|
||||
Some(function_value) => function_value,
|
||||
None => {
|
||||
let function_value = build_header(env, &layout, fn_name);
|
||||
let function_value = build_header(env, &layout, &fn_name);
|
||||
|
||||
build_inc_str_help(env, layout_ids, layout, function_value);
|
||||
|
||||
@ -703,6 +767,8 @@ pub fn build_inc_str<'a, 'ctx, 'env>(
|
||||
};
|
||||
|
||||
env.builder.position_at_end(block);
|
||||
env.builder
|
||||
.set_current_debug_location(env.context, di_location);
|
||||
let call = env
|
||||
.builder
|
||||
.build_call(function, &[original_wrapper.into()], "increment_str");
|
||||
@ -723,6 +789,23 @@ fn build_inc_str_help<'a, 'ctx, 'env>(
|
||||
|
||||
builder.position_at_end(entry);
|
||||
|
||||
let func_scope = fn_val.get_subprogram().unwrap();
|
||||
let lexical_block = env.dibuilder.create_lexical_block(
|
||||
/* scope */ func_scope.as_debug_info_scope(),
|
||||
/* file */ env.compile_unit.get_file(),
|
||||
/* line_no */ 0,
|
||||
/* column_no */ 0,
|
||||
);
|
||||
|
||||
let loc = env.dibuilder.create_debug_location(
|
||||
ctx,
|
||||
/* line */ 0,
|
||||
/* column */ 0,
|
||||
/* current_scope */ lexical_block.as_debug_info_scope(),
|
||||
/* inlined_at */ None,
|
||||
);
|
||||
builder.set_current_debug_location(&ctx, loc);
|
||||
|
||||
let mut scope = Scope::default();
|
||||
|
||||
// Add args to scope
|
||||
@ -784,6 +867,7 @@ pub fn build_dec_str<'a, 'ctx, 'env>(
|
||||
original_wrapper: StructValue<'ctx>,
|
||||
) {
|
||||
let block = env.builder.get_insert_block().expect("to be in a function");
|
||||
let di_location = env.builder.get_current_debug_location().unwrap();
|
||||
|
||||
let symbol = Symbol::DEC;
|
||||
let fn_name = layout_ids
|
||||
@ -793,7 +877,7 @@ pub fn build_dec_str<'a, 'ctx, 'env>(
|
||||
let function = match env.module.get_function(fn_name.as_str()) {
|
||||
Some(function_value) => function_value,
|
||||
None => {
|
||||
let function_value = build_header(env, &layout, fn_name);
|
||||
let function_value = build_header(env, &layout, &fn_name);
|
||||
|
||||
build_dec_str_help(env, layout_ids, layout, function_value);
|
||||
|
||||
@ -802,6 +886,8 @@ pub fn build_dec_str<'a, 'ctx, 'env>(
|
||||
};
|
||||
|
||||
env.builder.position_at_end(block);
|
||||
env.builder
|
||||
.set_current_debug_location(env.context, di_location);
|
||||
let call = env
|
||||
.builder
|
||||
.build_call(function, &[original_wrapper.into()], "decrement_str");
|
||||
@ -822,6 +908,23 @@ fn build_dec_str_help<'a, 'ctx, 'env>(
|
||||
|
||||
builder.position_at_end(entry);
|
||||
|
||||
let func_scope = fn_val.get_subprogram().unwrap();
|
||||
let lexical_block = env.dibuilder.create_lexical_block(
|
||||
/* scope */ func_scope.as_debug_info_scope(),
|
||||
/* file */ env.compile_unit.get_file(),
|
||||
/* line_no */ 0,
|
||||
/* column_no */ 0,
|
||||
);
|
||||
|
||||
let loc = env.dibuilder.create_debug_location(
|
||||
ctx,
|
||||
/* line */ 0,
|
||||
/* column */ 0,
|
||||
/* current_scope */ lexical_block.as_debug_info_scope(),
|
||||
/* inlined_at */ None,
|
||||
);
|
||||
builder.set_current_debug_location(&ctx, loc);
|
||||
|
||||
let mut scope = Scope::default();
|
||||
|
||||
// Add args to scope
|
||||
@ -880,7 +983,7 @@ fn build_dec_str_help<'a, 'ctx, 'env>(
|
||||
pub fn build_header<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout: &Layout<'a>,
|
||||
fn_name: String,
|
||||
fn_name: &str,
|
||||
) -> FunctionValue<'ctx> {
|
||||
let arena = env.arena;
|
||||
let context = &env.context;
|
||||
@ -892,11 +995,16 @@ pub fn build_header<'a, 'ctx, 'env>(
|
||||
|
||||
let fn_val = env
|
||||
.module
|
||||
.add_function(fn_name.as_str(), fn_type, Some(Linkage::Private));
|
||||
.add_function(fn_name, fn_type, Some(Linkage::Private));
|
||||
|
||||
// Because it's an internal-only function, it should use the fast calling convention.
|
||||
fn_val.set_call_conventions(FAST_CALL_CONV);
|
||||
|
||||
let subprogram = env.new_subprogram(&fn_name);
|
||||
fn_val.set_subprogram(subprogram);
|
||||
|
||||
env.dibuilder.finalize();
|
||||
|
||||
fn_val
|
||||
}
|
||||
|
||||
@ -909,6 +1017,7 @@ pub fn build_dec_union<'a, 'ctx, 'env>(
|
||||
let layout = Layout::Union(fields);
|
||||
|
||||
let block = env.builder.get_insert_block().expect("to be in a function");
|
||||
let di_location = env.builder.get_current_debug_location().unwrap();
|
||||
|
||||
let symbol = Symbol::DEC;
|
||||
let fn_name = layout_ids
|
||||
@ -918,7 +1027,7 @@ pub fn build_dec_union<'a, 'ctx, 'env>(
|
||||
let function = match env.module.get_function(fn_name.as_str()) {
|
||||
Some(function_value) => function_value,
|
||||
None => {
|
||||
let function_value = build_header(env, &layout, fn_name);
|
||||
let function_value = build_header(env, &layout, &fn_name);
|
||||
|
||||
build_dec_union_help(env, layout_ids, fields, function_value);
|
||||
|
||||
@ -927,6 +1036,9 @@ pub fn build_dec_union<'a, 'ctx, 'env>(
|
||||
};
|
||||
|
||||
env.builder.position_at_end(block);
|
||||
env.builder
|
||||
.set_current_debug_location(env.context, di_location);
|
||||
|
||||
let call = env
|
||||
.builder
|
||||
.build_call(function, &[value], "decrement_union");
|
||||
@ -952,11 +1064,29 @@ pub fn build_dec_union_help<'a, 'ctx, 'env>(
|
||||
|
||||
builder.position_at_end(entry);
|
||||
|
||||
let func_scope = fn_val.get_subprogram().unwrap();
|
||||
let lexical_block = env.dibuilder.create_lexical_block(
|
||||
/* scope */ func_scope.as_debug_info_scope(),
|
||||
/* file */ env.compile_unit.get_file(),
|
||||
/* line_no */ 0,
|
||||
/* column_no */ 0,
|
||||
);
|
||||
|
||||
let loc = env.dibuilder.create_debug_location(
|
||||
context,
|
||||
/* line */ 0,
|
||||
/* column */ 0,
|
||||
/* current_scope */ lexical_block.as_debug_info_scope(),
|
||||
/* inlined_at */ None,
|
||||
);
|
||||
builder.set_current_debug_location(&context, loc);
|
||||
|
||||
let mut scope = Scope::default();
|
||||
|
||||
// Add args to scope
|
||||
let arg_symbol = Symbol::ARG_1;
|
||||
let layout = Layout::Union(tags);
|
||||
|
||||
let arg_val = fn_val.get_param_iter().next().unwrap();
|
||||
|
||||
set_name(arg_val, arg_symbol.ident_string(&env.interns));
|
||||
@ -984,6 +1114,8 @@ pub fn build_dec_union_help<'a, 'ctx, 'env>(
|
||||
|
||||
let merge_block = env.context.append_basic_block(parent, "decrement_merge");
|
||||
|
||||
builder.set_current_debug_location(&context, loc);
|
||||
|
||||
for (tag_id, field_layouts) in tags.iter().enumerate() {
|
||||
// if none of the fields are or contain anything refcounted, just move on
|
||||
if !field_layouts
|
||||
@ -1097,6 +1229,7 @@ pub fn build_inc_union<'a, 'ctx, 'env>(
|
||||
let layout = Layout::Union(fields);
|
||||
|
||||
let block = env.builder.get_insert_block().expect("to be in a function");
|
||||
let di_location = env.builder.get_current_debug_location().unwrap();
|
||||
|
||||
let symbol = Symbol::INC;
|
||||
let fn_name = layout_ids
|
||||
@ -1106,7 +1239,7 @@ pub fn build_inc_union<'a, 'ctx, 'env>(
|
||||
let function = match env.module.get_function(fn_name.as_str()) {
|
||||
Some(function_value) => function_value,
|
||||
None => {
|
||||
let function_value = build_header(env, &layout, fn_name);
|
||||
let function_value = build_header(env, &layout, &fn_name);
|
||||
|
||||
build_inc_union_help(env, layout_ids, fields, function_value);
|
||||
|
||||
@ -1115,6 +1248,8 @@ pub fn build_inc_union<'a, 'ctx, 'env>(
|
||||
};
|
||||
|
||||
env.builder.position_at_end(block);
|
||||
env.builder
|
||||
.set_current_debug_location(env.context, di_location);
|
||||
let call = env
|
||||
.builder
|
||||
.build_call(function, &[value], "increment_union");
|
||||
@ -1140,6 +1275,23 @@ pub fn build_inc_union_help<'a, 'ctx, 'env>(
|
||||
|
||||
builder.position_at_end(entry);
|
||||
|
||||
let func_scope = fn_val.get_subprogram().unwrap();
|
||||
let lexical_block = env.dibuilder.create_lexical_block(
|
||||
/* scope */ func_scope.as_debug_info_scope(),
|
||||
/* file */ env.compile_unit.get_file(),
|
||||
/* line_no */ 0,
|
||||
/* column_no */ 0,
|
||||
);
|
||||
|
||||
let loc = env.dibuilder.create_debug_location(
|
||||
context,
|
||||
/* line */ 0,
|
||||
/* column */ 0,
|
||||
/* current_scope */ lexical_block.as_debug_info_scope(),
|
||||
/* inlined_at */ None,
|
||||
);
|
||||
builder.set_current_debug_location(&context, loc);
|
||||
|
||||
let mut scope = Scope::default();
|
||||
|
||||
// Add args to scope
|
||||
|
@ -152,10 +152,14 @@ pub fn helper<'a>(
|
||||
let (module_pass, function_pass) =
|
||||
roc_gen::llvm::build::construct_optimization_passes(module, opt_level);
|
||||
|
||||
let (dibuilder, compile_unit) = roc_gen::llvm::build::Env::new_debug_info(module);
|
||||
|
||||
// Compile and add all the Procs before adding main
|
||||
let env = roc_gen::llvm::build::Env {
|
||||
arena: &arena,
|
||||
builder: &builder,
|
||||
dibuilder: &dibuilder,
|
||||
compile_unit: &compile_unit,
|
||||
context,
|
||||
interns,
|
||||
module,
|
||||
@ -195,6 +199,9 @@ pub fn helper<'a>(
|
||||
|
||||
build_proc(&env, &mut layout_ids, scope.clone(), proc, fn_val);
|
||||
|
||||
// call finalize() before any code generation/verification
|
||||
env.dibuilder.finalize();
|
||||
|
||||
if fn_val.verify(true) {
|
||||
function_pass.run_on(&fn_val);
|
||||
} else {
|
||||
@ -228,6 +235,8 @@ pub fn helper<'a>(
|
||||
&main_fn_layout,
|
||||
);
|
||||
|
||||
env.dibuilder.finalize();
|
||||
|
||||
// Uncomment this to see the module's un-optimized LLVM instruction output:
|
||||
// env.module.print_to_stderr();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user