Re-implement DebugIR in a way that does not subclass AssemblyWriter:
[oota-llvm.git] / lib / Transforms / Instrumentation / DebugIR.cpp
1 //===--- DebugIR.cpp - Transform debug metadata to allow debugging IR -----===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // A Module transform pass that emits a succinct version of the IR and replaces
11 // the source file metadata to allow debuggers to step through the IR.
12 //
13 // The location where the IR file is emitted is the same as the directory
14 // operand of the !llvm.dbg.cu metadata node present in the input module. The
15 // file name is constructed from the original file name by stripping the
16 // extension and replacing it with "-debug-ll" or the Postfix string specified
17 // at construction.
18 //
19 // FIXME: instead of replacing debug metadata, additional metadata should be
20 // used to point capable debuggers to the IR file without destroying the
21 // mapping to the original source file.
22 //
23 // FIXME: this pass should not depend on the existance of debug metadata in
24 // the module as it does now. Instead, it should use DIBuilder to create the
25 // required metadata.
26 //
27 //===----------------------------------------------------------------------===//
28
29 #include <string>
30
31 #include "llvm/ADT/OwningPtr.h"
32 #include "llvm/ADT/ValueMap.h"
33 #include "llvm/Assembly/AssemblyAnnotationWriter.h"
34 #include "llvm/DebugInfo.h"
35 #include "llvm/DIBuilder.h"
36 #include "llvm/InstVisitor.h"
37 #include "llvm/IR/Instruction.h"
38 #include "llvm/IR/Module.h"
39 #include "llvm/Pass.h"
40 #include "llvm/Transforms/Instrumentation.h"
41 #include "llvm/Transforms/Utils/Cloning.h"
42 #include "llvm/Support/Debug.h"
43 #include "llvm/Support/ToolOutputFile.h"
44 #include "llvm/Support/FormattedStream.h"
45 using namespace llvm;
46
47 namespace {
48
49 /// Builds a map of Value* to line numbers on which the Value appears in a
50 /// textual representation of the IR by plugging into the AssemblyWriter by
51 /// masquerading as an AssemblyAnnotationWriter.
52 class ValueToLineMap : public AssemblyAnnotationWriter {
53   ValueMap<const Value *, unsigned int> Lines;
54   typedef ValueMap<const Value *, unsigned int>::const_iterator LineIter;
55
56 public:
57
58   /// Prints Module to a null buffer in order to build the map of Value pointers
59   /// to line numbers.
60   ValueToLineMap(Module *M) {
61     raw_null_ostream ThrowAway;
62     M->print(ThrowAway, this);
63   }
64
65   // This function is called after an Instruction, GlobalValue, or GlobalAlias
66   // is printed.
67   void printInfoComment(const Value &V, formatted_raw_ostream &Out) {
68     Out.flush();
69     Lines.insert(std::make_pair(&V, Out.getLine() + 1));
70   }
71
72   /// If V appears on a line in the textual IR representation, sets Line to the
73   /// line number and returns true, otherwise returns false.
74   bool getLine(const Value *V, unsigned int &Line) const {
75     LineIter i = Lines.find(V);
76     if (i != Lines.end()) {
77       Line = i->second;
78       return true;
79     }
80     return false;
81   }
82 };
83
84 /// Removes debug intrisncs like llvm.dbg.declare and llvm.dbg.value.
85 class DebugIntrinsicsRemover : public InstVisitor<DebugIntrinsicsRemover> {
86   void remove(Instruction &I) { I.eraseFromParent(); }
87
88 public:
89   void visitDbgDeclareInst(DbgDeclareInst &I) { remove(I); }
90   void visitDbgValueInst(DbgValueInst &I) { remove(I); }
91   void visitDbgInfoIntrinsic(DbgInfoIntrinsic &I) { remove(I); }
92 };
93
94 /// Removes debug metadata (!dbg) nodes from all instructions as well as
95 /// metadata named "llvm.dbg.cu" in the Module.
96 class DebugMetadataRemover : public InstVisitor<DebugMetadataRemover> {
97 public:
98   void visitInstruction(Instruction &I) {
99     if (I.getMetadata(LLVMContext::MD_dbg))
100       I.setMetadata(LLVMContext::MD_dbg, 0);
101   }
102
103   void run(Module *M) {
104     // Remove debug metadata attached to instructions
105     visit(M);
106
107     // Remove CU named metadata (and all children nodes)
108     NamedMDNode *Node = M->getNamedMetadata("llvm.dbg.cu");
109     M->eraseNamedMetadata(Node);
110   }
111 };
112
113 /// Replaces line number metadata attached to Instruction nodes with new line
114 /// numbers provided by the ValueToLineMap.
115 class LineNumberReplacer : public InstVisitor<LineNumberReplacer> {
116   /// Table of line numbers
117   const ValueToLineMap &LineTable;
118
119   /// Table of cloned values
120   const ValueToValueMapTy &VMap;
121
122   /// Directory of debug metadata
123   const DebugInfoFinder &Finder;
124
125 public:
126   LineNumberReplacer(const ValueToLineMap &VLM, const DebugInfoFinder &Finder,
127                      const ValueToValueMapTy &VMap)
128       : LineTable(VLM), VMap(VMap), Finder(Finder) {}
129
130   void visitInstruction(Instruction &I) {
131     DebugLoc Loc(I.getDebugLoc());
132
133     unsigned Col = 0; // FIXME: support columns
134     unsigned Line;
135     if (!LineTable.getLine(VMap.lookup(&I), Line))
136       // Instruction has no line, it may have been removed (in the module that
137       // will be passed to the debugger) so there is nothing to do here.
138       return;
139
140     DebugLoc NewLoc;
141     if (!Loc.isUnknown())
142       // I had a previous debug location: re-use the DebugLoc
143       NewLoc = DebugLoc::get(Line, Col, Loc.getScope(I.getContext()),
144                              Loc.getInlinedAt(I.getContext()));
145     else if (MDNode *scope = findFunctionMD(I.getParent()->getParent()))
146       // I had no previous debug location, but M has some debug information
147       NewLoc =
148           DebugLoc::get(Line, Col, scope, /*FIXME: inlined instructions*/ 0);
149     else
150       // Neither I nor M has any debug information -- nothing to do here.
151       // FIXME: support debugging of undecorated IR (generated by clang without
152       //        the -g option)
153       return;
154
155     addDebugLocation(const_cast<Instruction &>(I), NewLoc);
156   }
157
158 private:
159
160   /// Returns the MDNode that corresponds with F
161   MDNode *findFunctionMD(const Function *F) {
162     for (DebugInfoFinder::iterator i = Finder.subprogram_begin(),
163                                    e = Finder.subprogram_end();
164          i != e; ++i) {
165       DISubprogram S(*i);
166       if (S.getFunction() == F)
167         return *i;
168     }
169     // cannot find F -- likely means there is no debug information
170     return 0;
171   }
172
173   void addDebugLocation(Instruction &I, DebugLoc Loc) {
174     MDNode *MD = Loc.getAsMDNode(I.getContext());
175     I.setMetadata(LLVMContext::MD_dbg, MD);
176   }
177 };
178
179 class DebugIR : public ModulePass {
180   std::string Postfix;
181   std::string Filename;
182
183   /// Flags to control the verbosity of the generated IR file
184   bool hideDebugIntrinsics;
185   bool hideDebugMetadata;
186
187 public:
188   static char ID;
189
190   const char *getPassName() const { return "DebugIR"; }
191
192   // FIXME: figure out if we are compiling something that already exists on disk
193   // in text IR form, in which case we can omit outputting a new IR file, or if
194   // we're building something from memory where we actually need to emit a new
195   // IR file for the debugger.
196
197   /// Output a file with the same base name as the original, but with the
198   /// postfix "-debug-ll" appended.
199   DebugIR()
200       : ModulePass(ID), Postfix("-debug-ll"), hideDebugIntrinsics(true),
201         hideDebugMetadata(true) {}
202
203   /// Customize the postfix string used to replace the extension of the
204   /// original filename that appears in the !llvm.dbg.cu metadata node.
205   DebugIR(StringRef postfix, bool hideDebugIntrinsics, bool hideDebugMetadata)
206       : ModulePass(ID), Postfix(postfix),
207         hideDebugIntrinsics(hideDebugIntrinsics),
208         hideDebugMetadata(hideDebugMetadata) {}
209
210 private:
211   // Modify the filename embedded in the Compilation-Unit debug information of M
212   bool replaceFilename(Module &M, const DebugInfoFinder &Finder) {
213     bool changed = false;
214
215     // Sanity check -- if llvm.dbg.cu node exists, the DebugInfoFinder
216     // better have found at least one CU!
217     if (M.getNamedMetadata("llvm.dbg.cu"))
218       assert(Finder.compile_unit_count() > 0 &&
219              "Found no compile units but llvm.dbg.cu node exists");
220
221     for (DebugInfoFinder::iterator i = Finder.compile_unit_begin(),
222                                    e = Finder.compile_unit_end();
223          i != e; ++i) {
224       DICompileUnit CU(*i);
225       Filename = CU.getFilename();
226
227       // Replace extension with postfix
228       size_t dot = Filename.find_last_of(".");
229       if (dot != std::string::npos)
230         Filename.erase(dot);
231       Filename += Postfix;
232
233       CU.setFilename(Filename, M.getContext());
234       changed = true;
235     }
236     return changed;
237   }
238
239   /// Replace existing line number metadata with line numbers that correspond
240   /// with the IR file that is seen by the debugger.
241   void addLineNumberMetadata(Module *M, const ValueToLineMap &VLM,
242                              const ValueToValueMapTy &VMap,
243                              const DebugInfoFinder &Finder) {
244     LineNumberReplacer Replacer(VLM, Finder, VMap);
245     Replacer.visit(M);
246   }
247
248   void writeDebugBitcode(Module *M) {
249     std::string error;
250     tool_output_file OutFile(Filename.c_str(), error);
251     OutFile.keep();
252     formatted_raw_ostream OS;
253     OS.setStream(OutFile.os());
254     M->print(OS, 0);
255   }
256
257   void removeDebugIntrinsics(Module *M) {
258     DebugIntrinsicsRemover Remover;
259     Remover.visit(M);
260   }
261
262   void removeDebugMetadata(Module *M) {
263     DebugMetadataRemover Remover;
264     Remover.run(M);
265   }
266
267   void updateAndWriteDebugIRFile(Module *M, const DebugInfoFinder &Finder) {
268     // The module we output in text form for a debugger to open is stripped of
269     // 'extras' like debug intrinsics that end up in DWARF anyways and just
270     // clutter the debug experience.
271
272     ValueToValueMapTy VMap;
273     Module *DebuggerM = CloneModule(M, VMap);
274
275     if (hideDebugIntrinsics)
276       removeDebugIntrinsics(DebuggerM);
277
278     if (hideDebugMetadata)
279       removeDebugMetadata(DebuggerM);
280
281     // FIXME: remove all debug metadata from M once we support generating DWARF
282     // subprogram attributes.
283
284     ValueToLineMap LineTable(DebuggerM);
285     addLineNumberMetadata(M, LineTable, VMap, Finder);
286     writeDebugBitcode(DebuggerM);
287   }
288
289   bool runOnModule(Module &M) {
290     // Stores existing debug info needed when creating new line number entries.
291     DebugInfoFinder Finder;
292     Finder.processModule(M);
293
294     bool changed = replaceFilename(M, Finder);
295     if (changed)
296       updateAndWriteDebugIRFile(&M, Finder);
297     return changed;
298   }
299 };
300
301 } // anonymous namespace
302
303 char DebugIR::ID = 0;
304 INITIALIZE_PASS(DebugIR, "debug-ir", "Enable debugging IR", false, false)
305
306 ModulePass *llvm::createDebugIRPass(StringRef FilenamePostfix,
307                                     bool hideDebugIntrinsics,
308                                     bool hideDebugMetadata) {
309   return new DebugIR(FilenamePostfix, hideDebugIntrinsics, hideDebugMetadata);
310 }