#include "DwarfFile.h"
#include "DwarfCompileUnit.h"
#include "DwarfDebug.h"
#include "DwarfUnit.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/MC/MCStreamer.h"
#include <cstdint>
using namespace llvm;
DwarfFile::DwarfFile(AsmPrinter *AP, StringRef Pref, BumpPtrAllocator &DA)
: Asm(AP), Abbrevs(AbbrevAllocator), StrPool(DA, *Asm, Pref) {}
void DwarfFile::addUnit(std::unique_ptr<DwarfCompileUnit> U) {
CUs.push_back(std::move(U));
}
void DwarfFile::emitUnits(bool UseOffsets) {
for (const auto &TheU : CUs)
emitUnit(TheU.get(), UseOffsets);
}
void DwarfFile::emitUnit(DwarfUnit *TheU, bool UseOffsets) {
if (TheU->getCUNode()->isDebugDirectivesOnly())
return;
MCSection *S = TheU->getSection();
if (!S)
return;
if (llvm::empty(TheU->getUnitDie().values()))
return;
Asm->OutStreamer->switchSection(S);
TheU->emitHeader(UseOffsets);
Asm->emitDwarfDIE(TheU->getUnitDie());
if (MCSymbol *EndLabel = TheU->getEndLabel())
Asm->OutStreamer->emitLabel(EndLabel);
}
void DwarfFile::computeSizeAndOffsets() {
uint64_t SecOffset = 0;
for (const auto &TheU : CUs) {
if (TheU->getCUNode()->isDebugDirectivesOnly())
continue;
if (llvm::empty(TheU->getUnitDie().values()))
return;
TheU->setDebugSectionOffset(SecOffset);
SecOffset += computeSizeAndOffsetsForUnit(TheU.get());
}
if (SecOffset > UINT32_MAX && !Asm->isDwarf64())
report_fatal_error("The generated debug information is too large "
"for the 32-bit DWARF format.");
}
unsigned DwarfFile::computeSizeAndOffsetsForUnit(DwarfUnit *TheU) {
unsigned Offset = Asm->getUnitLengthFieldByteSize() + TheU->getHeaderSize();
return computeSizeAndOffset(TheU->getUnitDie(), Offset);
}
unsigned DwarfFile::computeSizeAndOffset(DIE &Die, unsigned Offset) {
return Die.computeOffsetsAndAbbrevs(Asm->getDwarfFormParams(), Abbrevs,
Offset);
}
void DwarfFile::emitAbbrevs(MCSection *Section) { Abbrevs.Emit(Asm, Section); }
void DwarfFile::emitStrings(MCSection *StrSection, MCSection *OffsetSection,
bool UseRelativeOffsets) {
StrPool.emit(*Asm, StrSection, OffsetSection, UseRelativeOffsets);
}
bool DwarfFile::addScopeVariable(LexicalScope *LS, DbgVariable *Var) {
auto &ScopeVars = ScopeVariables[LS];
const DILocalVariable *DV = Var->getVariable();
if (unsigned ArgNum = DV->getArg()) {
auto Cached = ScopeVars.Args.find(ArgNum);
if (Cached == ScopeVars.Args.end())
ScopeVars.Args[ArgNum] = Var;
else {
Cached->second->addMMIEntry(*Var);
return false;
}
} else {
ScopeVars.Locals.push_back(Var);
}
return true;
}
void DwarfFile::addScopeLabel(LexicalScope *LS, DbgLabel *Label) {
SmallVectorImpl<DbgLabel *> &Labels = ScopeLabels[LS];
Labels.push_back(Label);
}
std::pair<uint32_t, RangeSpanList *>
DwarfFile::addRange(const DwarfCompileUnit &CU, SmallVector<RangeSpan, 2> R) {
CURangeLists.push_back(
RangeSpanList{Asm->createTempSymbol("debug_ranges"), &CU, std::move(R)});
return std::make_pair(CURangeLists.size() - 1, &CURangeLists.back());
}