1 /*========================== begin_copyright_notice ============================
2
3 Copyright (C) 2021 Intel Corporation
4
5 SPDX-License-Identifier: MIT
6
7 ============================= end_copyright_notice ===========================*/
8
9 #include "vc/Utils/General/DebugInfo.h"
10 #include "vc/Utils/GenX/TypeSize.h"
11
12 #include <llvm/IR/DebugInfoMetadata.h>
13 #include <llvm/IR/GlobalVariable.h>
14 #include <llvm/IR/IRBuilder.h>
15 #include <llvm/IR/Intrinsics.h>
16 #include <llvm/IR/Module.h>
17 #include <llvm/Support/Debug.h>
18
19 #include <llvmWrapper/IR/DerivedTypes.h>
20
21 #include "Probe/Assertion.h"
22
23 #define DEBUG_TYPE "VC_DEBUG_INFO_UTILS"
24
25 using namespace llvm;
26
checkIfModuleHasDebugInfo(const llvm::Module & M)27 bool vc::DIBuilder::checkIfModuleHasDebugInfo(const llvm::Module &M) {
28 unsigned NumDebugCUs =
29 std::distance(M.debug_compile_units_begin(), M.debug_compile_units_end());
30
31 if (NumDebugCUs == 0)
32 return false;
33
34 IGC_ASSERT_MESSAGE(NumDebugCUs == 1,
35 "only modules with one CU are supported at the moment:");
36 return NumDebugCUs == 1;
37 }
38
checkIfFunctionHasDebugInfo(const llvm::Function & F)39 bool vc::DIBuilder::checkIfFunctionHasDebugInfo(const llvm::Function &F) {
40 DISubprogram *SP = F.getSubprogram();
41 if (!SP)
42 return false;
43 IGC_ASSERT(checkIfModuleHasDebugInfo(*F.getParent()));
44 return true;
45 }
46
createDbgDeclareForLocalizedGlobal(llvm::Instruction & Address,const llvm::GlobalVariable & GV,llvm::Instruction & InsertPt)47 llvm::DbgDeclareInst *vc::DIBuilder::createDbgDeclareForLocalizedGlobal(
48 llvm::Instruction &Address, const llvm::GlobalVariable &GV,
49 llvm::Instruction &InsertPt) {
50 auto &Fn = *Address.getFunction();
51
52 if (!vc::DIBuilder::checkIfFunctionHasDebugInfo(Fn))
53 return nullptr;
54
55 SmallVector<DIGlobalVariableExpression *, 1> GVEs;
56 GV.getDebugInfo(GVEs);
57 if (GVEs.empty())
58 return nullptr;
59 IGC_ASSERT(GVEs.size() == 1);
60
61 DIGlobalVariableExpression &GVE = *GVEs.front();
62 const DIGlobalVariable &DIDebugVariable = *GVE.getVariable();
63 DIExpression &DIExpr = *GVE.getExpression();
64
65 vc::DIBuilder DBuilder(*Address.getModule());
66
67 auto *DILocalVar = DBuilder.createLocalVariable(
68 Fn.getSubprogram(), DIDebugVariable.getName(), DIDebugVariable.getFile(),
69 0 /*LineNo*/, DIDebugVariable.getType(), 0 /*ArgNo*/,
70 DINode::DIFlags::FlagArtificial, DIDebugVariable.getAlignInBits());
71 auto *DILoc = DBuilder.createLocationForFunctionScope(Fn);
72 return DBuilder.createDbgDeclare(Address, *DILocalVar, DIExpr, *DILoc,
73 InsertPt);
74 }
75
registerNewGlobalVariable(llvm::DIGlobalVariableExpression * NewGV) const76 void vc::DIBuilder::registerNewGlobalVariable(
77 llvm::DIGlobalVariableExpression *NewGV) const {
78 IGC_ASSERT(NewGV);
79 auto *CU = getDICompileUnit();
80 IGC_ASSERT(CU);
81
82 auto OldGlobals = CU->getGlobalVariables();
83 SmallVector<Metadata *, 4> NewGlobals;
84 std::copy(OldGlobals.begin(), OldGlobals.end(),
85 std::back_inserter(NewGlobals));
86 NewGlobals.push_back(NewGV);
87
88 CU->replaceGlobalVariables(MDTuple::get(M.getContext(), NewGlobals));
89 }
90
createLocationForFunctionScope(Function & Fn) const91 DILocation *vc::DIBuilder::createLocationForFunctionScope(Function &Fn) const {
92 IGC_ASSERT(checkIfFunctionHasDebugInfo(Fn));
93 auto *SP = Fn.getSubprogram();
94 auto *DILoc = DILocation::get(SP->getContext(), SP->getScopeLine(), 0, SP);
95 return DILoc;
96 }
97
getDICompileUnit() const98 llvm::DICompileUnit *vc::DIBuilder::getDICompileUnit() const {
99 IGC_ASSERT_MESSAGE(checkIfModuleHasDebugInfo(M), "debug info required!");
100 return *M.debug_compile_units_begin();
101 }
102
translateScalarTypeToDIType(Type & Ty) const103 DIType *vc::DIBuilder::translateScalarTypeToDIType(Type &Ty) const {
104 IGC_ASSERT(!Ty.isVectorTy());
105 if (!Ty.isIntegerTy()) {
106 LLVM_DEBUG(dbgs() << "ERROR: could not derive DIType for: " << Ty << "\n");
107 return nullptr;
108 }
109 auto SizeInBits = vc::getTypeSize(&Ty, &M.getDataLayout()).inBits();
110 return DIBasicType::get(
111 M.getContext(), dwarf::DW_TAG_base_type, ("ui" + Twine(SizeInBits)).str(),
112 SizeInBits, 0 /*Align*/, dwarf::DW_ATE_unsigned, DINode::FlagZero);
113 }
114
translateTypeToDIType(Type & Ty) const115 DIType *vc::DIBuilder::translateTypeToDIType(Type &Ty) const {
116 if (!Ty.isVectorTy())
117 return translateScalarTypeToDIType(Ty);
118
119 auto *VTy = dyn_cast<IGCLLVM::FixedVectorType>(&Ty);
120 if (!VTy) {
121 LLVM_DEBUG(dbgs() << "ERROR: could not derive DIType for: " << Ty << "\n");
122 return nullptr;
123 }
124 auto *ScalarTy = VTy->getScalarType();
125 auto *ScalarDI = translateScalarTypeToDIType(*ScalarTy);
126 if (!ScalarDI) {
127 LLVM_DEBUG(dbgs() << "ERROR: could not derive element DIType for: " << *VTy
128 << "\n");
129 return nullptr;
130 }
131
132 auto &Ctx = M.getContext();
133 auto NumElements = VTy->getNumElements();
134 auto *SubrangeDI = DISubrange::get(Ctx, NumElements, 0 /*Lo*/);
135 auto *Subscripts = MDTuple::get(Ctx, SubrangeDI);
136 auto SizeInBits = vc::getTypeSize(VTy, &M.getDataLayout()).inBits();
137 auto *CompositeTypeDI = DICompositeType::get(
138 Ctx, dwarf::DW_TAG_array_type, "" /*Name*/, nullptr /*File*/, 0 /*Line*/,
139 nullptr /*Scope*/, ScalarDI, SizeInBits, 0 /*AlignInBits*/,
140 0 /*OfffsetInBits*/, DINode::FlagVector, Subscripts, 0, nullptr);
141 return CompositeTypeDI;
142 }
143
createGlobalVariableExpression(StringRef Name,StringRef LinkageName,DIType * Type) const144 llvm::DIGlobalVariableExpression *vc::DIBuilder::createGlobalVariableExpression(
145 StringRef Name, StringRef LinkageName, DIType *Type) const {
146 auto *CU = getDICompileUnit();
147 IGC_ASSERT(CU);
148 auto &Ctx = M.getContext();
149
150 auto *GV = DIGlobalVariable::getDistinct(
151 Ctx, cast_or_null<DIScope>(CU), Name, LinkageName, CU->getFile(),
152 0 /*Line No*/, Type, true /*IsLocalToUnit*/, true /*isDefined*/,
153 nullptr /*Decl*/, nullptr /*TemplateParams*/, 0 /*AlignInBits*/);
154 auto *EmptyExpr = DIExpression::get(Ctx, llvm::None);
155 auto *GVE = DIGlobalVariableExpression::get(Ctx, GV, EmptyExpr);
156
157 // all globals should be registered in DICompileUnit::globals
158 registerNewGlobalVariable(GVE);
159
160 return GVE;
161 }
162
163 llvm::DbgDeclareInst *
createDbgDeclare(Value & Address,DILocalVariable & LocalVar,DIExpression & Expr,DILocation & Loc,Instruction & InsertPt) const164 vc::DIBuilder::createDbgDeclare(Value &Address, DILocalVariable &LocalVar,
165 DIExpression &Expr, DILocation &Loc,
166 Instruction &InsertPt) const {
167 auto &Ctx = M.getContext();
168
169 Value *DeclareArgs[] = {
170 MetadataAsValue::get(Ctx, ValueAsMetadata::get(&Address)),
171 MetadataAsValue::get(Ctx, &LocalVar), MetadataAsValue::get(Ctx, &Expr)};
172
173 auto *DbgDeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare);
174 IRBuilder<> Builder(&InsertPt);
175 Builder.SetCurrentDebugLocation(&Loc);
176 auto *DeclareInst = Builder.CreateCall(DbgDeclareFn, DeclareArgs);
177 return cast<DbgDeclareInst>(DeclareInst);
178 }
179
createLocalVariable(llvm::DILocalScope * Scope,llvm::StringRef Name,llvm::DIFile * File,unsigned LineNo,llvm::DIType * Type,unsigned ArgNo,llvm::DINode::DIFlags Flags,unsigned AlignInBits) const180 llvm::DILocalVariable *vc::DIBuilder::createLocalVariable(
181 llvm::DILocalScope *Scope, llvm::StringRef Name, llvm::DIFile *File,
182 unsigned LineNo, llvm::DIType *Type, unsigned ArgNo,
183 llvm::DINode::DIFlags Flags, unsigned AlignInBits) const {
184 return DILocalVariable::get(M.getContext(), Scope, Name, File, LineNo, Type,
185 ArgNo, Flags, AlignInBits);
186 }
187