From b976bfc7119e18c2bc14cf9359f4699eac33089c Mon Sep 17 00:00:00 2001 From: Eric Lunderberg Date: Wed, 7 Feb 2024 16:26:13 -0600 Subject: [PATCH 1/6] [TIR] Expand debug symbol output for CodeGenLLVM Prior to this commit, the `CodeGenLLVM` would include DWARF symbols specifying the function signature of each TIR function. This commit expands the information exposed in the debug symbols. * Name functions based on the name of the corresponding TIR function. This is taken either from the `attr::kGlobalSymbol` if present, or the PrimFunc's `GlobalVar` otherwise. * Name function parameter based on their TIR variable name. * Annotate the name, the type signature, and parameter names for the private function produced by the `tir::attr::compute_scope` attribute. * Name local variables based on the name and type of the corresponding TIR variable. --- src/target/llvm/codegen_cpu.cc | 151 ++++++++---------------------- src/target/llvm/codegen_cpu.h | 16 ++-- src/target/llvm/codegen_llvm.cc | 159 +++++++++++++++++++++++++++++--- src/target/llvm/codegen_llvm.h | 19 +++- src/target/llvm/llvm_module.cc | 19 ++-- 5 files changed, 217 insertions(+), 147 deletions(-) diff --git a/src/target/llvm/codegen_cpu.cc b/src/target/llvm/codegen_cpu.cc index a778aa5281ae..cd56fa368c18 100644 --- a/src/target/llvm/codegen_cpu.cc +++ b/src/target/llvm/codegen_cpu.cc @@ -185,13 +185,18 @@ void CodeGenCPU::Init(const std::string& module_name, LLVMTarget* llvm_target, InitGlobalContext(dynamic_lookup); } -llvm::DISubprogram* CodeGenCPU::CreateDebugFunction(const PrimFunc& f) { -#if TVM_LLVM_VERSION >= 50 +llvm::DISubprogram* CodeGenCPU::CreateDebugFunction( + llvm::StringRef name, const Array& param_types, const Type& return_type +) { +#if TVM_LLVM_VERSION < 50 + return nullptr; +#else + llvm::SmallVector paramTys; - paramTys.push_back(GetDebugType(f->ret_type)); - for (const auto& param : f->params) { - paramTys.push_back(GetDebugType(GetType(param))); + paramTys.push_back(GetDebugType(return_type)); + for (const auto& param_type : param_types) { + paramTys.push_back(GetDebugType(param_type)); } auto* DIFunctionTy = dbg_info_->di_builder_->createSubroutineType( @@ -199,131 +204,42 @@ llvm::DISubprogram* CodeGenCPU::CreateDebugFunction(const PrimFunc& f) { bool local_to_unit = llvm::GlobalVariable::isLocalLinkage(llvm::GlobalValue::InternalLinkage); - // TODO(driazati): determine the IRModule name instead of hardcoding 'main.tir' #if TVM_LLVM_VERSION >= 80 auto SPFlags = llvm::DISubprogram::toSPFlags(local_to_unit, /*IsDefinition=*/true, /*IsOptimized=*/true); - auto* DIFunction = dbg_info_->di_builder_->createFunction( - /*Scope=*/dbg_info_->file_, /*Name=*/"main.tir", /*LinkageName=*/"", - /*File=*/dbg_info_->file_, /*LineNo=*/0, /*Ty=*/DIFunctionTy, - /*ScopeLine=*/0, /*Flags=*/llvm::DINode::FlagZero, /*SPFlags=*/SPFlags); #else + bool SPFlags = /*IsOptimized=*/true; +#endif + auto* DIFunction = dbg_info_->di_builder_->createFunction( - /*Scope=*/dbg_info_->file_, /*Name=*/"main.tir", /*LinkageName=*/"", + /*Scope=*/dbg_info_->file_, /*Name=*/name, /*LinkageName=*/"", /*File=*/dbg_info_->file_, /*LineNo=*/0, /*Ty=*/DIFunctionTy, - /*isLocalToUnit=*/local_to_unit, /*isDefinition=*/true, /*ScopeLine=*/0, - /*Flags=*/llvm::DINode::FlagPrototyped, /*isOptimized=*/true); -#endif + /*ScopeLine=*/0, /*Flags=*/llvm::DINode::FlagPrototyped, /*SPFlags=*/SPFlags); + return DIFunction; -#else - return nullptr; + #endif } -void CodeGenCPU::AddFunction(const GlobalVar& gvar, const PrimFunc& f) { -#if TVM_LLVM_VERSION >= 50 - di_subprogram_ = CreateDebugFunction(f); -#endif - EmitDebugLocation(f->span); - CodeGenLLVM::AddFunction(gvar, f); +llvm::DISubprogram* CodeGenCPU::CreateDebugFunction(const GlobalVar& gvar, const PrimFunc& func) { + std::string name = func->GetAttr(tvm::attr::kGlobalSymbol).value_or(gvar->name_hint); + return CreateDebugFunction(name, func->params.Map(GetType), func->ret_type); +} + +void CodeGenCPU::AddFunction(const GlobalVar& gvar, const PrimFunc& func) { + di_subprogram_ = CreateDebugFunction(gvar, func); + EmitDebugLocation(func->span); + CodeGenLLVM::AddFunction(gvar, func); if (f_tvm_register_system_symbol_ != nullptr) { - if (auto global_symbol = f->GetAttr(tvm::attr::kGlobalSymbol)) { + if (auto global_symbol = func->GetAttr(tvm::attr::kGlobalSymbol)) { export_system_symbols_.emplace_back( std::make_pair(global_symbol.value().operator std::string(), function_)); } } - AddDebugInformation(f, function_); + AddDebugInformation(function_, func->params.Map(GetType)); } -// Following Glow |DebugInfo::generateFunctionDebugInfo|, https://git.io/fjadv -void CodeGenCPU::AddDebugInformation(PrimFunc f_tir, llvm::Function* f_llvm) { -#if TVM_LLVM_VERSION >= 50 - ICHECK(di_subprogram_); - f_llvm->setSubprogram(di_subprogram_); - ICHECK_EQ(f_llvm->getSubprogram(), di_subprogram_); - IRBuilder builder(&f_llvm->getEntryBlock()); - if (!f_llvm->getEntryBlock().empty()) { - builder.SetInsertPoint(&f_llvm->getEntryBlock().front()); - } - llvm::DebugLoc DL; - builder.SetCurrentDebugLocation(DL); - llvm::LLVMContext* ctx = llvm_target_->GetContext(); - for (size_t i = 0; i < f_llvm->arg_size(); ++i) { - auto* paramAlloca = builder.CreateAlloca(f_llvm->getFunctionType()->getParamType(i)); - std::string paramName = "arg" + std::to_string(i + 1); - auto param = dbg_info_->di_builder_->createParameterVariable( - di_subprogram_, paramName, i + 1, dbg_info_->file_, 0, - GetDebugType(GetType(f_tir->params[i]), f_llvm->getFunctionType()->getParamType(i)), - /*alwaysPreserve=*/true); - auto* store = builder.CreateStore(f_llvm->arg_begin() + i, paramAlloca); - auto* di_loc = llvm::DILocation::get(*ctx, 0, 0, di_subprogram_); - dbg_info_->di_builder_->insertDeclare(paramAlloca, param, - dbg_info_->di_builder_->createExpression(), - llvm::DebugLoc(di_loc), store); - } - dbg_info_->di_builder_->finalizeSubprogram(f_llvm->getSubprogram()); - auto* scope = f_llvm->getSubprogram(); - if (!scope) { - return; - } - - for (auto& BB : *f_llvm) { - for (auto& I : BB) { - if (I.getDebugLoc()) { - continue; - } - auto* di_loc = llvm::DILocation::get(*ctx, 0, 0, scope); - I.setDebugLoc(llvm::DebugLoc(di_loc)); - } - } -#endif -} - -llvm::DIType* CodeGenCPU::GetDebugType(const Type& ty_tir) { - return GetDebugType(ty_tir, GetLLVMType(ty_tir)); -} -llvm::DIType* CodeGenCPU::GetDebugType(const Type& ty_tir, llvm::Type* ty_llvm) { - if (ty_llvm == t_void_) { - return nullptr; - - } else if (ty_llvm->isPointerTy()) { - auto* ptr_type = ty_tir.as(); - ICHECK(ptr_type != nullptr || GetRuntimeDataType(ty_tir).is_handle()) - << "Got LLVM pointer type from non-pointer IR type: " << ty_tir; - auto* pointee_type = ptr_type != nullptr ? GetDebugType(ptr_type->element_type, - GetLLVMType(ptr_type->element_type)) - : nullptr; - return dbg_info_->di_builder_->createPointerType(pointee_type, - ty_llvm->getPrimitiveSizeInBits()); - - } else if (auto* prim_type = ty_tir.as()) { - DataType dtype = prim_type->dtype; - auto dwarf_type = [&]() -> llvm::dwarf::TypeKind { - if (dtype.is_bool()) { - return llvm::dwarf::DW_ATE_boolean; - } else if (dtype.is_float()) { - return llvm::dwarf::DW_ATE_float; - } else if (dtype.is_int()) { - return llvm::dwarf::DW_ATE_signed; - } else if (dtype.is_uint()) { - return llvm::dwarf::DW_ATE_unsigned; - } else { - LOG(FATAL) << "No DWARF representation for TIR type " << dtype; - } - }(); - - return dbg_info_->di_builder_->createBasicType(DLDataType2String(dtype), - dtype.bits() * dtype.lanes(), dwarf_type); - - } else { - std::string type_str; - llvm::raw_string_ostream rso(type_str); - ty_llvm->print(rso); - LOG(FATAL) << "Unknown LLVM type:" << rso.str(); - } - return nullptr; -} void CodeGenCPU::AddMainFunction(const std::string& entry_func_name) { llvm::Function* f = module_->getFunction(entry_func_name); @@ -570,15 +486,18 @@ void CodeGenCPU::CreateComputeScope(const AttrStmtNode* op) { std::swap(function_, parent_->function_); std::swap(analyzer_, parent_->analyzer_); std::swap(var_map_, parent_->var_map_); + std::swap(di_subprogram_, parent_->di_subprogram_); } void ExitWithScope() { std::swap(function_, parent_->function_); std::swap(analyzer_, parent_->analyzer_); std::swap(var_map_, parent_->var_map_); + std::swap(di_subprogram_, parent_->di_subprogram_); } llvm::Function* function_{nullptr}; + llvm::DISubprogram* di_subprogram_{nullptr}; std::unordered_map var_map_; std::unique_ptr analyzer_{std::make_unique()}; CodeGenCPU* parent_; @@ -606,6 +525,11 @@ void CodeGenCPU::CreateComputeScope(const AttrStmtNode* op) { llvm::Function* fcompute = llvm::Function::Create(ftype, llvm::Function::InternalLinkage, MakeStringRef(value->value), module_.get()); SetTargetAttributes(fcompute); + for(auto it = fcompute->arg_begin(); it!=fcompute->arg_end(); it++) { + const Var& var = vargs[std::distance(fcompute->arg_begin(), it)]; + it->setName(std::string(var->name_hint)); + } + llvm::BasicBlock* compute_call_end = CheckCallSuccess(builder_->CreateCall(fcompute, arg_values)); llvm::LLVMContext* ctx = llvm_target_->GetContext(); @@ -640,11 +564,14 @@ void CodeGenCPU::CreateComputeScope(const AttrStmtNode* op) { } function_ = fcompute; + di_subprogram_ = CreateDebugFunction(MakeStringRef(value->value), vargs.Map(GetType), PrimType(DataType::Int(32))); auto* compute_entry = llvm::BasicBlock::Create(*ctx, "entry", function_); builder_->SetInsertPoint(compute_entry); this->VisitStmt(op->body); builder_->CreateRet(ConstInt32(0)); builder_->SetInsertPoint(compute_call_end); + + AddDebugInformation(fcompute, vargs.Map(GetType)); } CodeGenLLVM::TypedPointer CodeGenCPU::PackClosureData(const Array& vfields, diff --git a/src/target/llvm/codegen_cpu.h b/src/target/llvm/codegen_cpu.h index 2924aee46e6b..91fe1bc18631 100644 --- a/src/target/llvm/codegen_cpu.h +++ b/src/target/llvm/codegen_cpu.h @@ -165,7 +165,11 @@ class CodeGenCPU : public CodeGenLLVM { // if not directly finalize function and pass on return code. // return the end block after the check llvm::BasicBlock* CheckCallSuccess(llvm::Value* retcode); - llvm::DISubprogram* CreateDebugFunction(const PrimFunc& f); + + llvm::DISubprogram* CreateDebugFunction(const GlobalVar& gvar, const PrimFunc& f); + llvm::DISubprogram* CreateDebugFunction(llvm::StringRef name, const Array& param_types, + const Type& return_type); + // Context for injection lookup llvm::GlobalVariable* gv_mod_ctx_{nullptr}; llvm::GlobalVariable* gv_tvm_func_call_{nullptr}; @@ -189,19 +193,11 @@ class CodeGenCPU : public CodeGenLLVM { std::vector> export_system_symbols_; // List of functions to be registered in the FuncRegistry, if generated. std::vector> registry_functions_; - // internal debug information, to be populated by - std::unique_ptr dbg_info_; + bool target_c_runtime_; // The system lib prefix if it is not nullopt, then we should do // system lib registration with the given prefix. The prefix can be "" Optional system_lib_prefix_; - - // Get the DWARF type corresponding to the LLVM type |ty|. The current API in practice only - // generates |int32|, and |int8*|. - llvm::DIType* GetDebugType(const Type& ty_tir); - llvm::DIType* GetDebugType(const Type& ty_tir, llvm::Type* ty_llvm); - // Adds the DWARF debug information for |function| to |dbg_info_|. - void AddDebugInformation(PrimFunc f_tir, llvm::Function* f_llvm); }; } // namespace codegen diff --git a/src/target/llvm/codegen_llvm.cc b/src/target/llvm/codegen_llvm.cc index a689183d8f48..e8202f4c3bd7 100644 --- a/src/target/llvm/codegen_llvm.cc +++ b/src/target/llvm/codegen_llvm.cc @@ -739,7 +739,7 @@ std::unique_ptr CodeGenLLVM::CreateDebugInfo(llvm::Modul debug_info->di_builder_ = llvm::make_unique(*module); #endif // TODO(tulloch): pass this information through relay::Span classes to the IRModule instance? - debug_info->file_ = debug_info->di_builder_->createFile("main.tir", "."); + debug_info->file_ = debug_info->di_builder_->createFile("IRModule.CodeGenLLVM", "."); const int runtime_version = 0; const bool is_optimized = false; const char* compiler_flags = ""; @@ -866,7 +866,6 @@ llvm::Value* CodeGenLLVM::CreateVecConcat(std::vector vecs) { void CodeGenLLVM::CreateSerialFor(llvm::Value* begin, llvm::Value* end, llvm::Value* stride, const Var& loop_var, const Stmt& body) { - EmitDebugLocation(body->span); llvm::BasicBlock* pre_block = builder_->GetInsertBlock(); std::string loop_var_name = loop_var->name_hint; llvm::LLVMContext* ctx = llvm_target_->GetContext(); @@ -875,14 +874,18 @@ void CodeGenLLVM::CreateSerialFor(llvm::Value* begin, llvm::Value* end, llvm::Va auto* for_end = llvm::BasicBlock::Create(*ctx, "for_end_" + loop_var_name, function_); builder_->CreateBr(for_begin); builder_->SetInsertPoint(for_begin); + llvm::PHINode* loop_value = builder_->CreatePHI(begin->getType(), 2); - loop_value->setName(loop_var->name_hint.c_str()); + AddDebugInformation(loop_value, loop_var); loop_value->addIncoming(begin, pre_block); ICHECK(!var_map_.count(loop_var.get())); var_map_[loop_var.get()] = loop_value; + auto lt = CreateLT(loop_var.dtype(), loop_value, end); builder_->CreateCondBr(lt, for_body, for_end, md_very_likely_branch_); builder_->SetInsertPoint(for_body); + EmitDebugLocation(body->span); + this->VisitStmt(body); var_map_.erase(loop_var.get()); llvm::Value* loop_next = CreateAdd(loop_var.dtype(), loop_value, stride); @@ -947,10 +950,13 @@ llvm::Constant* CodeGenLLVM::GetGlobalConstant(llvm::Constant* const_data, const } llvm::Constant* CodeGenLLVM::GetConstString(const std::string& str) { - auto it = str_map_.find(str); - if (it != str_map_.end()) return it->second; + if (auto it = str_map_.find(str); it != str_map_.end()) { + return it->second; + } + auto llvm_str = llvm::ConstantDataArray::getString(*llvm_target_->GetContext(), str); auto ptr = GetGlobalConstant(llvm_str, ".str", llvm::GlobalValue::PrivateLinkage); + str_map_[str] = ptr; return ptr; } @@ -1651,7 +1657,7 @@ llvm::Value* CodeGenLLVM::VisitExpr_(const LetNode* op) { } auto var_value = MakeValue(op->value); var_map_[op->var.get()] = var_value; - var_value->setName(op->var->name_hint.c_str()); + AddDebugInformation(var_value, op->var); analyzer_->Bind(op->var, op->value); return MakeValue(op->body); } @@ -1998,7 +2004,7 @@ void CodeGenLLVM::VisitStmt_(const AllocateNode* op) { buf = builder_->CreatePointerCast( buf, DTypeToLLVMType(op->dtype)->getPointerTo(buf->getType()->getPointerAddressSpace())); - buf->setName(op->buffer_var->name_hint.c_str()); + AddDebugInformation(buf, op->buffer_var); ICHECK(!var_map_.count(op->buffer_var.get())); var_map_[op->buffer_var.get()] = buf; @@ -2064,13 +2070,14 @@ void CodeGenLLVM::VisitStmt_(const LetStmtNode* op) { } } - value->setName(v->name_hint.c_str()); + AddDebugInformation(value, op->var); var_map_[v] = value; analyzer_->Bind(op->var, op->value); if (alloc_storage_info_.count(v) && alloc_storage_info_[v].alignment > 1) { builder_->CreateAlignmentAssumption(*data_layout_, GetVarValue(v), alloc_storage_info_[v].alignment); } + AddDebugInformation(value, op->var); this->VisitStmt(op->body); } @@ -2091,18 +2098,23 @@ void CodeGenLLVM::VisitStmt_(const EvaluateNode* op) { MakeValue(op->value); } -void CodeGenLLVM::EmitDebugLocation(const Span& span) { +void CodeGenLLVM::EmitDebugLocation(const Optional& span) { #if TVM_LLVM_VERSION >= 50 if (di_subprogram_ == nullptr) { // debug info is not always generated outside of CPU codegen return; } - if (!span.defined()) { - VLOG(0) << "Cannot emit debug location for undefined span"; - return; - } + llvm::LLVMContext* ctx = llvm_target_->GetContext(); - auto loc = llvm::DebugLoc(llvm::DILocation::get(*ctx, span->line, span->column, di_subprogram_)); + int line = 0; + int column = 0; + if (span) { + auto ptr = span.as(); + line = ptr->line; + column = ptr->column; + } + + auto loc = llvm::DebugLoc(llvm::DILocation::get(*ctx, line, column, di_subprogram_)); builder_->SetCurrentDebugLocation(loc); #endif } @@ -2110,6 +2122,125 @@ void CodeGenLLVM::EmitDebugLocation(const Span& span) { void CodeGenLLVM::EmitDebugLocation() { builder_->SetCurrentDebugLocation(nullptr); } void CodeGenLLVM::EmitDebugLocation(const StmtNode* op) { EmitDebugLocation(op->span); } +// Following Glow |DebugInfo::generateFunctionDebugInfo|, https://git.io/fjadv +void CodeGenLLVM::AddDebugInformation(llvm::Function* f_llvm, const Array& tvm_param_types) { +#if TVM_LLVM_VERSION >= 50 + ICHECK(di_subprogram_); + f_llvm->setSubprogram(di_subprogram_); + ICHECK_EQ(f_llvm->getSubprogram(), di_subprogram_); + + IRBuilder builder(&f_llvm->getEntryBlock()); + if (!f_llvm->getEntryBlock().empty()) { + builder.SetInsertPoint(&f_llvm->getEntryBlock().front()); + } + llvm::DebugLoc DL; + builder.SetCurrentDebugLocation(DL); + llvm::LLVMContext* ctx = llvm_target_->GetContext(); + + ICHECK_EQ(f_llvm->arg_size(), tvm_param_types.size()); + for (auto iter_param = f_llvm->arg_begin(); iter_param != f_llvm->arg_end(); iter_param++) { + size_t i = std::distance(f_llvm->arg_begin(), iter_param); + auto* paramAlloca = builder.CreateAlloca(iter_param->getType()); + + auto param = dbg_info_->di_builder_->createParameterVariable( + di_subprogram_, iter_param->getName(), i + 1, dbg_info_->file_, 0, + GetDebugType(tvm_param_types[i], iter_param->getType()), + /*alwaysPreserve=*/true); + + auto* store = builder.CreateStore(iter_param, paramAlloca); + auto* di_loc = llvm::DILocation::get(*ctx, 0, 0, di_subprogram_); + dbg_info_->di_builder_->insertDeclare(paramAlloca, param, + dbg_info_->di_builder_->createExpression(), + llvm::DebugLoc(di_loc), store); + } + dbg_info_->di_builder_->finalizeSubprogram(f_llvm->getSubprogram()); + auto* scope = f_llvm->getSubprogram(); + if (!scope) { + return; + } + + for (auto& BB : *f_llvm) { + for (auto& I : BB) { + if (I.getDebugLoc()) { + continue; + } + auto* di_loc = llvm::DILocation::get(*ctx, 0, 0, scope); + I.setDebugLoc(llvm::DebugLoc(di_loc)); + } + } +#endif +} + +void CodeGenLLVM::AddDebugInformation(llvm::Value* llvm_value, const Var& tir_var, + llvm::Instruction* insert_before) { + llvm_value->setName(tir_var->name_hint.c_str()); + +#if TVM_LLVM_VERSION >= 50 + if (!di_subprogram_) return; + + auto local_var = dbg_info_->di_builder_->createAutoVariable( + di_subprogram_, std::string(tir_var->name_hint), dbg_info_->file_, 0, + GetDebugType(GetType(tir_var))); + + auto* di_loc = llvm::DILocation::get(*llvm_target_->GetContext(), 0, 0, di_subprogram_); + + if (insert_before) { + dbg_info_->di_builder_->insertDeclare(llvm_value, local_var, + dbg_info_->di_builder_->createExpression(), + llvm::DebugLoc(di_loc), insert_before); + } else { + dbg_info_->di_builder_->insertDeclare(llvm_value, local_var, + dbg_info_->di_builder_->createExpression(), + llvm::DebugLoc(di_loc), builder_->GetInsertBlock()); + } +#endif +} + +llvm::DIType* CodeGenLLVM::GetDebugType(const Type& ty_tir) { + return GetDebugType(ty_tir, GetLLVMType(ty_tir)); +} +llvm::DIType* CodeGenLLVM::GetDebugType(const Type& ty_tir, llvm::Type* ty_llvm) { + if (ty_llvm == t_void_) { + return nullptr; + + } else if (ty_llvm->isPointerTy()) { + auto* ptr_type = ty_tir.as(); + ICHECK(ptr_type != nullptr || GetRuntimeDataType(ty_tir).is_handle()) + << "Got LLVM pointer type from non-pointer IR type: " << ty_tir; + auto* pointee_type = ptr_type != nullptr ? GetDebugType(ptr_type->element_type, + GetLLVMType(ptr_type->element_type)) + : nullptr; + return dbg_info_->di_builder_->createPointerType(pointee_type, + ty_llvm->getPrimitiveSizeInBits()); + + } else if (auto* prim_type = ty_tir.as()) { + DataType dtype = prim_type->dtype; + auto dwarf_type = [&]() -> llvm::dwarf::TypeKind { + if (dtype.is_bool()) { + return llvm::dwarf::DW_ATE_boolean; + } else if (dtype.is_float()) { + return llvm::dwarf::DW_ATE_float; + } else if (dtype.is_int()) { + return llvm::dwarf::DW_ATE_signed; + } else if (dtype.is_uint()) { + return llvm::dwarf::DW_ATE_unsigned; + } else { + LOG(FATAL) << "No DWARF representation for TIR type " << dtype; + } + }(); + + return dbg_info_->di_builder_->createBasicType(DLDataType2String(dtype), + dtype.bits() * dtype.lanes(), dwarf_type); + + } else { + std::string type_str; + llvm::raw_string_ostream rso(type_str); + ty_llvm->print(rso); + LOG(FATAL) << "Unknown LLVM type:" << rso.str(); + } + return nullptr; +} + TVM_REGISTER_GLOBAL("tvm.codegen.llvm.GetDefaultTargetTriple").set_body_typed([]() -> std::string { return llvm::sys::getDefaultTargetTriple(); }); diff --git a/src/target/llvm/codegen_llvm.h b/src/target/llvm/codegen_llvm.h index 8c8929c8f093..2efac0307345 100644 --- a/src/target/llvm/codegen_llvm.h +++ b/src/target/llvm/codegen_llvm.h @@ -563,7 +563,7 @@ class CodeGenLLVM : public ExprFunctor, // binding of let variables. Enables duplicate var defs that map to same value std::unordered_map let_binding_; // debug info for function being compiled - llvm::DISubprogram* di_subprogram_; + llvm::DISubprogram* di_subprogram_{nullptr}; // Cache potential common path ops to slightly improve lookup time. // global symbol table. OpAttrMap op_attr_global_symbol_ = Op::GetAttrMap("TGlobalSymbol"); @@ -575,9 +575,20 @@ class CodeGenLLVM : public ExprFunctor, const Op& builtin_tvm_call_cpacked_lowered_ = builtin::tvm_call_cpacked_lowered(); void EmitDebugLocation(); - void EmitDebugLocation(const Span& span); + void EmitDebugLocation(const Optional& span); void EmitDebugLocation(const StmtNode* op); + // Get the DWARF type corresponding to the LLVM type |ty|. The current API in practice only + // generates |int32|, and |int8*|. + llvm::DIType* GetDebugType(const Type& ty_tir); + llvm::DIType* GetDebugType(const Type& ty_tir, llvm::Type* ty_llvm); + + // Adds the DWARF debug information for |function| to |dbg_info_|. + void AddDebugInformation(llvm::Function* f_llvm, const Array& tvm_param_types); + // Adds the DWARF debug information for |tir_var| to |dbg_info_|. + void AddDebugInformation(llvm::Value* llvm_value, const Var& tir_var, + llvm::Instruction* insert_before = nullptr); + /*! \brief Helper struct for debug infos. */ struct DebugInfo { ~DebugInfo(); // Because of the std::unique_ptr. @@ -585,6 +596,10 @@ class CodeGenLLVM : public ExprFunctor, llvm::DICompileUnit* compilation_unit_{nullptr}; llvm::DIFile* file_{nullptr}; }; + // Internal debug information, to be populated by EmitDebugLocation + // and AddDebugInformation + std::unique_ptr dbg_info_; + /*! * \brief Create a new DebugInfo struct from the given Module that * initializes file and compilation_unit_ to TVM defaults. diff --git a/src/target/llvm/llvm_module.cc b/src/target/llvm/llvm_module.cc index 62ea797edd2e..f946b16a4785 100644 --- a/src/target/llvm/llvm_module.cc +++ b/src/target/llvm/llvm_module.cc @@ -363,9 +363,8 @@ void LLVMModuleNode::Init(const IRModule& mod, const Target& target) { llvm::MDString::get(*(llvm_target->GetContext()), str_val)); } - if (tm->getTargetTriple().isOSDarwin()) { - module_->addModuleFlag(llvm::Module::Override, "Dwarf Version", 2); - } + module_->addModuleFlag(llvm::Module::Override, "Dwarf Version", + tm->getTargetTriple().isOSDarwin() ? 2 : llvm::dwarf::DWARF_VERSION); } void LLVMModuleNode::Init(std::unique_ptr module, @@ -640,9 +639,10 @@ runtime::Module CreateLLVMCppMetadataModule(runtime::metadata::Metadata metadata llvm_target->SetTargetMetadata(mod.get()); mod->addModuleFlag(llvm::Module::Override, "Debug Info Version", llvm::DEBUG_METADATA_VERSION); - if (llvm_target->GetOrCreateTargetMachine()->getTargetTriple().isOSDarwin()) { - mod->addModuleFlag(llvm::Module::Override, "Dwarf Version", 2); - } + mod->addModuleFlag(llvm::Module::Override, "Dwarf Version", + llvm_target->GetOrCreateTargetMachine()->getTargetTriple().isOSDarwin() + ? 2 + : llvm::dwarf::DWARF_VERSION); auto n = make_object(); n->Init(std::move(mod), std::move(llvm_instance)); @@ -686,9 +686,10 @@ runtime::Module CreateLLVMCrtMetadataModule(const Array& module llvm_target->SetTargetMetadata(mod.get()); mod->addModuleFlag(llvm::Module::Override, "Debug Info Version", llvm::DEBUG_METADATA_VERSION); - if (llvm_target->GetOrCreateTargetMachine()->getTargetTriple().isOSDarwin()) { - mod->addModuleFlag(llvm::Module::Override, "Dwarf Version", 2); - } + mod->addModuleFlag(llvm::Module::Override, "Dwarf Version", + llvm_target->GetOrCreateTargetMachine()->getTargetTriple().isOSDarwin() + ? 2 + : llvm::dwarf::DWARF_VERSION); auto n = make_object(); n->Init(std::move(mod), std::move(llvm_instance)); From 6dc971785d5665f2044771402ab84697d77c39ee Mon Sep 17 00:00:00 2001 From: Eric Lunderberg Date: Wed, 7 Feb 2024 20:12:31 -0600 Subject: [PATCH 2/6] lint fixes --- src/target/llvm/codegen_cpu.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/target/llvm/codegen_cpu.cc b/src/target/llvm/codegen_cpu.cc index cd56fa368c18..a717bb217fc8 100644 --- a/src/target/llvm/codegen_cpu.cc +++ b/src/target/llvm/codegen_cpu.cc @@ -525,12 +525,11 @@ void CodeGenCPU::CreateComputeScope(const AttrStmtNode* op) { llvm::Function* fcompute = llvm::Function::Create(ftype, llvm::Function::InternalLinkage, MakeStringRef(value->value), module_.get()); SetTargetAttributes(fcompute); - for(auto it = fcompute->arg_begin(); it!=fcompute->arg_end(); it++) { + for (auto it = fcompute->arg_begin(); it != fcompute->arg_end(); it++) { const Var& var = vargs[std::distance(fcompute->arg_begin(), it)]; it->setName(std::string(var->name_hint)); } - llvm::BasicBlock* compute_call_end = CheckCallSuccess(builder_->CreateCall(fcompute, arg_values)); llvm::LLVMContext* ctx = llvm_target_->GetContext(); // enter compute scope and setup compute function. @@ -564,7 +563,8 @@ void CodeGenCPU::CreateComputeScope(const AttrStmtNode* op) { } function_ = fcompute; - di_subprogram_ = CreateDebugFunction(MakeStringRef(value->value), vargs.Map(GetType), PrimType(DataType::Int(32))); + di_subprogram_ = CreateDebugFunction(MakeStringRef(value->value), vargs.Map(GetType), + PrimType(DataType::Int(32))); auto* compute_entry = llvm::BasicBlock::Create(*ctx, "entry", function_); builder_->SetInsertPoint(compute_entry); this->VisitStmt(op->body); From 305cc992b2aae06b1a657977cff733033108ffd5 Mon Sep 17 00:00:00 2001 From: Eric Lunderberg Date: Wed, 7 Feb 2024 21:33:15 -0600 Subject: [PATCH 3/6] lint fixes --- src/target/llvm/codegen_cpu.cc | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/target/llvm/codegen_cpu.cc b/src/target/llvm/codegen_cpu.cc index a717bb217fc8..481ba39cc7b1 100644 --- a/src/target/llvm/codegen_cpu.cc +++ b/src/target/llvm/codegen_cpu.cc @@ -185,9 +185,9 @@ void CodeGenCPU::Init(const std::string& module_name, LLVMTarget* llvm_target, InitGlobalContext(dynamic_lookup); } -llvm::DISubprogram* CodeGenCPU::CreateDebugFunction( - llvm::StringRef name, const Array& param_types, const Type& return_type -) { +llvm::DISubprogram* CodeGenCPU::CreateDebugFunction(llvm::StringRef name, + const Array& param_types, + const Type& return_type) { #if TVM_LLVM_VERSION < 50 return nullptr; #else @@ -239,8 +239,6 @@ void CodeGenCPU::AddFunction(const GlobalVar& gvar, const PrimFunc& func) { AddDebugInformation(function_, func->params.Map(GetType)); } - - void CodeGenCPU::AddMainFunction(const std::string& entry_func_name) { llvm::Function* f = module_->getFunction(entry_func_name); ICHECK(f) << "Function " << entry_func_name << "does not in module"; From 32cc53c988f641fddbf7671ebe5540f470d6a671 Mon Sep 17 00:00:00 2001 From: Eric Lunderberg Date: Thu, 8 Feb 2024 06:50:42 -0600 Subject: [PATCH 4/6] Remove reference to llvm::dwarf::DWARF_VERSION Not available on CI version of llvm --- src/target/llvm/llvm_module.cc | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/target/llvm/llvm_module.cc b/src/target/llvm/llvm_module.cc index f946b16a4785..59cd6a76b0b9 100644 --- a/src/target/llvm/llvm_module.cc +++ b/src/target/llvm/llvm_module.cc @@ -364,7 +364,7 @@ void LLVMModuleNode::Init(const IRModule& mod, const Target& target) { } module_->addModuleFlag(llvm::Module::Override, "Dwarf Version", - tm->getTargetTriple().isOSDarwin() ? 2 : llvm::dwarf::DWARF_VERSION); + tm->getTargetTriple().isOSDarwin() ? 2 : 4); } void LLVMModuleNode::Init(std::unique_ptr module, @@ -639,10 +639,9 @@ runtime::Module CreateLLVMCppMetadataModule(runtime::metadata::Metadata metadata llvm_target->SetTargetMetadata(mod.get()); mod->addModuleFlag(llvm::Module::Override, "Debug Info Version", llvm::DEBUG_METADATA_VERSION); - mod->addModuleFlag(llvm::Module::Override, "Dwarf Version", - llvm_target->GetOrCreateTargetMachine()->getTargetTriple().isOSDarwin() - ? 2 - : llvm::dwarf::DWARF_VERSION); + mod->addModuleFlag( + llvm::Module::Override, "Dwarf Version", + llvm_target->GetOrCreateTargetMachine()->getTargetTriple().isOSDarwin() ? 2 : 4); auto n = make_object(); n->Init(std::move(mod), std::move(llvm_instance)); @@ -686,10 +685,9 @@ runtime::Module CreateLLVMCrtMetadataModule(const Array& module llvm_target->SetTargetMetadata(mod.get()); mod->addModuleFlag(llvm::Module::Override, "Debug Info Version", llvm::DEBUG_METADATA_VERSION); - mod->addModuleFlag(llvm::Module::Override, "Dwarf Version", - llvm_target->GetOrCreateTargetMachine()->getTargetTriple().isOSDarwin() - ? 2 - : llvm::dwarf::DWARF_VERSION); + mod->addModuleFlag( + llvm::Module::Override, "Dwarf Version", + llvm_target->GetOrCreateTargetMachine()->getTargetTriple().isOSDarwin() ? 2 : 4); auto n = make_object(); n->Init(std::move(mod), std::move(llvm_instance)); From a7dba765652cd6d41a621bbbace89ffd833726ed Mon Sep 17 00:00:00 2001 From: Eric Lunderberg Date: Sun, 11 Feb 2024 08:01:46 -0600 Subject: [PATCH 5/6] Update number of debug locations --- tests/python/tir-base/test_debug_info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/python/tir-base/test_debug_info.py b/tests/python/tir-base/test_debug_info.py index 8bd22f1bb6bd..a94d4d74f2c8 100644 --- a/tests/python/tir-base/test_debug_info.py +++ b/tests/python/tir-base/test_debug_info.py @@ -141,7 +141,7 @@ def test_llvm_ir_debug_info(): source = runtime_module.get_source() locations = find_di_locations(source) - assert len(locations) == 34 + assert len(locations) == 35 def test_llvm_ir_debug_accuracy(): From 89e66a6a3cbb3d86d2f4fd3d81681e96e92a309f Mon Sep 17 00:00:00 2001 From: Eric Lunderberg Date: Sun, 11 Feb 2024 08:12:43 -0600 Subject: [PATCH 6/6] Fix segfault for pointers to custom data types --- src/target/llvm/codegen_llvm.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target/llvm/codegen_llvm.cc b/src/target/llvm/codegen_llvm.cc index e8202f4c3bd7..448bf5a2531a 100644 --- a/src/target/llvm/codegen_llvm.cc +++ b/src/target/llvm/codegen_llvm.cc @@ -2200,7 +2200,7 @@ llvm::DIType* CodeGenLLVM::GetDebugType(const Type& ty_tir) { return GetDebugType(ty_tir, GetLLVMType(ty_tir)); } llvm::DIType* CodeGenLLVM::GetDebugType(const Type& ty_tir, llvm::Type* ty_llvm) { - if (ty_llvm == t_void_) { + if (ty_llvm == nullptr || ty_llvm == t_void_) { return nullptr; } else if (ty_llvm->isPointerTy()) {