Define metadata interfaces for describing a static data member

of a class. Emit static data member declarations and definitions
through correctly.

Part of PR14471.

Patch by Paul Robinson!

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172590 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Eric Christopher
2013-01-16 01:22:23 +00:00
parent 171192f149
commit 6b6061f011
6 changed files with 164 additions and 51 deletions

View File

@@ -172,6 +172,19 @@ namespace llvm {
uint64_t AlignInBits, uint64_t OffsetInBits, uint64_t AlignInBits, uint64_t OffsetInBits,
unsigned Flags, DIType Ty); unsigned Flags, DIType Ty);
/// createStaticMemberType - Create debugging information entry for a
/// C++ static data member.
/// @param Scope Member scope.
/// @param Name Member name.
/// @param File File where this member is declared.
/// @param LineNo Line number.
/// @param Ty Type of the static member.
/// @param Flags Flags to encode member attribute, e.g. private.
/// @param Val Const initializer of the member.
DIType createStaticMemberType(DIDescriptor Scope, StringRef Name,
DIFile File, unsigned LineNo, DIType Ty,
unsigned Flags, llvm::Value *Val);
/// createObjCIVar - Create debugging information entry for Objective-C /// createObjCIVar - Create debugging information entry for Objective-C
/// instance variable. /// instance variable.
/// @param Name Member name. /// @param Name Member name.
@@ -402,10 +415,12 @@ namespace llvm {
/// @param isLocalToUnit Boolean flag indicate whether this variable is /// @param isLocalToUnit Boolean flag indicate whether this variable is
/// externally visible or not. /// externally visible or not.
/// @param Val llvm::Value of the variable. /// @param Val llvm::Value of the variable.
/// @param Decl Reference to the corresponding declaration.
DIGlobalVariable DIGlobalVariable
createStaticVariable(DIDescriptor Context, StringRef Name, createStaticVariable(DIDescriptor Context, StringRef Name,
StringRef LinkageName, DIFile File, unsigned LineNo, StringRef LinkageName, DIFile File, unsigned LineNo,
DIType Ty, bool isLocalToUnit, llvm::Value *Val); DIType Ty, bool isLocalToUnit, llvm::Value *Val,
MDNode *Decl = NULL);
/// createLocalVariable - Create a new descriptor for the specified /// createLocalVariable - Create a new descriptor for the specified

View File

@@ -62,7 +62,8 @@ namespace llvm {
FlagPrototyped = 1 << 8, FlagPrototyped = 1 << 8,
FlagObjcClassComplete = 1 << 9, FlagObjcClassComplete = 1 << 9,
FlagObjectPointer = 1 << 10, FlagObjectPointer = 1 << 10,
FlagVector = 1 << 11 FlagVector = 1 << 11,
FlagStaticMember = 1 << 12
}; };
protected: protected:
const MDNode *DbgNode; const MDNode *DbgNode;
@@ -300,6 +301,9 @@ namespace llvm {
bool isVector() const { bool isVector() const {
return (getFlags() & FlagVector) != 0; return (getFlags() & FlagVector) != 0;
} }
bool isStaticMember() const {
return (getFlags() & FlagStaticMember) != 0;
}
bool isValid() const { bool isValid() const {
return DbgNode && (isBasicType() || isDerivedType() || isCompositeType()); return DbgNode && (isBasicType() || isDerivedType() || isCompositeType());
} }
@@ -337,7 +341,8 @@ namespace llvm {
}; };
/// DIDerivedType - A simple derived type, like a const qualified type, /// DIDerivedType - A simple derived type, like a const qualified type,
/// a typedef, a pointer or reference, etc. /// a typedef, a pointer or reference, et cetera. Or, a data member of
/// a class/struct/union.
class DIDerivedType : public DIType { class DIDerivedType : public DIType {
friend class DIDescriptor; friend class DIDescriptor;
void printInternal(raw_ostream &OS) const; void printInternal(raw_ostream &OS) const;
@@ -363,6 +368,11 @@ namespace llvm {
return getFieldAs<DIType>(10); return getFieldAs<DIType>(10);
} }
Constant *getConstant() const {
assert((getTag() == dwarf::DW_TAG_member) && isStaticMember());
return getConstantField(10);
}
StringRef getObjCPropertyName() const { StringRef getObjCPropertyName() const {
if (getVersion() > LLVMDebugVersion11) if (getVersion() > LLVMDebugVersion11)
return StringRef(); return StringRef();
@@ -620,6 +630,9 @@ namespace llvm {
GlobalVariable *getGlobal() const { return getGlobalVariableField(11); } GlobalVariable *getGlobal() const { return getGlobalVariableField(11); }
Constant *getConstant() const { return getConstantField(11); } Constant *getConstant() const { return getConstantField(11); }
DIDerivedType getStaticDataMemberDeclaration() const {
return getFieldAs<DIDerivedType>(12);
}
/// Verify - Verify that a global variable descriptor is well formed. /// Verify - Verify that a global variable descriptor is well formed.
bool Verify() const; bool Verify() const;

View File

@@ -670,18 +670,21 @@ void CompileUnit::addTemplateParams(DIE &Buffer, DIArray TParams) {
} }
} }
/// getOrCreateContextDIE - Get context owner's DIE.
DIE *CompileUnit::getOrCreateContextDIE(DIDescriptor Context) {
if (Context.isType())
return getOrCreateTypeDIE(DIType(Context));
else if (Context.isNameSpace())
return getOrCreateNameSpace(DINameSpace(Context));
else if (Context.isSubprogram())
return getOrCreateSubprogramDIE(DISubprogram(Context));
else
return getDIE(Context);
}
/// addToContextOwner - Add Die into the list of its context owner's children. /// addToContextOwner - Add Die into the list of its context owner's children.
void CompileUnit::addToContextOwner(DIE *Die, DIDescriptor Context) { void CompileUnit::addToContextOwner(DIE *Die, DIDescriptor Context) {
if (Context.isType()) { if (DIE *ContextDIE = getOrCreateContextDIE(Context))
DIE *ContextDIE = getOrCreateTypeDIE(DIType(Context));
ContextDIE->addChild(Die);
} else if (Context.isNameSpace()) {
DIE *ContextDIE = getOrCreateNameSpace(DINameSpace(Context));
ContextDIE->addChild(Die);
} else if (Context.isSubprogram()) {
DIE *ContextDIE = getOrCreateSubprogramDIE(DISubprogram(Context));
ContextDIE->addChild(Die);
} else if (DIE *ContextDIE = getDIE(Context))
ContextDIE->addChild(Die); ContextDIE->addChild(Die);
else else
addDie(Die); addDie(Die);
@@ -925,22 +928,15 @@ void CompileUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) {
dwarf::DW_ACCESS_public); dwarf::DW_ACCESS_public);
if (SP.isExplicit()) if (SP.isExplicit())
addFlag(ElemDie, dwarf::DW_AT_explicit); addFlag(ElemDie, dwarf::DW_AT_explicit);
}
else if (Element.isVariable()) {
DIVariable DV(Element);
ElemDie = new DIE(dwarf::DW_TAG_variable);
addString(ElemDie, dwarf::DW_AT_name, DV.getName());
addType(ElemDie, DV.getType());
addFlag(ElemDie, dwarf::DW_AT_declaration);
addFlag(ElemDie, dwarf::DW_AT_external);
addSourceLine(ElemDie, DV);
} else if (Element.isDerivedType()) { } else if (Element.isDerivedType()) {
DIDerivedType DDTy(Element); DIDerivedType DDTy(Element);
if (DDTy.getTag() == dwarf::DW_TAG_friend) { if (DDTy.getTag() == dwarf::DW_TAG_friend) {
ElemDie = new DIE(dwarf::DW_TAG_friend); ElemDie = new DIE(dwarf::DW_TAG_friend);
addType(ElemDie, DDTy.getTypeDerivedFrom(), dwarf::DW_AT_friend); addType(ElemDie, DDTy.getTypeDerivedFrom(), dwarf::DW_AT_friend);
} else } else if (DDTy.isStaticMember())
ElemDie = createMemberDIE(DIDerivedType(Element)); ElemDie = createStaticMemberDIE(DDTy);
else
ElemDie = createMemberDIE(DDTy);
} else if (Element.isObjCProperty()) { } else if (Element.isObjCProperty()) {
DIObjCProperty Property(Element); DIObjCProperty Property(Element);
ElemDie = new DIE(Property.getTag()); ElemDie = new DIE(Property.getTag());
@@ -1256,33 +1252,48 @@ void CompileUnit::createGlobalVariableDIE(const MDNode *N) {
if (!GV.Verify()) if (!GV.Verify())
return; return;
DIE *VariableDIE = new DIE(GV.getTag());
// Add to map.
insertDIE(N, VariableDIE);
// Add name.
addString(VariableDIE, dwarf::DW_AT_name, GV.getDisplayName());
StringRef LinkageName = GV.getLinkageName();
bool isGlobalVariable = GV.getGlobal() != NULL;
if (!LinkageName.empty() && isGlobalVariable)
addString(VariableDIE, dwarf::DW_AT_MIPS_linkage_name,
getRealLinkageName(LinkageName));
// Add type.
DIType GTy = GV.getType();
addType(VariableDIE, GTy);
// Add scoping info.
if (!GV.isLocalToUnit())
addFlag(VariableDIE, dwarf::DW_AT_external);
// Add line number info.
addSourceLine(VariableDIE, GV);
// Add to context owner.
DIDescriptor GVContext = GV.getContext(); DIDescriptor GVContext = GV.getContext();
addToContextOwner(VariableDIE, GVContext); DIType GTy = GV.getType();
// If this is a static data member definition, some attributes belong
// to the declaration DIE.
DIE *VariableDIE = NULL;
DIDerivedType SDMDecl = GV.getStaticDataMemberDeclaration();
if (SDMDecl.Verify()) {
assert(SDMDecl.isStaticMember() && "Expected static member decl");
// We need the declaration DIE that is in the static member's class.
// But that class might not exist in the DWARF yet.
// Creating the class will create the static member decl DIE.
getOrCreateContextDIE(SDMDecl.getContext());
VariableDIE = getDIE(SDMDecl);
assert(VariableDIE && "Static member decl has no context?");
}
// If this is not a static data member definition, create the variable
// DIE and add the initial set of attributes to it.
if (!VariableDIE) {
VariableDIE = new DIE(GV.getTag());
// Add to map.
insertDIE(N, VariableDIE);
// Add name and type.
addString(VariableDIE, dwarf::DW_AT_name, GV.getDisplayName());
addType(VariableDIE, GTy);
// Add scoping info.
if (!GV.isLocalToUnit())
addFlag(VariableDIE, dwarf::DW_AT_external);
// Add line number info.
addSourceLine(VariableDIE, GV);
// Add to context owner.
addToContextOwner(VariableDIE, GVContext);
}
// Add location. // Add location.
bool addToAccelTable = false; bool addToAccelTable = false;
DIE *VariableSpecDIE = NULL; DIE *VariableSpecDIE = NULL;
bool isGlobalVariable = GV.getGlobal() != NULL;
if (isGlobalVariable) { if (isGlobalVariable) {
addToAccelTable = true; addToAccelTable = true;
DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); DIEBlock *Block = new (DIEValueAllocator) DIEBlock();
@@ -1298,11 +1309,18 @@ void CompileUnit::createGlobalVariableDIE(const MDNode *N) {
addDIEEntry(VariableSpecDIE, dwarf::DW_AT_specification, addDIEEntry(VariableSpecDIE, dwarf::DW_AT_specification,
dwarf::DW_FORM_ref4, VariableDIE); dwarf::DW_FORM_ref4, VariableDIE);
addBlock(VariableSpecDIE, dwarf::DW_AT_location, 0, Block); addBlock(VariableSpecDIE, dwarf::DW_AT_location, 0, Block);
addFlag(VariableDIE, dwarf::DW_AT_declaration); // A static member's declaration is already flagged as such.
if (!SDMDecl.Verify())
addFlag(VariableDIE, dwarf::DW_AT_declaration);
addDie(VariableSpecDIE); addDie(VariableSpecDIE);
} else { } else {
addBlock(VariableDIE, dwarf::DW_AT_location, 0, Block); addBlock(VariableDIE, dwarf::DW_AT_location, 0, Block);
} }
// Add linkage name.
StringRef LinkageName = GV.getLinkageName();
if (!LinkageName.empty() && isGlobalVariable)
addString(VariableDIE, dwarf::DW_AT_MIPS_linkage_name,
getRealLinkageName(LinkageName));
} else if (const ConstantInt *CI = } else if (const ConstantInt *CI =
dyn_cast_or_null<ConstantInt>(GV.getConstant())) dyn_cast_or_null<ConstantInt>(GV.getConstant()))
addConstantValue(VariableDIE, CI, GTy.isUnsignedDIType()); addConstantValue(VariableDIE, CI, GTy.isUnsignedDIType());
@@ -1638,3 +1656,36 @@ DIE *CompileUnit::createMemberDIE(DIDerivedType DT) {
} }
return MemberDie; return MemberDie;
} }
/// createStaticMemberDIE - Create new DIE for C++ static member.
DIE *CompileUnit::createStaticMemberDIE(const DIDerivedType DT) {
if (!DT.Verify())
return NULL;
DIE *StaticMemberDIE = new DIE(DT.getTag());
DIType Ty = DT.getTypeDerivedFrom();
addString(StaticMemberDIE, dwarf::DW_AT_name, DT.getName());
addType(StaticMemberDIE, Ty);
addSourceLine(StaticMemberDIE, DT);
addFlag(StaticMemberDIE, dwarf::DW_AT_external);
addFlag(StaticMemberDIE, dwarf::DW_AT_declaration);
// FIXME: We could omit private if the parent is a class_type, and
// public if the parent is something else.
if (DT.isProtected())
addUInt(StaticMemberDIE, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1,
dwarf::DW_ACCESS_protected);
else if (DT.isPrivate())
addUInt(StaticMemberDIE, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1,
dwarf::DW_ACCESS_private);
else
addUInt(StaticMemberDIE, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1,
dwarf::DW_ACCESS_public);
if (const ConstantInt *CI = dyn_cast_or_null<ConstantInt>(DT.getConstant()))
addConstantValue(StaticMemberDIE, CI, Ty.isUnsignedDIType());
insertDIE(DT, StaticMemberDIE);
return StaticMemberDIE;
}

