DwarfCompileUnit.cpp [plain text]
#include "DwarfCompileUnit.h"
#include "DwarfExpression.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instruction.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Target/TargetFrameLowering.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetSubtargetInfo.h"
namespace llvm {
DwarfCompileUnit::DwarfCompileUnit(unsigned UID, const DICompileUnit *Node,
AsmPrinter *A, DwarfDebug *DW,
DwarfFile *DWU)
: DwarfUnit(UID, dwarf::DW_TAG_compile_unit, Node, A, DW, DWU),
Skeleton(nullptr), BaseAddress(nullptr) {
insertDIE(Node, &getUnitDie());
}
void DwarfCompileUnit::addLabelAddress(DIE &Die, dwarf::Attribute Attribute,
const MCSymbol *Label) {
if (!DD->useSplitDwarf() || !Skeleton)
return addLocalLabelAddress(Die, Attribute, Label);
if (Label)
DD->addArangeLabel(SymbolCU(this, Label));
unsigned idx = DD->getAddressPool().getIndex(Label);
DIEValue *Value = new (DIEValueAllocator) DIEInteger(idx);
Die.addValue(Attribute, dwarf::DW_FORM_GNU_addr_index, Value, &DIEsToDelete);
}
void DwarfCompileUnit::addLocalLabelAddress(DIE &Die,
dwarf::Attribute Attribute,
const MCSymbol *Label) {
if (Label)
DD->addArangeLabel(SymbolCU(this, Label));
Die.addValue(Attribute, dwarf::DW_FORM_addr,
Label ? (DIEValue *)new (DIEValueAllocator) DIELabel(Label)
: new (DIEValueAllocator) DIEInteger(0),
&DIEsToDelete);
}
unsigned DwarfCompileUnit::getOrCreateSourceID(StringRef FileName,
StringRef DirName) {
return Asm->OutStreamer.EmitDwarfFileDirective(
0, DirName, FileName,
Asm->OutStreamer.hasRawTextSupport() ? 0 : getUniqueID());
}
static const ConstantExpr *getMergedGlobalExpr(const Value *V) {
const ConstantExpr *CE = dyn_cast_or_null<ConstantExpr>(V);
if (!CE || CE->getNumOperands() != 3 ||
CE->getOpcode() != Instruction::GetElementPtr)
return nullptr;
Value *Ptr = CE->getOperand(0);
if (!isa<GlobalValue>(Ptr) ||
!isa<StructType>(cast<PointerType>(Ptr->getType())->getElementType()))
return nullptr;
const ConstantInt *CI = dyn_cast_or_null<ConstantInt>(CE->getOperand(1));
if (!CI || !CI->isZero())
return nullptr;
if (!isa<ConstantInt>(CE->getOperand(2)))
return nullptr;
return CE;
}
DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
const DIGlobalVariable *GV) {
if (DIE *Die = getDIE(GV))
return Die;
assert(GV);
auto *GVContext = GV->getScope();
auto *GTy = DD->resolve(GV->getType());
DIE *ContextDIE = getOrCreateContextDIE(GVContext);
DIE *VariableDIE = &createAndAddDIE(GV->getTag(), *ContextDIE, GV);
DIScope *DeclContext;
if (auto *SDMDecl = GV->getStaticDataMemberDeclaration()) {
DeclContext = resolve(SDMDecl->getScope());
assert(SDMDecl->isStaticMember() && "Expected static member decl");
assert(GV->isDefinition());
DIE *VariableSpecDIE = getOrCreateStaticMemberDIE(SDMDecl);
addDIEEntry(*VariableDIE, dwarf::DW_AT_specification, *VariableSpecDIE);
} else {
DeclContext = GV->getScope();
addString(*VariableDIE, dwarf::DW_AT_name, GV->getDisplayName());
addType(*VariableDIE, GTy);
if (!GV->isLocalToUnit())
addFlag(*VariableDIE, dwarf::DW_AT_external);
addSourceLine(*VariableDIE, GV);
}
if (!GV->isDefinition())
addFlag(*VariableDIE, dwarf::DW_AT_declaration);
bool addToAccelTable = false;
if (auto *Global = dyn_cast_or_null<GlobalVariable>(GV->getVariable())) {
addToAccelTable = true;
DIELoc *Loc = new (DIEValueAllocator) DIELoc();
const MCSymbol *Sym = Asm->getSymbol(Global);
if (Global->isThreadLocal()) {
unsigned PointerSize = Asm->getDataLayout().getPointerSize();
assert((PointerSize == 4 || PointerSize == 8) &&
"Add support for other sizes if necessary");
if (!DD->useSplitDwarf()) {
addUInt(*Loc, dwarf::DW_FORM_data1,
PointerSize == 4 ? dwarf::DW_OP_const4u : dwarf::DW_OP_const8u);
addExpr(*Loc, dwarf::DW_FORM_udata,
Asm->getObjFileLowering().getDebugThreadLocalSymbol(Sym));
} else {
addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_const_index);
addUInt(*Loc, dwarf::DW_FORM_udata,
DD->getAddressPool().getIndex(Sym, true));
}
addUInt(*Loc, dwarf::DW_FORM_data1,
DD->useGNUTLSOpcode() ? dwarf::DW_OP_GNU_push_tls_address
: dwarf::DW_OP_form_tls_address);
} else {
DD->addArangeLabel(SymbolCU(this, Sym));
addOpAddress(*Loc, Sym);
}
addBlock(*VariableDIE, dwarf::DW_AT_location, Loc);
addLinkageName(*VariableDIE, GV->getLinkageName());
} else if (const ConstantInt *CI =
dyn_cast_or_null<ConstantInt>(GV->getVariable())) {
addConstantValue(*VariableDIE, CI, GTy);
} else if (const ConstantExpr *CE = getMergedGlobalExpr(GV->getVariable())) {
addToAccelTable = true;
DIELoc *Loc = new (DIEValueAllocator) DIELoc();
Value *Ptr = CE->getOperand(0);
MCSymbol *Sym = Asm->getSymbol(cast<GlobalValue>(Ptr));
DD->addArangeLabel(SymbolCU(this, Sym));
addOpAddress(*Loc, Sym);
addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_constu);
SmallVector<Value *, 3> Idx(CE->op_begin() + 1, CE->op_end());
addUInt(*Loc, dwarf::DW_FORM_udata,
Asm->getDataLayout().getIndexedOffset(Ptr->getType(), Idx));
addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus);
addBlock(*VariableDIE, dwarf::DW_AT_location, Loc);
}
if (addToAccelTable) {
DD->addAccelName(GV->getName(), *VariableDIE);
if (GV->getLinkageName() != "" && GV->getName() != GV->getLinkageName())
DD->addAccelName(GV->getLinkageName(), *VariableDIE);
}
addGlobalName(GV->getName(), *VariableDIE, DeclContext);
return VariableDIE;
}
void DwarfCompileUnit::addRange(RangeSpan Range) {
bool SameAsPrevCU = this == DD->getPrevCU();
DD->setPrevCU(this);
if (CURanges.empty() || !SameAsPrevCU ||
(&CURanges.back().getEnd()->getSection() !=
&Range.getEnd()->getSection())) {
CURanges.push_back(Range);
return;
}
CURanges.back().setEnd(Range.getEnd());
}
void DwarfCompileUnit::addSectionLabel(DIE &Die, dwarf::Attribute Attribute,
const MCSymbol *Label,
const MCSymbol *Sec) {
if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
addLabel(Die, Attribute,
DD->getDwarfVersion() >= 4 ? dwarf::DW_FORM_sec_offset
: dwarf::DW_FORM_data4,
Label);
else
addSectionDelta(Die, Attribute, Label, Sec);
}
void DwarfCompileUnit::initStmtList() {
MCSymbol *LineTableStartSym =
Asm->OutStreamer.getDwarfLineTableSymbol(getUniqueID());
stmtListIndex = UnitDie->getValues().size();
const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
addSectionLabel(*UnitDie, dwarf::DW_AT_stmt_list, LineTableStartSym,
TLOF.getDwarfLineSection()->getBeginSymbol());
}
void DwarfCompileUnit::applyStmtList(DIE &D) {
D.addValue(dwarf::DW_AT_stmt_list,
UnitDie->getAbbrev().getData()[stmtListIndex].getForm(),
UnitDie->getValues()[stmtListIndex],
&DIEsToDelete);
}
void DwarfCompileUnit::attachLowHighPC(DIE &D, const MCSymbol *Begin,
const MCSymbol *End) {
assert(Begin && "Begin label should not be null!");
assert(End && "End label should not be null!");
assert(Begin->isDefined() && "Invalid starting label");
assert(End->isDefined() && "Invalid end label");
addLabelAddress(D, dwarf::DW_AT_low_pc, Begin);
if (DD->getDwarfVersion() < 4)
addLabelAddress(D, dwarf::DW_AT_high_pc, End);
else
addLabelDelta(D, dwarf::DW_AT_high_pc, End, Begin);
}
DIE &DwarfCompileUnit::updateSubprogramScopeDIE(const DISubprogram *SP) {
DIE *SPDie = getOrCreateSubprogramDIE(SP, includeMinimalInlineScopes());
attachLowHighPC(*SPDie, Asm->getFunctionBegin(), Asm->getFunctionEnd());
if (!DD->getCurrentFunction()->getTarget().Options.DisableFramePointerElim(
*DD->getCurrentFunction()))
addFlag(*SPDie, dwarf::DW_AT_APPLE_omit_frame_ptr);
if (!includeMinimalInlineScopes()) {
const TargetRegisterInfo *RI = Asm->MF->getSubtarget().getRegisterInfo();
MachineLocation Location(RI->getFrameRegister(*Asm->MF));
if (RI->isPhysicalRegister(Location.getReg()))
addAddress(*SPDie, dwarf::DW_AT_frame_base, Location);
}
DD->addSubprogramNames(SP, *SPDie);
return *SPDie;
}
void DwarfCompileUnit::constructScopeDIE(
LexicalScope *Scope, SmallVectorImpl<DIE *> &FinalChildren) {
if (!Scope || !Scope->getScopeNode())
return;
auto *DS = Scope->getScopeNode();
assert((Scope->getInlinedAt() || !isa<DISubprogram>(DS)) &&
"Only handle inlined subprograms here, use "
"constructSubprogramScopeDIE for non-inlined "
"subprograms");
SmallVector<DIE *, 8> Children;
DIE *ScopeDIE;
if (Scope->getParent() && isa<DISubprogram>(DS)) {
ScopeDIE = constructInlinedScopeDIE(Scope);
if (!ScopeDIE)
return;
createScopeChildrenDIE(Scope, Children);
} else {
if (DD->isLexicalScopeDIENull(Scope))
return;
unsigned ChildScopeCount;
createScopeChildrenDIE(Scope, Children, &ChildScopeCount);
if (!includeMinimalInlineScopes()) {
for (const auto &E : DD->findImportedEntitiesForScope(DS))
Children.push_back(
constructImportedEntityDIE(cast<DIImportedEntity>(E.second)));
}
if (Children.size() == ChildScopeCount) {
FinalChildren.insert(FinalChildren.end(),
std::make_move_iterator(Children.begin()),
std::make_move_iterator(Children.end()));
return;
}
ScopeDIE = constructLexicalScopeDIE(Scope);
assert(ScopeDIE && "Scope DIE should not be null.");
}
for (auto &I : Children)
ScopeDIE->addChild(std::move(I));
FinalChildren.push_back(std::move(ScopeDIE));
}
void DwarfCompileUnit::addSectionDelta(DIE &Die, dwarf::Attribute Attribute,
const MCSymbol *Hi, const MCSymbol *Lo) {
DIEValue *Value = new (DIEValueAllocator) DIEDelta(Hi, Lo);
Die.addValue(Attribute, DD->getDwarfVersion() >= 4 ? dwarf::DW_FORM_sec_offset
: dwarf::DW_FORM_data4,
Value, &DIEsToDelete);
}
void DwarfCompileUnit::addScopeRangeList(DIE &ScopeDIE,
SmallVector<RangeSpan, 2> Range) {
const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
const MCSymbol *RangeSectionSym =
TLOF.getDwarfRangesSection()->getBeginSymbol();
RangeSpanList List(
Asm->GetTempSymbol("debug_ranges", DD->getNextRangeNumber()),
std::move(Range));
if (isDwoUnit())
addSectionDelta(ScopeDIE, dwarf::DW_AT_ranges, List.getSym(),
RangeSectionSym);
else
addSectionLabel(ScopeDIE, dwarf::DW_AT_ranges, List.getSym(),
RangeSectionSym);
(Skeleton ? Skeleton : this)->CURangeLists.push_back(std::move(List));
}
void DwarfCompileUnit::attachRangesOrLowHighPC(
DIE &Die, SmallVector<RangeSpan, 2> Ranges) {
if (Ranges.size() == 1) {
const auto &single = Ranges.front();
attachLowHighPC(Die, single.getStart(), single.getEnd());
} else
addScopeRangeList(Die, std::move(Ranges));
}
void DwarfCompileUnit::attachRangesOrLowHighPC(
DIE &Die, const SmallVectorImpl<InsnRange> &Ranges) {
SmallVector<RangeSpan, 2> List;
List.reserve(Ranges.size());
for (const InsnRange &R : Ranges)
List.push_back(RangeSpan(DD->getLabelBeforeInsn(R.first),
DD->getLabelAfterInsn(R.second)));
attachRangesOrLowHighPC(Die, std::move(List));
}
DIE *
DwarfCompileUnit::constructInlinedScopeDIE(LexicalScope *Scope) {
assert(Scope->getScopeNode());
auto *DS = Scope->getScopeNode();
auto *InlinedSP = getDISubprogram(DS);
DIE *OriginDIE = DU->getAbstractSPDies()[InlinedSP];
assert(OriginDIE && "Unable to find original DIE for an inlined subprogram.");
auto ScopeDIE = new (DIEValueAllocator) DIE(dwarf::DW_TAG_inlined_subroutine);
addDIEEntry(*ScopeDIE, dwarf::DW_AT_abstract_origin, *OriginDIE);
attachRangesOrLowHighPC(*ScopeDIE, Scope->getRanges());
const DILocation *IA = Scope->getInlinedAt();
addUInt(*ScopeDIE, dwarf::DW_AT_call_file, None,
getOrCreateSourceID(IA->getFilename(), IA->getDirectory()));
addUInt(*ScopeDIE, dwarf::DW_AT_call_line, None, IA->getLine());
DD->addSubprogramNames(InlinedSP, *ScopeDIE);
return ScopeDIE;
}
DIE *
DwarfCompileUnit::constructLexicalScopeDIE(LexicalScope *Scope) {
if (DD->isLexicalScopeDIENull(Scope))
return nullptr;
auto ScopeDIE = new (DIEValueAllocator) DIE(dwarf::DW_TAG_lexical_block);
if (Scope->isAbstractScope())
return ScopeDIE;
attachRangesOrLowHighPC(*ScopeDIE, Scope->getRanges());
return ScopeDIE;
}
DIE *DwarfCompileUnit::constructVariableDIE(DbgVariable &DV,
bool Abstract) {
auto D = constructVariableDIEImpl(DV, Abstract);
DV.setDIE(*D);
return D;
}
DIE *
DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,
bool Abstract) {
auto *VariableDie = new (DIEValueAllocator) DIE(DV.getTag());
if (Abstract) {
applyVariableAttributes(DV, *VariableDie);
return VariableDie;
}
unsigned Offset = DV.getDebugLocListIndex();
if (Offset != ~0U) {
addLocationList(*VariableDie, dwarf::DW_AT_location, Offset);
return VariableDie;
}
if (const MachineInstr *DVInsn = DV.getMInsn()) {
assert(DVInsn->getNumOperands() == 4);
if (DVInsn->getOperand(0).isReg()) {
const MachineOperand RegOp = DVInsn->getOperand(0);
if (DVInsn->getOperand(1).isImm()) {
MachineLocation Location(RegOp.getReg(),
DVInsn->getOperand(1).getImm());
addVariableAddress(DV, *VariableDie, Location);
} else if (RegOp.getReg())
addVariableAddress(DV, *VariableDie, MachineLocation(RegOp.getReg()));
} else if (DVInsn->getOperand(0).isImm())
addConstantValue(*VariableDie, DVInsn->getOperand(0), DV.getType());
else if (DVInsn->getOperand(0).isFPImm())
addConstantFPValue(*VariableDie, DVInsn->getOperand(0));
else if (DVInsn->getOperand(0).isCImm())
addConstantValue(*VariableDie, DVInsn->getOperand(0).getCImm(),
DV.getType());
return VariableDie;
}
if (DV.getFrameIndex().back() == ~0)
return VariableDie;
auto Expr = DV.getExpression().begin();
DIELoc *Loc = new (DIEValueAllocator) DIELoc();
DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
for (auto FI : DV.getFrameIndex()) {
unsigned FrameReg = 0;
const TargetFrameLowering *TFI = Asm->MF->getSubtarget().getFrameLowering();
int Offset = TFI->getFrameIndexReference(*Asm->MF, FI, FrameReg);
assert(Expr != DV.getExpression().end() &&
"Wrong number of expressions");
DwarfExpr.AddMachineRegIndirect(FrameReg, Offset);
DwarfExpr.AddExpression((*Expr)->expr_op_begin(), (*Expr)->expr_op_end());
++Expr;
}
addBlock(*VariableDie, dwarf::DW_AT_location, Loc);
return VariableDie;
}
DIE *DwarfCompileUnit::constructVariableDIE(
DbgVariable &DV, const LexicalScope &Scope, DIE *&ObjectPointer) {
auto Var = constructVariableDIE(DV, Scope.isAbstractScope());
if (DV.isObjectPointer())
ObjectPointer = Var;
return Var;
}
DIE *DwarfCompileUnit::createScopeChildrenDIE(
LexicalScope *Scope, SmallVectorImpl<DIE *> &Children,
unsigned *ChildScopeCount) {
DIE *ObjectPointer = nullptr;
for (DbgVariable *DV : DU->getScopeVariables().lookup(Scope))
Children.push_back(constructVariableDIE(*DV, *Scope, ObjectPointer));
unsigned ChildCountWithoutScopes = Children.size();
for (LexicalScope *LS : Scope->getChildren())
constructScopeDIE(LS, Children);
if (ChildScopeCount)
*ChildScopeCount = Children.size() - ChildCountWithoutScopes;
return ObjectPointer;
}
void DwarfCompileUnit::constructSubprogramScopeDIE(LexicalScope *Scope) {
assert(Scope && Scope->getScopeNode());
assert(!Scope->getInlinedAt());
assert(!Scope->isAbstractScope());
auto *Sub = cast<DISubprogram>(Scope->getScopeNode());
DD->getProcessedSPNodes().insert(Sub);
DIE &ScopeDIE = updateSubprogramScopeDIE(Sub);
DITypeRefArray FnArgs = Sub->getType()->getTypeArray();
if (DIE *ObjectPointer = createAndAddScopeChildren(Scope, ScopeDIE))
addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, *ObjectPointer);
if (FnArgs.size() > 1 && !FnArgs[FnArgs.size() - 1] &&
!includeMinimalInlineScopes())
ScopeDIE.addChild(new (DIEValueAllocator) DIE(dwarf::DW_TAG_unspecified_parameters));
}
DIE *DwarfCompileUnit::createAndAddScopeChildren(LexicalScope *Scope,
DIE &ScopeDIE) {
SmallVector<DIE *, 8> Children;
DIE *ObjectPointer = createScopeChildrenDIE(Scope, Children);
for (auto &I : Children)
ScopeDIE.addChild(std::move(I));
return ObjectPointer;
}
void
DwarfCompileUnit::constructAbstractSubprogramScopeDIE(LexicalScope *Scope) {
DIE *&AbsDef = DU->getAbstractSPDies()[Scope->getScopeNode()];
if (AbsDef)
return;
auto *SP = cast<DISubprogram>(Scope->getScopeNode());
DIE *ContextDIE;
if (includeMinimalInlineScopes())
ContextDIE = &getUnitDie();
else if (auto *SPDecl = SP->getDeclaration()) {
ContextDIE = &getUnitDie();
getOrCreateSubprogramDIE(SPDecl);
} else
ContextDIE = getOrCreateContextDIE(resolve(SP->getScope()));
AbsDef = &createAndAddDIE(dwarf::DW_TAG_subprogram, *ContextDIE, nullptr);
applySubprogramAttributesToDefinition(SP, *AbsDef);
if (!includeMinimalInlineScopes())
addUInt(*AbsDef, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined);
if (DIE *ObjectPointer = createAndAddScopeChildren(Scope, *AbsDef))
addDIEEntry(*AbsDef, dwarf::DW_AT_object_pointer, *ObjectPointer);
}
DIE *DwarfCompileUnit::constructImportedEntityDIE(
const DIImportedEntity *Module) {
DIE *IMDie = new (DIEValueAllocator) DIE((dwarf::Tag)Module->getTag());
insertDIE(Module, IMDie);
DIE *EntityDie;
auto *Entity = resolve(Module->getEntity());
if (auto *ETR = dyn_cast<DICompositeType>(Entity))
if (ETR->isExternalTypeRef()) {
StringRef UID = ETR->getIdentifier();
addString(*IMDie, dwarf::DW_AT_import, UID);
DD->addAccelExternalType(UID, ETR->getFilename());
addSourceLine(*IMDie, Module->getLine(), Module->getScope()->getFilename(),
Module->getScope()->getDirectory());
return IMDie;
}
if (auto *NS = dyn_cast<DINamespace>(Entity))
EntityDie = getOrCreateNameSpace(NS);
else if (auto *M = dyn_cast<DIModule>(Entity))
EntityDie = getOrCreateModule(M);
else if (auto *SP = dyn_cast<DISubprogram>(Entity))
EntityDie = getOrCreateSubprogramDIE(SP);
else if (auto *T = dyn_cast<DIType>(Entity))
EntityDie = getOrCreateTypeDIE(T);
else if (auto *GV = dyn_cast<DIGlobalVariable>(Entity))
EntityDie = getOrCreateGlobalVariableDIE(GV);
else
EntityDie = getDIE(Entity);
assert(EntityDie);
addSourceLine(*IMDie, Module->getLine(), Module->getScope()->getFilename(),
Module->getScope()->getDirectory());
addDIEEntry(*IMDie, dwarf::DW_AT_import, *EntityDie);
StringRef Name = Module->getName();
if (!Name.empty())
addString(*IMDie, dwarf::DW_AT_name, Name);
return IMDie;
}
void DwarfCompileUnit::finishSubprogramDefinition(const DISubprogram *SP) {
DIE *D = getDIE(SP);
if (DIE *AbsSPDIE = DU->getAbstractSPDies().lookup(SP)) {
if (D)
addDIEEntry(*D, dwarf::DW_AT_abstract_origin, *AbsSPDIE);
} else {
if (!D && !includeMinimalInlineScopes())
D = getOrCreateSubprogramDIE(SP);
if (D)
applySubprogramAttributesToDefinition(SP, *D);
}
}
void DwarfCompileUnit::collectDeadVariables(const DISubprogram *SP) {
assert(SP && "CU's subprogram list contains a non-subprogram");
assert(SP->isDefinition() &&
"CU's subprogram list contains a subprogram declaration");
auto Variables = SP->getVariables();
if (Variables.size() == 0)
return;
DIE *SPDIE = DU->getAbstractSPDies().lookup(SP);
if (!SPDIE)
SPDIE = getDIE(SP);
assert(SPDIE);
for (const DILocalVariable *DV : Variables) {
DbgVariable NewVar(DV, nullptr, nullptr, DD);
auto VariableDie = constructVariableDIE(NewVar);
applyVariableAttributes(NewVar, *VariableDie);
SPDIE->addChild(std::move(VariableDie));
}
}
void DwarfCompileUnit::emitHeader(bool UseOffsets) {
if (!Skeleton) {
LabelBegin = Asm->createTempSymbol("cu_begin", getUniqueID());
Asm->OutStreamer.EmitLabel(LabelBegin);
}
DwarfUnit::emitHeader(UseOffsets);
}
void DwarfCompileUnit::addGlobalName(StringRef Name, DIE &Die,
const DIScope *Context) {
if (includeMinimalInlineScopes())
return;
std::string FullName = getParentContextString(Context) + Name.str();
GlobalNames[FullName] = &Die;
}
void DwarfCompileUnit::addGlobalType(const DIType *Ty, const DIE &Die,
const DIScope *Context) {
if (includeMinimalInlineScopes())
return;
std::string FullName = getParentContextString(Context) + Ty->getName().str();
GlobalTypes[FullName] = &Die;
}
void DwarfCompileUnit::addVariableAddress(const DbgVariable &DV, DIE &Die,
MachineLocation Location) {
if (DV.variableHasComplexAddress())
addComplexAddress(DV, Die, dwarf::DW_AT_location, Location);
else if (DV.isBlockByrefVariable())
addBlockByrefAddress(DV, Die, dwarf::DW_AT_location, Location);
else
addAddress(Die, dwarf::DW_AT_location, Location);
}
void DwarfCompileUnit::addAddress(DIE &Die, dwarf::Attribute Attribute,
const MachineLocation &Location) {
DIELoc *Loc = new (DIEValueAllocator) DIELoc();
bool validReg;
if (Location.isReg())
validReg = addRegisterOpPiece(*Loc, Location.getReg());
else
validReg = addRegisterOffset(*Loc, Location.getReg(), Location.getOffset());
if (!validReg)
return;
addBlock(Die, Attribute, Loc);
}
void DwarfCompileUnit::addComplexAddress(const DbgVariable &DV, DIE &Die,
dwarf::Attribute Attribute,
const MachineLocation &Location) {
DIELoc *Loc = new (DIEValueAllocator) DIELoc();
DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
assert(DV.getExpression().size() == 1);
const DIExpression *Expr = DV.getExpression().back();
bool ValidReg;
if (Location.getOffset()) {
ValidReg = DwarfExpr.AddMachineRegIndirect(Location.getReg(),
Location.getOffset());
if (ValidReg)
DwarfExpr.AddExpression(Expr->expr_op_begin(), Expr->expr_op_end());
} else
ValidReg = DwarfExpr.AddMachineRegExpression(Expr, Location.getReg());
if (ValidReg)
addBlock(Die, Attribute, Loc);
}
void DwarfCompileUnit::addLocationList(DIE &Die, dwarf::Attribute Attribute,
unsigned Index) {
DIEValue *Value = new (DIEValueAllocator) DIELocList(Index);
dwarf::Form Form = DD->getDwarfVersion() >= 4 ? dwarf::DW_FORM_sec_offset
: dwarf::DW_FORM_data4;
Die.addValue(Attribute, Form, Value, &DIEsToDelete);
}
void DwarfCompileUnit::applyVariableAttributes(const DbgVariable &Var,
DIE &VariableDie) {
StringRef Name = Var.getName();
if (!Name.empty())
addString(VariableDie, dwarf::DW_AT_name, Name);
addSourceLine(VariableDie, Var.getVariable());
addType(VariableDie, Var.getType());
if (Var.isArtificial())
addFlag(VariableDie, dwarf::DW_AT_artificial);
}
void DwarfCompileUnit::addExpr(DIELoc &Die, dwarf::Form Form,
const MCExpr *Expr) {
DIEValue *Value = new (DIEValueAllocator) DIEExpr(Expr);
Die.addValue((dwarf::Attribute)0, Form, Value, &DIEsToDelete);
}
void DwarfCompileUnit::applySubprogramAttributesToDefinition(
const DISubprogram *SP, DIE &SPDie) {
auto *SPDecl = SP->getDeclaration();
auto *Context = resolve(SPDecl ? SPDecl->getScope() : SP->getScope());
applySubprogramAttributes(SP, SPDie, includeMinimalInlineScopes());
addGlobalName(SP->getName(), SPDie, Context);
}
bool DwarfCompileUnit::isDwoUnit() const {
return DD->useSplitDwarf() && Skeleton;
}
bool DwarfCompileUnit::includeMinimalInlineScopes() const {
return getCUNode()->getEmissionKind() == DIBuilder::LineTablesOnly ||
(DD->useSplitDwarf() && !Skeleton);
}
}