llvm-6502/lib/Analysis/DebugInfo.cpp

1288 lines
40 KiB
C++
Raw Normal View History

//===--- DebugInfo.cpp - Debug Information Helper Classes -----------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the helper classes used to build and interpret debug
// information in LLVM IR form.
//
//===----------------------------------------------------------------------===//
#include "llvm/Analysis/DebugInfo.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Intrinsics.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/Instructions.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/DebugLoc.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
using namespace llvm::dwarf;
//===----------------------------------------------------------------------===//
// DIDescriptor
//===----------------------------------------------------------------------===//
/// ValidDebugInfo - Return true if V represents valid debug info value.
/// FIXME : Add DIDescriptor.isValid()
bool DIDescriptor::ValidDebugInfo(MDNode *N, CodeGenOpt::Level OptLevel) {
if (!N)
return false;
DIDescriptor DI(N);
// Check current version. Allow Version6 for now.
unsigned Version = DI.getVersion();
if (Version != LLVMDebugVersion && Version != LLVMDebugVersion6)
return false;
unsigned Tag = DI.getTag();
switch (Tag) {
case DW_TAG_variable:
assert(DIVariable(N).Verify() && "Invalid DebugInfo value");
break;
case DW_TAG_compile_unit:
assert(DICompileUnit(N).Verify() && "Invalid DebugInfo value");
break;
case DW_TAG_subprogram:
assert(DISubprogram(N).Verify() && "Invalid DebugInfo value");
break;
case DW_TAG_lexical_block:
// FIXME: This interfers with the quality of generated code during
// optimization.
if (OptLevel != CodeGenOpt::None)
return false;
// FALLTHROUGH
default:
break;
}
return true;
}
DIDescriptor::DIDescriptor(MDNode *N, unsigned RequiredTag) {
DbgNode = N;
// If this is non-null, check to see if the Tag matches. If not, set to null.
if (N && getTag() != RequiredTag) {
DbgNode = 0;
}
}
const std::string &
DIDescriptor::getStringField(unsigned Elt, std::string &Result) const {
Result.clear();
if (DbgNode == 0)
return Result;
if (Elt < DbgNode->getNumElements())
if (MDString *MDS = dyn_cast_or_null<MDString>(DbgNode->getElement(Elt))) {
Result.assign(MDS->begin(), MDS->begin() + MDS->length());
return Result;
}
return Result;
}
uint64_t DIDescriptor::getUInt64Field(unsigned Elt) const {
if (DbgNode == 0)
return 0;
if (Elt < DbgNode->getNumElements())
if (ConstantInt *CI = dyn_cast<ConstantInt>(DbgNode->getElement(Elt)))
return CI->getZExtValue();
return 0;
}
DIDescriptor DIDescriptor::getDescriptorField(unsigned Elt) const {
if (DbgNode == 0)
return DIDescriptor();
if (Elt < DbgNode->getNumElements() && DbgNode->getElement(Elt))
return DIDescriptor(dyn_cast<MDNode>(DbgNode->getElement(Elt)));
return DIDescriptor();
}
GlobalVariable *DIDescriptor::getGlobalVariableField(unsigned Elt) const {
if (DbgNode == 0)
return 0;
if (Elt < DbgNode->getNumElements())
return dyn_cast<GlobalVariable>(DbgNode->getElement(Elt));
return 0;
}
//===----------------------------------------------------------------------===//
// Predicates
//===----------------------------------------------------------------------===//
/// isBasicType - Return true if the specified tag is legal for
/// DIBasicType.
bool DIDescriptor::isBasicType() const {
assert (!isNull() && "Invalid descriptor!");
unsigned Tag = getTag();
return Tag == dwarf::DW_TAG_base_type;
}
/// isDerivedType - Return true if the specified tag is legal for DIDerivedType.
bool DIDescriptor::isDerivedType() const {
assert (!isNull() && "Invalid descriptor!");
unsigned Tag = getTag();
switch (Tag) {
case dwarf::DW_TAG_typedef:
case dwarf::DW_TAG_pointer_type:
case dwarf::DW_TAG_reference_type:
case dwarf::DW_TAG_const_type:
case dwarf::DW_TAG_volatile_type:
case dwarf::DW_TAG_restrict_type:
case dwarf::DW_TAG_member:
case dwarf::DW_TAG_inheritance:
return true;
default:
// CompositeTypes are currently modelled as DerivedTypes.
return isCompositeType();
}
}
/// isCompositeType - Return true if the specified tag is legal for
/// DICompositeType.
bool DIDescriptor::isCompositeType() const {
assert (!isNull() && "Invalid descriptor!");
unsigned Tag = getTag();
switch (Tag) {
case dwarf::DW_TAG_array_type:
case dwarf::DW_TAG_structure_type:
case dwarf::DW_TAG_union_type:
case dwarf::DW_TAG_enumeration_type:
case dwarf::DW_TAG_vector_type:
case dwarf::DW_TAG_subroutine_type:
case dwarf::DW_TAG_class_type:
return true;
default:
return false;
}
}
/// isVariable - Return true if the specified tag is legal for DIVariable.
bool DIDescriptor::isVariable() const {
assert (!isNull() && "Invalid descriptor!");
unsigned Tag = getTag();
switch (Tag) {
case dwarf::DW_TAG_auto_variable:
case dwarf::DW_TAG_arg_variable:
case dwarf::DW_TAG_return_variable:
return true;
default:
return false;
}
}
/// isSubprogram - Return true if the specified tag is legal for
/// DISubprogram.
bool DIDescriptor::isSubprogram() const {
assert (!isNull() && "Invalid descriptor!");
unsigned Tag = getTag();
return Tag == dwarf::DW_TAG_subprogram;
}
/// isGlobalVariable - Return true if the specified tag is legal for
/// DIGlobalVariable.
bool DIDescriptor::isGlobalVariable() const {
assert (!isNull() && "Invalid descriptor!");
unsigned Tag = getTag();
return Tag == dwarf::DW_TAG_variable;
}
/// isScope - Return true if the specified tag is one of the scope
/// related tag.
bool DIDescriptor::isScope() const {
assert (!isNull() && "Invalid descriptor!");
unsigned Tag = getTag();
switch (Tag) {
case dwarf::DW_TAG_compile_unit:
case dwarf::DW_TAG_lexical_block:
case dwarf::DW_TAG_subprogram:
return true;
default:
break;
}
return false;
}
/// isCompileUnit - Return true if the specified tag is DW_TAG_compile_unit.
bool DIDescriptor::isCompileUnit() const {
assert (!isNull() && "Invalid descriptor!");
unsigned Tag = getTag();
return Tag == dwarf::DW_TAG_compile_unit;
}
/// isLexicalBlock - Return true if the specified tag is DW_TAG_lexical_block.
bool DIDescriptor::isLexicalBlock() const {
assert (!isNull() && "Invalid descriptor!");
unsigned Tag = getTag();
return Tag == dwarf::DW_TAG_lexical_block;
}
//===----------------------------------------------------------------------===//
// Simple Descriptor Constructors and other Methods
//===----------------------------------------------------------------------===//
DIType::DIType(MDNode *N) : DIDescriptor(N) {
if (!N) return;
if (!isBasicType() && !isDerivedType() && !isCompositeType()) {
DbgNode = 0;
}
}
unsigned DIArray::getNumElements() const {
assert (DbgNode && "Invalid DIArray");
return DbgNode->getNumElements();
}
/// replaceAllUsesWith - Replace all uses of debug info referenced by
/// this descriptor. After this completes, the current debug info value
/// is erased.
void DIDerivedType::replaceAllUsesWith(DIDescriptor &D) {
if (isNull())
return;
assert (!D.isNull() && "Can not replace with null");
// Since we use a TrackingVH for the node, its easy for clients to manufacture
// legitimate situations where they want to replaceAllUsesWith() on something
// which, due to uniquing, has merged with the source. We shield clients from
// this detail by allowing a value to be replaced with replaceAllUsesWith()
// itself.
if (getNode() != D.getNode()) {
MDNode *Node = DbgNode;
Node->replaceAllUsesWith(D.getNode());
delete Node;
}
}
/// Verify - Verify that a compile unit is well formed.
bool DICompileUnit::Verify() const {
if (isNull())
return false;
std::string Res;
if (getFilename(Res).empty())
return false;
// It is possible that directory and produce string is empty.
return true;
}
/// Verify - Verify that a type descriptor is well formed.
bool DIType::Verify() const {
if (isNull())
return false;
if (getContext().isNull())
return false;
DICompileUnit CU = getCompileUnit();
if (!CU.isNull() && !CU.Verify())
return false;
return true;
}
/// Verify - Verify that a composite type descriptor is well formed.
bool DICompositeType::Verify() const {
if (isNull())
return false;
if (getContext().isNull())
return false;
DICompileUnit CU = getCompileUnit();
if (!CU.isNull() && !CU.Verify())
return false;
return true;
}
/// Verify - Verify that a subprogram descriptor is well formed.
bool DISubprogram::Verify() const {
if (isNull())
return false;
if (getContext().isNull())
return false;
DICompileUnit CU = getCompileUnit();
if (!CU.Verify())
return false;
DICompositeType Ty = getType();
if (!Ty.isNull() && !Ty.Verify())
return false;
return true;
}
/// Verify - Verify that a global variable descriptor is well formed.
bool DIGlobalVariable::Verify() const {
if (isNull())
return false;
if (getContext().isNull())
return false;
DICompileUnit CU = getCompileUnit();
if (!CU.isNull() && !CU.Verify())
return false;
DIType Ty = getType();
if (!Ty.Verify())
return false;
if (!getGlobal())
return false;
return true;
}
/// Verify - Verify that a variable descriptor is well formed.
bool DIVariable::Verify() const {
if (isNull())
return false;
if (getContext().isNull())
return false;
DIType Ty = getType();
if (!Ty.Verify())
return false;
return true;
}
/// getOriginalTypeSize - If this type is derived from a base type then
/// return base type size.
uint64_t DIDerivedType::getOriginalTypeSize() const {
if (getTag() != dwarf::DW_TAG_member)
return getSizeInBits();
DIType BT = getTypeDerivedFrom();
if (BT.getTag() != dwarf::DW_TAG_base_type)
return getSizeInBits();
return BT.getSizeInBits();
}
/// describes - Return true if this subprogram provides debugging
/// information for the function F.
bool DISubprogram::describes(const Function *F) {
assert (F && "Invalid function");
std::string Name;
getLinkageName(Name);
if (Name.empty())
getName(Name);
if (F->getName() == Name)
return true;
return false;
}
//===----------------------------------------------------------------------===//
// DIDescriptor: dump routines for all descriptors.
//===----------------------------------------------------------------------===//
/// dump - Print descriptor.
void DIDescriptor::dump() const {
errs() << "[" << dwarf::TagString(getTag()) << "] ";
errs().write_hex((intptr_t) &*DbgNode) << ']';
}
/// dump - Print compile unit.
void DICompileUnit::dump() const {
if (getLanguage())
errs() << " [" << dwarf::LanguageString(getLanguage()) << "] ";
std::string Res1, Res2;
errs() << " [" << getDirectory(Res1) << "/" << getFilename(Res2) << " ]";
}
/// dump - Print type.
void DIType::dump() const {
if (isNull()) return;
std::string Res;
if (!getName(Res).empty())
errs() << " [" << Res << "] ";
unsigned Tag = getTag();
errs() << " [" << dwarf::TagString(Tag) << "] ";
// TODO : Print context
getCompileUnit().dump();
errs() << " ["
<< getLineNumber() << ", "
<< getSizeInBits() << ", "
<< getAlignInBits() << ", "
<< getOffsetInBits()
<< "] ";
if (isPrivate())
errs() << " [private] ";
else if (isProtected())
errs() << " [protected] ";
if (isForwardDecl())
errs() << " [fwd] ";
if (isBasicType())
DIBasicType(DbgNode).dump();
else if (isDerivedType())
DIDerivedType(DbgNode).dump();
else if (isCompositeType())
DICompositeType(DbgNode).dump();
else {
errs() << "Invalid DIType\n";
return;
}
errs() << "\n";
}
/// dump - Print basic type.
void DIBasicType::dump() const {
errs() << " [" << dwarf::AttributeEncodingString(getEncoding()) << "] ";
}
/// dump - Print derived type.
void DIDerivedType::dump() const {
errs() << "\n\t Derived From: "; getTypeDerivedFrom().dump();
}
/// dump - Print composite type.
void DICompositeType::dump() const {
DIArray A = getTypeArray();
if (A.isNull())
return;
errs() << " [" << A.getNumElements() << " elements]";
}
/// dump - Print global.
void DIGlobal::dump() const {
std::string Res;
if (!getName(Res).empty())
errs() << " [" << Res << "] ";
unsigned Tag = getTag();
errs() << " [" << dwarf::TagString(Tag) << "] ";
// TODO : Print context
getCompileUnit().dump();
errs() << " [" << getLineNumber() << "] ";
if (isLocalToUnit())
errs() << " [local] ";
if (isDefinition())
errs() << " [def] ";
if (isGlobalVariable())
DIGlobalVariable(DbgNode).dump();
errs() << "\n";
}
/// dump - Print subprogram.
void DISubprogram::dump() const {
std::string Res;
if (!getName(Res).empty())
errs() << " [" << Res << "] ";
unsigned Tag = getTag();
errs() << " [" << dwarf::TagString(Tag) << "] ";
// TODO : Print context
getCompileUnit().dump();
errs() << " [" << getLineNumber() << "] ";
if (isLocalToUnit())
errs() << " [local] ";
if (isDefinition())
errs() << " [def] ";
errs() << "\n";
}
/// dump - Print global variable.
void DIGlobalVariable::dump() const {
errs() << " [";
getGlobal()->dump();
errs() << "] ";
}
/// dump - Print variable.
void DIVariable::dump() const {
std::string Res;
if (!getName(Res).empty())
errs() << " [" << Res << "] ";
getCompileUnit().dump();
errs() << " [" << getLineNumber() << "] ";
getType().dump();
errs() << "\n";
}
//===----------------------------------------------------------------------===//
// DIFactory: Basic Helpers
//===----------------------------------------------------------------------===//
DIFactory::DIFactory(Module &m)
: M(m), VMContext(M.getContext()), StopPointFn(0), FuncStartFn(0),
RegionStartFn(0), RegionEndFn(0),
DeclareFn(0) {
EmptyStructPtr = PointerType::getUnqual(StructType::get(VMContext));
}
Constant *DIFactory::GetTagConstant(unsigned TAG) {
assert((TAG & LLVMDebugVersionMask) == 0 &&
"Tag too large for debug encoding!");
return ConstantInt::get(Type::getInt32Ty(VMContext), TAG | LLVMDebugVersion);
}
//===----------------------------------------------------------------------===//
// DIFactory: Primary Constructors
//===----------------------------------------------------------------------===//
/// GetOrCreateArray - Create an descriptor for an array of descriptors.
/// This implicitly uniques the arrays created.
DIArray DIFactory::GetOrCreateArray(DIDescriptor *Tys, unsigned NumTys) {
SmallVector<Value*, 16> Elts;
if (NumTys == 0)
Elts.push_back(llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)));
else
for (unsigned i = 0; i != NumTys; ++i)
Elts.push_back(Tys[i].getNode());
return DIArray(MDNode::get(VMContext,Elts.data(), Elts.size()));
}
/// GetOrCreateSubrange - Create a descriptor for a value range. This
/// implicitly uniques the values returned.
DISubrange DIFactory::GetOrCreateSubrange(int64_t Lo, int64_t Hi) {
Value *Elts[] = {
GetTagConstant(dwarf::DW_TAG_subrange_type),
ConstantInt::get(Type::getInt64Ty(VMContext), Lo),
ConstantInt::get(Type::getInt64Ty(VMContext), Hi)
};
return DISubrange(MDNode::get(VMContext, &Elts[0], 3));
}
/// CreateCompileUnit - Create a new descriptor for the specified compile
/// unit. Note that this does not unique compile units within the module.
DICompileUnit DIFactory::CreateCompileUnit(unsigned LangID,
const std::string &Filename,
const std::string &Directory,
const std::string &Producer,
Each input file is encoded as a separate compile unit in LLVM debugging information output. However, many target specific tool chains prefer to encode only one compile unit in an object file. In this situation, the LLVM code generator will include debugging information entities in the compile unit that is marked as main compile unit. The code generator accepts maximum one main compile unit per module. If a module does not contain any main compile unit then the code generator will emit multiple compile units in the output object file. [Part 1] Update DebugInfo APIs to accept optional boolean value while creating DICompileUnit to mark the unit as "main" unit. By defaults all units are considered non-main. Update SourceLevelDebugging.html to document "main" compile unit. Update DebugInfo APIs to not accept and encode separate source file/directory entries while creating various llvm.dbg.* entities. There was a recent, yet to be documented, change to include this additional information so no documentation changes are required here. Update DwarfDebug to handle "main" compile unit. If "main" compile unit is seen then all DIEs are inserted into "main" compile unit. All other compile units are used to find source location for llvm.dbg.* values. If there is not any "main" compile unit then create unique compile unit DIEs for each llvm.dbg.compile_unit. [Part 2] Create separate llvm.dbg.compile_unit for each input file. Mark compile unit create for main_input_filename as "main" compile unit. Use appropriate compile unit, based on source location information collected from the tree node, while creating llvm.dbg.* values using DebugInfo APIs. --- This is Part 1. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@63400 91177308-0d34-0410-b5e6-96231b3b80d8
2009-01-30 18:20:31 +00:00
bool isMain,
bool isOptimized,
const char *Flags,
unsigned RunTimeVer) {
Value *Elts[] = {
GetTagConstant(dwarf::DW_TAG_compile_unit),
llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)),
ConstantInt::get(Type::getInt32Ty(VMContext), LangID),
MDString::get(VMContext, Filename),
MDString::get(VMContext, Directory),
MDString::get(VMContext, Producer),
ConstantInt::get(Type::getInt1Ty(VMContext), isMain),
ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized),
MDString::get(VMContext, Flags),
ConstantInt::get(Type::getInt32Ty(VMContext), RunTimeVer)
};
return DICompileUnit(MDNode::get(VMContext, &Elts[0], 10));
}
/// CreateEnumerator - Create a single enumerator value.
DIEnumerator DIFactory::CreateEnumerator(const std::string &Name, uint64_t Val){
Value *Elts[] = {
GetTagConstant(dwarf::DW_TAG_enumerator),
MDString::get(VMContext, Name),
ConstantInt::get(Type::getInt64Ty(VMContext), Val)
};
return DIEnumerator(MDNode::get(VMContext, &Elts[0], 3));
}
/// CreateBasicType - Create a basic type like int, float, etc.
DIBasicType DIFactory::CreateBasicType(DIDescriptor Context,
const std::string &Name,
DICompileUnit CompileUnit,
unsigned LineNumber,
uint64_t SizeInBits,
uint64_t AlignInBits,
uint64_t OffsetInBits, unsigned Flags,
Each input file is encoded as a separate compile unit in LLVM debugging information output. However, many target specific tool chains prefer to encode only one compile unit in an object file. In this situation, the LLVM code generator will include debugging information entities in the compile unit that is marked as main compile unit. The code generator accepts maximum one main compile unit per module. If a module does not contain any main compile unit then the code generator will emit multiple compile units in the output object file. [Part 1] Update DebugInfo APIs to accept optional boolean value while creating DICompileUnit to mark the unit as "main" unit. By defaults all units are considered non-main. Update SourceLevelDebugging.html to document "main" compile unit. Update DebugInfo APIs to not accept and encode separate source file/directory entries while creating various llvm.dbg.* entities. There was a recent, yet to be documented, change to include this additional information so no documentation changes are required here. Update DwarfDebug to handle "main" compile unit. If "main" compile unit is seen then all DIEs are inserted into "main" compile unit. All other compile units are used to find source location for llvm.dbg.* values. If there is not any "main" compile unit then create unique compile unit DIEs for each llvm.dbg.compile_unit. [Part 2] Create separate llvm.dbg.compile_unit for each input file. Mark compile unit create for main_input_filename as "main" compile unit. Use appropriate compile unit, based on source location information collected from the tree node, while creating llvm.dbg.* values using DebugInfo APIs. --- This is Part 1. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@63400 91177308-0d34-0410-b5e6-96231b3b80d8
2009-01-30 18:20:31 +00:00
unsigned Encoding) {
Value *Elts[] = {
GetTagConstant(dwarf::DW_TAG_base_type),
Context.getNode(),
MDString::get(VMContext, Name),
CompileUnit.getNode(),
ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits),
ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits),
ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits),
ConstantInt::get(Type::getInt32Ty(VMContext), Flags),
ConstantInt::get(Type::getInt32Ty(VMContext), Encoding)
};
return DIBasicType(MDNode::get(VMContext, &Elts[0], 10));
}
/// CreateDerivedType - Create a derived type like const qualified type,
/// pointer, typedef, etc.
DIDerivedType DIFactory::CreateDerivedType(unsigned Tag,
DIDescriptor Context,
const std::string &Name,
DICompileUnit CompileUnit,
unsigned LineNumber,
uint64_t SizeInBits,
uint64_t AlignInBits,
uint64_t OffsetInBits,
unsigned Flags,
Each input file is encoded as a separate compile unit in LLVM debugging information output. However, many target specific tool chains prefer to encode only one compile unit in an object file. In this situation, the LLVM code generator will include debugging information entities in the compile unit that is marked as main compile unit. The code generator accepts maximum one main compile unit per module. If a module does not contain any main compile unit then the code generator will emit multiple compile units in the output object file. [Part 1] Update DebugInfo APIs to accept optional boolean value while creating DICompileUnit to mark the unit as "main" unit. By defaults all units are considered non-main. Update SourceLevelDebugging.html to document "main" compile unit. Update DebugInfo APIs to not accept and encode separate source file/directory entries while creating various llvm.dbg.* entities. There was a recent, yet to be documented, change to include this additional information so no documentation changes are required here. Update DwarfDebug to handle "main" compile unit. If "main" compile unit is seen then all DIEs are inserted into "main" compile unit. All other compile units are used to find source location for llvm.dbg.* values. If there is not any "main" compile unit then create unique compile unit DIEs for each llvm.dbg.compile_unit. [Part 2] Create separate llvm.dbg.compile_unit for each input file. Mark compile unit create for main_input_filename as "main" compile unit. Use appropriate compile unit, based on source location information collected from the tree node, while creating llvm.dbg.* values using DebugInfo APIs. --- This is Part 1. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@63400 91177308-0d34-0410-b5e6-96231b3b80d8
2009-01-30 18:20:31 +00:00
DIType DerivedFrom) {
Value *Elts[] = {
GetTagConstant(Tag),
Context.getNode(),
MDString::get(VMContext, Name),
CompileUnit.getNode(),
ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits),
ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits),
ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits),
ConstantInt::get(Type::getInt32Ty(VMContext), Flags),
DerivedFrom.getNode(),
};
return DIDerivedType(MDNode::get(VMContext, &Elts[0], 10));
}
/// CreateCompositeType - Create a composite type like array, struct, etc.
DICompositeType DIFactory::CreateCompositeType(unsigned Tag,
DIDescriptor Context,
const std::string &Name,
DICompileUnit CompileUnit,
unsigned LineNumber,
uint64_t SizeInBits,
uint64_t AlignInBits,
uint64_t OffsetInBits,
unsigned Flags,
DIType DerivedFrom,
DIArray Elements,
unsigned RuntimeLang) {
Value *Elts[] = {
GetTagConstant(Tag),
Context.getNode(),
MDString::get(VMContext, Name),
CompileUnit.getNode(),
ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits),
ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits),
ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits),
ConstantInt::get(Type::getInt32Ty(VMContext), Flags),
DerivedFrom.getNode(),
Elements.getNode(),
ConstantInt::get(Type::getInt32Ty(VMContext), RuntimeLang)
};
return DICompositeType(MDNode::get(VMContext, &Elts[0], 12));
}
/// CreateSubprogram - Create a new descriptor for the specified subprogram.
/// See comments in DISubprogram for descriptions of these fields. This
/// method does not unique the generated descriptors.
DISubprogram DIFactory::CreateSubprogram(DIDescriptor Context,
const std::string &Name,
const std::string &DisplayName,
const std::string &LinkageName,
DICompileUnit CompileUnit,
unsigned LineNo, DIType Type,
bool isLocalToUnit,
Each input file is encoded as a separate compile unit in LLVM debugging information output. However, many target specific tool chains prefer to encode only one compile unit in an object file. In this situation, the LLVM code generator will include debugging information entities in the compile unit that is marked as main compile unit. The code generator accepts maximum one main compile unit per module. If a module does not contain any main compile unit then the code generator will emit multiple compile units in the output object file. [Part 1] Update DebugInfo APIs to accept optional boolean value while creating DICompileUnit to mark the unit as "main" unit. By defaults all units are considered non-main. Update SourceLevelDebugging.html to document "main" compile unit. Update DebugInfo APIs to not accept and encode separate source file/directory entries while creating various llvm.dbg.* entities. There was a recent, yet to be documented, change to include this additional information so no documentation changes are required here. Update DwarfDebug to handle "main" compile unit. If "main" compile unit is seen then all DIEs are inserted into "main" compile unit. All other compile units are used to find source location for llvm.dbg.* values. If there is not any "main" compile unit then create unique compile unit DIEs for each llvm.dbg.compile_unit. [Part 2] Create separate llvm.dbg.compile_unit for each input file. Mark compile unit create for main_input_filename as "main" compile unit. Use appropriate compile unit, based on source location information collected from the tree node, while creating llvm.dbg.* values using DebugInfo APIs. --- This is Part 1. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@63400 91177308-0d34-0410-b5e6-96231b3b80d8
2009-01-30 18:20:31 +00:00
bool isDefinition) {
Value *Elts[] = {
GetTagConstant(dwarf::DW_TAG_subprogram),
llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)),
Context.getNode(),
MDString::get(VMContext, Name),
MDString::get(VMContext, DisplayName),
MDString::get(VMContext, LinkageName),
CompileUnit.getNode(),
ConstantInt::get(Type::getInt32Ty(VMContext), LineNo),
Type.getNode(),
ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit),
ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition)
};
return DISubprogram(MDNode::get(VMContext, &Elts[0], 11));
}
/// CreateGlobalVariable - Create a new descriptor for the specified global.
DIGlobalVariable
DIFactory::CreateGlobalVariable(DIDescriptor Context, const std::string &Name,
const std::string &DisplayName,
const std::string &LinkageName,
DICompileUnit CompileUnit,
unsigned LineNo, DIType Type,bool isLocalToUnit,
Each input file is encoded as a separate compile unit in LLVM debugging information output. However, many target specific tool chains prefer to encode only one compile unit in an object file. In this situation, the LLVM code generator will include debugging information entities in the compile unit that is marked as main compile unit. The code generator accepts maximum one main compile unit per module. If a module does not contain any main compile unit then the code generator will emit multiple compile units in the output object file. [Part 1] Update DebugInfo APIs to accept optional boolean value while creating DICompileUnit to mark the unit as "main" unit. By defaults all units are considered non-main. Update SourceLevelDebugging.html to document "main" compile unit. Update DebugInfo APIs to not accept and encode separate source file/directory entries while creating various llvm.dbg.* entities. There was a recent, yet to be documented, change to include this additional information so no documentation changes are required here. Update DwarfDebug to handle "main" compile unit. If "main" compile unit is seen then all DIEs are inserted into "main" compile unit. All other compile units are used to find source location for llvm.dbg.* values. If there is not any "main" compile unit then create unique compile unit DIEs for each llvm.dbg.compile_unit. [Part 2] Create separate llvm.dbg.compile_unit for each input file. Mark compile unit create for main_input_filename as "main" compile unit. Use appropriate compile unit, based on source location information collected from the tree node, while creating llvm.dbg.* values using DebugInfo APIs. --- This is Part 1. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@63400 91177308-0d34-0410-b5e6-96231b3b80d8
2009-01-30 18:20:31 +00:00
bool isDefinition, llvm::GlobalVariable *Val) {
Value *Elts[] = {
GetTagConstant(dwarf::DW_TAG_variable),
llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)),
Context.getNode(),
MDString::get(VMContext, Name),
MDString::get(VMContext, DisplayName),
MDString::get(VMContext, LinkageName),
CompileUnit.getNode(),
ConstantInt::get(Type::getInt32Ty(VMContext), LineNo),
Type.getNode(),
ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit),
ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition),
Val
};
Value *const *Vs = &Elts[0];
MDNode *Node = MDNode::get(VMContext,Vs, 12);
// Create a named metadata so that we do not lose this mdnode.
NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.gv");
NMD->addElement(Node);
return DIGlobalVariable(Node);
}
/// CreateVariable - Create a new descriptor for the specified variable.
DIVariable DIFactory::CreateVariable(unsigned Tag, DIDescriptor Context,
const std::string &Name,
DICompileUnit CompileUnit, unsigned LineNo,
Each input file is encoded as a separate compile unit in LLVM debugging information output. However, many target specific tool chains prefer to encode only one compile unit in an object file. In this situation, the LLVM code generator will include debugging information entities in the compile unit that is marked as main compile unit. The code generator accepts maximum one main compile unit per module. If a module does not contain any main compile unit then the code generator will emit multiple compile units in the output object file. [Part 1] Update DebugInfo APIs to accept optional boolean value while creating DICompileUnit to mark the unit as "main" unit. By defaults all units are considered non-main. Update SourceLevelDebugging.html to document "main" compile unit. Update DebugInfo APIs to not accept and encode separate source file/directory entries while creating various llvm.dbg.* entities. There was a recent, yet to be documented, change to include this additional information so no documentation changes are required here. Update DwarfDebug to handle "main" compile unit. If "main" compile unit is seen then all DIEs are inserted into "main" compile unit. All other compile units are used to find source location for llvm.dbg.* values. If there is not any "main" compile unit then create unique compile unit DIEs for each llvm.dbg.compile_unit. [Part 2] Create separate llvm.dbg.compile_unit for each input file. Mark compile unit create for main_input_filename as "main" compile unit. Use appropriate compile unit, based on source location information collected from the tree node, while creating llvm.dbg.* values using DebugInfo APIs. --- This is Part 1. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@63400 91177308-0d34-0410-b5e6-96231b3b80d8
2009-01-30 18:20:31 +00:00
DIType Type) {
Value *Elts[] = {
GetTagConstant(Tag),
Context.getNode(),
MDString::get(VMContext, Name),
CompileUnit.getNode(),
ConstantInt::get(Type::getInt32Ty(VMContext), LineNo),
Type.getNode(),
};
return DIVariable(MDNode::get(VMContext, &Elts[0], 6));
}
/// CreateBlock - This creates a descriptor for a lexical block with the
/// specified parent VMContext.
DILexicalBlock DIFactory::CreateLexicalBlock(DIDescriptor Context) {
Value *Elts[] = {
GetTagConstant(dwarf::DW_TAG_lexical_block),
Context.getNode()
};
return DILexicalBlock(MDNode::get(VMContext, &Elts[0], 2));
}
/// CreateLocation - Creates a debug info location.
DILocation DIFactory::CreateLocation(unsigned LineNo, unsigned ColumnNo,
DIScope S, DILocation OrigLoc) {
Value *Elts[] = {
ConstantInt::get(Type::getInt32Ty(VMContext), LineNo),
ConstantInt::get(Type::getInt32Ty(VMContext), ColumnNo),
S.getNode(),
OrigLoc.getNode(),
};
return DILocation(MDNode::get(VMContext, &Elts[0], 4));
}
//===----------------------------------------------------------------------===//
// DIFactory: Routines for inserting code into a function
//===----------------------------------------------------------------------===//
/// InsertStopPoint - Create a new llvm.dbg.stoppoint intrinsic invocation,
/// inserting it at the end of the specified basic block.
void DIFactory::InsertStopPoint(DICompileUnit CU, unsigned LineNo,
unsigned ColNo, BasicBlock *BB) {
// Lazily construct llvm.dbg.stoppoint function.
if (!StopPointFn)
StopPointFn = llvm::Intrinsic::getDeclaration(&M,
llvm::Intrinsic::dbg_stoppoint);
// Invoke llvm.dbg.stoppoint
Value *Args[] = {
ConstantInt::get(llvm::Type::getInt32Ty(VMContext), LineNo),
ConstantInt::get(llvm::Type::getInt32Ty(VMContext), ColNo),
CU.getNode()
};
CallInst::Create(StopPointFn, Args, Args+3, "", BB);
}
/// InsertSubprogramStart - Create a new llvm.dbg.func.start intrinsic to
/// mark the start of the specified subprogram.
void DIFactory::InsertSubprogramStart(DISubprogram SP, BasicBlock *BB) {
// Lazily construct llvm.dbg.func.start.
if (!FuncStartFn)
FuncStartFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_func_start);
// Call llvm.dbg.func.start which also implicitly sets a stoppoint.
CallInst::Create(FuncStartFn, SP.getNode(), "", BB);
}
/// InsertRegionStart - Insert a new llvm.dbg.region.start intrinsic call to
/// mark the start of a region for the specified scoping descriptor.
void DIFactory::InsertRegionStart(DIDescriptor D, BasicBlock *BB) {
// Lazily construct llvm.dbg.region.start function.
if (!RegionStartFn)
RegionStartFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_region_start);
// Call llvm.dbg.func.start.
CallInst::Create(RegionStartFn, D.getNode(), "", BB);
}
/// InsertRegionEnd - Insert a new llvm.dbg.region.end intrinsic call to
/// mark the end of a region for the specified scoping descriptor.
void DIFactory::InsertRegionEnd(DIDescriptor D, BasicBlock *BB) {
// Lazily construct llvm.dbg.region.end function.
if (!RegionEndFn)
RegionEndFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_region_end);
// Call llvm.dbg.region.end.
CallInst::Create(RegionEndFn, D.getNode(), "", BB);
}
/// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call.
void DIFactory::InsertDeclare(Value *Storage, DIVariable D, BasicBlock *BB) {
// Cast the storage to a {}* for the call to llvm.dbg.declare.
Storage = new BitCastInst(Storage, EmptyStructPtr, "", BB);
if (!DeclareFn)
DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare);
Value *Args[] = { Storage, D.getNode() };
CallInst::Create(DeclareFn, Args, Args+2, "", BB);
}
//===----------------------------------------------------------------------===//
// DebugInfoFinder implementations.
//===----------------------------------------------------------------------===//
/// processModule - Process entire module and collect debug info.
void DebugInfoFinder::processModule(Module &M) {
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
for (Function::iterator FI = (*I).begin(), FE = (*I).end(); FI != FE; ++FI)
for (BasicBlock::iterator BI = (*FI).begin(), BE = (*FI).end(); BI != BE;
++BI) {
if (DbgStopPointInst *SPI = dyn_cast<DbgStopPointInst>(BI))
processStopPoint(SPI);
else if (DbgFuncStartInst *FSI = dyn_cast<DbgFuncStartInst>(BI))
processFuncStart(FSI);
else if (DbgRegionStartInst *DRS = dyn_cast<DbgRegionStartInst>(BI))
processRegionStart(DRS);
else if (DbgRegionEndInst *DRE = dyn_cast<DbgRegionEndInst>(BI))
processRegionEnd(DRE);
else if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(BI))
processDeclare(DDI);
}
NamedMDNode *NMD = M.getNamedMetadata("llvm.dbg.gv");
if (!NMD)
return;
for (unsigned i = 0, e = NMD->getNumElements(); i != e; ++i) {
DIGlobalVariable DIG(cast<MDNode>(NMD->getElement(i)));
if (addGlobalVariable(DIG)) {
addCompileUnit(DIG.getCompileUnit());
processType(DIG.getType());
}
}
}
/// processType - Process DIType.
void DebugInfoFinder::processType(DIType DT) {
if (!addType(DT))
return;
addCompileUnit(DT.getCompileUnit());
if (DT.isCompositeType()) {
DICompositeType DCT(DT.getNode());
processType(DCT.getTypeDerivedFrom());
DIArray DA = DCT.getTypeArray();
if (!DA.isNull())
for (unsigned i = 0, e = DA.getNumElements(); i != e; ++i) {
DIDescriptor D = DA.getElement(i);
DIType TypeE = DIType(D.getNode());
if (!TypeE.isNull())
processType(TypeE);
else
processSubprogram(DISubprogram(D.getNode()));
}
} else if (DT.isDerivedType()) {
DIDerivedType DDT(DT.getNode());
if (!DDT.isNull())
processType(DDT.getTypeDerivedFrom());
}
}
/// processSubprogram - Process DISubprogram.
void DebugInfoFinder::processSubprogram(DISubprogram SP) {
if (SP.isNull())
return;
if (!addSubprogram(SP))
return;
addCompileUnit(SP.getCompileUnit());
processType(SP.getType());
}
/// processStopPoint - Process DbgStopPointInst.
void DebugInfoFinder::processStopPoint(DbgStopPointInst *SPI) {
MDNode *Context = dyn_cast<MDNode>(SPI->getContext());
addCompileUnit(DICompileUnit(Context));
}
/// processFuncStart - Process DbgFuncStartInst.
void DebugInfoFinder::processFuncStart(DbgFuncStartInst *FSI) {
MDNode *SP = dyn_cast<MDNode>(FSI->getSubprogram());
processSubprogram(DISubprogram(SP));
}
/// processRegionStart - Process DbgRegionStart.
void DebugInfoFinder::processRegionStart(DbgRegionStartInst *DRS) {
MDNode *SP = dyn_cast<MDNode>(DRS->getContext());
processSubprogram(DISubprogram(SP));
}
/// processRegionEnd - Process DbgRegionEnd.
void DebugInfoFinder::processRegionEnd(DbgRegionEndInst *DRE) {
MDNode *SP = dyn_cast<MDNode>(DRE->getContext());
processSubprogram(DISubprogram(SP));
}
/// processDeclare - Process DbgDeclareInst.
void DebugInfoFinder::processDeclare(DbgDeclareInst *DDI) {
DIVariable DV(cast<MDNode>(DDI->getVariable()));
if (DV.isNull())
return;
if (!NodesSeen.insert(DV.getNode()))
return;
addCompileUnit(DV.getCompileUnit());
processType(DV.getType());
}
/// addType - Add type into Tys.
bool DebugInfoFinder::addType(DIType DT) {
if (DT.isNull())
return false;
if (!NodesSeen.insert(DT.getNode()))
return false;
TYs.push_back(DT.getNode());
return true;
}
/// addCompileUnit - Add compile unit into CUs.
bool DebugInfoFinder::addCompileUnit(DICompileUnit CU) {
if (CU.isNull())
return false;
if (!NodesSeen.insert(CU.getNode()))
return false;
CUs.push_back(CU.getNode());
return true;
}
/// addGlobalVariable - Add global variable into GVs.
bool DebugInfoFinder::addGlobalVariable(DIGlobalVariable DIG) {
if (DIG.isNull())
return false;
if (!NodesSeen.insert(DIG.getNode()))
return false;
GVs.push_back(DIG.getNode());
return true;
}
// addSubprogram - Add subprgoram into SPs.
bool DebugInfoFinder::addSubprogram(DISubprogram SP) {
if (SP.isNull())
return false;
if (!NodesSeen.insert(SP.getNode()))
return false;
SPs.push_back(SP.getNode());
return true;
}
namespace llvm {
/// findStopPoint - Find the stoppoint coressponding to this instruction, that
/// is the stoppoint that dominates this instruction.
const DbgStopPointInst *findStopPoint(const Instruction *Inst) {
if (const DbgStopPointInst *DSI = dyn_cast<DbgStopPointInst>(Inst))
return DSI;
const BasicBlock *BB = Inst->getParent();
BasicBlock::const_iterator I = Inst, B;
while (BB) {
B = BB->begin();
// A BB consisting only of a terminator can't have a stoppoint.
while (I != B) {
--I;
if (const DbgStopPointInst *DSI = dyn_cast<DbgStopPointInst>(I))
return DSI;
}
// This BB didn't have a stoppoint: if there is only one predecessor, look
// for a stoppoint there. We could use getIDom(), but that would require
// dominator info.
BB = I->getParent()->getUniquePredecessor();
if (BB)
I = BB->getTerminator();
}
return 0;
}
/// findBBStopPoint - Find the stoppoint corresponding to first real
/// (non-debug intrinsic) instruction in this Basic Block, and return the
/// stoppoint for it.
const DbgStopPointInst *findBBStopPoint(const BasicBlock *BB) {
for(BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; ++I)
if (const DbgStopPointInst *DSI = dyn_cast<DbgStopPointInst>(I))
return DSI;
// Fallback to looking for stoppoint of unique predecessor. Useful if this
// BB contains no stoppoints, but unique predecessor does.
BB = BB->getUniquePredecessor();
if (BB)
return findStopPoint(BB->getTerminator());
return 0;
}
Value *findDbgGlobalDeclare(GlobalVariable *V) {
const Module *M = V->getParent();
NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.gv");
if (!NMD)
return 0;
for (unsigned i = 0, e = NMD->getNumElements(); i != e; ++i) {
DIGlobalVariable DIG(cast_or_null<MDNode>(NMD->getElement(i)));
if (DIG.isNull())
continue;
if (DIG.getGlobal() == V)
return DIG.getNode();
}
return 0;
}
/// Finds the llvm.dbg.declare intrinsic corresponding to this value if any.
/// It looks through pointer casts too.
const DbgDeclareInst *findDbgDeclare(const Value *V, bool stripCasts) {
if (stripCasts) {
V = V->stripPointerCasts();
// Look for the bitcast.
for (Value::use_const_iterator I = V->use_begin(), E =V->use_end();
I != E; ++I)
if (isa<BitCastInst>(I))
return findDbgDeclare(*I, false);
return 0;
}
// Find llvm.dbg.declare among uses of the instruction.
for (Value::use_const_iterator I = V->use_begin(), E =V->use_end();
I != E; ++I)
if (const DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(I))
return DDI;
return 0;
}
bool getLocationInfo(const Value *V, std::string &DisplayName,
std::string &Type, unsigned &LineNo, std::string &File,
std::string &Dir) {
DICompileUnit Unit;
DIType TypeD;
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(const_cast<Value*>(V))) {
Value *DIGV = findDbgGlobalDeclare(GV);
if (!DIGV) return false;
DIGlobalVariable Var(cast<MDNode>(DIGV));
Var.getDisplayName(DisplayName);
LineNo = Var.getLineNumber();
Unit = Var.getCompileUnit();
TypeD = Var.getType();
} else {
const DbgDeclareInst *DDI = findDbgDeclare(V);
if (!DDI) return false;
DIVariable Var(cast<MDNode>(DDI->getVariable()));
Var.getName(DisplayName);
LineNo = Var.getLineNumber();
Unit = Var.getCompileUnit();
TypeD = Var.getType();
}
TypeD.getName(Type);
Unit.getFilename(File);
Unit.getDirectory(Dir);
return true;
}
/// isValidDebugInfoIntrinsic - Return true if SPI is a valid debug
/// info intrinsic.
bool isValidDebugInfoIntrinsic(DbgStopPointInst &SPI,
CodeGenOpt::Level OptLev) {
return DIDescriptor::ValidDebugInfo(SPI.getContext(), OptLev);
}
/// isValidDebugInfoIntrinsic - Return true if FSI is a valid debug
/// info intrinsic.
bool isValidDebugInfoIntrinsic(DbgFuncStartInst &FSI,
CodeGenOpt::Level OptLev) {
return DIDescriptor::ValidDebugInfo(FSI.getSubprogram(), OptLev);
}
/// isValidDebugInfoIntrinsic - Return true if RSI is a valid debug
/// info intrinsic.
bool isValidDebugInfoIntrinsic(DbgRegionStartInst &RSI,
CodeGenOpt::Level OptLev) {
return DIDescriptor::ValidDebugInfo(RSI.getContext(), OptLev);
}
/// isValidDebugInfoIntrinsic - Return true if REI is a valid debug
/// info intrinsic.
bool isValidDebugInfoIntrinsic(DbgRegionEndInst &REI,
CodeGenOpt::Level OptLev) {
return DIDescriptor::ValidDebugInfo(REI.getContext(), OptLev);
}
/// isValidDebugInfoIntrinsic - Return true if DI is a valid debug
/// info intrinsic.
bool isValidDebugInfoIntrinsic(DbgDeclareInst &DI,
CodeGenOpt::Level OptLev) {
return DIDescriptor::ValidDebugInfo(DI.getVariable(), OptLev);
}
/// ExtractDebugLocation - Extract debug location information
/// from llvm.dbg.stoppoint intrinsic.
DebugLoc ExtractDebugLocation(DbgStopPointInst &SPI,
DebugLocTracker &DebugLocInfo) {
DebugLoc DL;
Value *Context = SPI.getContext();
// If this location is already tracked then use it.
DebugLocTuple Tuple(cast<MDNode>(Context), SPI.getLine(),
SPI.getColumn());
DenseMap<DebugLocTuple, unsigned>::iterator II
= DebugLocInfo.DebugIdMap.find(Tuple);
if (II != DebugLocInfo.DebugIdMap.end())
return DebugLoc::get(II->second);
// Add a new location entry.
unsigned Id = DebugLocInfo.DebugLocations.size();
DebugLocInfo.DebugLocations.push_back(Tuple);
DebugLocInfo.DebugIdMap[Tuple] = Id;
return DebugLoc::get(Id);
}
/// ExtractDebugLocation - Extract debug location information
/// from DILocation.
DebugLoc ExtractDebugLocation(DILocation &Loc,
DebugLocTracker &DebugLocInfo) {
DebugLoc DL;
MDNode *Context = Loc.getScope().getNode();
// If this location is already tracked then use it.
DebugLocTuple Tuple(Context, Loc.getLineNumber(),
Loc.getColumnNumber());
DenseMap<DebugLocTuple, unsigned>::iterator II
= DebugLocInfo.DebugIdMap.find(Tuple);
if (II != DebugLocInfo.DebugIdMap.end())
return DebugLoc::get(II->second);
// Add a new location entry.
unsigned Id = DebugLocInfo.DebugLocations.size();
DebugLocInfo.DebugLocations.push_back(Tuple);
DebugLocInfo.DebugIdMap[Tuple] = Id;
return DebugLoc::get(Id);
}
/// ExtractDebugLocation - Extract debug location information
/// from llvm.dbg.func_start intrinsic.
DebugLoc ExtractDebugLocation(DbgFuncStartInst &FSI,
DebugLocTracker &DebugLocInfo) {
DebugLoc DL;
Value *SP = FSI.getSubprogram();
DISubprogram Subprogram(cast<MDNode>(SP));
unsigned Line = Subprogram.getLineNumber();
DICompileUnit CU(Subprogram.getCompileUnit());
// If this location is already tracked then use it.
DebugLocTuple Tuple(CU.getNode(), Line, /* Column */ 0);
DenseMap<DebugLocTuple, unsigned>::iterator II
= DebugLocInfo.DebugIdMap.find(Tuple);
if (II != DebugLocInfo.DebugIdMap.end())
return DebugLoc::get(II->second);
// Add a new location entry.
unsigned Id = DebugLocInfo.DebugLocations.size();
DebugLocInfo.DebugLocations.push_back(Tuple);
DebugLocInfo.DebugIdMap[Tuple] = Id;
return DebugLoc::get(Id);
}
/// isInlinedFnStart - Return true if FSI is starting an inlined function.
bool isInlinedFnStart(DbgFuncStartInst &FSI, const Function *CurrentFn) {
DISubprogram Subprogram(cast<MDNode>(FSI.getSubprogram()));
if (Subprogram.describes(CurrentFn))
return false;
return true;
}
/// isInlinedFnEnd - Return true if REI is ending an inlined function.
bool isInlinedFnEnd(DbgRegionEndInst &REI, const Function *CurrentFn) {
DISubprogram Subprogram(cast<MDNode>(REI.getContext()));
if (Subprogram.isNull() || Subprogram.describes(CurrentFn))
return false;
return true;
}
}