blob: 9651ca4d31cc363a277eaacbce4009b67308214a [file] [log] [blame]
Dean De Leo09c7a412015-11-25 12:45:45 +00001/*
2 * Copyright 2015, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Jean-Luc Brouilleta2dd52f2017-02-16 20:57:26 -080017#include "Assert.h"
18#include "Log.h"
19#include "RSTransforms.h"
20
Dean De Leo9d009b02015-11-25 12:57:05 +000021#include "bcinfo/MetadataExtractor.h"
Dean De Leo09c7a412015-11-25 12:45:45 +000022
Jean-Luc Brouilleta2dd52f2017-02-16 20:57:26 -080023#include <string>
24
Dean De Leo09c7a412015-11-25 12:45:45 +000025#include <llvm/Pass.h>
Dean De Leo09c7a412015-11-25 12:45:45 +000026#include <llvm/IR/DIBuilder.h>
27#include <llvm/IR/Function.h>
Dean De Leo09c7a412015-11-25 12:45:45 +000028#include <llvm/IR/InstIterator.h>
29#include <llvm/IR/Instructions.h>
Dean De Leo9d009b02015-11-25 12:57:05 +000030#include <llvm/IR/IRBuilder.h>
Dean De Leo09c7a412015-11-25 12:45:45 +000031#include <llvm/IR/Module.h>
Luke Drummond04647892016-09-02 14:15:24 +010032#include <llvm/ADT/SetVector.h>
Dean De Leo09c7a412015-11-25 12:45:45 +000033
34namespace {
35
36const char DEBUG_SOURCE_PATH[] = "/opt/renderscriptdebugger/1";
37const char DEBUG_GENERATED_FILE[] = "generated.rs";
Dean De Leo9d009b02015-11-25 12:57:05 +000038const char DEBUG_PROTOTYPE_VAR_NAME[] = "rsDebugOuterForeachT";
39const char DEBUG_COMPILE_UNIT_MDNAME[] = "llvm.dbg.cu";
Dean De Leo09c7a412015-11-25 12:45:45 +000040
41/*
42 * LLVM pass to attach debug information to the bits of code
43 * generated by the compiler.
44 */
45class RSAddDebugInfoPass : public llvm::ModulePass {
46
47public:
48 // Pass ID
49 static char ID;
50
Dean De Leo9d009b02015-11-25 12:57:05 +000051 RSAddDebugInfoPass() : ModulePass(ID), kernelTypeMD(nullptr),
52 sourceFileName(nullptr), emptyExpr(nullptr), abiMetaCU(nullptr),
53 indexVarType(nullptr) {
Dean De Leo09c7a412015-11-25 12:45:45 +000054 }
55
56 virtual bool runOnModule(llvm::Module &Module) {
Dean De Leo9d009b02015-11-25 12:57:05 +000057 // Gather information about this bcc module.
58 bcinfo::MetadataExtractor me(&Module);
59 if (!me.extract()) {
60 ALOGE("Could not extract metadata from module!");
61 return false;
62 }
63
Luke Drummond04647892016-09-02 14:15:24 +010064 const size_t nForEachKernels = me.getExportForEachSignatureCount();
Dean De Leo9d009b02015-11-25 12:57:05 +000065 const char **forEachKernels = me.getExportForEachNameList();
Luke Drummond04647892016-09-02 14:15:24 +010066 const bcinfo::MetadataExtractor::Reduce *reductions =
67 me.getExportReduceList();
68 const size_t nReductions = me.getExportReduceCount();
69
70 llvm::SmallSetVector<llvm::Function *, 16> expandFuncs{};
71 auto pushExpanded = [&](const char *const name) -> void {
72 bccAssert(name && *name && (::strcmp(name, ".") != 0));
73
74 const std::string expandName = std::string(name) + ".expand";
75 if (llvm::Function *const func = Module.getFunction(expandName))
76 expandFuncs.insert(func);
77 };
78
79 for (size_t i = 0; i < nForEachKernels; ++i)
80 pushExpanded(forEachKernels[i]);
81
82 for (size_t i = 0; i < nReductions; ++i) {
83 const bcinfo::MetadataExtractor::Reduce &reduction = reductions[i];
84 pushExpanded(reduction.mAccumulatorName);
85 }
Dean De Leo9d009b02015-11-25 12:57:05 +000086
Dean De Leo09c7a412015-11-25 12:45:45 +000087 // Set up the debug info builder.
88 llvm::DIBuilder DebugInfo(Module);
Dean De Leo9d009b02015-11-25 12:57:05 +000089 initializeDebugInfo(DebugInfo, Module);
Dean De Leo09c7a412015-11-25 12:45:45 +000090
Luke Drummond04647892016-09-02 14:15:24 +010091 for (const auto &expandFunc : expandFuncs) {
92 // Attach DI metadata to each generated function.
93 // No inlining has occurred at this point so it's safe to name match
94 // without worrying about inlined function bodies.
95 attachDebugInfo(DebugInfo, *expandFunc);
Dean De Leo9d009b02015-11-25 12:57:05 +000096 }
Dean De Leo09c7a412015-11-25 12:45:45 +000097
98 DebugInfo.finalize();
99
Dean De Leo9d009b02015-11-25 12:57:05 +0000100 cleanupDebugInfo(Module);
101
Dean De Leo09c7a412015-11-25 12:45:45 +0000102 return true;
103 }
104
105private:
106
Dean De Leo9d009b02015-11-25 12:57:05 +0000107 // @brief Initialize the debug info generation.
108 //
109 // This method does a couple of things:
110 // * Look up debug metadata for kernel ABI and store it if present.
111 // * Store a couple of useful pieces of debug metadata in member
112 // variables so they do not have to be created multiple times.
113 void initializeDebugInfo(llvm::DIBuilder &DebugInfo,
114 const llvm::Module &Module) {
115 llvm::LLVMContext &ctx = Module.getContext();
116
117 // Start generating debug information for bcc-generated code.
Ewan Crawford0c5cfae2016-02-10 08:56:03 +0000118 DebugInfo.createCompileUnit(llvm::dwarf::DW_LANG_GOOGLE_RenderScript,
Dean De Leo9d009b02015-11-25 12:57:05 +0000119 DEBUG_GENERATED_FILE, DEBUG_SOURCE_PATH,
120 "RS", false, "", 0);
121
122 // Pre-generate and save useful pieces of debug metadata.
123 sourceFileName = DebugInfo.createFile(DEBUG_GENERATED_FILE, DEBUG_SOURCE_PATH);
124 emptyExpr = DebugInfo.createExpression();
125
126 // Lookup compile unit with kernel ABI debug metadata.
127 llvm::NamedMDNode *mdCompileUnitList =
128 Module.getNamedMetadata(DEBUG_COMPILE_UNIT_MDNAME);
129 bccAssert(mdCompileUnitList != nullptr &&
130 "DebugInfo pass could not find any existing compile units.");
131
132 llvm::DIGlobalVariable *kernelPrototypeVarMD = nullptr;
133 for (llvm::MDNode* CUNode : mdCompileUnitList->operands()) {
134 if (auto *CU = llvm::dyn_cast<llvm::DICompileUnit>(CUNode)) {
135 for (llvm::DIGlobalVariable* GV : CU->getGlobalVariables()) {
136 if (GV->getDisplayName() == DEBUG_PROTOTYPE_VAR_NAME) {
137 kernelPrototypeVarMD = GV;
138 abiMetaCU = CU;
139 break;
140 }
141 }
142 if (kernelPrototypeVarMD != nullptr)
143 break;
144 }
145 }
146
147 // Lookup the expanded function interface type metadata.
148 llvm::MDTuple *kernelPrototypeMD = nullptr;
149 if (kernelPrototypeVarMD != nullptr) {
150 // Dig into the metadata to look for function prototype.
151 llvm::DIDerivedType *DT = nullptr;
152 DT = llvm::cast<llvm::DIDerivedType>(kernelPrototypeVarMD->getType());
153 DT = llvm::cast<llvm::DIDerivedType>(DT->getBaseType());
154 llvm::DISubroutineType *ST = llvm::cast<llvm::DISubroutineType>(DT->getBaseType());
155 kernelPrototypeMD = llvm::cast<llvm::MDTuple>(ST->getRawTypeArray());
156
157 indexVarType = llvm::dyn_cast_or_null<llvm::DIType>(
158 kernelPrototypeMD->getOperand(2));
159 }
160 // Fall back to the function type of void() if there is no proper debug info.
161 if (kernelPrototypeMD == nullptr)
162 kernelPrototypeMD = llvm::MDTuple::get(ctx, {nullptr});
163 // Fall back to unspecified type if we don't have a proper index type.
164 if (indexVarType == nullptr)
165 indexVarType = DebugInfo.createBasicType("uint32_t", 32, 32,
166 llvm::dwarf::DW_ATE_unsigned);
167
168 // Capture the expanded kernel type debug info.
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -0800169 kernelTypeMD = DebugInfo.createSubroutineType(kernelPrototypeMD);
Dean De Leo9d009b02015-11-25 12:57:05 +0000170 }
171
Dean De Leo09c7a412015-11-25 12:45:45 +0000172 /// @brief Add debug information to a generated function.
173 ///
Dean De Leo9d009b02015-11-25 12:57:05 +0000174 /// This procedure adds the following pieces of debug information
175 /// to the function specified by Func:
176 /// * Entry for the function to the current compile unit.
177 /// * Adds debug info entries for each function argument.
178 /// * Adds debug info entry for the rsIndex local variable.
179 /// * File/line information to each instruction set to generates.rs:1.
Dean De Leo09c7a412015-11-25 12:45:45 +0000180 void attachDebugInfo(llvm::DIBuilder &DebugInfo, llvm::Function &Func) {
Dean De Leo9d009b02015-11-25 12:57:05 +0000181 // Lookup the current thread coordinate variable.
182 llvm::AllocaInst* indexVar = nullptr;
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -0800183 for (llvm::Instruction &inst : llvm::instructions(Func)) {
Dean De Leo9d009b02015-11-25 12:57:05 +0000184 if (auto *allocaInst = llvm::dyn_cast<llvm::AllocaInst>(&inst)) {
185 if (allocaInst->getName() == bcc::BCC_INDEX_VAR_NAME) {
186 indexVar = allocaInst;
187 break;
188 }
189 }
190 }
Dean De Leo09c7a412015-11-25 12:45:45 +0000191
192 // Create function-level debug metadata.
Dean De Leo9d009b02015-11-25 12:57:05 +0000193 llvm::DISubprogram *ExpandedFunc = DebugInfo.createFunction(
Dean De Leo09c7a412015-11-25 12:45:45 +0000194 sourceFileName, // scope
195 Func.getName(), Func.getName(),
Dean De Leo9d009b02015-11-25 12:57:05 +0000196 sourceFileName, 1, kernelTypeMD,
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -0800197 false, true, 1, 0, false
Dean De Leo09c7a412015-11-25 12:45:45 +0000198 );
Dean De Leo3ca8fe92016-04-01 17:11:16 +0100199 Func.setSubprogram(ExpandedFunc);
Dean De Leo09c7a412015-11-25 12:45:45 +0000200
Dean De Leo9d009b02015-11-25 12:57:05 +0000201 // IRBuilder for allocating variables for arguments.
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -0800202 llvm::IRBuilder<> ir(&*Func.getEntryBlock().begin());
Dean De Leo9d009b02015-11-25 12:57:05 +0000203
204 // Walk through the argument list and expanded function prototype
205 // debuginfo in lockstep to create debug entries for
206 // the expanded function arguments.
207 unsigned argIdx = 1;
208 llvm::MDTuple *argTypes = kernelTypeMD->getTypeArray().get();
209 for (llvm::Argument &arg : Func.getArgumentList()) {
210 // Stop processing arguments if we run out of debug info.
211 if (argIdx >= argTypes->getNumOperands())
212 break;
213
214 // Create debuginfo entry for the argument and advance.
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -0800215 llvm::DILocalVariable *argVarDI = DebugInfo.createParameterVariable(
216 ExpandedFunc, arg.getName(), argIdx, sourceFileName, 1,
Dean De Leo9d009b02015-11-25 12:57:05 +0000217 llvm::cast<llvm::DIType>(argTypes->getOperand(argIdx).get()),
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -0800218 true, 0
219 );
Dean De Leo9d009b02015-11-25 12:57:05 +0000220
221 // Annotate the argument variable in the IR.
222 llvm::AllocaInst *argVar =
223 ir.CreateAlloca(arg.getType(), nullptr, arg.getName() + ".var");
224 llvm::StoreInst *argStore = ir.CreateStore(&arg, argVar);
225 llvm::LoadInst *loadedVar = ir.CreateLoad(argVar, arg.getName() + ".l");
226 DebugInfo.insertDeclare(argVar, argVarDI, emptyExpr,
227 llvm::DebugLoc::get(1, 1, ExpandedFunc), loadedVar);
228 for (llvm::Use &u : arg.uses())
229 if (u.getUser() != argStore)
230 u.set(loadedVar);
231 argIdx++;
232 }
233
234 // Annotate the index variable with metadata.
235 if (indexVar) {
236 // Debug information for loop index variable.
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -0800237 llvm::DILocalVariable *indexVarDI = DebugInfo.createAutoVariable(
238 ExpandedFunc, bcc::BCC_INDEX_VAR_NAME, sourceFileName, 1,
239 indexVarType, true
240 );
Dean De Leo9d009b02015-11-25 12:57:05 +0000241
242 // Insert declaration annotation in the instruction stream.
243 llvm::Instruction *decl = DebugInfo.insertDeclare(
244 indexVar, indexVarDI, emptyExpr,
245 llvm::DebugLoc::get(1, 1, ExpandedFunc), indexVar);
246 indexVar->moveBefore(decl);
247 }
248
249 // Attach location information to each instruction in the function.
Pirama Arumuga Nainarf229c402016-03-06 23:05:45 -0800250 for (llvm::Instruction &inst : llvm::instructions(Func)) {
Dean De Leo9d009b02015-11-25 12:57:05 +0000251 inst.setDebugLoc(llvm::DebugLoc::get(1, 1, ExpandedFunc));
Dean De Leo09c7a412015-11-25 12:45:45 +0000252 }
253 }
254
Dean De Leo9d009b02015-11-25 12:57:05 +0000255 // @brief Clean up the debug info.
256 //
257 // At the moment, it only finds the compile unit for the expanded function
258 // metadata generated by clang and removes it.
259 void cleanupDebugInfo(llvm::Module& Module) {
260 if (abiMetaCU == nullptr)
261 return;
262
263 // Remove the compile unit with the runtime interface DI.
264 llvm::SmallVector<llvm::MDNode*, 4> unitsTmp;
265 llvm::NamedMDNode *debugMD =
266 Module.getNamedMetadata(DEBUG_COMPILE_UNIT_MDNAME);
267 for (llvm::MDNode *cu : debugMD->operands())
268 if (cu != abiMetaCU)
269 unitsTmp.push_back(cu);
270 debugMD->eraseFromParent();
271 debugMD = Module.getOrInsertNamedMetadata(DEBUG_COMPILE_UNIT_MDNAME);
272 for (llvm::MDNode *cu : unitsTmp)
273 debugMD->addOperand(cu);
274 }
275
276private:
277 // private attributes
278 llvm::DISubroutineType* kernelTypeMD;
279 llvm::DIFile *sourceFileName;
280 llvm::DIExpression *emptyExpr;
281 llvm::DICompileUnit *abiMetaCU;
282 llvm::DIType *indexVarType;
283
Dean De Leo09c7a412015-11-25 12:45:45 +0000284}; // end class RSAddDebugInfoPass
285
286char RSAddDebugInfoPass::ID = 0;
287static llvm::RegisterPass<RSAddDebugInfoPass> X("addrsdi", "Add RS DebugInfo Pass");
288
289} // end anonymous namespace
290
291namespace bcc {
292
293llvm::ModulePass * createRSAddDebugInfoPass() {
294 return new RSAddDebugInfoPass();
295}
296
297} // end namespace bcc