#include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
#include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
namespace llvm {
static bool inFunctionScope(CompileUnit &U, unsigned Idx) {
while (Idx) {
if (U.getOrigUnit().getDIEAtIndex(Idx).getTag() == dwarf::DW_TAG_subprogram)
return true;
Idx = U.getInfo(Idx).ParentIdx;
}
return false;
}
uint16_t CompileUnit::getLanguage() {
if (!Language) {
DWARFDie CU = getOrigUnit().getUnitDIE();
Language = dwarf::toUnsigned(CU.find(dwarf::DW_AT_language), 0);
}
return Language;
}
StringRef CompileUnit::getSysRoot() {
if (SysRoot.empty()) {
DWARFDie CU = getOrigUnit().getUnitDIE();
SysRoot = dwarf::toStringRef(CU.find(dwarf::DW_AT_LLVM_sysroot)).str();
}
return SysRoot;
}
void CompileUnit::markEverythingAsKept() {
unsigned Idx = 0;
for (auto &I : Info) {
I.Keep = !I.Prune;
auto DIE = OrigUnit.getDIEAtIndex(Idx++);
if (DIE.getTag() != dwarf::DW_TAG_variable &&
DIE.getTag() != dwarf::DW_TAG_constant)
continue;
Optional<DWARFFormValue> Value;
if (!(Value = DIE.find(dwarf::DW_AT_location))) {
if ((Value = DIE.find(dwarf::DW_AT_const_value)) &&
!inFunctionScope(*this, I.ParentIdx))
I.InDebugMap = true;
continue;
}
if (auto Block = Value->getAsBlock()) {
if (Block->size() > OrigUnit.getAddressByteSize() &&
(*Block)[0] == dwarf::DW_OP_addr)
I.InDebugMap = true;
}
}
}
uint64_t CompileUnit::computeNextUnitOffset(uint16_t DwarfVersion) {
NextUnitOffset = StartOffset;
if (NewUnit) {
NextUnitOffset += (DwarfVersion >= 5) ? 12 : 11; NextUnitOffset += NewUnit->getUnitDie().getSize();
}
return NextUnitOffset;
}
void CompileUnit::noteForwardReference(DIE *Die, const CompileUnit *RefUnit,
DeclContext *Ctxt, PatchLocation Attr) {
ForwardDIEReferences.emplace_back(Die, RefUnit, Ctxt, Attr);
}
void CompileUnit::fixupForwardReferences() {
for (const auto &Ref : ForwardDIEReferences) {
DIE *RefDie;
const CompileUnit *RefUnit;
PatchLocation Attr;
DeclContext *Ctxt;
std::tie(RefDie, RefUnit, Ctxt, Attr) = Ref;
if (Ctxt && Ctxt->hasCanonicalDIE()) {
assert(Ctxt->getCanonicalDIEOffset() &&
"Canonical die offset is not set");
Attr.set(Ctxt->getCanonicalDIEOffset());
} else
Attr.set(RefDie->getOffset() + RefUnit->getStartOffset());
}
}
void CompileUnit::addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset) {
Labels.insert({LabelLowPc, PcOffset});
}
void CompileUnit::addFunctionRange(uint64_t FuncLowPc, uint64_t FuncHighPc,
int64_t PcOffset) {
Ranges.insert({FuncLowPc, FuncHighPc}, PcOffset);
this->LowPc = std::min(LowPc, FuncLowPc + PcOffset);
this->HighPc = std::max(HighPc, FuncHighPc + PcOffset);
}
void CompileUnit::noteRangeAttribute(const DIE &Die, PatchLocation Attr) {
if (Die.getTag() != dwarf::DW_TAG_compile_unit)
RangeAttributes.push_back(Attr);
else
UnitRangeAttribute = Attr;
}
void CompileUnit::noteLocationAttribute(PatchLocation Attr, int64_t PcOffset) {
LocationAttributes.emplace_back(Attr, PcOffset);
}
void CompileUnit::addNamespaceAccelerator(const DIE *Die,
DwarfStringPoolEntryRef Name) {
Namespaces.emplace_back(Name, Die);
}
void CompileUnit::addObjCAccelerator(const DIE *Die,
DwarfStringPoolEntryRef Name,
bool SkipPubSection) {
ObjC.emplace_back(Name, Die, SkipPubSection);
}
void CompileUnit::addNameAccelerator(const DIE *Die,
DwarfStringPoolEntryRef Name,
bool SkipPubSection) {
Pubnames.emplace_back(Name, Die, SkipPubSection);
}
void CompileUnit::addTypeAccelerator(const DIE *Die,
DwarfStringPoolEntryRef Name,
bool ObjcClassImplementation,
uint32_t QualifiedNameHash) {
Pubtypes.emplace_back(Name, Die, QualifiedNameHash, ObjcClassImplementation);
}
}