19 #define DEBUG_TYPE "debug-ir"
42 #define STR_HELPER(x) #x
43 #define STR(x) STR_HELPER(x)
58 Lines.insert(std::make_pair(V, Out.
getLine() + 1));
65 ValueToLineMap(
const Module *M) {
67 M->
print(ThrowAway,
this);
82 bool getLine(
const Value *V,
unsigned int &Line)
const {
83 LineIter i = Lines.find(V);
84 if (i != Lines.end()) {
93 class DebugIntrinsicsRemover :
public InstVisitor<DebugIntrinsicsRemover> {
98 DebugIntrinsicsRemover Remover;
108 class DebugMetadataRemover :
public InstVisitor<DebugMetadataRemover> {
109 bool RemoveNamedInfo;
112 static void process(
Module &M,
bool RemoveNamedInfo =
true) {
113 DebugMetadataRemover Remover(RemoveNamedInfo);
117 DebugMetadataRemover(
bool RemoveNamedInfo)
118 : RemoveNamedInfo(RemoveNamedInfo) {}
129 if (RemoveNamedInfo) {
150 const ValueToLineMap LineTable;
164 MDNode *LexicalBlockFileNode;
174 : Builder(M), Layout(&M), LineTable(DisplayM ? DisplayM : &M), VMap(VMap),
175 Finder(), Filename(Filename), Directory(Directory), FileNode(0),
176 LexicalBlockFileNode(0), CUNode(0) {
177 Finder.processModule(M);
181 ~DIUpdater() { Builder.finalize(); }
183 void visitModule(
Module &M) {
184 if (Finder.compile_unit_count() > 1)
188 Finder.compile_unit_count() == 1 ? *Finder.compile_unit_begin() : 0);
200 if (!findLine(&F, Line)) {
207 unsigned ScopeLine = 0;
208 if (!findLine(FirstInst, ScopeLine)) {
209 DEBUG(
dbgs() <<
"WARNING: No line for 1st Instruction in Function "
216 bool IsOptimized =
false;
219 assert(CUNode && FileNode);
222 Sig, Local, IsDefinition, ScopeLine, FuncFlags, IsOptimized, &
F);
224 DEBUG(
dbgs() <<
"create subprogram mdnode " << *Sub <<
": "
227 SubprogramDescriptors.insert(std::make_pair(&F, Sub));
238 RealInst = VMap->lookup(&I);
245 if (!LineTable.getLine(RealInst, Line)) {
248 DEBUG(
dbgs() <<
"WARNING: no LineTable entry for instruction " << RealInst
250 DEBUG(RealInst->dump());
255 if (!Loc.isUnknown())
257 NewLoc =
DebugLoc::get(Line, Col, Loc.getScope(RealInst->getContext()),
258 Loc.getInlinedAt(RealInst->getContext()));
259 else if (
MDNode *scope = findScope(&I))
262 DEBUG(
dbgs() <<
"WARNING: no valid scope for instruction " << &I
263 <<
". no DebugLoc will be present."
268 addDebugLocation(I, NewLoc);
273 void createCompileUnit(
MDNode *CUToReplace) {
275 bool IsOptimized =
false;
277 unsigned RuntimeVersion(0);
290 "LLVM Version " STR(LLVM_VERSION_MAJOR)
"." STR(LLVM_VERSION_MINOR);
295 Producer, IsOptimized, Flags, RuntimeVersion);
301 FileNode = Builder.createFile(Filename, Directory);
302 LexicalBlockFileNode = Builder.createLexicalBlockFile(CU,
DIFile(FileNode));
308 if (
MDNode *ret = findDISubprogram(F))
311 DEBUG(
dbgs() <<
"WARNING: Using fallback lexical block file scope "
312 << LexicalBlockFileNode <<
" as scope for instruction " << I
314 return LexicalBlockFileNode;
320 FuncNodeIter i = SubprogramDescriptors.find(F);
321 if (i != SubprogramDescriptors.end())
324 DEBUG(
dbgs() <<
"searching for DI scope node for Function " << F
325 <<
" in a list of " << Finder.subprogram_count()
326 <<
" subprogram nodes"
330 e = Finder.subprogram_end();
334 DEBUG(
dbgs() <<
"Found DISubprogram " << *i <<
" for function "
339 DEBUG(
dbgs() <<
"unable to find DISubprogram node for function "
346 bool findLine(
const Value *V,
unsigned &Line) {
347 if (LineTable.getLine(V, Line))
351 Value *mapped = VMap->lookup(V);
352 if (mapped && LineTable.getLine(mapped, Line))
358 std::string getTypeName(
Type *
T) {
359 std::string TypeName;
361 T->
print(TypeStream);
370 TypeNodeIter i = TypeDescriptors.
find(T);
371 if (i != TypeDescriptors.end())
384 N = Builder.createStructType(
386 0, Layout.getTypeSizeInBits(T), Layout.getABITypeAlignment(T), 0,
392 TypeDescriptors[
T] =
N;
400 StructDescriptor.
setTypeArray(Builder.getOrCreateArray(Elements));
404 N = Builder.createPointerType(
405 getOrCreateType(PointeeTy), Layout.getPointerTypeSizeInBits(T),
406 Layout.getPrefTypeAlignment(T), getTypeName(T));
412 N = Builder.createArrayType(Layout.getTypeSizeInBits(T),
413 Layout.getPrefTypeAlignment(T),
415 Builder.getOrCreateArray(Subrange));
426 TypeDescriptors[
T] =
N;
440 Type *
T(i->getType());
444 DIArray ParamArray = Builder.getOrCreateArray(Params);
445 return Builder.createSubroutineType(
DIFile(FileNode), ParamArray);
457 bool getSourceInfoFromModule(
const Module &M, std::string &Directory,
458 std::string &Filename) {
460 if (PathStr.length() == 0 || PathStr ==
"<stdin>")
466 Directory =
StringRef(Path.data(), Path.size());
472 bool getSourceInfoFromDI(
const Module &M, std::string &Directory,
473 std::string &Filename) {
483 Directory = CU.getDirectory();
491 bool DebugIR::getSourceInfo(
const Module &M) {
492 ParsedPath = getSourceInfoFromDI(M, Directory, Filename) ||
493 getSourceInfoFromModule(M, Directory, Filename);
497 bool DebugIR::updateExtension(
StringRef NewExtension) {
498 size_t dot = Filename.find_last_of(
".");
499 if (dot == std::string::npos)
503 Filename += NewExtension.
str();
516 GeneratedPath =
true;
519 std::string DebugIR::getPath() {
522 Path.
resize(Filename.size() + Directory.size() + 2);
523 Path[Filename.size() + Directory.size() + 1] =
'\0';
524 return std::string(Path.
data());
527 void DebugIR::writeDebugBitcode(
const Module *M,
int *fd) {
532 std::string Path = getPath();
534 DEBUG(
dbgs() <<
"WRITING debug bitcode from Module " << M <<
" to file "
537 DEBUG(
dbgs() <<
"WRITING debug bitcode from Module " << M <<
" to fd "
553 if (WriteSourceToDisk && (HideDebugIntrinsics || HideDebugMetadata)) {
557 if (HideDebugIntrinsics)
558 DebugIntrinsicsRemover::process(*DisplayM);
560 if (HideDebugMetadata)
561 DebugMetadataRemover::process(*DisplayM);
564 DIUpdater R(M, Filename, Directory, DisplayM.
get(), VMap.
get());
567 bool DebugIR::isMissingPath() {
return Filename.empty() || Directory.empty(); }
572 if (isMissingPath() && !getSourceInfo(M)) {
573 if (!WriteSourceToDisk)
575 "Ensure Module contains an identifier, a valid "
576 "DICompileUnit, or construct DebugIR with "
577 "non-empty Filename/Directory parameters.");
579 generateFilename(fd);
582 if (!GeneratedPath && WriteSourceToDisk)
583 updateExtension(
".debug-ll");
587 DebugMetadataRemover::process(M, !ParsedPath);
590 createDebugInfo(M, DisplayM);
591 if (WriteSourceToDisk) {
593 writeDebugBitcode(OutputM, fd.
get());
612 bool HideDebugMetadata,
StringRef Directory,
614 return new DebugIR(HideDebugIntrinsics, HideDebugMetadata, Directory,
void push_back(const T &Elt)
unsigned getStructNumElements() const
Base class for instruction visitors.
bool isSubprogram() const
Module * CloneModule(const Module *M)
The main container class for the LLVM Intermediate Representation.
StringRef getFlags() const
raw_null_ostream - A raw_ostream that discards all output.
std::string str() const
str - Get the contents as an std::string.
Type * getReturnType() const
const Function * getParent() const
Return the enclosing method, or null if none.
MDNode * getAsMDNode(const LLVMContext &Ctx) const
MDNode - a tuple of other values.
FunctionType * getType(LLVMContext &Context, ID id, ArrayRef< Type * > Tys=None)
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason, bool gen_crash_diag=true)
Type * getPointerElementType() const
StringRef getName() const
DIArray - This descriptor holds an array of descriptors.
void print(raw_ostream &O) const
void setTypeArray(DIArray Elements, DIArray TParams=DIArray())
Set the array of member DITypes.
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
void remove_filename(SmallVectorImpl< char > &path)
Remove the last component from path unless it is the root dir.
void eraseNamedMetadata(NamedMDNode *NMD)
Type * getArrayElementType() const
bool hasInternalLinkage() const
StringRef getStructName() const
ID
LLVM Calling Convention Representation.
const std::string & getModuleIdentifier() const
DISubprogram - This is a wrapper for a subprogram (e.g. a function).
bool isFloatingPointTy() const
void replaceAllUsesWith(Value *V)
DIFile - This is a wrapper for a file.
ModulePass * createDebugIRPass(bool HideDebugIntrinsics, bool HideDebugMetadata, StringRef Directory=StringRef(), StringRef Filename=StringRef())
Function * getFunction() const
StringRef getFilename() const
Generic base class which exposes information about an operating system process.
size_type LLVM_ATTRIBUTE_UNUSED_RESULT size() const
const DebugLoc & getDebugLoc() const
getDebugLoc - Return the debug location for this node as a DebugLoc.
MDNode * getOperand(unsigned i) const
getOperand - Return specified operand.
LLVMContext & getContext() const
All values hold a context through their type.
error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD, SmallVectorImpl< char > &ResultPath)
Create a file in the system temporary directory.
void setMetadata(unsigned KindID, MDNode *Node)
void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW) const
DIScope - A base class for various scopes.
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
const FunctionListType & getFunctionList() const
Get the Module's list of functions (constant).
MDNode * getMetadata(unsigned KindID) const
raw_ostream & dbgs()
dbgs - Return a circular-buffered debug stream.
bool runOnModule(llvm::Module &M, std::string &Path)
Run pass on M and set Path to the source file path in the output module.
static DebugLoc get(unsigned Line, unsigned Col, MDNode *Scope, MDNode *InlinedAt=0)
NamedMDNode * getNamedMetadata(const Twine &Name) const
pointer data()
data - Return a pointer to the vector's buffer, even if empty().
bool isDeclaration() const
unsigned getRunTimeVersion() const
uint64_t getArrayNumElements() const
unsigned getPrimitiveSizeInBits() const
LLVM Value Representation.
const ArgumentListType & getArgumentList() const
unsigned getNumOperands() const
getNumOperands - Return the number of NamedMDNode operands.
Type * getStructElementType(unsigned N) const
const StringRef filename(StringRef path)
Get filename.
DICompileUnit - A wrapper for a compile unit.
iterator find(const KeyT &Val)
StringRef getProducer() const
void dump() const
Dump the module to stderr (for debugging).
const BasicBlock * getParent() const
bool isVoidTy() const
isVoidTy - Return true if this is 'void'.
StringRef getSplitDebugFilename() const