diff options
Diffstat (limited to 'llvm/lib/IR/DebugInfoMetadata.cpp')
-rw-r--r-- | llvm/lib/IR/DebugInfoMetadata.cpp | 188 |
1 files changed, 168 insertions, 20 deletions
diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp index b9fc5261fefe..50799327c78a 100644 --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -15,6 +15,7 @@ #include "MetadataImpl.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/BinaryFormat/Dwarf.h" #include "llvm/IR/Function.h" #include "llvm/IR/Type.h" #include "llvm/IR/Value.h" @@ -26,7 +27,7 @@ using namespace llvm; namespace llvm { // Use FS-AFDO discriminator. cl::opt<bool> EnableFSDiscriminator( - "enable-fs-discriminator", cl::Hidden, cl::init(false), + "enable-fs-discriminator", cl::Hidden, cl::desc("Enable adding flow sensitive discriminators")); } // namespace llvm @@ -77,8 +78,8 @@ DILocation *DILocation::getImpl(LLVMContext &Context, unsigned Line, Ops.push_back(Scope); if (InlinedAt) Ops.push_back(InlinedAt); - return storeImpl(new (Ops.size()) DILocation(Context, Storage, Line, Column, - Ops, ImplicitCode), + return storeImpl(new (Ops.size(), Storage) DILocation( + Context, Storage, Line, Column, Ops, ImplicitCode), Storage, Context.pImpl->DILocations); } @@ -180,6 +181,7 @@ void DILocation::decodeDiscriminator(unsigned D, unsigned &BD, unsigned &DF, CI = getUnsignedFromPrefixEncoding( getNextComponentInDiscriminator(getNextComponentInDiscriminator(D))); } +dwarf::Tag DINode::getTag() const { return (dwarf::Tag)SubclassData16; } DINode::DIFlags DINode::getFlag(StringRef Flag) { return StringSwitch<DIFlags>(Flag) @@ -282,6 +284,7 @@ static bool isCanonical(const MDString *S) { } #endif +dwarf::Tag GenericDINode::getTag() const { return (dwarf::Tag)SubclassData16; } GenericDINode *GenericDINode::getImpl(LLVMContext &Context, unsigned Tag, MDString *Header, ArrayRef<Metadata *> DwarfOps, @@ -301,7 +304,7 @@ GenericDINode *GenericDINode::getImpl(LLVMContext &Context, unsigned Tag, // Use a nullptr for empty headers. assert(isCanonical(Header) && "Expected canonical MDString"); Metadata *PreOps[] = {Header}; - return storeImpl(new (DwarfOps.size() + 1) GenericDINode( + return storeImpl(new (DwarfOps.size() + 1, Storage) GenericDINode( Context, Storage, Hash, Tag, PreOps, DwarfOps), Storage, Context.pImpl->GenericDINodes); } @@ -326,20 +329,25 @@ void GenericDINode::recalculateHash() { } \ } while (false) #define DEFINE_GETIMPL_STORE(CLASS, ARGS, OPS) \ - return storeImpl(new (array_lengthof(OPS)) \ + return storeImpl(new (array_lengthof(OPS), Storage) \ CLASS(Context, Storage, UNWRAP_ARGS(ARGS), OPS), \ Storage, Context.pImpl->CLASS##s) #define DEFINE_GETIMPL_STORE_NO_OPS(CLASS, ARGS) \ - return storeImpl(new (0u) CLASS(Context, Storage, UNWRAP_ARGS(ARGS)), \ + return storeImpl(new (0u, Storage) \ + CLASS(Context, Storage, UNWRAP_ARGS(ARGS)), \ Storage, Context.pImpl->CLASS##s) #define DEFINE_GETIMPL_STORE_NO_CONSTRUCTOR_ARGS(CLASS, OPS) \ - return storeImpl(new (array_lengthof(OPS)) CLASS(Context, Storage, OPS), \ + return storeImpl(new (array_lengthof(OPS), Storage) \ + CLASS(Context, Storage, OPS), \ Storage, Context.pImpl->CLASS##s) #define DEFINE_GETIMPL_STORE_N(CLASS, ARGS, OPS, NUM_OPS) \ - return storeImpl(new (NUM_OPS) \ + return storeImpl(new (NUM_OPS, Storage) \ CLASS(Context, Storage, UNWRAP_ARGS(ARGS), OPS), \ Storage, Context.pImpl->CLASS##s) +DISubrange::DISubrange(LLVMContext &C, StorageType Storage, + ArrayRef<Metadata *> Ops) + : DINode(C, DISubrangeKind, Storage, dwarf::DW_TAG_subrange_type, Ops) {} DISubrange *DISubrange::getImpl(LLVMContext &Context, int64_t Count, int64_t Lo, StorageType Storage, bool ShouldCreate) { auto *CountNode = ConstantAsMetadata::get( @@ -450,6 +458,10 @@ DISubrange::BoundType DISubrange::getStride() const { return BoundType(); } +DIGenericSubrange::DIGenericSubrange(LLVMContext &C, StorageType Storage, + ArrayRef<Metadata *> Ops) + : DINode(C, DIGenericSubrangeKind, Storage, dwarf::DW_TAG_generic_subrange, + Ops) {} DIGenericSubrange *DIGenericSubrange::getImpl(LLVMContext &Context, Metadata *CountNode, Metadata *LB, @@ -529,6 +541,13 @@ DIGenericSubrange::BoundType DIGenericSubrange::getStride() const { return BoundType(); } +DIEnumerator::DIEnumerator(LLVMContext &C, StorageType Storage, + const APInt &Value, bool IsUnsigned, + ArrayRef<Metadata *> Ops) + : DINode(C, DIEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops), + Value(Value) { + SubclassData32 = IsUnsigned; +} DIEnumerator *DIEnumerator::getImpl(LLVMContext &Context, const APInt &Value, bool IsUnsigned, MDString *Name, StorageType Storage, bool ShouldCreate) { @@ -580,6 +599,36 @@ DIStringType *DIStringType::getImpl(LLVMContext &Context, unsigned Tag, DEFINE_GETIMPL_STORE(DIStringType, (Tag, SizeInBits, AlignInBits, Encoding), Ops); } +DIType *DIDerivedType::getClassType() const { + assert(getTag() == dwarf::DW_TAG_ptr_to_member_type); + return cast_or_null<DIType>(getExtraData()); +} +uint32_t DIDerivedType::getVBPtrOffset() const { + assert(getTag() == dwarf::DW_TAG_inheritance); + if (auto *CM = cast_or_null<ConstantAsMetadata>(getExtraData())) + if (auto *CI = dyn_cast_or_null<ConstantInt>(CM->getValue())) + return static_cast<uint32_t>(CI->getZExtValue()); + return 0; +} +Constant *DIDerivedType::getStorageOffsetInBits() const { + assert(getTag() == dwarf::DW_TAG_member && isBitField()); + if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData())) + return C->getValue(); + return nullptr; +} + +Constant *DIDerivedType::getConstant() const { + assert(getTag() == dwarf::DW_TAG_member && isStaticMember()); + if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData())) + return C->getValue(); + return nullptr; +} +Constant *DIDerivedType::getDiscriminantValue() const { + assert(getTag() == dwarf::DW_TAG_member && !isStaticMember()); + if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData())) + return C->getValue(); + return nullptr; +} DIDerivedType *DIDerivedType::getImpl( LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, @@ -701,6 +750,12 @@ DICompositeType *DICompositeType::getODRTypeIfExists(LLVMContext &Context, return nullptr; return Context.pImpl->DITypeMap->lookup(&Identifier); } +DISubroutineType::DISubroutineType(LLVMContext &C, StorageType Storage, + DIFlags Flags, uint8_t CC, + ArrayRef<Metadata *> Ops) + : DIType(C, DISubroutineTypeKind, Storage, dwarf::DW_TAG_subroutine_type, 0, + 0, 0, 0, Flags, Ops), + CC(CC) {} DISubroutineType *DISubroutineType::getImpl(LLVMContext &Context, DIFlags Flags, uint8_t CC, Metadata *TypeArray, @@ -711,6 +766,12 @@ DISubroutineType *DISubroutineType::getImpl(LLVMContext &Context, DIFlags Flags, DEFINE_GETIMPL_STORE(DISubroutineType, (Flags, CC), Ops); } +DIFile::DIFile(LLVMContext &C, StorageType Storage, + Optional<ChecksumInfo<MDString *>> CS, Optional<MDString *> Src, + ArrayRef<Metadata *> Ops) + : DIScope(C, DIFileKind, Storage, dwarf::DW_TAG_file_type, Ops), + Checksum(CS), Source(Src) {} + // FIXME: Implement this string-enum correspondence with a .def file and macros, // so that the association is explicit rather than implied. static const char *ChecksumKindName[DIFile::CSK_Last] = { @@ -746,9 +807,23 @@ DIFile *DIFile::getImpl(LLVMContext &Context, MDString *Filename, assert((!Source || isCanonical(*Source)) && "Expected canonical MDString"); DEFINE_GETIMPL_LOOKUP(DIFile, (Filename, Directory, CS, Source)); Metadata *Ops[] = {Filename, Directory, CS ? CS->Value : nullptr, - Source.getValueOr(nullptr)}; + Source.value_or(nullptr)}; DEFINE_GETIMPL_STORE(DIFile, (CS, Source), Ops); } +DICompileUnit::DICompileUnit(LLVMContext &C, StorageType Storage, + unsigned SourceLanguage, bool IsOptimized, + unsigned RuntimeVersion, unsigned EmissionKind, + uint64_t DWOId, bool SplitDebugInlining, + bool DebugInfoForProfiling, unsigned NameTableKind, + bool RangesBaseAddress, ArrayRef<Metadata *> Ops) + : DIScope(C, DICompileUnitKind, Storage, dwarf::DW_TAG_compile_unit, Ops), + SourceLanguage(SourceLanguage), IsOptimized(IsOptimized), + RuntimeVersion(RuntimeVersion), EmissionKind(EmissionKind), DWOId(DWOId), + SplitDebugInlining(SplitDebugInlining), + DebugInfoForProfiling(DebugInfoForProfiling), + NameTableKind(NameTableKind), RangesBaseAddress(RangesBaseAddress) { + assert(Storage != Uniqued); +} DICompileUnit *DICompileUnit::getImpl( LLVMContext &Context, unsigned SourceLanguage, Metadata *File, @@ -775,7 +850,7 @@ DICompileUnit *DICompileUnit::getImpl( Macros, SysRoot, SDK}; - return storeImpl(new (array_lengthof(Ops)) DICompileUnit( + return storeImpl(new (array_lengthof(Ops), Storage) DICompileUnit( Context, Storage, SourceLanguage, IsOptimized, RuntimeVersion, EmissionKind, DWOId, SplitDebugInlining, DebugInfoForProfiling, NameTableKind, RangesBaseAddress, @@ -827,6 +902,30 @@ const char *DICompileUnit::nameTableKindString(DebugNameTableKind NTK) { } return nullptr; } +DISubprogram::DISubprogram(LLVMContext &C, StorageType Storage, unsigned Line, + unsigned ScopeLine, unsigned VirtualIndex, + int ThisAdjustment, DIFlags Flags, DISPFlags SPFlags, + ArrayRef<Metadata *> Ops) + : DILocalScope(C, DISubprogramKind, Storage, dwarf::DW_TAG_subprogram, Ops), + Line(Line), ScopeLine(ScopeLine), VirtualIndex(VirtualIndex), + ThisAdjustment(ThisAdjustment), Flags(Flags), SPFlags(SPFlags) { + static_assert(dwarf::DW_VIRTUALITY_max < 4, "Virtuality out of range"); +} +DISubprogram::DISPFlags +DISubprogram::toSPFlags(bool IsLocalToUnit, bool IsDefinition, bool IsOptimized, + unsigned Virtuality, bool IsMainSubprogram) { + // We're assuming virtuality is the low-order field. + static_assert(int(SPFlagVirtual) == int(dwarf::DW_VIRTUALITY_virtual) && + int(SPFlagPureVirtual) == + int(dwarf::DW_VIRTUALITY_pure_virtual), + "Virtuality constant mismatch"); + return static_cast<DISPFlags>( + (Virtuality & SPFlagVirtuality) | + (IsLocalToUnit ? SPFlagLocalToUnit : SPFlagZero) | + (IsDefinition ? SPFlagDefinition : SPFlagZero) | + (IsOptimized ? SPFlagOptimized : SPFlagZero) | + (IsMainSubprogram ? SPFlagMainSubprogram : SPFlagZero)); +} DISubprogram *DILocalScope::getSubprogram() const { if (auto *Block = dyn_cast<DILexicalBlockBase>(this)) @@ -881,27 +980,33 @@ DISubprogram *DISubprogram::getImpl( unsigned ScopeLine, Metadata *ContainingType, unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags, DISPFlags SPFlags, Metadata *Unit, Metadata *TemplateParams, Metadata *Declaration, Metadata *RetainedNodes, - Metadata *ThrownTypes, Metadata *Annotations, StorageType Storage, - bool ShouldCreate) { + Metadata *ThrownTypes, Metadata *Annotations, MDString *TargetFuncName, + StorageType Storage, bool ShouldCreate) { assert(isCanonical(Name) && "Expected canonical MDString"); assert(isCanonical(LinkageName) && "Expected canonical MDString"); + assert(isCanonical(TargetFuncName) && "Expected canonical MDString"); DEFINE_GETIMPL_LOOKUP(DISubprogram, (Scope, Name, LinkageName, File, Line, Type, ScopeLine, ContainingType, VirtualIndex, ThisAdjustment, Flags, SPFlags, Unit, TemplateParams, Declaration, - RetainedNodes, ThrownTypes, Annotations)); - SmallVector<Metadata *, 12> Ops = { + RetainedNodes, ThrownTypes, Annotations, + TargetFuncName)); + SmallVector<Metadata *, 13> Ops = { File, Scope, Name, LinkageName, Type, Unit, Declaration, RetainedNodes, - ContainingType, TemplateParams, ThrownTypes, Annotations}; - if (!Annotations) { + ContainingType, TemplateParams, ThrownTypes, Annotations, + TargetFuncName}; + if (!TargetFuncName) { Ops.pop_back(); - if (!ThrownTypes) { + if (!Annotations) { Ops.pop_back(); - if (!TemplateParams) { + if (!ThrownTypes) { Ops.pop_back(); - if (!ContainingType) + if (!TemplateParams) { Ops.pop_back(); + if (!ContainingType) + Ops.pop_back(); + } } } } @@ -915,6 +1020,10 @@ bool DISubprogram::describes(const Function *F) const { assert(F && "Invalid function"); return F->getSubprogram() == this; } +DILexicalBlockBase::DILexicalBlockBase(LLVMContext &C, unsigned ID, + StorageType Storage, + ArrayRef<Metadata *> Ops) + : DILocalScope(C, ID, Storage, dwarf::DW_TAG_lexical_block, Ops) {} DILexicalBlock *DILexicalBlock::getImpl(LLVMContext &Context, Metadata *Scope, Metadata *File, unsigned Line, @@ -940,6 +1049,10 @@ DILexicalBlockFile *DILexicalBlockFile::getImpl(LLVMContext &Context, DEFINE_GETIMPL_STORE(DILexicalBlockFile, (Discriminator), Ops); } +DINamespace::DINamespace(LLVMContext &Context, StorageType Storage, + bool ExportSymbols, ArrayRef<Metadata *> Ops) + : DIScope(Context, DINamespaceKind, Storage, dwarf::DW_TAG_namespace, Ops), + ExportSymbols(ExportSymbols) {} DINamespace *DINamespace::getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, bool ExportSymbols, StorageType Storage, bool ShouldCreate) { @@ -950,6 +1063,11 @@ DINamespace *DINamespace::getImpl(LLVMContext &Context, Metadata *Scope, DEFINE_GETIMPL_STORE(DINamespace, (ExportSymbols), Ops); } +DICommonBlock::DICommonBlock(LLVMContext &Context, StorageType Storage, + unsigned LineNo, ArrayRef<Metadata *> Ops) + : DIScope(Context, DICommonBlockKind, Storage, dwarf::DW_TAG_common_block, + Ops), + LineNo(LineNo) {} DICommonBlock *DICommonBlock::getImpl(LLVMContext &Context, Metadata *Scope, Metadata *Decl, MDString *Name, Metadata *File, unsigned LineNo, @@ -961,6 +1079,10 @@ DICommonBlock *DICommonBlock::getImpl(LLVMContext &Context, Metadata *Scope, DEFINE_GETIMPL_STORE(DICommonBlock, (LineNo), Ops); } +DIModule::DIModule(LLVMContext &Context, StorageType Storage, unsigned LineNo, + bool IsDecl, ArrayRef<Metadata *> Ops) + : DIScope(Context, DIModuleKind, Storage, dwarf::DW_TAG_module, Ops), + LineNo(LineNo), IsDecl(IsDecl) {} DIModule *DIModule::getImpl(LLVMContext &Context, Metadata *File, Metadata *Scope, MDString *Name, MDString *ConfigurationMacros, @@ -974,6 +1096,13 @@ DIModule *DIModule::getImpl(LLVMContext &Context, Metadata *File, IncludePath, APINotesFile}; DEFINE_GETIMPL_STORE(DIModule, (LineNo, IsDecl), Ops); } +DITemplateTypeParameter::DITemplateTypeParameter(LLVMContext &Context, + StorageType Storage, + bool IsDefault, + ArrayRef<Metadata *> Ops) + : DITemplateParameter(Context, DITemplateTypeParameterKind, Storage, + dwarf::DW_TAG_template_type_parameter, IsDefault, + Ops) {} DITemplateTypeParameter * DITemplateTypeParameter::getImpl(LLVMContext &Context, MDString *Name, @@ -1039,6 +1168,11 @@ DILocalVariable::getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, DEFINE_GETIMPL_STORE(DILocalVariable, (Line, Arg, Flags, AlignInBits), Ops); } +DIVariable::DIVariable(LLVMContext &C, unsigned ID, StorageType Storage, + signed Line, ArrayRef<Metadata *> Ops, + uint32_t AlignInBits) + : DINode(C, ID, Storage, dwarf::DW_TAG_variable, Ops), Line(Line), + AlignInBits(AlignInBits) {} Optional<uint64_t> DIVariable::getSizeInBits() const { // This is used by the Verifier so be mindful of broken types. const Metadata *RawType = getRawType(); @@ -1062,6 +1196,9 @@ Optional<uint64_t> DIVariable::getSizeInBits() const { return None; } +DILabel::DILabel(LLVMContext &C, StorageType Storage, unsigned Line, + ArrayRef<Metadata *> Ops) + : DINode(C, DILabelKind, Storage, dwarf::DW_TAG_label, Ops), Line(Line) {} DILabel *DILabel::getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, Metadata *File, unsigned Line, StorageType Storage, bool ShouldCreate) { @@ -1078,6 +1215,12 @@ DIExpression *DIExpression::getImpl(LLVMContext &Context, DEFINE_GETIMPL_LOOKUP(DIExpression, (Elements)); DEFINE_GETIMPL_STORE_NO_OPS(DIExpression, (Elements)); } +bool DIExpression::isEntryValue() const { + return getNumElements() > 0 && getElement(0) == dwarf::DW_OP_LLVM_entry_value; +} +bool DIExpression::startsWithDeref() const { + return getNumElements() > 0 && getElement(0) == dwarf::DW_OP_deref; +} unsigned DIExpression::ExprOperand::getSize() const { uint64_t Op = getOp(); @@ -1439,7 +1582,7 @@ DIExpression *DIExpression::appendToStack(const DIExpression *Expr, // // Match .* DW_OP_stack_value (DW_OP_LLVM_fragment A B)?. Optional<FragmentInfo> FI = Expr->getFragmentInfo(); - unsigned DropUntilStackValue = FI.hasValue() ? 3 : 0; + unsigned DropUntilStackValue = FI ? 3 : 0; ArrayRef<uint64_t> ExprOpsBeforeFragment = Expr->getElements().drop_back(DropUntilStackValue); bool NeedsDeref = (Expr->getNumElements() > DropUntilStackValue) && @@ -1597,6 +1740,11 @@ DIGlobalVariableExpression::getImpl(LLVMContext &Context, Metadata *Variable, Metadata *Ops[] = {Variable, Expression}; DEFINE_GETIMPL_STORE_NO_CONSTRUCTOR_ARGS(DIGlobalVariableExpression, Ops); } +DIObjCProperty::DIObjCProperty(LLVMContext &C, StorageType Storage, + unsigned Line, unsigned Attributes, + ArrayRef<Metadata *> Ops) + : DINode(C, DIObjCPropertyKind, Storage, dwarf::DW_TAG_APPLE_property, Ops), + Line(Line), Attributes(Attributes) {} DIObjCProperty *DIObjCProperty::getImpl( LLVMContext &Context, MDString *Name, Metadata *File, unsigned Line, |