View File

@@ -86,6 +86,9 @@ class CompileUnit {
/// DWARF version doesn't handle the language, return -1. /// DWARF version doesn't handle the language, return -1.
int64_t getDefaultLowerBound() const; int64_t getDefaultLowerBound() const;
/// getOrCreateContextDIE - Get context owner's DIE.
DIE *getOrCreateContextDIE(DIDescriptor Context);
public: public:
CompileUnit(unsigned UID, unsigned L, DIE *D, AsmPrinter *A, DwarfDebug *DW, CompileUnit(unsigned UID, unsigned L, DIE *D, AsmPrinter *A, DwarfDebug *DW,
DwarfUnits *); DwarfUnits *);
@@ -344,6 +347,9 @@ public:
/// createMemberDIE - Create new member DIE. /// createMemberDIE - Create new member DIE.
DIE *createMemberDIE(DIDerivedType DT); DIE *createMemberDIE(DIDerivedType DT);
/// createStaticMemberDIE - Create new static data member DIE.
DIE *createStaticMemberDIE(DIDerivedType DT);
private: private:
// DIEValueAllocator - All DIEValues are allocated through this allocator. // DIEValueAllocator - All DIEValues are allocated through this allocator.

View File

@@ -350,6 +350,30 @@ DIType DIBuilder::createMemberType(DIDescriptor Scope, StringRef Name,
return DIType(MDNode::get(VMContext, Elts)); return DIType(MDNode::get(VMContext, Elts));
} }
/// createStaticMemberType - Create debugging information entry for a
/// C++ static data member.
DIType DIBuilder::createStaticMemberType(DIDescriptor Scope, StringRef Name,
DIFile File, unsigned LineNumber,
DIType Ty, unsigned Flags,
llvm::Value *Val) {
// TAG_member is encoded in DIDerivedType format.
Flags |= DIDescriptor::FlagStaticMember;
Value *Elts[] = {
GetTagConstant(VMContext, dwarf::DW_TAG_member),
getNonCompileUnitScope(Scope),
MDString::get(VMContext, Name),
File,
ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
ConstantInt::get(Type::getInt64Ty(VMContext), 0/*SizeInBits*/),
ConstantInt::get(Type::getInt64Ty(VMContext), 0/*AlignInBits*/),
ConstantInt::get(Type::getInt64Ty(VMContext), 0/*OffsetInBits*/),
ConstantInt::get(Type::getInt32Ty(VMContext), Flags),
Ty,
Val
};
return DIType(MDNode::get(VMContext, Elts));
}
/// createObjCIVar - Create debugging information entry for Objective-C /// createObjCIVar - Create debugging information entry for Objective-C
/// instance variable. /// instance variable.
DIType DIBuilder::createObjCIVar(StringRef Name, DIType DIBuilder::createObjCIVar(StringRef Name,
@@ -787,7 +811,8 @@ createGlobalVariable(StringRef Name, DIFile F, unsigned LineNumber,
Ty, Ty,
ConstantInt::get(Type::getInt32Ty(VMContext), isLocalToUnit), ConstantInt::get(Type::getInt32Ty(VMContext), isLocalToUnit),
ConstantInt::get(Type::getInt32Ty(VMContext), 1), /* isDefinition*/ ConstantInt::get(Type::getInt32Ty(VMContext), 1), /* isDefinition*/
Val Val,
DIDescriptor()
}; };
MDNode *Node = MDNode::get(VMContext, Elts); MDNode *Node = MDNode::get(VMContext, Elts);
AllGVs.push_back(Node); AllGVs.push_back(Node);
@@ -799,7 +824,7 @@ createGlobalVariable(StringRef Name, DIFile F, unsigned LineNumber,
DIGlobalVariable DIBuilder:: DIGlobalVariable DIBuilder::
createStaticVariable(DIDescriptor Context, StringRef Name, createStaticVariable(DIDescriptor Context, StringRef Name,
StringRef LinkageName, DIFile F, unsigned LineNumber, StringRef LinkageName, DIFile F, unsigned LineNumber,
DIType Ty, bool isLocalToUnit, Value *Val) { DIType Ty, bool isLocalToUnit, Value *Val, MDNode *Decl) {
Value *Elts[] = { Value *Elts[] = {
GetTagConstant(VMContext, dwarf::DW_TAG_variable), GetTagConstant(VMContext, dwarf::DW_TAG_variable),
Constant::getNullValue(Type::getInt32Ty(VMContext)), Constant::getNullValue(Type::getInt32Ty(VMContext)),
@@ -812,7 +837,8 @@ createStaticVariable(DIDescriptor Context, StringRef Name,
Ty, Ty,
ConstantInt::get(Type::getInt32Ty(VMContext), isLocalToUnit), ConstantInt::get(Type::getInt32Ty(VMContext), isLocalToUnit),
ConstantInt::get(Type::getInt32Ty(VMContext), 1), /* isDefinition*/ ConstantInt::get(Type::getInt32Ty(VMContext), 1), /* isDefinition*/
Val Val,
DIDescriptor(Decl)
}; };
MDNode *Node = MDNode::get(VMContext, Elts); MDNode *Node = MDNode::get(VMContext, Elts);
AllGVs.push_back(Node); AllGVs.push_back(Node);

View File

@@ -1101,6 +1101,8 @@ void DIType::printInternal(raw_ostream &OS) const {
OS << " [fwd]"; OS << " [fwd]";
if (isVector()) if (isVector())
OS << " [vector]"; OS << " [vector]";
if (isStaticMember())
OS << " [static]";
} }
void DIDerivedType::printInternal(raw_ostream &OS) const { void DIDerivedType::printInternal(raw_ostream &OS) const {