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 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
/*========================== begin_copyright_notice ============================
Copyright (C) 2022-2023 Intel Corporation
SPDX-License-Identifier: MIT
============================= end_copyright_notice ===========================*/
//
/// GenXDebugLegalization
/// -----------------
///
/// Modifies incoming metadata to generate valid debug info later on.
///
/// Operation of the pass
/// ^^^^^^^^^^^^^^^^^^^^^
///
/// Remove DW_OP_constu 4/DW_OP_swap/DW_OP_xderef constructs. These are
/// generated by the FE compiler to annotate address space, which is not
/// used (directly) by the debugger.
///
//===----------------------------------------------------------------------===//
#include "GenX.h"
#include "GenXUtil.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
#include "llvm/Support/Debug.h"
#define DEBUG_TYPE "GENX_DEBUGLEGALIZATION"
using namespace llvm;
using namespace genx;
namespace {
// GenXDebugLegalization : reduce integer size
class GenXDebugLegalization : public FunctionPass {
public:
static char ID;
explicit GenXDebugLegalization() : FunctionPass(ID) { }
StringRef getPassName() const override { return "GenX debug legalization"; }
void getAnalysisUsage(AnalysisUsage &AU) const override;
bool runOnFunction(Function &F) override;
private:
bool extractAddressClass(Function &F);
bool removeDIArgList(Function &F);
};
} // end anonymous namespace
char GenXDebugLegalization::ID = 0;
namespace llvm { void initializeGenXDebugLegalizationPass(PassRegistry &); }
INITIALIZE_PASS_BEGIN(GenXDebugLegalization, "GenXDebugLegalization", "GenXDebugLegalization", false, false)
INITIALIZE_PASS_END(GenXDebugLegalization, "GenXDebugLegalization", "GenXDebugLegalization", false, false)
FunctionPass *llvm::createGenXDebugLegalizationPass() {
initializeGenXDebugLegalizationPass(*PassRegistry::getPassRegistry());
return new GenXDebugLegalization;
}
void GenXDebugLegalization::getAnalysisUsage(AnalysisUsage &AU) const
{
AU.setPreservesCFG();
}
// Detect instructions with an address class pattern. Then remove all opcodes of this pattern from
// this instruction's last operand (metadata of DIExpression).
// Pattern: !DIExpression(DW_OP_constu, 4, DW_OP_swap, DW_OP_xderef)
bool GenXDebugLegalization::extractAddressClass(Function &F) {
bool Modified = false;
DIBuilder di(*F.getParent());
for (auto& bb : F) {
for (auto& pInst : bb) {
if (auto* DI = dyn_cast<DbgVariableIntrinsic>(&pInst)) {
const DIExpression* DIExpr = DI->getExpression();
llvm::SmallVector<uint64_t, 5> newElements;
for (auto I = DIExpr->expr_op_begin(), E = DIExpr->expr_op_end(); I != E; ++I) {
if (I->getOp() == dwarf::DW_OP_constu) {
auto patternI = I;
if (++patternI != E && patternI->getOp() == dwarf::DW_OP_swap &&
++patternI != E && patternI->getOp() == dwarf::DW_OP_xderef) {
I = patternI;
continue;
}
}
I->appendToVector(newElements);
}
if (newElements.size() < DIExpr->getNumElements()) {
DIExpression* newDIExpr = di.createExpression(newElements);
DI->setExpression(newDIExpr);
Modified = true;
}
}
}
}
return Modified;
}
// LLVM 12+ may generate DIArgList construct which is not (yet) supported.
// In order to prevent crashes, remove such metadata.
bool GenXDebugLegalization::removeDIArgList(Function &F) {
bool Modified = false;
for (auto &BB : F) {
for (auto &I : BB) {
if (auto *dbgInst = dyn_cast<DbgVariableIntrinsic>(&I)) {
if (dbgInst->getNumVariableLocationOps() > 1) {
dbgInst->setUndef();
Modified = true;
}
}
}
}
return Modified;
}
/***********************************************************************
* GenXDebugLegalization::runOnFunction : process one function to
* reduce integer size where possible
*/
bool GenXDebugLegalization::runOnFunction(Function &F)
{
bool Modified = false;
Modified |= extractAddressClass(F);
Modified |= removeDIArgList(F);
return Modified;
}
|