1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
|
/*========================== begin_copyright_notice ============================
Copyright (C) 2021 Intel Corporation
SPDX-License-Identifier: MIT
============================= end_copyright_notice ===========================*/
#include "common/LLVMWarningsPush.hpp"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvmWrapper/IR/DIBuilder.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "common/LLVMWarningsPop.hpp"
#include "Utils.h"
namespace IGC {
namespace Utils {
/// @brief return true if given module contain debug info
/// @param M The LLVM module.
/// @return true if given module contain debug info
bool HasDebugInfo(llvm::Module &M) {
llvm::NamedMDNode *CU_Nodes = M.getNamedMetadata("llvm.dbg.cu");
return (CU_Nodes != nullptr);
}
/// @brief creates a new call instruction to llvm.dbg.value intrinsic with
/// same information as in debug info of given global variable and
/// with value set to new given value.
/// @param pGlobalVar global variable to handle its debug info
/// @param pNewVal new value to map to the source variable (in the debug info)
/// @param pEntryPoint entry point instruction to add new instructions before.
/// @isIndirect true iff pNewValue type is a pointer to source variable type.
/// @return new call instruction to llvm.dbg.value intrinsic
llvm::Instruction *UpdateGlobalVarDebugInfo(llvm::GlobalVariable *pGlobalVar, llvm::Value *pNewVal,
llvm::Instruction *pEntryPoint, bool isIndirect) {
llvm::Function *userFunc = pEntryPoint->getParent()->getParent();
llvm::Module &M = *userFunc->getParent();
llvm::NamedMDNode *CU_Nodes = M.getNamedMetadata("llvm.dbg.cu");
if (!CU_Nodes) {
return nullptr;
}
llvm::DINode::DIFlags flags = llvm::DINode::FlagZero;
llvm::DIScope *spScope = nullptr;
llvm::DILocation *loc = nullptr;
bool done = false;
for (auto bbIt = userFunc->begin(); bbIt != userFunc->end() && !done; bbIt++) {
for (auto instIt = bbIt->begin(); instIt != bbIt->end(); instIt++) {
// Discover first valid Loc in function
// and use it in dbg.declare nodes inserted
// later. Make sure the location belongs to
// the function and not to an inlined
// callee.
if (instIt->getDebugLoc() && !instIt->getDebugLoc().getInlinedAt()) {
loc = instIt->getDebugLoc().get();
spScope = loc->getScope()->getSubprogram();
done = true;
break;
}
}
}
llvm::SmallVector<llvm::DIGlobalVariableExpression *, 1> GVs;
pGlobalVar->getDebugInfo(GVs);
for (unsigned int j = 0; j < GVs.size(); j++) {
IGCLLVM::DIBuilder Builder(M);
llvm::DIGlobalVariable *GV = GVs[j]->getVariable();
llvm::DIScope *scopeToUse = GV->getScope();
llvm::DILocation *locToUse = llvm::DILocation::get(scopeToUse->getContext(), GV->getLine(), 0, scopeToUse, nullptr);
if (llvm::isa<llvm::DICompileUnit>(scopeToUse) || llvm::isa<llvm::DINamespace>(scopeToUse)) {
// Function has no DebugLoc so it is either internal
// or optimized. So there is no point inserting
// global var metadata as "local" to function.
if (!done)
continue;
// Use scope of current sub-program
scopeToUse = spScope;
locToUse = loc;
}
llvm::DIVariable *Var = Builder.createAutoVariable(scopeToUse, GV->getDisplayName(),
Builder.createFile(GV->getFilename(), GV->getDirectory()),
GV->getLine(), GV->getType(), false, flags);
if (isIndirect)
return Builder.insertDeclare(pNewVal, llvm::cast<llvm::DILocalVariable>(Var), Builder.createExpression(),
locToUse, pEntryPoint);
return Builder.insertDbgValueIntrinsic(pNewVal, 0, llvm::cast<llvm::DILocalVariable>(Var),
Builder.createExpression(), locToUse, pEntryPoint);
}
return nullptr;
}
} // namespace Utils
} // namespace IGC
|