[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