#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCTargetOptionsCommandFlags.h"
#include "llvm/Object/MachO.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/LEB128.h"
/// \brief Emit the abbreviation table \p Abbrevs to the
/// debug_abbrev section.
- void emitAbbrevs(const std::vector<DIEAbbrev *> &Abbrevs);
+ void emitAbbrevs(const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs);
/// \brief Emit the string table described by \p Pool.
void emitStrings(const NonRelocatableStringpool &Pool);
if (EC)
return error(Twine(OutputFilename) + ": " + EC.message(), Context);
- MS = TheTarget->createMCObjectStreamer(TheTriple, *MC, *MAB, *OutFile, MCE,
- *MSTI, false,
- /*DWARFMustBeAtTheEnd*/ false);
+ MCTargetOptions MCOptions = InitMCTargetOptionsFromFlags();
+ MS = TheTarget->createMCObjectStreamer(
+ TheTriple, *MC, *MAB, *OutFile, MCE, *MSTI, MCOptions.MCRelaxAll,
+ MCOptions.MCIncrementalLinkerCompatible,
+ /*DWARFMustBeAtTheEnd*/ false);
if (!MS)
return error("no object streamer for target " + TripleName, Context);
/// \brief Emit the \p Abbrevs array as the shared abbreviation table
/// for the linked Dwarf file.
-void DwarfStreamer::emitAbbrevs(const std::vector<DIEAbbrev *> &Abbrevs) {
+void DwarfStreamer::emitAbbrevs(
+ const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs) {
MS->SwitchSection(MOFI->getDwarfAbbrevSection());
Asm->emitDwarfAbbrevs(Abbrevs);
}
: OutputFilename(OutputFilename), Options(Options),
BinHolder(Options.Verbose), LastCIEOffset(0) {}
- ~DwarfLinker() {
- for (auto *Abbrev : Abbreviations)
- delete Abbrev;
- }
-
/// \brief Link the contents of the DebugMap.
bool link(const DebugMap &);
/// \brief Storage for the unique Abbreviations.
/// This is passed to AsmPrinter::emitDwarfAbbrevs(), thus it cannot
/// be changed to a vecot of unique_ptrs.
- std::vector<DIEAbbrev *> Abbreviations;
+ std::vector<std::unique_ptr<DIEAbbrev>> Abbreviations;
/// \brief Compute and emit debug_ranges section for \p Unit, and
/// patch the attributes referencing it.
/// The units of the current debug map object.
std::vector<CompileUnit> Units;
- /// The debug map object curently under consideration.
+ /// The debug map object currently under consideration.
DebugMapObject *CurrentDebugObject;
/// \brief The Dwarf string pool
DIE->getAttributeValueAsUnsignedConstant(
&CU.getOrigUnit(), dwarf::DW_AT_declaration, 0);
+ // Don't prune it if there is no definition for the DIE.
+ Info.Prune &= Info.Ctxt && Info.Ctxt->getCanonicalDIEOffset();
+
return Info.Prune;
}
Info.Ctxt->getCanonicalDIEOffset() && isODRAttribute(AttrSpec.Attr))
continue;
- Info.Prune = false;
+ // Keep a module forward declaration if there is no definition.
+ if (!(isODRAttribute(AttrSpec.Attr) && Info.Ctxt &&
+ Info.Ctxt->getCanonicalDIEOffset()))
+ Info.Prune = false;
+
unsigned ODRFlag = UseODR ? TF_ODR : 0;
lookForDIEsToKeep(RelocMgr, *RefDIE, DMO, *ReferencedCU,
TF_Keep | TF_DependencyWalk | ODRFlag);
} else {
// Add to abbreviation list.
Abbreviations.push_back(
- new DIEAbbrev(Abbrev.getTag(), Abbrev.hasChildren()));
+ llvm::make_unique<DIEAbbrev>(Abbrev.getTag(), Abbrev.hasChildren()));
for (const auto &Attr : Abbrev.getData())
Abbreviations.back()->AddAttribute(Attr.getAttribute(), Attr.getForm());
- AbbreviationsSet.InsertNode(Abbreviations.back(), InsertToken);
+ AbbreviationsSet.InsertNode(Abbreviations.back().get(), InsertToken);
// Assign the unique abbreviation number.
Abbrev.setNumber(Abbreviations.size());
Abbreviations.back()->setNumber(Abbreviations.size());
Unit.addTypeAccelerator(Die, AttrInfo.Name, AttrInfo.NameOffset);
}
+ // Determine whether there are any children that we want to keep.
+ bool HasChildren = false;
+ for (auto *Child = InputDIE.getFirstChild(); Child && !Child->isNULL();
+ Child = Child->getSibling()) {
+ unsigned Idx = U.getDIEIndex(Child);
+ if (Unit.getInfo(Idx).Keep) {
+ HasChildren = true;
+ break;
+ }
+ }
+
DIEAbbrev NewAbbrev = Die->generateAbbrev();
- // If a scope DIE is kept, we must have kept at least one child. If
- // it's not the case, we'll just be emitting one wasteful end of
- // children marker, but things won't break.
- if (InputDIE.hasChildren())
+ if (HasChildren)
NewAbbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes);
// Assign a permanent abbrev number
Linker.AssignAbbrev(NewAbbrev);
// Add the size of the abbreviation number to the output offset.
OutOffset += getULEB128Size(Die->getAbbrevNumber());
- if (!Abbrev->hasChildren()) {
+ if (!HasChildren) {
// Update our size.
Die->setSize(OutOffset - Die->getOffset());
return Die;
uint64_t OrigLowPc = OrigUnitDie->getAttributeValueAsAddress(
&OrigUnit, dwarf::DW_AT_low_pc, -1ULL);
// Ranges addresses are based on the unit's low_pc. Compute the
- // offset we need to apply to adapt to the the new unit's low_pc.
+ // offset we need to apply to adapt to the new unit's low_pc.
int64_t UnitPcOffset = 0;
if (OrigLowPc != -1ULL)
UnitPcOffset = int64_t(OrigLowPc) - Unit.getLowPc();
DWARFContextInMemory DwarfContext(*ErrOrObj);
startDebugObject(DwarfContext, *Obj);
- // In a first phase, just read in the debug info and store the DIE
- // parent links that we will use during the next phase.
+ // In a first phase, just read in the debug info and load all clang modules.
for (const auto &CU : DwarfContext.compile_units()) {
auto *CUDie = CU->getUnitDIE(false);
if (Options.Verbose) {
outs() << "Input compilation unit:";
CUDie->dump(outs(), CU.get(), 0);
}
- if (!registerModuleReference(*CUDie, *CU, ModuleMap)) {
+
+ if (!registerModuleReference(*CUDie, *CU, ModuleMap))
Units.emplace_back(*CU, UnitID++, !Options.NoODR, "");
- analyzeContextInfo(CUDie, 0, Units.back(), &ODRContexts.getRoot(),
- StringPool, ODRContexts);
- }
}
+ // Now build the DIE parent links that we will use during the next phase.
+ for (auto &CurrentUnit : Units)
+ analyzeContextInfo(CurrentUnit.getOrigUnit().getUnitDIE(), 0, CurrentUnit,
+ &ODRContexts.getRoot(), StringPool, ODRContexts);
+
// Then mark all the DIEs that need to be present in the linked
// output and collect some information about them. Note that this
// loop can not be merged with the previous one becaue cross-cu