const Metadata *MD = nullptr;
public:
+ TypedDebugNodeRef() = default;
TypedDebugNodeRef(std::nullptr_t) {}
/// \brief Construct from a raw pointer.
assert(Tag < 1u << 16);
SubclassData16 = Tag;
}
- ~DebugNode() {}
+ ~DebugNode() = default;
template <class Ty> Ty *getOperandAs(unsigned I) const {
return cast_or_null<Ty>(getOperand(I));
: DebugNode(C, MDSubrangeKind, Storage, dwarf::DW_TAG_subrange_type,
None),
Count(Count), LowerBound(LowerBound) {}
- ~MDSubrange() {}
+ ~MDSubrange() = default;
static MDSubrange *getImpl(LLVMContext &Context, int64_t Count,
int64_t LowerBound, StorageType Storage,
ArrayRef<Metadata *> Ops)
: DebugNode(C, MDEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops),
Value(Value) {}
- ~MDEnumerator() {}
+ ~MDEnumerator() = default;
static MDEnumerator *getImpl(LLVMContext &Context, int64_t Value,
StringRef Name, StorageType Storage,
MDScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag,
ArrayRef<Metadata *> Ops)
: DebugNode(C, ID, Storage, Tag, Ops) {}
- ~MDScope() {}
+ ~MDScope() = default;
public:
MDFile *getFile() const { return cast_or_null<MDFile>(getRawFile()); }
+ inline StringRef getFilename() const;
+ inline StringRef getDirectory() const;
+
+ StringRef getName() const;
+ MDScopeRef getScope() const;
+
/// \brief Return the raw underlying file.
///
/// An \a MDFile is an \a MDScope, but it doesn't point at a separate file
MDFile(LLVMContext &C, StorageType Storage, ArrayRef<Metadata *> Ops)
: MDScope(C, MDFileKind, Storage, dwarf::DW_TAG_file_type, Ops) {}
- ~MDFile() {}
+ ~MDFile() = default;
static MDFile *getImpl(LLVMContext &Context, StringRef Filename,
StringRef Directory, StorageType Storage,
}
};
+StringRef MDScope::getFilename() const {
+ if (auto *F = getFile())
+ return F->getFilename();
+ return "";
+}
+
+StringRef MDScope::getDirectory() const {
+ if (auto *F = getFile())
+ return F->getDirectory();
+ return "";
+}
+
/// \brief Base class for types.
///
/// TODO: Remove the hardcoded name and context, since many types don't use
: MDScope(C, ID, Storage, Tag, Ops), Line(Line), Flags(Flags),
SizeInBits(SizeInBits), AlignInBits(AlignInBits),
OffsetInBits(OffsetInBits) {}
- ~MDType() {}
+ ~MDType() = default;
public:
TempMDType clone() const {
: MDType(C, MDBasicTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0,
0, Ops),
Encoding(Encoding) {}
- ~MDBasicType() {}
+ ~MDBasicType() = default;
static MDBasicType *getImpl(LLVMContext &Context, unsigned Tag,
StringRef Name, uint64_t SizeInBits,
ArrayRef<Metadata *> Ops)
: MDType(C, ID, Storage, Tag, Line, SizeInBits, AlignInBits, OffsetInBits,
Flags, Ops) {}
- ~MDDerivedTypeBase() {}
+ ~MDDerivedTypeBase() = default;
public:
MDTypeRef getBaseType() const { return MDTypeRef(getRawBaseType()); }
uint64_t OffsetInBits, unsigned Flags, ArrayRef<Metadata *> Ops)
: MDDerivedTypeBase(C, MDDerivedTypeKind, Storage, Tag, Line, SizeInBits,
AlignInBits, OffsetInBits, Flags, Ops) {}
- ~MDDerivedType() {}
+ ~MDDerivedType() = default;
static MDDerivedType *getImpl(LLVMContext &Context, unsigned Tag,
StringRef Name, MDFile *File, unsigned Line,
Metadata *getExtraData() const { return getRawExtraData(); }
Metadata *getRawExtraData() const { return getOperand(4); }
+ /// \brief Get casted version of extra data.
+ /// @{
+ MDTypeRef getClassType() const {
+ assert(getTag() == dwarf::DW_TAG_ptr_to_member_type);
+ return MDTypeRef(getExtraData());
+ }
+ MDObjCProperty *getObjCProperty() const {
+ return dyn_cast_or_null<MDObjCProperty>(getExtraData());
+ }
+ Constant *getConstant() const {
+ assert(getTag() == dwarf::DW_TAG_member && isStaticMember());
+ if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData()))
+ return C->getValue();
+ return nullptr;
+ }
+ /// @}
+
static bool classof(const Metadata *MD) {
return MD->getMetadataID() == MDDerivedTypeKind;
}
: MDDerivedTypeBase(C, ID, Storage, Tag, Line, SizeInBits, AlignInBits,
OffsetInBits, Flags, Ops),
RuntimeLang(RuntimeLang) {}
- ~MDCompositeTypeBase() {}
+ ~MDCompositeTypeBase() = default;
public:
+ /// \brief Get the elements of the composite type.
+ ///
+ /// \note Calling this is only valid for \a MDCompositeType. This assertion
+ /// can be removed once \a MDSubroutineType has been separated from
+ /// "composite types".
DebugNodeArray getElements() const {
+ assert(!isa<MDSubroutineType>(this) && "no elements for DISubroutineType");
return cast_or_null<MDTuple>(getRawElements());
}
MDTypeRef getVTableHolder() const { return MDTypeRef(getRawVTableHolder()); }
: MDCompositeTypeBase(C, MDCompositeTypeKind, Storage, Tag, Line,
RuntimeLang, SizeInBits, AlignInBits, OffsetInBits,
Flags, Ops) {}
- ~MDCompositeType() {}
+ ~MDCompositeType() = default;
static MDCompositeType *
getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, Metadata *File,
: MDCompositeTypeBase(C, MDSubroutineTypeKind, Storage,
dwarf::DW_TAG_subroutine_type, 0, 0, 0, 0, 0, Flags,
Ops) {}
- ~MDSubroutineType() {}
+ ~MDSubroutineType() = default;
static MDSubroutineType *getImpl(LLVMContext &Context, unsigned Flags,
MDTypeRefArray TypeArray,
: MDScope(C, MDCompileUnitKind, Storage, dwarf::DW_TAG_compile_unit, Ops),
SourceLanguage(SourceLanguage), IsOptimized(IsOptimized),
RuntimeVersion(RuntimeVersion), EmissionKind(EmissionKind) {}
- ~MDCompileUnit() {}
+ ~MDCompileUnit() = default;
static MDCompileUnit *
getImpl(LLVMContext &Context, unsigned SourceLanguage, MDFile *File,
MDLocalScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag,
ArrayRef<Metadata *> Ops)
: MDScope(C, ID, Storage, Tag, Ops) {}
- ~MDLocalScope() {}
+ ~MDLocalScope() = default;
public:
/// \brief Get the subprogram for this scope.
return cast_or_null<MDLocation>(getRawInlinedAt());
}
+ MDFile *getFile() const { return getScope()->getFile(); }
+ StringRef getFilename() const { return getScope()->getFilename(); }
+ StringRef getDirectory() const { return getScope()->getDirectory(); }
+
/// \brief Get the scope where this is inlined.
///
/// Walk through \a getInlinedAt() and return \a getScope() from the deepest
return getScope();
}
+ /// \brief Check whether this can be discriminated from another location.
+ ///
+ /// Check \c this can be discriminated from \c RHS in a linetable entry.
+ /// Scope and inlined-at chains are not recorded in the linetable, so they
+ /// cannot be used to distinguish basic blocks.
+ ///
+ /// The current implementation is weaker than it should be, since it just
+ /// checks filename and line.
+ ///
+ /// FIXME: Add a check for getDiscriminator().
+ /// FIXME: Add a check for getColumn().
+ /// FIXME: Change the getFilename() check to getFile() (or add one for
+ /// getDirectory()).
+ bool canDiscriminate(const MDLocation &RHS) const {
+ return getFilename() != RHS.getFilename() || getLine() != RHS.getLine();
+ }
+
+ /// \brief Get the DWARF discriminator.
+ ///
+ /// DWARF discriminators distinguish identical file locations between
+ /// instructions that are on different basic blocks.
+ inline unsigned getDiscriminator() const;
+
+ /// \brief Compute new discriminator in the given context.
+ ///
+ /// This modifies the \a LLVMContext that \c this is in to increment the next
+ /// discriminator for \c this's line/filename combination.
+ ///
+ /// FIXME: Delete this. See comments in implementation and at the only call
+ /// site in \a AddDiscriminators::runOnFunction().
+ unsigned computeNewDiscriminator() const;
+
Metadata *getRawScope() const { return getOperand(0); }
Metadata *getRawInlinedAt() const {
if (getNumOperands() == 2)
Line(Line), ScopeLine(ScopeLine), Virtuality(Virtuality),
VirtualIndex(VirtualIndex), Flags(Flags), IsLocalToUnit(IsLocalToUnit),
IsDefinition(IsDefinition), IsOptimized(IsOptimized) {}
- ~MDSubprogram() {}
+ ~MDSubprogram() = default;
static MDSubprogram *
getImpl(LLVMContext &Context, MDScopeRef Scope, StringRef Name,
MDSubroutineType *Type, bool IsLocalToUnit, bool IsDefinition,
unsigned ScopeLine, MDTypeRef ContainingType, unsigned Virtuality,
unsigned VirtualIndex, unsigned Flags, bool IsOptimized,
- ConstantAsMetadata *Function, MDTemplateParameterArray TemplateParams,
+ Constant *Function, MDTemplateParameterArray TemplateParams,
MDSubprogram *Declaration, MDLocalVariableArray Variables,
StorageType Storage, bool ShouldCreate = true) {
return getImpl(Context, Scope, getCanonicalMDString(Context, Name),
getCanonicalMDString(Context, LinkageName), File, Line, Type,
IsLocalToUnit, IsDefinition, ScopeLine, ContainingType,
- Virtuality, VirtualIndex, Flags, IsOptimized, Function,
+ Virtuality, VirtualIndex, Flags, IsOptimized,
+ Function ? ConstantAsMetadata::get(Function) : nullptr,
TemplateParams.get(), Declaration, Variables.get(), Storage,
ShouldCreate);
}
getFile(), getLine(), getType(), isLocalToUnit(),
isDefinition(), getScopeLine(), getContainingType(),
getVirtuality(), getVirtualIndex(), getFlags(),
- isOptimized(), getFunction(), getTemplateParams(),
- getDeclaration(), getVariables());
+ isOptimized(), getFunctionConstant(),
+ getTemplateParams(), getDeclaration(), getVariables());
}
public:
bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine,
MDTypeRef ContainingType, unsigned Virtuality,
unsigned VirtualIndex, unsigned Flags, bool IsOptimized,
- ConstantAsMetadata *Function = nullptr,
+ Constant *Function = nullptr,
MDTemplateParameterArray TemplateParams = nullptr,
MDSubprogram *Declaration = nullptr,
MDLocalVariableArray Variables = nullptr),
return MDTypeRef(getRawContainingType());
}
- ConstantAsMetadata *getFunction() const {
- return cast_or_null<ConstantAsMetadata>(getRawFunction());
+ Constant *getFunctionConstant() const {
+ if (auto *C = cast_or_null<ConstantAsMetadata>(getRawFunction()))
+ return C->getValue();
+ return nullptr;
}
MDTemplateParameterArray getTemplateParams() const {
return cast_or_null<MDTuple>(getRawTemplateParams());
Metadata *getRawDeclaration() const { return getOperand(9); }
Metadata *getRawVariables() const { return getOperand(10); }
+ /// \brief Get a pointer to the function this subprogram describes.
+ ///
+ /// This dyn_casts \a getFunctionConstant() to \a Function.
+ ///
+ /// FIXME: Should this be looking through bitcasts?
+ Function *getFunction() const;
+
/// \brief Replace the function.
///
/// If \a isUniqued() and not \a isResolved(), this could node will be
void replaceFunction(std::nullptr_t) { replaceOperandWith(7, nullptr); }
/// @}
+ /// \brief Check if this subprogram decribes the given function.
+ ///
+ /// FIXME: Should this be looking through bitcasts?
+ bool describes(const Function *F) const;
+
static bool classof(const Metadata *MD) {
return MD->getMetadataID() == MDSubprogramKind;
}
MDLexicalBlockBase(LLVMContext &C, unsigned ID, StorageType Storage,
ArrayRef<Metadata *> Ops)
: MDLocalScope(C, ID, Storage, dwarf::DW_TAG_lexical_block, Ops) {}
- ~MDLexicalBlockBase() {}
+ ~MDLexicalBlockBase() = default;
public:
MDLocalScope *getScope() const { return cast<MDLocalScope>(getRawScope()); }
Metadata *getRawScope() const { return getOperand(1); }
+ /// \brief Forwarding accessors to LexicalBlock.
+ ///
+ /// TODO: Remove these and update code to use \a MDLexicalBlock directly.
+ /// @{
+ inline unsigned getLine() const;
+ inline unsigned getColumn() const;
+ /// @}
static bool classof(const Metadata *MD) {
return MD->getMetadataID() == MDLexicalBlockKind ||
MD->getMetadataID() == MDLexicalBlockFileKind;
unsigned Column, ArrayRef<Metadata *> Ops)
: MDLexicalBlockBase(C, MDLexicalBlockKind, Storage, Ops), Line(Line),
Column(Column) {}
- ~MDLexicalBlock() {}
+ ~MDLexicalBlock() = default;
static MDLexicalBlock *getImpl(LLVMContext &Context, MDLocalScope *Scope,
MDFile *File, unsigned Line, unsigned Column,
}
};
+unsigned MDLexicalBlockBase::getLine() const {
+ if (auto *N = dyn_cast<MDLexicalBlock>(this))
+ return N->getLine();
+ return 0;
+}
+
+unsigned MDLexicalBlockBase::getColumn() const {
+ if (auto *N = dyn_cast<MDLexicalBlock>(this))
+ return N->getColumn();
+ return 0;
+}
+
class MDLexicalBlockFile : public MDLexicalBlockBase {
friend class LLVMContextImpl;
friend class MDNode;
unsigned Discriminator, ArrayRef<Metadata *> Ops)
: MDLexicalBlockBase(C, MDLexicalBlockFileKind, Storage, Ops),
Discriminator(Discriminator) {}
- ~MDLexicalBlockFile() {}
+ ~MDLexicalBlockFile() = default;
static MDLexicalBlockFile *getImpl(LLVMContext &Context, MDLocalScope *Scope,
MDFile *File, unsigned Discriminator,
TempMDLexicalBlockFile clone() const { return cloneImpl(); }
+ // TODO: Remove these once they're gone from MDLexicalBlockBase.
+ unsigned getLine() const = delete;
+ unsigned getColumn() const = delete;
+
unsigned getDiscriminator() const { return Discriminator; }
static bool classof(const Metadata *MD) {
}
};
+unsigned MDLocation::getDiscriminator() const {
+ if (auto *F = dyn_cast<MDLexicalBlockFile>(getScope()))
+ return F->getDiscriminator();
+ return 0;
+}
+
class MDNamespace : public MDScope {
friend class LLVMContextImpl;
friend class MDNode;
: MDScope(Context, MDNamespaceKind, Storage, dwarf::DW_TAG_namespace,
Ops),
Line(Line) {}
- ~MDNamespace() {}
+ ~MDNamespace() = default;
static MDNamespace *getImpl(LLVMContext &Context, MDScope *Scope,
MDFile *File, StringRef Name, unsigned Line,
MDTemplateParameter(LLVMContext &Context, unsigned ID, StorageType Storage,
unsigned Tag, ArrayRef<Metadata *> Ops)
: DebugNode(Context, ID, Storage, Tag, Ops) {}
- ~MDTemplateParameter() {}
+ ~MDTemplateParameter() = default;
public:
StringRef getName() const { return getStringOperand(0); }
ArrayRef<Metadata *> Ops)
: MDTemplateParameter(Context, MDTemplateTypeParameterKind, Storage,
dwarf::DW_TAG_template_type_parameter, Ops) {}
- ~MDTemplateTypeParameter() {}
+ ~MDTemplateTypeParameter() = default;
static MDTemplateTypeParameter *getImpl(LLVMContext &Context, StringRef Name,
MDTypeRef Type, StorageType Storage,
unsigned Tag, ArrayRef<Metadata *> Ops)
: MDTemplateParameter(Context, MDTemplateValueParameterKind, Storage, Tag,
Ops) {}
- ~MDTemplateValueParameter() {}
+ ~MDTemplateValueParameter() = default;
static MDTemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag,
StringRef Name, MDTypeRef Type,
MDVariable(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag,
unsigned Line, ArrayRef<Metadata *> Ops)
: DebugNode(C, ID, Storage, Tag, Ops), Line(Line) {}
- ~MDVariable() {}
+ ~MDVariable() = default;
public:
unsigned getLine() const { return Line; }
MDFile *getFile() const { return cast_or_null<MDFile>(getRawFile()); }
MDTypeRef getType() const { return MDTypeRef(getRawType()); }
+ StringRef getFilename() const {
+ if (auto *F = getFile())
+ return F->getFilename();
+ return "";
+ }
+ StringRef getDirectory() const {
+ if (auto *F = getFile())
+ return F->getDirectory();
+ return "";
+ }
+
Metadata *getRawScope() const { return getOperand(0); }
MDString *getRawName() const { return getOperandAs<MDString>(1); }
Metadata *getRawFile() const { return getOperand(2); }
: MDVariable(C, MDGlobalVariableKind, Storage, dwarf::DW_TAG_variable,
Line, Ops),
IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition) {}
- ~MDGlobalVariable() {}
+ ~MDGlobalVariable() = default;
static MDGlobalVariable *
getImpl(LLVMContext &Context, MDScope *Scope, StringRef Name,
StringRef LinkageName, MDFile *File, unsigned Line, MDTypeRef Type,
- bool IsLocalToUnit, bool IsDefinition, ConstantAsMetadata *Variable,
+ bool IsLocalToUnit, bool IsDefinition, Constant *Variable,
MDDerivedType *StaticDataMemberDeclaration, StorageType Storage,
bool ShouldCreate = true) {
return getImpl(Context, Scope, getCanonicalMDString(Context, Name),
getCanonicalMDString(Context, LinkageName), File, Line, Type,
- IsLocalToUnit, IsDefinition, Variable,
+ IsLocalToUnit, IsDefinition,
+ Variable ? ConstantAsMetadata::get(Variable) : nullptr,
StaticDataMemberDeclaration, Storage, ShouldCreate);
}
static MDGlobalVariable *
DEFINE_MDNODE_GET(MDGlobalVariable,
(MDScope * Scope, StringRef Name, StringRef LinkageName,
MDFile *File, unsigned Line, MDTypeRef Type,
- bool IsLocalToUnit, bool IsDefinition,
- ConstantAsMetadata *Variable,
+ bool IsLocalToUnit, bool IsDefinition, Constant *Variable,
MDDerivedType *StaticDataMemberDeclaration),
(Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit,
IsDefinition, Variable, StaticDataMemberDeclaration))
bool isDefinition() const { return IsDefinition; }
StringRef getDisplayName() const { return getStringOperand(4); }
StringRef getLinkageName() const { return getStringOperand(5); }
- ConstantAsMetadata *getVariable() const {
- return cast_or_null<ConstantAsMetadata>(getRawVariable());
+ Constant *getVariable() const {
+ if (auto *C = cast_or_null<ConstantAsMetadata>(getRawVariable()))
+ return dyn_cast<Constant>(C->getValue());
+ return nullptr;
}
MDDerivedType *getStaticDataMemberDeclaration() const {
return cast_or_null<MDDerivedType>(getRawStaticDataMemberDeclaration());
ArrayRef<Metadata *> Ops)
: MDVariable(C, MDLocalVariableKind, Storage, Tag, Line, Ops), Arg(Arg),
Flags(Flags) {}
- ~MDLocalVariable() {}
+ ~MDLocalVariable() = default;
static MDLocalVariable *getImpl(LLVMContext &Context, unsigned Tag,
MDScope *Scope, StringRef Name, MDFile *File,
/// \brief DWARF expression.
///
+/// This is (almost) a DWARF expression that modifies the location of a
+/// variable or (or the location of a single piece of a variable).
+///
+/// FIXME: Instead of DW_OP_plus taking an argument, this should use DW_OP_const
+/// and have DW_OP_plus consume the topmost elements on the stack.
+///
/// TODO: Co-allocate the expression elements.
/// TODO: Separate from MDNode, or otherwise drop Distinct and Temporary
/// storage types.
MDExpression(LLVMContext &C, StorageType Storage, ArrayRef<uint64_t> Elements)
: MDNode(C, MDExpressionKind, Storage, None),
Elements(Elements.begin(), Elements.end()) {}
- ~MDExpression() {}
+ ~MDExpression() = default;
static MDExpression *getImpl(LLVMContext &Context,
ArrayRef<uint64_t> Elements, StorageType Storage,
: DebugNode(C, MDObjCPropertyKind, Storage, dwarf::DW_TAG_APPLE_property,
Ops),
Line(Line), Attributes(Attributes) {}
- ~MDObjCProperty() {}
+ ~MDObjCProperty() = default;
static MDObjCProperty *
getImpl(LLVMContext &Context, StringRef Name, MDFile *File, unsigned Line,
MDFile *getFile() const { return cast_or_null<MDFile>(getRawFile()); }
StringRef getGetterName() const { return getStringOperand(2); }
StringRef getSetterName() const { return getStringOperand(3); }
+
+ /// \brief Get the type.
+ ///
+ /// \note Objective-C doesn't have an ODR, so there is no benefit in storing
+ /// the type as a DITypeRef here.
MDType *getType() const { return cast_or_null<MDType>(getRawType()); }
+ StringRef getFilename() const {
+ if (auto *F = getFile())
+ return F->getFilename();
+ return "";
+ }
+ StringRef getDirectory() const {
+ if (auto *F = getFile())
+ return F->getDirectory();
+ return "";
+ }
+
MDString *getRawName() const { return getOperandAs<MDString>(0); }
Metadata *getRawFile() const { return getOperand(1); }
MDString *getRawGetterName() const { return getOperandAs<MDString>(2); }
}
};
+/// \brief An imported module (C++ using directive or similar).
class MDImportedEntity : public DebugNode {
friend class LLVMContextImpl;
friend class MDNode;
MDImportedEntity(LLVMContext &C, StorageType Storage, unsigned Tag,
unsigned Line, ArrayRef<Metadata *> Ops)
: DebugNode(C, MDImportedEntityKind, Storage, Tag, Ops), Line(Line) {}
- ~MDImportedEntity() {}
+ ~MDImportedEntity() = default;
static MDImportedEntity *getImpl(LLVMContext &Context, unsigned Tag,
MDScope *Scope, DebugNodeRef Entity,