blob: 020804ff5f7871961dd25a2f2316bd2b4a88dadd [file] [log] [blame]
Daniel Malea13ace662013-05-08 20:44:14 +00001//===--- 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
Daniel Maleaf8c243a2013-05-23 22:34:33 +000016// extension and replacing it with "-debug-ll" or the Postfix string specified
Daniel Malea13ace662013-05-08 20:44:14 +000017// 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
Daniel Maleaf8c243a2013-05-23 22:34:33 +000031#include "llvm/ADT/OwningPtr.h"
32#include "llvm/ADT/ValueMap.h"
33#include "llvm/Assembly/AssemblyAnnotationWriter.h"
Daniel Malea13ace662013-05-08 20:44:14 +000034#include "llvm/DebugInfo.h"
35#include "llvm/DIBuilder.h"
Daniel Maleaf8c243a2013-05-23 22:34:33 +000036#include "llvm/InstVisitor.h"
Daniel Malea13ace662013-05-08 20:44:14 +000037#include "llvm/IR/Instruction.h"
Daniel Malea13ace662013-05-08 20:44:14 +000038#include "llvm/IR/Module.h"
39#include "llvm/Pass.h"
40#include "llvm/Transforms/Instrumentation.h"
Daniel Maleaf8c243a2013-05-23 22:34:33 +000041#include "llvm/Transforms/Utils/Cloning.h"
Daniel Malea13ace662013-05-08 20:44:14 +000042#include "llvm/Support/Debug.h"
43#include "llvm/Support/ToolOutputFile.h"
Daniel Maleaf8c243a2013-05-23 22:34:33 +000044#include "llvm/Support/FormattedStream.h"
Daniel Malea13ace662013-05-08 20:44:14 +000045using namespace llvm;
46
47namespace {
48
Daniel Maleaf8c243a2013-05-23 22:34:33 +000049/// 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.
52class ValueToLineMap : public AssemblyAnnotationWriter {
53 ValueMap<const Value *, unsigned int> Lines;
54 typedef ValueMap<const Value *, unsigned int>::const_iterator LineIter;
Daniel Malea13ace662013-05-08 20:44:14 +000055
Daniel Maleaf8c243a2013-05-23 22:34:33 +000056public:
Daniel Malea13ace662013-05-08 20:44:14 +000057
Daniel Maleaf8c243a2013-05-23 22:34:33 +000058 /// 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.
85class DebugIntrinsicsRemover : public InstVisitor<DebugIntrinsicsRemover> {
86 void remove(Instruction &I) { I.eraseFromParent(); }
87
88public:
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.
96class DebugMetadataRemover : public InstVisitor<DebugMetadataRemover> {
97public:
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.
115class LineNumberReplacer : public InstVisitor<LineNumberReplacer> {
116 /// Table of line numbers
117 const ValueToLineMap &LineTable;
118
119 /// Table of cloned values
120 const ValueToValueMapTy &VMap;
121
Daniel Malea13ace662013-05-08 20:44:14 +0000122 /// Directory of debug metadata
123 const DebugInfoFinder &Finder;
124
Daniel Malea13ace662013-05-08 20:44:14 +0000125public:
Daniel Maleaf8c243a2013-05-23 22:34:33 +0000126 LineNumberReplacer(const ValueToLineMap &VLM, const DebugInfoFinder &Finder,
127 const ValueToValueMapTy &VMap)
128 : LineTable(VLM), VMap(VMap), Finder(Finder) {}
Daniel Malea13ace662013-05-08 20:44:14 +0000129
Daniel Maleaf8c243a2013-05-23 22:34:33 +0000130 void visitInstruction(Instruction &I) {
Daniel Malea13ace662013-05-08 20:44:14 +0000131 DebugLoc Loc(I.getDebugLoc());
132
Daniel Maleaf8c243a2013-05-23 22:34:33 +0000133 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;
Daniel Malea13ace662013-05-08 20:44:14 +0000139
140 DebugLoc NewLoc;
141 if (!Loc.isUnknown())
142 // I had a previous debug location: re-use the DebugLoc
Daniel Maleaf8c243a2013-05-23 22:34:33 +0000143 NewLoc = DebugLoc::get(Line, Col, Loc.getScope(I.getContext()),
Daniel Malea13ace662013-05-08 20:44:14 +0000144 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
Daniel Maleaf8c243a2013-05-23 22:34:33 +0000147 NewLoc =
148 DebugLoc::get(Line, Col, scope, /*FIXME: inlined instructions*/ 0);
Daniel Malea13ace662013-05-08 20:44:14 +0000149 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
Daniel Malea13ace662013-05-08 20:44:14 +0000155 addDebugLocation(const_cast<Instruction &>(I), NewLoc);
156 }
157
Daniel Maleaf8c243a2013-05-23 22:34:33 +0000158private:
Daniel Malea13ace662013-05-08 20:44:14 +0000159
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
Daniel Malea13ace662013-05-08 20:44:14 +0000173 void addDebugLocation(Instruction &I, DebugLoc Loc) {
174 MDNode *MD = Loc.getAsMDNode(I.getContext());
175 I.setMetadata(LLVMContext::MD_dbg, MD);
176 }
177};
178
179class DebugIR : public ModulePass {
180 std::string Postfix;
181 std::string Filename;
Daniel Maleaf8c243a2013-05-23 22:34:33 +0000182
183 /// Flags to control the verbosity of the generated IR file
184 bool hideDebugIntrinsics;
185 bool hideDebugMetadata;
Daniel Malea13ace662013-05-08 20:44:14 +0000186
187public:
188 static char ID;
189
Daniel Maleaf8c243a2013-05-23 22:34:33 +0000190 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) {}
Daniel Malea13ace662013-05-08 20:44:14 +0000202
203 /// Customize the postfix string used to replace the extension of the
204 /// original filename that appears in the !llvm.dbg.cu metadata node.
Daniel Maleaf8c243a2013-05-23 22:34:33 +0000205 DebugIR(StringRef postfix, bool hideDebugIntrinsics, bool hideDebugMetadata)
206 : ModulePass(ID), Postfix(postfix),
207 hideDebugIntrinsics(hideDebugIntrinsics),
208 hideDebugMetadata(hideDebugMetadata) {}
Daniel Malea13ace662013-05-08 20:44:14 +0000209
210private:
211 // Modify the filename embedded in the Compilation-Unit debug information of M
Daniel Maleaf8c243a2013-05-23 22:34:33 +0000212 bool replaceFilename(Module &M, const DebugInfoFinder &Finder) {
Daniel Malea13ace662013-05-08 20:44:14 +0000213 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
Daniel Maleaf8c243a2013-05-23 22:34:33 +0000239 /// 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) {
Daniel Malea13ace662013-05-08 20:44:14 +0000249 std::string error;
250 tool_output_file OutFile(Filename.c_str(), error);
251 OutFile.keep();
252 formatted_raw_ostream OS;
Daniel Maleaf8c243a2013-05-23 22:34:33 +0000253 OS.setStream(OutFile.os());
254 M->print(OS, 0);
255 }
Daniel Malea13ace662013-05-08 20:44:14 +0000256
Daniel Maleaf8c243a2013-05-23 22:34:33 +0000257 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);
Daniel Malea13ace662013-05-08 20:44:14 +0000287 }
288
289 bool runOnModule(Module &M) {
Daniel Maleaf8c243a2013-05-23 22:34:33 +0000290 // Stores existing debug info needed when creating new line number entries.
291 DebugInfoFinder Finder;
Daniel Malea13ace662013-05-08 20:44:14 +0000292 Finder.processModule(M);
Daniel Maleaf8c243a2013-05-23 22:34:33 +0000293
294 bool changed = replaceFilename(M, Finder);
Daniel Malea13ace662013-05-08 20:44:14 +0000295 if (changed)
Daniel Maleaf8c243a2013-05-23 22:34:33 +0000296 updateAndWriteDebugIRFile(&M, Finder);
Daniel Malea13ace662013-05-08 20:44:14 +0000297 return changed;
298 }
299};
300
301} // anonymous namespace
302
303char DebugIR::ID = 0;
304INITIALIZE_PASS(DebugIR, "debug-ir", "Enable debugging IR", false, false)
Daniel Maleaf8c243a2013-05-23 22:34:33 +0000305
306ModulePass *llvm::createDebugIRPass(StringRef FilenamePostfix,
307 bool hideDebugIntrinsics,
308 bool hideDebugMetadata) {
309 return new DebugIR(FilenamePostfix, hideDebugIntrinsics, hideDebugMetadata);
Daniel Malea13ace662013-05-08 20:44:14 +0000310}