[llvm] r223802 - IR: Split Metadata from Value
Duncan P. N. Exon Smith
dexonsmith at apple.com
Tue Dec 9 13:42:14 PST 2014
Saw it. I'm already going through the instructions for how to build
LLDB. Seems pretty different from how LLVM usually works, so it's taking
me a while to get through it.
I suspect the fixes are trivial, so if I'm too slow for you, you might
try these transformations yourself:
- Value *Ops[] => Metadata *Ops[]
- cast<ConstantInt>(N->getOperand(0)) =>
mdconst::extract<ConstantInt>(N->getOperand(0))
- Value *Op = ConstantInt::get(...) =>
Metadata *Op = ConstantAsMetadata::get(ConstantInt::get(...))
Sorry for the failures :(. I'll be as fast as I can.
> On 2014 Dec 9, at 13:35, Zachary Turner <zturner at google.com> wrote:
>
> LLDB build is also broken in multiple places, and not just on MSVC. I'm not sure how to fix some of these. Would you mind fixing them?
>
> On Tue Dec 09 2014 at 10:43:10 AM Duncan P. N. Exon Smith <dexonsmith at apple.com> wrote:
> Author: dexonsmith
> Date: Tue Dec 9 12:38:53 2014
> New Revision: 223802
>
> URL: http://llvm.org/viewvc/llvm-project?rev=223802&view=rev
> Log:
> IR: Split Metadata from Value
>
> Split `Metadata` away from the `Value` class hierarchy, as part of
> PR21532. Assembly and bitcode changes are in the wings, but this is the
> bulk of the change for the IR C++ API.
>
> I have a follow-up patch prepared for `clang`. If this breaks other
> sub-projects, I apologize in advance :(. Help me compile it on Darwin
> I'll try to fix it. FWIW, the errors should be easy to fix, so it may
> be simpler to just fix it yourself.
>
> This breaks the build for all metadata-related code that's out-of-tree.
> Rest assured the transition is mechanical and the compiler should catch
> almost all of the problems.
>
> Here's a quick guide for updating your code:
>
> - `Metadata` is the root of a class hierarchy with three main classes:
> `MDNode`, `MDString`, and `ValueAsMetadata`. It is distinct from
> the `Value` class hierarchy. It is typeless -- i.e., instances do
> *not* have a `Type`.
>
> - `MDNode`'s operands are all `Metadata *` (instead of `Value *`).
>
> - `TrackingVH<MDNode>` and `WeakVH` referring to metadata can be
> replaced with `TrackingMDNodeRef` and `TrackingMDRef`, respectively.
>
> If you're referring solely to resolved `MDNode`s -- post graph
> construction -- just use `MDNode*`.
>
> - `MDNode` (and the rest of `Metadata`) have only limited support for
> `replaceAllUsesWith()`.
>
> As long as an `MDNode` is pointing at a forward declaration -- the
> result of `MDNode::getTemporary()` -- it maintains a side map of its
> uses and can RAUW itself. Once the forward declarations are fully
> resolved RAUW support is dropped on the ground. This means that
> uniquing collisions on changing operands cause nodes to become
> "distinct". (This already happened fairly commonly, whenever an
> operand went to null.)
>
> If you're constructing complex (non self-reference) `MDNode` cycles,
> you need to call `MDNode::resolveCycles()` on each node (or on a
> top-level node that somehow references all of the nodes). Also,
> don't do that. Metadata cycles (and the RAUW machinery needed to
> construct them) are expensive.
>
> - An `MDNode` can only refer to a `Constant` through a bridge called
> `ConstantAsMetadata` (one of the subclasses of `ValueAsMetadata`).
>
> As a side effect, accessing an operand of an `MDNode` that is known
> to be, e.g., `ConstantInt`, takes three steps: first, cast from
> `Metadata` to `ConstantAsMetadata`; second, extract the `Constant`;
> third, cast down to `ConstantInt`.
>
> The eventual goal is to introduce `MDInt`/`MDFloat`/etc. and have
> metadata schema owners transition away from using `Constant`s when
> the type isn't important (and they don't care about referring to
> `GlobalValue`s).
>
> In the meantime, I've added transitional API to the `mdconst`
> namespace that matches semantics with the old code, in order to
> avoid adding the error-prone three-step equivalent to every call
> site. If your old code was:
>
> MDNode *N = foo();
> bar(isa <ConstantInt>(N->getOperand(0)));
> baz(cast <ConstantInt>(N->getOperand(1)));
> bak(cast_or_null <ConstantInt>(N->getOperand(2)));
> bat(dyn_cast <ConstantInt>(N->getOperand(3)));
> bay(dyn_cast_or_null<ConstantInt>(N->getOperand(4)));
>
> you can trivially match its semantics with:
>
> MDNode *N = foo();
> bar(mdconst::hasa <ConstantInt>(N->getOperand(0)));
> baz(mdconst::extract <ConstantInt>(N->getOperand(1)));
> bak(mdconst::extract_or_null <ConstantInt>(N->getOperand(2)));
> bat(mdconst::dyn_extract <ConstantInt>(N->getOperand(3)));
> bay(mdconst::dyn_extract_or_null<ConstantInt>(N->getOperand(4)));
>
> and when you transition your metadata schema to `MDInt`:
>
> MDNode *N = foo();
> bar(isa <MDInt>(N->getOperand(0)));
> baz(cast <MDInt>(N->getOperand(1)));
> bak(cast_or_null <MDInt>(N->getOperand(2)));
> bat(dyn_cast <MDInt>(N->getOperand(3)));
> bay(dyn_cast_or_null<MDInt>(N->getOperand(4)));
>
> - A `CallInst` -- specifically, intrinsic instructions -- can refer to
> metadata through a bridge called `MetadataAsValue`. This is a
> subclass of `Value` where `getType()->isMetadataTy()`.
>
> `MetadataAsValue` is the *only* class that can legally refer to a
> `LocalAsMetadata`, which is a bridged form of non-`Constant` values
> like `Argument` and `Instruction`. It can also refer to any other
> `Metadata` subclass.
>
> (I'll break all your testcases in a follow-up commit, when I propagate
> this change to assembly.)
>
> Added:
> llvm/trunk/include/llvm/IR/Metadata.def
> llvm/trunk/include/llvm/IR/MetadataTracking.h
> llvm/trunk/include/llvm/IR/TrackingMDRef.h
> llvm/trunk/lib/IR/MetadataTracking.cpp
> llvm/trunk/test/Linker/Inputs/unique-fwd-decl-order.ll
> llvm/trunk/test/Linker/unique-fwd-decl-order.ll
> Modified:
> llvm/trunk/bindings/go/llvm/DIBuilderBindings.cpp
> llvm/trunk/include/llvm-c/Core.h
> llvm/trunk/include/llvm/CodeGen/LexicalScopes.h
> llvm/trunk/include/llvm/CodeGen/MachineInstr.h
> llvm/trunk/include/llvm/CodeGen/MachineModuleInfo.h
> llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h
> llvm/trunk/include/llvm/IR/DIBuilder.h
> llvm/trunk/include/llvm/IR/DebugInfo.h
> llvm/trunk/include/llvm/IR/DebugLoc.h
> llvm/trunk/include/llvm/IR/IntrinsicInst.h
> llvm/trunk/include/llvm/IR/MDBuilder.h
> llvm/trunk/include/llvm/IR/Metadata.h
> llvm/trunk/include/llvm/IR/Module.h
> llvm/trunk/include/llvm/IR/TypeFinder.h
> llvm/trunk/include/llvm/IR/Value.h
> llvm/trunk/include/llvm/IR/ValueMap.h
> llvm/trunk/include/llvm/Transforms/Utils/ValueMapper.h
> llvm/trunk/lib/Analysis/BranchProbabilityInfo.cpp
> llvm/trunk/lib/Analysis/ScalarEvolution.cpp
> llvm/trunk/lib/Analysis/TypeBasedAliasAnalysis.cpp
> llvm/trunk/lib/Analysis/ValueTracking.cpp
> llvm/trunk/lib/AsmParser/LLParser.cpp
> llvm/trunk/lib/AsmParser/LLParser.h
> llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
> llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h
> llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
> llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp
> llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.h
> llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
> llvm/trunk/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
> llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp
> llvm/trunk/lib/CodeGen/MachineInstr.cpp
> llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
> llvm/trunk/lib/CodeGen/StackColoring.cpp
> llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
> llvm/trunk/lib/IR/AsmWriter.cpp
> llvm/trunk/lib/IR/AutoUpgrade.cpp
> llvm/trunk/lib/IR/CMakeLists.txt
> llvm/trunk/lib/IR/Core.cpp
> llvm/trunk/lib/IR/DIBuilder.cpp
> llvm/trunk/lib/IR/DebugInfo.cpp
> llvm/trunk/lib/IR/DebugLoc.cpp
> llvm/trunk/lib/IR/DiagnosticInfo.cpp
> llvm/trunk/lib/IR/Instructions.cpp
> llvm/trunk/lib/IR/IntrinsicInst.cpp
> llvm/trunk/lib/IR/LLVMContextImpl.cpp
> llvm/trunk/lib/IR/LLVMContextImpl.h
> llvm/trunk/lib/IR/MDBuilder.cpp
> llvm/trunk/lib/IR/Metadata.cpp
> llvm/trunk/lib/IR/Module.cpp
> llvm/trunk/lib/IR/TypeFinder.cpp
> llvm/trunk/lib/IR/Value.cpp
> llvm/trunk/lib/IR/ValueSymbolTable.cpp
> llvm/trunk/lib/IR/Verifier.cpp
> llvm/trunk/lib/LTO/LTOModule.cpp
> llvm/trunk/lib/Linker/LinkModules.cpp
> llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp
> llvm/trunk/lib/Target/NVPTX/NVPTXGenericToNVVM.cpp
> llvm/trunk/lib/Target/NVPTX/NVPTXUtilities.cpp
> llvm/trunk/lib/Transforms/IPO/StripSymbols.cpp
> llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp
> llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp
> llvm/trunk/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
> llvm/trunk/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
> llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp
> llvm/trunk/lib/Transforms/Scalar/SROA.cpp
> llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp
> llvm/trunk/lib/Transforms/Utils/AddDiscriminators.cpp
> llvm/trunk/lib/Transforms/Utils/CloneFunction.cpp
> llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp
> llvm/trunk/lib/Transforms/Utils/Local.cpp
> llvm/trunk/lib/Transforms/Utils/LoopUnrollRuntime.cpp
> llvm/trunk/lib/Transforms/Utils/PromoteMemoryToRegister.cpp
> llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp
> llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp
> llvm/trunk/lib/Transforms/Vectorize/LoopVectorize.cpp
> llvm/trunk/test/Assembler/functionlocal-metadata-attachments.ll
> llvm/trunk/test/Assembler/functionlocal-metadata-complex-3.ll
> llvm/trunk/test/Feature/metadata.ll
> llvm/trunk/test/Transforms/GlobalOpt/metadata.ll
> llvm/trunk/unittests/IR/MDBuilderTest.cpp
> llvm/trunk/unittests/IR/MetadataTest.cpp
>
> Modified: llvm/trunk/bindings/go/llvm/DIBuilderBindings.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/bindings/go/llvm/DIBuilderBindings.cpp?rev=223802&r1=223801&r2=223802&view=diff
> ==============================================================================
> --- llvm/trunk/bindings/go/llvm/DIBuilderBindings.cpp (original)
> +++ llvm/trunk/bindings/go/llvm/DIBuilderBindings.cpp Tue Dec 9 12:38:53 2014
> @@ -18,10 +18,31 @@
>
> 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)
> @@ -47,14 +68,14 @@ LLVMValueRef LLVMDIBuilderCreateCompileU
> 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,
> @@ -64,7 +85,7 @@ LLVMValueRef LLVMDIBuilderCreateLexicalB
> 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,
> @@ -74,7 +95,7 @@ LLVMValueRef LLVMDIBuilderCreateLexicalB
> DIBuilder *D = unwrap(Dref);
> DILexicalBlockFile LBF = D->createLexicalBlockFile(
> unwrapDI<DIDescriptor>(Scope), unwrapDI<DIFile>(File), Discriminator);
> - return wrap(LBF);
> + return wrapDI(LBF);
> }
>
> LLVMValueRef LLVMDIBuilderCreateFunction(
> @@ -87,7 +108,7 @@ 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(
> @@ -98,7 +119,7 @@ LLVMValueRef LLVMDIBuilderCreateLocalVar
> 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,
> @@ -107,7 +128,7 @@ LLVMValueRef LLVMDIBuilderCreateBasicTyp
> unsigned Encoding) {
> DIBuilder *D = unwrap(Dref);
> DIBasicType T = D->createBasicType(Name, SizeInBits, AlignInBits, Encoding);
> - return wrap(T);
> + return wrapDI(T);
> }
>
> LLVMValueRef LLVMDIBuilderCreatePointerType(LLVMDIBuilderRef Dref,
> @@ -118,7 +139,7 @@ LLVMValueRef LLVMDIBuilderCreatePointerT
> DIBuilder *D = unwrap(Dref);
> DIDerivedType T = D->createPointerType(unwrapDI<DIType>(PointeeType),
> SizeInBits, AlignInBits, Name);
> - return wrap(T);
> + return wrapDI(T);
> }
>
> LLVMValueRef LLVMDIBuilderCreateSubroutineType(LLVMDIBuilderRef Dref,
> @@ -127,7 +148,7 @@ LLVMValueRef LLVMDIBuilderCreateSubrouti
> DIBuilder *D = unwrap(Dref);
> DICompositeType CT = D->createSubroutineType(
> unwrapDI<DIFile>(File), unwrapDI<DITypeArray>(ParameterTypes));
> - return wrap(CT);
> + return wrapDI(CT);
> }
>
> LLVMValueRef LLVMDIBuilderCreateStructType(
> @@ -139,7 +160,7 @@ LLVMValueRef LLVMDIBuilderCreateStructTy
> 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(
> @@ -150,7 +171,7 @@ LLVMValueRef LLVMDIBuilderCreateMemberTy
> 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,
> @@ -162,7 +183,7 @@ LLVMValueRef LLVMDIBuilderCreateArrayTyp
> DICompositeType CT =
> D->createArrayType(SizeInBits, AlignInBits, unwrapDI<DIType>(ElementType),
> unwrapDI<DIArray>(Subscripts));
> - return wrap(CT);
> + return wrapDI(CT);
> }
>
> LLVMValueRef LLVMDIBuilderCreateTypedef(LLVMDIBuilderRef Dref, LLVMValueRef Ty,
> @@ -172,40 +193,36 @@ LLVMValueRef LLVMDIBuilderCreateTypedef(
> 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,
>
> Modified: llvm/trunk/include/llvm-c/Core.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm-c/Core.h?rev=223802&r1=223801&r2=223802&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm-c/Core.h (original)
> +++ llvm/trunk/include/llvm-c/Core.h Tue Dec 9 12:38:53 2014
> @@ -1157,8 +1157,6 @@ LLVMTypeRef LLVMX86MMXType(void);
> macro(Argument) \
> macro(BasicBlock) \
> macro(InlineAsm) \
> - macro(MDNode) \
> - macro(MDString) \
> macro(User) \
> macro(Constant) \
> macro(BlockAddress) \
> @@ -1307,6 +1305,9 @@ LLVMBool LLVMIsUndef(LLVMValueRef Val);
> LLVMValueRef LLVMIsA##name(LLVMValueRef Val);
> LLVM_FOR_EACH_VALUE_SUBCLASS(LLVM_DECLARE_VALUE_CAST)
>
> +LLVMValueRef LLVMIsAMDNode(LLVMValueRef Val);
> +LLVMValueRef LLVMIsAMDString(LLVMValueRef Val);
> +
> /**
> * @}
> */
>
> Modified: llvm/trunk/include/llvm/CodeGen/LexicalScopes.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/LexicalScopes.h?rev=223802&r1=223801&r2=223802&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/CodeGen/LexicalScopes.h (original)
> +++ llvm/trunk/include/llvm/CodeGen/LexicalScopes.h Tue Dec 9 12:38:53 2014
> @@ -48,6 +48,8 @@ public:
> 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);
> }
> @@ -116,8 +118,8 @@ public:
>
> 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.
>
> Modified: llvm/trunk/include/llvm/CodeGen/MachineInstr.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineInstr.h?rev=223802&r1=223801&r2=223802&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/CodeGen/MachineInstr.h (original)
> +++ llvm/trunk/include/llvm/CodeGen/MachineInstr.h Tue Dec 9 12:38:53 2014
> @@ -1139,7 +1139,10 @@ public:
> /// 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.
>
> Modified: llvm/trunk/include/llvm/CodeGen/MachineModuleInfo.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineModuleInfo.h?rev=223802&r1=223801&r2=223802&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/CodeGen/MachineModuleInfo.h (original)
> +++ llvm/trunk/include/llvm/CodeGen/MachineModuleInfo.h Tue Dec 9 12:38:53 2014
> @@ -165,10 +165,13 @@ public:
> 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;
> @@ -393,8 +396,7 @@ public:
> /// 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; }
>
> Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h?rev=223802&r1=223801&r2=223802&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h (original)
> +++ llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h Tue Dec 9 12:38:53 2014
> @@ -762,6 +762,7 @@ protected:
> 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 &&
> @@ -780,6 +781,7 @@ protected:
> 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!");
> }
>
> Modified: llvm/trunk/include/llvm/IR/DIBuilder.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/DIBuilder.h?rev=223802&r1=223801&r2=223802&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/IR/DIBuilder.h (original)
> +++ llvm/trunk/include/llvm/IR/DIBuilder.h Tue Dec 9 12:38:53 2014
> @@ -18,6 +18,7 @@
> #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"
>
> @@ -65,22 +66,34 @@ namespace llvm {
> 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.
> @@ -437,10 +450,10 @@ namespace llvm {
> 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.
>
> Modified: llvm/trunk/include/llvm/IR/DebugInfo.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/DebugInfo.h?rev=223802&r1=223801&r2=223802&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/IR/DebugInfo.h (original)
> +++ llvm/trunk/include/llvm/IR/DebugInfo.h Tue Dec 9 12:38:53 2014
> @@ -168,8 +168,9 @@ public:
>
> 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.
> @@ -740,7 +741,7 @@ public:
>
> 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();
>
> Modified: llvm/trunk/include/llvm/IR/DebugLoc.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/DebugLoc.h?rev=223802&r1=223801&r2=223802&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/IR/DebugLoc.h (original)
> +++ llvm/trunk/include/llvm/IR/DebugLoc.h Tue Dec 9 12:38:53 2014
> @@ -16,50 +16,40 @@
> #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>;
> + TrackingMDNodeRef Loc;
>
> - /// 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;
> + 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;
> }
> -
> - /// 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;
> + 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);
> @@ -68,56 +58,54 @@ namespace llvm {
> 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 */
>
> Modified: llvm/trunk/include/llvm/IR/IntrinsicInst.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/IntrinsicInst.h?rev=223802&r1=223801&r2=223802&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/IR/IntrinsicInst.h (original)
> +++ llvm/trunk/include/llvm/IR/IntrinsicInst.h Tue Dec 9 12:38:53 2014
> @@ -28,6 +28,7 @@
> #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
> @@ -81,8 +82,14 @@ namespace llvm {
> 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) {
> @@ -103,8 +110,14 @@ namespace llvm {
> 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) {
>
> Modified: llvm/trunk/include/llvm/IR/MDBuilder.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/MDBuilder.h?rev=223802&r1=223801&r2=223802&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/IR/MDBuilder.h (original)
> +++ llvm/trunk/include/llvm/IR/MDBuilder.h Tue Dec 9 12:38:53 2014
> @@ -24,6 +24,8 @@ namespace llvm {
> class APInt;
> template <typename T> class ArrayRef;
> class LLVMContext;
> +class Constant;
> +class ConstantAsMetadata;
> class MDNode;
> class MDString;
>
> @@ -36,6 +38,9 @@ public:
> /// \brief Return the given string as metadata.
> MDString *createString(StringRef Str);
>
> + /// \brief Return the given constant as metadata.
> + ConstantAsMetadata *createConstant(Constant *C);
> +
> //===------------------------------------------------------------------===//
> // FPMath metadata.
> //===------------------------------------------------------------------===//
>
> Added: llvm/trunk/include/llvm/IR/Metadata.def
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Metadata.def?rev=223802&view=auto
> ==============================================================================
> --- llvm/trunk/include/llvm/IR/Metadata.def (added)
> +++ llvm/trunk/include/llvm/IR/Metadata.def Tue Dec 9 12:38:53 2014
> @@ -0,0 +1,44 @@
> +//===- 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
>
> Modified: llvm/trunk/include/llvm/IR/Metadata.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Metadata.h?rev=223802&r1=223801&r2=223802&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/IR/Metadata.h (original)
> +++ llvm/trunk/include/llvm/IR/Metadata.h Tue Dec 9 12:38:53 2014
> @@ -18,11 +18,13 @@
>
> #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;
> @@ -38,20 +40,388 @@ enum LLVMConstants : uint32_t {
> /// \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.
> ///
> @@ -60,15 +430,13 @@ public:
> 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);
> @@ -89,8 +457,8 @@ public:
> 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;
> }
> };
>
> @@ -138,18 +506,80 @@ struct DenseMapInfo<AAMDNodes> {
> }
> };
>
> -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.
> @@ -165,83 +595,83 @@ protected:
> 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.
> @@ -254,18 +684,6 @@ public:
> 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.
> @@ -279,24 +697,59 @@ protected:
> /// 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.
> @@ -304,17 +757,21 @@ public:
> /// 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;
> };
>
> //===----------------------------------------------------------------------===//
> @@ -333,7 +790,7 @@ class NamedMDNode : public ilist_node<Na
>
> std::string Name;
> Module *Parent;
> - void *Operands; // SmallVector<TrackingVH<MDNode>, 4>
> + void *Operands; // SmallVector<TrackingMDRef, 4>
>
> void setParent(Module *M) { Parent = M; }
>
>
> Added: llvm/trunk/include/llvm/IR/MetadataTracking.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/MetadataTracking.h?rev=223802&view=auto
> ==============================================================================
> --- llvm/trunk/include/llvm/IR/MetadataTracking.h (added)
> +++ llvm/trunk/include/llvm/IR/MetadataTracking.h Tue Dec 9 12:38:53 2014
> @@ -0,0 +1,99 @@
> +//===- 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
>
> Modified: llvm/trunk/include/llvm/IR/Module.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Module.h?rev=223802&r1=223801&r2=223802&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/IR/Module.h (original)
> +++ llvm/trunk/include/llvm/IR/Module.h Tue Dec 9 12:38:53 2014
> @@ -188,16 +188,16 @@ public:
> 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) {}
> };
>
> /// @}
> @@ -442,7 +442,7 @@ public:
More information about the llvm-commits
mailing list