OSDN Git Service

Add support for metadata attachments for global variables.
authorPeter Collingbourne <peter@pcc.me.uk>
Tue, 31 May 2016 23:01:54 +0000 (23:01 +0000)
committerPeter Collingbourne <peter@pcc.me.uk>
Tue, 31 May 2016 23:01:54 +0000 (23:01 +0000)
This patch adds an IR, assembly and bitcode representation for metadata
attachments for globals. Future patches will port existing features to use
these new attachments.

Differential Revision: http://reviews.llvm.org/D20074

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@271348 91177308-0d34-0410-b5e6-96231b3b80d8

18 files changed:
docs/BitCodeFormat.rst
docs/LangRef.rst
include/llvm/Bitcode/LLVMBitCodes.h
include/llvm/IR/Function.h
include/llvm/IR/GlobalObject.h
include/llvm/IR/GlobalVariable.h
lib/AsmParser/LLParser.cpp
lib/AsmParser/LLParser.h
lib/Bitcode/Reader/BitcodeReader.cpp
lib/Bitcode/Writer/BitcodeWriter.cpp
lib/Bitcode/Writer/ValueEnumerator.cpp
lib/Bitcode/Writer/ValueEnumerator.h
lib/IR/AsmWriter.cpp
lib/IR/Function.cpp
lib/IR/Globals.cpp
lib/IR/LLVMContextImpl.h
lib/IR/Metadata.cpp
test/Assembler/metadata.ll

index edab66e..ac051c4 100644 (file)
@@ -856,6 +856,16 @@ be one ``GCNAME`` record for each garbage collector name referenced in function
 ``gc`` attributes within the module. These records can be referenced by 1-based
 index in the *gc* fields of ``FUNCTION`` records.
 
+MODULE_CODE_GLOBALVAR_ATTACHMENT Record
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+``[GLOBALVAR_ATTACHMENT, valueid, n x [id, mdnode]]``
+
+The ``GLOBALVAR_ATTACHMENT`` record (code 19) describes the metadata
+attachments for a global variable. The ``valueid`` is the value index for
+the global variable, and the remaining fields are pairs of metadata name
+indices and metadata node indices.
+
 .. _PARAMATTR_BLOCK:
 
 PARAMATTR_BLOCK Contents
index 4882ac1..2a1c7a0 100644 (file)
@@ -619,7 +619,8 @@ assume that the globals are densely packed in their section and try to
 iterate over them as an array, alignment padding would break this
 iteration. The maximum alignment is ``1 << 29``.
 
-Globals can also have a :ref:`DLL storage class <dllstorageclass>`.
+Globals can also have a :ref:`DLL storage class <dllstorageclass>` and
+an optional list of attached :ref:`metadata <metadata>`,
 
 Variables and aliases can have a
 :ref:`Thread Local Storage Model <tls_model>`.
@@ -630,7 +631,7 @@ Syntax::
                          [unnamed_addr] [AddrSpace] [ExternallyInitialized]
                          <global | constant> <Type> [<InitializerConstant>]
                          [, section "name"] [, comdat [($name)]]
-                         [, align <Alignment>]
+                         [, align <Alignment>] (, !name !N)*
 
 For example, the following defines a global in a numbered address space
 with an initializer, section, and alignment:
index c1d5fb5..a134e8c 100644 (file)
@@ -113,6 +113,9 @@ enum ModuleCodes {
 
   // IFUNC: [ifunc value type, addrspace, resolver val#, linkage, visibility]
   MODULE_CODE_IFUNC = 18,
+
+  // GLOBALVAR_ATTACHMENT: [valueid, n x [id, mdnode]]
+  MODULE_CODE_GLOBALVAR_ATTACHMENT = 19,
 };
 
 /// PARAMATTR blocks have code for defining a parameter attribute set.
index 6aeddab..dd21f2d 100644 (file)
@@ -72,13 +72,8 @@ private:
   /// Bits from GlobalObject::GlobalObjectSubclassData.
   enum {
     /// Whether this function is materializable.
-    IsMaterializableBit = 1 << 0,
-    HasMetadataHashEntryBit = 1 << 1
+    IsMaterializableBit = 0,
   };
