diff options
Diffstat (limited to 'llvm/lib/IR')
-rw-r--r-- | llvm/lib/IR/AutoUpgrade.cpp | 53 | ||||
-rw-r--r-- | llvm/lib/IR/DIBuilder.cpp | 72 | ||||
-rw-r--r-- | llvm/lib/IR/DebugInfo.cpp | 108 |
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 { |