return ScopeDIE;
}
-DIE *DwarfDebug::createScopeChildrenDIE(DwarfCompileUnit &TheCU,
- LexicalScope *Scope,
- SmallVectorImpl<DIE *> &Children) {
+DIE *DwarfDebug::createScopeChildrenDIE(
+ DwarfCompileUnit &TheCU, LexicalScope *Scope,
+ SmallVectorImpl<std::unique_ptr<DIE>> &Children) {
DIE *ObjectPointer = nullptr;
// Collect arguments for current function.
if (LScopes.isCurrentFunctionScope(Scope)) {
for (DbgVariable *ArgDV : CurrentFnArguments)
- if (ArgDV)
- if (DIE *Arg =
- TheCU.constructVariableDIE(*ArgDV, Scope->isAbstractScope())) {
- Children.push_back(Arg);
- if (ArgDV->isObjectPointer())
- ObjectPointer = Arg;
- }
+ if (ArgDV) {
+ std::unique_ptr<DIE> Arg =
+ TheCU.constructVariableDIE(*ArgDV, Scope->isAbstractScope());
+ assert(Arg);
+ if (ArgDV->isObjectPointer())
+ ObjectPointer = Arg.get();
+ Children.push_back(std::move(Arg));
+ }
// If this is a variadic function, add an unspecified parameter.
DISubprogram SP(Scope->getScopeNode());
DIArray FnArgs = SP.getType().getTypeArray();
if (FnArgs.getElement(FnArgs.getNumElements() - 1)
.isUnspecifiedParameter()) {
- DIE *Ellipsis = new DIE(dwarf::DW_TAG_unspecified_parameters);
- Children.push_back(Ellipsis);
+ Children.push_back(
+ make_unique<DIE>(dwarf::DW_TAG_unspecified_parameters));
}
}
// Collect lexical scope children first.
- for (DbgVariable *DV : ScopeVariables.lookup(Scope))
- if (DIE *Variable =
- TheCU.constructVariableDIE(*DV, Scope->isAbstractScope())) {
- Children.push_back(Variable);
- if (DV->isObjectPointer())
- ObjectPointer = Variable;
- }
+ for (DbgVariable *DV : ScopeVariables.lookup(Scope)) {
+ std::unique_ptr<DIE> Variable =
+ TheCU.constructVariableDIE(*DV, Scope->isAbstractScope());
+ assert(Variable);
+ if (DV->isObjectPointer())
+ ObjectPointer = Variable.get();
+ Children.push_back(std::move(Variable));
+ }
for (LexicalScope *LS : Scope->getChildren())
if (DIE *Nested = constructScopeDIE(TheCU, LS))
- Children.push_back(Nested);
+ Children.push_back(std::unique_ptr<DIE>(Nested));
return ObjectPointer;
}
DIScope DS(Scope->getScopeNode());
- SmallVector<DIE *, 8> Children;
+ SmallVector<std::unique_ptr<DIE>, 8> Children;
DIE *ObjectPointer = nullptr;
bool ChildrenCreated = false;
ObjectPointer = createScopeChildrenDIE(TheCU, Scope, Children);
// Add children
- for (DIE *I : Children)
- ScopeDIE->addChild(I);
+ for (auto &I : Children)
+ ScopeDIE->addChild(std::move(I));
if (DS.isSubprogram() && ObjectPointer != nullptr)
TheCU.addDIEEntry(*ScopeDIE, dwarf::DW_AT_object_pointer, *ObjectPointer);
if (!DV.isVariable())
continue;
DbgVariable NewVar(DV, nullptr, this);
- if (DIE *VariableDIE = SPCU->constructVariableDIE(NewVar, false))
- SPDIE->addChild(VariableDIE);
+ SPDIE->addChild(SPCU->constructVariableDIE(NewVar, false));
}
}
}
const MCSymbol *End = Range.getEnd();
assert(Begin && "Range without a begin symbol?");
assert(End && "Range without an end symbol?");
- Asm->OutStreamer.EmitSymbolValue(Begin, Size);
- Asm->OutStreamer.EmitSymbolValue(End, Size);
+ if (TheCU->getRanges().size() == 1) {
+ // Grab the begin symbol from the first range as our base.
+ const MCSymbol *Base = TheCU->getRanges()[0].getStart();
+ Asm->EmitLabelDifference(Begin, Base, Size);
+ Asm->EmitLabelDifference(End, Base, Size);
+ } else {
+ Asm->OutStreamer.EmitSymbolValue(Begin, Size);
+ Asm->OutStreamer.EmitSymbolValue(End, Size);
+ }
}
// And terminate the list with two 0 values.
return &SplitTypeUnitFileTable;
}
+static uint64_t makeTypeSignature(StringRef Identifier) {
+ MD5 Hash;
+ Hash.update(Identifier);
+ // ... take the least significant 8 bytes and return those. Our MD5
+ // implementation always returns its results in little endian, swap bytes
+ // appropriately.
+ MD5::MD5Result Result;
+ Hash.final(Result);
+ return *reinterpret_cast<support::ulittle64_t *>(Result + 8);
+}
+
void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
StringRef Identifier, DIE &RefDie,
DICompositeType CTy) {
- // Flag the type unit reference as a declaration so that if it contains
- // members (implicit special members, static data member definitions, member
- // declarations for definitions in this CU, etc) consumers don't get confused
- // and think this is a full definition.
- CU.addFlag(RefDie, dwarf::DW_AT_declaration);
+ // Fast path if we're building some type units and one has already used the
+ // address pool we know we're going to throw away all this work anyway, so
+ // don't bother building dependent types.
+ if (!TypeUnitsUnderConstruction.empty() && AddrPool.hasBeenUsed())
+ return;
const DwarfTypeUnit *&TU = DwarfTypeUnits[CTy];
if (TU) {
return;
}
+ bool TopLevelType = TypeUnitsUnderConstruction.empty();
+ AddrPool.resetUsedFlag();
+
DIE *UnitDie = new DIE(dwarf::DW_TAG_type_unit);
auto OwnedUnit =
make_unique<DwarfTypeUnit>(InfoHolder.getUnits().size(), UnitDie, CU, Asm,
this, &InfoHolder, getDwoLineTable(CU));
DwarfTypeUnit &NewTU = *OwnedUnit;
TU = &NewTU;
- InfoHolder.addUnit(std::move(OwnedUnit));
+ TypeUnitsUnderConstruction.push_back(std::make_pair(std::move(OwnedUnit), CTy));
NewTU.addUInt(*UnitDie, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
CU.getLanguage());
- MD5 Hash;
- Hash.update(Identifier);
- // ... take the least significant 8 bytes and return those. Our MD5
- // implementation always returns its results in little endian, swap bytes
- // appropriately.
- MD5::MD5Result Result;
- Hash.final(Result);
- uint64_t Signature = *reinterpret_cast<support::ulittle64_t *>(Result + 8);
+ uint64_t Signature = makeTypeSignature(Identifier);
NewTU.setTypeSignature(Signature);
- if (useSplitDwarf())
- NewTU.setSkeleton(constructSkeletonTU(NewTU));
- else
- CU.applyStmtList(*UnitDie);
- NewTU.setType(NewTU.createTypeDIE(CTy));
+ if (!useSplitDwarf())
+ CU.applyStmtList(*UnitDie);
NewTU.initSection(
useSplitDwarf()
? Asm->getObjFileLowering().getDwarfTypesDWOSection(Signature)
: Asm->getObjFileLowering().getDwarfTypesSection(Signature));
+ NewTU.setType(NewTU.createTypeDIE(CTy));
+
+ if (TopLevelType) {
+ auto TypeUnitsToAdd = std::move(TypeUnitsUnderConstruction);
+ TypeUnitsUnderConstruction.clear();
+
+ // Types referencing entries in the address table cannot be placed in type
+ // units.
+ if (AddrPool.hasBeenUsed()) {
+
+ // Remove all the types built while building this type.
+ // This is pessimistic as some of these types might not be dependent on
+ // the type that used an address.
+ for (const auto &TU : TypeUnitsToAdd)
+ DwarfTypeUnits.erase(TU.second);
+
+ // Construct this type in the CU directly.
+ // This is inefficient because all the dependent types will be rebuilt
+ // from scratch, including building them in type units, discovering that
+ // they depend on addresses, throwing them out and rebuilding them.
+ CU.constructTypeDIE(RefDie, CTy);
+ return;
+ }
+
+ // If the type wasn't dependent on fission addresses, finish adding the type
+ // and all its dependent types.
+ for (auto &TU : TypeUnitsToAdd) {
+ if (useSplitDwarf())
+ TU.first->setSkeleton(constructSkeletonTU(*TU.first));
+ InfoHolder.addUnit(std::move(TU.first));
+ }
+ }
CU.addDIETypeSignature(RefDie, NewTU);
}
void DwarfDebug::addAccelName(StringRef Name, const DIE &Die) {
if (!useDwarfAccelTables())
return;
- InfoHolder.getStringPoolEntry(Name);
- AccelNames.AddName(Name, &Die);
+ AccelNames.AddName(Name, InfoHolder.getStringPool().getSymbol(*Asm, Name),
+ &Die);
}
void DwarfDebug::addAccelObjC(StringRef Name, const DIE &Die) {
if (!useDwarfAccelTables())
return;
- InfoHolder.getStringPoolEntry(Name);
- AccelObjC.AddName(Name, &Die);
+ AccelObjC.AddName(Name, InfoHolder.getStringPool().getSymbol(*Asm, Name),
+ &Die);
}
void DwarfDebug::addAccelNamespace(StringRef Name, const DIE &Die) {
if (!useDwarfAccelTables())
return;
- InfoHolder.getStringPoolEntry(Name);
- AccelNamespace.AddName(Name, &Die);
+ AccelNamespace.AddName(Name, InfoHolder.getStringPool().getSymbol(*Asm, Name),
+ &Die);
}
void DwarfDebug::addAccelType(StringRef Name, const DIE &Die, char Flags) {
if (!useDwarfAccelTables())
return;
- InfoHolder.getStringPoolEntry(Name);
- AccelTypes.AddName(Name, &Die, Flags);
+ AccelTypes.AddName(Name, InfoHolder.getStringPool().getSymbol(*Asm, Name),
+ &Die);
}