#include "llvm/IR/DataLayout.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instructions.h"
+#include "llvm/MC/MCSection.h"
+#include "llvm/MC/MCStreamer.h"
#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetFrameLowering.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Support/CommandLine.h"
using namespace llvm;
+static cl::opt<bool> GenerateTypeUnits("generate-type-units", cl::Hidden,
+ cl::desc("Generate DWARF4 type units."),
+ cl::init(false));
+
/// CompileUnit - Compile unit constructor.
-CompileUnit::CompileUnit(unsigned UID, DIE *D, const MDNode *N, AsmPrinter *A,
- DwarfDebug *DW, DwarfUnits *DWU)
- : UniqueID(UID), Node(N), CUDie(D), Asm(A), DD(DW), DU(DWU), IndexTyDie(0) {
+CompileUnit::CompileUnit(unsigned UID, DIE *D, DICompileUnit Node,
+ AsmPrinter *A, DwarfDebug *DW, DwarfUnits *DWU)
+ : UniqueID(UID), Node(Node), Language(Node.getLanguage()), CUDie(D),
+ DebugInfoOffset(0), Asm(A), DD(DW), DU(DWU), IndexTyDie(0) {
+ DIEIntegerOne = new (DIEValueAllocator) DIEInteger(1);
+ insertDIE(Node, D);
+}
+
+CompileUnit::CompileUnit(unsigned UID, DIE *D, uint16_t Language, AsmPrinter *A,
+ DwarfDebug *DD, DwarfUnits *DU)
+ : UniqueID(UID), Node(NULL), Language(Language), CUDie(D),
+ DebugInfoOffset(0), Asm(A), DD(DD), DU(DU), IndexTyDie(0) {
DIEIntegerOne = new (DIEValueAllocator) DIEInteger(1);
- insertDIE(N, D);
}
/// ~CompileUnit - Destructor for compile unit.
/// getDefaultLowerBound - Return the default lower bound for an array. If the
/// DWARF version doesn't handle the language, return -1.
int64_t CompileUnit::getDefaultLowerBound() const {
- switch (DICompileUnit(Node).getLanguage()) {
+ switch (getLanguage()) {
default:
break;
return -1;
}
+/// Check whether the DIE for this MDNode can be shared across CUs.
+static bool isShareableAcrossCUs(DIDescriptor D) {
+ // When the MDNode can be part of the type system, the DIE can be shared
+ // across CUs.
+ // Combining type units and cross-CU DIE sharing is lower value (since
+ // cross-CU DIE sharing is used in LTO and removes type redundancy at that
+ // level already) but may be implementable for some value in projects
+ // building multiple independent libraries with LTO and then linking those
+ // together.
+ return (D.isType() ||
+ (D.isSubprogram() && !DISubprogram(D).isDefinition())) &&
+ !GenerateTypeUnits;
+}
+
+/// getDIE - Returns the debug information entry map slot for the
+/// specified debug variable. We delegate the request to DwarfDebug
+/// when the DIE for this MDNode can be shared across CUs. The mappings
+/// will be kept in DwarfDebug for shareable DIEs.
+DIE *CompileUnit::getDIE(DIDescriptor D) const {
+ if (isShareableAcrossCUs(D))
+ return DD->getDIE(D);
+ return MDNodeToDieMap.lookup(D);
+}
+
+/// insertDIE - Insert DIE into the map. We delegate the request to DwarfDebug
+/// when the DIE for this MDNode can be shared across CUs. The mappings
+/// will be kept in DwarfDebug for shareable DIEs.
+void CompileUnit::insertDIE(DIDescriptor Desc, DIE *D) {
+ if (isShareableAcrossCUs(Desc)) {
+ DD->insertDIE(Desc, D);
+ return;
+ }
+ MDNodeToDieMap.insert(std::make_pair(Desc, D));
+}
+
/// addFlag - Add a flag that is true.
void CompileUnit::addFlag(DIE *Die, dwarf::Attribute Attribute) {
if (DD->getDwarfVersion() >= 4)
/// more predictable sizes. In the case of split dwarf we emit an index
/// into another table which gets us the static offset into the string
/// table.
-void CompileUnit::addString(DIE *Die, dwarf::Attribute Attribute, StringRef String) {
+void CompileUnit::addString(DIE *Die, dwarf::Attribute Attribute,
+ StringRef String) {
DIEValue *Value;
dwarf::Form Form;
if (!DD->useSplitDwarf()) {
/// addLabel - Add a Dwarf label attribute data and value.
///
-void CompileUnit::addLabel(DIE *Die, dwarf::Attribute Attribute, dwarf::Form Form,
- const MCSymbol *Label) {
+void CompileUnit::addLabel(DIE *Die, dwarf::Attribute Attribute,
+ dwarf::Form Form, const MCSymbol *Label) {
DIEValue *Value = new (DIEValueAllocator) DIELabel(Label);
Die->addValue(Attribute, Form, Value);
}
addLabel(Die, (dwarf::Attribute)0, Form, Label);
}
+/// addSectionLabel - Add a Dwarf section label attribute data and value.
+///
+void CompileUnit::addSectionLabel(DIE *Die, dwarf::Attribute Attribute,
+ const MCSymbol *Label) {
+ if (DD->getDwarfVersion() >= 4)
+ addLabel(Die, Attribute, dwarf::DW_FORM_sec_offset, Label);
+ else
+ addLabel(Die, Attribute, dwarf::DW_FORM_data4, Label);
+}
+
+/// addSectionOffset - Add an offset into a section attribute data and value.
+///
+void CompileUnit::addSectionOffset(DIE *Die, dwarf::Attribute Attribute,
+ uint64_t Integer) {
+ if (DD->getDwarfVersion() >= 4)
+ addUInt(Die, Attribute, dwarf::DW_FORM_sec_offset, Integer);
+ else
+ addUInt(Die, Attribute, dwarf::DW_FORM_data4, Integer);
+}
+
/// addLabelAddress - Add a dwarf label attribute data and value using
/// DW_FORM_addr or DW_FORM_GNU_addr_index.
///
}
}
-/// addDelta - Add a label delta attribute data and value.
+/// addSectionDelta - Add a section label delta attribute data and value.
///
-void CompileUnit::addDelta(DIE *Die, dwarf::Attribute Attribute, dwarf::Form Form,
- const MCSymbol *Hi, const MCSymbol *Lo) {
+void CompileUnit::addSectionDelta(DIE *Die, dwarf::Attribute Attribute,
+ const MCSymbol *Hi, const MCSymbol *Lo) {
DIEValue *Value = new (DIEValueAllocator) DIEDelta(Hi, Lo);
- Die->addValue(Attribute, Form, Value);
+ if (DD->getDwarfVersion() >= 4)
+ Die->addValue(Attribute, dwarf::DW_FORM_sec_offset, Value);
+ else
+ Die->addValue(Attribute, dwarf::DW_FORM_data4, Value);
}
/// addDIEEntry - Add a DIE attribute data and value.
///
-void CompileUnit::addDIEEntry(DIE *Die, dwarf::Attribute Attribute, DIE *Entry) {
- // We currently only use ref4.
- Die->addValue(Attribute, dwarf::DW_FORM_ref4, createDIEEntry(Entry));
+void CompileUnit::addDIEEntry(DIE *Die, dwarf::Attribute Attribute,
+ DIE *Entry) {
+ addDIEEntry(Die, Attribute, createDIEEntry(Entry));
+}
+
+void CompileUnit::addDIEEntry(DIE *Die, dwarf::Attribute Attribute,
+ DIEEntry *Entry) {
+ const DIE *DieCU = Die->getUnitOrNull();
+ const DIE *EntryCU = Entry->getEntry()->getUnitOrNull();
+ if (!DieCU)
+ // We assume that Die belongs to this CU, if it is not linked to any CU yet.
+ DieCU = getCUDie();
+ if (!EntryCU)
+ EntryCU = getCUDie();
+ Die->addValue(Attribute, EntryCU == DieCU ? dwarf::DW_FORM_ref4
+ : dwarf::DW_FORM_ref_addr,
+ Entry);
}
/// Create a DIE with the given Tag, add the DIE to its parent, and
/// call insertDIE if MD is not null.
-DIE *CompileUnit::createAndAddDIE(unsigned Tag, DIE &Parent, const MDNode *MD) {
+DIE *CompileUnit::createAndAddDIE(unsigned Tag, DIE &Parent, DIDescriptor N) {
DIE *Die = new DIE(Tag);
Parent.addChild(Die);
- if (MD)
- insertDIE(MD, Die);
+ if (N)
+ insertDIE(N, Die);
return Die;
}
StringRef varName = DV.getName();
if (Tag == dwarf::DW_TAG_pointer_type) {
- DIDerivedType DTy = DIDerivedType(Ty);
+ DIDerivedType DTy(Ty);
TmpTy = resolve(DTy.getTypeDerivedFrom());
isPointer = true;
}
- DICompositeType blockStruct = DICompositeType(TmpTy);
+ DICompositeType blockStruct(TmpTy);
// Find the __forwarding field and the variable field in the __Block_byref
// struct.
DIArray Fields = blockStruct.getTypeArray();
- DIDescriptor varField = DIDescriptor();
- DIDescriptor forwardingField = DIDescriptor();
+ DIDerivedType varField;
+ DIDerivedType forwardingField;
for (unsigned i = 0, N = Fields.getNumElements(); i < N; ++i) {
- DIDescriptor Element = Fields.getElement(i);
- DIDerivedType DT = DIDerivedType(Element);
+ DIDerivedType DT(Fields.getElement(i));
StringRef fieldName = DT.getName();
if (fieldName == "__forwarding")
- forwardingField = Element;
+ forwardingField = DT;
else if (fieldName == varName)
- varField = Element;
+ varField = DT;
}
// Get the offsets for the forwarding field and the variable field.
- unsigned forwardingFieldOffset =
- DIDerivedType(forwardingField).getOffsetInBits() >> 3;
- unsigned varFieldOffset = DIDerivedType(varField).getOffsetInBits() >> 3;
+ unsigned forwardingFieldOffset = forwardingField.getOffsetInBits() >> 3;
+ unsigned varFieldOffset = varField.getOffsetInBits() >> 2;
// Decode the original location, and use that as the start of the byref
// variable's location.
// Output the constant to DWARF one byte at a time.
for (; Start != Stop; Start += Incr)
- addUInt(Block, dwarf::DW_FORM_data1,
- (unsigned char)0xFF & FltPtr[Start]);
+ addUInt(Block, dwarf::DW_FORM_data1, (unsigned char)0xFF & FltPtr[Start]);
addBlock(Die, dwarf::DW_AT_const_value, Block);
}
/// getOrCreateContextDIE - Get context owner's DIE.
DIE *CompileUnit::getOrCreateContextDIE(DIScope Context) {
+ if (!Context || Context.isFile())
+ return getCUDie();
if (Context.isType())
return getOrCreateTypeDIE(DIType(Context));
- else if (Context.isNameSpace())
+ if (Context.isNameSpace())
return getOrCreateNameSpace(DINameSpace(Context));
- else if (Context.isSubprogram())
+ if (Context.isSubprogram())
return getOrCreateSubprogramDIE(DISubprogram(Context));
- else
- return getDIE(Context);
+ return getDIE(Context);
}
-/// addToContextOwner - Add Die into the list of its context owner's children.
-void CompileUnit::addToContextOwner(DIE *Die, DIScope Context) {
- assert(!Die->getParent());
- if (DIE *ContextDIE = getOrCreateContextDIE(Context)) {
- if (Die->getParent()) {
- // While creating the context, if this is a type member, we will have
- // added the child to the context already.
- assert(Die->getParent() == ContextDIE);
- return;
- }
- ContextDIE->addChild(Die);
- } else
- addDie(Die);
+DIE *CompileUnit::createTypeDIE(DICompositeType Ty) {
+ DIE *ContextDIE = getOrCreateContextDIE(resolve(Ty.getContext()));
+
+ DIE *TyDIE = getDIE(Ty);
+ if (TyDIE)
+ return TyDIE;
+
+ // Create new type.
+ TyDIE = createAndAddDIE(Ty.getTag(), *ContextDIE, Ty);
+
+ constructTypeDIEImpl(*TyDIE, Ty);
+
+ updateAcceleratorTables(Ty, TyDIE);
+ return TyDIE;
}
/// getOrCreateTypeDIE - Find existing DIE or create new DIE for the
/// given DIType.
DIE *CompileUnit::getOrCreateTypeDIE(const MDNode *TyNode) {
- DIType Ty(TyNode);
- if (!Ty.isType())
+ if (!TyNode)
return NULL;
+
+ DIType Ty(TyNode);
+ assert(Ty.isType());
+
+ // Construct the context before querying for the existence of the DIE in case
+ // such construction creates the DIE.
+ DIE *ContextDIE = getOrCreateContextDIE(resolve(Ty.getContext()));
+ assert(ContextDIE);
+
DIE *TyDIE = getDIE(Ty);
if (TyDIE)
return TyDIE;
// Create new type.
- TyDIE = new DIE(Ty.getTag());
- insertDIE(Ty, TyDIE);
+ TyDIE = createAndAddDIE(Ty.getTag(), *ContextDIE, Ty);
+
if (Ty.isBasicType())
constructTypeDIE(*TyDIE, DIBasicType(Ty));
else if (Ty.isCompositeType())
assert(Ty.isDerivedType() && "Unknown kind of DIType");
constructTypeDIE(*TyDIE, DIDerivedType(Ty));
}
- // If this is a named finished type then include it in the list of types
- // for the accelerator tables.
+
+ updateAcceleratorTables(Ty, TyDIE);
+
+ return TyDIE;
+}
+
+void CompileUnit::updateAcceleratorTables(DIType Ty, const DIE *TyDIE) {
if (!Ty.getName().empty() && !Ty.isForwardDecl()) {
bool IsImplementation = 0;
if (Ty.isCompositeType()) {
unsigned Flags = IsImplementation ? dwarf::DW_FLAG_type_implementation : 0;
addAccelType(Ty.getName(), std::make_pair(TyDIE, Flags));
}
-
- addToContextOwner(TyDIE, resolve(Ty.getContext()));
- return TyDIE;
}
/// addType - Add a new type attribute to the specified entity.
DIEEntry *Entry = getDIEEntry(Ty);
// If it exists then use the existing value.
if (Entry) {
- Entity->addValue(Attribute, dwarf::DW_FORM_ref4, Entry);
+ addDIEEntry(Entity, Attribute, Entry);
return;
}
// Set up proxy.
Entry = createDIEEntry(Buffer);
insertDIEEntry(Ty, Entry);
- Entity->addValue(Attribute, dwarf::DW_FORM_ref4, Entry);
+ addDIEEntry(Entity, Attribute, Entry);
// If this is a complete composite type then include it in the
// list of global types.
// DIE to the proper table while ensuring that the name that we're going
// to reference is in the string table. We do this since the names we
// add may not only be identical to the names in the DIE.
-void CompileUnit::addAccelName(StringRef Name, DIE *Die) {
+void CompileUnit::addAccelName(StringRef Name, const DIE *Die) {
DU->getStringPoolEntry(Name);
- std::vector<DIE *> &DIEs = AccelNames[Name];
+ std::vector<const DIE *> &DIEs = AccelNames[Name];
DIEs.push_back(Die);
}
-void CompileUnit::addAccelObjC(StringRef Name, DIE *Die) {
+void CompileUnit::addAccelObjC(StringRef Name, const DIE *Die) {
DU->getStringPoolEntry(Name);
- std::vector<DIE *> &DIEs = AccelObjC[Name];
+ std::vector<const DIE *> &DIEs = AccelObjC[Name];
DIEs.push_back(Die);
}
-void CompileUnit::addAccelNamespace(StringRef Name, DIE *Die) {
+void CompileUnit::addAccelNamespace(StringRef Name, const DIE *Die) {
DU->getStringPoolEntry(Name);
- std::vector<DIE *> &DIEs = AccelNamespace[Name];
+ std::vector<const DIE *> &DIEs = AccelNamespace[Name];
DIEs.push_back(Die);
}
-void CompileUnit::addAccelType(StringRef Name, std::pair<DIE *, unsigned> Die) {
+void CompileUnit::addAccelType(StringRef Name,
+ std::pair<const DIE *, unsigned> Die) {
DU->getStringPoolEntry(Name);
- std::vector<std::pair<DIE *, unsigned> > &DIEs = AccelTypes[Name];
+ std::vector<std::pair<const DIE *, unsigned> > &DIEs = AccelTypes[Name];
DIEs.push_back(Die);
}
/// Return true if the type should be split out into a type unit.
static bool shouldCreateTypeUnit(DICompositeType CTy, const DwarfDebug *DD) {
+ if (!GenerateTypeUnits)
+ return false;
+
uint16_t Tag = CTy.getTag();
switch (Tag) {
/// constructTypeDIE - Construct type DIE from DICompositeType.
void CompileUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) {
- // Get core information.
+ // If this is a type applicable to a type unit it then add it to the
+ // list of types we'll compute a hash for later.
+ if (shouldCreateTypeUnit(CTy, DD))
+ DD->addTypeUnitType(&Buffer, CTy);
+ else
+ constructTypeDIEImpl(Buffer, CTy);
+}
+
+void CompileUnit::constructTypeDIEImpl(DIE &Buffer, DICompositeType CTy) {
+ // Add name if not anonymous or intermediate type.
StringRef Name = CTy.getName();
uint64_t Size = CTy.getSizeInBits() >> 3;
switch (Tag) {
case dwarf::DW_TAG_array_type:
- constructArrayTypeDIE(Buffer, &CTy);
+ constructArrayTypeDIE(Buffer, CTy);
+ break;
+ case dwarf::DW_TAG_enumeration_type:
+ constructEnumTypeDIE(Buffer, CTy);
break;
- case dwarf::DW_TAG_enumeration_type: {
- DIArray Elements = CTy.getTypeArray();
-
- // Add enumerators to enumeration type.
- for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) {
- DIDescriptor Enum(Elements.getElement(i));
- if (Enum.isEnumerator())
- constructEnumTypeDIE(Buffer, DIEnumerator(Enum));
- }
- DIType DTy = resolve(CTy.getTypeDerivedFrom());
- if (DTy) {
- addType(&Buffer, DTy);
- addFlag(&Buffer, dwarf::DW_AT_enum_class);
- }
- } break;
case dwarf::DW_TAG_subroutine_type: {
// Add return type. A void return won't have a type.
DIArray Elements = CTy.getTypeArray();
- DIDescriptor RTy = Elements.getElement(0);
+ DIType RTy(Elements.getElement(0));
if (RTy)
- addType(&Buffer, DIType(RTy));
+ addType(&Buffer, RTy);
bool isPrototyped = true;
// Add arguments.
}
// Add prototype flag if we're dealing with a C language and the
// function has been prototyped.
- uint16_t Language = DICompileUnit(Node).getLanguage();
+ uint16_t Language = getLanguage();
if (isPrototyped &&
(Language == dwarf::DW_LANG_C89 || Language == dwarf::DW_LANG_C99 ||
Language == dwarf::DW_LANG_ObjC))
DIE *ElemDie = NULL;
if (Element.isSubprogram()) {
DISubprogram SP(Element);
- ElemDie = getOrCreateSubprogramDIE(DISubprogram(Element));
+ ElemDie = getOrCreateSubprogramDIE(SP);
if (SP.isProtected())
addUInt(ElemDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1,
dwarf::DW_ACCESS_protected);
addFlag(&Buffer, dwarf::DW_AT_APPLE_block);
DICompositeType ContainingType(resolve(CTy.getContainingType()));
- if (DIDescriptor(ContainingType).isCompositeType())
+ if (ContainingType)
addDIEEntry(&Buffer, dwarf::DW_AT_containing_type,
- getOrCreateTypeDIE(DIType(ContainingType)));
+ getOrCreateTypeDIE(ContainingType));
if (CTy.isObjcClassComplete())
addFlag(&Buffer, dwarf::DW_AT_APPLE_objc_complete_type);
addUInt(&Buffer, dwarf::DW_AT_APPLE_runtime_class, dwarf::DW_FORM_data1,
RLang);
}
- // If this is a type applicable to a type unit it then add it to the
- // list of types we'll compute a hash for later.
- if (shouldCreateTypeUnit(CTy, DD))
- DD->addTypeUnitType(&Buffer);
}
/// constructTemplateTypeParameterDIE - Construct new DIE for the given
// For declaration non-type template parameters (such as global values and
// functions)
DIEBlock *Block = new (DIEValueAllocator) DIEBlock();
- addOpAddress(Block, Asm->Mang->getSymbol(GV));
+ addOpAddress(Block, Asm->getSymbol(GV));
// Emit DW_OP_stack_value to use the address as the immediate value of the
// parameter, rather than a pointer to it.
addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_stack_value);
/// getOrCreateNameSpace - Create a DIE for DINameSpace.
DIE *CompileUnit::getOrCreateNameSpace(DINameSpace NS) {
+ // Construct the context before querying for the existence of the DIE in case
+ // such construction creates the DIE.
+ DIE *ContextDIE = getOrCreateContextDIE(NS.getContext());
+
DIE *NDie = getDIE(NS);
if (NDie)
return NDie;
- NDie = new DIE(dwarf::DW_TAG_namespace);
- insertDIE(NS, NDie);
+ NDie = createAndAddDIE(dwarf::DW_TAG_namespace, *ContextDIE, NS);
+
if (!NS.getName().empty()) {
addString(NDie, dwarf::DW_AT_name, NS.getName());
addAccelNamespace(NS.getName(), NDie);
} else
addAccelNamespace("(anonymous namespace)", NDie);
addSourceLine(NDie, NS);
- addToContextOwner(NDie, NS.getContext());
return NDie;
}
// such construction creates the DIE (as is the case for member function
// declarations).
DIE *ContextDIE = getOrCreateContextDIE(resolve(SP.getContext()));
- if (!ContextDIE)
- ContextDIE = CUDie.get();
DIE *SPDie = getDIE(SP);
if (SPDie)
return SPDie;
- SPDie = new DIE(dwarf::DW_TAG_subprogram);
+ DISubprogram SPDecl = SP.getFunctionDeclaration();
+ if (SPDecl.isSubprogram())
+ // Add subprogram definitions to the CU die directly.
+ ContextDIE = CUDie.get();
// DW_TAG_inlined_subroutine may refer to this DIE.
- insertDIE(SP, SPDie);
+ SPDie = createAndAddDIE(dwarf::DW_TAG_subprogram, *ContextDIE, SP);
- DISubprogram SPDecl = SP.getFunctionDeclaration();
DIE *DeclDie = NULL;
if (SPDecl.isSubprogram())
DeclDie = getOrCreateSubprogramDIE(SPDecl);
// Refer function declaration directly.
addDIEEntry(SPDie, dwarf::DW_AT_specification, DeclDie);
- // Add subprogram definitions to the CU die directly.
- addDie(SPDie);
-
return SPDie;
}
- // Add to context owner.
- ContextDIE->addChild(SPDie);
-
// Add the linkage name if we have one.
StringRef LinkageName = SP.getLinkageName();
if (!LinkageName.empty())
// Add the prototype if we have a prototype and we have a C like
// language.
- uint16_t Language = DICompileUnit(Node).getLanguage();
+ uint16_t Language = getLanguage();
if (SP.isPrototyped() &&
(Language == dwarf::DW_LANG_C89 || Language == dwarf::DW_LANG_C99 ||
Language == dwarf::DW_LANG_ObjC))
addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_constu);
addUInt(Block, dwarf::DW_FORM_udata, SP.getVirtualIndex());
addBlock(SPDie, dwarf::DW_AT_vtable_elem_location, Block);
- ContainingTypeMap.insert(std::make_pair(SPDie,
- resolve(SP.getContainingType())));
+ ContainingTypeMap.insert(
+ std::make_pair(SPDie, resolve(SP.getContainingType())));
}
if (!SP.isDefinition()) {
// be handled while processing variables.
for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) {
DIE *Arg = createAndAddDIE(dwarf::DW_TAG_formal_parameter, *SPDie);
- DIType ATy = DIType(Args.getElement(i));
+ DIType ATy(Args.getElement(i));
addType(Arg, ATy);
if (ATy.isArtificial())
addFlag(Arg, dwarf::DW_AT_artificial);
}
/// createGlobalVariableDIE - create global variable DIE.
-void CompileUnit::createGlobalVariableDIE(const MDNode *N) {
+void CompileUnit::createGlobalVariableDIE(DIGlobalVariable GV) {
// Check for pre-existence.
- if (getDIE(N))
+ if (getDIE(GV))
return;
- DIGlobalVariable GV(N);
if (!GV.isGlobalVariable())
return;
// 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());
+ // Construct the context before querying for the existence of the DIE in
+ // case such construction creates the DIE.
+ DIE *ContextDIE = getOrCreateContextDIE(GVContext);
+
// Add to map.
- insertDIE(N, VariableDIE);
+ VariableDIE = createAndAddDIE(GV.getTag(), *ContextDIE, GV);
// Add name and type.
addString(VariableDIE, dwarf::DW_AT_name, GV.getDisplayName());
// Add line number info.
addSourceLine(VariableDIE, GV);
- // Add to context owner.
- addToContextOwner(VariableDIE, GVContext);
}
// Add location.
if (isGlobalVariable) {
addToAccelTable = true;
DIEBlock *Block = new (DIEValueAllocator) DIEBlock();
- const MCSymbol *Sym = Asm->Mang->getSymbol(GV.getGlobal());
+ const MCSymbol *Sym = Asm->getSymbol(GV.getGlobal());
if (GV.getGlobal()->isThreadLocal()) {
// FIXME: Make this work with -gsplit-dwarf.
unsigned PointerSize = Asm->getDataLayout().getPointerSize();
if (GVContext && GV.isDefinition() && !GVContext.isCompileUnit() &&
!GVContext.isFile() && !DD->isSubprogramContext(GVContext)) {
// Create specification DIE.
- VariableSpecDIE = createAndAddDIE(dwarf::DW_TAG_variable, *CUDie.get());
+ VariableSpecDIE = createAndAddDIE(dwarf::DW_TAG_variable, *CUDie);
addDIEEntry(VariableSpecDIE, dwarf::DW_AT_specification, VariableDIE);
addBlock(VariableSpecDIE, dwarf::DW_AT_location, Block);
// A static member's declaration is already flagged as such.
// it is not a static member.
if (!IsStaticMember)
addConstantValue(VariableDIE, CI, isUnsignedDIType(DD, GTy));
- } else if (const ConstantExpr *CE = getMergedGlobalExpr(N->getOperand(11))) {
+ } else if (const ConstantExpr *CE = getMergedGlobalExpr(GV->getOperand(11))) {
addToAccelTable = true;
// GV is a merged global.
DIEBlock *Block = new (DIEValueAllocator) DIEBlock();
Value *Ptr = CE->getOperand(0);
- addOpAddress(Block, Asm->Mang->getSymbol(cast<GlobalValue>(Ptr)));
+ addOpAddress(Block, Asm->getSymbol(cast<GlobalValue>(Ptr)));
addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_constu);
SmallVector<Value *, 3> Idx(CE->op_begin() + 1, CE->op_end());
addUInt(Block, dwarf::DW_FORM_udata,
if (Count != -1 && Count != 0)
// FIXME: An unbounded array should reference the expression that defines
// the array.
- addUInt(DW_Subrange, dwarf::DW_AT_upper_bound, None, LowerBound + Count - 1);
+ addUInt(DW_Subrange, dwarf::DW_AT_upper_bound, None,
+ LowerBound + Count - 1);
}
/// constructArrayTypeDIE - Construct array type DIE from DICompositeType.
-void CompileUnit::constructArrayTypeDIE(DIE &Buffer, DICompositeType *CTy) {
- if (CTy->isVector())
+void CompileUnit::constructArrayTypeDIE(DIE &Buffer, DICompositeType CTy) {
+ if (CTy.isVector())
addFlag(&Buffer, dwarf::DW_AT_GNU_vector);
// Emit the element type.
- addType(&Buffer, resolve(CTy->getTypeDerivedFrom()));
+ addType(&Buffer, resolve(CTy.getTypeDerivedFrom()));
// Get an anonymous type for index type.
// FIXME: This type should be passed down from the front end
}
// Add subranges to array type.
- DIArray Elements = CTy->getTypeArray();
+ DIArray Elements = CTy.getTypeArray();
for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) {
DIDescriptor Element = Elements.getElement(i);
if (Element.getTag() == dwarf::DW_TAG_subrange_type)
}
}
-/// constructEnumTypeDIE - Construct enum type DIE from DIEnumerator.
-void CompileUnit::constructEnumTypeDIE(DIE &Buffer, DIEnumerator ETy) {
- DIE *Enumerator = createAndAddDIE(dwarf::DW_TAG_enumerator, Buffer);
- StringRef Name = ETy.getName();
- addString(Enumerator, dwarf::DW_AT_name, Name);
- int64_t Value = ETy.getEnumValue();
- addSInt(Enumerator, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, Value);
+/// constructEnumTypeDIE - Construct an enum type DIE from DICompositeType.
+void CompileUnit::constructEnumTypeDIE(DIE &Buffer, DICompositeType CTy) {
+ DIArray Elements = CTy.getTypeArray();
+
+ // Add enumerators to enumeration type.
+ for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) {
+ DIEnumerator Enum(Elements.getElement(i));
+ if (Enum.isEnumerator()) {
+ DIE *Enumerator = createAndAddDIE(dwarf::DW_TAG_enumerator, Buffer);
+ StringRef Name = Enum.getName();
+ addString(Enumerator, dwarf::DW_AT_name, Name);
+ int64_t Value = Enum.getEnumValue();
+ addSInt(Enumerator, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata,
+ Value);
+ }
+ }
+ DIType DTy = resolve(CTy.getTypeDerivedFrom());
+ if (DTy) {
+ addType(&Buffer, DTy);
+ addFlag(&Buffer, dwarf::DW_AT_enum_class);
+ }
}
/// constructContainingTypeDIEs - Construct DIEs for types that contain
CE = ContainingTypeMap.end();
CI != CE; ++CI) {
DIE *SPDie = CI->first;
- const MDNode *N = CI->second;
- if (!N)
+ DIDescriptor D(CI->second);
+ if (!D)
continue;
- DIE *NDie = getDIE(N);
+ DIE *NDie = getDIE(D);
if (!NDie)
continue;
addDIEEntry(SPDie, dwarf::DW_AT_containing_type, NDie);
}
/// constructVariableDIE - Construct a DIE for the given DbgVariable.
-DIE *CompileUnit::constructVariableDIE(DbgVariable *DV, bool isScopeAbstract) {
- StringRef Name = DV->getName();
+DIE *CompileUnit::constructVariableDIE(DbgVariable &DV, bool isScopeAbstract) {
+ StringRef Name = DV.getName();
// Define variable debug information entry.
- DIE *VariableDie = new DIE(DV->getTag());
- DbgVariable *AbsVar = DV->getAbstractVariable();
+ DIE *VariableDie = new DIE(DV.getTag());
+ DbgVariable *AbsVar = DV.getAbstractVariable();
DIE *AbsDIE = AbsVar ? AbsVar->getDIE() : NULL;
if (AbsDIE)
addDIEEntry(VariableDie, dwarf::DW_AT_abstract_origin, AbsDIE);
else {
if (!Name.empty())
addString(VariableDie, dwarf::DW_AT_name, Name);
- addSourceLine(VariableDie, DV->getVariable());
- addType(VariableDie, DV->getType());
+ addSourceLine(VariableDie, DV.getVariable());
+ addType(VariableDie, DV.getType());
}
- if (DV->isArtificial())
+ if (DV.isArtificial())
addFlag(VariableDie, dwarf::DW_AT_artificial);
if (isScopeAbstract) {
- DV->setDIE(VariableDie);
+ DV.setDIE(VariableDie);
return VariableDie;
}
// Add variable address.
- unsigned Offset = DV->getDotDebugLocOffset();
+ unsigned Offset = DV.getDotDebugLocOffset();
if (Offset != ~0U) {
- addLabel(VariableDie, dwarf::DW_AT_location, dwarf::DW_FORM_data4,
- Asm->GetTempSymbol("debug_loc", Offset));
- DV->setDIE(VariableDie);
+ addSectionLabel(VariableDie, dwarf::DW_AT_location,
+ Asm->GetTempSymbol("debug_loc", Offset));
+ DV.setDIE(VariableDie);
return VariableDie;
}
// Check if variable is described by a DBG_VALUE instruction.
- if (const MachineInstr *DVInsn = DV->getMInsn()) {
+ if (const MachineInstr *DVInsn = DV.getMInsn()) {
assert(DVInsn->getNumOperands() == 3);
if (DVInsn->getOperand(0).isReg()) {
const MachineOperand RegOp = DVInsn->getOperand(0);
if (DVInsn->getOperand(1).isImm()) {
MachineLocation Location(RegOp.getReg(),
DVInsn->getOperand(1).getImm());
- addVariableAddress(*DV, VariableDie, Location);
+ addVariableAddress(DV, VariableDie, Location);
} else if (RegOp.getReg())
- addVariableAddress(*DV, VariableDie, MachineLocation(RegOp.getReg()));
+ addVariableAddress(DV, VariableDie, MachineLocation(RegOp.getReg()));
} else if (DVInsn->getOperand(0).isImm())
- addConstantValue(VariableDie, DVInsn->getOperand(0), DV->getType());
+ addConstantValue(VariableDie, DVInsn->getOperand(0), DV.getType());
else if (DVInsn->getOperand(0).isFPImm())
addConstantFPValue(VariableDie, DVInsn->getOperand(0));
else if (DVInsn->getOperand(0).isCImm())
addConstantValue(VariableDie, DVInsn->getOperand(0).getCImm(),
- isUnsignedDIType(DD, DV->getType()));
+ isUnsignedDIType(DD, DV.getType()));
- DV->setDIE(VariableDie);
+ DV.setDIE(VariableDie);
return VariableDie;
} else {
// .. else use frame index.
- int FI = DV->getFrameIndex();
+ int FI = DV.getFrameIndex();
if (FI != ~0) {
unsigned FrameReg = 0;
const TargetFrameLowering *TFI = Asm->TM.getFrameLowering();
int Offset = TFI->getFrameIndexReference(*Asm->MF, FI, FrameReg);
MachineLocation Location(FrameReg, Offset);
- addVariableAddress(*DV, VariableDie, Location);
+ addVariableAddress(DV, VariableDie, Location);
}
}
- DV->setDIE(VariableDie);
+ DV.setDIE(VariableDie);
return VariableDie;
}
DIEBlock *MemLocationDie = new (DIEValueAllocator) DIEBlock();
addUInt(MemLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
- uint64_t Size = DT.getSizeInBits();
- uint64_t FieldSize = getBaseTypeSize(DD, DT);
-
- if (Size != FieldSize) {
- // Handle bitfield.
- addUInt(MemberDie, dwarf::DW_AT_byte_size, None,
- getBaseTypeSize(DD, DT) >> 3);
- addUInt(MemberDie, dwarf::DW_AT_bit_size, None, DT.getSizeInBits());
-
- uint64_t Offset = DT.getOffsetInBits();
- uint64_t AlignMask = ~(DT.getAlignInBits() - 1);
- uint64_t HiMark = (Offset + FieldSize) & AlignMask;
- uint64_t FieldOffset = (HiMark - FieldSize);
- Offset -= FieldOffset;
-
- // Maybe we need to work from the other end.
- if (Asm->getDataLayout().isLittleEndian())
- Offset = FieldSize - (Offset + Size);
- addUInt(MemberDie, dwarf::DW_AT_bit_offset, None, Offset);
-
- // Here WD_AT_data_member_location points to the anonymous
- // field that includes this bit field.
- addUInt(MemLocationDie, dwarf::DW_FORM_udata, FieldOffset >> 3);
-
- } else
- // This is not a bitfield.
- addUInt(MemLocationDie, dwarf::DW_FORM_udata, DT.getOffsetInBits() >> 3);
-
if (DT.getTag() == dwarf::DW_TAG_inheritance && DT.isVirtual()) {
// For C++, virtual base classes are not at fixed offset. Use following
addUInt(VBaseLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_plus);
addBlock(MemberDie, dwarf::DW_AT_data_member_location, VBaseLocationDie);
- } else
- addBlock(MemberDie, dwarf::DW_AT_data_member_location, MemLocationDie);
+ } else {
+ uint64_t Size = DT.getSizeInBits();
+ uint64_t FieldSize = getBaseTypeSize(DD, DT);
+ uint64_t OffsetInBytes;
+
+ if (Size != FieldSize) {
+ // Handle bitfield.
+ addUInt(MemberDie, dwarf::DW_AT_byte_size, None,
+ getBaseTypeSize(DD, DT) >> 3);
+ addUInt(MemberDie, dwarf::DW_AT_bit_size, None, DT.getSizeInBits());
+
+ uint64_t Offset = DT.getOffsetInBits();
+ uint64_t AlignMask = ~(DT.getAlignInBits() - 1);
+ uint64_t HiMark = (Offset + FieldSize) & AlignMask;
+ uint64_t FieldOffset = (HiMark - FieldSize);
+ Offset -= FieldOffset;
+
+ // Maybe we need to work from the other end.
+ if (Asm->getDataLayout().isLittleEndian())
+ Offset = FieldSize - (Offset + Size);
+ addUInt(MemberDie, dwarf::DW_AT_bit_offset, None, Offset);
+
+ // Here WD_AT_data_member_location points to the anonymous
+ // field that includes this bit field.
+ OffsetInBytes = FieldOffset >> 3;
+ } else
+ // This is not a bitfield.
+ OffsetInBytes = DT.getOffsetInBits() >> 3;
+ addUInt(MemberDie, dwarf::DW_AT_data_member_location, None, OffsetInBytes);
+ }
if (DT.isProtected())
addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1,
}
/// getOrCreateStaticMemberDIE - Create new DIE for C++ static member.
-DIE *CompileUnit::getOrCreateStaticMemberDIE(const DIDerivedType DT) {
+DIE *CompileUnit::getOrCreateStaticMemberDIE(DIDerivedType DT) {
if (!DT.Verify())
return NULL;
// Construct the context before querying for the existence of the DIE in case
// such construction creates the DIE.
DIE *ContextDIE = getOrCreateContextDIE(resolve(DT.getContext()));
- assert(ContextDIE && "Static member should belong to a non-CU context.");
+ assert(dwarf::isType(ContextDIE->getTag()) &&
+ "Static member should belong to a type.");
DIE *StaticMemberDIE = getDIE(DT);
if (StaticMemberDIE)
return StaticMemberDIE;
}
+
+void CompileUnit::emitHeader(const MCSection *ASection,
+ const MCSymbol *ASectionSym) {
+ Asm->OutStreamer.AddComment("DWARF version number");
+ Asm->EmitInt16(DD->getDwarfVersion());
+ Asm->OutStreamer.AddComment("Offset Into Abbrev. Section");
+ Asm->EmitSectionOffset(Asm->GetTempSymbol(ASection->getLabelBeginName()),
+ ASectionSym);
+ Asm->OutStreamer.AddComment("Address Size (in bytes)");
+ Asm->EmitInt8(Asm->getDataLayout().getPointerSize());
+}