-  void setGlobalObjectBit(unsigned Mask, bool Value) {
-    setGlobalObjectSubClassData((~Mask & getGlobalObjectSubClassData()) |
-                                (Value ? Mask : 0u));
-  }
 
   friend class SymbolTableListTraits<Function>;
 
@@ -614,35 +609,6 @@ public:
   /// setjmp or other function that gcc recognizes as "returning twice".
   bool callsFunctionThatReturnsTwice() const;
 
-  /// \brief Check if this has any metadata.
-  bool hasMetadata() const { return hasMetadataHashEntry(); }
-
-  /// \brief Get the current metadata attachment, if any.
-  ///
-  /// Returns \c nullptr if such an attachment is missing.
-  /// @{
-  MDNode *getMetadata(unsigned KindID) const;
-  MDNode *getMetadata(StringRef Kind) const;
-  /// @}
-
-  /// \brief Set a particular kind of metadata attachment.
-  ///
-  /// Sets the given attachment to \c MD, erasing it if \c MD is \c nullptr or
-  /// replacing it if it already exists.
-  /// @{
-  void setMetadata(unsigned KindID, MDNode *MD);
-  void setMetadata(StringRef Kind, MDNode *MD);
-  /// @}
-
-  /// \brief Get all current metadata attachments.
-  void
-  getAllMetadata(SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const;
-
-  /// \brief Drop metadata not in the given list.
-  ///
-  /// Drop all metadata from \c this not included in \c KnownIDs.
-  void dropUnknownMetadata(ArrayRef<unsigned> KnownIDs);
-
   /// \brief Set the attached subprogram.
   ///
   /// Calls \a setMetadata() with \a LLVMContext::MD_dbg.
@@ -664,15 +630,6 @@ private:
     Value::setValueSubclassData(D);
   }
   void setValueSubclassDataBit(unsigned Bit, bool On);
-
-  bool hasMetadataHashEntry() const {
-    return getGlobalObjectSubClassData() & HasMetadataHashEntryBit;
-  }
-  void setHasMetadataHashEntry(bool HasEntry) {
-    setGlobalObjectBit(HasMetadataHashEntryBit, HasEntry);
-  }
-
-  void clearMetadata();
 };
 
 template <>
