summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
diff options
context:
space:
mode:
authorAdrian Prantl <aprantl@apple.com>2016-12-20 02:09:43 +0000
committerAdrian Prantl <aprantl@apple.com>2016-12-20 02:09:43 +0000
commitbceaaa9643609088b20a51d2c34b3c411185a3c0 (patch)
tree0522b0bc96fc25520b0d342c2e41fdc9ede93451 /llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
parent6db6efd40c46d4e54a302ac1227d1818fe28965d (diff)
downloadbcm5719-llvm-bceaaa9643609088b20a51d2c34b3c411185a3c0.tar.gz
bcm5719-llvm-bceaaa9643609088b20a51d2c34b3c411185a3c0.zip
[IR] Remove the DIExpression field from DIGlobalVariable.
This patch implements PR31013 by introducing a DIGlobalVariableExpression that holds a pair of DIGlobalVariable and DIExpression. Currently, DIGlobalVariables holds a DIExpression. This is not the best way to model this: (1) The DIGlobalVariable should describe the source level variable, not how to get to its location. (2) It makes it unsafe/hard to update the expressions when we call replaceExpression on the DIGLobalVariable. (3) It makes it impossible to represent a global variable that is in more than one location (e.g., a variable with multiple DW_OP_LLVM_fragment-s). We also moved away from attaching the DIExpression to DILocalVariable for the same reasons. This reapplies r289902 with additional testcase upgrades and a change to the Bitcode record for DIGlobalVariable, that makes upgrading the old format unambiguous also for variables without DIExpressions. <rdar://problem/29250149> https://llvm.org/bugs/show_bug.cgi?id=31013 Differential Revision: https://reviews.llvm.org/D26769 llvm-svn: 290153
Diffstat (limited to 'llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp130
1 files changed, 66 insertions, 64 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index 5f9506cd540..0db623bbc29 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -73,9 +73,8 @@ unsigned DwarfCompileUnit::getOrCreateSourceID(StringRef FileName,
Asm->OutStreamer->hasRawTextSupport() ? 0 : getUniqueID());
}
-/// getOrCreateGlobalVariableDIE - get or create global variable DIE.
DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
- const DIGlobalVariable *GV, const GlobalVariable *Global) {
+ const DIGlobalVariable *GV, ArrayRef<GlobalExpr> GlobalExprs) {
// Check for pre-existence.
if (DIE *Die = getDIE(GV))
return Die;
@@ -128,69 +127,76 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
// Add location.
bool addToAccelTable = false;
-
- DIExpression *Expr = GV->getExpr();
-
- // For compatibility with DWARF 3 and earlier,
- // DW_AT_location(DW_OP_constu, X, DW_OP_stack_value) becomes
- // DW_AT_const_value(X).
- if (Expr && Expr->getNumElements() == 3 &&
- Expr->getElement(0) == dwarf::DW_OP_constu &&
- Expr->getElement(2) == dwarf::DW_OP_stack_value) {
- addConstantValue(*VariableDIE, /*Unsigned=*/true, Expr->getElement(1));
- // We cannot describe the location of dllimport'd variables: the computation
- // of their address requires loads from the IAT.
- } else if (!Global || !Global->hasDLLImportStorageClass()) {
- DIELoc *Loc = new (DIEValueAllocator) DIELoc;
- if (Global) {
+ DIELoc *Loc = nullptr;
+ std::unique_ptr<DIEDwarfExpression> DwarfExpr;
+ bool AllConstant = std::all_of(
+ GlobalExprs.begin(), GlobalExprs.end(),
+ [&](const GlobalExpr GE) {
+ return GE.Expr && GE.Expr->isConstant();
+ });
+
+ for (const auto &GE : GlobalExprs) {
+ const GlobalVariable *Global = GE.Var;
+ const DIExpression *Expr = GE.Expr;
+ // For compatibility with DWARF 3 and earlier,
+ // DW_AT_location(DW_OP_constu, X, DW_OP_stack_value) becomes
+ // DW_AT_const_value(X).
+ if (GlobalExprs.size() == 1 && Expr && Expr->isConstant()) {
+ addConstantValue(*VariableDIE, /*Unsigned=*/true, Expr->getElement(1));
+ // We cannot describe the location of dllimport'd variables: the
+ // computation of their address requires loads from the IAT.
+ } else if ((Global && !Global->hasDLLImportStorageClass()) || AllConstant) {
+ if (!Loc) {
+ Loc = new (DIEValueAllocator) DIELoc;
+ DwarfExpr = llvm::make_unique<DIEDwarfExpression>(*Asm, *this, *Loc);
+ }
addToAccelTable = true;
- const MCSymbol *Sym = Asm->getSymbol(Global);
- if (Global->isThreadLocal()) {
- if (Asm->TM.Options.EmulatedTLS) {
- // TODO: add debug info for emulated thread local mode.
- } else {
- // FIXME: Make this work with -gsplit-dwarf.
- unsigned PointerSize = Asm->getDataLayout().getPointerSize();
- assert((PointerSize == 4 || PointerSize == 8) &&
- "Add support for other sizes if necessary");
- // Based on GCC's support for TLS:
- if (!DD->useSplitDwarf()) {
- // 1) Start with a constNu of the appropriate pointer size
- addUInt(*Loc, dwarf::DW_FORM_data1, PointerSize == 4
- ? dwarf::DW_OP_const4u
- : dwarf::DW_OP_const8u);
- // 2) containing the (relocated) offset of the TLS variable
- // within the module's TLS block.
- addExpr(*Loc, dwarf::DW_FORM_udata,
- Asm->getObjFileLowering().getDebugThreadLocalSymbol(Sym));
+ if (Global) {
+ const MCSymbol *Sym = Asm->getSymbol(Global);
+ if (Global->isThreadLocal()) {
+ if (Asm->TM.Options.EmulatedTLS) {
+ // TODO: add debug info for emulated thread local mode.
} else {
- addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_const_index);
- addUInt(*Loc, dwarf::DW_FORM_udata,
- DD->getAddressPool().getIndex(Sym, /* TLS */ true));
+ // FIXME: Make this work with -gsplit-dwarf.
+ unsigned PointerSize = Asm->getDataLayout().getPointerSize();
+ assert((PointerSize == 4 || PointerSize == 8) &&
+ "Add support for other sizes if necessary");
+ // Based on GCC's support for TLS:
+ if (!DD->useSplitDwarf()) {
+ // 1) Start with a constNu of the appropriate pointer size
+ addUInt(*Loc, dwarf::DW_FORM_data1,
+ PointerSize == 4 ? dwarf::DW_OP_const4u
+ : dwarf::DW_OP_const8u);
+ // 2) containing the (relocated) offset of the TLS variable
+ // within the module's TLS block.
+ 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, /* TLS */ true));
+ }
+ // 3) followed by an OP to make the debugger do a TLS lookup.
+ addUInt(*Loc, dwarf::DW_FORM_data1,
+ DD->useGNUTLSOpcode() ? dwarf::DW_OP_GNU_push_tls_address
+ : dwarf::DW_OP_form_tls_address);
}
- // 3) followed by an OP to make the debugger do a TLS lookup.
- 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);
}
- } else {
- DD->addArangeLabel(SymbolCU(this, Sym));
- addOpAddress(*Loc, Sym);
}
-
if (Expr) {
- DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
- DwarfExpr.addFragmentOffset(Expr);
- DwarfExpr.AddExpression(Expr);
- DwarfExpr.finalize();
+ DwarfExpr->addFragmentOffset(Expr);
+ DwarfExpr->AddExpression(Expr);
}
}
-
- addBlock(*VariableDIE, dwarf::DW_AT_location, Loc);
-
- if (DD->useAllLinkageNames())
- addLinkageName(*VariableDIE, GV->getLinkageName());
}
+ if (Loc)
+ addBlock(*VariableDIE, dwarf::DW_AT_location, DwarfExpr->finalize());
+
+ if (DD->useAllLinkageNames())
+ addLinkageName(*VariableDIE, GV->getLinkageName());
if (addToAccelTable) {
DD->addAccelName(GV->getName(), *VariableDIE);
@@ -503,8 +509,7 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,
DwarfExpr.addFragmentOffset(Expr);
DwarfExpr.AddUnsignedConstant(DVInsn->getOperand(0).getImm());
DwarfExpr.AddExpression(Expr);
- DwarfExpr.finalize();
- addBlock(*VariableDie, dwarf::DW_AT_location, Loc);
+ addBlock(*VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize());
} else
addConstantValue(*VariableDie, DVInsn->getOperand(0), DV.getType());
} else if (DVInsn->getOperand(0).isFPImm())
@@ -534,8 +539,7 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,
DwarfExpr.AddExpression(*Expr);
++Expr;
}
- DwarfExpr.finalize();
- addBlock(*VariableDie, dwarf::DW_AT_location, Loc);
+ addBlock(*VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize());
return VariableDie;
}
@@ -654,7 +658,7 @@ DIE *DwarfCompileUnit::constructImportedEntityDIE(
else if (auto *T = dyn_cast<DIType>(Entity))
EntityDie = getOrCreateTypeDIE(T);
else if (auto *GV = dyn_cast<DIGlobalVariable>(Entity))
- EntityDie = getOrCreateGlobalVariableDIE(GV, nullptr);
+ EntityDie = getOrCreateGlobalVariableDIE(GV, {});
else
EntityDie = getDIE(Entity);
assert(EntityDie);
@@ -740,10 +744,8 @@ void DwarfCompileUnit::addAddress(DIE &Die, dwarf::Attribute Attribute,
if (!validReg)
return;
- Expr.finalize();
-
// Now attach the location information to the DIE.
- addBlock(Die, Attribute, Loc);
+ addBlock(Die, Attribute, Expr.finalize());
}
/// Start with the address based on the location provided, and generate the
OpenPOWER on IntegriCloud