From ee3b18bd83daf7fc93f4995ebc5b55d1d2e118e3 Mon Sep 17 00:00:00 2001 From: ychenfo Date: Mon, 11 Apr 2022 23:36:52 +0800 Subject: [PATCH] nac3core: add basic debug info metadata --- nac3artiq/src/lib.rs | 32 ++++++++++++- nac3core/src/codegen/mod.rs | 95 ++++++++++++++++++++++++++++++------- 2 files changed, 110 insertions(+), 17 deletions(-) diff --git a/nac3artiq/src/lib.rs b/nac3artiq/src/lib.rs index d6ed943fa..5fb5ac14d 100644 --- a/nac3artiq/src/lib.rs +++ b/nac3artiq/src/lib.rs @@ -781,7 +781,37 @@ impl Nac3 { let context = inkwell::context::Context::create(); let module = context.create_module("attributes_writeback"); let builder = context.create_builder(); - let (_, module, _) = gen_func_impl(&context, &mut generator, ®istry, builder, module, + + module.add_basic_value_flag( + "Debug Info Version", + inkwell::module::FlagBehavior::Warning, + context.i32_type().const_int(3, false), + ); + module.add_basic_value_flag( + "Dwarf Version", + inkwell::module::FlagBehavior::Warning, + context.i32_type().const_int(4, false), + ); + let (dibuilder, compile_unit) = module.create_debug_info_builder( + true, + /* language */ inkwell::debug_info::DWARFSourceLanguage::Python, + /* filename */ "_attribute_writeback", + /* directory */ ".", + /* producer */ "NAC3", + /* 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, + "", + "", + ); + let debug_info_builder = nac3core::codegen::DebugInfoGenerator {dibuilder, compile_unit}; + + let (_, module, _, _) = gen_func_impl(&context, &mut generator, ®istry, builder, debug_info_builder, module, attributes_writeback_task, |generator, ctx| { attributes_writeback(ctx, generator, inner_resolver.as_ref(), host_attributes) }).unwrap(); diff --git a/nac3core/src/codegen/mod.rs b/nac3core/src/codegen/mod.rs index 191b023ed..f9c6786d3 100644 --- a/nac3core/src/codegen/mod.rs +++ b/nac3core/src/codegen/mod.rs @@ -17,7 +17,8 @@ use inkwell::{ module::Module, passes::{PassManager, PassManagerBuilder}, types::{AnyType, BasicType, BasicTypeEnum}, - values::{BasicValueEnum, FunctionValue, PhiValue, PointerValue} + values::{BasicValueEnum, FunctionValue, PhiValue, PointerValue}, + debug_info::{DebugInfoBuilder, DICompileUnit}, }; use itertools::Itertools; use nac3parser::ast::{Stmt, StrRef, Location}; @@ -49,6 +50,12 @@ pub struct StaticValueStore { pub type VarValue<'ctx> = (PointerValue<'ctx>, Option>, i64); +#[derive(Debug)] +pub struct DebugInfoGenerator<'ctx> { + pub dibuilder: DebugInfoBuilder<'ctx>, + pub compile_unit: DICompileUnit<'ctx>, +} + pub struct CodeGenContext<'ctx, 'a> { pub ctx: &'ctx Context, pub builder: Builder<'ctx>, @@ -78,6 +85,7 @@ pub struct CodeGenContext<'ctx, 'a> { Option<(Vec>>, BasicBlock<'ctx>, PhiValue<'ctx>)>, pub need_sret: bool, pub current_loc: Location, + pub debug_info_builder: DebugInfoGenerator<'ctx>, } impl<'ctx, 'a> CodeGenContext<'ctx, 'a> { @@ -203,6 +211,36 @@ impl WorkerRegistry { let mut builder = context.create_builder(); let module = context.create_module(generator.get_name()); + module.add_basic_value_flag( + "Debug Info Version", + inkwell::module::FlagBehavior::Warning, + context.i32_type().const_int(3, false), + ); + module.add_basic_value_flag( + "Dwarf Version", + inkwell::module::FlagBehavior::Warning, + context.i32_type().const_int(4, false), + ); + let (dibuilder, compile_unit) = module.create_debug_info_builder( + true, + /* language */ inkwell::debug_info::DWARFSourceLanguage::Python, + /* filename */ generator.get_name(), + /* directory */ ".", + /* producer */ "NAC3", + /* 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, + "", + "", + ); + let mut debug_info_builder = DebugInfoGenerator {dibuilder, compile_unit}; + + let pass_builder = PassManagerBuilder::create(); pass_builder.set_optimization_level(OptimizationLevel::Default); let passes = PassManager::create(&module); @@ -211,14 +249,17 @@ impl WorkerRegistry { let mut errors = HashSet::new(); while let Some(task) = self.receiver.recv().unwrap() { let tmp_module = context.create_module("tmp"); - match gen_func(&context, generator, self, builder, tmp_module, task) { + match gen_func(&context, generator, self, builder, debug_info_builder, tmp_module, task) + { Ok(result) => { builder = result.0; + debug_info_builder = result.3; passes.run_on(&result.2); module.link_in_module(result.1).unwrap(); } - Err((old_builder, e)) => { + Err((old_builder, old_di, e)) => { builder = old_builder; + debug_info_builder = old_di; errors.insert(e); } } @@ -361,15 +402,23 @@ fn need_sret<'ctx>(ctx: &'ctx Context, ty: BasicTypeEnum<'ctx>) -> bool { need_sret_impl(ctx, ty, true) } -pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenContext) -> Result<(), String>> ( +pub fn gen_func_impl< + 'ctx, + G: CodeGenerator, + F: FnOnce(&mut G, &mut CodeGenContext) -> Result<(), String>, +>( context: &'ctx Context, generator: &mut G, registry: &WorkerRegistry, builder: Builder<'ctx>, + debug_info_builder: DebugInfoGenerator<'ctx>, module: Module<'ctx>, task: CodeGenTask, - codegen_function: F -) -> Result<(Builder<'ctx>, Module<'ctx>, FunctionValue<'ctx>), (Builder<'ctx>, String)> { + codegen_function: F, +) -> Result< + (Builder<'ctx>, Module<'ctx>, FunctionValue<'ctx>, DebugInfoGenerator<'ctx>), + (Builder<'ctx>, DebugInfoGenerator<'ctx>, String), +> { let top_level_ctx = registry.top_level_ctx.clone(); let static_value_store = registry.static_value_store.clone(); let (mut unifier, primitives) = { @@ -568,6 +617,7 @@ pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenConte primitives, init_bb, builder, + debug_info_builder, module, unifier, static_value_store, @@ -582,12 +632,12 @@ pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenConte code_gen_context.builder.build_return(None); } - let CodeGenContext { builder, module, .. } = code_gen_context; + let CodeGenContext { builder, module, debug_info_builder, .. } = code_gen_context; if let Err(e) = result { - return Err((builder, e)); + return Err((builder, debug_info_builder, e)); } - Ok((builder, module, fn_val)) + Ok((builder, module, fn_val, debug_info_builder)) } pub fn gen_func<'ctx, G: CodeGenerator>( @@ -595,14 +645,27 @@ pub fn gen_func<'ctx, G: CodeGenerator>( generator: &mut G, registry: &WorkerRegistry, builder: Builder<'ctx>, + debug_info_builder: DebugInfoGenerator<'ctx>, module: Module<'ctx>, task: CodeGenTask, -) -> Result<(Builder<'ctx>, Module<'ctx>, FunctionValue<'ctx>), (Builder<'ctx>, String)> { +) -> Result< + (Builder<'ctx>, Module<'ctx>, FunctionValue<'ctx>, DebugInfoGenerator<'ctx>), + (Builder<'ctx>, DebugInfoGenerator<'ctx>, String), +> { let body = task.body.clone(); - gen_func_impl(context, generator, registry, builder, module, task, |generator, ctx| { - for stmt in body.iter() { - generator.gen_stmt(ctx, stmt)?; - } - Ok(()) - }) + gen_func_impl( + context, + generator, + registry, + builder, + debug_info_builder, + module, + task, + |generator, ctx| { + for stmt in body.iter() { + generator.gen_stmt(ctx, stmt)?; + } + Ok(()) + }, + ) }