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 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
|
/*========================== begin_copyright_notice ============================
Copyright (C) 2021 Intel Corporation
SPDX-License-Identifier: MIT
============================= end_copyright_notice ===========================*/
#include "llvm/Config/llvm-config.h"
#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
|