summaryrefslogtreecommitdiffstats
path: root/llvm/lib/IR
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/IR')
-rw-r--r--llvm/lib/IR/AutoUpgrade.cpp53
-rw-r--r--llvm/lib/IR/DIBuilder.cpp72
-rw-r--r--llvm/lib/IR/DebugInfo.cpp108
3 files changed, 142 insertions, 91 deletions
diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp
index bbb8462652c..b4f327bab5c 100644
--- a/llvm/lib/IR/AutoUpgrade.cpp
+++ b/llvm/lib/IR/AutoUpgrade.cpp
@@ -17,6 +17,7 @@
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instruction.h"
@@ -106,6 +107,20 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) {
}
break;
}
+ case 'd': {
+ if (Name.startswith("dbg.declare") && F->arg_size() == 2) {
+ F->setName(Name + ".old");
+ NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::dbg_declare);
+ return true;
+ }
+ if (Name.startswith("dbg.value") && F->arg_size() == 3) {
+ F->setName(Name + ".old");
+ NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::dbg_value);
+ return true;
+ }
+ break;
+ }
+
case 'o':
// We only need to change the name to match the mangling including the
// address space.
@@ -239,6 +254,22 @@ bool llvm::UpgradeGlobalVariable(GlobalVariable *GV) {
return false;
}
+static MDNode *getNodeField(const MDNode *DbgNode, unsigned Elt) {
+ if (!DbgNode || Elt >= DbgNode->getNumOperands())
+ return nullptr;
+ return dyn_cast_or_null<MDNode>(DbgNode->getOperand(Elt));
+}
+
+static DIExpression getExpression(Value *VarOperand, Function *F) {
+ // Old-style DIVariables have an optional expression as the 8th element.
+ DIExpression Expr(getNodeField(cast<MDNode>(VarOperand), 8));
+ if (!Expr) {
+ DIBuilder DIB(*F->getParent());
+ Expr = DIB.createExpression();
+ }
+ return Expr;
+}
+
// UpgradeIntrinsicCall - Upgrade a call to an old intrinsic to be a call the
// upgraded intrinsic. All argument and return casting must be provided in
// order to seamlessly integrate with existing context.
@@ -402,12 +433,32 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
}
std::string Name = CI->getName().str();
- CI->setName(Name + ".old");
+ if (!Name.empty())
+ CI->setName(Name + ".old");
switch (NewFn->getIntrinsicID()) {
default:
llvm_unreachable("Unknown function for CallInst upgrade.");
+ // Upgrade debug intrinsics to use an additional DIExpression argument.
+ case Intrinsic::dbg_declare: {
+ auto NewCI =
+ Builder.CreateCall3(NewFn, CI->getArgOperand(0), CI->getArgOperand(1),
+ getExpression(CI->getArgOperand(1), F), Name);
+ NewCI->setDebugLoc(CI->getDebugLoc());
+ CI->replaceAllUsesWith(NewCI);
+ CI->eraseFromParent();
+ return;
+ }
+ case Intrinsic::dbg_value: {
+ auto NewCI = Builder.CreateCall4(
+ NewFn, CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(2),
+ getExpression(CI->getArgOperand(2), F), Name);
+ NewCI->setDebugLoc(CI->getDebugLoc());
+ CI->replaceAllUsesWith(NewCI);
+ CI->eraseFromParent();
+ return;
+ }
case Intrinsic::ctlz:
case Intrinsic::cttz:
assert(CI->getNumArgOperands() == 1 &&
diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp
index a5c09b60c4f..1ab52523d73 100644
--- a/llvm/lib/IR/DIBuilder.cpp
+++ b/llvm/lib/IR/DIBuilder.cpp
@@ -1042,50 +1042,28 @@ DIVariable DIBuilder::createLocalVariable(unsigned Tag, DIDescriptor Scope,
return RetVar;
}
-/// createComplexVariable - Create a new descriptor for the specified variable
-/// which has a complex address expression for its address.
-DIVariable DIBuilder::createComplexVariable(unsigned Tag, DIDescriptor Scope,
- StringRef Name, DIFile F,
- unsigned LineNo,
- DITypeRef Ty,
- ArrayRef<Value *> Addr,
- unsigned ArgNo) {
- assert(Addr.size() > 0 && "complex address is empty");
- Value *Elts[] = {
- GetTagConstant(VMContext, Tag),
- getNonCompileUnitScope(Scope),
- MDString::get(VMContext, Name),
- F,
- ConstantInt::get(Type::getInt32Ty(VMContext),
- (LineNo | (ArgNo << 24))),
- Ty,
- Constant::getNullValue(Type::getInt32Ty(VMContext)),
- Constant::getNullValue(Type::getInt32Ty(VMContext)),
- MDNode::get(VMContext, Addr)
- };
- return DIVariable(MDNode::get(VMContext, Elts));
+/// createExpression - Create a new descriptor for the specified
+/// variable which has a complex address expression for its address.
+/// @param Addr An array of complex address operations.
+DIExpression DIBuilder::createExpression(ArrayRef<Value *> Addr) {
+ SmallVector<llvm::Value *, 16> Elts;
+ Elts.push_back(GetTagConstant(VMContext, DW_TAG_expression));
+ Elts.insert(Elts.end(), Addr.begin(), Addr.end());
+ return DIExpression(MDNode::get(VMContext, Elts));
}
/// createVariablePiece - Create a descriptor to describe one part
/// of aggregate variable that is fragmented across multiple Values.
-DIVariable DIBuilder::createVariablePiece(DIVariable Variable,
- unsigned OffsetInBytes,
- unsigned SizeInBytes) {
+DIExpression DIBuilder::createPieceExpression(unsigned OffsetInBytes,
+ unsigned SizeInBytes) {
assert(SizeInBytes > 0 && "zero-size piece");
Value *Addr[] = {
- ConstantInt::get(Type::getInt32Ty(VMContext), OpPiece),
- ConstantInt::get(Type::getInt32Ty(VMContext), OffsetInBytes),
- ConstantInt::get(Type::getInt32Ty(VMContext), SizeInBytes)
- };
-
- assert((Variable->getNumOperands() == 8 || Variable.isVariablePiece()) &&
- "variable already has a complex address");
- SmallVector<Value *, 9> Elts;
- for (unsigned i = 0; i < 8; ++i)
- Elts.push_back(Variable->getOperand(i));
+ GetTagConstant(VMContext, DW_TAG_expression),
+ ConstantInt::get(Type::getInt64Ty(VMContext), dwarf::DW_OP_piece),
+ ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBytes),
+ ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBytes)};
- Elts.push_back(MDNode::get(VMContext, Addr));
- return DIVariable(MDNode::get(VMContext, Elts));
+ return DIExpression(MDNode::get(VMContext, Addr));
}
/// createFunction - Create a new descriptor for the specified function.
@@ -1292,6 +1270,7 @@ DILexicalBlock DIBuilder::createLexicalBlock(DIDescriptor Scope, DIFile File,
/// insertDeclare - Insert a new llvm.dbg.declare intrinsic call.
Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo,
+ DIExpression Expr,
Instruction *InsertBefore) {
assert(Storage && "no storage passed to dbg.declare");
assert(VarInfo.isVariable() &&
@@ -1299,12 +1278,13 @@ Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo,
if (!DeclareFn)
DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare);
- Value *Args[] = { MDNode::get(Storage->getContext(), Storage), VarInfo };
+ Value *Args[] = {MDNode::get(Storage->getContext(), Storage), VarInfo, Expr};
return CallInst::Create(DeclareFn, Args, "", InsertBefore);
}
/// insertDeclare - Insert a new llvm.dbg.declare intrinsic call.
Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo,
+ DIExpression Expr,
BasicBlock *InsertAtEnd) {
assert(Storage && "no storage passed to dbg.declare");
assert(VarInfo.isVariable() &&
@@ -1312,7 +1292,7 @@ Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo,
if (!DeclareFn)
DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare);
- Value *Args[] = { MDNode::get(Storage->getContext(), Storage), VarInfo };
+ Value *Args[] = {MDNode::get(Storage->getContext(), Storage), VarInfo, Expr};
// If this block already has a terminator then insert this intrinsic
// before the terminator.
@@ -1325,6 +1305,7 @@ Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo,
/// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset,
DIVariable VarInfo,
+ DIExpression Expr,
Instruction *InsertBefore) {
assert(V && "no value passed to dbg.value");
assert(VarInfo.isVariable() &&
@@ -1332,15 +1313,16 @@ Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset,
if (!ValueFn)
ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value);
- Value *Args[] = { MDNode::get(V->getContext(), V),
- ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset),
- VarInfo };
+ Value *Args[] = {MDNode::get(V->getContext(), V),
+ ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset),
+ VarInfo, Expr};
return CallInst::Create(ValueFn, Args, "", InsertBefore);
}
/// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset,
DIVariable VarInfo,
+ DIExpression Expr,
BasicBlock *InsertAtEnd) {
assert(V && "no value passed to dbg.value");
assert(VarInfo.isVariable() &&
@@ -1348,8 +1330,8 @@ Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset,
if (!ValueFn)
ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value);
- Value *Args[] = { MDNode::get(V->getContext(), V),
- ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset),
- VarInfo };
+ Value *Args[] = {MDNode::get(V->getContext(), V),
+ ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset),
+ VarInfo, Expr};
return CallInst::Create(ValueFn, Args, "", InsertAtEnd);
}
diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp
index 4274d82d158..206d04e3749 100644
--- a/llvm/lib/IR/DebugInfo.cpp
+++ b/llvm/lib/IR/DebugInfo.cpp
@@ -49,7 +49,7 @@ bool DIDescriptor::Verify() const {
DIObjCProperty(DbgNode).Verify() ||
DITemplateTypeParameter(DbgNode).Verify() ||
DITemplateValueParameter(DbgNode).Verify() ||
- DIImportedEntity(DbgNode).Verify());
+ DIImportedEntity(DbgNode).Verify() || DIExpression(DbgNode).Verify());
}
static Value *getField(const MDNode *DbgNode, unsigned Elt) {
@@ -138,33 +138,9 @@ void DIDescriptor::replaceFunctionField(unsigned Elt, Function *F) {
}
}
-uint64_t DIVariable::getAddrElement(unsigned Idx) const {
- DIDescriptor ComplexExpr = getDescriptorField(8);
- if (Idx < ComplexExpr->getNumOperands())
- if (auto *CI = dyn_cast_or_null<ConstantInt>(ComplexExpr->getOperand(Idx)))
- return CI->getZExtValue();
-
- assert(false && "non-existing complex address element requested");
- return 0;
-}
-
/// getInlinedAt - If this variable is inlined then return inline location.
MDNode *DIVariable::getInlinedAt() const { return getNodeField(DbgNode, 7); }
-bool DIVariable::isVariablePiece() const {
- return hasComplexAddress() && getAddrElement(0) == DIBuilder::OpPiece;
-}
-
-uint64_t DIVariable::getPieceOffset() const {
- assert(isVariablePiece());
- return getAddrElement(1);
-}
-
-uint64_t DIVariable::getPieceSize() const {
- assert(isVariablePiece());
- return getAddrElement(2);
-}
-
/// Return the size reported by the variable's type.
unsigned DIVariable::getSizeInBits(const DITypeIdentifierMap &Map) {
DIType Ty = getType().resolve(Map);
@@ -178,8 +154,29 @@ unsigned DIVariable::getSizeInBits(const DITypeIdentifierMap &Map) {
return Ty.getSizeInBits();
}
+uint64_t DIExpression::getElement(unsigned Idx) const {
+ unsigned I = Idx + 1;
+ if (I < DbgNode->getNumOperands())
+ if (auto *CI = dyn_cast_or_null<ConstantInt>(DbgNode->getOperand(I)))
+ return CI->getZExtValue();
+ assert(false && "non-existing complex address element requested");
+ return 0;
+}
+
+bool DIExpression::isVariablePiece() const {
+ return getNumElements() && getElement(0) == dwarf::DW_OP_piece;
+}
+
+uint64_t DIExpression::getPieceOffset() const {
+ assert(isVariablePiece());
+ return getElement(1);
+}
+uint64_t DIExpression::getPieceSize() const {
+ assert(isVariablePiece());
+ return getElement(2);
+}
//===----------------------------------------------------------------------===//
// Predicates
@@ -357,6 +354,12 @@ bool DIDescriptor::isImportedEntity() const {
getTag() == dwarf::DW_TAG_imported_declaration);
}
+/// \brief Return true if the specified tag is DW_TAG_imported_module or
+/// DW_TAG_imported_declaration.
+bool DIDescriptor::isExpression() const {
+ return DbgNode && (getTag() == dwarf::DW_TAG_expression);
+}
+
//===----------------------------------------------------------------------===//
// Simple Descriptor Constructors and other Methods
//===----------------------------------------------------------------------===//
@@ -596,12 +599,20 @@ bool DIVariable::Verify() const {
if (!fieldIsTypeRef(DbgNode, 5))
return false;
- // Variable without a complex expression.
- if (DbgNode->getNumOperands() == 8)
+ // Variable without an inline location.
+ if (DbgNode->getNumOperands() == 7)
return true;
- // Make sure the complex expression is an MDNode.
- return (DbgNode->getNumOperands() == 9 && fieldIsMDNode(DbgNode, 8));
+ return DbgNode->getNumOperands() == 8;
+}
+
+/// Verify - Verify that a variable descriptor is well formed.
+bool DIExpression::Verify() const {
+ // Empty DIExpressions may be represented as a nullptr.
+ if (!DbgNode)
+ return true;
+
+ return isExpression();
}
/// Verify - Verify that a location descriptor is well formed.
@@ -936,19 +947,6 @@ DIVariable llvm::cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext) {
return DIVariable(MDNode::get(VMContext, Elts));
}
-
-/// getEntireVariable - Remove OpPiece exprs from the variable.
-DIVariable llvm::getEntireVariable(DIVariable DV) {
- if (!DV.isVariablePiece())
- return DV;
-
- SmallVector<Value *, 8> Elts;
- for (unsigned i = 0; i < 8; ++i)
- Elts.push_back(DV->getOperand(i));
-
- return DIVariable(MDNode::get(DV->getContext(), Elts));
-}
-
/// getDISubprogram - Find subprogram that is enclosing this scope.
DISubprogram llvm::getDISubprogram(const MDNode *Scope) {
DIDescriptor D(Scope);
@@ -1293,6 +1291,8 @@ void DIDescriptor::print(raw_ostream &OS) const {
DINameSpace(DbgNode).printInternal(OS);
} else if (this->isScope()) {
DIScope(DbgNode).printInternal(OS);
+ } else if (this->isExpression()) {
+ DIExpression(DbgNode).printInternal(OS);
}
}
@@ -1442,10 +1442,28 @@ void DIVariable::printInternal(raw_ostream &OS) const {
OS << " [" << Res << ']';
OS << " [line " << getLineNumber() << ']';
+}
- if (isVariablePiece())
- OS << " [piece, size " << getPieceSize()
- << ", offset " << getPieceOffset() << ']';
+void DIExpression::printInternal(raw_ostream &OS) const {
+ for (unsigned I = 0; I < getNumElements(); ++I) {
+ uint64_t OpCode = getElement(I);
+ OS << " [" << OperationEncodingString(OpCode);
+ switch (OpCode) {
+ case DW_OP_plus: {
+ OS << " " << getElement(++I);
+ break;
+ }
+ case DW_OP_piece: {
+ unsigned Offset = getElement(++I);
+ unsigned Size = getElement(++I);
+ OS << " offset=" << Offset << ", size= " << Size;
+ break;
+ }
+ default:
+ break;
+ }
+ OS << "]";
+ }
}
void DIObjCProperty::printInternal(raw_ostream &OS) const {
OpenPOWER on IntegriCloud