Newer
Older
return true;
default: break;
}
return false;
}
/// ApplyToFields - Target the visitor to the fields of the VariableDesc.
///
void VariableDesc::ApplyToFields(DIVisitor *Visitor) {
DebugInfoDesc::ApplyToFields(Visitor);
Visitor->Apply(Context);
Visitor->Apply(Name);
Visitor->Apply(Line);
}
/// getDescString - Return a string used to compose global names and labels.
///
const char *VariableDesc::getDescString() const {
return "llvm.dbg.variable";
}
/// getTypeString - Return a string used to label this descriptor's type.
///
const char *VariableDesc::getTypeString() const {
return "llvm.dbg.variable.type";
}
#ifndef NDEBUG
void VariableDesc::dump() {
cerr << getDescString() << " "
<< "Version(" << getVersion() << "), "
<< "Tag(" << getTag() << "), "
<< "Context(" << Context << "), "
<< "Name(\"" << Name << "\"), "
<< "File(" << File << "), "
<< "Line(" << Line << "), "
<< "TyDesc(" << TyDesc << ")\n";
}
#endif
//===----------------------------------------------------------------------===//
Jim Laskey
committed
GlobalDesc::GlobalDesc(unsigned T)
: AnchoredDesc(T)
, Context(0)
, Name("")
, FullName("")
, LinkageName("")
Jim Laskey
committed
, TyDesc(NULL)
, IsStatic(false)
, IsDefinition(false)
{}
/// ApplyToFields - Target the visitor to the fields of the global.
Jim Laskey
committed
void GlobalDesc::ApplyToFields(DIVisitor *Visitor) {
AnchoredDesc::ApplyToFields(Visitor);
Visitor->Apply(Context);
Visitor->Apply(Name);
Visitor->Apply(FullName);
Visitor->Apply(LinkageName);
Visitor->Apply(IsStatic);
Visitor->Apply(IsDefinition);
Jim Laskey
committed
}
//===----------------------------------------------------------------------===//
GlobalVariableDesc::GlobalVariableDesc()
: GlobalDesc(DW_TAG_variable)
Jim Laskey
committed
, Global(NULL)
{}
// Implement isa/cast/dyncast.
bool GlobalVariableDesc::classof(const DebugInfoDesc *D) {
return D->getTag() == DW_TAG_variable;
}
Jim Laskey
committed
/// ApplyToFields - Target the visitor to the fields of the GlobalVariableDesc.
///
void GlobalVariableDesc::ApplyToFields(DIVisitor *Visitor) {
GlobalDesc::ApplyToFields(Visitor);
}
Jim Laskey
committed
/// getDescString - Return a string used to compose global names and labels.
///
Jim Laskey
committed
const char *GlobalVariableDesc::getDescString() const {
return "llvm.dbg.global_variable";
}
/// getTypeString - Return a string used to label this descriptors type.
///
const char *GlobalVariableDesc::getTypeString() const {
return "llvm.dbg.global_variable.type";
}
/// getAnchorString - Return a string used to label this descriptor's anchor.
///
const char *GlobalVariableDesc::AnchorString = "llvm.dbg.global_variables";
Jim Laskey
committed
const char *GlobalVariableDesc::getAnchorString() const {
}
#ifndef NDEBUG
void GlobalVariableDesc::dump() {
cerr << getDescString() << " "
<< "Version(" << getVersion() << "), "
<< "Tag(" << getTag() << "), "
<< "Anchor(" << getAnchor() << "), "
<< "Name(\"" << getName() << "\"), "
<< "FullName(\"" << getFullName() << "\"), "
<< "LinkageName(\"" << getLinkageName() << "\"), "
<< "File(" << getFile() << "),"
<< "Line(" << getLine() << "),"
<< "Type(" << getType() << "), "
<< "IsStatic(" << (isStatic() ? "true" : "false") << "), "
<< "IsDefinition(" << (isDefinition() ? "true" : "false") << "), "
<< "Global(" << Global << ")\n";
}
#endif
//===----------------------------------------------------------------------===//
Jim Laskey
committed
SubprogramDesc::SubprogramDesc()
: GlobalDesc(DW_TAG_subprogram)
Jim Laskey
committed
{}
// Implement isa/cast/dyncast.
bool SubprogramDesc::classof(const DebugInfoDesc *D) {
return D->getTag() == DW_TAG_subprogram;
}
/// ApplyToFields - Target the visitor to the fields of the
/// SubprogramDesc.
void SubprogramDesc::ApplyToFields(DIVisitor *Visitor) {
Jim Laskey
committed
GlobalDesc::ApplyToFields(Visitor);
}
/// getDescString - Return a string used to compose global names and labels.
///
const char *SubprogramDesc::getDescString() const {
return "llvm.dbg.subprogram";
}
/// getTypeString - Return a string used to label this descriptors type.
///
const char *SubprogramDesc::getTypeString() const {
return "llvm.dbg.subprogram.type";
Jim Laskey
committed
/// getAnchorString - Return a string used to label this descriptor's anchor.
///
const char *SubprogramDesc::AnchorString = "llvm.dbg.subprograms";
Jim Laskey
committed
const char *SubprogramDesc::getAnchorString() const {
}
#ifndef NDEBUG
void SubprogramDesc::dump() {
cerr << getDescString() << " "
<< "Version(" << getVersion() << "), "
<< "Tag(" << getTag() << "), "
<< "Anchor(" << getAnchor() << "), "
<< "Name(\"" << getName() << "\"), "
<< "FullName(\"" << getFullName() << "\"), "
<< "LinkageName(\"" << getLinkageName() << "\"), "
<< "File(" << getFile() << "),"
<< "Line(" << getLine() << "),"
<< "Type(" << getType() << "), "
<< "IsStatic(" << (isStatic() ? "true" : "false") << "), "
<< "IsDefinition(" << (isDefinition() ? "true" : "false") << ")\n";
}
#endif
//===----------------------------------------------------------------------===//
BlockDesc::BlockDesc()
: DebugInfoDesc(DW_TAG_lexical_block)
, Context(NULL)
{}
// Implement isa/cast/dyncast.
bool BlockDesc::classof(const DebugInfoDesc *D) {
return D->getTag() == DW_TAG_lexical_block;
}
/// ApplyToFields - Target the visitor to the fields of the BlockDesc.
///
void BlockDesc::ApplyToFields(DIVisitor *Visitor) {
DebugInfoDesc::ApplyToFields(Visitor);
Visitor->Apply(Context);
}
/// getDescString - Return a string used to compose global names and labels.
///
const char *BlockDesc::getDescString() const {
return "llvm.dbg.block";
}
/// getTypeString - Return a string used to label this descriptors type.
///
const char *BlockDesc::getTypeString() const {
return "llvm.dbg.block.type";
}
#ifndef NDEBUG
void BlockDesc::dump() {
cerr << getDescString() << " "
<< "Version(" << getVersion() << "), "
<< "Tag(" << getTag() << "),"
<< "Context(" << Context << ")\n";
}
#endif
//===----------------------------------------------------------------------===//
DebugInfoDesc *DIDeserializer::Deserialize(Value *V) {
Jim Laskey
committed
return Deserialize(getGlobalVariable(V));
}
DebugInfoDesc *DIDeserializer::Deserialize(GlobalVariable *GV) {
Jim Laskey
committed
// Handle NULL.
if (!GV) return NULL;
// Check to see if it has been already deserialized.
DebugInfoDesc *&Slot = GlobalDescs[GV];
if (Slot) return Slot;
// Get the Tag from the global.
unsigned Tag = DebugInfoDesc::TagFromGlobal(GV);
// Create an empty instance of the correct sort.
Slot = DebugInfoDesc::DescFactory(Tag);
// If not a user defined descriptor.
if (Slot) {
// Deserialize the fields.
DIDeserializeVisitor DRAM(*this, GV);
DRAM.ApplyToFields(Slot);
}
return Slot;
}
//===----------------------------------------------------------------------===//
/// getStrPtrType - Return a "sbyte *" type.
///
const PointerType *DISerializer::getStrPtrType() {
// If not already defined.
if (!StrPtrTy) {
// Construct the pointer to signed bytes.
}
return StrPtrTy;
}
/// getEmptyStructPtrType - Return a "{ }*" type.
///
const PointerType *DISerializer::getEmptyStructPtrType() {
// If not already defined.
if (!EmptyStructPtrTy) {
// Construct the empty structure type.
const StructType *EmptyStructTy =
StructType::get(std::vector<const Type*>());
// Construct the pointer to empty structure type.
EmptyStructPtrTy = PointerType::get(EmptyStructTy);
}
return EmptyStructPtrTy;
}
/// getTagType - Return the type describing the specified descriptor (via tag.)
///
const StructType *DISerializer::getTagType(DebugInfoDesc *DD) {
// Attempt to get the previously defined type.
StructType *&Ty = TagTypes[DD->getTag()];
// If not already defined.
if (!Ty) {
// Set up fields vector.
std::vector<const Type*> Fields;
Jim Laskey
committed
// Get types of fields.
GTAM.ApplyToFields(DD);
// Construct structured type.
Ty = StructType::get(Fields);
// Register type name with module.
Jim Laskey
committed
M->addTypeName(DD->getTypeString(), Ty);
}
return Ty;
}
/// getString - Construct the string as constant string global.
///
Jim Laskey
committed
Constant *DISerializer::getString(const std::string &String) {
// Check string cache for previous edition.
Jim Laskey
committed
Constant *&Slot = StringCache[String];
// Return Constant if previously defined.
if (Slot) return Slot;
// If empty string then use a sbyte* null instead.
if (String.empty()) {
Slot = ConstantPointerNull::get(getStrPtrType());
} else {
// Construct string as an llvm constant.
Constant *ConstStr = ConstantArray::get(String);
// Otherwise create and return a new string global.
GlobalVariable *StrGV = new GlobalVariable(ConstStr->getType(), true,
GlobalVariable::InternalLinkage,
ConstStr, "str", M);
StrGV->setSection("llvm.metadata");
// Convert to generic string pointer.
Slot = ConstantExpr::getBitCast(StrGV, getStrPtrType());
Jim Laskey
committed
return Slot;
}
/// Serialize - Recursively cast the specified descriptor into a GlobalVariable
/// so that it can be serialized to a .bc or .ll file.
GlobalVariable *DISerializer::Serialize(DebugInfoDesc *DD) {
// Check if the DebugInfoDesc is already in the map.
GlobalVariable *&Slot = DescGlobals[DD];
// See if DebugInfoDesc exists, if so return prior GlobalVariable.
if (Slot) return Slot;
// Get the type associated with the Tag.
const StructType *Ty = getTagType(DD);
// Create the GlobalVariable early to prevent infinite recursion.
Jim Laskey
committed
GlobalVariable *GV = new GlobalVariable(Ty, true, DD->getLinkage(),
NULL, DD->getDescString(), M);
GV->setSection("llvm.metadata");
// Insert new GlobalVariable in DescGlobals map.
Slot = GV;
// Set up elements vector
std::vector<Constant*> Elements;
Jim Laskey
committed
// Add fields.
SRAM.ApplyToFields(DD);
// Set the globals initializer.
GV->setInitializer(ConstantStruct::get(Ty, Elements));
return GV;
}
//===----------------------------------------------------------------------===//
/// Verify - Return true if the GlobalVariable appears to be a valid
/// serialization of a DebugInfoDesc.
Jim Laskey
committed
bool DIVerifier::Verify(Value *V) {
return !V || Verify(getGlobalVariable(V));
Jim Laskey
committed
}
bool DIVerifier::Verify(GlobalVariable *GV) {
// NULLs are valid.
if (!GV) return true;
// Check prior validity.
unsigned &ValiditySlot = Validity[GV];
// If visited before then use old state.
if (ValiditySlot) return ValiditySlot == Valid;
// Assume validity for the time being (recursion.)
ValiditySlot = Valid;
// Make sure the global is internal or link once (anchor.)
if (GV->getLinkage() != GlobalValue::InternalLinkage &&
GV->getLinkage() != GlobalValue::LinkOnceLinkage) {
ValiditySlot = Invalid;
return false;
}
unsigned Tag = DebugInfoDesc::TagFromGlobal(GV);
// Check for user defined descriptors.
if (Tag == DW_TAG_invalid) {
ValiditySlot = Valid;
return true;
}
// Get the Version.
unsigned Version = DebugInfoDesc::VersionFromGlobal(GV);
// Check for version mismatch.
if (Version != LLVMDebugVersion) {
ValiditySlot = Invalid;
return false;
}
// Construct an empty DebugInfoDesc.
DebugInfoDesc *DD = DebugInfoDesc::DescFactory(Tag);
// Allow for user defined descriptors.
if (!DD) return true;
// Get the initializer constant.
ConstantStruct *CI = cast<ConstantStruct>(GV->getInitializer());
// Get the operand count.
unsigned N = CI->getNumOperands();
// Get the field count.
unsigned &CountSlot = Counts[Tag];
if (!CountSlot) {
// Check the operand count to the field count
CTAM.ApplyToFields(DD);
CountSlot = CTAM.getCount();
// Field count must be at most equal operand count.
if (CountSlot > N) {
ValiditySlot = Invalid;
return false;
}
// Check each field for valid type.
VRAM.ApplyToFields(DD);
// Release empty DebugInfoDesc.
delete DD;
// If fields are not valid.
if (!VRAM.isValid()) {
ValiditySlot = Invalid;
return false;
}
return true;
}
//===----------------------------------------------------------------------===//
DebugScope::~DebugScope() {
for (unsigned i = 0, N = Scopes.size(); i < N; ++i) delete Scopes[i];
for (unsigned j = 0, M = Variables.size(); j < M; ++j) delete Variables[j];
}
//===----------------------------------------------------------------------===//
MachineDebugInfo::MachineDebugInfo()
Jim Laskey
committed
: DR()
, VR()
, CompileUnits()
, Directories()
, SourceFiles()
, Lines()
Jim Laskey
committed
, LabelIDList()
, ScopeMap()
, RootScope(NULL)
MachineDebugInfo::~MachineDebugInfo() {
}
/// doInitialization - Initialize the debug state for a new module.
///
bool MachineDebugInfo::doInitialization() {
return false;
}
/// doFinalization - Tear down the debug state after completion of a module.
///
bool MachineDebugInfo::doFinalization() {
return false;
}
/// BeginFunction - Begin gathering function debug information.
///
void MachineDebugInfo::BeginFunction(MachineFunction *MF) {
// Coming soon.
}
/// MachineDebugInfo::EndFunction - Discard function debug information.
///
void MachineDebugInfo::EndFunction() {
// Clean up scope information.
if (RootScope) {
delete RootScope;
ScopeMap.clear();
RootScope = NULL;
}
// Clean up frame info.
FrameMoves.clear();
}
/// getDescFor - Convert a Value to a debug information descriptor.
Jim Laskey
committed
///
// FIXME - use new Value type when available.
DebugInfoDesc *MachineDebugInfo::getDescFor(Value *V) {
Jim Laskey
committed
return DR.Deserialize(V);
}
/// Verify - Verify that a Value is debug information descriptor.
///
bool MachineDebugInfo::Verify(Value *V) {
return VR.Verify(V);
}
/// AnalyzeModule - Scan the module for global debug information.
///
void MachineDebugInfo::AnalyzeModule(Module &M) {
SetupCompileUnits(M);
}
/// SetupCompileUnits - Set up the unique vector of compile units.
///
void MachineDebugInfo::SetupCompileUnits(Module &M) {
std::vector<CompileUnitDesc *>CU = getAnchoredDescriptors<CompileUnitDesc>(M);
for (unsigned i = 0, N = CU.size(); i < N; i++) {
CompileUnits.insert(CU[i]);
}
}
/// getCompileUnits - Return a vector of debug compile units.
///
const UniqueVector<CompileUnitDesc *> MachineDebugInfo::getCompileUnits()const{
return CompileUnits;
}
/// getGlobalVariablesUsing - Return all of the GlobalVariables that use the
/// named GlobalVariable.
std::vector<GlobalVariable*>
MachineDebugInfo::getGlobalVariablesUsing(Module &M,
const std::string &RootName) {
return ::getGlobalVariablesUsing(M, RootName);
}
/// RecordLabel - Records location information and associates it with a
/// debug label. Returns a unique label ID used to generate a label and
/// provide correspondence to the source line list.
unsigned MachineDebugInfo::RecordLabel(unsigned Line, unsigned Column,
unsigned Source) {
unsigned ID = NextLabelID();
Lines.push_back(SourceLineInfo(Line, Column, Source, ID));
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
return ID;
}
/// RecordSource - Register a source file with debug info. Returns an source
/// ID.
unsigned MachineDebugInfo::RecordSource(const std::string &Directory,
const std::string &Source) {
unsigned DirectoryID = Directories.insert(Directory);
return SourceFiles.insert(SourceFileInfo(DirectoryID, Source));
}
unsigned MachineDebugInfo::RecordSource(const CompileUnitDesc *CompileUnit) {
return RecordSource(CompileUnit->getDirectory(),
CompileUnit->getFileName());
}
/// RecordRegionStart - Indicate the start of a region.
///
unsigned MachineDebugInfo::RecordRegionStart(Value *V) {
// FIXME - need to be able to handle split scopes because of bb cloning.
DebugInfoDesc *ScopeDesc = DR.Deserialize(V);
DebugScope *Scope = getOrCreateScope(ScopeDesc);
unsigned ID = NextLabelID();
if (!Scope->getStartLabelID()) Scope->setStartLabelID(ID);
return ID;
}
/// RecordRegionEnd - Indicate the end of a region.
///
unsigned MachineDebugInfo::RecordRegionEnd(Value *V) {
// FIXME - need to be able to handle split scopes because of bb cloning.
DebugInfoDesc *ScopeDesc = DR.Deserialize(V);
DebugScope *Scope = getOrCreateScope(ScopeDesc);
unsigned ID = NextLabelID();
Scope->setEndLabelID(ID);
return ID;
}
/// RecordVariable - Indicate the declaration of a local variable.
///
void MachineDebugInfo::RecordVariable(Value *V, unsigned FrameIndex) {
VariableDesc *VD = cast<VariableDesc>(DR.Deserialize(V));
DebugScope *Scope = getOrCreateScope(VD->getContext());
DebugVariable *DV = new DebugVariable(VD, FrameIndex);
Scope->AddVariable(DV);
}
/// getOrCreateScope - Returns the scope associated with the given descriptor.
///
DebugScope *MachineDebugInfo::getOrCreateScope(DebugInfoDesc *ScopeDesc) {
DebugScope *&Slot = ScopeMap[ScopeDesc];
if (!Slot) {
// FIXME - breaks down when the context is an inlined function.
DebugInfoDesc *ParentDesc = NULL;
if (BlockDesc *Block = dyn_cast<BlockDesc>(ScopeDesc)) {
ParentDesc = Block->getContext();
}
DebugScope *Parent = ParentDesc ? getOrCreateScope(ParentDesc) : NULL;
Slot = new DebugScope(Parent, ScopeDesc);
if (Parent) {
Parent->AddScope(Slot);
} else if (RootScope) {
// FIXME - Add inlined function scopes to the root so we can delete
// them later. Long term, handle inlined functions properly.
RootScope->AddScope(Slot);
} else {
// First function is top level function.
RootScope = Slot;
}
}
return Slot;
}
Jim Laskey
committed
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
//===----------------------------------------------------------------------===//
/// DebugLabelFolding pass - This pass prunes out redundant debug labels. This
/// allows a debug emitter to determine if the range of two labels is empty,
/// by seeing if the labels map to the same reduced label.
namespace llvm {
struct DebugLabelFolder : public MachineFunctionPass {
virtual bool runOnMachineFunction(MachineFunction &MF);
virtual const char *getPassName() const { return "Debug Label Folder"; }
};
bool DebugLabelFolder::runOnMachineFunction(MachineFunction &MF) {
// Get machine debug info.
MachineDebugInfo *MDI = getAnalysisToUpdate<MachineDebugInfo>();
if (!MDI) return false;
// Get target instruction info.
const TargetInstrInfo *TII = MF.getTarget().getInstrInfo();
if (!TII) return false;
// Track if change is made.
bool MadeChange = false;
// No prior label to begin.
unsigned PriorLabel = 0;
// Iterate through basic blocks.
for (MachineFunction::iterator BB = MF.begin(), E = MF.end();
BB != E; ++BB) {
// Iterate through instructions.
for (MachineBasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) {
// Is it a debug label.
if ((unsigned)I->getOpcode() == TargetInstrInfo::LABEL) {
Jim Laskey
committed
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
// The label ID # is always operand #0, an immediate.
unsigned NextLabel = I->getOperand(0).getImm();
// If there was an immediate prior label.
if (PriorLabel) {
// Remap the current label to prior label.
MDI->RemapLabel(NextLabel, PriorLabel);
// Delete the current label.
I = BB->erase(I);
// Indicate a change has been made.
MadeChange = true;
continue;
} else {
// Start a new round.
PriorLabel = NextLabel;
}
} else {
// No consecutive labels.
PriorLabel = 0;
}
++I;
}
}
return MadeChange;
}
FunctionPass *createDebugLabelFoldingPass() { return new DebugLabelFolder(); }
}