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
|
//===- MachineStripDebug.cpp - Strip debug info ---------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file This removes debug info from everything. It can be used to ensure
/// tests can be debugified without affecting the output MIR.
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/InitializePasses.h"
#include "llvm/Support/CommandLine.h"
#define DEBUG_TYPE "mir-strip-debug"
using namespace llvm;
namespace {
cl::opt<bool>
OnlyDebugifiedDefault("mir-strip-debugify-only",
cl::desc("Should mir-strip-debug only strip debug "
"info from debugified modules by default"),
cl::init(true));
struct StripDebugMachineModule : public ModulePass {
bool runOnModule(Module &M) override {
if (OnlyDebugified) {
NamedMDNode *DebugifyMD = M.getNamedMetadata("llvm.debugify");
if (!DebugifyMD) {
LLVM_DEBUG(dbgs() << "Not stripping debug info"
" (debugify metadata not found)?\n");
return false;
}
}
MachineModuleInfo &MMI =
getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
bool Changed = false;
for (Function &F : M.functions()) {
MachineFunction &MF = MMI.getOrCreateMachineFunction(F);
for (MachineBasicBlock &MBB : MF) {
for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
I != E;) {
if (I->isDebugInstr()) {
// FIXME: We should remove all of them. However, AArch64 emits an
// invalid `DBG_VALUE $lr` with only one operand instead of
// the usual three and has a test that depends on it's
// preservation. Preserve it for now.
if (I->getNumOperands() > 1) {
LLVM_DEBUG(dbgs() << "Removing debug instruction " << *I);
I = MBB.erase(I);
Changed |= true;
continue;
}
}
if (I->getDebugLoc()) {
LLVM_DEBUG(dbgs() << "Removing location " << *I);
I->setDebugLoc(DebugLoc());
Changed |= true;
++I;
continue;
}
LLVM_DEBUG(dbgs() << "Keeping " << *I);
++I;
}
}
}
Changed |= StripDebugInfo(M);
NamedMDNode *NMD = M.getNamedMetadata("llvm.debugify");
if (NMD) {
NMD->eraseFromParent();
Changed |= true;
}
NMD = M.getModuleFlagsMetadata();
if (NMD) {
// There must be an easier way to remove an operand from a NamedMDNode.
SmallVector<MDNode *, 4> Flags;
for (MDNode *Flag : NMD->operands())
Flags.push_back(Flag);
NMD->clearOperands();
for (MDNode *Flag : Flags) {
MDString *Key = dyn_cast_or_null<MDString>(Flag->getOperand(1));
if (Key->getString() == "Debug Info Version") {
Changed |= true;
continue;
}
NMD->addOperand(Flag);
}
// If we left it empty we might as well remove it.
if (NMD->getNumOperands() == 0)
NMD->eraseFromParent();
}
return Changed;
}
StripDebugMachineModule() : StripDebugMachineModule(OnlyDebugifiedDefault) {}
StripDebugMachineModule(bool OnlyDebugified)
: ModulePass(ID), OnlyDebugified(OnlyDebugified) {}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addRequired<MachineModuleInfoWrapperPass>();
AU.addPreserved<MachineModuleInfoWrapperPass>();
}
static char ID; // Pass identification.
protected:
bool OnlyDebugified;
};
char StripDebugMachineModule::ID = 0;
} // end anonymous namespace
INITIALIZE_PASS_BEGIN(StripDebugMachineModule, DEBUG_TYPE,
"Machine Strip Debug Module", false, false)
INITIALIZE_PASS_END(StripDebugMachineModule, DEBUG_TYPE,
"Machine Strip Debug Module", false, false)
ModulePass *createStripDebugMachineModulePass(bool OnlyDebugified) {
return new StripDebugMachineModule(OnlyDebugified);
}
|