index 2171d6e..038fda9 100644 (file)
@@ -20,6 +20,7 @@
 
 namespace llvm {
 class Comdat;
+class MDNode;
 class Module;
 
 class GlobalObject : public GlobalValue {
@@ -36,12 +37,19 @@ protected:
 
   std::string Section;     // Section to emit this into, empty means default
   Comdat *ObjComdat;
-  static const unsigned AlignmentBits = 5;
+  enum {
+    LastAlignmentBit = 4,
+    HasMetadataHashEntryBit,
+
+    GlobalObjectBits,
+  };
   static const unsigned GlobalObjectSubClassDataBits =
-      GlobalValueSubClassDataBits - AlignmentBits;
+      GlobalValueSubClassDataBits - GlobalObjectBits;
 
 private:
+  static const unsigned AlignmentBits = LastAlignmentBit + 1;
   static const unsigned AlignmentMask = (1 << AlignmentBits) - 1;
+  static const unsigned GlobalObjectMask = (1 << GlobalObjectBits) - 1;
 
 public:
   unsigned getAlignment() const {
@@ -63,6 +71,35 @@ public:
   Comdat *getComdat() { return ObjComdat; }
   void setComdat(Comdat *C) { ObjComdat = C; }
 
+  /// Check if this has any metadata.
+  bool hasMetadata() const { return hasMetadataHashEntry(); }
+
+  /// Get the current metadata attachment, if any.
+  ///
+  /// Returns \c nullptr if such an attachment is missing.
+  /// @{
+  MDNode *getMetadata(unsigned KindID) const;
+  MDNode *getMetadata(StringRef Kind) const;
+  /// @}
+
+  /// Set a particular kind of metadata attachment.
+  ///
+  /// Sets the given attachment to \c MD, erasing it if \c MD is \c nullptr or
+  /// replacing it if it already exists.
+  /// @{
+  void setMetadata(unsigned KindID, MDNode *MD);
+  void setMetadata(StringRef Kind, MDNode *MD);
+  /// @}
+
+  /// Get all current metadata attachments.
+  void
+  getAllMetadata(SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const;
+
+  /// Drop metadata not in the given list.
+  ///
+  /// Drop all metadata from \c this not included in \c KnownIDs.
+  void dropUnknownMetadata(ArrayRef<unsigned> KnownIDs);
+
   void copyAttributesFrom(const GlobalValue *Src) override;
 
   // Methods for support type inquiry through isa, cast, and dyn_cast:
@@ -70,6 +107,19 @@ public:
     return V->getValueID() == Value::FunctionVal ||
            V->getValueID() == Value::GlobalVariableVal;
   }
+
+protected:
+  void clearMetadata();
+
+private:
+  bool hasMetadataHashEntry() const {
+    return getGlobalValueSubClassData() & (1 << HasMetadataHashEntryBit);
+  }
+  void setHasMetadataHashEntry(bool HasEntry) {
+    unsigned Mask = 1 << HasMetadataHashEntryBit;
+    setGlobalValueSubClassData((~Mask & getGlobalValueSubClassData()) |
+                               (HasEntry ? Mask : 0u));
+  }
 };
 
 } // End llvm namespace
index fd08fe0..7bc5287 100644 (file)
@@ -159,6 +159,10 @@ public:
   ///
   void eraseFromParent() override;
 
+  /// Drop all references in preparation to destroy the GlobalVariable. This
+  /// drops not only the reference to the initializer but also to any metadata.
+  void dropAllReferences();
+
   // Methods for support type inquiry through isa, cast, and dyn_cast:
   static inline bool classof(const Value *V) {
     return V->getValueID() == Value::GlobalVariableVal;
index 3f9ea57..09d012d 100644 (file)
@@ -891,6 +891,9 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc,
       unsigned Alignment;
       if (ParseOptionalAlignment(Alignment)) return true;
       GV->setAlignment(Alignment);
+    } else if (Lex.getKind() == lltok::MetadataVar) {
+      if (ParseGlobalObjectMetadataAttachment(*GV))
+        return true;
     } else {
       Comdat *C;
       if (parseOptionalComdat(Name, C))
@@ -1708,17 +1711,24 @@ bool LLParser::ParseInstructionMetadata(Instruction &Inst) {
   return false;
 }
 
+/// ParseGlobalObjectMetadataAttachment
+///   ::= !dbg !57
+bool LLParser::ParseGlobalObjectMetadataAttachment(GlobalObject &GO) {
+  unsigned MDK;
+  MDNode *N;
+  if (ParseMetadataAttachment(MDK, N))
+    return true;
+
+  GO.setMetadata(MDK, N);
+  return false;
+}
+
 /// ParseOptionalFunctionMetadata
 ///   ::= (!dbg !57)*
 bool LLParser::ParseOptionalFunctionMetadata(Function &F) {
-  while (Lex.getKind() == lltok::MetadataVar) {
-    unsigned MDK;
-    MDNode *N;
-    if (ParseMetadataAttachment(MDK, N))
+  while (Lex.getKind() == lltok::MetadataVar)
+    if (ParseGlobalObjectMetadataAttachment(F))
       return true;
-
-    F.setMetadata(MDK, N);
-  }
   return false;
 }
 
index cffea25..7c32f2c 100644 (file)
@@ -424,6 +424,7 @@ namespace llvm {
     bool ParseMDNodeVector(SmallVectorImpl<Metadata *> &MDs);
     bool ParseMetadataAttachment(unsigned &Kind, MDNode *&MD);
     bool ParseInstructionMetadata(Instruction &Inst);
+    bool ParseGlobalObjectMetadataAttachment(GlobalObject &GO);
     bool ParseOptionalFunctionMetadata(Function &F);
 
     template <class FieldTy>
index 2cd1297..55c0d06 100644 (file)
@@ -443,6 +443,9 @@ private:
                                        unsigned &NextMetadataNo);
   std::error_code parseMetadataKinds();
   std::error_code parseMetadataKindRecord(SmallVectorImpl<uint64_t> &Record);
+  std::error_code
+  parseGlobalObjectAttachment(GlobalObject &GO,
+                              ArrayRef<uint64_t> Record);
   std::error_code parseMetadataAttachment(Function &F);
   ErrorOr<std::string> parseModuleTriple();
   std::error_code parseUseLists();
@@ -3820,6 +3823,16 @@ std::error_code BitcodeReader::parseModule(uint64_t ResumeBit,
       }
       break;
     }
+    case bitc::MODULE_CODE_GLOBALVAR_ATTACHMENT: {
+      if (Record.size() % 2 == 0)
+        return error("Invalid record");
+      unsigned ValueID = Record[0];
+      if (ValueID >= ValueList.size())
+        return error("Invalid record");
+      if (auto *GV = dyn_cast<GlobalVariable>(ValueList[ValueID]))
+        parseGlobalObjectAttachment(*GV, ArrayRef<uint64_t>(Record).slice(1));
+      break;
+    }
     // FUNCTION:  [type, callingconv, isproto, linkage, paramattr,
     //             alignment, section, visibility, gc, unnamed_addr,
     //             prologuedata, dllstorageclass, comdat, prefixdata]
@@ -4144,6 +4157,21 @@ ErrorOr<std::string> BitcodeReader::parseIdentificationBlock() {
   }
 }
 
