1 //===- MachineStripDebug.cpp - Strip debug info ---------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file This removes debug info from everything. It can be used to ensure
10 /// tests can be debugified without affecting the output MIR.
11 //===----------------------------------------------------------------------===//
12 
13 #include "llvm/CodeGen/MachineFunctionPass.h"
14 #include "llvm/CodeGen/MachineModuleInfo.h"
15 #include "llvm/CodeGen/Passes.h"
16 #include "llvm/IR/DebugInfo.h"
17 #include "llvm/InitializePasses.h"
18 #include "llvm/Support/CommandLine.h"
19 
20 #define DEBUG_TYPE "mir-strip-debug"
21 
22 using namespace llvm;
23 
24 namespace {
25 cl::opt<bool>
26     OnlyDebugifiedDefault("mir-strip-debugify-only",
27                           cl::desc("Should mir-strip-debug only strip debug "
28                                    "info from debugified modules by default"),
29                           cl::init(true));
30 
31 struct StripDebugMachineModule : public ModulePass {
32   bool runOnModule(Module &M) override {
33     if (OnlyDebugified) {
34       NamedMDNode *DebugifyMD = M.getNamedMetadata("llvm.debugify");
35       if (!DebugifyMD) {
36         LLVM_DEBUG(dbgs() << "Not stripping debug info"
37                              " (debugify metadata not found)?\n");
38         return false;
39       }
40     }
41 
42     MachineModuleInfo &MMI =
43         getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
44 
45     bool Changed = false;
46     for (Function &F : M.functions()) {
47       MachineFunction &MF = MMI.getOrCreateMachineFunction(F);
48       for (MachineBasicBlock &MBB : MF) {
49         for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
50              I != E;) {
51           if (I->isDebugInstr()) {
52             // FIXME: We should remove all of them. However, AArch64 emits an
53             //        invalid `DBG_VALUE $lr` with only one operand instead of
54             //        the usual three and has a test that depends on it's
55             //        preservation. Preserve it for now.
56             if (I->getNumOperands() > 1) {
57               LLVM_DEBUG(dbgs() << "Removing debug instruction " << *I);
58               I = MBB.erase(I);
59               Changed |= true;
60               continue;
61             }
62           }
63           if (I->getDebugLoc()) {
64             LLVM_DEBUG(dbgs() << "Removing location " << *I);
65             I->setDebugLoc(DebugLoc());
66             Changed |= true;
67             ++I;
68             continue;
69           }
70           LLVM_DEBUG(dbgs() << "Keeping " << *I);
71           ++I;
72         }
73       }
74     }
75 
76     Changed |= StripDebugInfo(M);
77 
78     NamedMDNode *NMD = M.getNamedMetadata("llvm.debugify");
79     if (NMD) {
80       NMD->eraseFromParent();
81       Changed |= true;
82     }
83 
84     NMD = M.getModuleFlagsMetadata();
85     if (NMD) {
86       // There must be an easier way to remove an operand from a NamedMDNode.
87       SmallVector<MDNode *, 4> Flags;
88       for (MDNode *Flag : NMD->operands())
89         Flags.push_back(Flag);
90       NMD->clearOperands();
91       for (MDNode *Flag : Flags) {
92         MDString *Key = dyn_cast_or_null<MDString>(Flag->getOperand(1));
93         if (Key->getString() == "Debug Info Version") {
94           Changed |= true;
95           continue;
96         }
97         NMD->addOperand(Flag);
98       }
99       // If we left it empty we might as well remove it.
100       if (NMD->getNumOperands() == 0)
101         NMD->eraseFromParent();
102     }
103 
104     return Changed;
105   }
106 
107   StripDebugMachineModule() : StripDebugMachineModule(OnlyDebugifiedDefault) {}
108   StripDebugMachineModule(bool OnlyDebugified)
109       : ModulePass(ID), OnlyDebugified(OnlyDebugified) {}
110 
111   void getAnalysisUsage(AnalysisUsage &AU) const override {
112     AU.addRequired<MachineModuleInfoWrapperPass>();
113     AU.addPreserved<MachineModuleInfoWrapperPass>();
114   }
115 
116   static char ID; // Pass identification.
117 
118 protected:
119   bool OnlyDebugified;
120 };
121 char StripDebugMachineModule::ID = 0;
122 
123 } // end anonymous namespace
124 
125 INITIALIZE_PASS_BEGIN(StripDebugMachineModule, DEBUG_TYPE,
126                       "Machine Strip Debug Module", false, false)
127 INITIALIZE_PASS_END(StripDebugMachineModule, DEBUG_TYPE,
128                     "Machine Strip Debug Module", false, false)
129 
130 ModulePass *createStripDebugMachineModulePass(bool OnlyDebugified) {
131   return new StripDebugMachineModule(OnlyDebugified);
132 }
133