109c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo/*
209c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo * Copyright 2015, The Android Open Source Project
309c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo *
409c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo * Licensed under the Apache License, Version 2.0 (the "License");
509c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo * you may not use this file except in compliance with the License.
609c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo * You may obtain a copy of the License at
709c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo *
809c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo *     http://www.apache.org/licenses/LICENSE-2.0
909c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo *
1009c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo * Unless required by applicable law or agreed to in writing, software
1109c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo * distributed under the License is distributed on an "AS IS" BASIS,
1209c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1309c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo * See the License for the specific language governing permissions and
1409c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo * limitations under the License.
1509c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo */
1609c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo
17a2dd52f0710c214e00c1a13e25116e1af5eec77aJean-Luc Brouillet#include "Assert.h"
18a2dd52f0710c214e00c1a13e25116e1af5eec77aJean-Luc Brouillet#include "Log.h"
19a2dd52f0710c214e00c1a13e25116e1af5eec77aJean-Luc Brouillet#include "RSTransforms.h"
20a2dd52f0710c214e00c1a13e25116e1af5eec77aJean-Luc Brouillet
219d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo#include "bcinfo/MetadataExtractor.h"
2209c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo
23a2dd52f0710c214e00c1a13e25116e1af5eec77aJean-Luc Brouillet#include <string>
24a2dd52f0710c214e00c1a13e25116e1af5eec77aJean-Luc Brouillet
2509c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo#include <llvm/Pass.h>
2609c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo#include <llvm/IR/DIBuilder.h>
2709c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo#include <llvm/IR/Function.h>
2809c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo#include <llvm/IR/InstIterator.h>
2909c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo#include <llvm/IR/Instructions.h>
309d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo#include <llvm/IR/IRBuilder.h>
3109c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo#include <llvm/IR/Module.h>
320464789e86c9aa9a7f99762bd724444430bd86a7Luke Drummond#include <llvm/ADT/SetVector.h>
3309c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo
3409c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leonamespace {
3509c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo
3609c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leoconst char DEBUG_SOURCE_PATH[] = "/opt/renderscriptdebugger/1";
3709c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leoconst char DEBUG_GENERATED_FILE[] = "generated.rs";
389d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leoconst char DEBUG_PROTOTYPE_VAR_NAME[] = "rsDebugOuterForeachT";
399d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leoconst char DEBUG_COMPILE_UNIT_MDNAME[] = "llvm.dbg.cu";
4009c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo
4109c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo/*
4209c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo * LLVM pass to attach debug information to the bits of code
4309c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo * generated by the compiler.
4409c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo */
4509c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leoclass RSAddDebugInfoPass : public llvm::ModulePass {
4609c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo
4709c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leopublic:
4809c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo  // Pass ID
4909c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo  static char ID;
5009c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo
519d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo  RSAddDebugInfoPass() : ModulePass(ID), kernelTypeMD(nullptr),
529d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      sourceFileName(nullptr), emptyExpr(nullptr), abiMetaCU(nullptr),
539d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      indexVarType(nullptr) {
5409c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo  }
5509c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo
5609c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo  virtual bool runOnModule(llvm::Module &Module) {
579d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    // Gather information about this bcc module.
589d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    bcinfo::MetadataExtractor me(&Module);
599d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    if (!me.extract()) {
609d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      ALOGE("Could not extract metadata from module!");
619d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      return false;
629d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    }
639d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo
640464789e86c9aa9a7f99762bd724444430bd86a7Luke Drummond    const size_t nForEachKernels = me.getExportForEachSignatureCount();
659d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    const char **forEachKernels = me.getExportForEachNameList();
660464789e86c9aa9a7f99762bd724444430bd86a7Luke Drummond    const bcinfo::MetadataExtractor::Reduce *reductions =
670464789e86c9aa9a7f99762bd724444430bd86a7Luke Drummond        me.getExportReduceList();
680464789e86c9aa9a7f99762bd724444430bd86a7Luke Drummond    const size_t nReductions = me.getExportReduceCount();
690464789e86c9aa9a7f99762bd724444430bd86a7Luke Drummond
700464789e86c9aa9a7f99762bd724444430bd86a7Luke Drummond    llvm::SmallSetVector<llvm::Function *, 16> expandFuncs{};
710464789e86c9aa9a7f99762bd724444430bd86a7Luke Drummond    auto pushExpanded = [&](const char *const name) -> void {
720464789e86c9aa9a7f99762bd724444430bd86a7Luke Drummond      bccAssert(name && *name && (::strcmp(name, ".") != 0));
730464789e86c9aa9a7f99762bd724444430bd86a7Luke Drummond
740464789e86c9aa9a7f99762bd724444430bd86a7Luke Drummond      const std::string expandName = std::string(name) + ".expand";
750464789e86c9aa9a7f99762bd724444430bd86a7Luke Drummond      if (llvm::Function *const func = Module.getFunction(expandName))
760464789e86c9aa9a7f99762bd724444430bd86a7Luke Drummond        expandFuncs.insert(func);
770464789e86c9aa9a7f99762bd724444430bd86a7Luke Drummond    };
780464789e86c9aa9a7f99762bd724444430bd86a7Luke Drummond
790464789e86c9aa9a7f99762bd724444430bd86a7Luke Drummond    for (size_t i = 0; i < nForEachKernels; ++i)
800464789e86c9aa9a7f99762bd724444430bd86a7Luke Drummond      pushExpanded(forEachKernels[i]);
810464789e86c9aa9a7f99762bd724444430bd86a7Luke Drummond
820464789e86c9aa9a7f99762bd724444430bd86a7Luke Drummond    for (size_t i = 0; i < nReductions; ++i) {
830464789e86c9aa9a7f99762bd724444430bd86a7Luke Drummond      const bcinfo::MetadataExtractor::Reduce &reduction = reductions[i];
840464789e86c9aa9a7f99762bd724444430bd86a7Luke Drummond      pushExpanded(reduction.mAccumulatorName);
850464789e86c9aa9a7f99762bd724444430bd86a7Luke Drummond    }
869d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo
8709c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo    // Set up the debug info builder.
8809c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo    llvm::DIBuilder DebugInfo(Module);
899d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    initializeDebugInfo(DebugInfo, Module);
9009c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo
910464789e86c9aa9a7f99762bd724444430bd86a7Luke Drummond    for (const auto &expandFunc : expandFuncs) {
920464789e86c9aa9a7f99762bd724444430bd86a7Luke Drummond      // Attach DI metadata to each generated function.
930464789e86c9aa9a7f99762bd724444430bd86a7Luke Drummond      // No inlining has occurred at this point so it's safe to name match
940464789e86c9aa9a7f99762bd724444430bd86a7Luke Drummond      // without worrying about inlined function bodies.
950464789e86c9aa9a7f99762bd724444430bd86a7Luke Drummond      attachDebugInfo(DebugInfo, *expandFunc);
969d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    }
9709c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo
9809c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo    DebugInfo.finalize();
9909c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo
1009d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    cleanupDebugInfo(Module);
1019d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo
10209c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo    return true;
10309c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo  }
10409c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo
10509c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leoprivate:
10609c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo
1079d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo  // @brief Initialize the debug info generation.
1089d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo  //
1099d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo  // This method does a couple of things:
1109d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo  // * Look up debug metadata for kernel ABI and store it if present.
1119d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo  // * Store a couple of useful pieces of debug metadata in member
1129d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo  //   variables so they do not have to be created multiple times.
1139d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo  void initializeDebugInfo(llvm::DIBuilder &DebugInfo,
1149d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo                           const llvm::Module &Module) {
1159d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    llvm::LLVMContext &ctx = Module.getContext();
1169d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo
1179d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    // Start generating debug information for bcc-generated code.
1180c5cfaeeb30135efe5e21d1aa9c858965c3019a6Ewan Crawford    DebugInfo.createCompileUnit(llvm::dwarf::DW_LANG_GOOGLE_RenderScript,
1199d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo                                DEBUG_GENERATED_FILE, DEBUG_SOURCE_PATH,
1209d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo                                "RS", false, "", 0);
1219d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo
1229d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    // Pre-generate and save useful pieces of debug metadata.
1239d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    sourceFileName = DebugInfo.createFile(DEBUG_GENERATED_FILE, DEBUG_SOURCE_PATH);
1249d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    emptyExpr = DebugInfo.createExpression();
1259d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo
1269d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    // Lookup compile unit with kernel ABI debug metadata.
1279d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    llvm::NamedMDNode *mdCompileUnitList =
1289d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo        Module.getNamedMetadata(DEBUG_COMPILE_UNIT_MDNAME);
1299d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    bccAssert(mdCompileUnitList != nullptr &&
1309d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo        "DebugInfo pass could not find any existing compile units.");
1319d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo
1329d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    llvm::DIGlobalVariable *kernelPrototypeVarMD = nullptr;
1339d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    for (llvm::MDNode* CUNode : mdCompileUnitList->operands()) {
1349d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      if (auto *CU = llvm::dyn_cast<llvm::DICompileUnit>(CUNode)) {
1359d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo        for (llvm::DIGlobalVariable* GV : CU->getGlobalVariables()) {
1369d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo          if (GV->getDisplayName() == DEBUG_PROTOTYPE_VAR_NAME) {
1379d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo            kernelPrototypeVarMD = GV;
1389d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo            abiMetaCU = CU;
1399d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo            break;
1409d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo          }
1419d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo        }
1429d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo        if (kernelPrototypeVarMD != nullptr)
1439d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo          break;
1449d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      }
1459d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    }
1469d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo
1479d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    // Lookup the expanded function interface type metadata.
1489d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    llvm::MDTuple *kernelPrototypeMD = nullptr;
1499d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    if (kernelPrototypeVarMD != nullptr) {
1509d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      // Dig into the metadata to look for function prototype.
1519d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      llvm::DIDerivedType *DT = nullptr;
1529d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      DT = llvm::cast<llvm::DIDerivedType>(kernelPrototypeVarMD->getType());
1539d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      DT = llvm::cast<llvm::DIDerivedType>(DT->getBaseType());
1549d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      llvm::DISubroutineType *ST = llvm::cast<llvm::DISubroutineType>(DT->getBaseType());
1559d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      kernelPrototypeMD = llvm::cast<llvm::MDTuple>(ST->getRawTypeArray());
1569d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo
1579d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      indexVarType = llvm::dyn_cast_or_null<llvm::DIType>(
1589d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo          kernelPrototypeMD->getOperand(2));
1599d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    }
1609d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    // Fall back to the function type of void() if there is no proper debug info.
1619d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    if (kernelPrototypeMD == nullptr)
1629d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      kernelPrototypeMD = llvm::MDTuple::get(ctx, {nullptr});
1639d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    // Fall back to unspecified type if we don't have a proper index type.
1649d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    if (indexVarType == nullptr)
1659d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      indexVarType = DebugInfo.createBasicType("uint32_t", 32, 32,
1669d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo          llvm::dwarf::DW_ATE_unsigned);
1679d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo
1689d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    // Capture the expanded kernel type debug info.
169f229c40f0d2da19985e68955aef1a06ce4121e63Pirama Arumuga Nainar    kernelTypeMD = DebugInfo.createSubroutineType(kernelPrototypeMD);
1709d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo  }
1719d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo
17209c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo  /// @brief Add debug information to a generated function.
17309c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo  ///
1749d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo  /// This procedure adds the following pieces of debug information
1759d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo  /// to the function specified by Func:
1769d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo  /// * Entry for the function to the current compile unit.
1779d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo  /// * Adds debug info entries for each function argument.
1789d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo  /// * Adds debug info entry for the rsIndex local variable.
1799d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo  /// * File/line information to each instruction set to generates.rs:1.
18009c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo  void attachDebugInfo(llvm::DIBuilder &DebugInfo, llvm::Function &Func) {
1819d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    // Lookup the current thread coordinate variable.
1829d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    llvm::AllocaInst* indexVar = nullptr;
183f229c40f0d2da19985e68955aef1a06ce4121e63Pirama Arumuga Nainar    for (llvm::Instruction &inst : llvm::instructions(Func)) {
1849d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      if (auto *allocaInst = llvm::dyn_cast<llvm::AllocaInst>(&inst)) {
1859d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo        if (allocaInst->getName() == bcc::BCC_INDEX_VAR_NAME) {
1869d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo          indexVar = allocaInst;
1879d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo          break;
1889d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo        }
1899d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      }
1909d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    }
19109c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo
19209c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo    // Create function-level debug metadata.
1939d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    llvm::DISubprogram *ExpandedFunc = DebugInfo.createFunction(
19409c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo        sourceFileName, // scope
19509c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo        Func.getName(), Func.getName(),
1969d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo        sourceFileName, 1, kernelTypeMD,
197f229c40f0d2da19985e68955aef1a06ce4121e63Pirama Arumuga Nainar        false, true, 1, 0, false
19809c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo    );
1993ca8fe934c6147f486dbb346fea9ec14ada97daeDean De Leo    Func.setSubprogram(ExpandedFunc);
20009c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo
2019d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    // IRBuilder for allocating variables for arguments.
202f229c40f0d2da19985e68955aef1a06ce4121e63Pirama Arumuga Nainar    llvm::IRBuilder<> ir(&*Func.getEntryBlock().begin());
2039d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo
2049d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    // Walk through the argument list and expanded function prototype
2059d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    // debuginfo in lockstep to create debug entries for
2069d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    // the expanded function arguments.
2079d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    unsigned argIdx = 1;
2089d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    llvm::MDTuple *argTypes = kernelTypeMD->getTypeArray().get();
2099d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    for (llvm::Argument &arg : Func.getArgumentList()) {
2109d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      // Stop processing arguments if we run out of debug info.
2119d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      if (argIdx >= argTypes->getNumOperands())
2129d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo        break;
2139d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo
2149d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      // Create debuginfo entry for the argument and advance.
215f229c40f0d2da19985e68955aef1a06ce4121e63Pirama Arumuga Nainar      llvm::DILocalVariable *argVarDI = DebugInfo.createParameterVariable(
216f229c40f0d2da19985e68955aef1a06ce4121e63Pirama Arumuga Nainar          ExpandedFunc, arg.getName(), argIdx, sourceFileName, 1,
2179d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo          llvm::cast<llvm::DIType>(argTypes->getOperand(argIdx).get()),
218f229c40f0d2da19985e68955aef1a06ce4121e63Pirama Arumuga Nainar          true, 0
219f229c40f0d2da19985e68955aef1a06ce4121e63Pirama Arumuga Nainar      );
2209d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo
2219d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      // Annotate the argument variable in the IR.
2229d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      llvm::AllocaInst *argVar =
2239d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo          ir.CreateAlloca(arg.getType(), nullptr, arg.getName() + ".var");
2249d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      llvm::StoreInst *argStore = ir.CreateStore(&arg, argVar);
2259d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      llvm::LoadInst *loadedVar = ir.CreateLoad(argVar, arg.getName() + ".l");
2269d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      DebugInfo.insertDeclare(argVar, argVarDI, emptyExpr,
2279d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo          llvm::DebugLoc::get(1, 1, ExpandedFunc), loadedVar);
2289d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      for (llvm::Use &u : arg.uses())
2299d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo        if (u.getUser() != argStore)
2309d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo          u.set(loadedVar);
2319d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      argIdx++;
2329d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    }
2339d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo
2349d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    // Annotate the index variable with metadata.
2359d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    if (indexVar) {
2369d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      // Debug information for loop index variable.
237f229c40f0d2da19985e68955aef1a06ce4121e63Pirama Arumuga Nainar      llvm::DILocalVariable *indexVarDI = DebugInfo.createAutoVariable(
238f229c40f0d2da19985e68955aef1a06ce4121e63Pirama Arumuga Nainar          ExpandedFunc, bcc::BCC_INDEX_VAR_NAME, sourceFileName, 1,
239f229c40f0d2da19985e68955aef1a06ce4121e63Pirama Arumuga Nainar          indexVarType, true
240f229c40f0d2da19985e68955aef1a06ce4121e63Pirama Arumuga Nainar      );
2419d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo
2429d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      // Insert declaration annotation in the instruction stream.
2439d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      llvm::Instruction *decl = DebugInfo.insertDeclare(
2449d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo          indexVar, indexVarDI, emptyExpr,
2459d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo          llvm::DebugLoc::get(1, 1, ExpandedFunc), indexVar);
2469d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      indexVar->moveBefore(decl);
2479d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    }
2489d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo
2499d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    // Attach location information to each instruction in the function.
250f229c40f0d2da19985e68955aef1a06ce4121e63Pirama Arumuga Nainar    for (llvm::Instruction &inst : llvm::instructions(Func)) {
2519d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      inst.setDebugLoc(llvm::DebugLoc::get(1, 1, ExpandedFunc));
25209c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo    }
25309c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo  }
25409c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo
2559d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo  // @brief Clean up the debug info.
2569d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo  //
2579d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo  // At the moment, it only finds the compile unit for the expanded function
2589d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo  // metadata generated by clang and removes it.
2599d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo  void cleanupDebugInfo(llvm::Module& Module) {
2609d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    if (abiMetaCU == nullptr)
2619d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      return;
2629d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo
2639d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    // Remove the compile unit with the runtime interface DI.
2649d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    llvm::SmallVector<llvm::MDNode*, 4> unitsTmp;
2659d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    llvm::NamedMDNode *debugMD =
2669d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo        Module.getNamedMetadata(DEBUG_COMPILE_UNIT_MDNAME);
2679d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    for (llvm::MDNode *cu : debugMD->operands())
2689d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      if (cu != abiMetaCU)
2699d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo        unitsTmp.push_back(cu);
2709d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    debugMD->eraseFromParent();
2719d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    debugMD = Module.getOrInsertNamedMetadata(DEBUG_COMPILE_UNIT_MDNAME);
2729d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo    for (llvm::MDNode *cu : unitsTmp)
2739d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo      debugMD->addOperand(cu);
2749d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo  }
2759d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo
2769d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leoprivate:
2779d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo  // private attributes
2789d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo  llvm::DISubroutineType* kernelTypeMD;
2799d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo  llvm::DIFile *sourceFileName;
2809d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo  llvm::DIExpression *emptyExpr;
2819d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo  llvm::DICompileUnit *abiMetaCU;
2829d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo  llvm::DIType *indexVarType;
2839d009b0a25bf7eea6f2da2521107dc37acea9accDean De Leo
28409c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo}; // end class RSAddDebugInfoPass
28509c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo
28609c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leochar RSAddDebugInfoPass::ID = 0;
28709c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leostatic llvm::RegisterPass<RSAddDebugInfoPass> X("addrsdi", "Add RS DebugInfo Pass");
28809c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo
28909c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo} // end anonymous namespace
29009c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo
29109c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leonamespace bcc {
29209c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo
29309c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leollvm::ModulePass * createRSAddDebugInfoPass() {
29409c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo  return new RSAddDebugInfoPass();
29509c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo}
29609c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo
29709c7a41f73602bec33e9d392cc959d78931f73c4Dean De Leo} // end namespace bcc
298