+std::error_code BitcodeReader::parseGlobalObjectAttachment(
+    GlobalObject &GO, ArrayRef<uint64_t> Record) {
+  assert(Record.size() % 2 == 0);
+  for (unsigned I = 0, E = Record.size(); I != E; I += 2) {
+    auto K = MDKindMap.find(Record[I]);
+    if (K == MDKindMap.end())
+      return error("Invalid ID");
+    MDNode *MD = MetadataList.getMDNodeFwdRefOrNull(Record[I + 1]);
+    if (!MD)
+      return error("Invalid metadata attachment");
+    GO.setMetadata(K->second, MD);
+  }
+  return std::error_code();
+}
+
 /// Parse metadata attachments.
 std::error_code BitcodeReader::parseMetadataAttachment(Function &F) {
   if (Stream.EnterSubBlock(bitc::METADATA_ATTACHMENT_ID))
@@ -4175,15 +4203,8 @@ std::error_code BitcodeReader::parseMetadataAttachment(Function &F) {
         return error("Invalid record");
       if (RecordLength % 2 == 0) {
         // A function attachment.
-        for (unsigned I = 0; I != RecordLength; I += 2) {
-          auto K = MDKindMap.find(Record[I]);
-          if (K == MDKindMap.end())
-            return error("Invalid ID");
-          MDNode *MD = MetadataList.getMDNodeFwdRefOrNull(Record[I + 1]);
-          if (!MD)
-            return error("Invalid metadata attachment");
-          F.setMetadata(K->second, MD);
-        }
+        if (std::error_code EC = parseGlobalObjectAttachment(F, Record))
+          return EC;
         continue;
       }
 
index ec3ecb2..d65e924 100644 (file)
@@ -223,7 +223,10 @@ private:
                             SmallVectorImpl<uint64_t> &Record);
   void writeModuleMetadata();
   void writeFunctionMetadata(const Function &F);
-  void writeMetadataAttachment(const Function &F);
+  void writeFunctionMetadataAttachment(const Function &F);
+  void writeGlobalVariableMetadataAttachment(const GlobalVariable &GV);
+  void pushGlobalMetadataAttachment(SmallVectorImpl<uint64_t> &Record,
+                                    const GlobalObject &GO);
   void writeModuleMetadataStore();
   void writeOperandBundleTags();
   void writeConstants(unsigned FirstVal, unsigned LastVal, bool isGlobal);
@@ -1831,24 +1834,31 @@ void ModuleBitcodeWriter::writeFunctionMetadata(const Function &F) {
   Stream.ExitBlock();
 }
 
-void ModuleBitcodeWriter::writeMetadataAttachment(const Function &F) {
+void ModuleBitcodeWriter::pushGlobalMetadataAttachment(
+    SmallVectorImpl<uint64_t> &Record, const GlobalObject &GO) {
+  // [n x [id, mdnode]]
+  SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
+  GO.getAllMetadata(MDs);
+  for (const auto &I : MDs) {
+    Record.push_back(I.first);
+    Record.push_back(VE.getMetadataID(I.second));
+  }
+}
+
+void ModuleBitcodeWriter::writeFunctionMetadataAttachment(const Function &F) {
   Stream.EnterSubblock(bitc::METADATA_ATTACHMENT_ID, 3);
 
   SmallVector<uint64_t, 64> Record;
 
-  // Write metadata attachments
-  // METADATA_ATTACHMENT - [m x [value, [n x [id, mdnode]]]
-  SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
-  F.getAllMetadata(MDs);
-  if (!MDs.empty()) {
-    for (const auto &I : MDs) {
-      Record.push_back(I.first);
-      Record.push_back(VE.getMetadataID(I.second));
-    }
+  if (F.hasMetadata()) {
+    pushGlobalMetadataAttachment(Record, F);
     Stream.EmitRecord(bitc::METADATA_ATTACHMENT, Record, 0);
     Record.clear();
   }
 
+  // Write metadata attachments
+  // METADATA_ATTACHMENT - [m x [value, [n x [id, mdnode]]]
+  SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
   for (const BasicBlock &BB : F)
     for (const Instruction &I : BB) {
       MDs.clear();
@@ -2894,7 +2904,7 @@ void ModuleBitcodeWriter::writeFunction(
   writeValueSymbolTable(F.getValueSymbolTable());
 
   if (NeedsMetadataAttachment)
-    writeMetadataAttachment(F);
+    writeFunctionMetadataAttachment(F);
   if (VE.shouldPreserveUseListOrder())
     writeUseListBlock(&F);
   VE.purgeFunction();
@@ -3597,6 +3607,14 @@ void ModuleBitcodeWriter::writeModule() {
   writeValueSymbolTable(M.getValueSymbolTable(),
                         /* IsModuleLevel */ true, &FunctionToBitcodeIndex);
 
+  for (const GlobalVariable &GV : M.globals())
+    if (GV.hasMetadata()) {
+      SmallVector<uint64_t, 4> Record;
+      Record.push_back(VE.getValueID(&GV));
+      pushGlobalMetadataAttachment(Record, GV);
+      Stream.EmitRecord(bitc::MODULE_CODE_GLOBALVAR_ATTACHMENT, Record);
+    }
+
   if (GenerateHash) {
     writeModuleHash(BlockStartPos);
   }
index 6bf95b1..6051173 100644 (file)
@@ -344,6 +344,11 @@ ValueEnumerator::ValueEnumerator(const Module &M,
   EnumerateNamedMetadata(M);
 
   SmallVector<std::pair<unsigned, MDNode *>, 8> MDs;
+  for (const GlobalVariable &GV : M.globals()) {
+    GV.getAllMetadata(MDs);
+    for (const auto &I : MDs)
+      EnumerateMetadata(&GV, I.second);
+  }
 
   // Enumerate types used by function bodies and argument lists.
   for (const Function &F : M) {
@@ -523,17 +528,18 @@ void ValueEnumerator::EnumerateNamedMDNode(const NamedMDNode *MD) {
     EnumerateMetadata(nullptr, MD->getOperand(i));
 }
 
-unsigned ValueEnumerator::getMetadataFunctionID(const Function *F) const {
-  return F ? getValueID(F) + 1 : 0;
+unsigned ValueEnumerator::getMetadataGlobalID(const GlobalObject *GO) const {
+  return GO ? getValueID(GO) + 1 : 0;
 }
 
-void ValueEnumerator::EnumerateMetadata(const Function *F, const Metadata *MD) {
-  EnumerateMetadata(getMetadataFunctionID(F), MD);
+void ValueEnumerator::EnumerateMetadata(const GlobalObject *GO,
+                                        const Metadata *MD) {
+  EnumerateMetadata(getMetadataGlobalID(GO), MD);
 }
 
 void ValueEnumerator::EnumerateFunctionLocalMetadata(
     const Function &F, const LocalAsMetadata *Local) {
-  EnumerateFunctionLocalMetadata(getMetadataFunctionID(&F), Local);
+  EnumerateFunctionLocalMetadata(getMetadataGlobalID(&F), Local);
 }
 
 void ValueEnumerator::dropFunctionFromMetadata(
index bff2de7..34d33fc 100644 (file)
@@ -255,7 +255,7 @@ private:
   /// it's an \a MDNode.
   const MDNode *enumerateMetadataImpl(unsigned F, const Metadata *MD);
 
-  unsigned getMetadataFunctionID(const Function *F) const;
+  unsigned getMetadataGlobalID(const GlobalObject *GO) const;
 
   /// Enumerate reachable metadata in (almost) post-order.
   ///
@@ -272,7 +272,7 @@ private:
   /// \a organizeMetadata() will later partition distinct nodes ahead of
   /// uniqued ones.
   ///{
-  void EnumerateMetadata(const Function *F, const Metadata *MD);
+  void EnumerateMetadata(const GlobalObject *GO, const Metadata *MD);
   void EnumerateMetadata(unsigned F, const Metadata *MD);
   ///}
 
index ec975c7..c5002dc 100644 (file)
@@ -681,6 +681,9 @@ private:
   /// Add all of the functions arguments, basic blocks, and instructions.
   void processFunction();
 
+  /// Add the metadata directly attached to a GlobalObject.
+  void processGlobalObjectMetadata(const GlobalObject &GO);
+
   /// Add all of the metadata from a function.
   void processFunctionMetadata(const Function &F);
 
@@ -799,6 +802,7 @@ void SlotTracker::processModule() {
   for (const GlobalVariable &Var : TheModule->globals()) {
     if (!Var.hasName())
       CreateModuleSlot(&Var);
+    processGlobalObjectMetadata(Var);
   }
 
   for (const GlobalAlias &A : TheModule->aliases()) {
@@ -882,12 +886,15 @@ void SlotTracker::processFunction() {
   ST_DEBUG("end processFunction!\n");
 }
 
-void SlotTracker::processFunctionMetadata(const Function &F) {
+void SlotTracker::processGlobalObjectMetadata(const GlobalObject &GO) {
   SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
-  F.getAllMetadata(MDs);
+  GO.getAllMetadata(MDs);
   for (auto &MD : MDs)
     CreateMetadataSlot(MD.second);
+}
 
+void SlotTracker::processFunctionMetadata(const Function &F) {
+  processGlobalObjectMetadata(F);
   for (auto &BB : F) {
     for (auto &I : BB)
       processInstructionMetadata(I);
@@ -2473,6 +2480,10 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) {
   if (GV->getAlignment())
     Out << ", align " << GV->getAlignment();
 
+  SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
+  GV->getAllMetadata(MDs);
+  printMetadataAttachments(MDs, ", ");
+
   printInfoComment(*GV);
 }
 
index c874196..8159225 100644 (file)
@@ -218,11 +218,13 @@ bool Argument::hasAttribute(Attribute::AttrKind Kind) const {
 //===----------------------------------------------------------------------===//
 
 bool Function::isMaterializable() const {
-  return getGlobalObjectSubClassData() & IsMaterializableBit;
+  return getGlobalObjectSubClassData() & (1 << IsMaterializableBit);
 }
 
 void Function::setIsMaterializable(bool V) {
-  setGlobalObjectBit(IsMaterializableBit, V);
+  unsigned Mask = 1 << IsMaterializableBit;
+  setGlobalObjectSubClassData((~Mask & getGlobalObjectSubClassData()) |
+                              (V ? Mask : 0u));
 }
 
 LLVMContext &Function::getContext() const {
index 3bf3cc2..d151b9c 100644 (file)
@@ -81,13 +81,13 @@ void GlobalObject::setAlignment(unsigned Align) {
 
 unsigned GlobalObject::getGlobalObjectSubClassData() const {
   unsigned ValueData = getGlobalValueSubClassData();
-  return ValueData >> AlignmentBits;
+  return ValueData >> GlobalObjectBits;
 }
 
 void GlobalObject::setGlobalObjectSubClassData(unsigned Val) {
   unsigned OldData = getGlobalValueSubClassData();
-  setGlobalValueSubClassData((OldData & AlignmentMask) |
-                             (Val << AlignmentBits));
+  setGlobalValueSubClassData((OldData & GlobalObjectMask) |
+                             (Val << GlobalObjectBits));
   assert(getGlobalObjectSubClassData() == Val && "representation error");
 }
 
@@ -301,6 +301,10 @@ void GlobalVariable::copyAttributesFrom(const GlobalValue *Src) {
   }
 }
 
+void GlobalVariable::dropAllReferences() {
+  User::dropAllReferences();
+  clearMetadata();
+}
 
 //===----------------------------------------------------------------------===//
 // GlobalIndirectSymbol Implementation
index 7d7be44..02af08a 100644 (file)
@@ -1107,8 +1107,8 @@ public:
   /// Collection of per-instruction metadata used in this context.
   DenseMap<const Instruction *, MDAttachmentMap> InstructionMetadata;
 
-  /// Collection of per-function metadata used in this context.
-  DenseMap<const Function *, MDAttachmentMap> FunctionMetadata;
+  /// Collection of per-GlobalObject metadata used in this context.
+  DenseMap<const GlobalObject *, MDAttachmentMap> GlobalObjectMetadata;
 
   /// DiscriminatorTable - This table maps file:line locations to an
   /// integer representing the next DWARF path discriminator to assign to
index 9435cd2..a77565c 100644 (file)
@@ -1281,24 +1281,24 @@ void Instruction::clearMetadataHashEntries() {
   setHasMetadataHashEntry(false);
 }
 
-MDNode *Function::getMetadata(unsigned KindID) const {
+MDNode *GlobalObject::getMetadata(unsigned KindID) const {
   if (!hasMetadata())
     return nullptr;
-  return getContext().pImpl->FunctionMetadata[this].lookup(KindID);
+  return getContext().pImpl->GlobalObjectMetadata[this].lookup(KindID);
 }
 
-MDNode *Function::getMetadata(StringRef Kind) const {
+MDNode *GlobalObject::getMetadata(StringRef Kind) const {
   if (!hasMetadata())
     return nullptr;
   return getMetadata(getContext().getMDKindID(Kind));
 }
 
-void Function::setMetadata(unsigned KindID, MDNode *MD) {
+void GlobalObject::setMetadata(unsigned KindID, MDNode *MD) {
   if (MD) {
     if (!hasMetadata())
       setHasMetadataHashEntry(true);
 
-    getContext().pImpl->FunctionMetadata[this].set(KindID, *MD);
+    getContext().pImpl->GlobalObjectMetadata[this].set(KindID, *MD);
     return;
   }
 
@@ -1306,29 +1306,29 @@ void Function::setMetadata(unsigned KindID, MDNode *MD) {
   if (!hasMetadata())
     return;
 
-  auto &Store = getContext().pImpl->FunctionMetadata[this];
+  auto &Store = getContext().pImpl->GlobalObjectMetadata[this];
   Store.erase(KindID);
   if (Store.empty())
     clearMetadata();
 }
 
-void Function::setMetadata(StringRef Kind, MDNode *MD) {
+void GlobalObject::setMetadata(StringRef Kind, MDNode *MD) {
   if (!MD && !hasMetadata())
     return;
   setMetadata(getContext().getMDKindID(Kind), MD);
 }
 
-void Function::getAllMetadata(
+void GlobalObject::getAllMetadata(
     SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const {
   MDs.clear();
 
   if (!hasMetadata())
     return;
 
-  getContext().pImpl->FunctionMetadata[this].getAll(MDs);
+  getContext().pImpl->GlobalObjectMetadata[this].getAll(MDs);
 }
 
-void Function::dropUnknownMetadata(ArrayRef<unsigned> KnownIDs) {
+void GlobalObject::dropUnknownMetadata(ArrayRef<unsigned> KnownIDs) {
   if (!hasMetadata())
     return;
   if (KnownIDs.empty()) {
@@ -1339,7 +1339,7 @@ void Function::dropUnknownMetadata(ArrayRef<unsigned> KnownIDs) {
   SmallSet<unsigned, 5> KnownSet;
   KnownSet.insert(KnownIDs.begin(), KnownIDs.end());
 
-  auto &Store = getContext().pImpl->FunctionMetadata[this];
+  auto &Store = getContext().pImpl->GlobalObjectMetadata[this];
   assert(!Store.empty());
 
   Store.remove_if([&KnownSet](const std::pair<unsigned, TrackingMDNodeRef> &I) {
@@ -1350,10 +1350,10 @@ void Function::dropUnknownMetadata(ArrayRef<unsigned> KnownIDs) {
     clearMetadata();
 }
 
-void Function::clearMetadata() {
+void GlobalObject::clearMetadata() {
   if (!hasMetadata())
     return;
-  getContext().pImpl->FunctionMetadata.erase(this);
+  getContext().pImpl->GlobalObjectMetadata.erase(this);
   setHasMetadataHashEntry(false);
 }
 
index ba7065d..2fe26be 100644 (file)
@@ -1,8 +1,11 @@
 ; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
 ; RUN: verify-uselistorder %s
 
+; CHECK: @global = global i32 0, !foo [[M2:![0-9]+]], !baz [[M3:![0-9]+]]
+@global = global i32 0, !foo !2, !baz !3
+
 ; CHECK-LABEL: @test
-; CHECK: ret void, !bar !4, !foo !3
+; CHECK: ret void, !foo [[M0:![0-9]+]], !bar [[M1:![0-9]+]]
 define void @test() !dbg !1 {
   add i32 2, 1, !bar !0
   add i32 1, 2, !foo !1
@@ -11,24 +14,30 @@ define void @test() !dbg !1 {
   ret void, !foo !0, !bar !1
 }
 
-; CHECK-LABEL: define void @test2() !foo !5 !baz !6
+; CHECK: define void @test2() !foo [[M2]] !baz [[M3]]
 define void @test2() !foo !2 !baz !3 {
   unreachable
 }
 
-; CHECK-LABEL: define void @test3() !bar !6
-; CHECK: unreachable, !bar !7
+; CHECK: define void @test3() !bar [[M3]]
+; CHECK: unreachable, !bar [[M4:![0-9]+]]
 define void @test3() !bar !3 {
   unreachable, !bar !4
 }
 
 ; CHECK-LABEL: define void @test_attachment_name() {
-; CHECK:   unreachable, !\342abc !7
+; CHECK:   unreachable, !\342abc [[M4]]
 define void @test_attachment_name() {
   ;; Escape the first character when printing text IR, since it's a digit
   unreachable, !\34\32abc !4
 }
 
+; CHECK: [[M2]] = distinct !{}
+; CHECK: [[M3]] = distinct !{}
+; CHECK: [[M0]] = !DILocation
+; CHECK: [[M1]] = distinct !DISubprogram
+; CHECK: [[M4]] = distinct !{}
+
 !llvm.module.flags = !{!7}
 !llvm.dbg.cu = !{!5}
 !0 = !DILocation(line: 662302, column: 26, scope: !1)