1
//===--- DebugIR.cpp - Transform debug metadata to allow debugging IR -----===//
3
// The LLVM Compiler Infrastructure
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
8
//===----------------------------------------------------------------------===//
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.
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
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.
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
27
//===----------------------------------------------------------------------===//
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"
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;
58
/// Prints Module to a null buffer in order to build the map of Value pointers
60
ValueToLineMap(Module *M) {
61
raw_null_ostream ThrowAway;
62
M->print(ThrowAway, this);
65
// This function is called after an Instruction, GlobalValue, or GlobalAlias
67
void printInfoComment(const Value &V, formatted_raw_ostream &Out) {
69
Lines.insert(std::make_pair(&V, Out.getLine() + 1));
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()) {
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(); }
89
void visitDbgDeclareInst(DbgDeclareInst &I) { remove(I); }
90
void visitDbgValueInst(DbgValueInst &I) { remove(I); }
91
void visitDbgInfoIntrinsic(DbgInfoIntrinsic &I) { remove(I); }
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> {
98
void visitInstruction(Instruction &I) {
99
if (I.getMetadata(LLVMContext::MD_dbg))
100
I.setMetadata(LLVMContext::MD_dbg, 0);
103
void run(Module *M) {
104
// Remove debug metadata attached to instructions
107
// Remove CU named metadata (and all children nodes)
108
NamedMDNode *Node = M->getNamedMetadata("llvm.dbg.cu");
109
M->eraseNamedMetadata(Node);
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;
119
/// Table of cloned values
120
const ValueToValueMapTy &VMap;
122
/// Directory of debug metadata
123
const DebugInfoFinder &Finder;
126
LineNumberReplacer(const ValueToLineMap &VLM, const DebugInfoFinder &Finder,
127
const ValueToValueMapTy &VMap)
128
: LineTable(VLM), VMap(VMap), Finder(Finder) {}
130
void visitInstruction(Instruction &I) {
131
DebugLoc Loc(I.getDebugLoc());
133
unsigned Col = 0; // FIXME: support columns
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.
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
148
DebugLoc::get(Line, Col, scope, /*FIXME: inlined instructions*/ 0);
150
// Neither I nor M has any debug information -- nothing to do here.
151
// FIXME: support debugging of undecorated IR (generated by clang without
155
addDebugLocation(const_cast<Instruction &>(I), NewLoc);
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();
166
if (S.getFunction() == F)
169
// cannot find F -- likely means there is no debug information
173
void addDebugLocation(Instruction &I, DebugLoc Loc) {
174
MDNode *MD = Loc.getAsMDNode(I.getContext());
175
I.setMetadata(LLVMContext::MD_dbg, MD);
179
class DebugIR : public ModulePass {
181
std::string Filename;
183
/// Flags to control the verbosity of the generated IR file
184
bool hideDebugIntrinsics;
185
bool hideDebugMetadata;
190
const char *getPassName() const { return "DebugIR"; }
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.
197
/// Output a file with the same base name as the original, but with the
198
/// postfix "-debug-ll" appended.
200
: ModulePass(ID), Postfix("-debug-ll"), hideDebugIntrinsics(true),
201
hideDebugMetadata(true) {}
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) {}
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;
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");
221
for (DebugInfoFinder::iterator i = Finder.compile_unit_begin(),
222
e = Finder.compile_unit_end();
224
DICompileUnit CU(*i);
225
Filename = CU.getFilename();
227
// Replace extension with postfix
228
size_t dot = Filename.find_last_of(".");
229
if (dot != std::string::npos)
233
CU.setFilename(Filename, M.getContext());
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);
248
void writeDebugBitcode(Module *M) {
250
tool_output_file OutFile(Filename.c_str(), error);
252
formatted_raw_ostream OS;
253
OS.setStream(OutFile.os());
257
void removeDebugIntrinsics(Module *M) {
258
DebugIntrinsicsRemover Remover;
262
void removeDebugMetadata(Module *M) {
263
DebugMetadataRemover Remover;
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.
272
ValueToValueMapTy VMap;
273
Module *DebuggerM = CloneModule(M, VMap);
275
if (hideDebugIntrinsics)
276
removeDebugIntrinsics(DebuggerM);
278
if (hideDebugMetadata)
279
removeDebugMetadata(DebuggerM);
281
// FIXME: remove all debug metadata from M once we support generating DWARF
282
// subprogram attributes.
284
ValueToLineMap LineTable(DebuggerM);
285
addLineNumberMetadata(M, LineTable, VMap, Finder);
286
writeDebugBitcode(DebuggerM);
289
bool runOnModule(Module &M) {
290
// Stores existing debug info needed when creating new line number entries.
291
DebugInfoFinder Finder;
292
Finder.processModule(M);
294
bool changed = replaceFilename(M, Finder);
296
updateAndWriteDebugIRFile(&M, Finder);
301
} // anonymous namespace
303
char DebugIR::ID = 0;
304
INITIALIZE_PASS(DebugIR, "debug-ir", "Enable debugging IR", false, false)
306
ModulePass *llvm::createDebugIRPass(StringRef FilenamePostfix,
307
bool hideDebugIntrinsics,
308
bool hideDebugMetadata) {
309
return new DebugIR(FilenamePostfix, hideDebugIntrinsics, hideDebugMetadata);