summaryrefslogtreecommitdiffstats
path: root/llvm/lib/IR
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/IR')
-rw-r--r--llvm/lib/IR/AsmWriter.cpp13
-rw-r--r--llvm/lib/IR/DIBuilder.cpp19
-rw-r--r--llvm/lib/IR/DebugInfo.cpp16
-rw-r--r--llvm/lib/IR/DebugInfoMetadata.cpp45
-rw-r--r--llvm/lib/IR/LLVMContextImpl.h26
-rw-r--r--llvm/lib/IR/Metadata.cpp21
-rw-r--r--llvm/lib/IR/Verifier.cpp26
7 files changed, 119 insertions, 47 deletions
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index d58618f99ff..5c104f6ce0c 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -1827,7 +1827,6 @@ static void writeDIGlobalVariable(raw_ostream &Out, const DIGlobalVariable *N,
Printer.printMetadata("type", N->getRawType());
Printer.printBool("isLocal", N->isLocalToUnit());
Printer.printBool("isDefinition", N->isDefinition());
- Printer.printMetadata("expr", N->getExpr());
Printer.printMetadata("declaration", N->getRawStaticDataMemberDeclaration());
Printer.printInt("align", N->getAlignInBits());
Out << ")";
@@ -1870,6 +1869,18 @@ static void writeDIExpression(raw_ostream &Out, const DIExpression *N,
Out << ")";
}
+static void writeDIGlobalVariableExpression(raw_ostream &Out,
+ const DIGlobalVariableExpression *N,
+ TypePrinting *TypePrinter,
+ SlotTracker *Machine,
+ const Module *Context) {
+ Out << "!DIGlobalVariableExpression(";
+ MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
+ Printer.printMetadata("var", N->getVariable());
+ Printer.printMetadata("expr", N->getExpression());
+ Out << ")";
+}
+
static void writeDIObjCProperty(raw_ostream &Out, const DIObjCProperty *N,
TypePrinting *TypePrinter, SlotTracker *Machine,
const Module *Context) {
diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp
index dfca6895590..d009322a572 100644
--- a/llvm/lib/IR/DIBuilder.cpp
+++ b/llvm/lib/IR/DIBuilder.cpp
@@ -532,29 +532,30 @@ static void checkGlobalVariableScope(DIScope *Context) {
#endif
}
-DIGlobalVariable *DIBuilder::createGlobalVariable(
+DIGlobalVariableExpression *DIBuilder::createGlobalVariableExpression(
DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *F,
- unsigned LineNumber, DIType *Ty, bool isLocalToUnit,
- DIExpression *Expr, MDNode *Decl, uint32_t AlignInBits) {
+ unsigned LineNumber, DIType *Ty, bool isLocalToUnit, DIExpression *Expr,
+ MDNode *Decl, uint32_t AlignInBits) {
checkGlobalVariableScope(Context);
- auto *N = DIGlobalVariable::getDistinct(
+ auto *GV = DIGlobalVariable::getDistinct(
VMContext, cast_or_null<DIScope>(Context), Name, LinkageName, F,
- LineNumber, Ty, isLocalToUnit, true, Expr,
- cast_or_null<DIDerivedType>(Decl), AlignInBits);
+ LineNumber, Ty, isLocalToUnit, true, cast_or_null<DIDerivedType>(Decl),
+ AlignInBits);
+ auto *N = DIGlobalVariableExpression::get(VMContext, GV, Expr);
AllGVs.push_back(N);
return N;
}
DIGlobalVariable *DIBuilder::createTempGlobalVariableFwdDecl(
DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *F,
- unsigned LineNumber, DIType *Ty, bool isLocalToUnit,
- DIExpression *Expr, MDNode *Decl, uint32_t AlignInBits) {
+ unsigned LineNumber, DIType *Ty, bool isLocalToUnit, MDNode *Decl,
+ uint32_t AlignInBits) {
checkGlobalVariableScope(Context);
return DIGlobalVariable::getTemporary(
VMContext, cast_or_null<DIScope>(Context), Name, LinkageName, F,
- LineNumber, Ty, isLocalToUnit, false, Expr,
+ LineNumber, Ty, isLocalToUnit, false,
cast_or_null<DIDerivedType>(Decl), AlignInBits)
.release();
}
diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp
index 7f91b49d828..6b9bc689a44 100644
--- a/llvm/lib/IR/DebugInfo.cpp
+++ b/llvm/lib/IR/DebugInfo.cpp
@@ -53,11 +53,12 @@ void DebugInfoFinder::reset() {
void DebugInfoFinder::processModule(const Module &M) {
for (auto *CU : M.debug_compile_units()) {
addCompileUnit(CU);
- for (auto *DIG : CU->getGlobalVariables()) {
- if (addGlobalVariable(DIG)) {
- processScope(DIG->getScope());
- processType(DIG->getType().resolve());
- }
+ for (auto DIG : CU->getGlobalVariables()) {
+ if (!addGlobalVariable(DIG))
+ continue;
+ auto *GV = DIG->getVariable();
+ processScope(GV->getScope());
+ processType(GV->getType().resolve());
}
for (auto *ET : CU->getEnumTypes())
processType(ET);
@@ -206,10 +207,7 @@ bool DebugInfoFinder::addCompileUnit(DICompileUnit *CU) {
return true;
}
-bool DebugInfoFinder::addGlobalVariable(DIGlobalVariable *DIG) {
- if (!DIG)
- return false;
-
+bool DebugInfoFinder::addGlobalVariable(DIGlobalVariableExpression *DIG) {
if (!NodesSeen.insert(DIG).second)
return false;
diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index fe61c279778..75c397e1345 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -514,18 +514,17 @@ DIGlobalVariable *
DIGlobalVariable::getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name,
MDString *LinkageName, Metadata *File, unsigned Line,
Metadata *Type, bool IsLocalToUnit, bool IsDefinition,
- Metadata *Variable,
Metadata *StaticDataMemberDeclaration,
- uint32_t AlignInBits,
- StorageType Storage, bool ShouldCreate) {
+ uint32_t AlignInBits, StorageType Storage,
+ bool ShouldCreate) {
assert(isCanonical(Name) && "Expected canonical MDString");
assert(isCanonical(LinkageName) && "Expected canonical MDString");
DEFINE_GETIMPL_LOOKUP(DIGlobalVariable,
(Scope, Name, LinkageName, File, Line, Type,
- IsLocalToUnit, IsDefinition, Variable,
+ IsLocalToUnit, IsDefinition,
StaticDataMemberDeclaration, AlignInBits));
- Metadata *Ops[] = {Scope, Name, File, Type,
- Name, LinkageName, Variable, StaticDataMemberDeclaration};
+ Metadata *Ops[] = {
+ Scope, Name, File, Type, Name, LinkageName, StaticDataMemberDeclaration};
DEFINE_GETIMPL_STORE(DIGlobalVariable,
(Line, IsLocalToUnit, IsDefinition, AlignInBits),
Ops);
@@ -581,10 +580,17 @@ bool DIExpression::isValid() const {
default:
return false;
case dwarf::DW_OP_LLVM_fragment:
- case dwarf::DW_OP_stack_value:
- // We only support fragment and stack value expressions which appear at
- // the end.
+ // A fragment operator must appear at the end.
return I->get() + I->getSize() == E->get();
+ case dwarf::DW_OP_stack_value: {
+ // Must be the last one or followed by a DW_OP_LLVM_fragment.
+ if (I->get() + I->getSize() == E->get())
+ break;
+ auto J = I;
+ if ((++J)->getOp() != dwarf::DW_OP_LLVM_fragment)
+ return false;
+ break;
+ }
case dwarf::DW_OP_constu:
case dwarf::DW_OP_plus:
case dwarf::DW_OP_minus:
@@ -613,6 +619,27 @@ uint64_t DIExpression::getFragmentSizeInBits() const {
return getElement(getNumElements() - 1);
}
+bool DIExpression::isConstant() const {
+ // Recognize DW_OP_constu C DW_OP_stack_value (DW_OP_LLVM_fragment Len Ofs)?.
+ if (getNumElements() != 3 && getNumElements() != 6)
+ return false;
+ if (getElement(0) != dwarf::DW_OP_constu ||
+ getElement(2) != dwarf::DW_OP_stack_value)
+ return false;
+ if (getNumElements() == 6 && getElement(3) != dwarf::DW_OP_LLVM_fragment)
+ return false;
+ return true;
+}
+
+DIGlobalVariableExpression *
+DIGlobalVariableExpression::getImpl(LLVMContext &Context, Metadata *Variable,
+ Metadata *Expression, StorageType Storage,
+ bool ShouldCreate) {
+ DEFINE_GETIMPL_LOOKUP(DIGlobalVariableExpression, (Variable, Expression));
+ Metadata *Ops[] = {Variable, Expression};
+ DEFINE_GETIMPL_STORE_NO_CONSTRUCTOR_ARGS(DIGlobalVariableExpression, Ops);
+}
+
DIObjCProperty *DIObjCProperty::getImpl(
LLVMContext &Context, MDString *Name, Metadata *File, unsigned Line,
MDString *GetterName, MDString *SetterName, unsigned Attributes,
diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h
index f1cc12a2902..55443c598f9 100644
--- a/llvm/lib/IR/LLVMContextImpl.h
+++ b/llvm/lib/IR/LLVMContextImpl.h
@@ -763,18 +763,16 @@ template <> struct MDNodeKeyImpl<DIGlobalVariable> {
Metadata *Type;
bool IsLocalToUnit;
bool IsDefinition;
- Metadata *Expr;
Metadata *StaticDataMemberDeclaration;
uint32_t AlignInBits;
MDNodeKeyImpl(Metadata *Scope, MDString *Name, MDString *LinkageName,
Metadata *File, unsigned Line, Metadata *Type,
bool IsLocalToUnit, bool IsDefinition,
- Metadata *Expr, Metadata *StaticDataMemberDeclaration,
- uint32_t AlignInBits)
+ Metadata *StaticDataMemberDeclaration, uint32_t AlignInBits)
: Scope(Scope), Name(Name), LinkageName(LinkageName), File(File),
Line(Line), Type(Type), IsLocalToUnit(IsLocalToUnit),
- IsDefinition(IsDefinition), Expr(Expr),
+ IsDefinition(IsDefinition),
StaticDataMemberDeclaration(StaticDataMemberDeclaration),
AlignInBits(AlignInBits) {}
MDNodeKeyImpl(const DIGlobalVariable *N)
@@ -782,7 +780,6 @@ template <> struct MDNodeKeyImpl<DIGlobalVariable> {
LinkageName(N->getRawLinkageName()), File(N->getRawFile()),
Line(N->getLine()), Type(N->getRawType()),
IsLocalToUnit(N->isLocalToUnit()), IsDefinition(N->isDefinition()),
- Expr(N->getRawExpr()),
StaticDataMemberDeclaration(N->getRawStaticDataMemberDeclaration()),
AlignInBits(N->getAlignInBits()) {}
@@ -792,7 +789,6 @@ template <> struct MDNodeKeyImpl<DIGlobalVariable> {
File == RHS->getRawFile() && Line == RHS->getLine() &&
Type == RHS->getRawType() && IsLocalToUnit == RHS->isLocalToUnit() &&
IsDefinition == RHS->isDefinition() &&
- Expr == RHS->getRawExpr() &&
StaticDataMemberDeclaration ==
RHS->getRawStaticDataMemberDeclaration() &&
AlignInBits == RHS->getAlignInBits();
@@ -806,7 +802,7 @@ template <> struct MDNodeKeyImpl<DIGlobalVariable> {
// generated IR is random for each run and test fails with Align included.
// TODO: make hashing work fine with such situations
return hash_combine(Scope, Name, LinkageName, File, Line, Type,
- IsLocalToUnit, IsDefinition, /* AlignInBits, */ Expr,
+ IsLocalToUnit, IsDefinition, /* AlignInBits, */
StaticDataMemberDeclaration);
}
};
@@ -863,6 +859,22 @@ template <> struct MDNodeKeyImpl<DIExpression> {
}
};
+template <> struct MDNodeKeyImpl<DIGlobalVariableExpression> {
+ Metadata *Variable;
+ Metadata *Expression;
+
+ MDNodeKeyImpl(Metadata *Variable, Metadata *Expression)
+ : Variable(Variable), Expression(Expression) {}
+ MDNodeKeyImpl(const DIGlobalVariableExpression *N)
+ : Variable(N->getRawVariable()), Expression(N->getRawExpression()) {}
+
+ bool isKeyOf(const DIGlobalVariableExpression *RHS) const {
+ return Variable == RHS->getRawVariable() &&
+ Expression == RHS->getRawExpression();
+ }
+ unsigned getHashValue() const { return hash_combine(Variable, Expression); }
+};
+
template <> struct MDNodeKeyImpl<DIObjCProperty> {
MDString *Name;
Metadata *File;
diff --git a/llvm/lib/IR/Metadata.cpp b/llvm/lib/IR/Metadata.cpp
index adc91573a7f..1d193045923 100644
--- a/llvm/lib/IR/Metadata.cpp
+++ b/llvm/lib/IR/Metadata.cpp
@@ -1419,9 +1419,15 @@ void GlobalObject::copyMetadata(const GlobalObject *Other, unsigned Offset) {
// If an offset adjustment was specified we need to modify the DIExpression
// to prepend the adjustment:
// !DIExpression(DW_OP_plus, Offset, [original expr])
+ auto *Attachment = MD.second;
if (Offset != 0 && MD.first == LLVMContext::MD_dbg) {
- DIGlobalVariable *GV = cast<DIGlobalVariable>(MD.second);
- DIExpression *E = GV->getExpr();
+ DIGlobalVariable *GV = dyn_cast<DIGlobalVariable>(Attachment);
+ DIExpression *E = nullptr;
+ if (!GV) {
+ auto *GVE = cast<DIGlobalVariableExpression>(Attachment);
+ GV = GVE->getVariable();
+ E = GVE->getExpression();
+ }
ArrayRef<uint64_t> OrigElements;
if (E)
OrigElements = E->getElements();
@@ -1429,9 +1435,10 @@ void GlobalObject::copyMetadata(const GlobalObject *Other, unsigned Offset) {
Elements[0] = dwarf::DW_OP_plus;
Elements[1] = Offset;
std::copy(OrigElements.begin(), OrigElements.end(), Elements.begin() + 2);
- GV->replaceExpr(DIExpression::get(getContext(), Elements));
+ E = DIExpression::get(getContext(), Elements);
+ Attachment = DIGlobalVariableExpression::get(getContext(), GV, E);
}
- addMetadata(MD.first, *MD.second);
+ addMetadata(MD.first, *Attachment);
}
}
@@ -1452,14 +1459,14 @@ DISubprogram *Function::getSubprogram() const {
return cast_or_null<DISubprogram>(getMetadata(LLVMContext::MD_dbg));
}
-void GlobalVariable::addDebugInfo(DIGlobalVariable *GV) {
+void GlobalVariable::addDebugInfo(DIGlobalVariableExpression *GV) {
addMetadata(LLVMContext::MD_dbg, *GV);
}
void GlobalVariable::getDebugInfo(
- SmallVectorImpl<DIGlobalVariable *> &GVs) const {
+ SmallVectorImpl<DIGlobalVariableExpression *> &GVs) const {
SmallVector<MDNode *, 1> MDs;
getMetadata(LLVMContext::MD_dbg, MDs);
for (MDNode *MD : MDs)
- GVs.push_back(cast<DIGlobalVariable>(MD));
+ GVs.push_back(cast<DIGlobalVariableExpression>(MD));
}
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 3609628561b..1e6bbe42756 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -594,7 +594,6 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) {
"Global variable initializer type does not match global "
"variable type!",
&GV);
-
// If the global has common linkage, it must have a zero initializer and
// cannot be constant.
if (GV.hasCommonLinkage()) {
@@ -660,6 +659,16 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) {
GV.hasAvailableExternallyLinkage(),
"Global is marked as dllimport, but not external", &GV);
+ // Visit any debug info attachments.
+ SmallVector<MDNode *, 1> MDs;
+ GV.getMetadata(LLVMContext::MD_dbg, MDs);
+ for (auto *MD : MDs)
+ if (auto *GVE = dyn_cast<DIGlobalVariableExpression>(MD))
+ visitDIGlobalVariableExpression(*GVE);
+ else
+ AssertDI(false, "!dbg attachment of global variable must be a "
+ "DIGlobalVariableExpression");
+
if (!GV.hasInitializer()) {
visitGlobalValue(GV);
return;
@@ -1002,8 +1011,8 @@ void Verifier::visitDICompileUnit(const DICompileUnit &N) {
if (auto *Array = N.getRawGlobalVariables()) {
AssertDI(isa<MDTuple>(Array), "invalid global variable list", &N, Array);
for (Metadata *Op : N.getGlobalVariables()->operands()) {
- AssertDI(Op && isa<DIGlobalVariable>(Op), "invalid global variable ref",
- &N, Op);
+ AssertDI(Op && (isa<DIGlobalVariableExpression>(Op)),
+ "invalid global variable ref", &N, Op);
}
}
if (auto *Array = N.getRawImportedEntities()) {
@@ -1146,8 +1155,6 @@ void Verifier::visitDIGlobalVariable(const DIGlobalVariable &N) {
AssertDI(N.getTag() == dwarf::DW_TAG_variable, "invalid tag", &N);
AssertDI(!N.getName().empty(), "missing global variable name", &N);
- if (auto *V = N.getRawExpr())
- AssertDI(isa<DIExpression>(V), "invalid expression location", &N, V);
if (auto *Member = N.getRawStaticDataMemberDeclaration()) {
AssertDI(isa<DIDerivedType>(Member),
"invalid static data member declaration", &N, Member);
@@ -1167,6 +1174,15 @@ void Verifier::visitDIExpression(const DIExpression &N) {
AssertDI(N.isValid(), "invalid expression", &N);
}
+void Verifier::visitDIGlobalVariableExpression(
+ const DIGlobalVariableExpression &GVE) {
+ AssertDI(GVE.getVariable(), "missing variable");
+ if (auto *Var = GVE.getVariable())
+ visitDIGlobalVariable(*Var);
+ if (auto *Expr = GVE.getExpression())
+ visitDIExpression(*Expr);
+}
+
void Verifier::visitDIObjCProperty(const DIObjCProperty &N) {
AssertDI(N.getTag() == dwarf::DW_TAG_APPLE_property, "invalid tag", &N);
if (auto *T = N.getRawType())
OpenPOWER on IntegriCloud