using namespace llvm;
+static Metadata *unwrapMetadata(LLVMValueRef VRef) {
+ Value *V = unwrap(VRef);
+ if (!V)
+ return nullptr;
+ if (auto *MD = dyn_cast<MetadataAsValue>(V))
+ return MD->getMetadata();
+ return ValueAsMetadata::get(V);
+}
+
+static SmallVector<Metadata *, 8> unwrapMetadataArray(LLVMValueRef *Data,
+ size_t Length) {
+ SmallVector<Metadata *, 8> Elements;
+ for (size_t I = 0; I != Length; ++I)
+ Elements.push_back(unwrapMetadata(Data[I]));
+ return Elements;
+}
+
namespace {
template <typename T> T unwrapDI(LLVMValueRef v) {
- return v ? T(unwrap<MDNode>(v)) : T();
+ return T(cast_or_null<MDNode>(unwrapMetadata(v)));
+}
}
+
+static LLVMValueRef wrapDI(DIDescriptor N) {
+ return wrap(MetadataAsValue::get(N->getContext(), N));
}
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DIBuilder, LLVMDIBuilderRef)
DIBuilder *D = unwrap(Dref);
DICompileUnit CU = D->createCompileUnit(Lang, File, Dir, Producer, Optimized,
Flags, RuntimeVersion);
- return wrap(CU);
+ return wrapDI(CU);
}
LLVMValueRef LLVMDIBuilderCreateFile(LLVMDIBuilderRef Dref, const char *File,
const char *Dir) {
DIBuilder *D = unwrap(Dref);
DIFile F = D->createFile(File, Dir);
- return wrap(F);
+ return wrapDI(F);
}
LLVMValueRef LLVMDIBuilderCreateLexicalBlock(LLVMDIBuilderRef Dref,
DIBuilder *D = unwrap(Dref);
DILexicalBlock LB = D->createLexicalBlock(
unwrapDI<DIDescriptor>(Scope), unwrapDI<DIFile>(File), Line, Column);
- return wrap(LB);
+ return wrapDI(LB);
}
LLVMValueRef LLVMDIBuilderCreateLexicalBlockFile(LLVMDIBuilderRef Dref,
DIBuilder *D = unwrap(Dref);
DILexicalBlockFile LBF = D->createLexicalBlockFile(
unwrapDI<DIDescriptor>(Scope), unwrapDI<DIFile>(File), Discriminator);
- return wrap(LBF);
+ return wrapDI(LBF);
}
LLVMValueRef LLVMDIBuilderCreateFunction(
unwrapDI<DIDescriptor>(Scope), Name, LinkageName, unwrapDI<DIFile>(File),
Line, unwrapDI<DICompositeType>(CompositeType), IsLocalToUnit,
IsDefinition, ScopeLine, Flags, IsOptimized, unwrap<Function>(Func));
- return wrap(SP);
+ return wrapDI(SP);
}
LLVMValueRef LLVMDIBuilderCreateLocalVariable(
DIVariable V = D->createLocalVariable(
Tag, unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), Line,
unwrapDI<DIType>(Ty), AlwaysPreserve, Flags, ArgNo);
- return wrap(V);
+ return wrapDI(V);
}
LLVMValueRef LLVMDIBuilderCreateBasicType(LLVMDIBuilderRef Dref,
unsigned Encoding) {
DIBuilder *D = unwrap(Dref);
DIBasicType T = D->createBasicType(Name, SizeInBits, AlignInBits, Encoding);
- return wrap(T);
+ return wrapDI(T);
}
LLVMValueRef LLVMDIBuilderCreatePointerType(LLVMDIBuilderRef Dref,
DIBuilder *D = unwrap(Dref);
DIDerivedType T = D->createPointerType(unwrapDI<DIType>(PointeeType),
SizeInBits, AlignInBits, Name);
- return wrap(T);
+ return wrapDI(T);
}
LLVMValueRef LLVMDIBuilderCreateSubroutineType(LLVMDIBuilderRef Dref,
DIBuilder *D = unwrap(Dref);
DICompositeType CT = D->createSubroutineType(
unwrapDI<DIFile>(File), unwrapDI<DITypeArray>(ParameterTypes));
- return wrap(CT);
+ return wrapDI(CT);
}
LLVMValueRef LLVMDIBuilderCreateStructType(
unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), Line,
SizeInBits, AlignInBits, Flags, unwrapDI<DIType>(DerivedFrom),
unwrapDI<DIArray>(ElementTypes));
- return wrap(CT);
+ return wrapDI(CT);
}
LLVMValueRef LLVMDIBuilderCreateMemberType(
DIDerivedType DT = D->createMemberType(
unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), Line,
SizeInBits, AlignInBits, OffsetInBits, Flags, unwrapDI<DIType>(Ty));
- return wrap(DT);
+ return wrapDI(DT);
}
LLVMValueRef LLVMDIBuilderCreateArrayType(LLVMDIBuilderRef Dref,
DICompositeType CT =
D->createArrayType(SizeInBits, AlignInBits, unwrapDI<DIType>(ElementType),
unwrapDI<DIArray>(Subscripts));
- return wrap(CT);
+ return wrapDI(CT);
}
LLVMValueRef LLVMDIBuilderCreateTypedef(LLVMDIBuilderRef Dref, LLVMValueRef Ty,
DIDerivedType DT =
D->createTypedef(unwrapDI<DIType>(Ty), Name, unwrapDI<DIFile>(File), Line,
unwrapDI<DIDescriptor>(Context));
- return wrap(DT);
+ return wrapDI(DT);
}
LLVMValueRef LLVMDIBuilderGetOrCreateSubrange(LLVMDIBuilderRef Dref, int64_t Lo,
int64_t Count) {
DIBuilder *D = unwrap(Dref);
DISubrange S = D->getOrCreateSubrange(Lo, Count);
- return wrap(S);
+ return wrapDI(S);
}
LLVMValueRef LLVMDIBuilderGetOrCreateArray(LLVMDIBuilderRef Dref,
LLVMValueRef *Data, size_t Length) {
DIBuilder *D = unwrap(Dref);
- Value **DataValue = unwrap(Data);
- ArrayRef<Value *> Elements(DataValue, Length);
- DIArray A = D->getOrCreateArray(Elements);
- return wrap(A);
+ DIArray A = D->getOrCreateArray(unwrapMetadataArray(Data, Length));
+ return wrapDI(A);
}
LLVMValueRef LLVMDIBuilderGetOrCreateTypeArray(LLVMDIBuilderRef Dref,
LLVMValueRef *Data,
size_t Length) {
DIBuilder *D = unwrap(Dref);
- Value **DataValue = unwrap(Data);
- ArrayRef<Value *> Elements(DataValue, Length);
- DITypeArray A = D->getOrCreateTypeArray(Elements);
- return wrap(A);
+ DITypeArray A = D->getOrCreateTypeArray(unwrapMetadataArray(Data, Length));
+ return wrapDI(A);
}
LLVMValueRef LLVMDIBuilderCreateExpression(LLVMDIBuilderRef Dref, int64_t *Addr,
size_t Length) {
DIBuilder *D = unwrap(Dref);
DIExpression Expr = D->createExpression(ArrayRef<int64_t>(Addr, Length));
- return wrap(Expr);
+ return wrapDI(Expr);
}
LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(LLVMDIBuilderRef Dref,
macro(Argument) \
macro(BasicBlock) \
macro(InlineAsm) \
- macro(MDNode) \
- macro(MDString) \
macro(User) \
macro(Constant) \
macro(BlockAddress) \
LLVMValueRef LLVMIsA##name(LLVMValueRef Val);
LLVM_FOR_EACH_VALUE_SUBCLASS(LLVM_DECLARE_VALUE_CAST)
+LLVMValueRef LLVMIsAMDNode(LLVMValueRef Val);
+LLVMValueRef LLVMIsAMDString(LLVMValueRef Val);
+
/**
* @}
*/
LexicalScope(LexicalScope *P, const MDNode *D, const MDNode *I, bool A)
: Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(A),
LastInsn(nullptr), FirstInsn(nullptr), DFSIn(0), DFSOut(0) {
+ assert((!D || D->isResolved()) && "Expected resolved node");
+ assert((!I || I->isResolved()) && "Expected resolved node");
if (Parent)
Parent->addChild(this);
}
private:
LexicalScope *Parent; // Parent to this scope.
- AssertingVH<const MDNode> Desc; // Debug info descriptor.
- AssertingVH<const MDNode> InlinedAtLocation; // Location at which this
+ const MDNode *Desc; // Debug info descriptor.
+ const MDNode *InlinedAtLocation; // Location at which this
// scope is inlined.
bool AbstractScope; // Abstract Scope
SmallVector<LexicalScope *, 4> Children; // Scopes defined in scope.
/// setDebugLoc - Replace current source information with new such.
/// Avoid using this, the constructor argument is preferable.
///
- void setDebugLoc(const DebugLoc dl) { debugLoc = dl; }
+ void setDebugLoc(const DebugLoc dl) {
+ debugLoc = dl;
+ assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor");
+ }
/// RemoveOperand - Erase an operand from an instruction, leaving it with one
/// fewer operand than it started with.
static char ID; // Pass identification, replacement for typeid
struct VariableDbgInfo {
- TrackingVH<MDNode> Var;
- TrackingVH<MDNode> Expr;
+ TrackingMDNodeRef Var;
+ TrackingMDNodeRef Expr;
unsigned Slot;
DebugLoc Loc;
+
+ VariableDbgInfo(MDNode *Var, MDNode *Expr, unsigned Slot, DebugLoc Loc)
+ : Var(Var), Expr(Expr), Slot(Slot), Loc(Loc) {}
};
typedef SmallVector<VariableDbgInfo, 4> VariableDbgInfoMapTy;
VariableDbgInfoMapTy VariableDbgInfos;
/// information of a variable.
void setVariableDbgInfo(MDNode *Var, MDNode *Expr, unsigned Slot,
DebugLoc Loc) {
- VariableDbgInfo Info = {Var, Expr, Slot, Loc};
- VariableDbgInfos.push_back(std::move(Info));
+ VariableDbgInfos.emplace_back(Var, Expr, Slot, Loc);
}
VariableDbgInfoMapTy &getVariableDbgInfo() { return VariableDbgInfos; }
ValueList(VTs.VTs), UseList(nullptr),
NumOperands(Ops.size()), NumValues(VTs.NumVTs),
debugLoc(dl), IROrder(Order) {
+ assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor");
assert(NumOperands == Ops.size() &&
"NumOperands wasn't wide enough for its operands!");
assert(NumValues == VTs.NumVTs &&
SubclassData(0), NodeId(-1), OperandList(nullptr), ValueList(VTs.VTs),
UseList(nullptr), NumOperands(0), NumValues(VTs.NumVTs), debugLoc(dl),
IROrder(Order) {
+ assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor");
assert(NumValues == VTs.NumVTs &&
"NumValues wasn't wide enough for its operands!");
}
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/TrackingMDRef.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Support/DataTypes.h"
Function *DeclareFn; // llvm.dbg.declare
Function *ValueFn; // llvm.dbg.value
- SmallVector<Value *, 4> AllEnumTypes;
- /// Use TrackingVH to collect RetainTypes, since they can be updated
- /// later on.
- SmallVector<TrackingVH<MDNode>, 4> AllRetainTypes;
- SmallVector<Value *, 4> AllSubprograms;
- SmallVector<Value *, 4> AllGVs;
- SmallVector<TrackingVH<MDNode>, 4> AllImportedModules;
+ SmallVector<Metadata *, 4> AllEnumTypes;
+ /// Track the RetainTypes, since they can be updated later on.
+ SmallVector<TrackingMDNodeRef, 4> AllRetainTypes;
+ SmallVector<Metadata *, 4> AllSubprograms;
+ SmallVector<Metadata *, 4> AllGVs;
+ SmallVector<TrackingMDNodeRef, 4> AllImportedModules;
+
+ /// \brief Track nodes that may be unresolved.
+ SmallVector<TrackingMDNodeRef, 4> UnresolvedNodes;
+ bool AllowUnresolvedNodes;
/// Each subprogram's preserved local variables.
- DenseMap<MDNode *, std::vector<TrackingVH<MDNode>>> PreservedVariables;
+ DenseMap<MDNode *, std::vector<TrackingMDNodeRef>> PreservedVariables;
DIBuilder(const DIBuilder &) LLVM_DELETED_FUNCTION;
void operator=(const DIBuilder &) LLVM_DELETED_FUNCTION;
+ /// \brief Create a temporary.
+ ///
+ /// Create an \a MDNodeFwdDecl and track it in \a UnresolvedNodes.
+ void trackIfUnresolved(MDNode *N);
+
public:
- explicit DIBuilder(Module &M);
+ /// \brief Construct a builder for a module.
+ ///
+ /// If \c AllowUnresolved, collect unresolved nodes attached to the module
+ /// in order to resolve cycles during \a finalize().
+ explicit DIBuilder(Module &M, bool AllowUnresolved = true);
enum DebugEmissionKind { FullDebug=1, LineTablesOnly };
/// finalize - Construct any deferred debug info descriptors.
DIBasicType createUnspecifiedParameter();
/// getOrCreateArray - Get a DIArray, create one if required.
- DIArray getOrCreateArray(ArrayRef<Value *> Elements);
+ DIArray getOrCreateArray(ArrayRef<Metadata *> Elements);
/// getOrCreateTypeArray - Get a DITypeArray, create one if required.
- DITypeArray getOrCreateTypeArray(ArrayRef<Value *> Elements);
+ DITypeArray getOrCreateTypeArray(ArrayRef<Metadata *> Elements);
/// getOrCreateSubrange - Create a descriptor for a value range. This
/// implicitly uniques the values returned.
bool Verify() const;
- operator MDNode *() const { return const_cast<MDNode *>(DbgNode); }
- MDNode *operator->() const { return const_cast<MDNode *>(DbgNode); }
+ MDNode *get() const { return const_cast<MDNode *>(DbgNode); }
+ operator MDNode *() const { return get(); }
+ MDNode *operator->() const { return get(); }
// An explicit operator bool so that we can do testing of DI values
// easily.
DIScopeRef getContext() const { return getFieldAs<DIScopeRef>(1); }
DITypeRef getType() const { return getFieldAs<DITypeRef>(2); }
- Value *getValue() const;
+ Metadata *getValue() const;
StringRef getFilename() const { return getFieldAs<DIFile>(4).getFilename(); }
StringRef getDirectory() const {
return getFieldAs<DIFile>(4).getDirectory();
#define LLVM_IR_DEBUGLOC_H
#include "llvm/Support/DataTypes.h"
+#include "llvm/IR/TrackingMDRef.h"
namespace llvm {
- template <typename T> struct DenseMapInfo;
- class MDNode;
+
class LLVMContext;
class raw_ostream;
+ class MDNode;
/// DebugLoc - Debug location id. This is carried by Instruction, SDNode,
/// and MachineInstr to compactly encode file/line/scope information for an
/// operation.
class DebugLoc {
- friend struct DenseMapInfo<DebugLoc>;
-
- /// getEmptyKey() - A private constructor that returns an unknown that is
- /// not equal to the tombstone key or DebugLoc().
- static DebugLoc getEmptyKey() {
- DebugLoc DL;
- DL.LineCol = 1;
- return DL;
- }
+ TrackingMDNodeRef Loc;
- /// getTombstoneKey() - A private constructor that returns an unknown that
- /// is not equal to the empty key or DebugLoc().
- static DebugLoc getTombstoneKey() {
- DebugLoc DL;
- DL.LineCol = 2;
- return DL;
+ public:
+ DebugLoc() {}
+ DebugLoc(DebugLoc &&X) : Loc(std::move(X.Loc)) {}
+ DebugLoc(const DebugLoc &X) : Loc(X.Loc) {}
+ DebugLoc &operator=(DebugLoc &&X) {
+ Loc = std::move(X.Loc);
+ return *this;
+ }
+ DebugLoc &operator=(const DebugLoc &X) {
+ Loc = X.Loc;
+ return *this;
}
- /// LineCol - This 32-bit value encodes the line and column number for the
- /// location, encoded as 24-bits for line and 8 bits for col. A value of 0
- /// for either means unknown.
- uint32_t LineCol;
-
- /// ScopeIdx - This is an opaque ID# for Scope/InlinedAt information,
- /// decoded by LLVMContext. 0 is unknown.
- int ScopeIdx;
- public:
- DebugLoc() : LineCol(0), ScopeIdx(0) {} // Defaults to unknown.
+ /// \brief Check whether this has a trivial destructor.
+ bool hasTrivialDestructor() const { return Loc.hasTrivialDestructor(); }
/// get - Get a new DebugLoc that corresponds to the specified line/col
/// scope/inline location.
- static DebugLoc get(unsigned Line, unsigned Col,
- MDNode *Scope, MDNode *InlinedAt = nullptr);
+ static DebugLoc get(unsigned Line, unsigned Col, MDNode *Scope,
+ MDNode *InlinedAt = nullptr);
/// getFromDILocation - Translate the DILocation quad into a DebugLoc.
static DebugLoc getFromDILocation(MDNode *N);
static DebugLoc getFromDILexicalBlock(MDNode *N);
/// isUnknown - Return true if this is an unknown location.
- bool isUnknown() const { return ScopeIdx == 0; }
+ bool isUnknown() const { return !Loc; }
- unsigned getLine() const {
- return (LineCol << 8) >> 8; // Mask out column.
- }
-
- unsigned getCol() const {
- return LineCol >> 24;
- }
+ unsigned getLine() const;
+ unsigned getCol() const;
/// getScope - This returns the scope pointer for this DebugLoc, or null if
/// invalid.
- MDNode *getScope(const LLVMContext &Ctx) const;
+ MDNode *getScope() const;
+ MDNode *getScope(const LLVMContext &) const { return getScope(); }
/// getInlinedAt - This returns the InlinedAt pointer for this DebugLoc, or
/// null if invalid or not present.
- MDNode *getInlinedAt(const LLVMContext &Ctx) const;
+ MDNode *getInlinedAt() const;
+ MDNode *getInlinedAt(const LLVMContext &) const { return getInlinedAt(); }
/// getScopeAndInlinedAt - Return both the Scope and the InlinedAt values.
+ void getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA) const;
void getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA,
- const LLVMContext &Ctx) const;
+ const LLVMContext &) const {
+ return getScopeAndInlinedAt(Scope, IA);
+ }
/// getScopeNode - Get MDNode for DebugLoc's scope, or null if invalid.
- MDNode *getScopeNode(const LLVMContext &Ctx) const;
+ MDNode *getScopeNode() const;
+ MDNode *getScopeNode(const LLVMContext &) const { return getScopeNode(); }
// getFnDebugLoc - Walk up the scope chain of given debug loc and find line
// number info for the function.
- DebugLoc getFnDebugLoc(const LLVMContext &Ctx) const;
+ DebugLoc getFnDebugLoc() const;
+ DebugLoc getFnDebugLoc(const LLVMContext &) const {
+ return getFnDebugLoc();
+ }
/// getAsMDNode - This method converts the compressed DebugLoc node into a
/// DILocation compatible MDNode.
- MDNode *getAsMDNode(const LLVMContext &Ctx) const;
+ MDNode *getAsMDNode() const;
+ MDNode *getAsMDNode(LLVMContext &) const { return getAsMDNode(); }
- bool operator==(const DebugLoc &DL) const {
- return LineCol == DL.LineCol && ScopeIdx == DL.ScopeIdx;
- }
+ bool operator==(const DebugLoc &DL) const { return Loc == DL.Loc; }
bool operator!=(const DebugLoc &DL) const { return !(*this == DL); }
- void dump(const LLVMContext &Ctx) const;
+ void dump() const;
+ void dump(const LLVMContext &) const { dump(); }
/// \brief prints source location /path/to/file.exe:line:col @[inlined at]
- void print(const LLVMContext &Ctx, raw_ostream &OS) const;
+ void print(raw_ostream &OS) const;
+ void print(const LLVMContext &, raw_ostream &OS) const { print(OS); }
};
- template <>
- struct DenseMapInfo<DebugLoc> {
- static DebugLoc getEmptyKey() { return DebugLoc::getEmptyKey(); }
- static DebugLoc getTombstoneKey() { return DebugLoc::getTombstoneKey(); }
- static unsigned getHashValue(const DebugLoc &Key);
- static bool isEqual(DebugLoc LHS, DebugLoc RHS) { return LHS == RHS; }
- };
} // end namespace llvm
#endif /* LLVM_SUPPORT_DEBUGLOC_H */
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/Metadata.h"
namespace llvm {
/// IntrinsicInst - A useful wrapper class for inspecting calls to intrinsic
class DbgDeclareInst : public DbgInfoIntrinsic {
public:
Value *getAddress() const;
- MDNode *getVariable() const { return cast<MDNode>(getArgOperand(1)); }
- MDNode *getExpression() const { return cast<MDNode>(getArgOperand(2)); }
+ MDNode *getVariable() const {
+ return cast<MDNode>(
+ cast<MetadataAsValue>(getArgOperand(1))->getMetadata());
+ }
+ MDNode *getExpression() const {
+ return cast<MDNode>(
+ cast<MetadataAsValue>(getArgOperand(2))->getMetadata());
+ }
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const IntrinsicInst *I) {
return cast<ConstantInt>(
const_cast<Value*>(getArgOperand(1)))->getZExtValue();
}
- MDNode *getVariable() const { return cast<MDNode>(getArgOperand(2)); }
- MDNode *getExpression() const { return cast<MDNode>(getArgOperand(3)); }
+ MDNode *getVariable() const {
+ return cast<MDNode>(
+ cast<MetadataAsValue>(getArgOperand(2))->getMetadata());
+ }
+ MDNode *getExpression() const {
+ return cast<MDNode>(
+ cast<MetadataAsValue>(getArgOperand(3))->getMetadata());
+ }
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const IntrinsicInst *I) {
class APInt;
template <typename T> class ArrayRef;
class LLVMContext;
+class Constant;
+class ConstantAsMetadata;
class MDNode;
class MDString;
/// \brief Return the given string as metadata.
MDString *createString(StringRef Str);
+ /// \brief Return the given constant as metadata.
+ ConstantAsMetadata *createConstant(Constant *C);
+
//===------------------------------------------------------------------===//
// FPMath metadata.
//===------------------------------------------------------------------===//
--- /dev/null
+//===- llvm/Metadata.def - Metadata definitions -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Macros for running through all types of metadata.
+//
+//===----------------------------------------------------------------------===//
+
+#if !(defined HANDLE_METADATA || defined HANDLE_METADATA_LEAF || \
+ defined HANDLE_METADATA_BRANCH)
+#error "Missing macro definition of HANDLE_METADATA*"
+#endif
+
+// Handler for all types of metadata.
+#ifndef HANDLE_METADATA
+#define HANDLE_METADATA(CLASS)
+#endif
+
+// Handler for leaf nodes in the class hierarchy.
+#ifndef HANDLE_METADATA_LEAF
+#define HANDLE_METADATA_LEAF(CLASS) HANDLE_METADATA(CLASS)
+#endif
+
+// Handler for non-leaf nodes in the class hierarchy.
+#ifndef HANDLE_METADATA_BRANCH
+#define HANDLE_METADATA_BRANCH(CLASS) HANDLE_METADATA(CLASS)
+#endif
+
+HANDLE_METADATA_LEAF(MDString)
+HANDLE_METADATA_BRANCH(ValueAsMetadata)
+HANDLE_METADATA_LEAF(ConstantAsMetadata)
+HANDLE_METADATA_LEAF(LocalAsMetadata)
+HANDLE_METADATA_BRANCH(MDNode)
+HANDLE_METADATA_LEAF(MDNodeFwdDecl)
+HANDLE_METADATA_LEAF(GenericMDNode)
+
+#undef HANDLE_METADATA
+#undef HANDLE_METADATA_LEAF
+#undef HANDLE_METADATA_BRANCH
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ilist_node.h"
#include "llvm/ADT/iterator_range.h"
+#include "llvm/IR/Constant.h"
+#include "llvm/IR/MetadataTracking.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/ErrorHandling.h"
+#include <type_traits>
namespace llvm {
class LLVMContext;
/// \brief Root of the metadata hierarchy.
///
/// This is a root class for typeless data in the IR.
-///
-/// TODO: Detach from the Value hierarchy.
-class Metadata : public Value {
+class Metadata {
+ friend class ReplaceableMetadataImpl;
+
+ /// \brief RTTI.
+ const unsigned char SubclassID;
+
protected:
- Metadata(LLVMContext &Context, unsigned ID);
+ /// \brief Storage flag for non-uniqued, otherwise unowned, metadata.
+ bool IsDistinctInContext : 1;
+ // TODO: expose remaining bits to subclasses.
+
+ unsigned short SubclassData16;
+ unsigned SubclassData32;
+
+public:
+ enum MetadataKind {
+ GenericMDNodeKind,
+ MDNodeFwdDeclKind,
+ ConstantAsMetadataKind,
+ LocalAsMetadataKind,
+ MDStringKind
+ };
+
+protected:
+ Metadata(unsigned ID)
+ : SubclassID(ID), IsDistinctInContext(false), SubclassData16(0),
+ SubclassData32(0) {}
+ ~Metadata() {}
+
+ /// \brief Store this in a big non-uniqued untyped bucket.
+ bool isStoredDistinctInContext() const { return IsDistinctInContext; }
+
+ /// \brief Default handling of a changed operand, which asserts.
+ ///
+ /// If subclasses pass themselves in as owners to a tracking node reference,
+ /// they must provide an implementation of this method.
+ void handleChangedOperand(void *, Metadata *) {
+ llvm_unreachable("Unimplemented in Metadata subclass");
+ }
public:
+ unsigned getMetadataID() const { return SubclassID; }
+
+ /// \brief User-friendly dump.
+ void dump() const;
+ void print(raw_ostream &OS) const;
+ void printAsOperand(raw_ostream &OS, bool PrintType = true,
+ const Module *M = nullptr) const;
+};
+
+#define HANDLE_METADATA(CLASS) class CLASS;
+#include "llvm/IR/Metadata.def"
+
+inline raw_ostream &operator<<(raw_ostream &OS, const Metadata &MD) {
+ MD.print(OS);
+ return OS;
+}
+
+/// \brief Metadata wrapper in the Value hierarchy.
+///
+/// A member of the \a Value hierarchy to represent a reference to metadata.
+/// This allows, e.g., instrinsics to have metadata as operands.
+///
+/// Notably, this is the only thing in either hierarchy that is allowed to
+/// reference \a LocalAsMetadata.
+class MetadataAsValue : public Value {
+ friend class ReplaceableMetadataImpl;
+ friend class LLVMContextImpl;
+
+ Metadata *MD;
+
+ MetadataAsValue(Type *Ty, Metadata *MD);
+ ~MetadataAsValue();
+
+public:
+ static MetadataAsValue *get(LLVMContext &Context, Metadata *MD);
+ static MetadataAsValue *getIfExists(LLVMContext &Context, Metadata *MD);
+ Metadata *getMetadata() const { return MD; }
+
static bool classof(const Value *V) {
- return V->getValueID() == GenericMDNodeVal ||
- V->getValueID() == MDNodeFwdDeclVal ||
- V->getValueID() == MDStringVal;
+ return V->getValueID() == MetadataAsValueVal;
+ }
+
+private:
+ void handleChangedMetadata(Metadata *MD);
+ void track();
+ void untrack();
+};
+
+/// \brief Shared implementation of use-lists for replaceable metadata.
+///
+/// Most metadata cannot be RAUW'ed. This is a shared implementation of
+/// use-lists and associated API for the two that support it (\a ValueAsMetadata
+/// and \a TempMDNode).
+class ReplaceableMetadataImpl {
+ friend class MetadataTracking;
+
+public:
+ typedef MetadataTracking::OwnerTy OwnerTy;
+
+private:
+ SmallDenseMap<void *, OwnerTy, 4> UseMap;
+
+public:
+ ~ReplaceableMetadataImpl() {
+ assert(UseMap.empty() && "Cannot destroy in-use replaceable metadata");
+ }
+
+ /// \brief Replace all uses of this with MD.
+ ///
+ /// Replace all uses of this with \c MD, which is allowed to be null.
+ void replaceAllUsesWith(Metadata *MD);
+
+ /// \brief Resolve all uses of this.
+ ///
+ /// Resolve all uses of this, turning off RAUW permanently. If \c
+ /// ResolveUsers, call \a GenericMDNode::resolve() on any users whose last
+ /// operand is resolved.
+ void resolveAllUses(bool ResolveUsers = true);
+
+private:
+ void addRef(void *Ref, OwnerTy Owner);
+ void dropRef(void *Ref);
+ void moveRef(void *Ref, void *New, const Metadata &MD);
+
+ static ReplaceableMetadataImpl *get(Metadata &MD);
+};
+
+/// \brief Value wrapper in the Metadata hierarchy.
+///
+/// This is a custom value handle that allows other metadata to refer to
+/// classes in the Value hierarchy.
+///
+/// Because of full uniquing support, each value is only wrapped by a single \a
+/// ValueAsMetadata object, so the lookup maps are far more efficient than
+/// those using ValueHandleBase.
+class ValueAsMetadata : public Metadata, ReplaceableMetadataImpl {
+ friend class ReplaceableMetadataImpl;
+ friend class LLVMContextImpl;
+
+ Value *V;
+
+protected:
+ ValueAsMetadata(LLVMContext &Context, unsigned ID, Value *V)
+ : Metadata(ID), V(V) {
+ assert(V && "Expected valid value");
+ }
+ ~ValueAsMetadata() {}
+
+public:
+ static ValueAsMetadata *get(Value *V);
+ static ConstantAsMetadata *getConstant(Value *C) {
+ return cast<ConstantAsMetadata>(get(C));
+ }
+ static LocalAsMetadata *getLocal(Value *Local) {
+ return cast<LocalAsMetadata>(get(Local));
+ }
+
+ static ValueAsMetadata *getIfExists(Value *V);
+ static ConstantAsMetadata *getConstantIfExists(Value *C) {
+ return cast_or_null<ConstantAsMetadata>(getIfExists(C));
+ }
+ static LocalAsMetadata *getLocalIfExists(Value *Local) {
+ return cast_or_null<LocalAsMetadata>(getIfExists(Local));
+ }
+
+ Value *getValue() const { return V; }
+ Type *getType() const { return V->getType(); }
+ LLVMContext &getContext() const { return V->getContext(); }
+
+ static void handleDeletion(Value *V);
+ static void handleRAUW(Value *From, Value *To);
+
+protected:
+ /// \brief Handle collisions after \a Value::replaceAllUsesWith().
+ ///
+ /// RAUW isn't supported directly for \a ValueAsMetadata, but if the wrapped
+ /// \a Value gets RAUW'ed and the target already exists, this is used to
+ /// merge the two metadata nodes.
+ void replaceAllUsesWith(Metadata *MD) {
+ ReplaceableMetadataImpl::replaceAllUsesWith(MD);
+ }
+
+public:
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == LocalAsMetadataKind ||
+ MD->getMetadataID() == ConstantAsMetadataKind;
+ }
+};
+
+class ConstantAsMetadata : public ValueAsMetadata {
+ friend class ValueAsMetadata;
+
+ ConstantAsMetadata(LLVMContext &Context, Constant *C)
+ : ValueAsMetadata(Context, ConstantAsMetadataKind, C) {}
+
+public:
+ static ConstantAsMetadata *get(Constant *C) {
+ return ValueAsMetadata::getConstant(C);
+ }
+ static ConstantAsMetadata *getIfExists(Constant *C) {
+ return ValueAsMetadata::getConstantIfExists(C);
+ }
+
+ Constant *getValue() const {
+ return cast<Constant>(ValueAsMetadata::getValue());
+ }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == ConstantAsMetadataKind;
+ }
+};
+
+class LocalAsMetadata : public ValueAsMetadata {
+ friend class ValueAsMetadata;
+
+ LocalAsMetadata(LLVMContext &Context, Value *Local)
+ : ValueAsMetadata(Context, LocalAsMetadataKind, Local) {
+ assert(!isa<Constant>(Local) && "Expected local value");
+ }
+
+public:
+ static LocalAsMetadata *get(Value *Local) {
+ return ValueAsMetadata::getLocal(Local);
}
+ static LocalAsMetadata *getIfExists(Value *Local) {
+ return ValueAsMetadata::getLocalIfExists(Local);
+ }
+
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == LocalAsMetadataKind;
+ }
+};
+
+/// \brief Transitional API for extracting constants from Metadata.
+///
+/// This namespace contains transitional functions for metadata that points to
+/// \a Constants.
+///
+/// In prehistory -- when metadata was a subclass of \a Value -- \a MDNode
+/// operands could refer to any \a Value. There's was a lot of code like this:
+///
+/// \code
+/// MDNode *N = ...;
+/// auto *CI = dyn_cast<ConstantInt>(N->getOperand(2));
+/// \endcode
+///
+/// Now that \a Value and \a Metadata are in separate hierarchies, maintaining
+/// the semantics for \a isa(), \a cast(), \a dyn_cast() (etc.) requires three
+/// steps: cast in the \a Metadata hierarchy, extraction of the \a Value, and
+/// cast in the \a Value hierarchy. Besides creating boiler-plate, this
+/// requires subtle control flow changes.
+///
+/// The end-goal is to create a new type of metadata, called (e.g.) \a MDInt,
+/// so that metadata can refer to numbers without traversing a bridge to the \a
+/// Value hierarchy. In this final state, the code above would look like this:
+///
+/// \code
+/// MDNode *N = ...;
+/// auto *MI = dyn_cast<MDInt>(N->getOperand(2));
+/// \endcode
+///
+/// The API in this namespace supports the transition. \a MDInt doesn't exist
+/// yet, and even once it does, changing each metadata schema to use it is its
+/// own mini-project. In the meantime this API prevents us from introducing
+/// complex and bug-prone control flow that will disappear in the end. In
+/// particular, the above code looks like this:
+///
+/// \code
+/// MDNode *N = ...;
+/// auto *CI = mdconst::dyn_extract<ConstantInt>(N->getOperand(2));
+/// \endcode
+///
+/// The full set of provided functions includes:
+///
+/// mdconst::hasa <=> isa
+/// mdconst::extract <=> cast
+/// mdconst::extract_or_null <=> cast_or_null
+/// mdconst::dyn_extract <=> dyn_cast
+/// mdconst::dyn_extract_or_null <=> dyn_cast_or_null
+///
+/// The target of the cast must be a subclass of \a Constant.
+namespace mdconst {
+
+namespace detail {
+template <class T> T &make();
+template <class T, class Result> struct HasDereference {
+ typedef char Yes[1];
+ typedef char No[2];
+ template <size_t N> struct SFINAE {};
+
+ template <class U, class V>
+ static Yes &hasDereference(SFINAE<sizeof(static_cast<V>(*make<U>()))> * = 0);
+ template <class U, class V> static No &hasDereference(...);
+
+ static const bool value =
+ sizeof(hasDereference<T, Result>(nullptr)) == sizeof(Yes);
+};
+template <class V, class M> struct IsValidPointer {
+ static const bool value = std::is_base_of<Constant, V>::value &&
+ HasDereference<M, const Metadata &>::value;
};
+template <class V, class M> struct IsValidReference {
+ static const bool value = std::is_base_of<Constant, V>::value &&
+ std::is_convertible<M, const Metadata &>::value;
+};
+} // end namespace detail
+
+/// \brief Check whether Metadata has a Value.
+///
+/// As an analogue to \a isa(), check whether \c MD has an \a Value inside of
+/// type \c X.
+template <class X, class Y>
+inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, bool>::type
+hasa(Y &&MD) {
+ assert(MD && "Null pointer sent into hasa");
+ if (auto *V = dyn_cast<ConstantAsMetadata>(MD))
+ return isa<X>(V->getValue());
+ return false;
+}
+template <class X, class Y>
+inline
+ typename std::enable_if<detail::IsValidReference<X, Y &>::value, bool>::type
+ hasa(Y &MD) {
+ return hasa(&MD);
+}
+
+/// \brief Extract a Value from Metadata.
+///
+/// As an analogue to \a cast(), extract the \a Value subclass \c X from \c MD.
+template <class X, class Y>
+inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, X *>::type
+extract(Y &&MD) {
+ return cast<X>(cast<ConstantAsMetadata>(MD)->getValue());
+}
+template <class X, class Y>
+inline
+ typename std::enable_if<detail::IsValidReference<X, Y &>::value, X *>::type
+ extract(Y &MD) {
+ return extract(&MD);
+}
+
+/// \brief Extract a Value from Metadata, allowing null.
+///
+/// As an analogue to \a cast_or_null(), extract the \a Value subclass \c X
+/// from \c MD, allowing \c MD to be null.
+template <class X, class Y>
+inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, X *>::type
+extract_or_null(Y &&MD) {
+ if (auto *V = cast_or_null<ConstantAsMetadata>(MD))
+ return cast<X>(V->getValue());
+ return nullptr;
+}
+
+/// \brief Extract a Value from Metadata, if any.
+///
+/// As an analogue to \a dyn_cast_or_null(), extract the \a Value subclass \c X
+/// from \c MD, return null if \c MD doesn't contain a \a Value or if the \a
+/// Value it does contain is of the wrong subclass.
+template <class X, class Y>
+inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, X *>::type
+dyn_extract(Y &&MD) {
+ if (auto *V = dyn_cast<ConstantAsMetadata>(MD))
+ return dyn_cast<X>(V->getValue());
+ return nullptr;
+}
+
+/// \brief Extract a Value from Metadata, if any, allowing null.
+///
+/// As an analogue to \a dyn_cast_or_null(), extract the \a Value subclass \c X
+/// from \c MD, return null if \c MD doesn't contain a \a Value or if the \a
+/// Value it does contain is of the wrong subclass, allowing \c MD to be null.
+template <class X, class Y>
+inline typename std::enable_if<detail::IsValidPointer<X, Y>::value, X *>::type
+dyn_extract_or_null(Y &&MD) {
+ if (auto *V = dyn_cast_or_null<ConstantAsMetadata>(MD))
+ return dyn_cast<X>(V->getValue());
+ return nullptr;
+}
+
+} // end namespace mdconst
//===----------------------------------------------------------------------===//
/// \brief A single uniqued string.
class MDString : public Metadata {
friend class StringMapEntry<MDString>;
- virtual void anchor();
MDString(const MDString &) LLVM_DELETED_FUNCTION;
+ MDString &operator=(MDString &&) LLVM_DELETED_FUNCTION;
+ MDString &operator=(const MDString &) LLVM_DELETED_FUNCTION;
StringMapEntry<MDString> *Entry;
- explicit MDString(LLVMContext &Context)
- : Metadata(Context, Value::MDStringVal), Entry(nullptr) {}
-
- /// \brief Shadow Value::getName() to prevent its use.
- StringRef getName() const LLVM_DELETED_FUNCTION;
+ MDString() : Metadata(MDStringKind), Entry(nullptr) {}
+ MDString(MDString &&) : Metadata(MDStringKind) {}
public:
static MDString *get(LLVMContext &Context, StringRef Str);
iterator end() const { return getString().end(); }
/// \brief Methods for support type inquiry through isa, cast, and dyn_cast.
- static bool classof(const Value *V) {
- return V->getValueID() == MDStringVal;
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == MDStringKind;
}
};
}
};
-class MDNodeOperand;
+/// \brief Tracking metadata reference owned by Metadata.
+///
+/// Similar to \a TrackingMDRef, but it's expected to be owned by an instance
+/// of \a Metadata, which has the option of registering itself for callbacks to
+/// re-unique itself.
+///
+/// In particular, this is used by \a MDNode.
+class MDOperand {
+ MDOperand(MDOperand &&) LLVM_DELETED_FUNCTION;
+ MDOperand(const MDOperand &) LLVM_DELETED_FUNCTION;
+ MDOperand &operator=(MDOperand &&) LLVM_DELETED_FUNCTION;
+ MDOperand &operator=(const MDOperand &) LLVM_DELETED_FUNCTION;
+
+ Metadata *MD;
+
+public:
+ MDOperand() : MD(nullptr) {}
+ ~MDOperand() { untrack(); }
+
+ LLVM_EXPLICIT operator bool() const { return get(); }
+ Metadata *get() const { return MD; }
+ operator Metadata *() const { return get(); }
+ Metadata *operator->() const { return get(); }
+ Metadata &operator*() const { return *get(); }
+
+ void reset() {
+ untrack();
+ MD = nullptr;
+ }
+ void reset(Metadata *MD, Metadata *Owner) {
+ untrack();
+ this->MD = MD;
+ track(Owner);
+ }
+
+private:
+ void track(Metadata *Owner) {
+ if (MD) {
+ if (Owner)
+ MetadataTracking::track(this, *MD, *Owner);
+ else
+ MetadataTracking::track(MD);
+ }
+ }
+ void untrack() {
+ assert(static_cast<void *>(this) == &MD && "Expected same address");
+ if (MD)
+ MetadataTracking::untrack(MD);
+ }
+};
+
+template <> struct simplify_type<MDOperand> {
+ typedef Metadata *SimpleType;
+ static SimpleType getSimplifiedValue(MDOperand &MD) { return MD.get(); }
+};
+
+template <> struct simplify_type<const MDOperand> {
+ typedef Metadata *SimpleType;
+ static SimpleType getSimplifiedValue(const MDOperand &MD) { return MD.get(); }
+};
//===----------------------------------------------------------------------===//
/// \brief Tuple of metadata.
class MDNode : public Metadata {
MDNode(const MDNode &) LLVM_DELETED_FUNCTION;
void operator=(const MDNode &) LLVM_DELETED_FUNCTION;
- friend class MDNodeOperand;
- friend class LLVMContextImpl;
void *operator new(size_t) LLVM_DELETED_FUNCTION;
+ LLVMContext &Context;
+ unsigned NumOperands;
+
protected:
+ unsigned MDNodeSubclassData;
+
void *operator new(size_t Size, unsigned NumOps);
/// \brief Required by std, but never called.
llvm_unreachable("Constructor throws?");
}
- /// \brief Subclass data enums.
- enum {
- /// FunctionLocalBit - This bit is set if this MDNode is function local.
- /// This is true when it (potentially transitively) contains a reference to
- /// something in a function, like an argument, basicblock, or instruction.
- FunctionLocalBit = 1 << 0,
-
- /// NotUniquedBit - This is set on MDNodes that are not uniqued because they
- /// have a null operand.
- NotUniquedBit = 1 << 1
- };
+ MDNode(LLVMContext &Context, unsigned ID, ArrayRef<Metadata *> MDs);
+ ~MDNode() { dropAllReferences(); }
- /// \brief FunctionLocal enums.
- enum FunctionLocalness {
- FL_Unknown = -1,
- FL_No = 0,
- FL_Yes = 1
- };
+ void dropAllReferences();
+ void storeDistinctInContext();
- /// \brief Replace each instance of the given operand with a new value.
- void replaceOperand(MDNodeOperand *Op, Value *NewVal);
+ static MDNode *getMDNode(LLVMContext &C, ArrayRef<Metadata *> MDs,
+ bool Insert = true);
- MDNode(LLVMContext &C, unsigned ID, ArrayRef<Value *> Vals,
- bool isFunctionLocal);
- ~MDNode() {}
+ MDOperand *mutable_begin() { return mutable_end() - NumOperands; }
+ MDOperand *mutable_end() { return reinterpret_cast<MDOperand *>(this); }
- static MDNode *getMDNode(LLVMContext &C, ArrayRef<Value*> Vals,
- FunctionLocalness FL, bool Insert = true);
public:
- static MDNode *get(LLVMContext &Context, ArrayRef<Value*> Vals);
- /// \brief Construct MDNode with an explicit function-localness.
- ///
- /// Don't analyze Vals; trust isFunctionLocal.
+ static MDNode *get(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+ return getMDNode(Context, MDs, true);
+ }
static MDNode *getWhenValsUnresolved(LLVMContext &Context,
- ArrayRef<Value*> Vals,
- bool isFunctionLocal);
+ ArrayRef<Metadata *> MDs) {
+ // TODO: Remove this.
+ return get(Context, MDs);
+ }
- static MDNode *getIfExists(LLVMContext &Context, ArrayRef<Value*> Vals);
+ static MDNode *getIfExists(LLVMContext &Context, ArrayRef<Metadata *> MDs) {
+ return getMDNode(Context, MDs, false);
+ }
/// \brief Return a temporary MDNode
///
/// For use in constructing cyclic MDNode structures. A temporary MDNode is
/// not uniqued, may be RAUW'd, and must be manually deleted with
/// deleteTemporary.
- static MDNode *getTemporary(LLVMContext &Context, ArrayRef<Value*> Vals);
+ static MDNodeFwdDecl *getTemporary(LLVMContext &Context,
+ ArrayRef<Metadata *> MDs);
/// \brief Deallocate a node created by getTemporary.
///
/// The node must not have any users.
static void deleteTemporary(MDNode *N);
+ LLVMContext &getContext() const { return Context; }
+
/// \brief Replace a specific operand.
- void replaceOperandWith(unsigned i, Value *NewVal);
+ void replaceOperandWith(unsigned I, Metadata *New);
- /// \brief Return specified operand.
- Value *getOperand(unsigned i) const LLVM_READONLY;
+ /// \brief Check if node is fully resolved.
+ bool isResolved() const;
- /// \brief Return number of MDNode operands.
- unsigned getNumOperands() const { return NumOperands; }
+protected:
+ /// \brief Set an operand.
+ ///
+ /// Sets the operand directly, without worrying about uniquing.
+ void setOperand(unsigned I, Metadata *New);
+
+public:
+ typedef const MDOperand *op_iterator;
+ typedef iterator_range<op_iterator> op_range;
- /// \brief Return whether MDNode is local to a function.
- bool isFunctionLocal() const {
- return (getSubclassDataFromValue() & FunctionLocalBit) != 0;
+ op_iterator op_begin() const {
+ return const_cast<MDNode *>(this)->mutable_begin();
}
+ op_iterator op_end() const {
+ return const_cast<MDNode *>(this)->mutable_end();
+ }
+ op_range operands() const { return op_range(op_begin(), op_end()); }
- /// \brief Return the first function-local operand's function.
- ///
- /// If this metadata is function-local and recursively has a function-local
- /// operand, return the first such operand's parent function. Otherwise,
- /// return null. getFunction() should not be used for performance- critical
- /// code because it recursively visits all the MDNode's operands.
- const Function *getFunction() const;
+ const MDOperand &getOperand(unsigned I) const {
+ assert(I < NumOperands && "Out of range");
+ return op_begin()[I];
+ }
+
+ /// \brief Return number of MDNode operands.
+ unsigned getNumOperands() const { return NumOperands; }
/// \brief Methods for support type inquiry through isa, cast, and dyn_cast:
- static bool classof(const Value *V) {
- return V->getValueID() == GenericMDNodeVal ||
- V->getValueID() == MDNodeFwdDeclVal;
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == GenericMDNodeKind ||
+ MD->getMetadataID() == MDNodeFwdDeclKind;
}
/// \brief Check whether MDNode is a vtable access.
static AAMDNodes getMostGenericAA(const AAMDNodes &A, const AAMDNodes &B);
static MDNode *getMostGenericFPMath(MDNode *A, MDNode *B);
static MDNode *getMostGenericRange(MDNode *A, MDNode *B);
-
-protected:
- bool isNotUniqued() const {
- return (getSubclassDataFromValue() & NotUniquedBit) != 0;
- }
- void setIsNotUniqued();
-
- // Shadow Value::setValueSubclassData with a private forwarding method so that
- // any future subclasses cannot accidentally use it.
- void setValueSubclassData(unsigned short D) {
- Value::setValueSubclassData(D);
- }
};
/// \brief Generic metadata node.
/// TODO: Make uniquing opt-out (status: mandatory, sometimes dropped).
/// TODO: Drop support for RAUW.
class GenericMDNode : public MDNode {
+ friend class Metadata;
friend class MDNode;
friend class LLVMContextImpl;
+ friend class ReplaceableMetadataImpl;
- unsigned Hash;
+ /// \brief Support RAUW as long as one of its arguments is replaceable.
+ ///
+ /// If an operand is an \a MDNodeFwdDecl (or a replaceable \a GenericMDNode),
+ /// support RAUW to support uniquing as forward declarations are resolved.
+ /// As soon as operands have been resolved, drop support.
+ ///
+ /// FIXME: Save memory by storing this in a pointer union with the
+ /// LLVMContext, and adding an LLVMContext reference to RMI.
+ std::unique_ptr<ReplaceableMetadataImpl> ReplaceableUses;
- GenericMDNode(LLVMContext &C, ArrayRef<Value *> Vals, bool isFunctionLocal)
- : MDNode(C, GenericMDNodeVal, Vals, isFunctionLocal), Hash(0) {}
+ GenericMDNode(LLVMContext &C, ArrayRef<Metadata *> Vals);
~GenericMDNode();
- void dropAllReferences();
+ void setHash(unsigned Hash) { MDNodeSubclassData = Hash; }
public:
/// \brief Get the hash, if any.
- unsigned getHash() const { return Hash; }
+ unsigned getHash() const { return MDNodeSubclassData; }
- static bool classof(const Value *V) {
- return V->getValueID() == GenericMDNodeVal;
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == GenericMDNodeKind;
}
+
+ /// \brief Check whether any operands are forward declarations.
+ ///
+ /// Returns \c true as long as any operands (or their operands, etc.) are \a
+ /// MDNodeFwdDecl.
+ ///
+ /// As forward declarations are resolved, their containers should get
+ /// resolved automatically. However, if this (or one of its operands) is
+ /// involved in a cycle, \a resolveCycles() needs to be called explicitly.
+ bool isResolved() const { return !ReplaceableUses; }
+
+ /// \brief Resolve cycles.
+ ///
+ /// Once all forward declarations have been resolved, force cycles to be
+ /// resolved.
+ ///
+ /// \pre No operands (or operands' operands, etc.) are \a MDNodeFwdDecl.
+ void resolveCycles();
+
+private:
+ void handleChangedOperand(void *Ref, Metadata *New);
+
+ bool hasUnresolvedOperands() const { return SubclassData32; }
+ void incrementUnresolvedOperands() { ++SubclassData32; }
+ void decrementUnresolvedOperands() { --SubclassData32; }
+ void resolve();
};
/// \brief Forward declaration of metadata.
/// Forward declaration of metadata, in the form of a metadata node. Unlike \a
/// GenericMDNode, this class has support for RAUW and is suitable for forward
/// references.
-class MDNodeFwdDecl : public MDNode {
+class MDNodeFwdDecl : public MDNode, ReplaceableMetadataImpl {
+ friend class Metadata;
friend class MDNode;
+ friend class ReplaceableMetadataImpl;
- MDNodeFwdDecl(LLVMContext &C, ArrayRef<Value *> Vals, bool isFunctionLocal)
- : MDNode(C, MDNodeFwdDeclVal, Vals, isFunctionLocal) {}
+ MDNodeFwdDecl(LLVMContext &C, ArrayRef<Metadata *> Vals)
+ : MDNode(C, MDNodeFwdDeclKind, Vals) {}
~MDNodeFwdDecl() {}
public:
- static bool classof(const Value *V) {
- return V->getValueID() == MDNodeFwdDeclVal;
+ static bool classof(const Metadata *MD) {
+ return MD->getMetadataID() == MDNodeFwdDeclKind;
}
+
+ using ReplaceableMetadataImpl::replaceAllUsesWith;
};
//===----------------------------------------------------------------------===//
std::string Name;
Module *Parent;
- void *Operands; // SmallVector<TrackingVH<MDNode>, 4>
+ void *Operands; // SmallVector<TrackingMDRef, 4>
void setParent(Module *M) { Parent = M; }
--- /dev/null
+//===- llvm/IR/MetadataTracking.h - Metadata tracking ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Low-level functions to enable tracking of metadata that could RAUW.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_METADATATRACKING_H
+#define LLVM_IR_METADATATRACKING_H
+
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/Support/Casting.h"
+#include <type_traits>
+
+namespace llvm {
+
+class Metadata;
+class MetadataAsValue;
+
+/// \brief API for tracking metadata references through RAUW and deletion.
+///
+/// Shared API for updating \a Metadata pointers in subclasses that support
+/// RAUW.
+///
+/// This API is not meant to be used directly. See \a TrackingMDRef for a
+/// user-friendly tracking reference.
+class MetadataTracking {
+public:
+ /// \brief Track the reference to metadata.
+ ///
+ /// Register \c MD with \c *MD, if the subclass supports tracking. If \c *MD
+ /// gets RAUW'ed, \c MD will be updated to the new address. If \c *MD gets
+ /// deleted, \c MD will be set to \c nullptr.
+ ///
+ /// If tracking isn't supported, \c *MD will not change.
+ ///
+ /// \return true iff tracking is supported by \c MD.
+ static bool track(Metadata *&MD) {
+ return track(&MD, *MD, static_cast<Metadata *>(nullptr));
+ }
+
+ /// \brief Track the reference to metadata for \a Metadata.
+ ///
+ /// As \a track(Metadata*&), but with support for calling back to \c Owner to
+ /// tell it that its operand changed. This could trigger \c Owner being
+ /// re-uniqued.
+ static bool track(void *Ref, Metadata &MD, Metadata &Owner) {
+ return track(Ref, MD, &Owner);
+ }
+
+ /// \brief Track the reference to metadata for \a MetadataAsValue.
+ ///
+ /// As \a track(Metadata*&), but with support for calling back to \c Owner to
+ /// tell it that its operand changed. This could trigger \c Owner being
+ /// re-uniqued.
+ static bool track(void *Ref, Metadata &MD, MetadataAsValue &Owner) {
+ return track(Ref, MD, &Owner);
+ }
+
+ /// \brief Stop tracking a reference to metadata.
+ ///
+ /// Stops \c *MD from tracking \c MD.
+ static void untrack(Metadata *&MD) { untrack(&MD, *MD); }
+ static void untrack(void *Ref, Metadata &MD);
+
+ /// \brief Move tracking from one reference to another.
+ ///
+ /// Semantically equivalent to \c untrack(MD) followed by \c track(New),
+ /// except that ownership callbacks are maintained.
+ ///
+ /// Note: it is an error if \c *MD does not equal \c New.
+ ///
+ /// \return true iff tracking is supported by \c MD.
+ static bool retrack(Metadata *&MD, Metadata *&New) {
+ return retrack(&MD, *MD, &New);
+ }
+ static bool retrack(void *Ref, Metadata &MD, void *New);
+
+ /// \brief Check whether metadata is replaceable.
+ static bool isReplaceable(const Metadata &MD);
+
+ typedef PointerUnion<MetadataAsValue *, Metadata *> OwnerTy;
+
+private:
+ /// \brief Track a reference to metadata for an owner.
+ ///
+ /// Generalized version of tracking.
+ static bool track(void *Ref, Metadata &MD, OwnerTy Owner);
+};
+
+} // end namespace llvm
+
+#endif
ModFlagBehaviorLastVal = AppendUnique
};
- /// Checks if Value represents a valid ModFlagBehavior, and stores the
+ /// Checks if Metadata represents a valid ModFlagBehavior, and stores the
/// converted result in MFB.
- static bool isValidModFlagBehavior(Value *V, ModFlagBehavior &MFB);
+ static bool isValidModFlagBehavior(Metadata *MD, ModFlagBehavior &MFB);
struct ModuleFlagEntry {
ModFlagBehavior Behavior;
MDString *Key;
- Value *Val;
- ModuleFlagEntry(ModFlagBehavior B, MDString *K, Value *V)
- : Behavior(B), Key(K), Val(V) {}
+ Metadata *Val;
+ ModuleFlagEntry(ModFlagBehavior B, MDString *K, Metadata *V)
+ : Behavior(B), Key(K), Val(V) {}
};
/// @}
/// Return the corresponding value if Key appears in module flags, otherwise
/// return null.
- Value *getModuleFlag(StringRef Key) const;
+ Metadata *getModuleFlag(StringRef Key) const;
/// Returns the NamedMDNode in the module that represents module-level flags.
/// This method returns null if there are no module-level flags.
/// Add a module-level flag to the module-level flags metadata. It will create
/// the module-level flags named metadata if it doesn't already exist.
- void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, Value *Val);
+ void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, Metadata *Val);
+ void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, Constant *Val);
void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, uint32_t Val);
void addModuleFlag(MDNode *Node);
--- /dev/null
+//===- llvm/IR/TrackingMDRef.h - Tracking Metadata references -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// References to metadata that track RAUW.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_TRACKINGMDREF_H
+#define LLVM_IR_TRACKINGMDREF_H
+
+#include "llvm/IR/MetadataTracking.h"
+#include "llvm/Support/Casting.h"
+
+namespace llvm {
+
+class Metadata;
+class MDNode;
+class ValueAsMetadata;
+
+/// \brief Tracking metadata reference.
+///
+/// This class behaves like \a TrackingVH, but for metadata.
+class TrackingMDRef {
+ Metadata *MD;
+
+public:
+ TrackingMDRef() : MD(nullptr) {}
+ explicit TrackingMDRef(Metadata *MD) : MD(MD) { track(); }
+
+ TrackingMDRef(TrackingMDRef &&X) : MD(X.MD) { retrack(X); }
+ TrackingMDRef(const TrackingMDRef &X) : MD(X.MD) { track(); }
+ TrackingMDRef &operator=(TrackingMDRef &&X) {
+ if (&X == this)
+ return *this;
+
+ untrack();
+ MD = X.MD;
+ retrack(X);
+ return *this;
+ }
+ TrackingMDRef &operator=(const TrackingMDRef &X) {
+ if (&X == this)
+ return *this;
+
+ untrack();
+ MD = X.MD;
+ track();
+ return *this;
+ }
+ ~TrackingMDRef() { untrack(); }
+
+ LLVM_EXPLICIT operator bool() const { return get(); }
+ Metadata *get() const { return MD; }
+ operator Metadata *() const { return get(); }
+ Metadata *operator->() const { return get(); }
+ Metadata &operator*() const { return *get(); }
+
+ void reset() {
+ untrack();
+ MD = nullptr;
+ }
+ void reset(Metadata *MD) {
+ untrack();
+ this->MD = MD;
+ track();
+ }
+
+ /// \brief Check whether this has a trivial destructor.
+ ///
+ /// If \c MD isn't replaceable, the destructor will be a no-op.
+ bool hasTrivialDestructor() const {
+ return !MD || !MetadataTracking::isReplaceable(*MD);
+ }
+
+private:
+ void track() {
+ if (MD)
+ MetadataTracking::track(MD);
+ }
+ void untrack() {
+ if (MD)
+ MetadataTracking::untrack(MD);
+ }
+ void retrack(TrackingMDRef &X) {
+ assert(MD == X.MD && "Expected values to match");
+ if (X.MD) {
+ MetadataTracking::retrack(X.MD, MD);
+ X.MD = nullptr;
+ }
+ }
+};
+
+/// \brief Typed tracking ref.
+///
+/// Track refererences of a particular type. It's useful to use this for \a
+/// MDNode and \a ValueAsMetadata.
+template <class T> class TypedTrackingMDRef {
+ TrackingMDRef Ref;
+
+public:
+ TypedTrackingMDRef() {}
+ explicit TypedTrackingMDRef(T *MD) : Ref(static_cast<Metadata *>(MD)) {}
+
+ TypedTrackingMDRef(TypedTrackingMDRef &&X) : Ref(std::move(X.Ref)) {}
+ TypedTrackingMDRef(const TypedTrackingMDRef &X) : Ref(X.Ref) {}
+ TypedTrackingMDRef &operator=(TypedTrackingMDRef &&X) {
+ Ref = std::move(X.Ref);
+ return *this;
+ }
+ TypedTrackingMDRef &operator=(const TypedTrackingMDRef &X) {
+ Ref = X.Ref;
+ return *this;
+ }
+
+ LLVM_EXPLICIT operator bool() const { return get(); }
+ T *get() const { return (T *)Ref.get(); }
+ operator T *() const { return get(); }
+ T *operator->() const { return get(); }
+ T &operator*() const { return *get(); }
+
+ void reset() { Ref.reset(); }
+ void reset(T *MD) { Ref.reset(static_cast<Metadata *>(MD)); }
+
+ /// \brief Check whether this has a trivial destructor.
+ bool hasTrivialDestructor() const { return Ref.hasTrivialDestructor(); }
+};
+
+typedef TypedTrackingMDRef<MDNode> TrackingMDNodeRef;
+typedef TypedTrackingMDRef<ValueAsMetadata> TrackingValueAsMetadataRef;
+
+// Expose the underlying metadata to casting.
+template <> struct simplify_type<TrackingMDRef> {
+ typedef Metadata *SimpleType;
+ static SimpleType getSimplifiedValue(TrackingMDRef &MD) { return MD.get(); }
+};
+
+template <> struct simplify_type<const TrackingMDRef> {
+ typedef Metadata *SimpleType;
+ static SimpleType getSimplifiedValue(const TrackingMDRef &MD) {
+ return MD.get();
+ }
+};
+
+template <class T> struct simplify_type<TypedTrackingMDRef<T>> {
+ typedef T *SimpleType;
+ static SimpleType getSimplifiedValue(TypedTrackingMDRef<T> &MD) {
+ return MD.get();
+ }
+};
+
+template <class T> struct simplify_type<const TypedTrackingMDRef<T>> {
+ typedef T *SimpleType;
+ static SimpleType getSimplifiedValue(const TypedTrackingMDRef<T> &MD) {
+ return MD.get();
+ }
+};
+
+} // end namespace llvm
+
+#endif
// To avoid walking constant expressions multiple times and other IR
// objects, we keep several helper maps.
DenseSet<const Value*> VisitedConstants;
+ DenseSet<const MDNode *> VisitedMetadata;
DenseSet<Type*> VisitedTypes;
std::vector<StructType*> StructTypes;
class InlineAsm;
class Instruction;
class LLVMContext;
-class MDNode;
class Module;
class StringRef;
class Twine;
Type *VTy;
Use *UseList;
- friend class ValueSymbolTable; // Allow ValueSymbolTable to directly mod Name.
+ friend class ValueAsMetadata; // Allow access to NameAndIsUsedByMD.
friend class ValueHandleBase;
- ValueName *Name;
+ PointerIntPair<ValueName *, 1> NameAndIsUsedByMD;
const unsigned char SubclassID; // Subclass identifier (for isa/dyn_cast)
unsigned char HasValueHandle : 1; // Has a ValueHandle pointing to this?
LLVMContext &getContext() const;
// \brief All values can potentially be named.
- bool hasName() const { return Name != nullptr; }
- ValueName *getValueName() const { return Name; }
- void setValueName(ValueName *VN) { Name = VN; }
+ bool hasName() const { return getValueName() != nullptr; }
+ ValueName *getValueName() const { return NameAndIsUsedByMD.getPointer(); }
+ void setValueName(ValueName *VN) { NameAndIsUsedByMD.setPointer(VN); }
+private:
+ void destroyValueName();
+
+public:
/// \brief Return a constant reference to the value's name.
///
/// This is cheap and guaranteed to return the same reference as long as the
ConstantStructVal, // This is an instance of ConstantStruct
ConstantVectorVal, // This is an instance of ConstantVector
ConstantPointerNullVal, // This is an instance of ConstantPointerNull
- GenericMDNodeVal, // This is an instance of GenericMDNode
- MDNodeFwdDeclVal, // This is an instance of MDNodeFwdDecl
- MDStringVal, // This is an instance of MDString
+ MetadataAsValueVal, // This is an instance of MetadataAsValue
InlineAsmVal, // This is an instance of InlineAsm
InstructionVal, // This is an instance of Instruction
// Enum values starting at InstructionVal are used for Instructions;
/// \brief Return true if there is a value handle associated with this value.
bool hasValueHandle() const { return HasValueHandle; }
+ /// \brief Return true if there is metadata referencing this value.
+ bool isUsedByMetadata() const { return NameAndIsUsedByMD.getInt(); }
+
/// \brief Strip off pointer casts, all-zero GEPs, and aliases.
///
/// Returns the original uncasted value. If this is called on a non-pointer
}
};
-template <> struct isa_impl<MDNode, Value> {
- static inline bool doit(const Value &Val) {
- return Val.getValueID() == Value::GenericMDNodeVal ||
- Val.getValueID() == Value::MDNodeFwdDeclVal;
- }
-};
-
// Value* is only 4-byte aligned.
template<>
class PointerLikeTypeTraits<Value*> {
#define LLVM_IR_VALUEMAP_H
#include "llvm/ADT/DenseMap.h"
+#include "llvm/IR/TrackingMDRef.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Support/Mutex.h"
#include "llvm/Support/UniqueLock.h"
friend class ValueMapCallbackVH<KeyT, ValueT, Config>;
typedef ValueMapCallbackVH<KeyT, ValueT, Config> ValueMapCVH;
typedef DenseMap<ValueMapCVH, ValueT, DenseMapInfo<ValueMapCVH> > MapT;
+ typedef DenseMap<const Metadata *, TrackingMDRef> MDMapT;
typedef typename Config::ExtraData ExtraData;
MapT Map;
+ std::unique_ptr<MDMapT> MDMap;
ExtraData Data;
ValueMap(const ValueMap&) LLVM_DELETED_FUNCTION;
ValueMap& operator=(const ValueMap&) LLVM_DELETED_FUNCTION;
typedef unsigned size_type;
explicit ValueMap(unsigned NumInitBuckets = 64)
- : Map(NumInitBuckets), Data() {}
+ : Map(NumInitBuckets), Data() {}
explicit ValueMap(const ExtraData &Data, unsigned NumInitBuckets = 64)
- : Map(NumInitBuckets), Data(Data) {}
+ : Map(NumInitBuckets), Data(Data) {}
~ValueMap() {}
+ bool hasMD() const { return MDMap; }
+ MDMapT &MD() {
+ if (!MDMap)
+ MDMap.reset(new MDMapT);
+ return *MDMap;
+ }
+
typedef ValueMapIterator<MapT, KeyT> iterator;
typedef ValueMapConstIterator<MapT, KeyT> const_iterator;
inline iterator begin() { return iterator(Map.begin()); }
/// Grow the map so that it has at least Size buckets. Does not shrink
void resize(size_t Size) { Map.resize(Size); }
- void clear() { Map.clear(); }
+ void clear() {
+ Map.clear();
+ MDMap.reset();
+ }
/// Return 1 if the specified key is in the map, 0 otherwise.
size_type count(const KeyT &Val) const {
ValueMapTypeRemapper *TypeMapper = nullptr,
ValueMaterializer *Materializer = nullptr);
+ Metadata *MapValue(const Metadata *MD, ValueToValueMapTy &VM,
+ RemapFlags Flags = RF_None,
+ ValueMapTypeRemapper *TypeMapper = nullptr,
+ ValueMaterializer *Materializer = nullptr);
+
+ /// MapValue - provide versions that preserve type safety for MDNodes.
+ MDNode *MapValue(const MDNode *MD, ValueToValueMapTy &VM,
+ RemapFlags Flags = RF_None,
+ ValueMapTypeRemapper *TypeMapper = nullptr,
+ ValueMaterializer *Materializer = nullptr);
+
void RemapInstruction(Instruction *I, ValueToValueMapTy &VM,
RemapFlags Flags = RF_None,
ValueMapTypeRemapper *TypeMapper = nullptr,
ValueMaterializer *Materializer = nullptr);
- /// MapValue - provide versions that preserve type safety for MDNode and
- /// Constants.
- inline MDNode *MapValue(const MDNode *V, ValueToValueMapTy &VM,
- RemapFlags Flags = RF_None,
- ValueMapTypeRemapper *TypeMapper = nullptr,
- ValueMaterializer *Materializer = nullptr) {
- return cast<MDNode>(MapValue((const Value*)V, VM, Flags, TypeMapper,
- Materializer));
- }
+ /// MapValue - provide versions that preserve type safety for Constants.
inline Constant *MapValue(const Constant *V, ValueToValueMapTy &VM,
RemapFlags Flags = RF_None,
ValueMapTypeRemapper *TypeMapper = nullptr,
SmallVector<uint32_t, 2> Weights;
Weights.reserve(TI->getNumSuccessors());
for (unsigned i = 1, e = WeightsNode->getNumOperands(); i != e; ++i) {
- ConstantInt *Weight = dyn_cast<ConstantInt>(WeightsNode->getOperand(i));
+ ConstantInt *Weight =
+ mdconst::dyn_extract<ConstantInt>(WeightsNode->getOperand(i));
if (!Weight)
return false;
Weights.push_back(
assert(NumRanges >= 1);
for (unsigned i = 0; i < NumRanges; ++i) {
- ConstantInt *Lower = cast<ConstantInt>(MD->getOperand(2*i + 0));
- ConstantInt *Upper = cast<ConstantInt>(MD->getOperand(2*i + 1));
+ ConstantInt *Lower =
+ mdconst::extract<ConstantInt>(MD->getOperand(2 * i + 0));
+ ConstantInt *Upper =
+ mdconst::extract<ConstantInt>(MD->getOperand(2 * i + 1));
ConstantRange Range(Lower->getValue(), Upper->getValue());
TotalRange = TotalRange.unionWith(Range);
}
bool TypeIsImmutable() const {
if (Node->getNumOperands() < 3)
return false;
- ConstantInt *CI = dyn_cast<ConstantInt>(Node->getOperand(2));
+ ConstantInt *CI = mdconst::dyn_extract<ConstantInt>(Node->getOperand(2));
if (!CI)
return false;
return CI->getValue()[0];
return dyn_cast_or_null<MDNode>(Node->getOperand(1));
}
uint64_t getOffset() const {
- return cast<ConstantInt>(Node->getOperand(2))->getZExtValue();
+ return mdconst::extract<ConstantInt>(Node->getOperand(2))->getZExtValue();
}
/// TypeIsImmutable - Test if this TBAAStructTagNode represents a type for
/// objects which are not modified (by any means) in the context where this
bool TypeIsImmutable() const {
if (Node->getNumOperands() < 4)
return false;
- ConstantInt *CI = dyn_cast<ConstantInt>(Node->getOperand(3));
+ ConstantInt *CI = mdconst::dyn_extract<ConstantInt>(Node->getOperand(3));
if (!CI)
return false;
return CI->getValue()[0];
// Fast path for a scalar type node and a struct type node with a single
// field.
if (Node->getNumOperands() <= 3) {
- uint64_t Cur = Node->getNumOperands() == 2 ? 0 :
- cast<ConstantInt>(Node->getOperand(2))->getZExtValue();
+ uint64_t Cur = Node->getNumOperands() == 2
+ ? 0
+ : mdconst::extract<ConstantInt>(Node->getOperand(2))
+ ->getZExtValue();
Offset -= Cur;
MDNode *P = dyn_cast_or_null<MDNode>(Node->getOperand(1));
if (!P)
// the current offset is bigger than the given offset.
unsigned TheIdx = 0;
for (unsigned Idx = 1; Idx < Node->getNumOperands(); Idx += 2) {
- uint64_t Cur = cast<ConstantInt>(Node->getOperand(Idx + 1))->
- getZExtValue();
+ uint64_t Cur = mdconst::extract<ConstantInt>(Node->getOperand(Idx + 1))
+ ->getZExtValue();
if (Cur > Offset) {
assert(Idx >= 3 &&
"TBAAStructTypeNode::getParent should have an offset match!");
// Move along the last field.
if (TheIdx == 0)
TheIdx = Node->getNumOperands() - 2;
- uint64_t Cur = cast<ConstantInt>(Node->getOperand(TheIdx + 1))->
- getZExtValue();
+ uint64_t Cur = mdconst::extract<ConstantInt>(Node->getOperand(TheIdx + 1))
+ ->getZExtValue();
Offset -= Cur;
MDNode *P = dyn_cast_or_null<MDNode>(Node->getOperand(TheIdx));
if (!P)
return nullptr;
// We need to convert from a type node to a tag node.
Type *Int64 = IntegerType::get(A->getContext(), 64);
- Value *Ops[3] = { Ret, Ret, ConstantInt::get(Int64, 0) };
+ Metadata *Ops[3] = {Ret, Ret,
+ ConstantAsMetadata::get(ConstantInt::get(Int64, 0))};
return MDNode::get(A->getContext(), Ops);
}
// Use the high end of the ranges to find leading zeros.
unsigned MinLeadingZeros = BitWidth;
for (unsigned i = 0; i < NumRanges; ++i) {
- ConstantInt *Lower = cast<ConstantInt>(Ranges.getOperand(2*i + 0));
- ConstantInt *Upper = cast<ConstantInt>(Ranges.getOperand(2*i + 1));
+ ConstantInt *Lower =
+ mdconst::extract<ConstantInt>(Ranges.getOperand(2 * i + 0));
+ ConstantInt *Upper =
+ mdconst::extract<ConstantInt>(Ranges.getOperand(2 * i + 1));
ConstantRange Range(Lower->getValue(), Upper->getValue());
if (Range.isWrappedSet())
MinLeadingZeros = 0; // -1 has no zeros
const unsigned NumRanges = Ranges->getNumOperands() / 2;
assert(NumRanges >= 1);
for (unsigned i = 0; i < NumRanges; ++i) {
- ConstantInt *Lower = cast<ConstantInt>(Ranges->getOperand(2*i + 0));
- ConstantInt *Upper = cast<ConstantInt>(Ranges->getOperand(2*i + 1));
+ ConstantInt *Lower =
+ mdconst::extract<ConstantInt>(Ranges->getOperand(2 * i + 0));
+ ConstantInt *Upper =
+ mdconst::extract<ConstantInt>(Ranges->getOperand(2 * i + 1));
ConstantRange Range(Lower->getValue(), Upper->getValue());
if (Range.contains(Value))
return false;
NumberedMetadata[SlotNo] == nullptr)
return Error(MDList[i].Loc, "use of undefined metadata '!" +
Twine(SlotNo) + "'");
- assert(!NumberedMetadata[SlotNo]->isFunctionLocal() &&
- "Unexpected function-local metadata");
Inst->setMetadata(MDList[i].MDKind, NumberedMetadata[SlotNo]);
}
}
"use of undefined metadata '!" +
Twine(ForwardRefMDNodes.begin()->first) + "'");
+ // Resolve metadata cycles.
+ for (auto &N : NumberedMetadata)
+ if (auto *G = cast_or_null<GenericMDNode>(N))
+ G->resolveCycles();
// Look for intrinsic functions and CallInst that need to be upgraded
for (Module::iterator FI = M->begin(), FE = M->end(); FI != FE; )
if (Result) return false;
// Otherwise, create MDNode forward reference.
- MDNode *FwdNode = MDNode::getTemporary(Context, None);
+ MDNodeFwdDecl *FwdNode = MDNode::getTemporary(Context, None);
ForwardRefMDNodes[MID] = std::make_pair(FwdNode, Lex.getLoc());
if (NumberedMetadata.size() <= MID)
NumberedMetadata.resize(MID+1);
- NumberedMetadata[MID] = FwdNode;
+ NumberedMetadata[MID].reset(FwdNode);
Result = FwdNode;
return false;
}
LocTy TyLoc;
Type *Ty = nullptr;
- SmallVector<Value *, 16> Elts;
+ MDNode *Init;
if (ParseUInt32(MetadataID) ||
ParseToken(lltok::equal, "expected '=' here") ||
ParseType(Ty, TyLoc) ||
ParseToken(lltok::exclaim, "Expected '!' here") ||
- ParseToken(lltok::lbrace, "Expected '{' here") ||
- ParseMDNodeVector(Elts, nullptr) ||
- ParseToken(lltok::rbrace, "expected end of metadata node"))
+ ParseMDNode(Init))
return true;
- MDNode *Init = MDNode::get(Context, Elts);
-
// See if this was forward referenced, if so, handle it.
- std::map<unsigned, std::pair<TrackingVH<MDNode>, LocTy> >::iterator
- FI = ForwardRefMDNodes.find(MetadataID);
+ auto FI = ForwardRefMDNodes.find(MetadataID);
if (FI != ForwardRefMDNodes.end()) {
- MDNode *Temp = FI->second.first;
+ auto *Temp = FI->second.first;
Temp->replaceAllUsesWith(Init);
MDNode::deleteTemporary(Temp);
ForwardRefMDNodes.erase(FI);
if (NumberedMetadata[MetadataID] != nullptr)
return TokError("Metadata id is already used");
- NumberedMetadata[MetadataID] = Init;
+ NumberedMetadata[MetadataID].reset(Init);
}
return false;
if (ParseToken(lltok::exclaim, "expected '!' here"))
return true;
- // This code is similar to that of ParseMetadataValue, however it needs to
+ // This code is similar to that of ParseMetadata, however it needs to
// have special-case code for a forward reference; see the comments on
// ForwardRefInstMetadata for details. Also, MDStrings are not supported
// at the top level here.
if (Lex.getKind() == lltok::lbrace) {
- ValID ID;
- if (ParseMetadataListValue(ID, PFS))
+ MDNode *N;
+ if (ParseMDNode(N))
return true;
- assert(ID.Kind == ValID::t_MDNode);
- if (ID.MDNodeVal->isFunctionLocal())
- return Error(Loc, "unexpected function-local metadata");
- Inst->setMetadata(MDK, ID.MDNodeVal);
+ Inst->setMetadata(MDK, N);
} else {
unsigned NodeID = 0;
if (ParseMDNodeID(Node, NodeID))
ID.Kind = ValID::t_LocalName;
break;
case lltok::exclaim: // !42, !{...}, or !"foo"
- return ParseMetadataValue(ID, PFS);
+ return ParseMetadataAsValue(ID, PFS);
case lltok::APSInt:
ID.APSIntVal = Lex.getAPSIntVal();
ID.Kind = ValID::t_APSInt;
return false;
}
-bool LLParser::ParseMetadataListValue(ValID &ID, PerFunctionState *PFS) {
- assert(Lex.getKind() == lltok::lbrace);
- Lex.Lex();
+bool LLParser::ParseMDNode(MDNode *&MD) {
+ SmallVector<Metadata *, 16> Elts;
+ if (ParseMDNodeVector(Elts, nullptr))
+ return true;
- SmallVector<Value*, 16> Elts;
- if (ParseMDNodeVector(Elts, PFS) ||
- ParseToken(lltok::rbrace, "expected end of metadata node"))
+ MD = MDNode::get(Context, Elts);
+ return false;
+}
+
+bool LLParser::ParseMDNodeOrLocal(Metadata *&MD, PerFunctionState *PFS) {
+ SmallVector<Metadata *, 16> Elts;
+ if (ParseMDNodeVector(Elts, PFS))
return true;
- ID.MDNodeVal = MDNode::get(Context, Elts);
- ID.Kind = ValID::t_MDNode;
+ // Check for function-local metadata masquerading as an MDNode.
+ if (PFS && Elts.size() == 1 && Elts[0] && isa<LocalAsMetadata>(Elts[0])) {
+ MD = Elts[0];
+ return false;
+ }
+
+ MD = MDNode::get(Context, Elts);
+ return false;
+}
+
+bool LLParser::ParseMetadataAsValue(ValID &ID, PerFunctionState *PFS) {
+ Metadata *MD;
+ if (ParseMetadata(MD, PFS))
+ return true;
+
+ ID.Kind = ValID::t_Metadata;
+ ID.MetadataVal = MetadataAsValue::get(Context, MD);
return false;
}
-/// ParseMetadataValue
+/// ParseMetadata
/// ::= !42
/// ::= !{...}
/// ::= !"string"
-bool LLParser::ParseMetadataValue(ValID &ID, PerFunctionState *PFS) {
+bool LLParser::ParseMetadata(Metadata *&MD, PerFunctionState *PFS) {
assert(Lex.getKind() == lltok::exclaim);
Lex.Lex();
// MDNode:
// !{ ... }
if (Lex.getKind() == lltok::lbrace)
- return ParseMetadataListValue(ID, PFS);
+ return ParseMDNodeOrLocal(MD, PFS);
// Standalone metadata reference
// !42
if (Lex.getKind() == lltok::APSInt) {
- if (ParseMDNodeID(ID.MDNodeVal)) return true;
- ID.Kind = ValID::t_MDNode;
+ MDNode *N;
+ if (ParseMDNodeID(N))
+ return true;
+ MD = N;
return false;
}
// MDString:
// ::= '!' STRINGCONSTANT
- if (ParseMDString(ID.MDStringVal)) return true;
- ID.Kind = ValID::t_MDString;
+ MDString *S;
+ if (ParseMDString(S))
+ return true;
+ MD = S;
return false;
}
(ID.UIntVal>>1)&1, (InlineAsm::AsmDialect(ID.UIntVal>>2)));
return false;
}
- case ValID::t_MDNode:
+ case ValID::t_Metadata:
if (!Ty->isMetadataTy())
return Error(ID.Loc, "metadata value must have metadata type");
- V = ID.MDNodeVal;
- return false;
- case ValID::t_MDString:
- if (!Ty->isMetadataTy())
- return Error(ID.Loc, "metadata value must have metadata type");
- V = ID.MDStringVal;
+ V = ID.MetadataVal;
return false;
case ValID::t_GlobalName:
V = GetGlobalVal(ID.StrVal, Ty, ID.Loc);
//===----------------------------------------------------------------------===//
/// ParseMDNodeVector
-/// ::= Element (',' Element)*
+/// ::= { Element (',' Element)* }
/// Element
/// ::= 'null' | TypeAndValue
-bool LLParser::ParseMDNodeVector(SmallVectorImpl<Value*> &Elts,
+bool LLParser::ParseMDNodeVector(SmallVectorImpl<Metadata *> &Elts,
PerFunctionState *PFS) {
+ assert(Lex.getKind() == lltok::lbrace);
+ Lex.Lex();
+
// Check for an empty list.
- if (Lex.getKind() == lltok::rbrace)
+ if (EatIfPresent(lltok::rbrace))
return false;
bool IsLocal = false;
continue;
}
+ Type *Ty = nullptr;
+ if (ParseType(Ty))
+ return true;
+
+ if (Ty->isMetadataTy()) {
+ // No function-local metadata here.
+ Metadata *MD = nullptr;
+ if (ParseMetadata(MD, nullptr))
+ return true;
+ Elts.push_back(MD);
+ continue;
+ }
+
Value *V = nullptr;
- if (ParseTypeAndValue(V, PFS)) return true;
- Elts.push_back(V);
+ if (ParseValue(Ty, V, PFS))
+ return true;
+ assert(V && "Expected valid value");
+ Elts.push_back(ValueAsMetadata::get(V));
- if (isa<MDNode>(V) && cast<MDNode>(V)->isFunctionLocal())
- return TokError("unexpected nested function-local metadata");
- if (!V->getType()->isMetadataTy() && !isa<Constant>(V)) {
+ if (isa<LocalAsMetadata>(Elts.back())) {
assert(PFS && "Unexpected function-local metadata without PFS");
if (Elts.size() > 1)
return TokError("unexpected function-local metadata");
}
} while (EatIfPresent(lltok::comma));
- return false;
+ return ParseToken(lltok::rbrace, "expected end of metadata node");
}
//===----------------------------------------------------------------------===//
t_EmptyArray, // No value: []
t_Constant, // Value in ConstantVal.
t_InlineAsm, // Value in StrVal/StrVal2/UIntVal.
- t_MDNode, // Value in MDNodeVal.
- t_MDString, // Value in MDStringVal.
+ t_Metadata, // Value in MetadataVal.
t_ConstantStruct, // Value in ConstantStructElts.
t_PackedConstantStruct // Value in ConstantStructElts.
} Kind;
APSInt APSIntVal;
APFloat APFloatVal;
Constant *ConstantVal;
- MDNode *MDNodeVal;
- MDString *MDStringVal;
+ MetadataAsValue *MetadataVal;
Constant **ConstantStructElts;
ValID() : Kind(t_LocalID), APFloatVal(0.0) {}
StringMap<std::pair<Type*, LocTy> > NamedTypes;
std::vector<std::pair<Type*, LocTy> > NumberedTypes;
- std::vector<TrackingVH<MDNode> > NumberedMetadata;
- std::map<unsigned, std::pair<TrackingVH<MDNode>, LocTy> > ForwardRefMDNodes;
+ std::vector<TrackingMDNodeRef> NumberedMetadata;
+ std::map<unsigned, std::pair<MDNodeFwdDecl *, LocTy>> ForwardRefMDNodes;
// Global Value reference information.
std::map<std::string, std::pair<GlobalValue*, LocTy> > ForwardRefVals;
bool ParseGlobalTypeAndValue(Constant *&V);
bool ParseGlobalValueVector(SmallVectorImpl<Constant *> &Elts);
bool parseOptionalComdat(Comdat *&C);
- bool ParseMetadataListValue(ValID &ID, PerFunctionState *PFS);
- bool ParseMetadataValue(ValID &ID, PerFunctionState *PFS);
- bool ParseMDNodeVector(SmallVectorImpl<Value*> &, PerFunctionState *PFS);
+ bool ParseMetadataAsValue(ValID &ID, PerFunctionState *PFS);
+ bool ParseMetadata(Metadata *&MD, PerFunctionState *PFS);
+ bool ParseMDNode(MDNode *&MD);
+ bool ParseMDNodeOrLocal(Metadata *&MD, PerFunctionState *PFS);
+ bool ParseMDNodeVector(SmallVectorImpl<Metadata *> &,
+ PerFunctionState *PFS);
bool ParseInstructionMetadata(Instruction *Inst, PerFunctionState *PFS);
// Function Parsing.
}
}
-void BitcodeReaderMDValueList::AssignValue(Value *V, unsigned Idx) {
+void BitcodeReaderMDValueList::AssignValue(Metadata *MD, unsigned Idx) {
if (Idx == size()) {
- push_back(V);
+ push_back(MD);
return;
}
if (Idx >= size())
resize(Idx+1);
- WeakVH &OldV = MDValuePtrs[Idx];
- if (!OldV) {
- OldV = V;
+ TrackingMDRef &OldMD = MDValuePtrs[Idx];
+ if (!OldMD) {
+ OldMD.reset(MD);
return;
}
// If there was a forward reference to this value, replace it.
- MDNode *PrevVal = cast<MDNode>(OldV);
- OldV->replaceAllUsesWith(V);
- MDNode::deleteTemporary(PrevVal);
- // Deleting PrevVal sets Idx value in MDValuePtrs to null. Set new
- // value for Idx.
- MDValuePtrs[Idx] = V;
+ MDNodeFwdDecl *PrevMD = cast<MDNodeFwdDecl>(OldMD.get());
+ PrevMD->replaceAllUsesWith(MD);
+ MDNode::deleteTemporary(PrevMD);
+ --NumFwdRefs;
}
-Value *BitcodeReaderMDValueList::getValueFwdRef(unsigned Idx) {
+Metadata *BitcodeReaderMDValueList::getValueFwdRef(unsigned Idx) {
if (Idx >= size())
resize(Idx + 1);
- if (Value *V = MDValuePtrs[Idx]) {
- assert(V->getType()->isMetadataTy() && "Type mismatch in value table!");
- return V;
- }
+ if (Metadata *MD = MDValuePtrs[Idx])
+ return MD;
// Create and return a placeholder, which will later be RAUW'd.
- Value *V = MDNode::getTemporary(Context, None);
- MDValuePtrs[Idx] = V;
- return V;
+ AnyFwdRefs = true;
+ ++NumFwdRefs;
+ Metadata *MD = MDNode::getTemporary(Context, None);
+ MDValuePtrs[Idx].reset(MD);
+ return MD;
+}
+
+void BitcodeReaderMDValueList::tryToResolveCycles() {
+ if (!AnyFwdRefs)
+ // Nothing to do.
+ return;
+
+ if (NumFwdRefs)
+ // Still forward references... can't resolve cycles.
+ return;
+
+ // Resolve any cycles.
+ for (auto &MD : MDValuePtrs) {
+ assert(!(MD && isa<MDNodeFwdDecl>(MD)) && "Unexpected forward reference");
+ if (auto *G = dyn_cast_or_null<GenericMDNode>(MD))
+ G->resolveCycles();
+ }
}
Type *BitcodeReader::getTypeByID(unsigned ID) {
case BitstreamEntry::Error:
return Error(BitcodeError::MalformedBlock);
case BitstreamEntry::EndBlock:
+ MDValueList.tryToResolveCycles();
return std::error_code();
case BitstreamEntry::Record:
// The interesting case.
break;
}
case bitc::METADATA_FN_NODE: {
- // This is a function-local node.
+ // This is a LocalAsMetadata record, the only type of function-local
+ // metadata.
if (Record.size() % 2 == 1)
return Error(BitcodeError::InvalidRecord);
- // If this isn't a single-operand node that directly references
- // non-metadata, we're dropping it. This used to be legal, but there's
- // no upgrade path.
+ // If this isn't a LocalAsMetadata record, we're dropping it. This used
+ // to be legal, but there's no upgrade path.
auto dropRecord = [&] {
MDValueList.AssignValue(MDNode::get(Context, None), NextMDValueNo++);
};
break;
}
- Value *Elts[] = {ValueList.getValueFwdRef(Record[1], Ty)};
- Value *V = MDNode::getWhenValsUnresolved(Context, Elts,
- /*IsFunctionLocal*/ true);
- MDValueList.AssignValue(V, NextMDValueNo++);
+ MDValueList.AssignValue(
+ LocalAsMetadata::get(ValueList.getValueFwdRef(Record[1], Ty)),
+ NextMDValueNo++);
break;
}
case bitc::METADATA_NODE: {
return Error(BitcodeError::InvalidRecord);
unsigned Size = Record.size();
- SmallVector<Value*, 8> Elts;
+ SmallVector<Metadata *, 8> Elts;
for (unsigned i = 0; i != Size; i += 2) {
Type *Ty = getTypeByID(Record[i]);
if (!Ty)
return Error(BitcodeError::InvalidRecord);
if (Ty->isMetadataTy())
Elts.push_back(MDValueList.getValueFwdRef(Record[i+1]));
- else if (!Ty->isVoidTy())
- Elts.push_back(ValueList.getValueFwdRef(Record[i+1], Ty));
- else
+ else if (!Ty->isVoidTy()) {
+ auto *MD =
+ ValueAsMetadata::get(ValueList.getValueFwdRef(Record[i + 1], Ty));
+ assert(isa<ConstantAsMetadata>(MD) &&
+ "Expected non-function-local metadata");
+ Elts.push_back(MD);
+ } else
Elts.push_back(nullptr);
}
- Value *V = MDNode::getWhenValsUnresolved(Context, Elts,
- /*IsFunctionLocal*/ false);
- MDValueList.AssignValue(V, NextMDValueNo++);
+ MDValueList.AssignValue(MDNode::get(Context, Elts), NextMDValueNo++);
break;
}
case bitc::METADATA_STRING: {
std::string String(Record.begin(), Record.end());
llvm::UpgradeMDStringConstant(String);
- Value *V = MDString::get(Context, String);
- MDValueList.AssignValue(V, NextMDValueNo++);
+ Metadata *MD = MDString::get(Context, String);
+ MDValueList.AssignValue(MD, NextMDValueNo++);
break;
}
case bitc::METADATA_KIND: {
MDKindMap.find(Kind);
if (I == MDKindMap.end())
return Error(BitcodeError::InvalidID);
- MDNode *Node = cast<MDNode>(MDValueList.getValueFwdRef(Record[i+1]));
- if (Node->isFunctionLocal())
+ Metadata *Node = MDValueList.getValueFwdRef(Record[i + 1]);
+ if (isa<LocalAsMetadata>(Node))
// Drop the attachment. This used to be legal, but there's no
// upgrade path.
break;
- Inst->setMetadata(I->second, Node);
+ Inst->setMetadata(I->second, cast<MDNode>(Node));
if (I->second == LLVMContext::MD_tbaa)
InstsWithTBAATag.push_back(Inst);
}
#include "llvm/Bitcode/LLVMBitCodes.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/GVMaterializer.h"
+#include "llvm/IR/Metadata.h"
#include "llvm/IR/OperandTraits.h"
+#include "llvm/IR/TrackingMDRef.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/ValueHandle.h"
#include <deque>
//===----------------------------------------------------------------------===//
class BitcodeReaderMDValueList {
- std::vector<WeakVH> MDValuePtrs;
+ unsigned NumFwdRefs;
+ bool AnyFwdRefs;
+ std::vector<TrackingMDRef> MDValuePtrs;
LLVMContext &Context;
public:
- BitcodeReaderMDValueList(LLVMContext& C) : Context(C) {}
+ BitcodeReaderMDValueList(LLVMContext &C)
+ : NumFwdRefs(0), AnyFwdRefs(false), Context(C) {}
// vector compatibility methods
unsigned size() const { return MDValuePtrs.size(); }
void resize(unsigned N) { MDValuePtrs.resize(N); }
- void push_back(Value *V) { MDValuePtrs.push_back(V); }
+ void push_back(Metadata *MD) { MDValuePtrs.emplace_back(MD); }
void clear() { MDValuePtrs.clear(); }
- Value *back() const { return MDValuePtrs.back(); }
+ Metadata *back() const { return MDValuePtrs.back(); }
void pop_back() { MDValuePtrs.pop_back(); }
bool empty() const { return MDValuePtrs.empty(); }
- Value *operator[](unsigned i) const {
+ Metadata *operator[](unsigned i) const {
assert(i < MDValuePtrs.size());
return MDValuePtrs[i];
}
MDValuePtrs.resize(N);
}
- Value *getValueFwdRef(unsigned Idx);
- void AssignValue(Value *V, unsigned Idx);
+ Metadata *getValueFwdRef(unsigned Idx);
+ void AssignValue(Metadata *MD, unsigned Idx);
+ void tryToResolveCycles();
};
class BitcodeReader : public GVMaterializer {
Type *getTypeByID(unsigned ID);
Value *getFnValueByID(unsigned ID, Type *Ty) {
if (Ty && Ty->isMetadataTy())
- return MDValueList.getValueFwdRef(ID);
+ return MetadataAsValue::get(Ty->getContext(), getFnMetadataByID(ID));
return ValueList.getValueFwdRef(ID, Ty);
}
+ Metadata *getFnMetadataByID(unsigned ID) {
+ return MDValueList.getValueFwdRef(ID);
+ }
BasicBlock *getBasicBlock(unsigned ID) const {
if (ID >= FunctionBBs.size()) return nullptr; // Invalid ID
return FunctionBBs[ID];
return Flags;
}
+static void WriteValueAsMetadataImpl(const ValueAsMetadata *MD,
+ const ValueEnumerator &VE,
+ BitstreamWriter &Stream,
+ SmallVectorImpl<uint64_t> &Record,
+ unsigned Code) {
+ // Mimic an MDNode with a value as one operand.
+ Value *V = MD->getValue();
+ Record.push_back(VE.getTypeID(V->getType()));
+ Record.push_back(VE.getValueID(V));
+ Stream.EmitRecord(Code, Record, 0);
+ Record.clear();
+}
+
+static void WriteLocalAsMetadata(const LocalAsMetadata *MD,
+ const ValueEnumerator &VE,
+ BitstreamWriter &Stream,
+ SmallVectorImpl<uint64_t> &Record) {
+ WriteValueAsMetadataImpl(MD, VE, Stream, Record, bitc::METADATA_FN_NODE);
+}
+
+static void WriteConstantAsMetadata(const ConstantAsMetadata *MD,
+ const ValueEnumerator &VE,
+ BitstreamWriter &Stream,
+ SmallVectorImpl<uint64_t> &Record) {
+ WriteValueAsMetadataImpl(MD, VE, Stream, Record, bitc::METADATA_NODE);
+}
+
static void WriteMDNode(const MDNode *N,
const ValueEnumerator &VE,
BitstreamWriter &Stream,
SmallVectorImpl<uint64_t> &Record) {
for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
- if (N->getOperand(i)) {
- Record.push_back(VE.getTypeID(N->getOperand(i)->getType()));
- Record.push_back(VE.getValueID(N->getOperand(i)));
- } else {
+ Metadata *MD = N->getOperand(i);
+ if (!MD) {
Record.push_back(VE.getTypeID(Type::getVoidTy(N->getContext())));
Record.push_back(0);
+ continue;
}
+ if (auto *V = dyn_cast<ConstantAsMetadata>(MD)) {
+ Record.push_back(VE.getTypeID(V->getValue()->getType()));
+ Record.push_back(VE.getValueID(V->getValue()));
+ continue;
+ }
+ assert(!isa<LocalAsMetadata>(MD) && "Unexpected function-local metadata");
+ Record.push_back(VE.getTypeID(Type::getMetadataTy(N->getContext())));
+ Record.push_back(VE.getMetadataID(MD));
}
- unsigned MDCode = N->isFunctionLocal() ? bitc::METADATA_FN_NODE :
- bitc::METADATA_NODE;
- Stream.EmitRecord(MDCode, Record, 0);
+ Stream.EmitRecord(bitc::METADATA_NODE, Record, 0);
Record.clear();
}
static void WriteModuleMetadata(const Module *M,
const ValueEnumerator &VE,
BitstreamWriter &Stream) {
- const auto &Vals = VE.getMDValues();
+ const auto &MDs = VE.getMDs();
bool StartedMetadataBlock = false;
unsigned MDSAbbrev = 0;
SmallVector<uint64_t, 64> Record;
- for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
-
- if (const MDNode *N = dyn_cast<MDNode>(Vals[i])) {
- if (!N->isFunctionLocal() || !N->getFunction()) {
- if (!StartedMetadataBlock) {
- Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3);
- StartedMetadataBlock = true;
- }
- WriteMDNode(N, VE, Stream, Record);
+ for (unsigned i = 0, e = MDs.size(); i != e; ++i) {
+ if (const MDNode *N = dyn_cast<MDNode>(MDs[i])) {
+ if (!StartedMetadataBlock) {
+ Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3);
+ StartedMetadataBlock = true;
+ }
+ WriteMDNode(N, VE, Stream, Record);
+ } else if (const auto *MDC = dyn_cast<ConstantAsMetadata>(MDs[i])) {
+ if (!StartedMetadataBlock) {
+ Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3);
+ StartedMetadataBlock = true;
}
- } else if (const MDString *MDS = dyn_cast<MDString>(Vals[i])) {
- if (!StartedMetadataBlock) {
+ WriteConstantAsMetadata(MDC, VE, Stream, Record);
+ } else if (const MDString *MDS = dyn_cast<MDString>(MDs[i])) {
+ if (!StartedMetadataBlock) {
Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3);
// Abbrev for METADATA_STRING.
// Write named metadata operands.
for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i)
- Record.push_back(VE.getValueID(NMD->getOperand(i)));
+ Record.push_back(VE.getMetadataID(NMD->getOperand(i)));
Stream.EmitRecord(bitc::METADATA_NAMED_NODE, Record, 0);
Record.clear();
}
BitstreamWriter &Stream) {
bool StartedMetadataBlock = false;
SmallVector<uint64_t, 64> Record;
- const SmallVectorImpl<const MDNode *> &Vals = VE.getFunctionLocalMDValues();
- for (unsigned i = 0, e = Vals.size(); i != e; ++i)
- if (const MDNode *N = Vals[i])
- if (N->isFunctionLocal() && N->getFunction() == &F) {
- if (!StartedMetadataBlock) {
- Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3);
- StartedMetadataBlock = true;
- }
- WriteMDNode(N, VE, Stream, Record);
- }
+ const SmallVectorImpl<const LocalAsMetadata *> &MDs =
+ VE.getFunctionLocalMDs();
+ for (unsigned i = 0, e = MDs.size(); i != e; ++i) {
+ assert(MDs[i] && "Expected valid function-local metadata");
+ if (!StartedMetadataBlock) {
+ Stream.EnterSubblock(bitc::METADATA_BLOCK_ID, 3);
+ StartedMetadataBlock = true;
+ }
+ WriteLocalAsMetadata(MDs[i], VE, Stream, Record);
+ }
if (StartedMetadataBlock)
Stream.ExitBlock();
for (unsigned i = 0, e = MDs.size(); i != e; ++i) {
Record.push_back(MDs[i].first);
- Record.push_back(VE.getValueID(MDs[i].second));
+ Record.push_back(VE.getMetadataID(MDs[i].second));
}
Stream.EmitRecord(bitc::METADATA_ATTACHMENT, Record, 0);
Record.clear();
} else {
MDNode *Scope, *IA;
DL.getScopeAndInlinedAt(Scope, IA, I->getContext());
+ assert(Scope && "Expected valid scope");
Vals.push_back(DL.getLine());
Vals.push_back(DL.getCol());
- Vals.push_back(Scope ? VE.getValueID(Scope)+1 : 0);
- Vals.push_back(IA ? VE.getValueID(IA)+1 : 0);
+ Vals.push_back(Scope ? VE.getMetadataID(Scope) + 1 : 0);
+ Vals.push_back(IA ? VE.getMetadataID(IA) + 1 : 0);
Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_LOC, Vals);
Vals.clear();
if (I->hasPrologueData())
EnumerateValue(I->getPrologueData());
+ // Enumerate the metadata type.
+ //
+ // TODO: Move this to ValueEnumerator::EnumerateOperandType() once bitcode
+ // only encodes the metadata type when it's used as a value.
+ EnumerateType(Type::getMetadataTy(M.getContext()));
+
// Insert constants and metadata that are named at module level into the slot
// pool so that the module symbol table can refer to them...
EnumerateValueSymbolTable(M.getValueSymbolTable());
for (const BasicBlock &BB : F)
for (const Instruction &I : BB) {
for (const Use &Op : I.operands()) {
- if (MDNode *MD = dyn_cast<MDNode>(&Op))
- if (MD->isFunctionLocal() && MD->getFunction())
- // These will get enumerated during function-incorporation.
- continue;
- EnumerateOperandType(Op);
+ auto *MD = dyn_cast<MetadataAsValue>(&Op);
+ if (!MD) {
+ EnumerateOperandType(Op);
+ continue;
+ }
+
+ // Local metadata is enumerated during function-incorporation.
+ if (isa<LocalAsMetadata>(MD->getMetadata()))
+ continue;
+
+ EnumerateMetadata(MD->getMetadata());
}
EnumerateType(I.getType());
if (const CallInst *CI = dyn_cast<CallInst>(&I))
}
unsigned ValueEnumerator::getValueID(const Value *V) const {
- if (isa<MDNode>(V) || isa<MDString>(V)) {
- ValueMapType::const_iterator I = MDValueMap.find(V);
- assert(I != MDValueMap.end() && "Value not in slotcalculator!");
- return I->second-1;
- }
+ if (auto *MD = dyn_cast<MetadataAsValue>(V))
+ return getMetadataID(MD->getMetadata());
ValueMapType::const_iterator I = ValueMap.find(V);
assert(I != ValueMap.end() && "Value not in slotcalculator!");
return I->second-1;
}
+unsigned ValueEnumerator::getMetadataID(const Metadata *MD) const {
+ auto I = MDValueMap.find(MD);
+ assert(I != MDValueMap.end() && "Metadata not in slotcalculator!");
+ return I->second - 1;
+}
+
void ValueEnumerator::dump() const {
print(dbgs(), ValueMap, "Default");
dbgs() << '\n';
}
}
+void ValueEnumerator::print(raw_ostream &OS, const MetadataMapType &Map,
+ const char *Name) const {
+
+ OS << "Map Name: " << Name << "\n";
+ OS << "Size: " << Map.size() << "\n";
+ for (auto I = Map.begin(), E = Map.end(); I != E; ++I) {
+ const Metadata *MD = I->first;
+ OS << "Metadata: slot = " << I->second << "\n";
+ MD->dump();
+ }
+}
+
/// OptimizeConstants - Reorder constant pool for denser encoding.
void ValueEnumerator::OptimizeConstants(unsigned CstStart, unsigned CstEnd) {
if (CstStart == CstEnd || CstStart+1 == CstEnd) return;
/// and types referenced by the given MDNode.
void ValueEnumerator::EnumerateMDNodeOperands(const MDNode *N) {
for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
- if (Value *V = N->getOperand(i)) {
- if (isa<MDNode>(V) || isa<MDString>(V))
- EnumerateMetadata(V);
- else if (!isa<Instruction>(V) && !isa<Argument>(V))
- EnumerateValue(V);
- } else
+ Metadata *MD = N->getOperand(i);
+ if (!MD) {
EnumerateType(Type::getVoidTy(N->getContext()));
+ continue;
+ }
+ assert(!isa<LocalAsMetadata>(MD) && "MDNodes cannot be function-local");
+ if (auto *C = dyn_cast<ConstantAsMetadata>(MD)) {
+ EnumerateValue(C->getValue());
+ continue;
+ }
+ EnumerateMetadata(MD);
}
}
-void ValueEnumerator::EnumerateMetadata(const Value *MD) {
- assert((isa<MDNode>(MD) || isa<MDString>(MD)) && "Invalid metadata kind");
-
- // Skip function-local nodes themselves, but walk their operands.
- const MDNode *N = dyn_cast<MDNode>(MD);
- if (N && N->isFunctionLocal() && N->getFunction()) {
- EnumerateMDNodeOperands(N);
- return;
- }
+void ValueEnumerator::EnumerateMetadata(const Metadata *MD) {
+ assert(
+ (isa<MDNode>(MD) || isa<MDString>(MD) || isa<ConstantAsMetadata>(MD)) &&
+ "Invalid metadata kind");
// Insert a dummy ID to block the co-recursive call to
// EnumerateMDNodeOperands() from re-visiting MD in a cyclic graph.
if (!MDValueMap.insert(std::make_pair(MD, 0)).second)
return;
- // Enumerate the type of this value.
- EnumerateType(MD->getType());
-
// Visit operands first to minimize RAUW.
- if (N)
+ if (auto *N = dyn_cast<MDNode>(MD))
EnumerateMDNodeOperands(N);
+ else if (auto *C = dyn_cast<ConstantAsMetadata>(MD))
+ EnumerateValue(C->getValue());
// Replace the dummy ID inserted above with the correct one. MDValueMap may
// have changed by inserting operands, so we need a fresh lookup here.
- MDValues.push_back(MD);
- MDValueMap[MD] = MDValues.size();
+ MDs.push_back(MD);
+ MDValueMap[MD] = MDs.size();
}
/// EnumerateFunctionLocalMetadataa - Incorporate function-local metadata
-/// information reachable from the given MDNode.
-void ValueEnumerator::EnumerateFunctionLocalMetadata(const MDNode *N) {
- assert(N->isFunctionLocal() && N->getFunction() &&
- "EnumerateFunctionLocalMetadata called on non-function-local mdnode!");
-
- // Enumerate the type of this value.
- EnumerateType(N->getType());
-
+/// information reachable from the metadata.
+void ValueEnumerator::EnumerateFunctionLocalMetadata(
+ const LocalAsMetadata *Local) {
// Check to see if it's already in!
- unsigned &MDValueID = MDValueMap[N];
+ unsigned &MDValueID = MDValueMap[Local];
if (MDValueID)
return;
- MDValues.push_back(N);
- MDValueID = MDValues.size();
-
- // To incoroporate function-local information visit all function-local
- // MDNodes and all function-local values they reference.
- for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i)
- if (Value *V = N->getOperand(i)) {
- if (MDNode *O = dyn_cast<MDNode>(V)) {
- if (O->isFunctionLocal() && O->getFunction())
- EnumerateFunctionLocalMetadata(O);
- } else if (isa<Instruction>(V) || isa<Argument>(V))
- EnumerateValue(V);
- }
+ MDs.push_back(Local);
+ MDValueID = MDs.size();
+
+ EnumerateValue(Local->getValue());
- // Also, collect all function-local MDNodes for easy access.
- FunctionLocalMDs.push_back(N);
+ // Also, collect all function-local metadata for easy access.
+ FunctionLocalMDs.push_back(Local);
}
void ValueEnumerator::EnumerateValue(const Value *V) {
assert(!V->getType()->isVoidTy() && "Can't insert void values!");
- assert(!isa<MDNode>(V) && !isa<MDString>(V) &&
- "EnumerateValue doesn't handle Metadata!");
+ assert(!isa<MetadataAsValue>(V) && "EnumerateValue doesn't handle Metadata!");
// Check to see if it's already in!
unsigned &ValueID = ValueMap[V];
void ValueEnumerator::EnumerateOperandType(const Value *V) {
EnumerateType(V->getType());
- if (const Constant *C = dyn_cast<Constant>(V)) {
- // If this constant is already enumerated, ignore it, we know its type must
- // be enumerated.
- if (ValueMap.count(V)) return;
+ if (auto *MD = dyn_cast<MetadataAsValue>(V)) {
+ assert(!isa<LocalAsMetadata>(MD->getMetadata()) &&
+ "Function-local metadata should be left for later");
- // This constant may have operands, make sure to enumerate the types in
- // them.
- for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i) {
- const Value *Op = C->getOperand(i);
+ EnumerateMetadata(MD->getMetadata());
+ return;
+ }
- // Don't enumerate basic blocks here, this happens as operands to
- // blockaddress.
- if (isa<BasicBlock>(Op)) continue;
+ const Constant *C = dyn_cast<Constant>(V);
+ if (!C)
+ return;
- EnumerateOperandType(Op);
- }
+ // If this constant is already enumerated, ignore it, we know its type must
+ // be enumerated.
+ if (ValueMap.count(C))
+ return;
- if (const MDNode *N = dyn_cast<MDNode>(V)) {
- for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i)
- if (Value *Elem = N->getOperand(i))
- EnumerateOperandType(Elem);
- }
- } else if (isa<MDString>(V) || isa<MDNode>(V))
- EnumerateMetadata(V);
+ // This constant may have operands, make sure to enumerate the types in
+ // them.
+ for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i) {
+ const Value *Op = C->getOperand(i);
+
+ // Don't enumerate basic blocks here, this happens as operands to
+ // blockaddress.
+ if (isa<BasicBlock>(Op))
+ continue;
+
+ EnumerateOperandType(Op);
+ }
}
void ValueEnumerator::EnumerateAttributes(AttributeSet PAL) {
void ValueEnumerator::incorporateFunction(const Function &F) {
InstructionCount = 0;
NumModuleValues = Values.size();
- NumModuleMDValues = MDValues.size();
+ NumModuleMDs = MDs.size();
// Adding function arguments to the value table.
for (Function::const_arg_iterator I = F.arg_begin(), E = F.arg_end();
FirstInstID = Values.size();
- SmallVector<MDNode *, 8> FnLocalMDVector;
+ SmallVector<LocalAsMetadata *, 8> FnLocalMDVector;
// Add all of the instructions.
for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB) {
for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E; ++I) {
for (User::const_op_iterator OI = I->op_begin(), E = I->op_end();
OI != E; ++OI) {
- if (MDNode *MD = dyn_cast<MDNode>(*OI))
- if (MD->isFunctionLocal() && MD->getFunction())
+ if (auto *MD = dyn_cast<MetadataAsValue>(&*OI))
+ if (auto *Local = dyn_cast<LocalAsMetadata>(MD->getMetadata()))
// Enumerate metadata after the instructions they might refer to.
- FnLocalMDVector.push_back(MD);
- }
-
- SmallVector<std::pair<unsigned, MDNode *>, 8> MDs;
- I->getAllMetadataOtherThanDebugLoc(MDs);
- for (unsigned i = 0, e = MDs.size(); i != e; ++i) {
- MDNode *N = MDs[i].second;
- if (N->isFunctionLocal() && N->getFunction())
- FnLocalMDVector.push_back(N);
+ FnLocalMDVector.push_back(Local);
}
if (!I->getType()->isVoidTy())
/// Remove purged values from the ValueMap.
for (unsigned i = NumModuleValues, e = Values.size(); i != e; ++i)
ValueMap.erase(Values[i].first);
- for (unsigned i = NumModuleMDValues, e = MDValues.size(); i != e; ++i)
- MDValueMap.erase(MDValues[i]);
+ for (unsigned i = NumModuleMDs, e = MDs.size(); i != e; ++i)
+ MDValueMap.erase(MDs[i]);
for (unsigned i = 0, e = BasicBlocks.size(); i != e; ++i)
ValueMap.erase(BasicBlocks[i]);
Values.resize(NumModuleValues);
- MDValues.resize(NumModuleMDValues);
+ MDs.resize(NumModuleMDs);
BasicBlocks.clear();
FunctionLocalMDs.clear();
}
class Comdat;
class Function;
class Module;
+class Metadata;
+class LocalAsMetadata;
class MDNode;
class NamedMDNode;
class AttributeSet;
typedef UniqueVector<const Comdat *> ComdatSetType;
ComdatSetType Comdats;
- std::vector<const Value *> MDValues;
- SmallVector<const MDNode *, 8> FunctionLocalMDs;
- ValueMapType MDValueMap;
+ std::vector<const Metadata *> MDs;
+ SmallVector<const LocalAsMetadata *, 8> FunctionLocalMDs;
+ typedef DenseMap<const Metadata *, unsigned> MetadataMapType;
+ MetadataMapType MDValueMap;
typedef DenseMap<AttributeSet, unsigned> AttributeGroupMapType;
AttributeGroupMapType AttributeGroupMap;
/// When a function is incorporated, this is the size of the MDValues list
/// before incorporation.
- unsigned NumModuleMDValues;
+ unsigned NumModuleMDs;
unsigned FirstFuncConstantID;
unsigned FirstInstID;
void dump() const;
void print(raw_ostream &OS, const ValueMapType &Map, const char *Name) const;
+ void print(raw_ostream &OS, const MetadataMapType &Map,
+ const char *Name) const;
unsigned getValueID(const Value *V) const;
+ unsigned getMetadataID(const Metadata *V) const;
unsigned getTypeID(Type *T) const {
TypeMapType::const_iterator I = TypeMap.find(T);
}
const ValueList &getValues() const { return Values; }
- const std::vector<const Value *> &getMDValues() const { return MDValues; }
- const SmallVectorImpl<const MDNode *> &getFunctionLocalMDValues() const {
+ const std::vector<const Metadata *> &getMDs() const { return MDs; }
+ const SmallVectorImpl<const LocalAsMetadata *> &getFunctionLocalMDs() const {
return FunctionLocalMDs;
}
const TypeList &getTypes() const { return Types; }
void OptimizeConstants(unsigned CstStart, unsigned CstEnd);
void EnumerateMDNodeOperands(const MDNode *N);
- void EnumerateMetadata(const Value *MD);
- void EnumerateFunctionLocalMetadata(const MDNode *N);
+ void EnumerateMetadata(const Metadata *MD);
+ void EnumerateFunctionLocalMetadata(const LocalAsMetadata *Local);
void EnumerateNamedMDNode(const NamedMDNode *NMD);
void EnumerateValue(const Value *V);
void EnumerateType(Type *T);
if (LocInfo->getNumOperands() != 0)
if (const ConstantInt *CI =
- dyn_cast<ConstantInt>(LocInfo->getOperand(ErrorLine)))
+ mdconst::dyn_extract<ConstantInt>(LocInfo->getOperand(ErrorLine)))
LocCookie = CI->getZExtValue();
}
if (MI->getOperand(i-1).isMetadata() &&
(LocMD = MI->getOperand(i-1).getMetadata()) &&
LocMD->getNumOperands() != 0) {
- if (const ConstantInt *CI = dyn_cast<ConstantInt>(LocMD->getOperand(0))) {
+ if (const ConstantInt *CI =
+ mdconst::dyn_extract<ConstantInt>(LocMD->getOperand(0))) {
LocCookie = CI->getZExtValue();
break;
}
addType(ParamDIE, resolve(VP.getType()));
if (!VP.getName().empty())
addString(ParamDIE, dwarf::DW_AT_name, VP.getName());
- if (Value *Val = VP.getValue()) {
- if (ConstantInt *CI = dyn_cast<ConstantInt>(Val))
+ if (Metadata *Val = VP.getValue()) {
+ if (ConstantInt *CI = mdconst::dyn_extract<ConstantInt>(Val))
addConstantValue(ParamDIE, CI, resolve(VP.getType()));
- else if (GlobalValue *GV = dyn_cast<GlobalValue>(Val)) {
+ else if (GlobalValue *GV = mdconst::dyn_extract<GlobalValue>(Val)) {
// For declaration non-type template parameters (such as global values and
// functions)
DIELoc *Loc = new (DIEValueAllocator) DIELoc();
if (!ProfileData || ProfileData->getNumOperands() != 3)
return false;
- const auto *CITrue = dyn_cast<ConstantInt>(ProfileData->getOperand(1));
- const auto *CIFalse = dyn_cast<ConstantInt>(ProfileData->getOperand(2));
+ const auto *CITrue =
+ mdconst::dyn_extract<ConstantInt>(ProfileData->getOperand(1));
+ const auto *CIFalse =
+ mdconst::dyn_extract<ConstantInt>(ProfileData->getOperand(2));
if (!CITrue || !CIFalse)
return false;
break;
case MachineOperand::MO_Metadata:
OS << '<';
- getMetadata()->printAsOperand(OS, /*PrintType=*/false);
+ getMetadata()->printAsOperand(OS);
OS << '>';
break;
case MachineOperand::MO_MCSymbol:
if (const MDNode *TBAAInfo = MMO.getAAInfo().TBAA) {
OS << "(tbaa=";
if (TBAAInfo->getNumOperands() > 0)
- TBAAInfo->getOperand(0)->printAsOperand(OS, /*PrintType=*/false);
+ TBAAInfo->getOperand(0)->printAsOperand(OS);
else
OS << "<unknown>";
OS << ")";
OS << "(alias.scope=";
if (ScopeInfo->getNumOperands() > 0)
for (unsigned i = 0, ie = ScopeInfo->getNumOperands(); i != ie; ++i) {
- ScopeInfo->getOperand(i)->printAsOperand(OS, /*PrintType=*/false);
+ ScopeInfo->getOperand(i)->printAsOperand(OS);
if (i != ie-1)
OS << ",";
}
OS << "(noalias=";
if (NoAliasInfo->getNumOperands() > 0)
for (unsigned i = 0, ie = NoAliasInfo->getNumOperands(); i != ie; ++i) {
- NoAliasInfo->getOperand(i)->printAsOperand(OS, /*PrintType=*/false);
+ NoAliasInfo->getOperand(i)->printAsOperand(OS);
if (i != ie-1)
OS << ",";
}
: MCID(&tid), Parent(nullptr), Operands(nullptr), NumOperands(0),
Flags(0), AsmPrinterFlags(0),
NumMemRefs(0), MemRefs(nullptr), debugLoc(dl) {
+ assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor");
+
// Reserve space for the expected number of operands.
if (unsigned NumOps = MCID->getNumOperands() +
MCID->getNumImplicitDefs() + MCID->getNumImplicitUses()) {
Flags(0), AsmPrinterFlags(0),
NumMemRefs(MI.NumMemRefs), MemRefs(MI.MemRefs),
debugLoc(MI.getDebugLoc()) {
+ assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor");
+
CapOperands = OperandCapacity::get(MI.getNumOperands());
Operands = MF.allocateOperandArray(CapOperands);
if (getOperand(i-1).isMetadata() &&
(LocMD = getOperand(i-1).getMetadata()) &&
LocMD->getNumOperands() != 0) {
- if (const ConstantInt *CI = dyn_cast<ConstantInt>(LocMD->getOperand(0))) {
+ if (const ConstantInt *CI =
+ mdconst::dyn_extract<ConstantInt>(LocMD->getOperand(0))) {
LocCookie = CI->getZExtValue();
break;
}
return nullptr;
case Intrinsic::read_register: {
Value *Reg = I.getArgOperand(0);
- SDValue RegName = DAG.getMDNode(cast<MDNode>(Reg));
+ SDValue RegName =
+ DAG.getMDNode(cast<MDNode>(cast<MetadataAsValue>(Reg)->getMetadata()));
EVT VT = TLI.getValueType(I.getType());
setValue(&I, DAG.getNode(ISD::READ_REGISTER, sdl, VT, RegName));
return nullptr;
Value *Reg = I.getArgOperand(0);
Value *RegValue = I.getArgOperand(1);
SDValue Chain = getValue(RegValue).getOperand(0);
- SDValue RegName = DAG.getMDNode(cast<MDNode>(Reg));
+ SDValue RegName =
+ DAG.getMDNode(cast<MDNode>(cast<MetadataAsValue>(Reg)->getMetadata()));
DAG.setRoot(DAG.getNode(ISD::WRITE_REGISTER, sdl, MVT::Other, Chain,
RegName, getValue(RegValue)));
return nullptr;
if (!VI.Var)
continue;
if (SlotRemap.count(VI.Slot)) {
- DEBUG(dbgs()<<"Remapping debug info for ["<<VI.Var->getName()<<"].\n");
+ DEBUG(dbgs() << "Remapping debug info for ["
+ << DIVariable(VI.Var).getName() << "].\n");
VI.Slot = SlotRemap[VI.Slot];
FixedDbg++;
}
continue;
StringRef Key = MFE.Key->getString();
- Value *Val = MFE.Val;
+ Metadata *Val = MFE.Val;
if (Key == "Objective-C Image Info Version") {
- VersionVal = cast<ConstantInt>(Val)->getZExtValue();
+ VersionVal = mdconst::extract<ConstantInt>(Val)->getZExtValue();
} else if (Key == "Objective-C Garbage Collection" ||
Key == "Objective-C GC Only" ||
Key == "Objective-C Is Simulated" ||
Key == "Objective-C Image Swift Version") {
- ImageInfoFlags |= cast<ConstantInt>(Val)->getZExtValue();
+ ImageInfoFlags |= mdconst::extract<ConstantInt>(Val)->getZExtValue();
} else if (Key == "Objective-C Image Info Section") {
SectionVal = cast<MDString>(Val)->getString();
} else if (Key == "Linker Options") {
i = ModuleFlags.begin(), e = ModuleFlags.end(); i != e; ++i) {
const Module::ModuleFlagEntry &MFE = *i;
StringRef Key = MFE.Key->getString();
- Value *Val = MFE.Val;
+ Metadata *Val = MFE.Val;
if (Key == "Linker Options") {
LinkerOptions = cast<MDNode>(Val);
break;
if (const Function *Func = dyn_cast<Function>(V))
return new SlotTracker(Func);
- if (const MDNode *MD = dyn_cast<MDNode>(V)) {
- if (!MD->isFunctionLocal())
- return new SlotTracker(MD->getFunction());
-
- return new SlotTracker((Function *)nullptr);
- }
-
return nullptr;
}
// Module level constructor. Causes the contents of the Module (sans functions)
// to be added to the slot table.
SlotTracker::SlotTracker(const Module *M)
- : TheModule(M), TheFunction(nullptr), FunctionProcessed(false),
- mNext(0), fNext(0), mdnNext(0), asNext(0) {
-}
+ : TheModule(M), TheFunction(nullptr), FunctionProcessed(false), mNext(0),
+ fNext(0), mdnNext(0), asNext(0) {}
// Function level constructor. Causes the contents of the Module and the one
// function provided to be added to the slot table.
SlotTracker::SlotTracker(const Function *F)
- : TheModule(F ? F->getParent() : nullptr), TheFunction(F),
- FunctionProcessed(false), mNext(0), fNext(0), mdnNext(0), asNext(0) {
-}
+ : TheModule(F ? F->getParent() : nullptr), TheFunction(F),
+ FunctionProcessed(false), mNext(0), fNext(0), mdnNext(0), asNext(0) {}
inline void SlotTracker::initialize() {
if (TheModule) {
if (Function *F = CI->getCalledFunction())
if (F->isIntrinsic())
for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i)
- if (MDNode *N = dyn_cast_or_null<MDNode>(I->getOperand(i)))
- CreateMetadataSlot(N);
+ if (auto *V = dyn_cast_or_null<MetadataAsValue>(I->getOperand(i)))
+ if (MDNode *N = dyn_cast<MDNode>(V->getMetadata()))
+ CreateMetadataSlot(N);
// Add all the call attributes to the table.
AttributeSet Attrs = CI->getAttributes().getFnAttributes();
void SlotTracker::CreateMetadataSlot(const MDNode *N) {
assert(N && "Can't insert a null Value into SlotTracker!");
- // Don't insert if N is a function-local metadata, these are always printed
- // inline.
- if (!N->isFunctionLocal()) {
- mdn_iterator I = mdnMap.find(N);
- if (I != mdnMap.end())
- return;
-
- unsigned DestSlot = mdnNext++;
- mdnMap[N] = DestSlot;
- }
+ unsigned DestSlot = mdnNext;
+ if (!mdnMap.insert(std::make_pair(N, DestSlot)).second)
+ return;
+ ++mdnNext;
// Recursively add any MDNodes referenced by operands.
for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i)
SlotTracker *Machine,
const Module *Context);
+static void WriteAsOperandInternal(raw_ostream &Out, const Metadata *MD,
+ TypePrinting *TypePrinter,
+ SlotTracker *Machine, const Module *Context,
+ bool FromValue = false);
+
static const char *getPredicateText(unsigned predicate) {
const char * pred = "unknown";
switch (predicate) {
const Module *Context) {
Out << "!{";
for (unsigned mi = 0, me = Node->getNumOperands(); mi != me; ++mi) {
- const Value *V = Node->getOperand(mi);
- if (!V)
+ const Metadata *MD = Node->getOperand(mi);
+ if (!MD)
Out << "null";
- else {
+ else if (auto *MDV = dyn_cast<ValueAsMetadata>(MD)) {
+ Value *V = MDV->getValue();
TypePrinter->print(V->getType(), Out);
Out << ' ';
- WriteAsOperandInternal(Out, Node->getOperand(mi),
- TypePrinter, Machine, Context);
+ WriteAsOperandInternal(Out, V, TypePrinter, Machine, Context);
+ } else {
+ Out << "metadata ";
+ WriteAsOperandInternal(Out, MD, TypePrinter, Machine, Context);
}
if (mi + 1 != me)
Out << ", ";
return;
}
- if (const MDNode *N = dyn_cast<MDNode>(V)) {
- if (N->isFunctionLocal()) {
- // Print metadata inline, not via slot reference number.
- WriteMDNodeBodyInternal(Out, N, TypePrinter, Machine, Context);
- return;
- }
-
- if (!Machine) {
- if (N->isFunctionLocal())
- Machine = new SlotTracker(N->getFunction());
- else
- Machine = new SlotTracker(Context);
- }
- int Slot = Machine->getMetadataSlot(N);
- if (Slot == -1)
- Out << "<badref>";
- else
- Out << '!' << Slot;
- return;
- }
-
- if (const MDString *MDS = dyn_cast<MDString>(V)) {
- Out << "!\"";
- PrintEscapedString(MDS->getString(), Out);
- Out << '"';
+ if (auto *MD = dyn_cast<MetadataAsValue>(V)) {
+ WriteAsOperandInternal(Out, MD->getMetadata(), TypePrinter, Machine,
+ Context, /* FromValue */ true);
return;
}
Out << "<badref>";
}
+static void WriteAsOperandInternal(raw_ostream &Out, const Metadata *MD,
+ TypePrinting *TypePrinter,
+ SlotTracker *Machine, const Module *Context,
+ bool FromValue) {
+ if (const MDNode *N = dyn_cast<MDNode>(MD)) {
+ if (!Machine)
+ Machine = new SlotTracker(Context);
+ int Slot = Machine->getMetadataSlot(N);
+ if (Slot == -1)
+ Out << "<badref>";
+ else
+ Out << '!' << Slot;
+ return;
+ }
+
+ if (const MDString *MDS = dyn_cast<MDString>(MD)) {
+ Out << "!\"";
+ PrintEscapedString(MDS->getString(), Out);
+ Out << '"';
+ return;
+ }
+
+ auto *V = cast<ValueAsMetadata>(MD);
+ assert(TypePrinter && "TypePrinter required for metadata values");
+ assert((FromValue || !isa<LocalAsMetadata>(V)) &&
+ "Unexpected function-local metadata outside of value argument");
+
+ if (FromValue)
+ Out << "!{";
+ TypePrinter->print(V->getValue()->getType(), Out);
+ Out << ' ';
+ WriteAsOperandInternal(Out, V->getValue(), TypePrinter, Machine, Context);
+ if (FromValue)
+ Out << "}";
+}
+
void AssemblyWriter::init() {
if (!TheModule)
return;
if (Node->getNumOperands() < 1)
return;
- Value *Op = Node->getOperand(0);
+ Metadata *Op = Node->getOperand(0);
if (!Op || !isa<MDString>(Op))
return;
W.printFunction(F);
else
W.printAlias(cast<GlobalAlias>(GV));
- } else if (const MDNode *N = dyn_cast<MDNode>(this)) {
- const Function *F = N->getFunction();
- SlotTracker SlotTable(F);
- AssemblyWriter W(OS, SlotTable, F ? F->getParent() : nullptr, nullptr);
- W.printMDNodeBody(N);
+ } else if (const MetadataAsValue *V = dyn_cast<MetadataAsValue>(this)) {
+ V->getMetadata()->print(ROS);
} else if (const Constant *C = dyn_cast<Constant>(this)) {
TypePrinting TypePrinter;
TypePrinter.print(C->getType(), OS);
OS << ' ';
WriteConstantInternal(OS, C, TypePrinter, nullptr, nullptr);
- } else if (isa<InlineAsm>(this) || isa<MDString>(this) ||
- isa<Argument>(this)) {
+ } else if (isa<InlineAsm>(this) || isa<Argument>(this)) {
this->printAsOperand(OS);
} else {
llvm_unreachable("Unknown value to print out!");
void Value::printAsOperand(raw_ostream &O, bool PrintType, const Module *M) const {
// Fast path: Don't construct and populate a TypePrinting object if we
// won't be needing any types printed.
- if (!PrintType &&
- ((!isa<Constant>(this) && !isa<MDNode>(this)) ||
- hasName() || isa<GlobalValue>(this))) {
+ if (!PrintType && ((!isa<Constant>(this) && !isa<MetadataAsValue>(this)) ||
+ hasName() || isa<GlobalValue>(this))) {
WriteAsOperandInternal(O, this, nullptr, nullptr, M);
return;
}
WriteAsOperandInternal(O, this, &TypePrinter, nullptr, M);
}
+void Metadata::print(raw_ostream &ROS) const {
+ formatted_raw_ostream OS(ROS);
+ if (auto *N = dyn_cast<MDNode>(this)) {
+ OS << "metadata ";
+ SlotTracker SlotTable(static_cast<Function *>(nullptr));
+ AssemblyWriter W(OS, SlotTable, nullptr, nullptr);
+ W.printMDNodeBody(N);
+
+ return;
+ }
+ printAsOperand(OS);
+}
+
+void Metadata::printAsOperand(raw_ostream &ROS, bool PrintType,
+ const Module *M) const {
+ formatted_raw_ostream OS(ROS);
+ if (PrintType)
+ OS << "metadata ";
+
+ std::unique_ptr<TypePrinting> TypePrinter;
+ if (PrintType) {
+ TypePrinter.reset(new TypePrinting);
+ if (M)
+ TypePrinter->incorporateTypes(*M);
+ }
+ WriteAsOperandInternal(OS, this, TypePrinter.get(), nullptr, M,
+ /* FromValue */ true);
+}
+
// Value::dump - allow easy printing of Values from the debugger.
void Value::dump() const { print(dbgs()); dbgs() << '\n'; }
// NamedMDNode::dump() - Allow printing of NamedMDNodes from the debugger.
void NamedMDNode::dump() const { print(dbgs()); }
+
+void Metadata::dump() const {
+ print(dbgs());
+ dbgs() << '\n';
+}
return dyn_cast_or_null<MDNode>(DbgNode->getOperand(Elt));
}
-static DIExpression getExpression(Value *VarOperand, Function *F) {
+static MetadataAsValue *getExpression(Value *VarOperand, Function *F) {
// Old-style DIVariables have an optional expression as the 8th element.
- DIExpression Expr(getNodeField(cast<MDNode>(VarOperand), 8));
+ DIExpression Expr(getNodeField(
+ cast<MDNode>(cast<MetadataAsValue>(VarOperand)->getMetadata()), 8));
if (!Expr) {
- DIBuilder DIB(*F->getParent());
+ DIBuilder DIB(*F->getParent(), /*AllowUnresolved*/ false);
Expr = DIB.createExpression();
}
- return Expr;
+ return MetadataAsValue::get(F->getContext(), Expr);
}
// UpgradeIntrinsicCall - Upgrade a call to an old intrinsic to be a call the
Builder.SetInsertPoint(CI->getParent(), CI);
Module *M = F->getParent();
- SmallVector<Value *, 1> Elts;
- Elts.push_back(ConstantInt::get(Type::getInt32Ty(C), 1));
+ SmallVector<Metadata *, 1> Elts;
+ Elts.push_back(
+ ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(C), 1)));
MDNode *Node = MDNode::get(C, Elts);
Value *Arg0 = CI->getArgOperand(0);
return;
if (MD->getNumOperands() == 3) {
- Value *Elts[] = {
- MD->getOperand(0),
- MD->getOperand(1)
- };
+ Metadata *Elts[] = {MD->getOperand(0), MD->getOperand(1)};
MDNode *ScalarType = MDNode::get(I->getContext(), Elts);
// Create a MDNode <ScalarType, ScalarType, offset 0, const>
- Value *Elts2[] = {
- ScalarType, ScalarType,
- Constant::getNullValue(Type::getInt64Ty(I->getContext())),
- MD->getOperand(2)
- };
+ Metadata *Elts2[] = {ScalarType, ScalarType,
+ ConstantAsMetadata::get(Constant::getNullValue(
+ Type::getInt64Ty(I->getContext()))),
+ MD->getOperand(2)};
I->setMetadata(LLVMContext::MD_tbaa, MDNode::get(I->getContext(), Elts2));
} else {
// Create a MDNode <MD, MD, offset 0>
- Value *Elts[] = {MD, MD,
- Constant::getNullValue(Type::getInt64Ty(I->getContext()))};
+ Metadata *Elts[] = {MD, MD, ConstantAsMetadata::get(Constant::getNullValue(
+ Type::getInt64Ty(I->getContext())))};
I->setMetadata(LLVMContext::MD_tbaa, MDNode::get(I->getContext(), Elts));
}
}
MDBuilder.cpp
Mangler.cpp
Metadata.cpp
+ MetadataTracking.cpp
Module.cpp
Pass.cpp
PassManager.cpp
}
LLVMValueRef LLVMGetMetadata(LLVMValueRef Inst, unsigned KindID) {
- return wrap(unwrap<Instruction>(Inst)->getMetadata(KindID));
+ auto *I = unwrap<Instruction>(Inst);
+ assert(I && "Expected instruction");
+ if (auto *MD = I->getMetadata(KindID))
+ return wrap(MetadataAsValue::get(I->getContext(), MD));
+ return nullptr;
}
void LLVMSetMetadata(LLVMValueRef Inst, unsigned KindID, LLVMValueRef MD) {
- unwrap<Instruction>(Inst)
- ->setMetadata(KindID, MD ? unwrap<MDNode>(MD) : nullptr);
+ MDNode *N =
+ MD ? cast<MDNode>(unwrap<MetadataAsValue>(MD)->getMetadata()) : nullptr;
+ unwrap<Instruction>(Inst)->setMetadata(KindID, N);
}
/*--.. Conversion functions ................................................--*/
LLVM_FOR_EACH_VALUE_SUBCLASS(LLVM_DEFINE_VALUE_CAST)
+LLVMValueRef LLVMIsAMDNode(LLVMValueRef Val) {
+ if (auto *MD = dyn_cast_or_null<MetadataAsValue>(unwrap(Val)))
+ if (isa<MDNode>(MD->getMetadata()) ||
+ isa<ValueAsMetadata>(MD->getMetadata()))
+ return Val;
+ return nullptr;
+}
+
+LLVMValueRef LLVMIsAMDString(LLVMValueRef Val) {
+ if (auto *MD = dyn_cast_or_null<MetadataAsValue>(unwrap(Val)))
+ if (isa<MDString>(MD->getMetadata()))
+ return Val;
+ return nullptr;
+}
+
/*--.. Operations on Uses ..................................................--*/
LLVMUseRef LLVMGetFirstUse(LLVMValueRef Val) {
Value *V = unwrap(Val);
}
/*--.. Operations on Users .................................................--*/
+
+static LLVMValueRef getMDNodeOperandImpl(LLVMContext &Context, const MDNode *N,
+ unsigned Index) {
+ Metadata *Op = N->getOperand(Index);
+ if (!Op)
+ return nullptr;
+ if (auto *C = dyn_cast<ConstantAsMetadata>(Op))
+ return wrap(C->getValue());
+ return wrap(MetadataAsValue::get(Context, Op));
+}
+
LLVMValueRef LLVMGetOperand(LLVMValueRef Val, unsigned Index) {
Value *V = unwrap(Val);
- if (MDNode *MD = dyn_cast<MDNode>(V))
- return wrap(MD->getOperand(Index));
+ if (auto *MD = dyn_cast<MetadataAsValue>(V)) {
+ if (auto *L = dyn_cast<ValueAsMetadata>(MD->getMetadata())) {
+ assert(Index == 0 && "Function-local metadata can only have one operand");
+ return wrap(L->getValue());
+ }
+ return getMDNodeOperandImpl(V->getContext(),
+ cast<MDNode>(MD->getMetadata()), Index);
+ }
+
return wrap(cast<User>(V)->getOperand(Index));
}
int LLVMGetNumOperands(LLVMValueRef Val) {
Value *V = unwrap(Val);
- if (MDNode *MD = dyn_cast<MDNode>(V))
- return MD->getNumOperands();
+ if (isa<MetadataAsValue>(V))
+ return LLVMGetMDNodeNumOperands(Val);
+
return cast<User>(V)->getNumOperands();
}
LLVMValueRef LLVMMDStringInContext(LLVMContextRef C, const char *Str,
unsigned SLen) {
- return wrap(MDString::get(*unwrap(C), StringRef(Str, SLen)));
+ LLVMContext &Context = *unwrap(C);
+ return wrap(MetadataAsValue::get(
+ Context, MDString::get(Context, StringRef(Str, SLen))));
}
LLVMValueRef LLVMMDString(const char *Str, unsigned SLen) {
LLVMValueRef LLVMMDNodeInContext(LLVMContextRef C, LLVMValueRef *Vals,
unsigned Count) {
- return wrap(MDNode::get(*unwrap(C),
- makeArrayRef(unwrap<Value>(Vals, Count), Count)));
+ LLVMContext &Context = *unwrap(C);
+ SmallVector<Metadata *, 8> MDs;
+ for (auto *OV : makeArrayRef(Vals, Count)) {
+ Value *V = unwrap(OV);
+ Metadata *MD;
+ if (!V)
+ MD = nullptr;
+ else if (auto *C = dyn_cast<Constant>(V))
+ MD = ConstantAsMetadata::get(C);
+ else if (auto *MDV = dyn_cast<MetadataAsValue>(V)) {
+ MD = MDV->getMetadata();
+ assert(!isa<LocalAsMetadata>(MD) && "Unexpected function-local metadata "
+ "outside of direct argument to call");
+ } else {
+ // This is function-local metadata. Pretend to make an MDNode.
+ assert(Count == 1 &&
+ "Expected only one operand to function-local metadata");
+ return wrap(MetadataAsValue::get(Context, LocalAsMetadata::get(V)));
+ }
+
+ MDs.push_back(MD);
+ }
+ return wrap(MetadataAsValue::get(Context, MDNode::get(Context, MDs)));
}
LLVMValueRef LLVMMDNode(LLVMValueRef *Vals, unsigned Count) {
}
const char *LLVMGetMDString(LLVMValueRef V, unsigned* Len) {
- if (const MDString *S = dyn_cast<MDString>(unwrap(V))) {
- *Len = S->getString().size();
- return S->getString().data();
- }
+ if (const auto *MD = dyn_cast<MetadataAsValue>(unwrap(V)))
+ if (const MDString *S = dyn_cast<MDString>(MD->getMetadata())) {
+ *Len = S->getString().size();
+ return S->getString().data();
+ }
*Len = 0;
return nullptr;
}
unsigned LLVMGetMDNodeNumOperands(LLVMValueRef V)
{
- return cast<MDNode>(unwrap(V))->getNumOperands();
+ auto *MD = cast<MetadataAsValue>(unwrap(V));
+ if (isa<ValueAsMetadata>(MD->getMetadata()))
+ return 1;
+ return cast<MDNode>(MD->getMetadata())->getNumOperands();
}
void LLVMGetMDNodeOperands(LLVMValueRef V, LLVMValueRef *Dest)
{
- const MDNode *N = cast<MDNode>(unwrap(V));
+ auto *MD = cast<MetadataAsValue>(unwrap(V));
+ if (auto *MDV = dyn_cast<ValueAsMetadata>(MD->getMetadata())) {
+ *Dest = wrap(MDV->getValue());
+ return;
+ }
+ const auto *N = cast<MDNode>(MD->getMetadata());
const unsigned numOperands = N->getNumOperands();
+ LLVMContext &Context = unwrap(V)->getContext();
for (unsigned i = 0; i < numOperands; i++)
- Dest[i] = wrap(N->getOperand(i));
+ Dest[i] = getMDNodeOperandImpl(Context, N, i);
}
unsigned LLVMGetNamedMetadataNumOperands(LLVMModuleRef M, const char* name)
NamedMDNode *N = unwrap(M)->getNamedMetadata(name);
if (!N)
return;
+ LLVMContext &Context = unwrap(M)->getContext();
for (unsigned i=0;i<N->getNumOperands();i++)
- Dest[i] = wrap(N->getOperand(i));
+ Dest[i] = wrap(MetadataAsValue::get(Context, N->getOperand(i)));
}
void LLVMAddNamedMetadataOperand(LLVMModuleRef M, const char* name,
NamedMDNode *N = unwrap(M)->getOrInsertNamedMetadata(name);
if (!N)
return;
- MDNode *Op = Val ? unwrap<MDNode>(Val) : nullptr;
- if (Op)
- N->addOperand(Op);
+ if (!Val)
+ return;
+ N->addOperand(cast<MDNode>(unwrap<MetadataAsValue>(Val)->getMetadata()));
}
/*--.. Operations on scalar constants ......................................--*/
/*--.. Metadata builders ...................................................--*/
void LLVMSetCurrentDebugLocation(LLVMBuilderRef Builder, LLVMValueRef L) {
- MDNode *Loc = L ? unwrap<MDNode>(L) : nullptr;
+ MDNode *Loc =
+ L ? cast<MDNode>(unwrap<MetadataAsValue>(L)->getMetadata()) : nullptr;
unwrap(Builder)->SetCurrentDebugLocation(DebugLoc::getFromDILocation(Loc));
}
LLVMValueRef LLVMGetCurrentDebugLocation(LLVMBuilderRef Builder) {
- return wrap(unwrap(Builder)->getCurrentDebugLocation()
- .getAsMDNode(unwrap(Builder)->getContext()));
+ LLVMContext &Context = unwrap(Builder)->getContext();
+ return wrap(MetadataAsValue::get(
+ Context,
+ unwrap(Builder)->getCurrentDebugLocation().getAsMDNode(Context)));
}
void LLVMSetInstDebugLocation(LLVMBuilderRef Builder, LLVMValueRef Inst) {
};
}
-DIBuilder::DIBuilder(Module &m)
+DIBuilder::DIBuilder(Module &m, bool AllowUnresolvedNodes)
: M(m), VMContext(M.getContext()), TempEnumTypes(nullptr),
TempRetainTypes(nullptr), TempSubprograms(nullptr), TempGVs(nullptr),
- DeclareFn(nullptr), ValueFn(nullptr) {}
+ DeclareFn(nullptr), ValueFn(nullptr),
+ AllowUnresolvedNodes(AllowUnresolvedNodes) {}
+
+static bool isUnresolved(MDNode *N) {
+ return N && (isa<MDNodeFwdDecl>(N) || !cast<GenericMDNode>(N)->isResolved());
+}
+
+void DIBuilder::trackIfUnresolved(MDNode *N) {
+ if (!AllowUnresolvedNodes) {
+ assert(!isUnresolved(N) && "Cannot handle unresolved nodes");
+ return;
+ }
+ if (isUnresolved(N))
+ UnresolvedNodes.emplace_back(N);
+ return;
+}
void DIBuilder::finalize() {
DIArray Enums = getOrCreateArray(AllEnumTypes);
DIType(TempEnumTypes).replaceAllUsesWith(Enums);
- SmallVector<Value *, 16> RetainValues;
+ SmallVector<Metadata *, 16> RetainValues;
// Declarations and definitions of the same type may be retained. Some
// clients RAUW these pairs, leaving duplicates in the retained types
// list. Use a set to remove the duplicates while we transform the
// TrackingVHs back into Values.
- SmallPtrSet<Value *, 16> RetainSet;
+ SmallPtrSet<Metadata *, 16> RetainSet;
for (unsigned I = 0, E = AllRetainTypes.size(); I < E; I++)
if (RetainSet.insert(AllRetainTypes[I]).second)
RetainValues.push_back(AllRetainTypes[I]);
for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) {
DISubprogram SP(SPs.getElement(i));
if (MDNode *Temp = SP.getVariablesNodes()) {
- SmallVector<Value *, 4> Variables;
- for (Value *V : PreservedVariables.lookup(SP))
+ SmallVector<Metadata *, 4> Variables;
+ for (Metadata *V : PreservedVariables.lookup(SP))
Variables.push_back(V);
DIArray AV = getOrCreateArray(Variables);
DIType(Temp).replaceAllUsesWith(AV);
DIArray GVs = getOrCreateArray(AllGVs);
DIType(TempGVs).replaceAllUsesWith(GVs);
- SmallVector<Value *, 16> RetainValuesI;
+ SmallVector<Metadata *, 16> RetainValuesI;
for (unsigned I = 0, E = AllImportedModules.size(); I < E; I++)
RetainValuesI.push_back(AllImportedModules[I]);
DIArray IMs = getOrCreateArray(RetainValuesI);
DIType(TempImportedModules).replaceAllUsesWith(IMs);
+
+ // Now that all temp nodes have been replaced or deleted, resolve remaining
+ // cycles.
+ for (const auto &N : UnresolvedNodes)
+ if (N)
+ cast<GenericMDNode>(N)->resolveCycles();
+ UnresolvedNodes.clear();
+
+ // Can't handle unresolved nodes anymore.
+ AllowUnresolvedNodes = false;
}
/// If N is compile unit return NULL otherwise return N.
static MDNode *createFilePathPair(LLVMContext &VMContext, StringRef Filename,
StringRef Directory) {
assert(!Filename.empty() && "Unable to create file without name");
- Value *Pair[] = {
- MDString::get(VMContext, Filename),
- MDString::get(VMContext, Directory)
- };
+ Metadata *Pair[] = {MDString::get(VMContext, Filename),
+ MDString::get(VMContext, Directory)};
return MDNode::get(VMContext, Pair);
}
"Invalid Language tag");
assert(!Filename.empty() &&
"Unable to create compile unit without filename");
- Value *TElts[] = {HeaderBuilder::get(DW_TAG_base_type).get(VMContext)};
+ Metadata *TElts[] = {HeaderBuilder::get(DW_TAG_base_type).get(VMContext)};
TempEnumTypes = MDNode::getTemporary(VMContext, TElts);
TempRetainTypes = MDNode::getTemporary(VMContext, TElts);
TempImportedModules = MDNode::getTemporary(VMContext, TElts);
- Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_compile_unit)
- .concat(Lang)
- .concat(Producer)
- .concat(isOptimized)
- .concat(Flags)
- .concat(RunTimeVer)
- .concat(SplitName)
- .concat(Kind)
- .get(VMContext),
- createFilePathPair(VMContext, Filename, Directory),
- TempEnumTypes, TempRetainTypes, TempSubprograms, TempGVs,
- TempImportedModules};
+ Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_compile_unit)
+ .concat(Lang)
+ .concat(Producer)
+ .concat(isOptimized)
+ .concat(Flags)
+ .concat(RunTimeVer)
+ .concat(SplitName)
+ .concat(Kind)
+ .get(VMContext),
+ createFilePathPair(VMContext, Filename, Directory),
+ TempEnumTypes, TempRetainTypes, TempSubprograms, TempGVs,
+ TempImportedModules};
MDNode *CUNode = MDNode::get(VMContext, Elts);
NMD->addOperand(CUNode);
}
+ trackIfUnresolved(CUNode);
return DICompileUnit(CUNode);
}
static DIImportedEntity
createImportedModule(LLVMContext &C, dwarf::Tag Tag, DIScope Context,
- Value *NS, unsigned Line, StringRef Name,
- SmallVectorImpl<TrackingVH<MDNode>> &AllImportedModules) {
+ Metadata *NS, unsigned Line, StringRef Name,
+ SmallVectorImpl<TrackingMDNodeRef> &AllImportedModules) {
const MDNode *R;
- Value *Elts[] = {HeaderBuilder::get(Tag).concat(Line).concat(Name).get(C),
- Context, NS};
+ Metadata *Elts[] = {HeaderBuilder::get(Tag).concat(Line).concat(Name).get(C),
+ Context, NS};
R = MDNode::get(C, Elts);
DIImportedEntity M(R);
assert(M.Verify() && "Imported module should be valid");
- AllImportedModules.push_back(TrackingVH<MDNode>(M));
+ AllImportedModules.emplace_back(M.get());
return M;
}
unsigned Line, StringRef Name) {
// Make sure to use the unique identifier based metadata reference for
// types that have one.
- Value *V = Decl.isType() ? static_cast<Value*>(DIType(Decl).getRef()) : Decl;
+ Metadata *V =
+ Decl.isType() ? static_cast<Metadata *>(DIType(Decl).getRef()) : Decl;
return ::createImportedModule(VMContext, dwarf::DW_TAG_imported_declaration,
Context, V, Line, Name,
AllImportedModules);
}
DIFile DIBuilder::createFile(StringRef Filename, StringRef Directory) {
- Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_file_type).get(VMContext),
- createFilePathPair(VMContext, Filename, Directory)};
+ Metadata *Elts[] = {
+ HeaderBuilder::get(dwarf::DW_TAG_file_type).get(VMContext),
+ createFilePathPair(VMContext, Filename, Directory)};
return DIFile(MDNode::get(VMContext, Elts));
}
DIEnumerator DIBuilder::createEnumerator(StringRef Name, int64_t Val) {
assert(!Name.empty() && "Unable to create enumerator without name");
- Value *Elts[] = {
- HeaderBuilder::get(dwarf::DW_TAG_enumerator).concat(Name).concat(Val).get(
- VMContext)};
+ Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_enumerator)
+ .concat(Name)
+ .concat(Val)
+ .get(VMContext)};
return DIEnumerator(MDNode::get(VMContext, Elts));
}
assert(!Name.empty() && "Unable to create type without name");
// Unspecified types are encoded in DIBasicType format. Line number, filename,
// size, alignment, offset and flags are always empty here.
- Value *Elts[] = {
+ Metadata *Elts[] = {
HeaderBuilder::get(dwarf::DW_TAG_unspecified_type)
.concat(Name)
.concat(0)
assert(!Name.empty() && "Unable to create type without name");
// Basic types are encoded in DIBasicType format. Line number, filename,
// offset and flags are always empty here.
- Value *Elts[] = {
+ Metadata *Elts[] = {
HeaderBuilder::get(dwarf::DW_TAG_base_type)
.concat(Name)
.concat(0) // Line
DIDerivedType DIBuilder::createQualifiedType(unsigned Tag, DIType FromTy) {
// Qualified types are encoded in DIDerivedType format.
- Value *Elts[] = {HeaderBuilder::get(Tag)
- .concat(StringRef()) // Name
- .concat(0) // Line
- .concat(0) // Size
- .concat(0) // Align
- .concat(0) // Offset
- .concat(0) // Flags
- .get(VMContext),
- nullptr, // Filename
- nullptr, // Unused
- FromTy.getRef()};
+ Metadata *Elts[] = {HeaderBuilder::get(Tag)
+ .concat(StringRef()) // Name
+ .concat(0) // Line
+ .concat(0) // Size
+ .concat(0) // Align
+ .concat(0) // Offset
+ .concat(0) // Flags
+ .get(VMContext),
+ nullptr, // Filename
+ nullptr, // Unused
+ FromTy.getRef()};
return DIDerivedType(MDNode::get(VMContext, Elts));
}
DIBuilder::createPointerType(DIType PointeeTy, uint64_t SizeInBits,
uint64_t AlignInBits, StringRef Name) {
// Pointer types are encoded in DIDerivedType format.
- Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_pointer_type)
- .concat(Name)
- .concat(0) // Line
- .concat(SizeInBits)
- .concat(AlignInBits)
- .concat(0) // Offset
- .concat(0) // Flags
- .get(VMContext),
- nullptr, // Filename
- nullptr, // Unused
- PointeeTy.getRef()};
+ Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_pointer_type)
+ .concat(Name)
+ .concat(0) // Line
+ .concat(SizeInBits)
+ .concat(AlignInBits)
+ .concat(0) // Offset
+ .concat(0) // Flags
+ .get(VMContext),
+ nullptr, // Filename
+ nullptr, // Unused
+ PointeeTy.getRef()};
return DIDerivedType(MDNode::get(VMContext, Elts));
}
DIDerivedType DIBuilder::createMemberPointerType(DIType PointeeTy,
DIType Base) {
// Pointer types are encoded in DIDerivedType format.
- Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_ptr_to_member_type)
- .concat(StringRef())
- .concat(0) // Line
- .concat(0) // Size
- .concat(0) // Align
- .concat(0) // Offset
- .concat(0) // Flags
- .get(VMContext),
- nullptr, // Filename
- nullptr, // Unused
- PointeeTy.getRef(), Base.getRef()};
+ Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_ptr_to_member_type)
+ .concat(StringRef())
+ .concat(0) // Line
+ .concat(0) // Size
+ .concat(0) // Align
+ .concat(0) // Offset
+ .concat(0) // Flags
+ .get(VMContext),
+ nullptr, // Filename
+ nullptr, // Unused
+ PointeeTy.getRef(), Base.getRef()};
return DIDerivedType(MDNode::get(VMContext, Elts));
}
DIDerivedType DIBuilder::createReferenceType(unsigned Tag, DIType RTy) {
assert(RTy.isType() && "Unable to create reference type");
// References are encoded in DIDerivedType format.
- Value *Elts[] = {HeaderBuilder::get(Tag)
- .concat(StringRef()) // Name
- .concat(0) // Line
- .concat(0) // Size
- .concat(0) // Align
- .concat(0) // Offset
- .concat(0) // Flags
- .get(VMContext),
- nullptr, // Filename
- nullptr, // TheCU,
- RTy.getRef()};
+ Metadata *Elts[] = {HeaderBuilder::get(Tag)
+ .concat(StringRef()) // Name
+ .concat(0) // Line
+ .concat(0) // Size
+ .concat(0) // Align
+ .concat(0) // Offset
+ .concat(0) // Flags
+ .get(VMContext),
+ nullptr, // Filename
+ nullptr, // TheCU,
+ RTy.getRef()};
return DIDerivedType(MDNode::get(VMContext, Elts));
}
DIDerivedType DIBuilder::createTypedef(DIType Ty, StringRef Name, DIFile File,
unsigned LineNo, DIDescriptor Context) {
// typedefs are encoded in DIDerivedType format.
- Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_typedef)
- .concat(Name)
- .concat(LineNo)
- .concat(0) // Size
- .concat(0) // Align
- .concat(0) // Offset
- .concat(0) // Flags
- .get(VMContext),
- File.getFileNode(),
- DIScope(getNonCompileUnitScope(Context)).getRef(),
- Ty.getRef()};
+ Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_typedef)
+ .concat(Name)
+ .concat(LineNo)
+ .concat(0) // Size
+ .concat(0) // Align
+ .concat(0) // Offset
+ .concat(0) // Flags
+ .get(VMContext),
+ File.getFileNode(),
+ DIScope(getNonCompileUnitScope(Context)).getRef(),
+ Ty.getRef()};
return DIDerivedType(MDNode::get(VMContext, Elts));
}
// typedefs are encoded in DIDerivedType format.
assert(Ty.isType() && "Invalid type!");
assert(FriendTy.isType() && "Invalid friend type!");
- Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_friend)
- .concat(StringRef()) // Name
- .concat(0) // Line
- .concat(0) // Size
- .concat(0) // Align
- .concat(0) // Offset
- .concat(0) // Flags
- .get(VMContext),
- nullptr, Ty.getRef(), FriendTy.getRef()};
+ Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_friend)
+ .concat(StringRef()) // Name
+ .concat(0) // Line
+ .concat(0) // Size
+ .concat(0) // Align
+ .concat(0) // Offset
+ .concat(0) // Flags
+ .get(VMContext),
+ nullptr, Ty.getRef(), FriendTy.getRef()};
return DIDerivedType(MDNode::get(VMContext, Elts));
}
unsigned Flags) {
assert(Ty.isType() && "Unable to create inheritance");
// TAG_inheritance is encoded in DIDerivedType format.
- Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_inheritance)
- .concat(StringRef()) // Name
- .concat(0) // Line
- .concat(0) // Size
- .concat(0) // Align
- .concat(BaseOffset)
- .concat(Flags)
- .get(VMContext),
- nullptr, Ty.getRef(), BaseTy.getRef()};
+ Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_inheritance)
+ .concat(StringRef()) // Name
+ .concat(0) // Line
+ .concat(0) // Size
+ .concat(0) // Align
+ .concat(BaseOffset)
+ .concat(Flags)
+ .get(VMContext),
+ nullptr, Ty.getRef(), BaseTy.getRef()};
return DIDerivedType(MDNode::get(VMContext, Elts));
}
uint64_t OffsetInBits, unsigned Flags,
DIType Ty) {
// TAG_member is encoded in DIDerivedType format.
- Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_member)
- .concat(Name)
- .concat(LineNumber)
- .concat(SizeInBits)
- .concat(AlignInBits)
- .concat(OffsetInBits)
- .concat(Flags)
- .get(VMContext),
- File.getFileNode(),
- DIScope(getNonCompileUnitScope(Scope)).getRef(),
- Ty.getRef()};
+ Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_member)
+ .concat(Name)
+ .concat(LineNumber)
+ .concat(SizeInBits)
+ .concat(AlignInBits)
+ .concat(OffsetInBits)
+ .concat(Flags)
+ .get(VMContext),
+ File.getFileNode(),
+ DIScope(getNonCompileUnitScope(Scope)).getRef(),
+ Ty.getRef()};
return DIDerivedType(MDNode::get(VMContext, Elts));
}
+static Metadata *getConstantOrNull(Constant *C) {
+ if (C)
+ return ConstantAsMetadata::get(C);
+ return nullptr;
+}
+
DIDerivedType DIBuilder::createStaticMemberType(DIDescriptor Scope,
StringRef Name, DIFile File,
unsigned LineNumber, DIType Ty,
llvm::Constant *Val) {
// TAG_member is encoded in DIDerivedType format.
Flags |= DIDescriptor::FlagStaticMember;
- Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_member)
- .concat(Name)
- .concat(LineNumber)
- .concat(0) // Size
- .concat(0) // Align
- .concat(0) // Offset
- .concat(Flags)
- .get(VMContext),
- File.getFileNode(),
- DIScope(getNonCompileUnitScope(Scope)).getRef(), Ty.getRef(),
- Val};
+ Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_member)
+ .concat(Name)
+ .concat(LineNumber)
+ .concat(0) // Size
+ .concat(0) // Align
+ .concat(0) // Offset
+ .concat(Flags)
+ .get(VMContext),
+ File.getFileNode(),
+ DIScope(getNonCompileUnitScope(Scope)).getRef(),
+ Ty.getRef(), getConstantOrNull(Val)};
return DIDerivedType(MDNode::get(VMContext, Elts));
}
uint64_t OffsetInBits, unsigned Flags,
DIType Ty, MDNode *PropertyNode) {
// TAG_member is encoded in DIDerivedType format.
- Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_member)
- .concat(Name)
- .concat(LineNumber)
- .concat(SizeInBits)
- .concat(AlignInBits)
- .concat(OffsetInBits)
- .concat(Flags)
- .get(VMContext),
- File.getFileNode(), getNonCompileUnitScope(File), Ty,
- PropertyNode};
+ Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_member)
+ .concat(Name)
+ .concat(LineNumber)
+ .concat(SizeInBits)
+ .concat(AlignInBits)
+ .concat(OffsetInBits)
+ .concat(Flags)
+ .get(VMContext),
+ File.getFileNode(), getNonCompileUnitScope(File), Ty,
+ PropertyNode};
return DIDerivedType(MDNode::get(VMContext, Elts));
}
DIBuilder::createObjCProperty(StringRef Name, DIFile File, unsigned LineNumber,
StringRef GetterName, StringRef SetterName,
unsigned PropertyAttributes, DIType Ty) {
- Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_APPLE_property)
- .concat(Name)
- .concat(LineNumber)
- .concat(GetterName)
- .concat(SetterName)
- .concat(PropertyAttributes)
- .get(VMContext),
- File, Ty};
+ Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_APPLE_property)
+ .concat(Name)
+ .concat(LineNumber)
+ .concat(GetterName)
+ .concat(SetterName)
+ .concat(PropertyAttributes)
+ .get(VMContext),
+ File, Ty};
return DIObjCProperty(MDNode::get(VMContext, Elts));
}
DIBuilder::createTemplateTypeParameter(DIDescriptor Context, StringRef Name,
DIType Ty, MDNode *File, unsigned LineNo,
unsigned ColumnNo) {
- Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_template_type_parameter)
- .concat(Name)
- .concat(LineNo)
- .concat(ColumnNo)
- .get(VMContext),
- DIScope(getNonCompileUnitScope(Context)).getRef(),
- Ty.getRef(), File};
+ Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_template_type_parameter)
+ .concat(Name)
+ .concat(LineNo)
+ .concat(ColumnNo)
+ .get(VMContext),
+ DIScope(getNonCompileUnitScope(Context)).getRef(),
+ Ty.getRef(), File};
return DITemplateTypeParameter(MDNode::get(VMContext, Elts));
}
static DITemplateValueParameter createTemplateValueParameterHelper(
LLVMContext &VMContext, unsigned Tag, DIDescriptor Context, StringRef Name,
- DIType Ty, Value *Val, MDNode *File, unsigned LineNo, unsigned ColumnNo) {
- Value *Elts[] = {
+ DIType Ty, Metadata *MD, MDNode *File, unsigned LineNo, unsigned ColumnNo) {
+ Metadata *Elts[] = {
HeaderBuilder::get(Tag).concat(Name).concat(LineNo).concat(ColumnNo).get(
VMContext),
- DIScope(getNonCompileUnitScope(Context)).getRef(), Ty.getRef(), Val,
- File};
+ DIScope(getNonCompileUnitScope(Context)).getRef(), Ty.getRef(), MD, File};
return DITemplateValueParameter(MDNode::get(VMContext, Elts));
}
DIType Ty, Constant *Val, MDNode *File,
unsigned LineNo, unsigned ColumnNo) {
return createTemplateValueParameterHelper(
- VMContext, dwarf::DW_TAG_template_value_parameter, Context, Name, Ty, Val,
- File, LineNo, ColumnNo);
+ VMContext, dwarf::DW_TAG_template_value_parameter, Context, Name, Ty,
+ getConstantOrNull(Val), File, LineNo, ColumnNo);
}
DITemplateValueParameter
assert((!Context || Context.isScope() || Context.isType()) &&
"createClassType should be called with a valid Context");
// TAG_class_type is encoded in DICompositeType format.
- Value *Elts[] = {
+ Metadata *Elts[] = {
HeaderBuilder::get(dwarf::DW_TAG_class_type)
.concat(Name)
.concat(LineNumber)
DIType VTableHolder,
StringRef UniqueIdentifier) {
// TAG_structure_type is encoded in DICompositeType format.
- Value *Elts[] = {
+ Metadata *Elts[] = {
HeaderBuilder::get(dwarf::DW_TAG_structure_type)
.concat(Name)
.concat(LineNumber)
unsigned RunTimeLang,
StringRef UniqueIdentifier) {
// TAG_union_type is encoded in DICompositeType format.
- Value *Elts[] = {
+ Metadata *Elts[] = {
HeaderBuilder::get(dwarf::DW_TAG_union_type)
.concat(Name)
.concat(LineNumber)
DITypeArray ParameterTypes,
unsigned Flags) {
// TAG_subroutine_type is encoded in DICompositeType format.
- Value *Elts[] = {
+ Metadata *Elts[] = {
HeaderBuilder::get(dwarf::DW_TAG_subroutine_type)
.concat(StringRef())
.concat(0) // Line
uint64_t SizeInBits, uint64_t AlignInBits, DIArray Elements,
DIType UnderlyingType, StringRef UniqueIdentifier) {
// TAG_enumeration_type is encoded in DICompositeType format.
- Value *Elts[] = {
+ Metadata *Elts[] = {
HeaderBuilder::get(dwarf::DW_TAG_enumeration_type)
.concat(Name)
.concat(LineNumber)
DICompositeType DIBuilder::createArrayType(uint64_t Size, uint64_t AlignInBits,
DIType Ty, DIArray Subscripts) {
// TAG_array_type is encoded in DICompositeType format.
- Value *Elts[] = {
+ Metadata *Elts[] = {
HeaderBuilder::get(dwarf::DW_TAG_array_type)
.concat(StringRef())
.concat(0) // Line
DICompositeType DIBuilder::createVectorType(uint64_t Size, uint64_t AlignInBits,
DIType Ty, DIArray Subscripts) {
// A vector is an array type with the FlagVector flag applied.
- Value *Elts[] = {
+ Metadata *Elts[] = {
HeaderBuilder::get(dwarf::DW_TAG_array_type)
.concat("")
.concat(0) // Line
static DIType createTypeWithFlags(LLVMContext &Context, DIType Ty,
unsigned FlagsToSet) {
- SmallVector<Value *, 9> Elts;
+ SmallVector<Metadata *, 9> Elts;
MDNode *N = Ty;
assert(N && "Unexpected input DIType!");
// Update header field.
return createTypeWithFlags(VMContext, Ty, Flags);
}
-void DIBuilder::retainType(DIType T) {
- AllRetainTypes.push_back(TrackingVH<MDNode>(T));
-}
+void DIBuilder::retainType(DIType T) { AllRetainTypes.emplace_back(T); }
DIBasicType DIBuilder::createUnspecifiedParameter() {
return DIBasicType();
uint64_t SizeInBits, uint64_t AlignInBits,
StringRef UniqueIdentifier) {
// Create a temporary MDNode.
- Value *Elts[] = {
+ Metadata *Elts[] = {
HeaderBuilder::get(Tag)
.concat(Name)
.concat(Line)
unsigned RuntimeLang, uint64_t SizeInBits, uint64_t AlignInBits,
StringRef UniqueIdentifier) {
// Create a temporary MDNode.
- Value *Elts[] = {
+ Metadata *Elts[] = {
HeaderBuilder::get(Tag)
.concat(Name)
.concat(Line)
nullptr, // TemplateParams
UniqueIdentifier.empty() ? nullptr
: MDString::get(VMContext, UniqueIdentifier)};
- MDNode *Node = MDNode::getTemporary(VMContext, Elts);
- DICompositeType RetTy(Node);
+ DICompositeType RetTy(MDNode::getTemporary(VMContext, Elts));
assert(RetTy.isCompositeType() &&
"createReplaceableForwardDecl result should be a DIType");
if (!UniqueIdentifier.empty())
return RetTy;
}
-DIArray DIBuilder::getOrCreateArray(ArrayRef<Value *> Elements) {
+DIArray DIBuilder::getOrCreateArray(ArrayRef<Metadata *> Elements) {
return DIArray(MDNode::get(VMContext, Elements));
}
-DITypeArray DIBuilder::getOrCreateTypeArray(ArrayRef<Value *> Elements) {
- SmallVector<llvm::Value *, 16> Elts;
+DITypeArray DIBuilder::getOrCreateTypeArray(ArrayRef<Metadata *> Elements) {
+ SmallVector<llvm::Metadata *, 16> Elts;
for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
if (Elements[i] && isa<MDNode>(Elements[i]))
Elts.push_back(DIType(cast<MDNode>(Elements[i])).getRef());
}
DISubrange DIBuilder::getOrCreateSubrange(int64_t Lo, int64_t Count) {
- Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_subrange_type)
- .concat(Lo)
- .concat(Count)
- .get(VMContext)};
+ Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_subrange_type)
+ .concat(Lo)
+ .concat(Count)
+ .get(VMContext)};
return DISubrange(MDNode::get(VMContext, Elts));
}
LLVMContext &VMContext, DIDescriptor Context, StringRef Name,
StringRef LinkageName, DIFile F, unsigned LineNumber, DITypeRef Ty,
bool isLocalToUnit, Constant *Val, MDNode *Decl, bool isDefinition,
- std::function<MDNode *(ArrayRef<Value *>)> CreateFunc) {
+ std::function<MDNode *(ArrayRef<Metadata *>)> CreateFunc) {
MDNode *TheCtx = getNonCompileUnitScope(Context);
if (DIScope(TheCtx).isCompositeType()) {
"Context of a global variable should not be a type with identifier");
}
- Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_variable)
- .concat(Name)
- .concat(Name)
- .concat(LinkageName)
- .concat(LineNumber)
- .concat(isLocalToUnit)
- .concat(isDefinition)
- .get(VMContext),
- TheCtx, F, Ty, Val,
- DIDescriptor(Decl)};
+ Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_variable)
+ .concat(Name)
+ .concat(Name)
+ .concat(LinkageName)
+ .concat(LineNumber)
+ .concat(isLocalToUnit)
+ .concat(isDefinition)
+ .get(VMContext),
+ TheCtx, F, Ty, getConstantOrNull(Val),
+ DIDescriptor(Decl)};
return DIGlobalVariable(CreateFunc(Elts));
}
DIDescriptor Context, StringRef Name, StringRef LinkageName, DIFile F,
unsigned LineNumber, DITypeRef Ty, bool isLocalToUnit, Constant *Val,
MDNode *Decl) {
- return createGlobalVariableHelper(VMContext, Context, Name, LinkageName, F,
- LineNumber, Ty, isLocalToUnit, Val, Decl, true,
- [&] (ArrayRef<Value *> Elts) -> MDNode * {
- MDNode *Node = MDNode::get(VMContext, Elts);
- AllGVs.push_back(Node);
- return Node;
- });
+ return createGlobalVariableHelper(
+ VMContext, Context, Name, LinkageName, F, LineNumber, Ty, isLocalToUnit,
+ Val, Decl, true, [&](ArrayRef<Metadata *> Elts) -> MDNode *{
+ MDNode *Node = MDNode::get(VMContext, Elts);
+ AllGVs.push_back(Node);
+ return Node;
+ });
}
DIGlobalVariable DIBuilder::createTempGlobalVariableFwdDecl(
unsigned LineNumber, DITypeRef Ty, bool isLocalToUnit, Constant *Val,
MDNode *Decl) {
return createGlobalVariableHelper(VMContext, Context, Name, LinkageName, F,
- LineNumber, Ty, isLocalToUnit, Val, Decl, false,
- [&] (ArrayRef<Value *> Elts) {
- return MDNode::getTemporary(VMContext, Elts);
- });
+ LineNumber, Ty, isLocalToUnit, Val, Decl,
+ false, [&](ArrayRef<Metadata *> Elts) {
+ return MDNode::getTemporary(VMContext, Elts);
+ });
}
DIVariable DIBuilder::createLocalVariable(unsigned Tag, DIDescriptor Scope,
DIDescriptor Context(getNonCompileUnitScope(Scope));
assert((!Context || Context.isScope()) &&
"createLocalVariable should be called with a valid Context");
- Value *Elts[] = {HeaderBuilder::get(Tag)
- .concat(Name)
- .concat(LineNo | (ArgNo << 24))
- .concat(Flags)
- .get(VMContext),
- getNonCompileUnitScope(Scope), File, Ty};
+ Metadata *Elts[] = {HeaderBuilder::get(Tag)
+ .concat(Name)
+ .concat(LineNo | (ArgNo << 24))
+ .concat(Flags)
+ .get(VMContext),
+ getNonCompileUnitScope(Scope), File, Ty};
MDNode *Node = MDNode::get(VMContext, Elts);
if (AlwaysPreserve) {
// The optimizer may remove local variable. If there is an interest
// named mdnode.
DISubprogram Fn(getDISubprogram(Scope));
assert(Fn && "Missing subprogram for local variable");
- PreservedVariables[Fn].push_back(Node);
+ PreservedVariables[Fn].emplace_back(Node);
}
DIVariable RetVar(Node);
assert(RetVar.isVariable() &&
auto Header = HeaderBuilder::get(DW_TAG_expression);
for (int64_t I : Addr)
Header.concat(I);
- Value *Elts[] = {Header.get(VMContext)};
+ Metadata *Elts[] = {Header.get(VMContext)};
return DIExpression(MDNode::get(VMContext, Elts));
}
Flags, isOptimized, Fn, TParams, Decl);
}
-static DISubprogram
-createFunctionHelper(LLVMContext &VMContext, DIDescriptor Context, StringRef Name,
- StringRef LinkageName, DIFile File, unsigned LineNo,
- DICompositeType Ty, bool isLocalToUnit, bool isDefinition,
- unsigned ScopeLine, unsigned Flags, bool isOptimized,
- Function *Fn, MDNode *TParams, MDNode *Decl, MDNode *Vars,
- std::function<MDNode *(ArrayRef<Value *>)> CreateFunc) {
+static DISubprogram createFunctionHelper(
+ LLVMContext &VMContext, DIDescriptor Context, StringRef Name,
+ StringRef LinkageName, DIFile File, unsigned LineNo, DICompositeType Ty,
+ bool isLocalToUnit, bool isDefinition, unsigned ScopeLine, unsigned Flags,
+ bool isOptimized, Function *Fn, MDNode *TParams, MDNode *Decl, MDNode *Vars,
+ std::function<MDNode *(ArrayRef<Metadata *>)> CreateFunc) {
assert(Ty.getTag() == dwarf::DW_TAG_subroutine_type &&
"function types should be subroutines");
- Value *Elts[] = {
- HeaderBuilder::get(dwarf::DW_TAG_subprogram)
- .concat(Name)
- .concat(Name)
- .concat(LinkageName)
- .concat(LineNo)
- .concat(isLocalToUnit)
- .concat(isDefinition)
- .concat(0)
- .concat(0)
- .concat(Flags)
- .concat(isOptimized)
- .concat(ScopeLine)
- .get(VMContext),
- File.getFileNode(), DIScope(getNonCompileUnitScope(Context)).getRef(), Ty,
- nullptr, Fn, TParams, Decl, Vars};
+ Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_subprogram)
+ .concat(Name)
+ .concat(Name)
+ .concat(LinkageName)
+ .concat(LineNo)
+ .concat(isLocalToUnit)
+ .concat(isDefinition)
+ .concat(0)
+ .concat(0)
+ .concat(Flags)
+ .concat(isOptimized)
+ .concat(ScopeLine)
+ .get(VMContext),
+ File.getFileNode(),
+ DIScope(getNonCompileUnitScope(Context)).getRef(), Ty,
+ nullptr, getConstantOrNull(Fn), TParams, Decl, Vars};
DISubprogram S(CreateFunc(Elts));
assert(S.isSubprogram() &&
bool isOptimized, Function *Fn,
MDNode *TParams, MDNode *Decl) {
return createFunctionHelper(VMContext, Context, Name, LinkageName, File,
- LineNo, Ty, isLocalToUnit, isDefinition, ScopeLine,
- Flags, isOptimized, Fn, TParams, Decl,
+ LineNo, Ty, isLocalToUnit, isDefinition,
+ ScopeLine, Flags, isOptimized, Fn, TParams, Decl,
MDNode::getTemporary(VMContext, None),
- [&] (ArrayRef<Value *> Elts) -> MDNode *{
- MDNode *Node = MDNode::get(VMContext, Elts);
- // Create a named metadata so that we
- // do not lose this mdnode.
- if (isDefinition)
- AllSubprograms.push_back(Node);
- return Node;
- });
+ [&](ArrayRef<Metadata *> Elts) -> MDNode *{
+ MDNode *Node = MDNode::get(VMContext, Elts);
+ // Create a named metadata so that we
+ // do not lose this mdnode.
+ if (isDefinition)
+ AllSubprograms.push_back(Node);
+ return Node;
+ });
}
DISubprogram
bool isOptimized, Function *Fn,
MDNode *TParams, MDNode *Decl) {
return createFunctionHelper(VMContext, Context, Name, LinkageName, File,
- LineNo, Ty, isLocalToUnit, isDefinition, ScopeLine,
- Flags, isOptimized, Fn, TParams, Decl, nullptr,
- [&] (ArrayRef<Value *> Elts) {
- return MDNode::getTemporary(VMContext, Elts);
- });
+ LineNo, Ty, isLocalToUnit, isDefinition,
+ ScopeLine, Flags, isOptimized, Fn, TParams, Decl,
+ nullptr, [&](ArrayRef<Metadata *> Elts) {
+ return MDNode::getTemporary(VMContext, Elts);
+ });
}
DISubprogram DIBuilder::createMethod(DIDescriptor Context, StringRef Name,
assert(getNonCompileUnitScope(Context) &&
"Methods should have both a Context and a context that isn't "
"the compile unit.");
- Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_subprogram)
- .concat(Name)
- .concat(Name)
- .concat(LinkageName)
- .concat(LineNo)
- .concat(isLocalToUnit)
- .concat(isDefinition)
- .concat(VK)
- .concat(VIndex)
- .concat(Flags)
- .concat(isOptimized)
- .concat(LineNo)
- // FIXME: Do we want to use different scope/lines?
- .get(VMContext),
- F.getFileNode(), DIScope(Context).getRef(), Ty,
- VTableHolder.getRef(), Fn, TParam, nullptr, nullptr};
+ Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_subprogram)
+ .concat(Name)
+ .concat(Name)
+ .concat(LinkageName)
+ .concat(LineNo)
+ .concat(isLocalToUnit)
+ .concat(isDefinition)
+ .concat(VK)
+ .concat(VIndex)
+ .concat(Flags)
+ .concat(isOptimized)
+ .concat(LineNo)
+ // FIXME: Do we want to use different scope/lines?
+ .get(VMContext),
+ F.getFileNode(), DIScope(Context).getRef(), Ty,
+ VTableHolder.getRef(), getConstantOrNull(Fn), TParam,
+ nullptr, nullptr};
MDNode *Node = MDNode::get(VMContext, Elts);
if (isDefinition)
AllSubprograms.push_back(Node);
DINameSpace DIBuilder::createNameSpace(DIDescriptor Scope, StringRef Name,
DIFile File, unsigned LineNo) {
- Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_namespace)
- .concat(Name)
- .concat(LineNo)
- .get(VMContext),
- File.getFileNode(), getNonCompileUnitScope(Scope)};
+ Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_namespace)
+ .concat(Name)
+ .concat(LineNo)
+ .get(VMContext),
+ File.getFileNode(), getNonCompileUnitScope(Scope)};
DINameSpace R(MDNode::get(VMContext, Elts));
assert(R.Verify() &&
"createNameSpace should return a verifiable DINameSpace");
DILexicalBlockFile DIBuilder::createLexicalBlockFile(DIDescriptor Scope,
DIFile File,
unsigned Discriminator) {
- Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_lexical_block)
- .concat(Discriminator)
- .get(VMContext),
- File.getFileNode(), Scope};
+ Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_lexical_block)
+ .concat(Discriminator)
+ .get(VMContext),
+ File.getFileNode(), Scope};
DILexicalBlockFile R(MDNode::get(VMContext, Elts));
assert(
R.Verify() &&
// Defeat MDNode uniquing for lexical blocks by using unique id.
static unsigned int unique_id = 0;
- Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_lexical_block)
- .concat(Line)
- .concat(Col)
- .concat(unique_id++)
- .get(VMContext),
- File.getFileNode(), getNonCompileUnitScope(Scope)};
+ Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_lexical_block)
+ .concat(Line)
+ .concat(Col)
+ .concat(unique_id++)
+ .get(VMContext),
+ File.getFileNode(), getNonCompileUnitScope(Scope)};
DILexicalBlock R(MDNode::get(VMContext, Elts));
assert(R.Verify() &&
"createLexicalBlock should return a verifiable DILexicalBlock");
return R;
}
+static Value *getDbgIntrinsicValueImpl(LLVMContext &VMContext, Value *V) {
+ assert(V && "no value passed to dbg intrinsic");
+ return MetadataAsValue::get(VMContext, ValueAsMetadata::get(V));
+}
+
Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo,
DIExpression Expr,
Instruction *InsertBefore) {
- assert(Storage && "no storage passed to dbg.declare");
assert(VarInfo.isVariable() &&
"empty or invalid DIVariable passed to dbg.declare");
if (!DeclareFn)
DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare);
- Value *Args[] = {MDNode::get(Storage->getContext(), Storage), VarInfo, Expr};
+ trackIfUnresolved(VarInfo);
+ trackIfUnresolved(Expr);
+ Value *Args[] = {getDbgIntrinsicValueImpl(VMContext, Storage),
+ MetadataAsValue::get(VMContext, VarInfo),
+ MetadataAsValue::get(VMContext, Expr)};
return CallInst::Create(DeclareFn, Args, "", InsertBefore);
}
Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo,
DIExpression Expr,
BasicBlock *InsertAtEnd) {
- assert(Storage && "no storage passed to dbg.declare");
assert(VarInfo.isVariable() &&
"empty or invalid DIVariable passed to dbg.declare");
if (!DeclareFn)
DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare);
- Value *Args[] = {MDNode::get(Storage->getContext(), Storage), VarInfo, Expr};
+ trackIfUnresolved(VarInfo);
+ trackIfUnresolved(Expr);
+ Value *Args[] = {getDbgIntrinsicValueImpl(VMContext, Storage),
+ MetadataAsValue::get(VMContext, VarInfo),
+ MetadataAsValue::get(VMContext, Expr)};
// If this block already has a terminator then insert this intrinsic
// before the terminator.
if (!ValueFn)
ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value);
- Value *Args[] = {MDNode::get(V->getContext(), V),
- ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset),
- VarInfo, Expr};
+ trackIfUnresolved(VarInfo);
+ trackIfUnresolved(Expr);
+ Value *Args[] = {getDbgIntrinsicValueImpl(VMContext, V),
+ ConstantInt::get(Type::getInt64Ty(VMContext), Offset),
+ MetadataAsValue::get(VMContext, VarInfo),
+ MetadataAsValue::get(VMContext, Expr)};
return CallInst::Create(ValueFn, Args, "", InsertBefore);
}
if (!ValueFn)
ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value);
- Value *Args[] = {MDNode::get(V->getContext(), V),
- ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset),
- VarInfo, Expr};
+ trackIfUnresolved(VarInfo);
+ trackIfUnresolved(Expr);
+ Value *Args[] = {getDbgIntrinsicValueImpl(VMContext, V),
+ ConstantInt::get(Type::getInt64Ty(VMContext), Offset),
+ MetadataAsValue::get(VMContext, VarInfo),
+ MetadataAsValue::get(VMContext, Expr)};
return CallInst::Create(ValueFn, Args, "", InsertAtEnd);
}
DIImportedEntity(DbgNode).Verify() || DIExpression(DbgNode).Verify());
}
-static Value *getField(const MDNode *DbgNode, unsigned Elt) {
+static Metadata *getField(const MDNode *DbgNode, unsigned Elt) {
if (!DbgNode || Elt >= DbgNode->getNumOperands())
return nullptr;
return DbgNode->getOperand(Elt);
}
uint64_t DIDescriptor::getUInt64Field(unsigned Elt) const {
- if (!DbgNode)
- return 0;
-
- if (Elt < DbgNode->getNumOperands())
- if (ConstantInt *CI =
- dyn_cast_or_null<ConstantInt>(DbgNode->getOperand(Elt)))
+ if (auto *C = getConstantField(Elt))
+ if (ConstantInt *CI = dyn_cast<ConstantInt>(C))
return CI->getZExtValue();
return 0;
}
int64_t DIDescriptor::getInt64Field(unsigned Elt) const {
- if (!DbgNode)
- return 0;
-
- if (Elt < DbgNode->getNumOperands())
- if (ConstantInt *CI =
- dyn_cast_or_null<ConstantInt>(DbgNode->getOperand(Elt)))
- return CI->getSExtValue();
+ if (auto *C = getConstantField(Elt))
+ if (ConstantInt *CI = dyn_cast<ConstantInt>(C))
+ return CI->getZExtValue();
return 0;
}
}
GlobalVariable *DIDescriptor::getGlobalVariableField(unsigned Elt) const {
- if (!DbgNode)
- return nullptr;
-
- if (Elt < DbgNode->getNumOperands())
- return dyn_cast_or_null<GlobalVariable>(DbgNode->getOperand(Elt));
- return nullptr;
+ return dyn_cast_or_null<GlobalVariable>(getConstantField(Elt));
}
Constant *DIDescriptor::getConstantField(unsigned Elt) const {
return nullptr;
if (Elt < DbgNode->getNumOperands())
- return dyn_cast_or_null<Constant>(DbgNode->getOperand(Elt));
+ if (auto *C =
+ dyn_cast_or_null<ConstantAsMetadata>(DbgNode->getOperand(Elt)))
+ return C->getValue();
return nullptr;
}
Function *DIDescriptor::getFunctionField(unsigned Elt) const {
- if (!DbgNode)
- return nullptr;
-
- if (Elt < DbgNode->getNumOperands())
- return dyn_cast_or_null<Function>(DbgNode->getOperand(Elt));
- return nullptr;
+ return dyn_cast_or_null<Function>(getConstantField(Elt));
}
void DIDescriptor::replaceFunctionField(unsigned Elt, Function *F) {
if (Elt < DbgNode->getNumOperands()) {
MDNode *Node = const_cast<MDNode *>(DbgNode);
- Node->replaceOperandWith(Elt, F);
+ Node->replaceOperandWith(Elt, F ? ConstantAsMetadata::get(F) : nullptr);
}
}
// itself.
const MDNode *DN = D;
if (DbgNode == DN) {
- SmallVector<Value*, 10> Ops(DbgNode->getNumOperands());
+ SmallVector<Metadata *, 10> Ops(DbgNode->getNumOperands());
for (size_t i = 0; i != Ops.size(); ++i)
Ops[i] = DbgNode->getOperand(i);
DN = MDNode::get(VMContext, Ops);
}
- MDNode *Node = const_cast<MDNode *>(DbgNode);
- const Value *V = cast_or_null<Value>(DN);
- Node->replaceAllUsesWith(const_cast<Value *>(V));
+ auto *Node = cast<MDNodeFwdDecl>(const_cast<MDNode *>(DbgNode));
+ Node->replaceAllUsesWith(const_cast<MDNode *>(DN));
MDNode::deleteTemporary(Node);
DbgNode = DN;
}
void DIDescriptor::replaceAllUsesWith(MDNode *D) {
-
assert(DbgNode && "Trying to replace an unverified type!");
assert(DbgNode != D && "This replacement should always happen");
- MDNode *Node = const_cast<MDNode *>(DbgNode);
- const MDNode *DN = D;
- const Value *V = cast_or_null<Value>(DN);
- Node->replaceAllUsesWith(const_cast<Value *>(V));
+ auto *Node = cast<MDNodeFwdDecl>(const_cast<MDNode *>(DbgNode));
+ Node->replaceAllUsesWith(D);
MDNode::deleteTemporary(Node);
}
static bool fieldIsMDNode(const MDNode *DbgNode, unsigned Elt) {
// FIXME: This function should return true, if the field is null or the field
// is indeed a MDNode: return !Fld || isa<MDNode>(Fld).
- Value *Fld = getField(DbgNode, Elt);
+ Metadata *Fld = getField(DbgNode, Elt);
if (Fld && isa<MDString>(Fld) && !cast<MDString>(Fld)->getString().empty())
return false;
return true;
/// \brief Check if a field at position Elt of a MDNode is a MDString.
static bool fieldIsMDString(const MDNode *DbgNode, unsigned Elt) {
- Value *Fld = getField(DbgNode, Elt);
+ Metadata *Fld = getField(DbgNode, Elt);
return !Fld || isa<MDString>(Fld);
}
// If a DISubprogram has an llvm::Function*, then scope chains from all
// instructions within the function should lead to this DISubprogram.
if (auto *F = getFunction()) {
- LLVMContext &Ctxt = F->getContext();
for (auto &BB : *F) {
for (auto &I : BB) {
DebugLoc DL = I.getDebugLoc();
MDNode *Scope = nullptr;
MDNode *IA = nullptr;
// walk the inlined-at scopes
- while (DL.getScopeAndInlinedAt(Scope, IA, F->getContext()), IA)
+ while ((IA = DL.getInlinedAt()))
DL = DebugLoc::getFromDILocation(IA);
- DL.getScopeAndInlinedAt(Scope, IA, Ctxt);
+ DL.getScopeAndInlinedAt(Scope, IA);
assert(!IA);
while (!DIDescriptor(Scope).isSubprogram()) {
DILexicalBlockFile D(Scope);
Scope = D.isLexicalBlockFile()
? D.getScope()
- : DebugLoc::getFromDILexicalBlock(Scope).getScope(Ctxt);
+ : DebugLoc::getFromDILexicalBlock(Scope).getScope();
}
if (!DISubprogram(Scope).describes(F))
return false;
static void VerifySubsetOf(const MDNode *LHS, const MDNode *RHS) {
for (unsigned i = 0; i != LHS->getNumOperands(); ++i) {
// Skip the 'empty' list (that's a single i32 0, rather than truly empty).
- if (i == 0 && isa<ConstantInt>(LHS->getOperand(i)))
+ if (i == 0 && mdconst::hasa<ConstantInt>(LHS->getOperand(i)))
continue;
const MDNode *E = cast<MDNode>(LHS->getOperand(i));
bool found = false;
#endif
void DICompositeType::setArraysHelper(MDNode *Elements, MDNode *TParams) {
- TrackingVH<MDNode> N(*this);
+ TrackingMDNodeRef N(*this);
if (Elements) {
#ifndef NDEBUG
// Check that the new list of members contains all the old members as well.
}
void DICompositeType::setContainingType(DICompositeType ContainingType) {
- TrackingVH<MDNode> N(*this);
+ TrackingMDNodeRef N(*this);
N->replaceOperandWith(5, ContainingType.getRef());
DbgNode = N;
}
return DIArray(getNodeField(DbgNode, 8));
}
-Value *DITemplateValueParameter::getValue() const {
- return getField(DbgNode, 3);
+Metadata *DITemplateValueParameter::getValue() const {
+ return DbgNode->getOperand(3);
}
DIScopeRef DIScope::getContext() const {
DILocation DILocation::copyWithNewScope(LLVMContext &Ctx,
DILexicalBlockFile NewScope) {
- SmallVector<Value *, 10> Elts;
+ SmallVector<Metadata *, 10> Elts;
assert(Verify());
for (unsigned I = 0; I < DbgNode->getNumOperands(); ++I) {
if (I != 2)
return cleanseInlinedVariable(DV, VMContext);
// Insert inlined scope.
- SmallVector<Value *, 8> Elts;
+ SmallVector<Metadata *, 8> Elts;
for (unsigned I = 0, E = DIVariableInlinedAtIndex; I != E; ++I)
Elts.push_back(DV->getOperand(I));
Elts.push_back(InlinedScope);
return DIVariable(DV);
// Remove inlined scope.
- SmallVector<Value *, 8> Elts;
+ SmallVector<Metadata *, 8> Elts;
for (unsigned I = 0, E = DIVariableInlinedAtIndex; I != E; ++I)
Elts.push_back(DV->getOperand(I));
if (Inst == BB.end())
continue;
DebugLoc DLoc = Inst->getDebugLoc();
- const MDNode *Scope = DLoc.getScopeNode(F->getParent()->getContext());
+ const MDNode *Scope = DLoc.getScopeNode();
DISubprogram Subprogram = getDISubprogram(Scope);
return Subprogram.describes(F) ? Subprogram : DISubprogram();
}
}
unsigned llvm::getDebugMetadataVersionFromModule(const Module &M) {
- Value *Val = M.getModuleFlag("Debug Info Version");
- if (!Val)
- return 0;
- return cast<ConstantInt>(Val)->getZExtValue();
+ if (auto *Val = mdconst::extract_or_null<ConstantInt>(
+ M.getModuleFlag("Debug Info Version")))
+ return Val->getZExtValue();
+ return 0;
}
llvm::DenseMap<const llvm::Function *, llvm::DISubprogram>
// DebugLoc Implementation
//===----------------------------------------------------------------------===//
-MDNode *DebugLoc::getScope(const LLVMContext &Ctx) const {
- if (ScopeIdx == 0) return nullptr;
-
- if (ScopeIdx > 0) {
- // Positive ScopeIdx is an index into ScopeRecords, which has no inlined-at
- // position specified.
- assert(unsigned(ScopeIdx) <= Ctx.pImpl->ScopeRecords.size() &&
- "Invalid ScopeIdx!");
- return Ctx.pImpl->ScopeRecords[ScopeIdx-1].get();
- }
-
- // Otherwise, the index is in the ScopeInlinedAtRecords array.
- assert(unsigned(-ScopeIdx) <= Ctx.pImpl->ScopeInlinedAtRecords.size() &&
- "Invalid ScopeIdx");
- return Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].first.get();
-}
+unsigned DebugLoc::getLine() const { return DILocation(Loc).getLineNumber(); }
+unsigned DebugLoc::getCol() const { return DILocation(Loc).getColumnNumber(); }
+
+MDNode *DebugLoc::getScope() const { return DILocation(Loc).getScope(); }
-MDNode *DebugLoc::getInlinedAt(const LLVMContext &Ctx) const {
- // Positive ScopeIdx is an index into ScopeRecords, which has no inlined-at
- // position specified. Zero is invalid.
- if (ScopeIdx >= 0) return nullptr;
-
- // Otherwise, the index is in the ScopeInlinedAtRecords array.
- assert(unsigned(-ScopeIdx) <= Ctx.pImpl->ScopeInlinedAtRecords.size() &&
- "Invalid ScopeIdx");
- return Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].second.get();
+MDNode *DebugLoc::getInlinedAt() const {
+ return DILocation(Loc).getOrigLocation();
}
/// Return both the Scope and the InlinedAt values.
-void DebugLoc::getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA,
- const LLVMContext &Ctx) const {
- if (ScopeIdx == 0) {
- Scope = IA = nullptr;
- return;
- }
-
- if (ScopeIdx > 0) {
- // Positive ScopeIdx is an index into ScopeRecords, which has no inlined-at
- // position specified.
- assert(unsigned(ScopeIdx) <= Ctx.pImpl->ScopeRecords.size() &&
- "Invalid ScopeIdx!");
- Scope = Ctx.pImpl->ScopeRecords[ScopeIdx-1].get();
- IA = nullptr;
- return;
- }
-
- // Otherwise, the index is in the ScopeInlinedAtRecords array.
- assert(unsigned(-ScopeIdx) <= Ctx.pImpl->ScopeInlinedAtRecords.size() &&
- "Invalid ScopeIdx");
- Scope = Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].first.get();
- IA = Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].second.get();
+void DebugLoc::getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA) const {
+ Scope = getScope();
+ IA = getInlinedAt();
}
-MDNode *DebugLoc::getScopeNode(const LLVMContext &Ctx) const {
- if (MDNode *InlinedAt = getInlinedAt(Ctx))
- return DebugLoc::getFromDILocation(InlinedAt).getScopeNode(Ctx);
- return getScope(Ctx);
+MDNode *DebugLoc::getScopeNode() const {
+ if (MDNode *InlinedAt = getInlinedAt())
+ return DebugLoc::getFromDILocation(InlinedAt).getScopeNode();
+ return getScope();
}
-DebugLoc DebugLoc::getFnDebugLoc(const LLVMContext &Ctx) const {
- const MDNode *Scope = getScopeNode(Ctx);
+DebugLoc DebugLoc::getFnDebugLoc() const {
+ const MDNode *Scope = getScopeNode();
DISubprogram SP = getDISubprogram(Scope);
if (SP.isSubprogram())
return DebugLoc::get(SP.getScopeLineNumber(), 0, SP);
DebugLoc DebugLoc::get(unsigned Line, unsigned Col,
MDNode *Scope, MDNode *InlinedAt) {
- DebugLoc Result;
-
// If no scope is available, this is an unknown location.
- if (!Scope) return Result;
+ if (!Scope)
+ return DebugLoc();
// Saturate line and col to "unknown".
+ // FIXME: Allow 16-bits for columns.
if (Col > 255) Col = 0;
if (Line >= (1 << 24)) Line = 0;
- Result.LineCol = Line | (Col << 24);
-
- LLVMContext &Ctx = Scope->getContext();
-
- // If there is no inlined-at location, use the ScopeRecords array.
- if (!InlinedAt)
- Result.ScopeIdx = Ctx.pImpl->getOrAddScopeRecordIdxEntry(Scope, 0);
- else
- Result.ScopeIdx = Ctx.pImpl->getOrAddScopeInlinedAtIdxEntry(Scope,
- InlinedAt, 0);
- return Result;
+ LLVMContext &Context = Scope->getContext();
+ Type *Int32 = Type::getInt32Ty(Context);
+ Metadata *Elts[] = {ConstantAsMetadata::get(ConstantInt::get(Int32, Line)),
+ ConstantAsMetadata::get(ConstantInt::get(Int32, Col)),
+ Scope, InlinedAt};
+ return getFromDILocation(MDNode::get(Context, Elts));
}
/// getAsMDNode - This method converts the compressed DebugLoc node into a
/// DILocation-compatible MDNode.
-MDNode *DebugLoc::getAsMDNode(const LLVMContext &Ctx) const {
- if (isUnknown()) return nullptr;
-
- MDNode *Scope, *IA;
- getScopeAndInlinedAt(Scope, IA, Ctx);
- assert(Scope && "If scope is null, this should be isUnknown()");
-
- LLVMContext &Ctx2 = Scope->getContext();
- Type *Int32 = Type::getInt32Ty(Ctx2);
- Value *Elts[] = {
- ConstantInt::get(Int32, getLine()), ConstantInt::get(Int32, getCol()),
- Scope, IA
- };
- return MDNode::get(Ctx2, Elts);
-}
+MDNode *DebugLoc::getAsMDNode() const { return Loc; }
/// getFromDILocation - Translate the DILocation quad into a DebugLoc.
DebugLoc DebugLoc::getFromDILocation(MDNode *N) {
- DILocation Loc(N);
- MDNode *Scope = Loc.getScope();
- if (!Scope) return DebugLoc();
- return get(Loc.getLineNumber(), Loc.getColumnNumber(), Scope,
- Loc.getOrigLocation());
+ DebugLoc Loc;
+ Loc.Loc.reset(N);
+ return Loc;
}
/// getFromDILexicalBlock - Translate the DILexicalBlock into a DebugLoc.
nullptr);
}
-void DebugLoc::dump(const LLVMContext &Ctx) const {
+void DebugLoc::dump() const {
#ifndef NDEBUG
if (!isUnknown()) {
dbgs() << getLine();
if (getCol() != 0)
dbgs() << ',' << getCol();
- DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(getInlinedAt(Ctx));
+ DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(getInlinedAt());
if (!InlinedAtDL.isUnknown()) {
dbgs() << " @ ";
- InlinedAtDL.dump(Ctx);
+ InlinedAtDL.dump();
} else
dbgs() << "\n";
}
#endif
}
-void DebugLoc::print(const LLVMContext &Ctx, raw_ostream &OS) const {
+void DebugLoc::print(raw_ostream &OS) const {
if (!isUnknown()) {
// Print source line info.
- DIScope Scope(getScope(Ctx));
+ DIScope Scope(getScope());
assert((!Scope || Scope.isScope()) &&
"Scope of a DebugLoc should be null or a DIScope.");
if (Scope)
OS << ':' << getLine();
if (getCol() != 0)
OS << ':' << getCol();
- DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(getInlinedAt(Ctx));
+ DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(getInlinedAt());
if (!InlinedAtDL.isUnknown()) {
OS << " @[ ";
- InlinedAtDL.print(Ctx, OS);
+ InlinedAtDL.print(OS);
OS << " ]";
}
}
}
-
-//===----------------------------------------------------------------------===//
-// DenseMap specialization
-//===----------------------------------------------------------------------===//
-
-unsigned DenseMapInfo<DebugLoc>::getHashValue(const DebugLoc &Key) {
- return static_cast<unsigned>(hash_combine(Key.LineCol, Key.ScopeIdx));
-}
-
-//===----------------------------------------------------------------------===//
-// LLVMContextImpl Implementation
-//===----------------------------------------------------------------------===//
-
-int LLVMContextImpl::getOrAddScopeRecordIdxEntry(MDNode *Scope,
- int ExistingIdx) {
- // If we already have an entry for this scope, return it.
- int &Idx = ScopeRecordIdx[Scope];
- if (Idx) return Idx;
-
- // If we don't have an entry, but ExistingIdx is specified, use it.
- if (ExistingIdx)
- return Idx = ExistingIdx;
-
- // Otherwise add a new entry.
-
- // Start out ScopeRecords with a minimal reasonable size to avoid
- // excessive reallocation starting out.
- if (ScopeRecords.empty())
- ScopeRecords.reserve(128);
-
- // Index is biased by 1 for index.
- Idx = ScopeRecords.size()+1;
- ScopeRecords.push_back(DebugRecVH(Scope, this, Idx));
- return Idx;
-}
-
-int LLVMContextImpl::getOrAddScopeInlinedAtIdxEntry(MDNode *Scope, MDNode *IA,
- int ExistingIdx) {
- // If we already have an entry, return it.
- int &Idx = ScopeInlinedAtIdx[std::make_pair(Scope, IA)];
- if (Idx) return Idx;
-
- // If we don't have an entry, but ExistingIdx is specified, use it.
- if (ExistingIdx)
- return Idx = ExistingIdx;
-
- // Start out ScopeInlinedAtRecords with a minimal reasonable size to avoid
- // excessive reallocation starting out.
- if (ScopeInlinedAtRecords.empty())
- ScopeInlinedAtRecords.reserve(128);
-
- // Index is biased by 1 and negated.
- Idx = -ScopeInlinedAtRecords.size()-1;
- ScopeInlinedAtRecords.push_back(std::make_pair(DebugRecVH(Scope, this, Idx),
- DebugRecVH(IA, this, Idx)));
- return Idx;
-}
-
-
-//===----------------------------------------------------------------------===//
-// DebugRecVH Implementation
-//===----------------------------------------------------------------------===//
-
-/// deleted - The MDNode this is pointing to got deleted, so this pointer needs
-/// to drop to null and we need remove our entry from the DenseMap.
-void DebugRecVH::deleted() {
- // If this is a non-canonical reference, just drop the value to null, we know
- // it doesn't have a map entry.
- if (Idx == 0) {
- setValPtr(nullptr);
- return;
- }
-
- MDNode *Cur = get();
-
- // If the index is positive, it is an entry in ScopeRecords.
- if (Idx > 0) {
- assert(Ctx->ScopeRecordIdx[Cur] == Idx && "Mapping out of date!");
- Ctx->ScopeRecordIdx.erase(Cur);
- // Reset this VH to null and we're done.
- setValPtr(nullptr);
- Idx = 0;
- return;
- }
-
- // Otherwise, it is an entry in ScopeInlinedAtRecords, we don't know if it
- // is the scope or the inlined-at record entry.
- assert(unsigned(-Idx-1) < Ctx->ScopeInlinedAtRecords.size());
- std::pair<DebugRecVH, DebugRecVH> &Entry = Ctx->ScopeInlinedAtRecords[-Idx-1];
- assert((this == &Entry.first || this == &Entry.second) &&
- "Mapping out of date!");
-
- MDNode *OldScope = Entry.first.get();
- MDNode *OldInlinedAt = Entry.second.get();
- assert(OldScope && OldInlinedAt &&
- "Entry should be non-canonical if either val dropped to null");
-
- // Otherwise, we do have an entry in it, nuke it and we're done.
- assert(Ctx->ScopeInlinedAtIdx[std::make_pair(OldScope, OldInlinedAt)] == Idx&&
- "Mapping out of date");
- Ctx->ScopeInlinedAtIdx.erase(std::make_pair(OldScope, OldInlinedAt));
-
- // Reset this VH to null. Drop both 'Idx' values to null to indicate that
- // we're in non-canonical form now.
- setValPtr(nullptr);
- Entry.first.Idx = Entry.second.Idx = 0;
-}
-
-void DebugRecVH::allUsesReplacedWith(Value *NewVa) {
- // If being replaced with a non-mdnode value (e.g. undef) handle this as if
- // the mdnode got deleted.
- MDNode *NewVal = dyn_cast<MDNode>(NewVa);
- if (!NewVal) return deleted();
-
- // If this is a non-canonical reference, just change it, we know it already
- // doesn't have a map entry.
- if (Idx == 0) {
- setValPtr(NewVa);
- return;
- }
-
- MDNode *OldVal = get();
- assert(OldVal != NewVa && "Node replaced with self?");
-
- // If the index is positive, it is an entry in ScopeRecords.
- if (Idx > 0) {
- assert(Ctx->ScopeRecordIdx[OldVal] == Idx && "Mapping out of date!");
- Ctx->ScopeRecordIdx.erase(OldVal);
- setValPtr(NewVal);
-
- int NewEntry = Ctx->getOrAddScopeRecordIdxEntry(NewVal, Idx);
-
- // If NewVal already has an entry, this becomes a non-canonical reference,
- // just drop Idx to 0 to signify this.
- if (NewEntry != Idx)
- Idx = 0;
- return;
- }
-
- // Otherwise, it is an entry in ScopeInlinedAtRecords, we don't know if it
- // is the scope or the inlined-at record entry.
- assert(unsigned(-Idx-1) < Ctx->ScopeInlinedAtRecords.size());
- std::pair<DebugRecVH, DebugRecVH> &Entry = Ctx->ScopeInlinedAtRecords[-Idx-1];
- assert((this == &Entry.first || this == &Entry.second) &&
- "Mapping out of date!");
-
- MDNode *OldScope = Entry.first.get();
- MDNode *OldInlinedAt = Entry.second.get();
- assert(OldScope && OldInlinedAt &&
- "Entry should be non-canonical if either val dropped to null");
-
- // Otherwise, we do have an entry in it, nuke it and we're done.
- assert(Ctx->ScopeInlinedAtIdx[std::make_pair(OldScope, OldInlinedAt)] == Idx&&
- "Mapping out of date");
- Ctx->ScopeInlinedAtIdx.erase(std::make_pair(OldScope, OldInlinedAt));
-
- // Reset this VH to the new value.
- setValPtr(NewVal);
-
- int NewIdx = Ctx->getOrAddScopeInlinedAtIdxEntry(Entry.first.get(),
- Entry.second.get(), Idx);
- // If NewVal already has an entry, this becomes a non-canonical reference,
- // just drop Idx to 0 to signify this.
- if (NewIdx != Idx) {
- std::pair<DebugRecVH, DebugRecVH> &Entry=Ctx->ScopeInlinedAtRecords[-Idx-1];
- Entry.first.Idx = Entry.second.Idx = 0;
- }
-}
Instr(&I) {
if (const MDNode *SrcLoc = I.getMetadata("srcloc")) {
if (SrcLoc->getNumOperands() != 0)
- if (const ConstantInt *CI = dyn_cast<ConstantInt>(SrcLoc->getOperand(0)))
+ if (const auto *CI =
+ mdconst::dyn_extract<ConstantInt>(SrcLoc->getOperand(0)))
LocCookie = CI->getZExtValue();
}
}
return;
// The first operand is the name. Fetch them backwards and build a new one.
- Value *Ops[] = {
- ProfileData->getOperand(0),
- ProfileData->getOperand(2),
- ProfileData->getOperand(1)
- };
+ Metadata *Ops[] = {ProfileData->getOperand(0), ProfileData->getOperand(2),
+ ProfileData->getOperand(1)};
setMetadata(LLVMContext::MD_prof,
MDNode::get(ProfileData->getContext(), Ops));
}
cast<Instruction>(this)->getMetadata(LLVMContext::MD_fpmath);
if (!MD)
return 0.0;
- ConstantFP *Accuracy = cast<ConstantFP>(MD->getOperand(0));
+ ConstantFP *Accuracy = mdconst::extract<ConstantFP>(MD->getOperand(0));
return Accuracy->getValueAPF().convertToFloat();
}
return dyn_cast<GlobalVariable>(C);
}
+static Value *getValueImpl(Value *Op) {
+ auto *MD = cast<MetadataAsValue>(Op)->getMetadata();
+ if (auto *V = dyn_cast<ValueAsMetadata>(MD))
+ return V->getValue();
+
+ // When the value goes to null, it gets replaced by an empty MDNode.
+ assert(!cast<MDNode>(MD)->getNumOperands() && "Expected an empty MDNode");
+ return nullptr;
+}
+
//===----------------------------------------------------------------------===//
/// DbgDeclareInst - This represents the llvm.dbg.declare instruction.
///
Value *DbgDeclareInst::getAddress() const {
- if (MDNode* MD = cast_or_null<MDNode>(getArgOperand(0)))
- return MD->getOperand(0);
- else
+ if (!getArgOperand(0))
return nullptr;
+
+ return getValueImpl(getArgOperand(0));
}
//===----------------------------------------------------------------------===//
///
const Value *DbgValueInst::getValue() const {
- return cast<MDNode>(getArgOperand(0))->getOperand(0);
+ return const_cast<DbgValueInst *>(this)->getValue();
}
-Value *DbgValueInst::getValue() {
- return cast<MDNode>(getArgOperand(0))->getOperand(0);
-}
+Value *DbgValueInst::getValue() { return getValueImpl(getArgOperand(0)); }
delete &*Elem;
}
+ // Destroy MetadataAsValues.
+ {
+ SmallVector<MetadataAsValue *, 8> MDVs;
+ MDVs.reserve(MetadataAsValues.size());
+ for (auto &Pair : MetadataAsValues)
+ MDVs.push_back(Pair.second);
+ MetadataAsValues.clear();
+ for (auto *V : MDVs)
+ delete V;
+ }
+
+ // Destroy ValuesAsMetadata.
+ for (auto &Pair : ValuesAsMetadata)
+ delete Pair.second;
+
// Destroy MDNodes. ~MDNode can move and remove nodes between the MDNodeSet
// and the NonUniquedMDNodes sets, so copy the values out first.
SmallVector<GenericMDNode *, 8> MDNodes;
/// the operands.
struct GenericMDNodeInfo {
struct KeyTy {
- ArrayRef<Value *> Ops;
+ ArrayRef<Metadata *> RawOps;
+ ArrayRef<MDOperand> Ops;
unsigned Hash;
- KeyTy(ArrayRef<Value *> Ops)
- : Ops(Ops), Hash(hash_combine_range(Ops.begin(), Ops.end())) {}
+ KeyTy(ArrayRef<Metadata *> Ops)
+ : RawOps(Ops), Hash(hash_combine_range(Ops.begin(), Ops.end())) {}
- KeyTy(GenericMDNode *N, SmallVectorImpl<Value *> &Storage) {
- Storage.resize(N->getNumOperands());
- for (unsigned I = 0, E = N->getNumOperands(); I != E; ++I)
- Storage[I] = N->getOperand(I);
- Ops = Storage;
- Hash = hash_combine_range(Ops.begin(), Ops.end());
- }
+ KeyTy(GenericMDNode *N)
+ : Ops(N->op_begin(), N->op_end()), Hash(N->getHash()) {}
bool operator==(const GenericMDNode *RHS) const {
if (RHS == getEmptyKey() || RHS == getTombstoneKey())
return false;
- if (Hash != RHS->getHash() || Ops.size() != RHS->getNumOperands())
+ if (Hash != RHS->getHash())
return false;
- for (unsigned I = 0, E = Ops.size(); I != E; ++I)
- if (Ops[I] != RHS->getOperand(I))
- return false;
- return true;
+ assert((RawOps.empty() || Ops.empty()) && "Two sets of operands?");
+ return RawOps.empty() ? compareOps(Ops, RHS) : compareOps(RawOps, RHS);
+ }
+ template <class T>
+ static bool compareOps(ArrayRef<T> Ops, const GenericMDNode *RHS) {
+ if (Ops.size() != RHS->getNumOperands())
+ return false;
+ return std::equal(Ops.begin(), Ops.end(), RHS->op_begin());
}
};
static inline GenericMDNode *getEmptyKey() {
}
};
-/// DebugRecVH - This is a CallbackVH used to keep the Scope -> index maps
-/// up to date as MDNodes mutate. This class is implemented in DebugLoc.cpp.
-class DebugRecVH : public CallbackVH {
- /// Ctx - This is the LLVM Context being referenced.
- LLVMContextImpl *Ctx;
-
- /// Idx - The index into either ScopeRecordIdx or ScopeInlinedAtRecords that
- /// this reference lives in. If this is zero, then it represents a
- /// non-canonical entry that has no DenseMap value. This can happen due to
- /// RAUW.
- int Idx;
-public:
- DebugRecVH(MDNode *n, LLVMContextImpl *ctx, int idx)
- : CallbackVH(n), Ctx(ctx), Idx(idx) {}
-
- MDNode *get() const {
- return cast_or_null<MDNode>(getValPtr());
- }
-
- void deleted() override;
- void allUsesReplacedWith(Value *VNew) override;
-};
-
class LLVMContextImpl {
public:
/// OwnedModules - The set of modules instantiated in this context, and which
FoldingSet<AttributeSetNode> AttrsSetNodes;
StringMap<MDString> MDStringCache;
+ DenseMap<Value *, ValueAsMetadata *> ValuesAsMetadata;
+ DenseMap<Metadata *, MetadataAsValue *> MetadataAsValues;
DenseSet<GenericMDNode *, GenericMDNodeInfo> MDNodeSet;
ConstantInt *TheFalseVal;
LeakDetectorImpl<Value> LLVMObjects;
-
+ LeakDetectorImpl<Metadata> LLVMMDObjects;
+
// Basic type instances.
Type VoidTy, LabelTy, HalfTy, FloatTy, DoubleTy, MetadataTy;
Type X86_FP80Ty, FP128Ty, PPC_FP128Ty, X86_MMXTy;
/// CustomMDKindNames - Map to hold the metadata string to ID mapping.
StringMap<unsigned> CustomMDKindNames;
-
- typedef std::pair<unsigned, TrackingVH<MDNode> > MDPairTy;
+
+ typedef std::pair<unsigned, TrackingMDNodeRef> MDPairTy;
typedef SmallVector<MDPairTy, 2> MDMapTy;
/// MetadataStore - Collection of per-instruction metadata used in this
/// context.
DenseMap<const Instruction *, MDMapTy> MetadataStore;
- /// ScopeRecordIdx - This is the index in ScopeRecords for an MDNode scope
- /// entry with no "inlined at" element.
- DenseMap<MDNode*, int> ScopeRecordIdx;
-
- /// ScopeRecords - These are the actual mdnodes (in a value handle) for an
- /// index. The ValueHandle ensures that ScopeRecordIdx stays up to date if
- /// the MDNode is RAUW'd.
- std::vector<DebugRecVH> ScopeRecords;
-
- /// ScopeInlinedAtIdx - This is the index in ScopeInlinedAtRecords for an
- /// scope/inlined-at pair.
- DenseMap<std::pair<MDNode*, MDNode*>, int> ScopeInlinedAtIdx;
-
- /// ScopeInlinedAtRecords - These are the actual mdnodes (in value handles)
- /// for an index. The ValueHandle ensures that ScopeINlinedAtIdx stays up
- /// to date.
- std::vector<std::pair<DebugRecVH, DebugRecVH> > ScopeInlinedAtRecords;
-
/// DiscriminatorTable - This table maps file:line locations to an
/// integer representing the next DWARF path discriminator to assign to
/// instructions in different blocks at the same location.
return MDString::get(Context, Str);
}
+ConstantAsMetadata *MDBuilder::createConstant(Constant *C) {
+ return ConstantAsMetadata::get(C);
+}
+
MDNode *MDBuilder::createFPMath(float Accuracy) {
if (Accuracy == 0.0)
return nullptr;
assert(Accuracy > 0.0 && "Invalid fpmath accuracy!");
- Value *Op = ConstantFP::get(Type::getFloatTy(Context), Accuracy);
+ auto *Op =
+ createConstant(ConstantFP::get(Type::getFloatTy(Context), Accuracy));
return MDNode::get(Context, Op);
}
MDNode *MDBuilder::createBranchWeights(ArrayRef<uint32_t> Weights) {
assert(Weights.size() >= 2 && "Need at least two branch weights!");
- SmallVector<Value *, 4> Vals(Weights.size() + 1);
+ SmallVector<Metadata *, 4> Vals(Weights.size() + 1);
Vals[0] = createString("branch_weights");
Type *Int32Ty = Type::getInt32Ty(Context);
for (unsigned i = 0, e = Weights.size(); i != e; ++i)
- Vals[i + 1] = ConstantInt::get(Int32Ty, Weights[i]);
+ Vals[i + 1] = createConstant(ConstantInt::get(Int32Ty, Weights[i]));
return MDNode::get(Context, Vals);
}
// Return the range [Lo, Hi).
Type *Ty = IntegerType::get(Context, Lo.getBitWidth());
- Value *Range[2] = {ConstantInt::get(Ty, Lo), ConstantInt::get(Ty, Hi)};
+ Metadata *Range[2] = {createConstant(ConstantInt::get(Ty, Lo)),
+ createConstant(ConstantInt::get(Ty, Hi))};
return MDNode::get(Context, Range);
}
// To ensure uniqueness the root node is self-referential.
MDNode *Dummy = MDNode::getTemporary(Context, None);
- SmallVector<Value *, 3> Args(1, Dummy);
+ SmallVector<Metadata *, 3> Args(1, Dummy);
if (Extra)
Args.push_back(Extra);
if (!Name.empty())
bool isConstant) {
if (isConstant) {
Constant *Flags = ConstantInt::get(Type::getInt64Ty(Context), 1);
- Value *Ops[3] = {createString(Name), Parent, Flags};
+ Metadata *Ops[3] = {createString(Name), Parent, createConstant(Flags)};
return MDNode::get(Context, Ops);
} else {
- Value *Ops[2] = {createString(Name), Parent};
+ Metadata *Ops[2] = {createString(Name), Parent};
return MDNode::get(Context, Ops);
}
}
}
MDNode *MDBuilder::createAliasScope(StringRef Name, MDNode *Domain) {
- Value *Ops[2] = { createString(Name), Domain };
+ Metadata *Ops[2] = {createString(Name), Domain};
return MDNode::get(Context, Ops);
}
/// \brief Return metadata for a tbaa.struct node with the given
/// struct field descriptions.
MDNode *MDBuilder::createTBAAStructNode(ArrayRef<TBAAStructField> Fields) {
- SmallVector<Value *, 4> Vals(Fields.size() * 3);
+ SmallVector<Metadata *, 4> Vals(Fields.size() * 3);
Type *Int64 = Type::getInt64Ty(Context);
for (unsigned i = 0, e = Fields.size(); i != e; ++i) {
- Vals[i * 3 + 0] = ConstantInt::get(Int64, Fields[i].Offset);
- Vals[i * 3 + 1] = ConstantInt::get(Int64, Fields[i].Size);
+ Vals[i * 3 + 0] = createConstant(ConstantInt::get(Int64, Fields[i].Offset));
+ Vals[i * 3 + 1] = createConstant(ConstantInt::get(Int64, Fields[i].Size));
Vals[i * 3 + 2] = Fields[i].TBAA;
}
return MDNode::get(Context, Vals);
/// with the given name, a list of pairs (offset, field type in the type DAG).
MDNode *MDBuilder::createTBAAStructTypeNode(
StringRef Name, ArrayRef<std::pair<MDNode *, uint64_t>> Fields) {
- SmallVector<Value *, 4> Ops(Fields.size() * 2 + 1);
+ SmallVector<Metadata *, 4> Ops(Fields.size() * 2 + 1);
Type *Int64 = Type::getInt64Ty(Context);
Ops[0] = createString(Name);
for (unsigned i = 0, e = Fields.size(); i != e; ++i) {
Ops[i * 2 + 1] = Fields[i].first;
- Ops[i * 2 + 2] = ConstantInt::get(Int64, Fields[i].second);
+ Ops[i * 2 + 2] = createConstant(ConstantInt::get(Int64, Fields[i].second));
}
return MDNode::get(Context, Ops);
}
MDNode *MDBuilder::createTBAAScalarTypeNode(StringRef Name, MDNode *Parent,
uint64_t Offset) {
ConstantInt *Off = ConstantInt::get(Type::getInt64Ty(Context), Offset);
- Value *Ops[3] = {createString(Name), Parent, Off};
+ Metadata *Ops[3] = {createString(Name), Parent, createConstant(Off)};
return MDNode::get(Context, Ops);
}
MDNode *MDBuilder::createTBAAStructTagNode(MDNode *BaseType, MDNode *AccessType,
uint64_t Offset) {
Type *Int64 = Type::getInt64Ty(Context);
- Value *Ops[3] = {BaseType, AccessType, ConstantInt::get(Int64, Offset)};
+ Metadata *Ops[3] = {BaseType, AccessType,
+ createConstant(ConstantInt::get(Int64, Offset))};
return MDNode::get(Context, Ops);
}
using namespace llvm;
-Metadata::Metadata(LLVMContext &Context, unsigned ID)
- : Value(Type::getMetadataTy(Context), ID) {}
+MetadataAsValue::MetadataAsValue(Type *Ty, Metadata *MD)
+ : Value(Ty, MetadataAsValueVal), MD(MD) {
+ track();
+}
-//===----------------------------------------------------------------------===//
-// MDString implementation.
-//
+MetadataAsValue::~MetadataAsValue() {
+ getType()->getContext().pImpl->MetadataAsValues.erase(MD);
+ untrack();
+}
-void MDString::anchor() { }
+/// \brief Canonicalize metadata arguments to intrinsics.
+///
+/// To support bitcode upgrades (and assembly semantic sugar) for \a
+/// MetadataAsValue, we need to canonicalize certain metadata.
+///
+/// - nullptr is replaced by an empty MDNode.
+/// - An MDNode with a single null operand is replaced by an empty MDNode.
+/// - An MDNode whose only operand is a \a ConstantAsMetadata gets skipped.
+///
+/// This maintains readability of bitcode from when metadata was a type of
+/// value, and these bridges were unnecessary.
+static Metadata *canonicalizeMetadataForValue(LLVMContext &Context,
+ Metadata *MD) {
+ if (!MD)
+ // !{}
+ return MDNode::get(Context, None);
+
+ // Return early if this isn't a single-operand MDNode.
+ auto *N = dyn_cast<MDNode>(MD);
+ if (!N || N->getNumOperands() != 1)
+ return MD;
+
+ if (!N->getOperand(0))
+ // !{}
+ return MDNode::get(Context, None);
+
+ if (auto *C = dyn_cast<ConstantAsMetadata>(N->getOperand(0)))
+ // Look through the MDNode.
+ return C;
+
+ return MD;
+}
+
+MetadataAsValue *MetadataAsValue::get(LLVMContext &Context, Metadata *MD) {
+ MD = canonicalizeMetadataForValue(Context, MD);
+ auto *&Entry = Context.pImpl->MetadataAsValues[MD];
+ if (!Entry)
+ Entry = new MetadataAsValue(Type::getMetadataTy(Context), MD);
+ return Entry;
+}
+
+MetadataAsValue *MetadataAsValue::getIfExists(LLVMContext &Context,
+ Metadata *MD) {
+ MD = canonicalizeMetadataForValue(Context, MD);
+ auto &Store = Context.pImpl->MetadataAsValues;
+ auto I = Store.find(MD);
+ return I == Store.end() ? nullptr : I->second;
+}
+
+void MetadataAsValue::handleChangedMetadata(Metadata *MD) {
+ LLVMContext &Context = getContext();
+ MD = canonicalizeMetadataForValue(Context, MD);
+ auto &Store = Context.pImpl->MetadataAsValues;
+
+ // Stop tracking the old metadata.
+ Store.erase(this->MD);
+ untrack();
+ this->MD = nullptr;
+
+ // Start tracking MD, or RAUW if necessary.
+ auto *&Entry = Store[MD];
+ if (Entry) {
+ replaceAllUsesWith(Entry);
+ delete this;
+ return;
+ }
-MDString *MDString::get(LLVMContext &Context, StringRef Str) {
- auto &Store = Context.pImpl->MDStringCache;
- auto I = Store.find(Str);
- if (I != Store.end())
- return &I->second;
+ this->MD = MD;
+ track();
+ Entry = this;
+}
- auto *Entry =
- StringMapEntry<MDString>::Create(Str, Store.getAllocator(), Context);
- bool WasInserted = Store.insert(Entry);
+void MetadataAsValue::track() {
+ if (MD)
+ MetadataTracking::track(&MD, *MD, *this);
+}
+
+void MetadataAsValue::untrack() {
+ if (MD)
+ MetadataTracking::untrack(MD);
+}
+
+void ReplaceableMetadataImpl::addRef(void *Ref, OwnerTy Owner) {
+ bool WasInserted = UseMap.insert(std::make_pair(Ref, Owner)).second;
(void)WasInserted;
- assert(WasInserted && "Expected entry to be inserted");
- Entry->second.Entry = Entry;
- return &Entry->second;
+ assert(WasInserted && "Expected to add a reference");
}
-StringRef MDString::getString() const {
- assert(Entry && "Expected to find string map entry");
- return Entry->first();
+void ReplaceableMetadataImpl::dropRef(void *Ref) {
+ bool WasErased = UseMap.erase(Ref);
+ (void)WasErased;
+ assert(WasErased && "Expected to drop a reference");
}
-//===----------------------------------------------------------------------===//
-// MDNodeOperand implementation.
-//
+void ReplaceableMetadataImpl::moveRef(void *Ref, void *New,
+ const Metadata &MD) {
+ auto I = UseMap.find(Ref);
+ assert(I != UseMap.end() && "Expected to move a reference");
+ OwnerTy Owner = I->second;
+ UseMap.erase(I);
+ addRef(New, Owner);
-// Use CallbackVH to hold MDNode operands.
-namespace llvm {
-class MDNodeOperand : public CallbackVH {
- MDNode *getParent() {
- MDNodeOperand *Cur = this;
+ // Check that the references are direct if there's no owner.
+ (void)MD;
+ assert((Owner || *static_cast<Metadata **>(Ref) == &MD) &&
+ "Reference without owner must be direct");
+ assert((Owner || *static_cast<Metadata **>(New) == &MD) &&
+ "Reference without owner must be direct");
+}
+
+void ReplaceableMetadataImpl::replaceAllUsesWith(Metadata *MD) {
+ assert(!(MD && isa<MDNodeFwdDecl>(MD)) && "Expected non-temp node");
+
+ if (UseMap.empty())
+ return;
- while (Cur->getValPtrInt() != 1)
- ++Cur;
+ // Copy out uses since UseMap will get touched below.
+ SmallVector<std::pair<void *, OwnerTy>, 8> Uses(UseMap.begin(), UseMap.end());
+ for (const auto &Pair : Uses) {
+ if (!Pair.second) {
+ // Update unowned tracking references directly.
+ Metadata *&Ref = *static_cast<Metadata **>(Pair.first);
+ Ref = MD;
+ MetadataTracking::track(Ref);
+ UseMap.erase(Pair.first);
+ continue;
+ }
+
+ // Check for MetadataAsValue.
+ if (Pair.second.is<MetadataAsValue *>()) {
+ Pair.second.get<MetadataAsValue *>()->handleChangedMetadata(MD);
+ continue;
+ }
+
+ // There's a Metadata owner -- dispatch.
+ Metadata *Owner = Pair.second.get<Metadata *>();
+ switch (Owner->getMetadataID()) {
+#define HANDLE_METADATA_LEAF(CLASS) \
+ case Metadata::CLASS##Kind: \
+ cast<CLASS>(Owner)->handleChangedOperand(Pair.first, MD); \
+ continue;
+#include "llvm/IR/Metadata.def"
+ default:
+ llvm_unreachable("Invalid metadata subclass");
+ }
+ }
+ assert(UseMap.empty() && "Expected all uses to be replaced");
+}
+
+void ReplaceableMetadataImpl::resolveAllUses(bool ResolveUsers) {
+ if (UseMap.empty())
+ return;
- assert(Cur->getValPtrInt() == 1 &&
- "Couldn't find the end of the operand list!");
- return reinterpret_cast<MDNode *>(Cur + 1);
+ if (!ResolveUsers) {
+ UseMap.clear();
+ return;
}
-public:
- MDNodeOperand() {}
- virtual ~MDNodeOperand();
+ // Copy out uses since UseMap could get touched below.
+ SmallVector<std::pair<void *, OwnerTy>, 8> Uses(UseMap.begin(), UseMap.end());
+ UseMap.clear();
+ for (const auto &Pair : Uses) {
+ if (!Pair.second)
+ continue;
+ if (Pair.second.is<MetadataAsValue *>())
+ continue;
- void set(Value *V) {
- unsigned IsLast = this->getValPtrInt();
- this->setValPtr(V);
- this->setAsLastOperand(IsLast);
+ // Resolve GenericMDNodes that point at this.
+ auto *Owner = dyn_cast<GenericMDNode>(Pair.second.get<Metadata *>());
+ if (!Owner)
+ continue;
+ if (Owner->isResolved())
+ continue;
+ Owner->decrementUnresolvedOperands();
+ if (!Owner->hasUnresolvedOperands())
+ Owner->resolve();
}
+}
- /// \brief Accessor method to mark the operand as the first in the list.
- void setAsLastOperand(unsigned I) { this->setValPtrInt(I); }
+static Function *getLocalFunction(Value *V) {
+ assert(V && "Expected value");
+ if (auto *A = dyn_cast<Argument>(V))
+ return A->getParent();
+ if (BasicBlock *BB = cast<Instruction>(V)->getParent())
+ return BB->getParent();
+ return nullptr;
+}
- void deleted() override;
- void allUsesReplacedWith(Value *NV) override;
-};
-} // end namespace llvm.
+ValueAsMetadata *ValueAsMetadata::get(Value *V) {
+ assert(V && "Unexpected null Value");
+
+ auto &Context = V->getContext();
+ auto *&Entry = Context.pImpl->ValuesAsMetadata[V];
+ if (!Entry) {
+ assert((isa<Constant>(V) || isa<Argument>(V) || isa<Instruction>(V)) &&
+ "Expected constant or function-local value");
+ assert(!V->NameAndIsUsedByMD.getInt() &&
+ "Expected this to be the only metadata use");
+ V->NameAndIsUsedByMD.setInt(true);
+ if (auto *C = dyn_cast<Constant>(V))
+ Entry = new ConstantAsMetadata(Context, C);
+ else
+ Entry = new LocalAsMetadata(Context, V);
+ }
-// Provide out-of-line definition to prevent weak vtable.
-MDNodeOperand::~MDNodeOperand() {}
+ return Entry;
+}
-void MDNodeOperand::deleted() {
- getParent()->replaceOperand(this, nullptr);
+ValueAsMetadata *ValueAsMetadata::getIfExists(Value *V) {
+ assert(V && "Unexpected null Value");
+ return V->getContext().pImpl->ValuesAsMetadata.lookup(V);
}
-void MDNodeOperand::allUsesReplacedWith(Value *NV) {
- getParent()->replaceOperand(this, NV);
+void ValueAsMetadata::handleDeletion(Value *V) {
+ assert(V && "Expected valid value");
+
+ auto &Store = V->getType()->getContext().pImpl->ValuesAsMetadata;
+ auto I = Store.find(V);
+ if (I == Store.end())
+ return;
+
+ // Remove old entry from the map.
+ ValueAsMetadata *MD = I->second;
+ assert(MD && "Expected valid metadata");
+ assert(MD->getValue() == V && "Expected valid mapping");
+ Store.erase(I);
+
+ // Delete the metadata.
+ MD->replaceAllUsesWith(nullptr);
+ delete MD;
+}
+
+void ValueAsMetadata::handleRAUW(Value *From, Value *To) {
+ assert(From && "Expected valid value");
+ assert(To && "Expected valid value");
+ assert(From != To && "Expected changed value");
+ assert(From->getType() == To->getType() && "Unexpected type change");
+
+ LLVMContext &Context = From->getType()->getContext();
+ auto &Store = Context.pImpl->ValuesAsMetadata;
+ auto I = Store.find(From);
+ if (I == Store.end()) {
+ assert(!From->NameAndIsUsedByMD.getInt() &&
+ "Expected From not to be used by metadata");
+ return;
+ }
+
+ // Remove old entry from the map.
+ assert(From->NameAndIsUsedByMD.getInt() &&
+ "Expected From to be used by metadata");
+ From->NameAndIsUsedByMD.setInt(false);
+ ValueAsMetadata *MD = I->second;
+ assert(MD && "Expected valid metadata");
+ assert(MD->getValue() == From && "Expected valid mapping");
+ Store.erase(I);
+
+ if (isa<LocalAsMetadata>(MD)) {
+ if (auto *C = dyn_cast<Constant>(To)) {
+ // Local became a constant.
+ MD->replaceAllUsesWith(ConstantAsMetadata::get(C));
+ delete MD;
+ return;
+ }
+ if (getLocalFunction(From) && getLocalFunction(To) &&
+ getLocalFunction(From) != getLocalFunction(To)) {
+ // Function changed.
+ MD->replaceAllUsesWith(nullptr);
+ delete MD;
+ return;
+ }
+ } else if (!isa<Constant>(To)) {
+ // Changed to function-local value.
+ MD->replaceAllUsesWith(nullptr);
+ delete MD;
+ return;
+ }
+
+ auto *&Entry = Store[To];
+ if (Entry) {
+ // The target already exists.
+ MD->replaceAllUsesWith(Entry);
+ delete MD;
+ return;
+ }
+
+ // Update MD in place (and update the map entry).
+ assert(!To->NameAndIsUsedByMD.getInt() &&
+ "Expected this to be the only metadata use");
+ To->NameAndIsUsedByMD.setInt(true);
+ MD->V = To;
+ Entry = MD;
}
//===----------------------------------------------------------------------===//
-// MDNode implementation.
+// MDString implementation.
//
-/// \brief Get the MDNodeOperand's coallocated on the end of the MDNode.
-static MDNodeOperand *getOperandPtr(MDNode *N, unsigned Op) {
- // Use <= instead of < to permit a one-past-the-end address.
- assert(Op <= N->getNumOperands() && "Invalid operand number");
- return reinterpret_cast<MDNodeOperand *>(N) - N->getNumOperands() + Op;
+MDString *MDString::get(LLVMContext &Context, StringRef Str) {
+ auto &Store = Context.pImpl->MDStringCache;
+ auto I = Store.find(Str);
+ if (I != Store.end())
+ return &I->second;
+
+ auto *Entry = StringMapEntry<MDString>::Create(Str, Store.getAllocator());
+ bool WasInserted = Store.insert(Entry);
+ (void)WasInserted;
+ assert(WasInserted && "Expected entry to be inserted");
+ Entry->second.Entry = Entry;
+ return &Entry->second;
}
-void MDNode::replaceOperandWith(unsigned i, Value *Val) {
- MDNodeOperand *Op = getOperandPtr(this, i);
- replaceOperand(Op, Val);
+StringRef MDString::getString() const {
+ assert(Entry && "Expected to find string map entry");
+ return Entry->first();
}
+//===----------------------------------------------------------------------===//
+// MDNode implementation.
+//
+
void *MDNode::operator new(size_t Size, unsigned NumOps) {
- void *Ptr = ::operator new(Size + NumOps * sizeof(MDNodeOperand));
- MDNodeOperand *Op = static_cast<MDNodeOperand *>(Ptr);
- if (NumOps) {
- MDNodeOperand *Last = Op + NumOps;
- for (; Op != Last; ++Op)
- new (Op) MDNodeOperand();
- (Op - 1)->setAsLastOperand(1);
- }
- return Op;
+ void *Ptr = ::operator new(Size + NumOps * sizeof(MDOperand));
+ MDOperand *First = new (Ptr) MDOperand[NumOps];
+ return First + NumOps;
}
void MDNode::operator delete(void *Mem) {
MDNode *N = static_cast<MDNode *>(Mem);
- MDNodeOperand *Op = static_cast<MDNodeOperand *>(Mem);
- for (unsigned I = 0, E = N->NumOperands; I != E; ++I)
- (--Op)->~MDNodeOperand();
- ::operator delete(Op);
+ MDOperand *Last = static_cast<MDOperand *>(Mem);
+ ::operator delete(Last - N->NumOperands);
+}
+
+MDNode::MDNode(LLVMContext &Context, unsigned ID, ArrayRef<Metadata *> MDs)
+ : Metadata(ID), Context(Context), NumOperands(MDs.size()),
+ MDNodeSubclassData(0) {
+ for (unsigned I = 0, E = MDs.size(); I != E; ++I)
+ setOperand(I, MDs[I]);
}
-MDNode::MDNode(LLVMContext &C, unsigned ID, ArrayRef<Value *> Vals,
- bool isFunctionLocal)
- : Metadata(C, ID) {
- NumOperands = Vals.size();
+bool MDNode::isResolved() const {
+ if (isa<MDNodeFwdDecl>(this))
+ return false;
+ return cast<GenericMDNode>(this)->isResolved();
+}
+
+static bool isOperandUnresolved(Metadata *Op) {
+ if (auto *N = dyn_cast_or_null<MDNode>(Op))
+ return !N->isResolved();
+ return false;
+}
- if (isFunctionLocal)
- setValueSubclassData(getSubclassDataFromValue() | FunctionLocalBit);
+GenericMDNode::GenericMDNode(LLVMContext &C, ArrayRef<Metadata *> Vals)
+ : MDNode(C, GenericMDNodeKind, Vals) {
+ // Check whether any operands are unresolved, requiring re-uniquing.
+ for (const auto &Op : operands())
+ if (isOperandUnresolved(Op))
+ incrementUnresolvedOperands();
- // Initialize the operand list.
- unsigned i = 0;
- for (MDNodeOperand *Op = getOperandPtr(this, 0), *E = Op + NumOperands;
- Op != E; ++Op, ++i)
- Op->set(Vals[i]);
+ if (hasUnresolvedOperands())
+ ReplaceableUses.reset(new ReplaceableMetadataImpl);
}
GenericMDNode::~GenericMDNode() {
- LLVMContextImpl *pImpl = getType()->getContext().pImpl;
- if (isNotUniqued()) {
+ LLVMContextImpl *pImpl = getContext().pImpl;
+ if (isStoredDistinctInContext())
pImpl->NonUniquedMDNodes.erase(this);
- } else {
+ else
pImpl->MDNodeSet.erase(this);
- }
}
-void GenericMDNode::dropAllReferences() {
- for (MDNodeOperand *Op = getOperandPtr(this, 0), *E = Op + NumOperands;
- Op != E; ++Op)
- Op->set(nullptr);
+void GenericMDNode::resolve() {
+ assert(!isResolved() && "Expected this to be unresolved");
+
+ // Move the map, so that this immediately looks resolved.
+ auto Uses = std::move(ReplaceableUses);
+ SubclassData32 = 0;
+ assert(isResolved() && "Expected this to be resolved");
+
+ // Drop RAUW support.
+ Uses->resolveAllUses();
}
-static const Function *getFunctionForValue(Value *V) {
- if (!V) return nullptr;
- if (Instruction *I = dyn_cast<Instruction>(V)) {
- BasicBlock *BB = I->getParent();
- return BB ? BB->getParent() : nullptr;
+void GenericMDNode::resolveCycles() {
+ if (isResolved())
+ return;
+
+ // Resolve this node immediately.
+ resolve();
+
+ // Resolve all operands.
+ for (const auto &Op : operands()) {
+ if (!Op)
+ continue;
+ assert(!isa<MDNodeFwdDecl>(Op) &&
+ "Expected all forward declarations to be resolved");
+ if (auto *N = dyn_cast<GenericMDNode>(Op))
+ if (!N->isResolved())
+ N->resolveCycles();
}
- if (Argument *A = dyn_cast<Argument>(V))
- return A->getParent();
- if (BasicBlock *BB = dyn_cast<BasicBlock>(V))
- return BB->getParent();
- if (MDNode *MD = dyn_cast<MDNode>(V))
- return MD->getFunction();
- return nullptr;
}
-// getFunction - If this metadata is function-local and recursively has a
-// function-local operand, return the first such operand's parent function.
-// Otherwise, return null. getFunction() should not be used for performance-
-// critical code because it recursively visits all the MDNode's operands.
-const Function *MDNode::getFunction() const {
- if (!isFunctionLocal())
- return nullptr;
- assert(getNumOperands() == 1 &&
- "Expected one operand for function-local metadata");
- assert(getOperand(0) &&
- "Expected non-null operand for function-local metadata");
- assert(!getOperand(0)->getType()->isMetadataTy() &&
- "Expected non-metadata as operand of function-local metadata");
- return getFunctionForValue(getOperand(0));
+void MDNode::dropAllReferences() {
+ for (unsigned I = 0, E = NumOperands; I != E; ++I)
+ setOperand(I, nullptr);
+ if (auto *G = dyn_cast<GenericMDNode>(this))
+ if (!G->isResolved()) {
+ G->ReplaceableUses->resolveAllUses(/* ResolveUsers */ false);
+ G->ReplaceableUses.reset();
+ }
}
-/// \brief Check if the Value would require a function-local MDNode.
-static bool isFunctionLocalValue(Value *V) {
- return isa<Instruction>(V) || isa<Argument>(V) || isa<BasicBlock>(V) ||
- (isa<MDNode>(V) && cast<MDNode>(V)->isFunctionLocal());
+namespace llvm {
+/// \brief Make MDOperand transparent for hashing.
+///
+/// This overload of an implementation detail of the hashing library makes
+/// MDOperand hash to the same value as a \a Metadata pointer.
+///
+/// Note that overloading \a hash_value() as follows:
+///
+/// \code
+/// size_t hash_value(const MDOperand &X) { return hash_value(X.get()); }
+/// \endcode
+///
+/// does not cause MDOperand to be transparent. In particular, a bare pointer
+/// doesn't get hashed before it's combined, whereas \a MDOperand would.
+static const Metadata *get_hashable_data(const MDOperand &X) { return X.get(); }
}
-MDNode *MDNode::getMDNode(LLVMContext &Context, ArrayRef<Value*> Vals,
- FunctionLocalness FL, bool Insert) {
- auto &Store = Context.pImpl->MDNodeSet;
+void GenericMDNode::handleChangedOperand(void *Ref, Metadata *New) {
+ unsigned Op = static_cast<MDOperand *>(Ref) - op_begin();
+ assert(Op < getNumOperands() && "Expected valid operand");
- GenericMDNodeInfo::KeyTy Key(Vals);
- auto I = Store.find_as(Key);
- if (I != Store.end())
- return *I;
- if (!Insert)
- return nullptr;
+ if (isStoredDistinctInContext()) {
+ assert(isResolved() && "Expected distinct node to be resolved");
- bool isFunctionLocal = false;
- switch (FL) {
- case FL_Unknown:
- for (Value *V : Vals) {
- if (!V) continue;
- if (isFunctionLocalValue(V)) {
- isFunctionLocal = true;
- break;
- }
- }
- break;
- case FL_No:
- isFunctionLocal = false;
- break;
- case FL_Yes:
- isFunctionLocal = true;
- break;
+ // This node is not uniqued. Just set the operand and be done with it.
+ setOperand(Op, New);
+ return;
}
- if (isFunctionLocal) {
- assert(Vals.size() == 1 &&
- "Expected exactly one operand for function-local metadata");
- assert(Vals[0] && "Expected non-null operand for function-local metadata");
- assert(!Vals[0]->getType()->isMetadataTy() &&
- "Expected non-metadata as operand of function-local metadata");
+ auto &Store = getContext().pImpl->MDNodeSet;
+ Store.erase(this);
+
+ Metadata *Old = getOperand(Op);
+ setOperand(Op, New);
+
+ // Drop uniquing for self-reference cycles or if an operand drops to null.
+ //
+ // FIXME: Stop dropping uniquing when an operand drops to null. The original
+ // motivation was to prevent madness during teardown of LLVMContextImpl, but
+ // dropAllReferences() fixes that problem in a better way. (It's just here
+ // now for better staging of semantic changes.)
+ if (New == this || !New) {
+ storeDistinctInContext();
+ setHash(0);
+ if (!isResolved())
+ resolve();
+ return;
}
- // Coallocate space for the node and Operands together, then placement new.
- GenericMDNode *N =
- new (Vals.size()) GenericMDNode(Context, Vals, isFunctionLocal);
+ // Re-calculate the hash.
+ setHash(hash_combine_range(op_begin(), op_end()));
+#ifndef NDEBUG
+ {
+ SmallVector<Metadata *, 8> MDs(op_begin(), op_end());
+ unsigned RawHash = hash_combine_range(MDs.begin(), MDs.end());
+ assert(getHash() == RawHash &&
+ "Expected hash of MDOperand to equal hash of Metadata*");
+ }
+#endif
- N->Hash = Key.Hash;
- Store.insert(N);
- return N;
-}
+ // Re-unique the node.
+ GenericMDNodeInfo::KeyTy Key(this);
+ auto I = Store.find_as(Key);
+ if (I == Store.end()) {
+ Store.insert(this);
+
+ if (!isResolved()) {
+ // Check if the last unresolved operand has just been resolved; if so,
+ // resolve this as well.
+ if (isOperandUnresolved(Old))
+ decrementUnresolvedOperands();
+ if (isOperandUnresolved(New))
+ incrementUnresolvedOperands();
+ if (!hasUnresolvedOperands())
+ resolve();
+ }
-MDNode *MDNode::get(LLVMContext &Context, ArrayRef<Value*> Vals) {
- return getMDNode(Context, Vals, FL_Unknown);
-}
+ return;
+ }
-MDNode *MDNode::getWhenValsUnresolved(LLVMContext &Context,
- ArrayRef<Value*> Vals,
- bool isFunctionLocal) {
- return getMDNode(Context, Vals, isFunctionLocal ? FL_Yes : FL_No);
+ // Collision.
+ if (!isResolved()) {
+ // Still unresolved, so RAUW.
+ ReplaceableUses->replaceAllUsesWith(*I);
+ delete this;
+ return;
+ }
+
+ // Store in non-uniqued form if this node has already been resolved.
+ setHash(0);
+ storeDistinctInContext();
}
-MDNode *MDNode::getIfExists(LLVMContext &Context, ArrayRef<Value*> Vals) {
- return getMDNode(Context, Vals, FL_Unknown, false);
+MDNode *MDNode::getMDNode(LLVMContext &Context, ArrayRef<Metadata *> MDs,
+ bool Insert) {
+ auto &Store = Context.pImpl->MDNodeSet;
+
+ GenericMDNodeInfo::KeyTy Key(MDs);
+ auto I = Store.find_as(Key);
+ if (I != Store.end())
+ return *I;
+ if (!Insert)
+ return nullptr;
+
+ // Coallocate space for the node and Operands together, then placement new.
+ GenericMDNode *N = new (MDs.size()) GenericMDNode(Context, MDs);
+ N->setHash(Key.Hash);
+ Store.insert(N);
+ return N;
}
-MDNode *MDNode::getTemporary(LLVMContext &Context, ArrayRef<Value*> Vals) {
- MDNode *N = new (Vals.size()) MDNodeFwdDecl(Context, Vals, FL_No);
- N->setValueSubclassData(N->getSubclassDataFromValue() | NotUniquedBit);
+MDNodeFwdDecl *MDNode::getTemporary(LLVMContext &Context,
+ ArrayRef<Metadata *> MDs) {
+ MDNodeFwdDecl *N = new (MDs.size()) MDNodeFwdDecl(Context, MDs);
LeakDetector::addGarbageObject(N);
return N;
}
void MDNode::deleteTemporary(MDNode *N) {
- assert(N->use_empty() && "Temporary MDNode has uses!");
assert(isa<MDNodeFwdDecl>(N) && "Expected forward declaration");
- assert((N->getSubclassDataFromValue() & NotUniquedBit) &&
- "Temporary MDNode does not have NotUniquedBit set!");
LeakDetector::removeGarbageObject(N);
delete cast<MDNodeFwdDecl>(N);
}
-/// \brief Return specified operand.
-Value *MDNode::getOperand(unsigned i) const {
- assert(i < getNumOperands() && "Invalid operand number");
- return *getOperandPtr(const_cast<MDNode*>(this), i);
-}
-
-void MDNode::setIsNotUniqued() {
- setValueSubclassData(getSubclassDataFromValue() | NotUniquedBit);
- LLVMContextImpl *pImpl = getType()->getContext().pImpl;
+void MDNode::storeDistinctInContext() {
+ assert(!IsDistinctInContext && "Expected newly distinct metadata");
+ IsDistinctInContext = true;
auto *G = cast<GenericMDNode>(this);
- G->Hash = 0;
- pImpl->NonUniquedMDNodes.insert(G);
+ G->setHash(0);
+ getContext().pImpl->NonUniquedMDNodes.insert(G);
}
// Replace value from this node's operand list.
-void MDNode::replaceOperand(MDNodeOperand *Op, Value *To) {
- Value *From = *Op;
-
- // If is possible that someone did GV->RAUW(inst), replacing a global variable
- // with an instruction or some other function-local object. If this is a
- // non-function-local MDNode, it can't point to a function-local object.
- // Handle this case by implicitly dropping the MDNode reference to null.
- // Likewise if the MDNode is function-local but for a different function.
- if (To && isFunctionLocalValue(To)) {
- assert(!To->getType()->isMetadataTy() &&
- "Expected non-metadata as operand of function-local metadata");
- if (!isFunctionLocal())
- To = nullptr;
- else {
- const Function *F = getFunction();
- const Function *FV = getFunctionForValue(To);
- // Metadata can be function-local without having an associated function.
- // So only consider functions to have changed if non-null.
- if (F && FV && F != FV)
- To = nullptr;
- }
- }
-
- if (From == To)
+void MDNode::replaceOperandWith(unsigned I, Metadata *New) {
+ if (getOperand(I) == New)
return;
- // If this MDValue was previously function-local but no longer is, clear
- // its function-local flag.
- if (isFunctionLocal() && !(To && isFunctionLocalValue(To))) {
- assert(getNumOperands() == 1 &&
- "Expected function-local metadata to have exactly one operand");
- setValueSubclassData(getSubclassDataFromValue() & ~FunctionLocalBit);
- }
-
- // If this node is already not being uniqued (because one of the operands
- // already went to null), then there is nothing else to do here.
- if (isNotUniqued()) {
- Op->set(To);
- return;
- }
-
- auto &Store = getContext().pImpl->MDNodeSet;
- auto *N = cast<GenericMDNode>(this);
-
- // Remove "this" from the context map.
- Store.erase(N);
-
- // Update the operand.
- Op->set(To);
-
- // If we are dropping an argument to null, we choose to not unique the MDNode
- // anymore. This commonly occurs during destruction, and uniquing these
- // brings little reuse. Also, this means we don't need to include
- // isFunctionLocal bits in the hash for MDNodes.
- //
- // Also drop uniquing if this has a reference to itself.
- if (!To || To == this) {
- setIsNotUniqued();
+ if (auto *N = dyn_cast<GenericMDNode>(this)) {
+ N->handleChangedOperand(mutable_begin() + I, New);
return;
}
- // Now that the node is out of the table, get ready to reinsert it. First,
- // check to see if another node with the same operands already exists in the
- // set. If so, then this node is redundant.
- SmallVector<Value *, 8> Vals;
- GenericMDNodeInfo::KeyTy Key(N, Vals);
- auto I = Store.find_as(Key);
- if (I != Store.end()) {
- N->replaceAllUsesWith(*I);
- delete N;
- return;
- }
+ assert(isa<MDNodeFwdDecl>(this) && "Expected an MDNode");
+ setOperand(I, New);
+}
- N->Hash = Key.Hash;
- Store.insert(N);
+void MDNode::setOperand(unsigned I, Metadata *New) {
+ assert(I < NumOperands);
+ if (isStoredDistinctInContext() || isa<MDNodeFwdDecl>(this))
+ // No need for a callback, this isn't uniqued.
+ mutable_begin()[I].reset(New, nullptr);
+ else
+ mutable_begin()[I].reset(New, this);
}
/// \brief Get a node, or a self-reference that looks like it.
/// MDNode::concatenate() and \a MDNode::intersect() to maintain behaviour from
/// when self-referencing nodes were still uniqued. If the first operand has
/// the same operands as \c Ops, return the first operand instead.
-static MDNode *getOrSelfReference(LLVMContext &Context, ArrayRef<Value *> Ops) {
+static MDNode *getOrSelfReference(LLVMContext &Context,
+ ArrayRef<Metadata *> Ops) {
if (!Ops.empty())
if (MDNode *N = dyn_cast_or_null<MDNode>(Ops[0]))
if (N->getNumOperands() == Ops.size() && N == N->getOperand(0)) {
if (!B)
return A;
- SmallVector<Value *, 4> Vals(A->getNumOperands() +
- B->getNumOperands());
+ SmallVector<Metadata *, 4> MDs(A->getNumOperands() + B->getNumOperands());
unsigned j = 0;
for (unsigned i = 0, ie = A->getNumOperands(); i != ie; ++i)
- Vals[j++] = A->getOperand(i);
+ MDs[j++] = A->getOperand(i);
for (unsigned i = 0, ie = B->getNumOperands(); i != ie; ++i)
- Vals[j++] = B->getOperand(i);
+ MDs[j++] = B->getOperand(i);
// FIXME: This preserves long-standing behaviour, but is it really the right
// behaviour? Or was that an unintended side-effect of node uniquing?
- return getOrSelfReference(A->getContext(), Vals);
+ return getOrSelfReference(A->getContext(), MDs);
}
MDNode *MDNode::intersect(MDNode *A, MDNode *B) {
if (!A || !B)
return nullptr;
- SmallVector<Value *, 4> Vals;
+ SmallVector<Metadata *, 4> MDs;
for (unsigned i = 0, ie = A->getNumOperands(); i != ie; ++i) {
- Value *V = A->getOperand(i);
+ Metadata *MD = A->getOperand(i);
for (unsigned j = 0, je = B->getNumOperands(); j != je; ++j)
- if (V == B->getOperand(j)) {
- Vals.push_back(V);
+ if (MD == B->getOperand(j)) {
+ MDs.push_back(MD);
break;
}
}
// FIXME: This preserves long-standing behaviour, but is it really the right
// behaviour? Or was that an unintended side-effect of node uniquing?
- return getOrSelfReference(A->getContext(), Vals);
+ return getOrSelfReference(A->getContext(), MDs);
}
MDNode *MDNode::getMostGenericFPMath(MDNode *A, MDNode *B) {
if (!A || !B)
return nullptr;
- APFloat AVal = cast<ConstantFP>(A->getOperand(0))->getValueAPF();
- APFloat BVal = cast<ConstantFP>(B->getOperand(0))->getValueAPF();
+ APFloat AVal = mdconst::extract<ConstantFP>(A->getOperand(0))->getValueAPF();
+ APFloat BVal = mdconst::extract<ConstantFP>(B->getOperand(0))->getValueAPF();
if (AVal.compare(BVal) == APFloat::cmpLessThan)
return A;
return B;
return !A.intersectWith(B).isEmptySet() || isContiguous(A, B);
}
-static bool tryMergeRange(SmallVectorImpl<Value *> &EndPoints, ConstantInt *Low,
- ConstantInt *High) {
+static bool tryMergeRange(SmallVectorImpl<ConstantInt *> &EndPoints,
+ ConstantInt *Low, ConstantInt *High) {
ConstantRange NewRange(Low->getValue(), High->getValue());
unsigned Size = EndPoints.size();
- APInt LB = cast<ConstantInt>(EndPoints[Size - 2])->getValue();
- APInt LE = cast<ConstantInt>(EndPoints[Size - 1])->getValue();
+ APInt LB = EndPoints[Size - 2]->getValue();
+ APInt LE = EndPoints[Size - 1]->getValue();
ConstantRange LastRange(LB, LE);
if (canBeMerged(NewRange, LastRange)) {
ConstantRange Union = LastRange.unionWith(NewRange);
Type *Ty = High->getType();
- EndPoints[Size - 2] = ConstantInt::get(Ty, Union.getLower());
- EndPoints[Size - 1] = ConstantInt::get(Ty, Union.getUpper());
+ EndPoints[Size - 2] =
+ cast<ConstantInt>(ConstantInt::get(Ty, Union.getLower()));
+ EndPoints[Size - 1] =
+ cast<ConstantInt>(ConstantInt::get(Ty, Union.getUpper()));
return true;
}
return false;
}
-static void addRange(SmallVectorImpl<Value *> &EndPoints, ConstantInt *Low,
- ConstantInt *High) {
+static void addRange(SmallVectorImpl<ConstantInt *> &EndPoints,
+ ConstantInt *Low, ConstantInt *High) {
if (!EndPoints.empty())
if (tryMergeRange(EndPoints, Low, High))
return;
// First, walk both lists in older of the lower boundary of each interval.
// At each step, try to merge the new interval to the last one we adedd.
- SmallVector<Value*, 4> EndPoints;
+ SmallVector<ConstantInt *, 4> EndPoints;
int AI = 0;
int BI = 0;
int AN = A->getNumOperands() / 2;
int BN = B->getNumOperands() / 2;
while (AI < AN && BI < BN) {
- ConstantInt *ALow = cast<ConstantInt>(A->getOperand(2 * AI));
- ConstantInt *BLow = cast<ConstantInt>(B->getOperand(2 * BI));
+ ConstantInt *ALow = mdconst::extract<ConstantInt>(A->getOperand(2 * AI));
+ ConstantInt *BLow = mdconst::extract<ConstantInt>(B->getOperand(2 * BI));
if (ALow->getValue().slt(BLow->getValue())) {
- addRange(EndPoints, ALow, cast<ConstantInt>(A->getOperand(2 * AI + 1)));
+ addRange(EndPoints, ALow,
+ mdconst::extract<ConstantInt>(A->getOperand(2 * AI + 1)));
++AI;
} else {
- addRange(EndPoints, BLow, cast<ConstantInt>(B->getOperand(2 * BI + 1)));
+ addRange(EndPoints, BLow,
+ mdconst::extract<ConstantInt>(B->getOperand(2 * BI + 1)));
++BI;
}
}
while (AI < AN) {
- addRange(EndPoints, cast<ConstantInt>(A->getOperand(2 * AI)),
- cast<ConstantInt>(A->getOperand(2 * AI + 1)));
+ addRange(EndPoints, mdconst::extract<ConstantInt>(A->getOperand(2 * AI)),
+ mdconst::extract<ConstantInt>(A->getOperand(2 * AI + 1)));
++AI;
}
while (BI < BN) {
- addRange(EndPoints, cast<ConstantInt>(B->getOperand(2 * BI)),
- cast<ConstantInt>(B->getOperand(2 * BI + 1)));
+ addRange(EndPoints, mdconst::extract<ConstantInt>(B->getOperand(2 * BI)),
+ mdconst::extract<ConstantInt>(B->getOperand(2 * BI + 1)));
++BI;
}
// the last and first ones.
unsigned Size = EndPoints.size();
if (Size > 4) {
- ConstantInt *FB = cast<ConstantInt>(EndPoints[0]);
- ConstantInt *FE = cast<ConstantInt>(EndPoints[1]);
+ ConstantInt *FB = EndPoints[0];
+ ConstantInt *FE = EndPoints[1];
if (tryMergeRange(EndPoints, FB, FE)) {
for (unsigned i = 0; i < Size - 2; ++i) {
EndPoints[i] = EndPoints[i + 2];
// If in the end we have a single range, it is possible that it is now the
// full range. Just drop the metadata in that case.
if (EndPoints.size() == 2) {
- ConstantRange Range(cast<ConstantInt>(EndPoints[0])->getValue(),
- cast<ConstantInt>(EndPoints[1])->getValue());
+ ConstantRange Range(EndPoints[0]->getValue(), EndPoints[1]->getValue());
if (Range.isFullSet())
return nullptr;
}
- return MDNode::get(A->getContext(), EndPoints);
+ SmallVector<Metadata *, 4> MDs;
+ MDs.reserve(EndPoints.size());
+ for (auto *I : EndPoints)
+ MDs.push_back(ConstantAsMetadata::get(I));
+ return MDNode::get(A->getContext(), MDs);
}
//===----------------------------------------------------------------------===//
// NamedMDNode implementation.
//
-static SmallVector<TrackingVH<MDNode>, 4> &getNMDOps(void *Operands) {
- return *(SmallVector<TrackingVH<MDNode>, 4> *)Operands;
+static SmallVector<TrackingMDRef, 4> &getNMDOps(void *Operands) {
+ return *(SmallVector<TrackingMDRef, 4> *)Operands;
}
NamedMDNode::NamedMDNode(const Twine &N)
: Name(N.str()), Parent(nullptr),
- Operands(new SmallVector<TrackingVH<MDNode>, 4>()) {}
+ Operands(new SmallVector<TrackingMDRef, 4>()) {}
NamedMDNode::~NamedMDNode() {
dropAllReferences();
MDNode *NamedMDNode::getOperand(unsigned i) const {
assert(i < getNumOperands() && "Invalid Operand number!");
- return &*getNMDOps(Operands)[i];
+ auto *N = getNMDOps(Operands)[i].get();
+ if (N && i > 10000)
+ N->dump();
+ return cast_or_null<MDNode>(N);
}
-void NamedMDNode::addOperand(MDNode *M) {
- assert(!M->isFunctionLocal() &&
- "NamedMDNode operands must not be function-local!");
- getNMDOps(Operands).push_back(TrackingVH<MDNode>(M));
-}
+void NamedMDNode::addOperand(MDNode *M) { getNMDOps(Operands).emplace_back(M); }
void NamedMDNode::eraseFromParent() {
getParent()->eraseNamedMetadata(this);
continue;
}
- Info[I] = Info.back();
+ Info[I] = std::move(Info.back());
Info.pop_back();
--E;
}
// Handle the case when we're adding/updating metadata on an instruction.
if (Node) {
- assert(!Node->isFunctionLocal() &&
- "Function-local metadata cannot be attached to instructions");
LLVMContextImpl::MDMapTy &Info = getContext().pImpl->MetadataStore[this];
assert(!Info.empty() == hasMetadataHashEntry() &&
"HasMetadata bit is wonked");
// Handle replacement of an existing value.
for (auto &P : Info)
if (P.first == KindID) {
- P.second = Node;
+ P.second.reset(Node);
return;
}
}
// No replacement, just add it to the list.
- Info.push_back(std::make_pair(KindID, Node));
+ Info.emplace_back(std::piecewise_construct, std::make_tuple(KindID),
+ std::make_tuple(Node));
return;
}
// Handle removal of an existing value.
for (unsigned i = 0, e = Info.size(); i != e; ++i)
if (Info[i].first == KindID) {
- Info[i] = Info.back();
+ Info[i] = std::move(Info.back());
Info.pop_back();
assert(!Info.empty() && "Removing last entry should be handled above");
return;
MDNode *Instruction::getMetadataImpl(unsigned KindID) const {
// Handle 'dbg' as a special case since it is not stored in the hash table.
if (KindID == LLVMContext::MD_dbg)
- return DbgLoc.getAsMDNode(getContext());
-
+ return DbgLoc.getAsMDNode();
+
if (!hasMetadataHashEntry()) return nullptr;
LLVMContextImpl::MDMapTy &Info = getContext().pImpl->MetadataStore[this];
// Handle 'dbg' as a special case since it is not stored in the hash table.
if (!DbgLoc.isUnknown()) {
- Result.push_back(std::make_pair((unsigned)LLVMContext::MD_dbg,
- DbgLoc.getAsMDNode(getContext())));
+ Result.push_back(
+ std::make_pair((unsigned)LLVMContext::MD_dbg, DbgLoc.getAsMDNode()));
if (!hasMetadataHashEntry()) return;
}
getContext().pImpl->MetadataStore.find(this)->second;
assert(!Info.empty() && "Shouldn't have called this");
- Result.append(Info.begin(), Info.end());
+ Result.reserve(Result.size() + Info.size());
+ for (auto &I : Info)
+ Result.push_back(std::make_pair(I.first, cast<MDNode>(I.second.get())));
// Sort the resulting array so it is stable.
if (Result.size() > 1)
const LLVMContextImpl::MDMapTy &Info =
getContext().pImpl->MetadataStore.find(this)->second;
assert(!Info.empty() && "Shouldn't have called this");
- Result.append(Info.begin(), Info.end());
+ Result.reserve(Result.size() + Info.size());
+ for (auto &I : Info)
+ Result.push_back(std::make_pair(I.first, cast<MDNode>(I.second.get())));
// Sort the resulting array so it is stable.
if (Result.size() > 1)
--- /dev/null
+//===- MetadataTracking.cpp - Implement metadata tracking -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements Metadata tracking.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/IR/MetadataTracking.h"
+#include "llvm/IR/Metadata.h"
+
+using namespace llvm;
+
+ReplaceableMetadataImpl *ReplaceableMetadataImpl::get(Metadata &MD) {
+ if (auto *N = dyn_cast<MDNode>(&MD)) {
+ if (auto *G = dyn_cast<GenericMDNode>(N))
+ return G->ReplaceableUses.get();
+ return cast<MDNodeFwdDecl>(N);
+ }
+ return dyn_cast<ValueAsMetadata>(&MD);
+}
+
+bool MetadataTracking::track(void *Ref, Metadata &MD, OwnerTy Owner) {
+ assert(Ref && "Expected live reference");
+ assert((Owner || *static_cast<Metadata **>(Ref) == &MD) &&
+ "Reference without owner must be direct");
+ if (auto *R = ReplaceableMetadataImpl::get(MD)) {
+ R->addRef(Ref, Owner);
+ return true;
+ }
+ return false;
+}
+
+void MetadataTracking::untrack(void *Ref, Metadata &MD) {
+ assert(Ref && "Expected live reference");
+ if (auto *R = ReplaceableMetadataImpl::get(MD))
+ R->dropRef(Ref);
+}
+
+bool MetadataTracking::retrack(void *Ref, Metadata &MD, void *New) {
+ assert(Ref && "Expected live reference");
+ assert(New && "Expected live reference");
+ assert(Ref != New && "Expected change");
+ if (auto *R = ReplaceableMetadataImpl::get(MD)) {
+ R->moveRef(Ref, New, MD);
+ return true;
+ }
+ return false;
+}
+
+bool MetadataTracking::isReplaceable(const Metadata &MD) {
+ return ReplaceableMetadataImpl::get(const_cast<Metadata &>(MD));
+}
NamedMDList.erase(NMD);
}
-bool Module::isValidModFlagBehavior(Value *V, ModFlagBehavior &MFB) {
- if (ConstantInt *Behavior = dyn_cast<ConstantInt>(V)) {
+bool Module::isValidModFlagBehavior(Metadata *MD, ModFlagBehavior &MFB) {
+ if (ConstantInt *Behavior = mdconst::dyn_extract<ConstantInt>(MD)) {
uint64_t Val = Behavior->getLimitedValue();
if (Val >= ModFlagBehaviorFirstVal && Val <= ModFlagBehaviorLastVal) {
MFB = static_cast<ModFlagBehavior>(Val);
// Check the operands of the MDNode before accessing the operands.
// The verifier will actually catch these failures.
MDString *Key = cast<MDString>(Flag->getOperand(1));
- Value *Val = Flag->getOperand(2);
+ Metadata *Val = Flag->getOperand(2);
Flags.push_back(ModuleFlagEntry(MFB, Key, Val));
}
}
/// Return the corresponding value if Key appears in module flags, otherwise
/// return null.
-Value *Module::getModuleFlag(StringRef Key) const {
+Metadata *Module::getModuleFlag(StringRef Key) const {
SmallVector<Module::ModuleFlagEntry, 8> ModuleFlags;
getModuleFlagsMetadata(ModuleFlags);
for (const ModuleFlagEntry &MFE : ModuleFlags) {
/// metadata. It will create the module-level flags named metadata if it doesn't
/// already exist.
void Module::addModuleFlag(ModFlagBehavior Behavior, StringRef Key,
- Value *Val) {
+ Metadata *Val) {
Type *Int32Ty = Type::getInt32Ty(Context);
- Value *Ops[3] = {
- ConstantInt::get(Int32Ty, Behavior), MDString::get(Context, Key), Val
- };
+ Metadata *Ops[3] = {
+ ConstantAsMetadata::get(ConstantInt::get(Int32Ty, Behavior)),
+ MDString::get(Context, Key), Val};
getOrInsertModuleFlagsMetadata()->addOperand(MDNode::get(Context, Ops));
}
+void Module::addModuleFlag(ModFlagBehavior Behavior, StringRef Key,
+ Constant *Val) {
+ addModuleFlag(Behavior, Key, ConstantAsMetadata::get(Val));
+}
void Module::addModuleFlag(ModFlagBehavior Behavior, StringRef Key,
uint32_t Val) {
Type *Int32Ty = Type::getInt32Ty(Context);
void Module::addModuleFlag(MDNode *Node) {
assert(Node->getNumOperands() == 3 &&
"Invalid number of operands for module flag!");
- assert(isa<ConstantInt>(Node->getOperand(0)) &&
+ assert(mdconst::hasa<ConstantInt>(Node->getOperand(0)) &&
isa<MDString>(Node->getOperand(1)) &&
"Invalid operand types for module flag!");
getOrInsertModuleFlagsMetadata()->addOperand(Node);
}
unsigned Module::getDwarfVersion() const {
- Value *Val = getModuleFlag("Dwarf Version");
+ auto *Val = cast_or_null<ConstantAsMetadata>(getModuleFlag("Dwarf Version"));
if (!Val)
return dwarf::DWARF_VERSION;
- return cast<ConstantInt>(Val)->getZExtValue();
+ return cast<ConstantInt>(Val->getValue())->getZExtValue();
}
Comdat *Module::getOrInsertComdat(StringRef Name) {
}
PICLevel::Level Module::getPICLevel() const {
- Value *Val = getModuleFlag("PIC Level");
+ auto *Val = cast_or_null<ConstantAsMetadata>(getModuleFlag("PIC Level"));
if (Val == NULL)
return PICLevel::Default;
- return static_cast<PICLevel::Level>(cast<ConstantInt>(Val)->getZExtValue());
+ return static_cast<PICLevel::Level>(
+ cast<ConstantInt>(Val->getValue())->getZExtValue());
}
void Module::setPICLevel(PICLevel::Level PL) {
/// other ways. GlobalValues, basic blocks, instructions, and inst operands are
/// all explicitly enumerated.
void TypeFinder::incorporateValue(const Value *V) {
- if (const MDNode *M = dyn_cast<MDNode>(V))
- return incorporateMDNode(M);
+ if (const auto *M = dyn_cast<MetadataAsValue>(V)) {
+ if (const auto *N = dyn_cast<MDNode>(M->getMetadata()))
+ return incorporateMDNode(N);
+ if (const auto *MDV = dyn_cast<ValueAsMetadata>(M->getMetadata()))
+ return incorporateValue(MDV->getValue());
+ return;
+ }
if (!isa<Constant>(V) || isa<GlobalValue>(V)) return;
/// find types hiding within.
void TypeFinder::incorporateMDNode(const MDNode *V) {
// Already visited?
- if (!VisitedConstants.insert(V).second)
+ if (!VisitedMetadata.insert(V).second)
return;
// Look in operands for types.
- for (unsigned i = 0, e = V->getNumOperands(); i != e; ++i)
- if (Value *Op = V->getOperand(i))
- incorporateValue(Op);
+ for (unsigned i = 0, e = V->getNumOperands(); i != e; ++i) {
+ Metadata *Op = V->getOperand(i);
+ if (!Op)
+ continue;
+ if (auto *N = dyn_cast<MDNode>(Op)) {
+ incorporateMDNode(N);
+ continue;
+ }
+ if (auto *C = dyn_cast<ConstantAsMetadata>(Op)) {
+ incorporateValue(C->getValue());
+ continue;
+ }
+ }
}
}
Value::Value(Type *ty, unsigned scid)
- : VTy(checkType(ty)), UseList(nullptr), Name(nullptr), SubclassID(scid),
- HasValueHandle(0), SubclassOptionalData(0), SubclassData(0),
- NumOperands(0) {
+ : VTy(checkType(ty)), UseList(nullptr), SubclassID(scid), HasValueHandle(0),
+ SubclassOptionalData(0), SubclassData(0), NumOperands(0) {
// FIXME: Why isn't this in the subclass gunk??
// Note, we cannot call isa<CallInst> before the CallInst has been
// constructed.
// Notify all ValueHandles (if present) that this value is going away.
if (HasValueHandle)
ValueHandleBase::ValueIsDeleted(this);
+ if (isUsedByMetadata())
+ ValueAsMetadata::handleDeletion(this);
#ifndef NDEBUG // Only in -g mode...
// Check to make sure that there are no uses of this value that are still
// If this value is named, destroy the name. This should not be in a symtab
// at this point.
- if (Name && SubclassID != MDStringVal)
- Name->Destroy();
+ destroyValueName();
// There should be no uses of this object anymore, remove it.
LeakDetector::removeGarbageObject(this);
}
+void Value::destroyValueName() {
+ ValueName *Name = getValueName();
+ if (Name)
+ Name->Destroy();
+ setValueName(nullptr);
+}
+
bool Value::hasNUses(unsigned N) const {
const_use_iterator UI = use_begin(), E = use_end();
} else if (Argument *A = dyn_cast<Argument>(V)) {
if (Function *P = A->getParent())
ST = &P->getValueSymbolTable();
- } else if (isa<MDString>(V))
- return true;
- else {
+ } else {
assert(isa<Constant>(V) && "Unknown value type!");
return true; // no name is setable for this.
}
// Make sure the empty string is still a C string. For historical reasons,
// some clients want to call .data() on the result and expect it to be null
// terminated.
- if (!Name) return StringRef("", 0);
- return Name->getKey();
+ if (!getValueName())
+ return StringRef("", 0);
+ return getValueName()->getKey();
}
void Value::setName(const Twine &NewName) {
- assert(SubclassID != MDStringVal &&
- "Cannot set the name of MDString with this method!");
-
// Fast path for common IRBuilder case of setName("") when there is no name.
if (NewName.isTriviallyEmpty() && !hasName())
return;
if (!ST) { // No symbol table to update? Just do the change.
if (NameRef.empty()) {
// Free the name for this value.
- Name->Destroy();
- Name = nullptr;
+ destroyValueName();
return;
}
- if (Name)
- Name->Destroy();
-
// NOTE: Could optimize for the case the name is shrinking to not deallocate
// then reallocated.
+ destroyValueName();
// Create the new name.
- Name = ValueName::Create(NameRef);
- Name->setValue(this);
+ setValueName(ValueName::Create(NameRef));
+ getValueName()->setValue(this);
return;
}
// then reallocated.
if (hasName()) {
// Remove old name.
- ST->removeValueName(Name);
- Name->Destroy();
- Name = nullptr;
+ ST->removeValueName(getValueName());
+ destroyValueName();
if (NameRef.empty())
return;
}
// Name is changing to something new.
- Name = ST->createValueName(NameRef, this);
+ setValueName(ST->createValueName(NameRef, this));
}
void Value::takeName(Value *V) {
- assert(SubclassID != MDStringVal && "Cannot take the name of an MDString!");
-
ValueSymbolTable *ST = nullptr;
// If this value has a name, drop it.
if (hasName()) {
// Remove old name.
if (ST)
- ST->removeValueName(Name);
- Name->Destroy();
- Name = nullptr;
+ ST->removeValueName(getValueName());
+ destroyValueName();
}
// Now we know that this has no name.
// This works even if both values have no symtab yet.
if (ST == VST) {
// Take the name!
- Name = V->Name;
- V->Name = nullptr;
- Name->setValue(this);
+ setValueName(V->getValueName());
+ V->setValueName(nullptr);
+ getValueName()->setValue(this);
return;
}
// then reinsert it into ST.
if (VST)
- VST->removeValueName(V->Name);
- Name = V->Name;
- V->Name = nullptr;
- Name->setValue(this);
+ VST->removeValueName(V->getValueName());
+ setValueName(V->getValueName());
+ V->setValueName(nullptr);
+ getValueName()->setValue(this);
if (ST)
ST->reinsertValue(this);
// Notify all ValueHandles (if present) that this value is going away.
if (HasValueHandle)
ValueHandleBase::ValueIsRAUWd(this, New);
+ if (isUsedByMetadata())
+ ValueAsMetadata::handleRAUW(this, New);
while (!use_empty()) {
Use &U = *UseList;
assert(V->hasName() && "Can't insert nameless Value into symbol table");
// Try inserting the name, assuming it won't conflict.
- if (vmap.insert(V->Name)) {
- //DEBUG(dbgs() << " Inserted value: " << V->Name << ": " << *V << "\n");
+ if (vmap.insert(V->getValueName())) {
+ //DEBUG(dbgs() << " Inserted value: " << V->getValueName() << ": " << *V << "\n");
return;
}
SmallString<256> UniqueName(V->getName().begin(), V->getName().end());
// The name is too already used, just free it so we can allocate a new name.
- V->Name->Destroy();
-
+ V->getValueName()->Destroy();
+
unsigned BaseSize = UniqueName.size();
while (1) {
// Trim any suffix off and append the next number.
auto IterBool = vmap.insert(std::make_pair(UniqueName, V));
if (IterBool.second) {
// Newly inserted name. Success!
- V->Name = &*IterBool.first;
+ V->setValueName(&*IterBool.first);
//DEBUG(dbgs() << " Inserted value: " << UniqueName << ": " << *V << "\n");
return;
}
}
}
+ void WriteMetadata(const Metadata *MD) {
+ if (!MD)
+ return;
+ MD->printAsOperand(OS, true, M);
+ OS << '\n';
+ }
+
void WriteType(Type *T) {
if (!T)
return;
Broken = true;
}
+ void CheckFailed(const Twine &Message, const Metadata *V1, const Metadata *V2,
+ const Metadata *V3 = nullptr, const Metadata *V4 = nullptr) {
+ OS << Message.str() << "\n";
+ WriteMetadata(V1);
+ WriteMetadata(V2);
+ WriteMetadata(V3);
+ WriteMetadata(V4);
+ Broken = true;
+ }
+
+ void CheckFailed(const Twine &Message, const Metadata *V1,
+ const Value *V2 = nullptr) {
+ OS << Message.str() << "\n";
+ WriteMetadata(V1);
+ WriteValue(V2);
+ Broken = true;
+ }
+
void CheckFailed(const Twine &Message, const Value *V1, Type *T2,
const Value *V3 = nullptr) {
OS << Message.str() << "\n";
SmallPtrSet<Instruction *, 16> InstsInThisBlock;
/// \brief Keep track of the metadata nodes that have been checked already.
- SmallPtrSet<MDNode *, 32> MDNodes;
+ SmallPtrSet<Metadata *, 32> MDNodes;
/// \brief The personality function referenced by the LandingPadInsts.
/// All LandingPadInsts within the same function must use the same
void visitAliaseeSubExpr(SmallPtrSetImpl<const GlobalAlias *> &Visited,
const GlobalAlias &A, const Constant &C);
void visitNamedMDNode(const NamedMDNode &NMD);
- void visitMDNode(MDNode &MD, Function *F);
+ void visitMDNode(MDNode &MD);
+ void visitMetadataAsValue(MetadataAsValue &MD, Function *F);
+ void visitValueAsMetadata(ValueAsMetadata &MD, Function *F);
void visitComdat(const Comdat &C);
void visitModuleIdents(const Module &M);
void visitModuleFlags(const Module &M);
if (!MD)
continue;
- Assert1(!MD->isFunctionLocal(),
- "Named metadata operand cannot be function local!", MD);
- visitMDNode(*MD, nullptr);
+ visitMDNode(*MD);
}
}
-void Verifier::visitMDNode(MDNode &MD, Function *F) {
+void Verifier::visitMDNode(MDNode &MD) {
// Only visit each node once. Metadata can be mutually recursive, so this
// avoids infinite recursion here, as well as being an optimization.
if (!MDNodes.insert(&MD).second)
return;
for (unsigned i = 0, e = MD.getNumOperands(); i != e; ++i) {
- Value *Op = MD.getOperand(i);
+ Metadata *Op = MD.getOperand(i);
if (!Op)
continue;
- if (isa<Constant>(Op) || isa<MDString>(Op))
+ Assert2(!isa<LocalAsMetadata>(Op), "Invalid operand for global metadata!",
+ &MD, Op);
+ if (auto *N = dyn_cast<MDNode>(Op)) {
+ visitMDNode(*N);
continue;
- if (MDNode *N = dyn_cast<MDNode>(Op)) {
- Assert2(MD.isFunctionLocal() || !N->isFunctionLocal(),
- "Global metadata operand cannot be function local!", &MD, N);
- visitMDNode(*N, F);
+ }
+ if (auto *V = dyn_cast<ValueAsMetadata>(Op)) {
+ visitValueAsMetadata(*V, nullptr);
continue;
}
- Assert2(MD.isFunctionLocal(), "Invalid operand for global metadata!", &MD, Op);
-
- // If this was an instruction, bb, or argument, verify that it is in the
- // function that we expect.
- Function *ActualF = nullptr;
- if (Instruction *I = dyn_cast<Instruction>(Op))
- ActualF = I->getParent()->getParent();
- else if (BasicBlock *BB = dyn_cast<BasicBlock>(Op))
- ActualF = BB->getParent();
- else if (Argument *A = dyn_cast<Argument>(Op))
- ActualF = A->getParent();
- assert(ActualF && "Unimplemented function local metadata case!");
-
- Assert2(ActualF == F, "function-local metadata used in wrong function",
- &MD, Op);
}
+
+ // Check these last, so we diagnose problems in operands first.
+ Assert1(!isa<MDNodeFwdDecl>(MD), "Expected no forward declarations!", &MD);
+ Assert1(MD.isResolved(), "All nodes should be resolved!", &MD);
+}
+
+void Verifier::visitValueAsMetadata(ValueAsMetadata &MD, Function *F) {
+ Assert1(MD.getValue(), "Expected valid value", &MD);
+ Assert2(!MD.getValue()->getType()->isMetadataTy(),
+ "Unexpected metadata round-trip through values", &MD, MD.getValue());
+
+ auto *L = dyn_cast<LocalAsMetadata>(&MD);
+ if (!L)
+ return;
+
+ Assert1(F, "function-local metadata used outside a function", L);
+
+ // If this was an instruction, bb, or argument, verify that it is in the
+ // function that we expect.
+ Function *ActualF = nullptr;
+ if (Instruction *I = dyn_cast<Instruction>(L->getValue())) {
+ Assert2(I->getParent(), "function-local metadata not in basic block", L, I);
+ ActualF = I->getParent()->getParent();
+ } else if (BasicBlock *BB = dyn_cast<BasicBlock>(L->getValue()))
+ ActualF = BB->getParent();
+ else if (Argument *A = dyn_cast<Argument>(L->getValue()))
+ ActualF = A->getParent();
+ assert(ActualF && "Unimplemented function local metadata case!");
+
+ Assert1(ActualF == F, "function-local metadata used in wrong function", L);
+}
+
+void Verifier::visitMetadataAsValue(MetadataAsValue &MDV, Function *F) {
+ Metadata *MD = MDV.getMetadata();
+ if (auto *N = dyn_cast<MDNode>(MD)) {
+ visitMDNode(*N);
+ return;
+ }
+
+ // Only visit each node once. Metadata can be mutually recursive, so this
+ // avoids infinite recursion here, as well as being an optimization.
+ if (!MDNodes.insert(MD).second)
+ return;
+
+ if (auto *V = dyn_cast<ValueAsMetadata>(MD))
+ visitValueAsMetadata(*V, F);
}
void Verifier::visitComdat(const Comdat &C) {
for (unsigned I = 0, E = Requirements.size(); I != E; ++I) {
const MDNode *Requirement = Requirements[I];
const MDString *Flag = cast<MDString>(Requirement->getOperand(0));
- const Value *ReqValue = Requirement->getOperand(1);
+ const Metadata *ReqValue = Requirement->getOperand(1);
const MDNode *Op = SeenIDs.lookup(Flag);
if (!Op) {
Module::ModFlagBehavior MFB;
if (!Module::isValidModFlagBehavior(Op->getOperand(0), MFB)) {
Assert1(
- dyn_cast<ConstantInt>(Op->getOperand(0)),
+ mdconst::dyn_extract<ConstantInt>(Op->getOperand(0)),
"invalid behavior operand in module flag (expected constant integer)",
Op->getOperand(0));
Assert1(false,
ConstantRange LastRange(1); // Dummy initial value
for (unsigned i = 0; i < NumRanges; ++i) {
- ConstantInt *Low = dyn_cast<ConstantInt>(Range->getOperand(2*i));
+ ConstantInt *Low =
+ mdconst::dyn_extract<ConstantInt>(Range->getOperand(2 * i));
Assert1(Low, "The lower limit must be an integer!", Low);
- ConstantInt *High = dyn_cast<ConstantInt>(Range->getOperand(2*i + 1));
+ ConstantInt *High =
+ mdconst::dyn_extract<ConstantInt>(Range->getOperand(2 * i + 1));
Assert1(High, "The upper limit must be an integer!", High);
Assert1(High->getType() == Low->getType() &&
High->getType() == Ty, "Range types must match instruction type!",
}
if (NumRanges > 2) {
APInt FirstLow =
- dyn_cast<ConstantInt>(Range->getOperand(0))->getValue();
+ mdconst::dyn_extract<ConstantInt>(Range->getOperand(0))->getValue();
APInt FirstHigh =
- dyn_cast<ConstantInt>(Range->getOperand(1))->getValue();
+ mdconst::dyn_extract<ConstantInt>(Range->getOperand(1))->getValue();
ConstantRange FirstRange(FirstLow, FirstHigh);
Assert1(FirstRange.intersectWith(LastRange).isEmptySet(),
"Intervals are overlapping", Range);
Assert1(I.getType()->isFPOrFPVectorTy(),
"fpmath requires a floating point result!", &I);
Assert1(MD->getNumOperands() == 1, "fpmath takes one operand!", &I);
- Value *Op0 = MD->getOperand(0);
- if (ConstantFP *CFP0 = dyn_cast_or_null<ConstantFP>(Op0)) {
+ if (ConstantFP *CFP0 =
+ mdconst::dyn_extract_or_null<ConstantFP>(MD->getOperand(0))) {
APFloat Accuracy = CFP0->getValueAPF();
Assert1(Accuracy.isFiniteNonZero() && !Accuracy.isNegative(),
"fpmath accuracy not a positive number!", &I);
// If the intrinsic takes MDNode arguments, verify that they are either global
// or are local to *this* function.
for (unsigned i = 0, e = CI.getNumArgOperands(); i != e; ++i)
- if (MDNode *MD = dyn_cast<MDNode>(CI.getArgOperand(i)))
- visitMDNode(*MD, CI.getParent()->getParent());
+ if (auto *MD = dyn_cast<MetadataAsValue>(CI.getArgOperand(i)))
+ visitMetadataAsValue(*MD, CI.getParent()->getParent());
switch (ID) {
default:
"constant int", &CI);
break;
case Intrinsic::dbg_declare: { // llvm.dbg.declare
- Assert1(CI.getArgOperand(0) && isa<MDNode>(CI.getArgOperand(0)),
- "invalid llvm.dbg.declare intrinsic call 1", &CI);
- MDNode *MD = cast<MDNode>(CI.getArgOperand(0));
- Assert1(MD->getNumOperands() == 1,
- "invalid llvm.dbg.declare intrinsic call 2", &CI);
+ Assert1(CI.getArgOperand(0) && isa<MetadataAsValue>(CI.getArgOperand(0)),
+ "invalid llvm.dbg.declare intrinsic call 1", &CI);
} break;
case Intrinsic::memcpy:
case Intrinsic::memmove:
/// parseMetadata - Parse metadata from the module
void LTOModule::parseMetadata() {
// Linker Options
- if (Value *Val = getModule().getModuleFlag("Linker Options")) {
+ if (Metadata *Val = getModule().getModuleFlag("Linker Options")) {
MDNode *LinkerOptions = cast<MDNode>(Val);
for (unsigned i = 0, e = LinkerOptions->getNumOperands(); i != e; ++i) {
MDNode *MDOptions = cast<MDNode>(LinkerOptions->getOperand(i));
SmallSetVector<MDNode*, 16> Requirements;
for (unsigned I = 0, E = DstModFlags->getNumOperands(); I != E; ++I) {
MDNode *Op = DstModFlags->getOperand(I);
- ConstantInt *Behavior = cast<ConstantInt>(Op->getOperand(0));
+ ConstantInt *Behavior = mdconst::extract<ConstantInt>(Op->getOperand(0));
MDString *ID = cast<MDString>(Op->getOperand(1));
if (Behavior->getZExtValue() == Module::Require) {
bool HasErr = false;
for (unsigned I = 0, E = SrcModFlags->getNumOperands(); I != E; ++I) {
MDNode *SrcOp = SrcModFlags->getOperand(I);
- ConstantInt *SrcBehavior = cast<ConstantInt>(SrcOp->getOperand(0));
+ ConstantInt *SrcBehavior =
+ mdconst::extract<ConstantInt>(SrcOp->getOperand(0));
MDString *ID = cast<MDString>(SrcOp->getOperand(1));
MDNode *DstOp = Flags.lookup(ID);
unsigned SrcBehaviorValue = SrcBehavior->getZExtValue();
}
// Otherwise, perform a merge.
- ConstantInt *DstBehavior = cast<ConstantInt>(DstOp->getOperand(0));
+ ConstantInt *DstBehavior =
+ mdconst::extract<ConstantInt>(DstOp->getOperand(0));
unsigned DstBehaviorValue = DstBehavior->getZExtValue();
// If either flag has override behavior, handle it first.
continue;
} else if (SrcBehaviorValue == Module::Override) {
// Update the destination flag to that of the source.
- DstOp->replaceOperandWith(0, SrcBehavior);
+ DstOp->replaceOperandWith(0, ConstantAsMetadata::get(SrcBehavior));
DstOp->replaceOperandWith(2, SrcOp->getOperand(2));
continue;
}
case Module::Append: {
MDNode *DstValue = cast<MDNode>(DstOp->getOperand(2));
MDNode *SrcValue = cast<MDNode>(SrcOp->getOperand(2));
- unsigned NumOps = DstValue->getNumOperands() + SrcValue->getNumOperands();
- Value **VP, **Values = VP = new Value*[NumOps];
- for (unsigned i = 0, e = DstValue->getNumOperands(); i != e; ++i, ++VP)
- *VP = DstValue->getOperand(i);
- for (unsigned i = 0, e = SrcValue->getNumOperands(); i != e; ++i, ++VP)
- *VP = SrcValue->getOperand(i);
- DstOp->replaceOperandWith(2, MDNode::get(DstM->getContext(),
- ArrayRef<Value*>(Values,
- NumOps)));
- delete[] Values;
+ SmallVector<Metadata *, 8> MDs;
+ MDs.reserve(DstValue->getNumOperands() + SrcValue->getNumOperands());
+ for (unsigned i = 0, e = DstValue->getNumOperands(); i != e; ++i)
+ MDs.push_back(DstValue->getOperand(i));
+ for (unsigned i = 0, e = SrcValue->getNumOperands(); i != e; ++i)
+ MDs.push_back(SrcValue->getOperand(i));
+ DstOp->replaceOperandWith(2, MDNode::get(DstM->getContext(), MDs));
break;
}
case Module::AppendUnique: {
- SmallSetVector<Value*, 16> Elts;
+ SmallSetVector<Metadata *, 16> Elts;
MDNode *DstValue = cast<MDNode>(DstOp->getOperand(2));
MDNode *SrcValue = cast<MDNode>(SrcOp->getOperand(2));
for (unsigned i = 0, e = DstValue->getNumOperands(); i != e; ++i)
Elts.insert(DstValue->getOperand(i));
for (unsigned i = 0, e = SrcValue->getNumOperands(); i != e; ++i)
Elts.insert(SrcValue->getOperand(i));
- DstOp->replaceOperandWith(2, MDNode::get(DstM->getContext(),
- ArrayRef<Value*>(Elts.begin(),
- Elts.end())));
+ DstOp->replaceOperandWith(
+ 2, MDNode::get(DstM->getContext(),
+ makeArrayRef(Elts.begin(), Elts.end())));
break;
}
}
for (unsigned I = 0, E = Requirements.size(); I != E; ++I) {
MDNode *Requirement = Requirements[I];
MDString *Flag = cast<MDString>(Requirement->getOperand(0));
- Value *ReqValue = Requirement->getOperand(1);
+ Metadata *ReqValue = Requirement->getOperand(1);
MDNode *Op = Flags[Flag];
if (!Op || Op->getOperand(2) != ReqValue) {
if (const Module *SourceModule = MMI->getModule()) {
// ABI_PCS_wchar_t to indicate wchar_t width
// FIXME: There is no way to emit value 0 (wchar_t prohibited).
- if (auto WCharWidthValue = cast_or_null<ConstantInt>(
+ if (auto WCharWidthValue = mdconst::extract_or_null<ConstantInt>(
SourceModule->getModuleFlag("wchar_size"))) {
int WCharWidth = WCharWidthValue->getZExtValue();
assert((WCharWidth == 2 || WCharWidth == 4) &&
// ABI_enum_size to indicate enum width
// FIXME: There is no way to emit value 0 (enums prohibited) or value 3
// (all enums contain a value needing 32 bits to encode).
- if (auto EnumWidthValue = cast_or_null<ConstantInt>(
+ if (auto EnumWidthValue = mdconst::extract_or_null<ConstantInt>(
SourceModule->getModuleFlag("min_enum_size"))) {
int EnumWidth = EnumWidthValue->getZExtValue();
assert((EnumWidth == 1 || EnumWidth == 4) &&
MDNode *GenericToNVVM::remapMDNode(Module *M, MDNode *N) {
bool OperandChanged = false;
- SmallVector<Value *, 8> NewOperands;
+ SmallVector<Metadata *, 8> NewOperands;
unsigned NumOperands = N->getNumOperands();
// Check if any operand is or contains a global variable in GVMap, and thus
// converted to another value.
for (unsigned i = 0; i < NumOperands; ++i) {
- Value *Operand = N->getOperand(i);
- Value *NewOperand = Operand;
+ Metadata *Operand = N->getOperand(i);
+ Metadata *NewOperand = Operand;
if (Operand) {
- if (isa<GlobalVariable>(Operand)) {
- GVMapTy::iterator I = GVMap.find(cast<GlobalVariable>(Operand));
- if (I != GVMap.end()) {
- NewOperand = I->second;
- if (++i < NumOperands) {
- NewOperands.push_back(NewOperand);
- // Address space of the global variable follows the global variable
- // in the global variable debug info (see createGlobalVariable in
- // lib/Analysis/DIBuilder.cpp).
- NewOperand =
- ConstantInt::get(Type::getInt32Ty(M->getContext()),
- I->second->getType()->getAddressSpace());
+ if (auto *N = dyn_cast<MDNode>(Operand)) {
+ NewOperand = remapMDNode(M, N);
+ } else if (auto *C = dyn_cast<ConstantAsMetadata>(Operand)) {
+ if (auto *G = dyn_cast<GlobalVariable>(C->getValue())) {
+ GVMapTy::iterator I = GVMap.find(G);
+ if (I != GVMap.end()) {
+ NewOperand = ConstantAsMetadata::get(I->second);
+ if (++i < NumOperands) {
+ NewOperands.push_back(NewOperand);
+ // Address space of the global variable follows the global
+ // variable
+ // in the global variable debug info (see createGlobalVariable in
+ // lib/Analysis/DIBuilder.cpp).
+ NewOperand = ConstantAsMetadata::get(
+ ConstantInt::get(Type::getInt32Ty(M->getContext()),
+ I->second->getType()->getAddressSpace()));
+ }
}
}
- } else if (isa<MDNode>(Operand)) {
- NewOperand = remapMDNode(M, cast<MDNode>(Operand));
}
}
OperandChanged |= Operand != NewOperand;
assert(prop && "Annotation property not a string");
// value
- ConstantInt *Val = dyn_cast<ConstantInt>(md->getOperand(i + 1));
+ ConstantInt *Val = mdconst::dyn_extract<ConstantInt>(md->getOperand(i + 1));
assert(Val && "Value operand not a constant int");
std::string keyname = prop->getString().str();
for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
const MDNode *elem = NMD->getOperand(i);
- Value *entity = elem->getOperand(0);
+ GlobalValue *entity =
+ mdconst::dyn_extract_or_null<GlobalValue>(elem->getOperand(0));
// entity may be null due to DCE
if (!entity)
continue;
if (MDNode *alignNode = I.getMetadata("callalign")) {
for (int i = 0, n = alignNode->getNumOperands(); i < n; i++) {
if (const ConstantInt *CI =
- dyn_cast<ConstantInt>(alignNode->getOperand(i))) {
+ mdconst::dyn_extract<ConstantInt>(alignNode->getOperand(i))) {
unsigned v = CI->getZExtValue();
if ((v >> 16) == index) {
align = v & 0xFFFF;
// For each compile unit, find the live set of global variables/functions and
// replace the current list of potentially dead global variables/functions
// with the live list.
- SmallVector<Value *, 64> LiveGlobalVariables;
- SmallVector<Value *, 64> LiveSubprograms;
+ SmallVector<Metadata *, 64> LiveGlobalVariables;
+ SmallVector<Metadata *, 64> LiveSubprograms;
DenseSet<const MDNode *> VisitedSet;
for (DICompileUnit DIC : F.compile_units()) {
// If the memcpy has metadata describing the members, see if we can
// get the TBAA tag describing our copy.
if (MDNode *M = MI->getMetadata(LLVMContext::MD_tbaa_struct)) {
- if (M->getNumOperands() == 3 &&
- M->getOperand(0) &&
- isa<ConstantInt>(M->getOperand(0)) &&
- cast<ConstantInt>(M->getOperand(0))->isNullValue() &&
+ if (M->getNumOperands() == 3 && M->getOperand(0) &&
+ mdconst::hasa<ConstantInt>(M->getOperand(0)) &&
+ mdconst::extract<ConstantInt>(M->getOperand(0))->isNullValue() &&
M->getOperand(1) &&
- isa<ConstantInt>(M->getOperand(1)) &&
- cast<ConstantInt>(M->getOperand(1))->getValue() == Size &&
- M->getOperand(2) &&
- isa<MDNode>(M->getOperand(2)))
+ mdconst::hasa<ConstantInt>(M->getOperand(1)) &&
+ mdconst::extract<ConstantInt>(M->getOperand(1))->getValue() ==
+ Size &&
+ M->getOperand(2) && isa<MDNode>(M->getOperand(2)))
CopyMD = cast<MDNode>(M->getOperand(2));
}
}
cast<Constant>(RHS)->isNullValue()) {
LoadInst* LI = cast<LoadInst>(LHS);
if (isValidAssumeForContext(II, LI, DL, DT)) {
- MDNode* MD = MDNode::get(II->getContext(), ArrayRef<Value*>());
+ MDNode *MD = MDNode::get(II->getContext(), None);
LI->setMetadata(LLVMContext::MD_nonnull, MD);
return EraseInstFromFunction(*II);
}
assert(MDN->getNumOperands() == 3);
MDString *MDFilename = cast<MDString>(MDN->getOperand(0));
Filename = MDFilename->getString();
- LineNo = cast<ConstantInt>(MDN->getOperand(1))->getLimitedValue();
- ColumnNo = cast<ConstantInt>(MDN->getOperand(2))->getLimitedValue();
+ LineNo =
+ mdconst::extract<ConstantInt>(MDN->getOperand(1))->getLimitedValue();
+ ColumnNo =
+ mdconst::extract<ConstantInt>(MDN->getOperand(2))->getLimitedValue();
}
};
for (auto MDN : Globals->operands()) {
// Metadata node contains the global and the fields of "Entry".
assert(MDN->getNumOperands() == 5);
- Value *V = MDN->getOperand(0);
+ auto *GV = mdconst::extract_or_null<GlobalVariable>(MDN->getOperand(0));
// The optimizer may optimize away a global entirely.
- if (!V)
+ if (!GV)
continue;
- GlobalVariable *GV = cast<GlobalVariable>(V);
// We can already have an entry for GV if it was merged with another
// global.
Entry &E = Entries[GV];
- if (Value *Loc = MDN->getOperand(1))
- E.SourceLoc.parse(cast<MDNode>(Loc));
- if (Value *Name = MDN->getOperand(2)) {
- MDString *MDName = cast<MDString>(Name);
- E.Name = MDName->getString();
- }
- ConstantInt *IsDynInit = cast<ConstantInt>(MDN->getOperand(3));
+ if (auto *Loc = cast_or_null<MDNode>(MDN->getOperand(1)))
+ E.SourceLoc.parse(Loc);
+ if (auto *Name = cast_or_null<MDString>(MDN->getOperand(2)))
+ E.Name = Name->getString();
+ ConstantInt *IsDynInit =
+ mdconst::extract<ConstantInt>(MDN->getOperand(3));
E.IsDynInit |= IsDynInit->isOne();
- ConstantInt *IsBlacklisted = cast<ConstantInt>(MDN->getOperand(4));
+ ConstantInt *IsBlacklisted =
+ mdconst::extract<ConstantInt>(MDN->getOperand(4));
E.IsBlacklisted |= IsBlacklisted->isOne();
}
}
AllocaForValueMapTy AllocaForValue;
FunctionStackPoisoner(Function &F, AddressSanitizer &ASan)
- : F(F), ASan(ASan), DIB(*F.getParent()), C(ASan.C),
- IntptrTy(ASan.IntptrTy), IntptrPtrTy(PointerType::get(IntptrTy, 0)),
- Mapping(ASan.Mapping),
+ : F(F), ASan(ASan), DIB(*F.getParent(), /*AllowUnresolved*/ false),
+ C(ASan.C), IntptrTy(ASan.IntptrTy),
+ IntptrPtrTy(PointerType::get(IntptrTy, 0)), Mapping(ASan.Mapping),
StackAlignment(1 << Mapping.Scale) {}
bool runOnFunction() {
Load->setAtomic(Monotonic);
Load->setAlignment(1);
Load->setMetadata(F.getParent()->getMDKindID("nosanitize"),
- MDNode::get(*C, ArrayRef<llvm::Value *>()));
+ MDNode::get(*C, None));
Value *Cmp = IRB.CreateICmpEQ(Constant::getNullValue(Int8Ty), Load);
Instruction *Ins = SplitBlockAndInsertIfThen(
Cmp, IP, false, MDBuilder(*C).createBranchWeights(1, 100000));
Sequence OldSeq,
Sequence NewSeq) {
MDNode *Node = nullptr;
- Value *tmp[3] = {PtrSourceMDNodeID,
- SequenceToMDString(Inst->getContext(),
- OldSeq),
- SequenceToMDString(Inst->getContext(),
- NewSeq)};
+ Metadata *tmp[3] = {PtrSourceMDNodeID,
+ SequenceToMDString(Inst->getContext(), OldSeq),
+ SequenceToMDString(Inst->getContext(), NewSeq)};
Node = MDNode::get(Inst->getContext(), tmp);
Inst->setMetadata(NodeId, Node);
if (MD) {
assert(MD->getNumOperands() == 2 &&
"Unroll count hint metadata should have two operands.");
- unsigned Count = cast<ConstantInt>(MD->getOperand(1))->getZExtValue();
+ unsigned Count =
+ mdconst::extract<ConstantInt>(MD->getOperand(1))->getZExtValue();
assert(Count >= 1 && "Unroll count must be positive.");
return Count;
}
if (!LoopID) return;
// First remove any existing loop unrolling metadata.
- SmallVector<Value *, 4> Vals;
+ SmallVector<Metadata *, 4> MDs;
// Reserve first location for self reference to the LoopID metadata node.
- Vals.push_back(nullptr);
+ MDs.push_back(nullptr);
for (unsigned i = 1, ie = LoopID->getNumOperands(); i < ie; ++i) {
bool IsUnrollMetadata = false;
MDNode *MD = dyn_cast<MDNode>(LoopID->getOperand(i));
const MDString *S = dyn_cast<MDString>(MD->getOperand(0));
IsUnrollMetadata = S && S->getString().startswith("llvm.loop.unroll.");
}
- if (!IsUnrollMetadata) Vals.push_back(LoopID->getOperand(i));
+ if (!IsUnrollMetadata)
+ MDs.push_back(LoopID->getOperand(i));
}
// Add unroll(disable) metadata to disable future unrolling.
LLVMContext &Context = L->getHeader()->getContext();
- SmallVector<Value *, 1> DisableOperands;
+ SmallVector<Metadata *, 1> DisableOperands;
DisableOperands.push_back(MDString::get(Context, "llvm.loop.unroll.disable"));
MDNode *DisableNode = MDNode::get(Context, DisableOperands);
- Vals.push_back(DisableNode);
+ MDs.push_back(DisableNode);
- MDNode *NewLoopID = MDNode::get(Context, Vals);
+ MDNode *NewLoopID = MDNode::get(Context, MDs);
// Set operand 0 to refer to the loop id itself.
NewLoopID->replaceOperandWith(0, NewLoopID);
L->setLoopID(NewLoopID);
void run(const SmallVectorImpl<Instruction*> &Insts) {
// Retain the debug information attached to the alloca for use when
// rewriting loads and stores.
- if (MDNode *DebugNode = MDNode::getIfExists(AI.getContext(), &AI)) {
- for (User *U : DebugNode->users())
- if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(U))
- DDIs.push_back(DDI);
- else if (DbgValueInst *DVI = dyn_cast<DbgValueInst>(U))
- DVIs.push_back(DVI);
+ if (auto *L = LocalAsMetadata::getIfExists(&AI)) {
+ if (auto *DebugNode = MetadataAsValue::getIfExists(AI.getContext(), L)) {
+ for (User *U : DebugNode->users())
+ if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(U))
+ DDIs.push_back(DDI);
+ else if (DbgValueInst *DVI = dyn_cast<DbgValueInst>(U))
+ DVIs.push_back(DVI);
+ }
}
LoadAndStorePromoter::run(Insts);
DEBUG(dbgs() << "Promoting allocas with SSAUpdater...\n");
SSAUpdater SSA;
- DIBuilder DIB(*F.getParent());
+ DIBuilder DIB(*F.getParent(), /*AllowUnresolved*/ false);
SmallVector<Instruction *, 64> Insts;
// We need a worklist to walk the uses of each alloca.
void run(AllocaInst *AI, const SmallVectorImpl<Instruction*> &Insts) {
// Remember which alloca we're promoting (for isInstInList).
this->AI = AI;
- if (MDNode *DebugNode = MDNode::getIfExists(AI->getContext(), AI)) {
- for (User *U : DebugNode->users())
- if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(U))
- DDIs.push_back(DDI);
- else if (DbgValueInst *DVI = dyn_cast<DbgValueInst>(U))
- DVIs.push_back(DVI);
+ if (auto *L = LocalAsMetadata::getIfExists(AI)) {
+ if (auto *DebugNode = MetadataAsValue::getIfExists(AI->getContext(), L)) {
+ for (User *U : DebugNode->users())
+ if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(U))
+ DDIs.push_back(DDI);
+ else if (DbgValueInst *DVI = dyn_cast<DbgValueInst>(U))
+ DVIs.push_back(DVI);
+ }
}
LoadAndStorePromoter::run(Insts);
AssumptionTracker *AT = &getAnalysis<AssumptionTracker>();
BasicBlock &BB = F.getEntryBlock(); // Get the entry node for the function
- DIBuilder DIB(*F.getParent());
+ DIBuilder DIB(*F.getParent(), /*AllowUnresolved*/ false);
bool Changed = false;
SmallVector<Instruction*, 64> Insts;
while (1) {
bool Changed = false;
Module *M = F.getParent();
LLVMContext &Ctx = M->getContext();
- DIBuilder Builder(*M);
+ DIBuilder Builder(*M, /*AllowUnresolved*/ false);
// Traverse all the blocks looking for instructions in different
// blocks that are at the same file:line location.
// Add an operand to an existing MDNode. The new operand will be added at the
// back of the operand list.
-static void AddOperand(DICompileUnit CU, DIArray SPs, Value *NewSP) {
- SmallVector<Value *, 16> NewSPs;
+static void AddOperand(DICompileUnit CU, DIArray SPs, Metadata *NewSP) {
+ SmallVector<Metadata *, 16> NewSPs;
NewSPs.reserve(SPs->getNumOperands() + 1);
for (unsigned I = 0, E = SPs->getNumOperands(); I != E; ++I)
NewSPs.push_back(SPs->getOperand(I));
// Walk the existing metadata, adding the complete (perhaps cyclic) chain to
// the set.
- SmallVector<const Value *, 16> Queue(MD.begin(), MD.end());
+ SmallVector<const Metadata *, 16> Queue(MD.begin(), MD.end());
while (!Queue.empty()) {
const MDNode *M = cast<MDNode>(Queue.pop_back_val());
for (unsigned i = 0, ie = M->getNumOperands(); i != ie; ++i)
// Now we have a complete set of all metadata in the chains used to specify
// the noalias scopes and the lists of those scopes.
SmallVector<MDNode *, 16> DummyNodes;
- DenseMap<const MDNode *, TrackingVH<MDNode> > MDMap;
+ DenseMap<const MDNode *, TrackingMDNodeRef> MDMap;
for (SetVector<const MDNode *>::iterator I = MD.begin(), IE = MD.end();
I != IE; ++I) {
MDNode *Dummy = MDNode::getTemporary(CalledFunc->getContext(), None);
DummyNodes.push_back(Dummy);
- MDMap[*I] = Dummy;
+ MDMap[*I].reset(Dummy);
}
// Create new metadata nodes to replace the dummy nodes, replacing old
// node.
for (SetVector<const MDNode *>::iterator I = MD.begin(), IE = MD.end();
I != IE; ++I) {
- SmallVector<Value *, 4> NewOps;
+ SmallVector<Metadata *, 4> NewOps;
for (unsigned i = 0, ie = (*I)->getNumOperands(); i != ie; ++i) {
- const Value *V = (*I)->getOperand(i);
+ const Metadata *V = (*I)->getOperand(i);
if (const MDNode *M = dyn_cast<MDNode>(V))
NewOps.push_back(MDMap[M]);
else
- NewOps.push_back(const_cast<Value *>(V));
+ NewOps.push_back(const_cast<Metadata *>(V));
}
- MDNode *NewM = MDNode::get(CalledFunc->getContext(), NewOps),
- *TempM = MDMap[*I];
+ MDNode *NewM = MDNode::get(CalledFunc->getContext(), NewOps);
+ MDNodeFwdDecl *TempM = cast<MDNodeFwdDecl>(MDMap[*I]);
TempM->replaceAllUsesWith(NewM);
}
// need to go through several PHIs to see it, and thus could be
// repeated in the Objects list.
SmallPtrSet<const Value *, 4> ObjSet;
- SmallVector<Value *, 4> Scopes, NoAliases;
+ SmallVector<Metadata *, 4> Scopes, NoAliases;
SmallSetVector<const Argument *, 4> NAPtrArgs;
for (unsigned i = 0, ie = PtrArgs.size(); i != ie; ++i) {
if (DbgValueInst *DVI = dyn_cast<DbgValueInst>(BI)) {
LLVMContext &Ctx = BI->getContext();
MDNode *InlinedAt = BI->getDebugLoc().getInlinedAt(Ctx);
- DVI->setOperand(2, createInlinedVariable(DVI->getVariable(),
- InlinedAt, Ctx));
+ DVI->setOperand(2, MetadataAsValue::get(
+ Ctx, createInlinedVariable(DVI->getVariable(),
+ InlinedAt, Ctx)));
}
}
}
SmallVector<uint32_t, 8> Weights;
for (unsigned MD_i = 1, MD_e = MD->getNumOperands(); MD_i < MD_e;
++MD_i) {
- ConstantInt* CI = dyn_cast<ConstantInt>(MD->getOperand(MD_i));
+ ConstantInt *CI =
+ mdconst::dyn_extract<ConstantInt>(MD->getOperand(MD_i));
assert(CI);
Weights.push_back(CI->getValue().getZExtValue());
}
SI->getDefaultDest());
MDNode *MD = SI->getMetadata(LLVMContext::MD_prof);
if (MD && MD->getNumOperands() == 3) {
- ConstantInt *SICase = dyn_cast<ConstantInt>(MD->getOperand(2));
- ConstantInt *SIDef = dyn_cast<ConstantInt>(MD->getOperand(1));
+ ConstantInt *SICase =
+ mdconst::dyn_extract<ConstantInt>(MD->getOperand(2));
+ ConstantInt *SIDef =
+ mdconst::dyn_extract<ConstantInt>(MD->getOperand(1));
assert(SICase && SIDef);
// The TrueWeight should be the weight for the single case of SI.
NewBr->setMetadata(LLVMContext::MD_prof,
/// LowerDbgDeclare - Lowers llvm.dbg.declare intrinsics into appropriate set
/// of llvm.dbg.value intrinsics.
bool llvm::LowerDbgDeclare(Function &F) {
- DIBuilder DIB(*F.getParent());
+ DIBuilder DIB(*F.getParent(), /*AllowUnresolved*/ false);
SmallVector<DbgDeclareInst *, 4> Dbgs;
for (auto &FI : F)
for (BasicBlock::iterator BI : FI)
/// FindAllocaDbgDeclare - Finds the llvm.dbg.declare intrinsic describing the
/// alloca 'V', if any.
DbgDeclareInst *llvm::FindAllocaDbgDeclare(Value *V) {
- if (MDNode *DebugNode = MDNode::getIfExists(V->getContext(), V))
- for (User *U : DebugNode->users())
- if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(U))
- return DDI;
+ if (auto *L = LocalAsMetadata::getIfExists(V))
+ if (auto *MDV = MetadataAsValue::getIfExists(V->getContext(), L))
+ for (User *U : MDV->users())
+ if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(U))
+ return DDI;
return nullptr;
}
}
if (NewLoop) {
// Add unroll disable metadata to disable future unrolling for this loop.
- SmallVector<Value *, 4> Vals;
+ SmallVector<Metadata *, 4> MDs;
// Reserve first location for self reference to the LoopID metadata node.
- Vals.push_back(nullptr);
+ MDs.push_back(nullptr);
MDNode *LoopID = NewLoop->getLoopID();
if (LoopID) {
// First remove any existing loop unrolling metadata.
const MDString *S = dyn_cast<MDString>(MD->getOperand(0));
IsUnrollMetadata = S && S->getString().startswith("llvm.loop.unroll.");
}
- if (!IsUnrollMetadata) Vals.push_back(LoopID->getOperand(i));
+ if (!IsUnrollMetadata)
+ MDs.push_back(LoopID->getOperand(i));
}
}
LLVMContext &Context = NewLoop->getHeader()->getContext();
- SmallVector<Value *, 1> DisableOperands;
+ SmallVector<Metadata *, 1> DisableOperands;
DisableOperands.push_back(MDString::get(Context, "llvm.loop.unroll.disable"));
MDNode *DisableNode = MDNode::get(Context, DisableOperands);
- Vals.push_back(DisableNode);
+ MDs.push_back(DisableNode);
- MDNode *NewLoopID = MDNode::get(Context, Vals);
+ MDNode *NewLoopID = MDNode::get(Context, MDs);
// Set operand 0 to refer to the loop id itself.
NewLoopID->replaceOperandWith(0, NewLoopID);
NewLoop->setLoopID(NewLoopID);
PromoteMem2Reg(ArrayRef<AllocaInst *> Allocas, DominatorTree &DT,
AliasSetTracker *AST, AssumptionTracker *AT)
: Allocas(Allocas.begin(), Allocas.end()), DT(DT),
- DIB(*DT.getRoot()->getParent()->getParent()), AST(AST), AT(AT) {}
+ DIB(*DT.getRoot()->getParent()->getParent(), /*AllowUnresolved*/ false),
+ AST(AST), AT(AT) {}
void run();
// Record debuginfo for the store and remove the declaration's
// debuginfo.
if (DbgDeclareInst *DDI = Info.DbgDeclare) {
- DIBuilder DIB(*AI->getParent()->getParent()->getParent());
+ DIBuilder DIB(*AI->getParent()->getParent()->getParent(),
+ /*AllowUnresolved*/ false);
ConvertDebugDeclareToDebugValue(DDI, Info.OnlyStore, DIB);
DDI->eraseFromParent();
LBI.deleteValue(DDI);
StoreInst *SI = cast<StoreInst>(AI->user_back());
// Record debuginfo for the store before removing it.
if (DbgDeclareInst *DDI = Info.DbgDeclare) {
- DIBuilder DIB(*AI->getParent()->getParent()->getParent());
+ DIBuilder DIB(*AI->getParent()->getParent()->getParent(),
+ /*AllowUnresolved*/ false);
ConvertDebugDeclareToDebugValue(DDI, SI, DIB);
}
SI->eraseFromParent();
if (HasWeight)
for (unsigned MD_i = 1, MD_e = MD->getNumOperands(); MD_i < MD_e;
++MD_i) {
- ConstantInt* CI = dyn_cast<ConstantInt>(MD->getOperand(MD_i));
- assert(CI);
+ ConstantInt *CI = mdconst::extract<ConstantInt>(MD->getOperand(MD_i));
Weights.push_back(CI->getValue().getZExtValue());
}
for (SwitchInst::CaseIt i = SI->case_end(), e = SI->case_begin(); i != e;) {
MDNode *MD = TI->getMetadata(LLVMContext::MD_prof);
assert(MD);
for (unsigned i = 1, e = MD->getNumOperands(); i < e; ++i) {
- ConstantInt *CI = cast<ConstantInt>(MD->getOperand(i));
+ ConstantInt *CI = mdconst::extract<ConstantInt>(MD->getOperand(i));
Weights.push_back(CI->getValue().getZExtValue());
}
"Looking for probabilities on unconditional branch?");
MDNode *ProfileData = BI->getMetadata(LLVMContext::MD_prof);
if (!ProfileData || ProfileData->getNumOperands() != 3) return false;
- ConstantInt *CITrue = dyn_cast<ConstantInt>(ProfileData->getOperand(1));
- ConstantInt *CIFalse = dyn_cast<ConstantInt>(ProfileData->getOperand(2));
+ ConstantInt *CITrue =
+ mdconst::dyn_extract<ConstantInt>(ProfileData->getOperand(1));
+ ConstantInt *CIFalse =
+ mdconst::dyn_extract<ConstantInt>(ProfileData->getOperand(2));
if (!CITrue || !CIFalse) return false;
ProbTrue = CITrue->getValue().getZExtValue();
ProbFalse = CIFalse->getValue().getZExtValue();
// Global values do not need to be seeded into the VM if they
// are using the identity mapping.
- if (isa<GlobalValue>(V) || isa<MDString>(V))
+ if (isa<GlobalValue>(V))
return VM[V] = const_cast<Value*>(V);
if (const InlineAsm *IA = dyn_cast<InlineAsm>(V)) {
return VM[V] = const_cast<Value*>(V);
}
-
- if (const MDNode *MD = dyn_cast<MDNode>(V)) {
+ if (const auto *MDV = dyn_cast<MetadataAsValue>(V)) {
+ const Metadata *MD = MDV->getMetadata();
// If this is a module-level metadata and we know that nothing at the module
// level is changing, then use an identity mapping.
- if (!MD->isFunctionLocal() && (Flags & RF_NoModuleLevelChanges))
- return VM[V] = const_cast<Value*>(V);
-
- // Create a dummy node in case we have a metadata cycle.
- MDNode *Dummy = MDNode::getTemporary(V->getContext(), None);
- VM[V] = Dummy;
-
- // Check all operands to see if any need to be remapped.
- for (unsigned i = 0, e = MD->getNumOperands(); i != e; ++i) {
- Value *OP = MD->getOperand(i);
- if (!OP) continue;
- Value *Mapped_OP = MapValue(OP, VM, Flags, TypeMapper, Materializer);
- // Use identity map if Mapped_Op is null and we can ignore missing
- // entries.
- if (Mapped_OP == OP ||
- (Mapped_OP == nullptr && (Flags & RF_IgnoreMissingEntries)))
- continue;
-
- // Ok, at least one operand needs remapping.
- SmallVector<Value*, 4> Elts;
- Elts.reserve(MD->getNumOperands());
- for (i = 0; i != e; ++i) {
- Value *Op = MD->getOperand(i);
- if (!Op)
- Elts.push_back(nullptr);
- else {
- Value *Mapped_Op = MapValue(Op, VM, Flags, TypeMapper, Materializer);
- // Use identity map if Mapped_Op is null and we can ignore missing
- // entries.
- if (Mapped_Op == nullptr && (Flags & RF_IgnoreMissingEntries))
- Mapped_Op = Op;
- Elts.push_back(Mapped_Op);
- }
- }
- MDNode *NewMD = MDNode::get(V->getContext(), Elts);
- Dummy->replaceAllUsesWith(NewMD);
- VM[V] = NewMD;
- MDNode::deleteTemporary(Dummy);
- return NewMD;
- }
+ if (!isa<LocalAsMetadata>(MD) && (Flags & RF_NoModuleLevelChanges))
+ return VM[V] = const_cast<Value *>(V);
- VM[V] = const_cast<Value*>(V);
- MDNode::deleteTemporary(Dummy);
+ auto *MappedMD = MapValue(MD, VM, Flags, TypeMapper, Materializer);
+ if (MD == MappedMD || (!MappedMD && (Flags & RF_IgnoreMissingEntries)))
+ return VM[V] = const_cast<Value *>(V);
- // No operands needed remapping. Use an identity mapping.
- return const_cast<Value*>(V);
+ // FIXME: This assert crashes during bootstrap, but I think it should be
+ // correct. For now, just match behaviour from before the metadata/value
+ // split.
+ //
+ // assert(MappedMD && "Referenced metadata value not in value map");
+ return VM[V] = MetadataAsValue::get(V->getContext(), MappedMD);
}
// Okay, this either must be a constant (which may or may not be mappable) or
return VM[V] = ConstantPointerNull::get(cast<PointerType>(NewTy));
}
+static Metadata *map(ValueToValueMapTy &VM, const Metadata *Key,
+ Metadata *Val) {
+ VM.MD()[Key].reset(Val);
+ return Val;
+}
+
+static Metadata *mapToSelf(ValueToValueMapTy &VM, const Metadata *MD) {
+ return map(VM, MD, const_cast<Metadata *>(MD));
+}
+
+static Metadata *MapValueImpl(const Metadata *MD, ValueToValueMapTy &VM,
+ RemapFlags Flags,
+ ValueMapTypeRemapper *TypeMapper,
+ ValueMaterializer *Materializer) {
+ // If the value already exists in the map, use it.
+ if (Metadata *NewMD = VM.MD().lookup(MD).get())
+ return NewMD;
+
+ if (isa<MDString>(MD))
+ return mapToSelf(VM, MD);
+
+ if (isa<ConstantAsMetadata>(MD))
+ if ((Flags & RF_NoModuleLevelChanges))
+ return mapToSelf(VM, MD);
+
+ if (const auto *VMD = dyn_cast<ValueAsMetadata>(MD)) {
+ Value *MappedV =
+ MapValue(VMD->getValue(), VM, Flags, TypeMapper, Materializer);
+ if (VMD->getValue() == MappedV ||
+ (!MappedV && (Flags & RF_IgnoreMissingEntries)))
+ return mapToSelf(VM, MD);
+
+ // FIXME: This assert crashes during bootstrap, but I think it should be
+ // correct. For now, just match behaviour from before the metadata/value
+ // split.
+ //
+ // assert(MappedV && "Referenced metadata not in value map!");
+ if (MappedV)
+ return map(VM, MD, ValueAsMetadata::get(MappedV));
+ return nullptr;
+ }
+
+ const MDNode *Node = cast<MDNode>(MD);
+ assert(Node->isResolved() && "Unexpected unresolved node");
+
+ auto getMappedOp = [&](Metadata *Op) -> Metadata *{
+ if (!Op)
+ return nullptr;
+ if (Metadata *MappedOp =
+ MapValueImpl(Op, VM, Flags, TypeMapper, Materializer))
+ return MappedOp;
+ // Use identity map if MappedOp is null and we can ignore missing entries.
+ if (Flags & RF_IgnoreMissingEntries)
+ return Op;
+
+ // FIXME: This assert crashes during bootstrap, but I think it should be
+ // correct. For now, just match behaviour from before the metadata/value
+ // split.
+ //
+ // llvm_unreachable("Referenced metadata not in value map!");
+ return nullptr;
+ };
+
+ // If this is a module-level metadata and we know that nothing at the
+ // module level is changing, then use an identity mapping.
+ if (Flags & RF_NoModuleLevelChanges)
+ return mapToSelf(VM, MD);
+
+ // Create a dummy node in case we have a metadata cycle.
+ MDNodeFwdDecl *Dummy = MDNode::getTemporary(Node->getContext(), None);
+ map(VM, Node, Dummy);
+
+ // Check all operands to see if any need to be remapped.
+ for (unsigned I = 0, E = Node->getNumOperands(); I != E; ++I) {
+ Metadata *Op = Node->getOperand(I);
+ Metadata *MappedOp = getMappedOp(Op);
+ if (Op == MappedOp)
+ continue;
+
+ // Ok, at least one operand needs remapping.
+ SmallVector<Metadata *, 4> Elts;
+ Elts.reserve(Node->getNumOperands());
+ for (I = 0; I != E; ++I)
+ Elts.push_back(getMappedOp(Node->getOperand(I)));
+
+ MDNode *NewMD = MDNode::get(Node->getContext(), Elts);
+ Dummy->replaceAllUsesWith(NewMD);
+ MDNode::deleteTemporary(Dummy);
+ return map(VM, Node, NewMD);
+ }
+
+ // No operands needed remapping. Use an identity mapping.
+ mapToSelf(VM, MD);
+ MDNode::deleteTemporary(Dummy);
+ return const_cast<Metadata *>(MD);
+}
+
+Metadata *llvm::MapValue(const Metadata *MD, ValueToValueMapTy &VM,
+ RemapFlags Flags, ValueMapTypeRemapper *TypeMapper,
+ ValueMaterializer *Materializer) {
+ Metadata *NewMD = MapValueImpl(MD, VM, Flags, TypeMapper, Materializer);
+ if (NewMD && NewMD != MD)
+ if (auto *G = dyn_cast<GenericMDNode>(NewMD))
+ G->resolveCycles();
+ return NewMD;
+}
+
+MDNode *llvm::MapValue(const MDNode *MD, ValueToValueMapTy &VM,
+ RemapFlags Flags, ValueMapTypeRemapper *TypeMapper,
+ ValueMaterializer *Materializer) {
+ return cast<MDNode>(MapValue(static_cast<const Metadata *>(MD), VM, Flags,
+ TypeMapper, Materializer));
+}
+
/// RemapInstruction - Convert the instruction operands from referencing the
/// current values into those specified by VMap.
///
for (unsigned i = 1, ie = LoopID->getNumOperands(); i < ie; ++i) {
const MDString *S = nullptr;
- SmallVector<Value*, 4> Args;
+ SmallVector<Metadata *, 4> Args;
// The expected hint is either a MDString or a MDNode with the first
// operand a MDString.
}
/// Checks string hint with one operand and set value if valid.
- void setHint(StringRef Name, Value *Arg) {
+ void setHint(StringRef Name, Metadata *Arg) {
if (!Name.startswith(Prefix()))
return;
Name = Name.substr(Prefix().size(), StringRef::npos);
- const ConstantInt *C = dyn_cast<ConstantInt>(Arg);
+ const ConstantInt *C = mdconst::dyn_extract<ConstantInt>(Arg);
if (!C) return;
unsigned Val = C->getZExtValue();
/// Create a new hint from name / value pair.
MDNode *createHintMetadata(StringRef Name, unsigned V) const {
LLVMContext &Context = TheLoop->getHeader()->getContext();
- Value *Vals[] = {MDString::get(Context, Name),
- ConstantInt::get(Type::getInt32Ty(Context), V)};
- return MDNode::get(Context, Vals);
+ Metadata *MDs[] = {MDString::get(Context, Name),
+ ConstantAsMetadata::get(
+ ConstantInt::get(Type::getInt32Ty(Context), V))};
+ return MDNode::get(Context, MDs);
}
/// Matches metadata with hint name.
return;
// Reserve the first element to LoopID (see below).
- SmallVector<Value*, 4> Vals(1);
+ SmallVector<Metadata *, 4> MDs(1);
// If the loop already has metadata, then ignore the existing operands.
MDNode *LoopID = TheLoop->getLoopID();
if (LoopID) {
MDNode *Node = cast<MDNode>(LoopID->getOperand(i));
// If node in update list, ignore old value.
if (!matchesHintMetadataName(Node, HintTypes))
- Vals.push_back(Node);
+ MDs.push_back(Node);
}
}
// Now, add the missing hints.
for (auto H : HintTypes)
- Vals.push_back(
- createHintMetadata(Twine(Prefix(), H.Name).str(), H.Value));
+ MDs.push_back(createHintMetadata(Twine(Prefix(), H.Name).str(), H.Value));
// Replace current metadata node with new one.
LLVMContext &Context = TheLoop->getHeader()->getContext();
- MDNode *NewLoopID = MDNode::get(Context, Vals);
+ MDNode *NewLoopID = MDNode::get(Context, MDs);
// Set operand 0 to refer to the loop id itself.
NewLoopID->replaceOperandWith(0, NewLoopID);
define void @foo(i32 %v) {
entry:
-; CHECK: <stdin>:[[@LINE+1]]:{{[0-9]+}}: error: unexpected function-local metadata
+; CHECK: <stdin>:[[@LINE+1]]:{{[0-9]+}}: error: invalid use of function-local name
ret void, !foo !{i32 %v}
}
define void @foo(i32 %v) {
entry:
-; CHECK: <stdin>:[[@LINE+1]]:{{[0-9]+}}: error: unexpected nested function-local metadata
+; CHECK: <stdin>:[[@LINE+1]]:{{[0-9]+}}: error: invalid use of function-local name
call void @llvm.bar(metadata !{metadata !{i32 %v}})
ret void
}
; PR7105
define void @foo(i32 %x) {
- call void @llvm.zonk(metadata !1, i64 0, metadata !1)
+ call void @llvm.zonk(metadata !{i32 %x}, i64 0, metadata !1)
store i32 0, i32* null, !whatever !0, !whatever_else !{}, !more !{metadata !"hello"}
store i32 0, i32* null, !whatever !{metadata !"hello", metadata !1, metadata !{}, metadata !2}
ret void
--- /dev/null
+!named = !{!0}
+
+; These nodes are intentionally in the opposite order from the test-driver.
+; However, they are numbered the same for the reader's convenience.
+!1 = metadata !{}
+!0 = metadata !{metadata !1}
--- /dev/null
+; RUN: llvm-link %s %S/Inputs/unique-fwd-decl-order.ll -S -o - | FileCheck %s
+; RUN: llvm-link %S/Inputs/unique-fwd-decl-order.ll %s -S -o - | FileCheck %s
+
+; This test exercises MDNode hashing. For the nodes to be correctly uniqued,
+; the hash of a to-be-created MDNode has to match the hash of an
+; operand-just-changed MDNode (with the same operands).
+;
+; Note that these two assembly files number the nodes identically, even though
+; the nodes are in a different order. This is for the reader's convenience.
+
+; CHECK: !named = !{!0, !0}
+!named = !{!0}
+
+; CHECK: !0 = metadata !{metadata !1}
+!0 = metadata !{metadata !1}
+
+; CHECK: !1 = metadata !{}
+!1 = metadata !{}
+
+; CHECK-NOT: !2
}
define void @foo(i32 %x) {
- call void @llvm.foo(metadata !{i8*** @G})
-; CHECK: call void @llvm.foo(metadata !0)
+; Note: these arguments look like MDNodes, but they're really syntactic sugar
+; for 'MetadataAsValue::get(ValueAsMetadata::get(Value*))'. When @G drops to
+; null, the ValueAsMetadata instance gets replaced by metadata !{}, or
+; MDNode::get({}).
+ call void @llvm.foo(metadata !{i8*** @G}, metadata !{i32 %x})
+; CHECK: call void @llvm.foo(metadata ![[EMPTY:[0-9]+]], metadata !{i32 %x})
ret void
}
-declare void @llvm.foo(metadata) nounwind readnone
+declare void @llvm.foo(metadata, metadata) nounwind readnone
!named = !{!0}
-; CHECK: !named = !{!0}
+; CHECK: !named = !{![[NULL:[0-9]+]]}
!0 = metadata !{i8*** @G}
-; CHECK: !0 = metadata !{null}
+; CHECK-DAG: ![[NULL]] = metadata !{null}
+; CHECK-DAG: ![[EMPTY]] = metadata !{}
EXPECT_EQ(MD0, (MDNode *)nullptr);
EXPECT_NE(MD1, (MDNode *)nullptr);
EXPECT_EQ(MD1->getNumOperands(), 1U);
- Value *Op = MD1->getOperand(0);
- EXPECT_TRUE(isa<ConstantFP>(Op));
- EXPECT_TRUE(Op->getType()->isFloatingPointTy());
- ConstantFP *Val = cast<ConstantFP>(Op);
+ Metadata *Op = MD1->getOperand(0);
+ EXPECT_TRUE(mdconst::hasa<ConstantFP>(Op));
+ ConstantFP *Val = mdconst::extract<ConstantFP>(Op);
+ EXPECT_TRUE(Val->getType()->isFloatingPointTy());
EXPECT_TRUE(Val->isExactlyValue(1.0));
}
TEST_F(MDBuilderTest, createRangeMetadata) {
EXPECT_EQ(R0, (MDNode *)nullptr);
EXPECT_NE(R1, (MDNode *)nullptr);
EXPECT_EQ(R1->getNumOperands(), 2U);
- EXPECT_TRUE(isa<ConstantInt>(R1->getOperand(0)));
- EXPECT_TRUE(isa<ConstantInt>(R1->getOperand(1)));
- ConstantInt *C0 = cast<ConstantInt>(R1->getOperand(0));
- ConstantInt *C1 = cast<ConstantInt>(R1->getOperand(1));
+ EXPECT_TRUE(mdconst::hasa<ConstantInt>(R1->getOperand(0)));
+ EXPECT_TRUE(mdconst::hasa<ConstantInt>(R1->getOperand(1)));
+ ConstantInt *C0 = mdconst::extract<ConstantInt>(R1->getOperand(0));
+ ConstantInt *C1 = mdconst::extract<ConstantInt>(R1->getOperand(1));
EXPECT_EQ(C0->getValue(), A);
EXPECT_EQ(C1->getValue(), B);
}
EXPECT_EQ(N0->getOperand(1), R);
EXPECT_EQ(N1->getOperand(1), R);
EXPECT_EQ(N2->getOperand(1), R);
- EXPECT_TRUE(isa<ConstantInt>(N2->getOperand(2)));
- EXPECT_EQ(cast<ConstantInt>(N2->getOperand(2))->getZExtValue(), 1U);
+ EXPECT_TRUE(mdconst::hasa<ConstantInt>(N2->getOperand(2)));
+ EXPECT_EQ(mdconst::extract<ConstantInt>(N2->getOperand(2))->getZExtValue(),
+ 1U);
}
}
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
-#include "llvm/IR/ValueHandle.h"
#include "llvm/Support/raw_ostream.h"
#include "gtest/gtest.h"
using namespace llvm;
MDString *s1 = MDString::get(Context, StringRef(&x[0], 3));
MDString *s2 = MDString::get(Context, StringRef(&y[0], 3));
- ConstantInt *CI = ConstantInt::get(getGlobalContext(), APInt(8, 0));
+ ConstantAsMetadata *CI = ConstantAsMetadata::get(
+ ConstantInt::get(getGlobalContext(), APInt(8, 0)));
- std::vector<Value *> V;
+ std::vector<Metadata *> V;
V.push_back(s1);
V.push_back(CI);
V.push_back(s2);
MDNode *n1 = MDNode::get(Context, V);
- Value *const c1 = n1;
+ Metadata *const c1 = n1;
MDNode *n2 = MDNode::get(Context, c1);
- Value *const c2 = n2;
+ Metadata *const c2 = n2;
MDNode *n3 = MDNode::get(Context, V);
MDNode *n4 = MDNode::getIfExists(Context, V);
MDNode *n5 = MDNode::getIfExists(Context, c1);
EXPECT_EQ(n1, n3);
EXPECT_EQ(n4, n1);
EXPECT_EQ(n5, n2);
- EXPECT_EQ(n6, (Value*)nullptr);
+ EXPECT_EQ(n6, (Metadata *)nullptr);
EXPECT_EQ(3u, n1->getNumOperands());
EXPECT_EQ(s1, n1->getOperand(0));
Constant *C = ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 1);
Instruction *I = new BitCastInst(C, Type::getInt32Ty(getGlobalContext()));
- Value *const V = I;
+ Metadata *const V = LocalAsMetadata::get(I);
MDNode *n = MDNode::get(Context, V);
- WeakVH wvh = n;
+ TrackingMDRef wvh(n);
EXPECT_EQ(n, wvh);
// !1 = metadata !{metadata !0}
{
MDNode *Temp = MDNode::getTemporary(Context, None);
- Value *Args[] = {Temp};
+ Metadata *Args[] = {Temp};
MDNode *Self = MDNode::get(Context, Args);
Self->replaceOperandWith(0, Self);
MDNode::deleteTemporary(Temp);
// !1 = metadata !{metadata !0, metadata !{}}
{
MDNode *Temp = MDNode::getTemporary(Context, None);
- Value *Args[] = {Temp, MDNode::get(Context, None)};
+ Metadata *Args[] = {Temp, MDNode::get(Context, None)};
MDNode *Self = MDNode::get(Context, Args);
Self->replaceOperandWith(0, Self);
MDNode::deleteTemporary(Temp);
}
}
+typedef MetadataTest MetadataAsValueTest;
+
+TEST_F(MetadataAsValueTest, MDNode) {
+ MDNode *N = MDNode::get(Context, None);
+ auto *V = MetadataAsValue::get(Context, N);
+ EXPECT_TRUE(V->getType()->isMetadataTy());
+ EXPECT_EQ(N, V->getMetadata());
+
+ auto *V2 = MetadataAsValue::get(Context, N);
+ EXPECT_EQ(V, V2);
+}
+
+TEST_F(MetadataAsValueTest, MDNodeMDNode) {
+ MDNode *N = MDNode::get(Context, None);
+ Metadata *Ops[] = {N};
+ MDNode *N2 = MDNode::get(Context, Ops);
+ auto *V = MetadataAsValue::get(Context, N2);
+ EXPECT_TRUE(V->getType()->isMetadataTy());
+ EXPECT_EQ(N2, V->getMetadata());
+
+ auto *V2 = MetadataAsValue::get(Context, N2);
+ EXPECT_EQ(V, V2);
+
+ auto *V3 = MetadataAsValue::get(Context, N);
+ EXPECT_TRUE(V3->getType()->isMetadataTy());
+ EXPECT_NE(V, V3);
+ EXPECT_EQ(N, V3->getMetadata());
+}
+
+TEST_F(MetadataAsValueTest, MDNodeConstant) {
+ auto *C = ConstantInt::getTrue(Context);
+ auto *MD = ConstantAsMetadata::get(C);
+ Metadata *Ops[] = {MD};
+ auto *N = MDNode::get(Context, Ops);
+
+ auto *V = MetadataAsValue::get(Context, MD);
+ EXPECT_TRUE(V->getType()->isMetadataTy());
+ EXPECT_EQ(MD, V->getMetadata());
+
+ auto *V2 = MetadataAsValue::get(Context, N);
+ EXPECT_EQ(MD, V2->getMetadata());
+ EXPECT_EQ(V, V2);
+}
+
TEST(NamedMDNodeTest, Search) {
LLVMContext Context;
- Constant *C = ConstantInt::get(Type::getInt32Ty(Context), 1);
- Constant *C2 = ConstantInt::get(Type::getInt32Ty(Context), 2);
+ ConstantAsMetadata *C =
+ ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(Context), 1));
+ ConstantAsMetadata *C2 =
+ ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(Context), 2));
- Value *const V = C;
- Value *const V2 = C2;
+ Metadata *const V = C;
+ Metadata *const V2 = C2;
MDNode *n = MDNode::get(Context, V);
MDNode *n2 = MDNode::get(Context, V2);