~ubuntu-branches/ubuntu/trusty/llvm-toolchain-snapshot/trusty-201310232150

« back to all changes in this revision

Viewing changes to lib/Transforms/Instrumentation/DebugIR.cpp

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-27 15:01:57 UTC
  • mfrom: (0.10.1) (0.9.1) (0.8.1) (0.7.1) (0.6.1) (0.5.2)
  • Revision ID: package-import@ubuntu.com-20130527150157-tdkrsjpuvht7v0qx
Tags: 1:3.4~svn182733-1~exp1
* New snapshot release (3.4 release)
* Add a symlink of libLLVM-3.4.so.1 to usr/lib/llvm-3.4/lib/libLLVM-3.4.so
    to fix make the llvm-config-3.4 --libdir work (Closes: #708677)
  * Various packages rename to allow co installations:
    * libclang1 => libclang1-3.4
    * libclang1-dbg => libclang1-3.4-dbg
    * libclang-dev => libclang-3.4-dev
    * libclang-common-dev => libclang-common-3.4-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
}