#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),
- DebugInfoOffset(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(DIDescriptor(N), D);
}
/// ~CompileUnit - Destructor for compile unit.
/// 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.
- return D.isType() ||
- (D.isSubprogram() && !DISubprogram(D).isDefinition());
+ // 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
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,
DIEEntry *Entry) {
- const DIE *DieCU = Die->getCompileUnitOrNull();
- const DIE *EntryCU = Entry->getEntry()->getCompileUnitOrNull();
+ 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();
/// 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(DIDescriptor(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.
return getDIE(Context);
}
+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) {
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));
}
-
- return TyDIE;
}
/// addType - Add a new type attribute to the specified entity.
// 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;
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.
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
// 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) {
- DIGlobalVariable GV(N);
-
+void CompileUnit::createGlobalVariableDIE(DIGlobalVariable GV) {
// Check for pre-existence.
if (getDIE(GV))
return;
DIE *ContextDIE = getOrCreateContextDIE(GVContext);
// Add to map.
- VariableDIE = createAndAddDIE(GV.getTag(), *ContextDIE, N);
+ VariableDIE = createAndAddDIE(GV.getTag(), *ContextDIE, GV);
// Add name and type.
addString(VariableDIE, dwarf::DW_AT_name, GV.getDisplayName());
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();
// Add enumerators to enumeration type.
for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) {
- DIDescriptor Enum(Elements.getElement(i));
- DIEnumerator ETy = DIEnumerator(Enum);
+ DIEnumerator Enum(Elements.getElement(i));
if (Enum.isEnumerator()) {
DIE *Enumerator = createAndAddDIE(dwarf::DW_TAG_enumerator, Buffer);
- StringRef Name = ETy.getName();
+ StringRef Name = Enum.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);
+ int64_t Value = Enum.getEnumValue();
+ addSInt(Enumerator, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata,
+ Value);
}
}
DIType DTy = resolve(CTy.getTypeDerivedFrom());
unsigned Offset = DV.getDotDebugLocOffset();
if (Offset != ~0U) {
- addLabel(VariableDie, dwarf::DW_AT_location, dwarf::DW_FORM_data4,
- Asm->GetTempSymbol("debug_loc", Offset));
+ addSectionLabel(VariableDie, dwarf::DW_AT_location,
+ Asm->GetTempSymbol("debug_loc", Offset));
DV.setDIE(VariableDie);
return VariableDie;
}