From 6f4585e7d84c587f2e4531bbd3e2a2367985f23e Mon Sep 17 00:00:00 2001 From: Folkert Date: Wed, 18 Nov 2020 19:24:49 +0100 Subject: [PATCH] add subprogram debug info --- compiler/gen/src/llvm/build.rs | 74 ++++++++++++++++++++++++++-------- 1 file changed, 57 insertions(+), 17 deletions(-) diff --git a/compiler/gen/src/llvm/build.rs b/compiler/gen/src/llvm/build.rs index e658a40b3b..b136b44c8b 100644 --- a/compiler/gen/src/llvm/build.rs +++ b/compiler/gen/src/llvm/build.rs @@ -17,7 +17,7 @@ use bumpalo::Bump; use inkwell::basic_block::BasicBlock; use inkwell::builder::Builder; use inkwell::context::Context; -use inkwell::debug_info::{DICompileUnit, DISubprogram, DebugInfoBuilder}; +use inkwell::debug_info::{AsDIScope, DICompileUnit, DISubprogram, DebugInfoBuilder}; use inkwell::memory_buffer::MemoryBuffer; use inkwell::module::{Linkage, Module}; use inkwell::passes::{PassManager, PassManagerBuilder}; @@ -201,7 +201,6 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> { } pub fn new_subprogram(&self, function_name: &str) -> DISubprogram<'ctx> { - use inkwell::debug_info::AsDIScope; use inkwell::debug_info::DIFlagsConstants; let dibuilder = self.dibuilder; @@ -1042,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! @@ -1065,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 { @@ -1666,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>( @@ -2011,6 +2030,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); } @@ -2150,6 +2172,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));