From 98fe3db7bb4f875ac7aa6cb8b661da5ebdbd9815 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Mon, 28 Aug 2023 21:43:53 +0200 Subject: [PATCH 1/2] LLVM: Started rewriting the debug symbol codegen --- src/thorin/CMakeLists.txt | 1 + src/thorin/be/codegen.h | 1 - src/thorin/be/llvm/debug.cpp | 116 +++++++++++++++++++++++++++++++++++ src/thorin/be/llvm/llvm.cpp | 56 +++++++---------- src/thorin/be/llvm/llvm.h | 32 +++++++++- 5 files changed, 168 insertions(+), 38 deletions(-) create mode 100644 src/thorin/be/llvm/debug.cpp diff --git a/src/thorin/CMakeLists.txt b/src/thorin/CMakeLists.txt index 58c57ce5a..19ecffcf4 100644 --- a/src/thorin/CMakeLists.txt +++ b/src/thorin/CMakeLists.txt @@ -104,6 +104,7 @@ if(LLVM_FOUND) be/llvm/runtime.cpp be/llvm/runtime.h be/llvm/vectorize.cpp + be/llvm/debug.cpp ) endif() diff --git a/src/thorin/be/codegen.h b/src/thorin/be/codegen.h index 9a2974eaa..7db38de32 100644 --- a/src/thorin/be/codegen.h +++ b/src/thorin/be/codegen.h @@ -19,7 +19,6 @@ class CodeGen { //@{ Thorin& thorin() const { return thorin_; } World& world() const { return thorin().world(); } - bool debug() const { return debug_; } //@} private: diff --git a/src/thorin/be/llvm/debug.cpp b/src/thorin/be/llvm/debug.cpp new file mode 100644 index 000000000..ba9b2bed0 --- /dev/null +++ b/src/thorin/be/llvm/debug.cpp @@ -0,0 +1,116 @@ +#include "llvm.h" + +#include +#include +#include +#include +#include + +namespace thorin::llvm { + +CodeGen::Debug::Debug(thorin::llvm::CodeGen& cg) : cg_(cg), dibuilder_(cg.module()) {} + +void CodeGen::Debug::emit_module() { + cg_.module().addModuleFlag(llvm::Module::Warning, "Debug Info Version", llvm::DEBUG_METADATA_VERSION); + // Darwin only supports dwarf2 + if (llvm::Triple(llvm::sys::getProcessTriple()).isOSDarwin()) + cg_.module().addModuleFlag(llvm::Module::Warning, "Dwarf Version", 2); + dicompile_unit_ = dibuilder_.createCompileUnit(llvm::dwarf::DW_LANG_C, dibuilder_.createFile(cg_.world().name(), llvm::StringRef()), "Impala", cg_.opt() > 0, llvm::StringRef(), 0); +} + +void CodeGen::Debug::prepare(const thorin::Scope& scope, llvm::Function* fct) { + auto difile = get_difile(cg_.entry_->loc().file); + auto disub_program = dibuilder_.createFunction( + discope_, fct->getName(), fct->getName(), difile, cg_.entry_->loc().begin.row, + dibuilder_.createSubroutineType(dibuilder_.getOrCreateTypeArray(llvm::ArrayRef())), + cg_.entry_->loc().begin.row, + llvm::DINode::FlagPrototyped, + llvm::DISubprogram::SPFlagDefinition | (cg_.opt() > 0 ? llvm::DISubprogram::SPFlagOptimized : llvm::DISubprogram::SPFlagZero)); + fct->setSubprogram(disub_program); + discope_ = disub_program; +} + +void CodeGen::Debug::prepare(llvm::IRBuilder<>& irbuilder, const thorin::Continuation* cont) { + irbuilder.SetCurrentDebugLocation(llvm::DILocation::get(discope_->getContext(), cont->loc().begin.row, cont->loc().begin.col, discope_)); +} + +void CodeGen::Debug::prepare(llvm::IRBuilder<>& irbuilder, const thorin::Def* def) { + irbuilder.SetCurrentDebugLocation(llvm::DILocation::get(discope_->getContext(), def->loc().begin.row, def->loc().begin.col, discope_)); +} + +void CodeGen::Debug::finalize(const thorin::Def* def, llvm::Value* val) { + val->setName(def->unique_name()); +} + +void CodeGen::Debug::register_param(const Param* param, int index, llvm::Value* val) { + if (!param->type()->isa()) + return; + llvm::DIFile* file = get_difile(param->debug().loc.file); + auto local_var = dibuilder_.createParameterVariable(discope_, param->name(), index, file, param->debug().loc.begin.row, get_ditype(param->type())); + dibuilder_.insertDbgValueIntrinsic(val, local_var, llvm::DIExpression::get(cg_.context(), {}), get_dilocation(param->debug().loc, discope_), cg_.cont2bb(param->continuation())); +} + +llvm::DIFile* CodeGen::Debug::get_difile(const std::string& file) { + auto src_file = llvm::sys::path::filename(file); + auto src_dir = llvm::sys::path::parent_path(file); + return dibuilder_.createFile(src_file, src_dir); +} + +llvm::DILocation* CodeGen::Debug::get_dilocation(const thorin::Loc& loc, llvm::DIScope* discope) { + return llvm::DILocation::get(cg_.context(), loc.begin.row, loc.begin.col, discope); +} + +llvm::DIType* CodeGen::Debug::get_ditype(const thorin::Type* t) { + if (auto found = types_.lookup(t)) + return *found; + + using namespace llvm::dwarf; + + if (auto prim_type = t->isa()) { + switch (prim_type->primtype_tag()) { + case PrimType_bool: return types_[t] = dibuilder_.createBasicType("bool", 1, DW_ATE_boolean); + case PrimType_ps8: case PrimType_qs8: case PrimType_pu8: case PrimType_qu8: return types_[t] = dibuilder_.createBasicType("bool", 8, is_type_s(prim_type) ? DW_ATE_signed_char : DW_ATE_unsigned_char); + case PrimType_ps16: case PrimType_qs16: case PrimType_pu16: case PrimType_qu16: return types_[t] = dibuilder_.createBasicType("bool", 16, is_type_s(prim_type) ? DW_ATE_signed : DW_ATE_unsigned); + case PrimType_ps32: case PrimType_qs32: case PrimType_pu32: case PrimType_qu32: return types_[t] = dibuilder_.createBasicType("bool", 32, is_type_s(prim_type) ? DW_ATE_signed : DW_ATE_unsigned); + case PrimType_ps64: case PrimType_qs64: case PrimType_pu64: case PrimType_qu64: return types_[t] = dibuilder_.createBasicType("bool", 64, is_type_s(prim_type) ? DW_ATE_signed : DW_ATE_unsigned); + case PrimType_pf16: case PrimType_qf16: return types_[t] = dibuilder_.createBasicType("bool", 16, DW_ATE_float); + case PrimType_pf32: case PrimType_qf32: return types_[t] = dibuilder_.createBasicType("bool", 32, DW_ATE_float); + case PrimType_pf64: case PrimType_qf64: return types_[t] = dibuilder_.createBasicType("bool", 64, DW_ATE_float); + } + } else if (auto ptr_t = t->isa()) { + return types_[t] = dibuilder_.createPointerType(get_ditype(ptr_t->pointee()), cg_.machine_->getPointerSize(static_cast(ptr_t->addr_space()))); + } else if (auto fun_t = t->isa()) { + + } else if (auto agg_t = t->isa()) { + types_[t] = dibuilder_.createForwardDecl(DW_TAG_structure_type, agg_t->name().str(), dicompile_unit_, get_difile(t->debug().loc.file), t->debug().loc.begin.row); + auto data_layout = cg_.module().getDataLayout(); + auto layout_t = data_layout.getStructLayout(llvm::cast(cg_.convert(t))); + std::vector members; + size_t i = 0; + for (auto member_t : agg_t->types()) { + auto member_di = get_ditype(member_t); + auto member_llvm_t = cg_.convert(member_t); + auto derived = dibuilder_.createMemberType(dicompile_unit_, agg_t->op_name(i).str(), get_difile(t->debug().loc.file), t->debug().loc.begin.row, + data_layout.getTypeSizeInBits(member_llvm_t), + data_layout.getABITypeAlign(member_llvm_t).value(), + layout_t->getElementOffsetInBits(i), + llvm::DINode::DIFlags::FlagZero, + member_di); + i++; + } + return types_[t] = dibuilder_.createStructType(dicompile_unit_, agg_t->name().str(), get_difile(t->debug().loc.file), t->debug().loc.begin.row, + layout_t->getSizeInBits(), + layout_t->getAlignment().value(), + llvm::DINode::DIFlags::FlagZero, + nullptr, + dibuilder_.getOrCreateArray(members)); + } + + assert(false); +} + +void CodeGen::Debug::finalize() { + dibuilder_.finalize(); +} + +} \ No newline at end of file diff --git a/src/thorin/be/llvm/llvm.cpp b/src/thorin/be/llvm/llvm.cpp index 41af5aece..20fdc8b2f 100644 --- a/src/thorin/be/llvm/llvm.cpp +++ b/src/thorin/be/llvm/llvm.cpp @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -51,7 +50,7 @@ CodeGen::CodeGen( , context_(std::make_unique()) , module_(std::make_unique(world().name(), context())) , opt_(opt) - , dibuilder_(module()) + , debug_(debug ? std::make_optional(*this) : std::nullopt) , function_calling_convention_(function_calling_convention) , device_calling_convention_(device_calling_convention) , kernel_calling_convention_(kernel_calling_convention) @@ -295,13 +294,7 @@ void CodeGen::emit_stream(std::ostream& stream) { std::pair, std::unique_ptr> CodeGen::emit_module() { - if (debug()) { - module().addModuleFlag(llvm::Module::Warning, "Debug Info Version", llvm::DEBUG_METADATA_VERSION); - // Darwin only supports dwarf2 - if (llvm::Triple(llvm::sys::getProcessTriple()).isOSDarwin()) - module().addModuleFlag(llvm::Module::Warning, "Dwarf Version", 2); - dicompile_unit_ = dibuilder_.createCompileUnit(llvm::dwarf::DW_LANG_C, dibuilder_.createFile(world().name(), llvm::StringRef()), "Impala", opt() > 0, llvm::StringRef(), 0); - } + if (debug_) debug_->emit_module(); for (auto&& [_, def] : world().externals()) { if (auto global = def->isa()) { @@ -319,7 +312,7 @@ CodeGen::emit_module() { emit_scope(scope, forest); }); - if (debug()) dibuilder_.finalize(); + if (debug_) debug_->finalize(); #if THORIN_ENABLE_RV for (auto [width, fct, call] : vec_todo_) @@ -380,21 +373,7 @@ llvm::Function* CodeGen::emit_fun_decl(Continuation* continuation) { llvm::Function* CodeGen::prepare(const Scope& scope) { auto fct = llvm::cast(emit(scope.entry())); - discope_ = dicompile_unit_; - if (debug()) { - auto file = entry_->loc().file; - auto src_file = llvm::sys::path::filename(file); - auto src_dir = llvm::sys::path::parent_path(file); - auto difile = dibuilder_.createFile(src_file, src_dir); - auto disub_program = dibuilder_.createFunction( - discope_, fct->getName(), fct->getName(), difile, entry_->loc().begin.row, - dibuilder_.createSubroutineType(dibuilder_.getOrCreateTypeArray(llvm::ArrayRef())), - entry_->loc().begin.row, - llvm::DINode::FlagPrototyped, - llvm::DISubprogram::SPFlagDefinition | (opt() > 0 ? llvm::DISubprogram::SPFlagOptimized : llvm::DISubprogram::SPFlagZero)); - fct->setSubprogram(disub_program); - discope_ = disub_program; - } + if (debug_) debug_->prepare(scope, fct); return fct; } @@ -407,11 +386,11 @@ void CodeGen::prepare(Continuation* cont, llvm::Function* fct) { auto& irbuilder = *i->second.second; irbuilder.SetInsertPoint(bb); - if (debug()) - irbuilder.SetCurrentDebugLocation(llvm::DILocation::get(discope_->getContext(), cont->loc().begin.row, cont->loc().begin.col, discope_)); + if (debug_) debug_->prepare(irbuilder, cont); if (entry_ == cont) { auto arg = fct->arg_begin(); + size_t arg_id = 0; for (auto param : entry_->params()) { if (is_mem(param) || is_unit(param)) { defs_[param] = nullptr; @@ -420,13 +399,18 @@ void CodeGen::prepare(Continuation* cont, llvm::Function* fct) { auto value = map_param(fct, argv, param); if (value == argv) { arg->setName(param->unique_name()); // use param - defs_[param] = &*arg++; + defs_[param] = argv; + arg++; } else { defs_[param] = value; // use provided value } + + if (debug_) debug_->register_param(param, arg_id, defs_[param]); } + arg_id++; } } else { + size_t arg_id = 0; for (auto param : cont->params()) { if (is_mem(param) || is_unit(param)) { defs_[param] = nullptr; @@ -434,7 +418,10 @@ void CodeGen::prepare(Continuation* cont, llvm::Function* fct) { // do not bother reserving anything (the 0 below) - it's a tiny optimization nobody cares about auto phi = irbuilder.CreatePHI(convert(param->type()), 0, param->name().c_str()); defs_[param] = phi; + + // if (debug_) debug_->register_param(param, arg_id, defs_[param]); } + arg_id++; } } } @@ -614,19 +601,19 @@ void CodeGen::emit_epilogue(Continuation* continuation) { llvm::Value* CodeGen::emit_constant(const Def* def) { auto irbuilder = llvm::IRBuilder(context()); auto val = emit_builder(irbuilder, def); + if (debug_ && val) debug_->finalize(def, val); return val; } llvm::Value* CodeGen::emit_bb(BB& bb, const Def* def) { auto& irbuilder = *bb.second; auto val = emit_builder(irbuilder, def); + if (debug_ && val) debug_->finalize(def, val); return val; } llvm::Value* CodeGen::emit_builder(llvm::IRBuilder<>& irbuilder, const Def* def) { - // TODO - //if (debug()) - //irbuilder.SetCurrentDebugLocation(llvm::DILocation::get(discope_->getContext(), def->loc().begin.row, def->loc().begin.col, discope_)); + if (debug_) debug_->prepare(irbuilder, def); if (false) {} else if (auto load = def->isa()) return emit_load(irbuilder, load); @@ -1035,10 +1022,11 @@ llvm::AllocaInst* CodeGen::emit_alloca(llvm::IRBuilder<>& irbuilder, llvm::Type* auto entry = &irbuilder.GetInsertBlock()->getParent()->getEntryBlock(); auto layout = module().getDataLayout(); llvm::AllocaInst* alloca; - if (entry->empty()) - alloca = new llvm::AllocaInst(type, layout.getAllocaAddrSpace(), nullptr, name, entry); + llvm::Instruction* insert_before = entry->empty() ? nullptr : entry->getFirstNonPHIOrDbg(); + if (insert_before) + alloca = new llvm::AllocaInst(type, layout.getAllocaAddrSpace(), nullptr, name, insert_before); else - alloca = new llvm::AllocaInst(type, layout.getAllocaAddrSpace(), nullptr, name, entry->getFirstNonPHIOrDbg()); + alloca = new llvm::AllocaInst(type, layout.getAllocaAddrSpace(), nullptr, name, entry); alloca->setAlignment(layout.getABITypeAlign(type)); return alloca; } diff --git a/src/thorin/be/llvm/llvm.h b/src/thorin/be/llvm/llvm.h index 7d5414331..a7f694d83 100644 --- a/src/thorin/be/llvm/llvm.h +++ b/src/thorin/be/llvm/llvm.h @@ -130,17 +130,43 @@ class CodeGen : public thorin::CodeGen, public thorin::Emitter machine_; - llvm::DIBuilder dibuilder_; - llvm::DICompileUnit* dicompile_unit_; llvm::CallingConv::ID function_calling_convention_; llvm::CallingConv::ID device_calling_convention_; llvm::CallingConv::ID kernel_calling_convention_; - llvm::DIScope* discope_ = nullptr; std::unique_ptr runtime_; #if THORIN_ENABLE_RV std::vector> vec_todo_; #endif + struct Debug { + Debug(CodeGen&); + + void emit_module(); + void finalize(); + + void prepare(const Scope&, llvm::Function*); + void prepare(llvm::IRBuilder<>& irbuilder, const Continuation*); + + void prepare(llvm::IRBuilder<>& irbuilder, const Def*); + void finalize(const Def*, llvm::Value*); + + void register_param(const Param* param, int index, llvm::Value*); + + llvm::DIFile* get_difile(const std::string&); + llvm::DILocation* get_dilocation(const Loc&, llvm::DIScope*); + llvm::DIType* get_ditype(const Type*); + + private: + CodeGen& cg_; + + llvm::DIBuilder dibuilder_; + llvm::DICompileUnit* dicompile_unit_; + llvm::DIScope* discope_ = nullptr; + + DefMap types_; + }; + std::optional debug_; + friend class Runtime; }; From c47dc3ae4ac0ae405dad4bbd3c9029837a5e3c39 Mon Sep 17 00:00:00 2001 From: Hugo Devillers Date: Thu, 31 Aug 2023 13:35:12 +0200 Subject: [PATCH 2/2] Made Debug a dumb struct, made Loc optional --- src/thorin/be/c/c.cpp | 4 +- src/thorin/be/llvm/debug.cpp | 52 +++++++++++++-------- src/thorin/be/llvm/llvm.cpp | 2 +- src/thorin/be/llvm/llvm.h | 2 +- src/thorin/debug.h | 52 ++++++--------------- src/thorin/def.h | 2 +- src/thorin/transform/closure_conversion.cpp | 1 - src/thorin/transform/hls_channels.cpp | 4 +- src/thorin/transform/hls_kernel_launch.cpp | 4 +- src/thorin/transform/lift_builtins.cpp | 4 +- src/thorin/world.h | 6 +-- 11 files changed, 59 insertions(+), 74 deletions(-) diff --git a/src/thorin/be/c/c.cpp b/src/thorin/be/c/c.cpp index c0804238b..ab56b9559 100644 --- a/src/thorin/be/c/c.cpp +++ b/src/thorin/be/c/c.cpp @@ -1451,8 +1451,8 @@ std::string CCodeGen::emit_fun_decl(Continuation* cont) { } Stream& CCodeGen::emit_debug_info(Stream& s, const Def* def) { - if (debug_ && !def->loc().file.empty()) - return s.fmt("#line {} \"{}\"\n", def->loc().begin.row, def->loc().file); + if (debug_ && def->loc()) + return s.fmt("#line {} \"{}\"\n", def->loc()->begin.row, def->loc()->file); return s; } diff --git a/src/thorin/be/llvm/debug.cpp b/src/thorin/be/llvm/debug.cpp index ba9b2bed0..336273203 100644 --- a/src/thorin/be/llvm/debug.cpp +++ b/src/thorin/be/llvm/debug.cpp @@ -19,23 +19,29 @@ void CodeGen::Debug::emit_module() { } void CodeGen::Debug::prepare(const thorin::Scope& scope, llvm::Function* fct) { - auto difile = get_difile(cg_.entry_->loc().file); - auto disub_program = dibuilder_.createFunction( - discope_, fct->getName(), fct->getName(), difile, cg_.entry_->loc().begin.row, - dibuilder_.createSubroutineType(dibuilder_.getOrCreateTypeArray(llvm::ArrayRef())), - cg_.entry_->loc().begin.row, - llvm::DINode::FlagPrototyped, - llvm::DISubprogram::SPFlagDefinition | (cg_.opt() > 0 ? llvm::DISubprogram::SPFlagOptimized : llvm::DISubprogram::SPFlagZero)); - fct->setSubprogram(disub_program); - discope_ = disub_program; + if (auto loc = scope.entry()->debug().loc) { + auto difile = get_difile(loc->file); + auto disub_program = dibuilder_.createFunction( + discope_, fct->getName(), fct->getName(), difile, loc->begin.row, + dibuilder_.createSubroutineType(dibuilder_.getOrCreateTypeArray(llvm::ArrayRef())), + loc->begin.row, + llvm::DINode::FlagPrototyped, + llvm::DISubprogram::SPFlagDefinition | (cg_.opt() > 0 ? llvm::DISubprogram::SPFlagOptimized : llvm::DISubprogram::SPFlagZero)); + fct->setSubprogram(disub_program); + discope_ = disub_program; + } else { + discope_ = dicompile_unit_; + } } void CodeGen::Debug::prepare(llvm::IRBuilder<>& irbuilder, const thorin::Continuation* cont) { - irbuilder.SetCurrentDebugLocation(llvm::DILocation::get(discope_->getContext(), cont->loc().begin.row, cont->loc().begin.col, discope_)); + if (auto loc = cont->debug().loc) + irbuilder.SetCurrentDebugLocation(llvm::DILocation::get(discope_->getContext(), loc->begin.row, loc->begin.col, discope_)); } void CodeGen::Debug::prepare(llvm::IRBuilder<>& irbuilder, const thorin::Def* def) { - irbuilder.SetCurrentDebugLocation(llvm::DILocation::get(discope_->getContext(), def->loc().begin.row, def->loc().begin.col, discope_)); + if (auto loc = def->debug().loc) + irbuilder.SetCurrentDebugLocation(llvm::DILocation::get(discope_->getContext(), loc->begin.row, loc->begin.col, discope_)); } void CodeGen::Debug::finalize(const thorin::Def* def, llvm::Value* val) { @@ -45,9 +51,11 @@ void CodeGen::Debug::finalize(const thorin::Def* def, llvm::Value* val) { void CodeGen::Debug::register_param(const Param* param, int index, llvm::Value* val) { if (!param->type()->isa()) return; - llvm::DIFile* file = get_difile(param->debug().loc.file); - auto local_var = dibuilder_.createParameterVariable(discope_, param->name(), index, file, param->debug().loc.begin.row, get_ditype(param->type())); - dibuilder_.insertDbgValueIntrinsic(val, local_var, llvm::DIExpression::get(cg_.context(), {}), get_dilocation(param->debug().loc, discope_), cg_.cont2bb(param->continuation())); + if (auto loc = param->debug().loc; loc) { + llvm::DIFile* file = get_difile(loc->file); + auto local_var = dibuilder_.createParameterVariable(discope_, param->name(), index, file, loc->begin.row, get_ditype(param->type(), *loc)); + dibuilder_.insertDbgValueIntrinsic(val, local_var, llvm::DIExpression::get(cg_.context(), {}), get_dilocation(*loc, discope_), cg_.cont2bb(param->continuation())); + } } llvm::DIFile* CodeGen::Debug::get_difile(const std::string& file) { @@ -60,10 +68,14 @@ llvm::DILocation* CodeGen::Debug::get_dilocation(const thorin::Loc& loc, llvm::D return llvm::DILocation::get(cg_.context(), loc.begin.row, loc.begin.col, discope); } -llvm::DIType* CodeGen::Debug::get_ditype(const thorin::Type* t) { +llvm::DIType* CodeGen::Debug::get_ditype(const thorin::Type* t, Loc loc) { if (auto found = types_.lookup(t)) return *found; + // If the type comes with its own debug info, let's use that instead! + if (t->debug().loc) + loc = *t->debug().loc; + using namespace llvm::dwarf; if (auto prim_type = t->isa()) { @@ -78,19 +90,19 @@ llvm::DIType* CodeGen::Debug::get_ditype(const thorin::Type* t) { case PrimType_pf64: case PrimType_qf64: return types_[t] = dibuilder_.createBasicType("bool", 64, DW_ATE_float); } } else if (auto ptr_t = t->isa()) { - return types_[t] = dibuilder_.createPointerType(get_ditype(ptr_t->pointee()), cg_.machine_->getPointerSize(static_cast(ptr_t->addr_space()))); + return types_[t] = dibuilder_.createPointerType(get_ditype(ptr_t->pointee(), loc), cg_.machine_->getPointerSize(static_cast(ptr_t->addr_space()))); } else if (auto fun_t = t->isa()) { } else if (auto agg_t = t->isa()) { - types_[t] = dibuilder_.createForwardDecl(DW_TAG_structure_type, agg_t->name().str(), dicompile_unit_, get_difile(t->debug().loc.file), t->debug().loc.begin.row); + types_[t] = dibuilder_.createForwardDecl(DW_TAG_structure_type, agg_t->name().str(), dicompile_unit_, get_difile(loc.file), loc.begin.row); auto data_layout = cg_.module().getDataLayout(); auto layout_t = data_layout.getStructLayout(llvm::cast(cg_.convert(t))); std::vector members; size_t i = 0; for (auto member_t : agg_t->types()) { - auto member_di = get_ditype(member_t); + auto member_di = get_ditype(member_t, loc); auto member_llvm_t = cg_.convert(member_t); - auto derived = dibuilder_.createMemberType(dicompile_unit_, agg_t->op_name(i).str(), get_difile(t->debug().loc.file), t->debug().loc.begin.row, + auto derived = dibuilder_.createMemberType(dicompile_unit_, agg_t->op_name(i).str(), get_difile(loc.file), loc.begin.row, data_layout.getTypeSizeInBits(member_llvm_t), data_layout.getABITypeAlign(member_llvm_t).value(), layout_t->getElementOffsetInBits(i), @@ -98,7 +110,7 @@ llvm::DIType* CodeGen::Debug::get_ditype(const thorin::Type* t) { member_di); i++; } - return types_[t] = dibuilder_.createStructType(dicompile_unit_, agg_t->name().str(), get_difile(t->debug().loc.file), t->debug().loc.begin.row, + return types_[t] = dibuilder_.createStructType(dicompile_unit_, agg_t->name().str(), get_difile(loc.file), loc.begin.row, layout_t->getSizeInBits(), layout_t->getAlignment().value(), llvm::DINode::DIFlags::FlagZero, diff --git a/src/thorin/be/llvm/llvm.cpp b/src/thorin/be/llvm/llvm.cpp index 20fdc8b2f..8257284ba 100644 --- a/src/thorin/be/llvm/llvm.cpp +++ b/src/thorin/be/llvm/llvm.cpp @@ -977,7 +977,7 @@ llvm::Value* CodeGen::emit_builder(llvm::IRBuilder<>& irbuilder, const Def* def) } else if (auto vector = def->isa()) { llvm::Value* vec = llvm::UndefValue::get(convert(vector->type())); for (size_t i = 0, e = vector->num_ops(); i != e; ++i) - vec = irbuilder.CreateInsertElement(vec, emit(vector->op(i)), emit(world().literal_pu32(i, vector->loc()))); + vec = irbuilder.CreateInsertElement(vec, emit(vector->op(i)), emit(world().literal_pu32(i, vector->debug()))); return vec; } else if (auto global = def->isa()) { diff --git a/src/thorin/be/llvm/llvm.h b/src/thorin/be/llvm/llvm.h index a7f694d83..65bf28439 100644 --- a/src/thorin/be/llvm/llvm.h +++ b/src/thorin/be/llvm/llvm.h @@ -154,7 +154,7 @@ class CodeGen : public thorin::CodeGen, public thorin::Emitter #include +#include #include "thorin/config.h" #include "thorin/util/stream.h" @@ -13,8 +14,8 @@ class Def; class World; struct Pos { - uint32_t row = -1; - uint32_t col = -1; + uint32_t row; + uint32_t col; }; struct Loc : public Streamable { @@ -33,48 +34,21 @@ struct Loc : public Streamable { Loc anew_finis() const { return {file, finis, finis}; } std::string file; - Pos begin = {uint32_t(-1), uint32_t(-1)}; - Pos finis = {uint32_t(-1), uint32_t(-1)}; + Pos begin; + Pos finis; Stream& stream(Stream&) const; }; -class Debug { -public: - Debug() = default; // TODO remove - Debug(std::string name, Loc loc = {}, const Def* meta = nullptr) - : name(name) -#if THORIN_ENABLE_CREATION_CONTEXT - , creation_context("") -#endif - , loc(loc) - , meta(meta) - {} - Debug(const char* name, Loc loc = {}, const Def* meta = nullptr) - : Debug(std::string(name), loc, meta) - {} -#if THORIN_ENABLE_CREATION_CONTEXT - Debug(std::string name, std::string creation_context, Loc loc = {}, const Def* meta = nullptr) - : name(name) - , creation_context(creation_context) - , loc(loc) - , meta(meta) - {} - Debug(const char* name, const char* creation_context, Loc loc = {}, const Def* meta = nullptr) - : Debug(std::string(name), std::string(creation_context), loc, meta) - {} -#endif - Debug(Loc loc) - : Debug("", loc) - {} - //Debug(const Def*); +struct Debug { + std::string name = ""; + std::optional loc = std::nullopt; - std::string name; -#if THORIN_ENABLE_CREATION_CONTEXT - std::string creation_context; -#endif - Loc loc; - const Def* meta = nullptr; + inline Debug with_name(std::string new_name) { + Debug d = *this; + d.name = new_name; + return d; + } }; } diff --git a/src/thorin/def.h b/src/thorin/def.h index 83419e8dc..83c714833 100644 --- a/src/thorin/def.h +++ b/src/thorin/def.h @@ -190,7 +190,7 @@ class Def : public RuntimeCast, public Streamable { /// In Debug build if @c World::enable_history is @c true, this thing keeps the @p gid to track a history of @p gid%s. Debug debug_history() const; std::string name() const { return debug().name; } - Loc loc() const { return debug().loc; } + std::optional loc() const { return debug().loc; } void set_name(const std::string&) const; std::string unique_name() const; //@} diff --git a/src/thorin/transform/closure_conversion.cpp b/src/thorin/transform/closure_conversion.cpp index 9140f4132..dd5286a92 100644 --- a/src/thorin/transform/closure_conversion.cpp +++ b/src/thorin/transform/closure_conversion.cpp @@ -237,7 +237,6 @@ class ClosureConversion { ContinuationSet converted_; }; - void closure_conversion(World& world) { ClosureConversion(world).run(); } diff --git a/src/thorin/transform/hls_channels.cpp b/src/thorin/transform/hls_channels.cpp index a5e968a79..975495cfb 100644 --- a/src/thorin/transform/hls_channels.cpp +++ b/src/thorin/transform/hls_channels.cpp @@ -250,7 +250,7 @@ DeviceParams hls_channels(Thorin& thorin, Importer& importer, Top2Kernel& top2ke } } - auto hls_top = world.continuation(world.fn_type(top_param_types), Debug("hls_top")); + auto hls_top = world.continuation(world.fn_type(top_param_types), { "hls_top" } ); for (auto tuple : param_index) { // (non-channel params, top params as kernel call args) auto param = std::get<0>(tuple)->param(std::get<1>(tuple)); @@ -378,7 +378,7 @@ DeviceParams hls_channels(Thorin& thorin, Importer& importer, Top2Kernel& top2ke auto ret_type = ret_param->type()->as(); bool last_kernel = kernel == new_kernels.back(); const Def* hls_top_ret = hls_top->param(1); - const Def* ret = last_kernel ? hls_top_ret : world.continuation(ret_type, Debug("next_kernel")); + const Def* ret = last_kernel ? hls_top_ret : world.continuation(ret_type, { "next_kernel" }); // Fill the array of arguments Array args(kernel->type()->num_ops()); for (size_t i = 0; i < kernel->type()->num_ops(); ++i) { diff --git a/src/thorin/transform/hls_kernel_launch.cpp b/src/thorin/transform/hls_kernel_launch.cpp index 94c3f32ed..73ab0c3a2 100644 --- a/src/thorin/transform/hls_kernel_launch.cpp +++ b/src/thorin/transform/hls_kernel_launch.cpp @@ -40,7 +40,7 @@ static Continuation* make_opencl_intrinsic(World& world, const Continuation* con auto opencl_type = world.fn_type(opencl_param_types); - auto opencl = world.continuation(opencl_type, Intrinsic::OpenCL, Debug("opencl")); + auto opencl = world.continuation(opencl_type, Intrinsic::OpenCL, { "opencl" }); return opencl; } @@ -100,7 +100,7 @@ void hls_kernel_launch(World& world, DeviceParams& device_params) { // Building a dummy hls_top function auto hls_top_fn_type = opencl->param(4)->type()->as()->pointee()->as(); - auto hls_top_fn = world.continuation(hls_top_fn_type, Debug("hls_top")); + auto hls_top_fn = world.continuation(hls_top_fn_type, { "hls_top" }); auto hls_top_global = world.global(hls_top_fn,false); opencl_args[4] = hls_top_global; diff --git a/src/thorin/transform/lift_builtins.cpp b/src/thorin/transform/lift_builtins.cpp index 6bd509da6..810d4001f 100644 --- a/src/thorin/transform/lift_builtins.cpp +++ b/src/thorin/transform/lift_builtins.cpp @@ -48,8 +48,8 @@ void lift_pipeline(World& world) { // Note the use of 'return' as the second argument to pipeline_continue. // This is required to encode the dependence of the loop body over the call to pipeline, // so that lift_builtins can extract the correct free variables. - auto pipeline_continue = world.continuation(p_cont_type, Intrinsic::PipelineContinue, Debug("pipeline_continue")); - auto continue_wrapper = world.continuation(cont_type, Debug("continue_wrapper")); + auto pipeline_continue = world.continuation(p_cont_type, Intrinsic::PipelineContinue, Debug { "pipeline_continue" }); + auto continue_wrapper = world.continuation(cont_type, Debug { "continue_wrapper" }); auto new_pipeline = world.continuation(pipe_type, Intrinsic::Pipeline, callee->debug()); auto old_body = body->arg(4); auto body_cont = world.continuation(body_type, old_body->debug()); diff --git a/src/thorin/world.h b/src/thorin/world.h index 547dfdca6..fd858a895 100644 --- a/src/thorin/world.h +++ b/src/thorin/world.h @@ -313,15 +313,15 @@ class World : public Streamable { void set(std::shared_ptr stream) { stream_ = stream; } template - void log(LogLevel level, Loc loc, const char* fmt, Args&&... args) { + void log(LogLevel level, std::optional loc, const char* fmt, Args&&... args) { if (stream_ && int(min_level()) <= int(level)) { - stream().fmt("{}:{}: ", colorize(level2string(level), level2color(level)), colorize(loc.to_string(), 7)); + stream().fmt("{}:{}: ", colorize(level2string(level), level2color(level)), colorize(loc ? loc->to_string() : "", 7)); stream().fmt(fmt, std::forward(args)...).endl().flush(); } } template - [[noreturn]] void error(Loc loc, const char* fmt, Args&&... args) { + [[noreturn]] void error(std::optional loc, const char* fmt, Args&&... args) { log(LogLevel::Error, loc, fmt, std::forward(args)...); std::abort(); }