[llvm-commits] PATCH: BasicBlock metadata

Ralf Karrenberg karrenberg at cdl.uni-saarland.de
Tue May 8 14:18:10 PDT 2012


 > On 5/8/12 7:07 AM, Richard Osborne wrote:
 > > On 08/05/12 11:29, Ralf Karrenberg wrote:
 > >> On 5/8/12 11:40 AM, Richard Osborne wrote:
 > >>>> Cheers,
 > >>>> Ralf
 > >>>>     /// hasAddressTaken - returns true if there are any uses of 
this basic block
 > >>>>     /// other than direct branches, switches, etc. to it.
 > >>>> -  bool hasAddressTaken() const { return 
getSubclassDataFromValue() != 0; }
 > >>>> +  bool hasAddressTaken() const {
 > >>>> +    return (getSubclassDataFromValue()&  ~HasMetadataBit) != 0;
 > >>>> +  }
 > >>> I think this will result in basic block metadata effecting
 > >>> optimizations. What would happen if you just ignored metadata here?
 > >> It will always treat a block that has metadata attached as a block
 > >> whose address has been taken, which results in a crash at a later
 > >> point (don't remember exactly where) because the address was never 
taken.
 >
 > I think you might want to update the comment explaining what you said
 > above and providing a justification for it.  Developers misunderstanding
 > code seems like a flag for a better comment, IMHO.

That makes sense. I attached the updated patch.

 > -- John T.
 >
 > > Ah sorry, I totally misread this bit of the code. It looks fine to me.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20120508/51cbd02d/attachment.html>
-------------- next part --------------
Index: test/Assembler/metadata-block.ll
===================================================================
--- test/Assembler/metadata-block.ll	(revision 0)
+++ test/Assembler/metadata-block.ll	(revision 0)
@@ -0,0 +1,36 @@
+; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
+
+; CHECK: @test
+; CHECK: !foo !0
+; CHECK: !bar !1
+; CHECK: !bar !2
+; CHECK: !foo !3, !bar !4
+define i32 @test(i32 %a) {
+entry:
+    !foo !0
+  %x = mul i32 %a, %a
+  %cmp = icmp ogt i32 %x, 13
+  br i1 %cmp, label %if.then, label %if.else
+
+if.then:
+	!bar !1
+  %y = add i32 %a, 1
+  br label %if.end
+
+if.else:
+	!bar !2
+  %z = sub i32 %a, 1
+  br label %if.end
+
+if.end:
+	!foo !3, !bar !4
+  %r = phi i32 [ %y, %if.then ], [ %z, %if.else ]
+  ret i32 %r
+}
+
+!0 = metadata !{null}
+!1 = metadata !{i1 false}
+!2 = metadata !{i32 42}
+!3 = metadata !{i1 true}
+!4 = metadata !{i32 13}
+
Index: include/llvm/BasicBlock.h
===================================================================
--- include/llvm/BasicBlock.h	(revision 156419)
+++ include/llvm/BasicBlock.h	(working copy)
@@ -88,6 +88,12 @@
   ///
   explicit BasicBlock(LLVMContext &C, const Twine &Name = "",
                       Function *Parent = 0, BasicBlock *InsertBefore = 0);
+
+  enum {
+    /// HasMetadataBit - This is a bit stored in the SubClassData field which
+    /// indicates whether this block has metadata attached to it or not.
+    HasMetadataBit = 1 << 15
+  };
 public:
   /// getContext - Get the context in which this basic block lives.
   LLVMContext &getContext() const;
@@ -255,7 +261,11 @@
 
   /// hasAddressTaken - returns true if there are any uses of this basic block
   /// other than direct branches, switches, etc. to it.
-  bool hasAddressTaken() const { return getSubclassDataFromValue() != 0; }
+  /// The metadatabit is deactivated to prevent returning 'true' in cases where
+  /// the address has not been taken but the block has metadata attached.
+  bool hasAddressTaken() const {
+    return (getSubclassDataFromValue() & ~HasMetadataBit) != 0;
+  }
 
   /// replaceSuccessorsPhiUsesWith - Update all phi nodes in all our successors
   /// to refer to basic block New instead of to us.
@@ -284,6 +294,69 @@
   void setValueSubclassData(unsigned short D) {
     Value::setValueSubclassData(D);
   }
+  unsigned short getSubclassDataFromValue() const {
+    return Value::getSubclassDataFromValue();
+  }
+
+public:
+  //===--------------------------------------------------------------------===//
+  // Metadata manipulation.
+  //===--------------------------------------------------------------------===//
+
+  /// hasMetadata() - Return true if this block has any metadata attached
+  /// to it.
+  bool hasMetadata() const {
+    return hasMetadataHashEntry();
+  }
+
+  /// getMetadata - Get the metadata of given kind attached to this block.
+  /// If the metadata is not found then return null.
+  MDNode *getMetadata(unsigned KindID) const {
+    if (!hasMetadata()) return 0;
+    return getMetadataImpl(KindID);
+  }
+
+  /// getMetadata - Get the metadata of given kind attached to this block.
+  /// If the metadata is not found then return null.
+  MDNode *getMetadata(StringRef Kind) const {
+    if (!hasMetadata()) return 0;
+    return getMetadataImpl(Kind);
+  }
+
+  /// getAllMetadata - Get all metadata attached to this block.  The first
+  /// element of each pair returned is the KindID, the second element is the
+  /// metadata value.  This list is returned sorted by the KindID.
+  void getAllMetadata(SmallVectorImpl<std::pair<unsigned, MDNode*> > &MDs)const{
+    if (hasMetadata())
+      getAllMetadataImpl(MDs);
+  }
+
+  /// setMetadata - Set the metadata of the specified kind to the specified
+  /// node.  This updates/replaces metadata if already present, or removes it if
+  /// Node is null.
+  void setMetadata(unsigned KindID, MDNode *Node);
+  void setMetadata(StringRef Kind, MDNode *Node);
+
+private:
+  /// hasMetadataHashEntry - Return true if we have an entry in the on-the-side
+  /// metadata hash.
+  bool hasMetadataHashEntry() const {
+    return (getSubclassDataFromValue() & HasMetadataBit) != 0;
+  }
+
+  // These are all implemented in Metadata.cpp.
+  MDNode *getMetadataImpl(unsigned KindID) const;
+  MDNode *getMetadataImpl(StringRef Kind) const;
+  void getAllMetadataImpl(SmallVectorImpl<std::pair<unsigned,MDNode*> > &)const;
+  void getAllMetadataOtherThanDebugLocImpl(SmallVectorImpl<std::pair<unsigned,
+                                           MDNode*> > &) const;
+  void clearMetadataHashEntries();
+
+  void setHasMetadataHashEntry(bool V) {
+    setValueSubclassData((getSubclassDataFromValue() & ~HasMetadataBit) |
+                         (V ? HasMetadataBit : 0));
+  }
+  
 };
 
 } // End llvm namespace
Index: include/llvm/Bitcode/LLVMBitCodes.h
===================================================================
--- include/llvm/Bitcode/LLVMBitCodes.h	(revision 156419)
+++ include/llvm/Bitcode/LLVMBitCodes.h	(working copy)
@@ -126,17 +126,18 @@
   };
 
   enum MetadataCodes {
-    METADATA_STRING        = 1,   // MDSTRING:      [values]
+    METADATA_STRING           = 1,   // MDSTRING:      [values]
     // 2 is unused.
     // 3 is unused.
-    METADATA_NAME          = 4,   // STRING:        [values]
+    METADATA_NAME             = 4,   // STRING:        [values]
     // 5 is unused.
-    METADATA_KIND          = 6,   // [n x [id, name]]
+    METADATA_KIND             = 6,   // [n x [id, name]]
     // 7 is unused.
-    METADATA_NODE          = 8,   // NODE:          [n x (type num, value num)]
-    METADATA_FN_NODE       = 9,   // FN_NODE:       [n x (type num, value num)]
-    METADATA_NAMED_NODE    = 10,  // NAMED_NODE:    [n x mdnodes]
-    METADATA_ATTACHMENT    = 11   // [m x [value, [n x [id, mdnode]]]
+    METADATA_NODE             = 8,   // NODE:          [n x (type num, value num)]
+    METADATA_FN_NODE          = 9,   // FN_NODE:       [n x (type num, value num)]
+    METADATA_NAMED_NODE       = 10,  // NAMED_NODE:    [n x mdnodes]
+    METADATA_ATTACHMENT       = 11,  // [m x [value, [n x [id, mdnode]]]
+    METADATA_BLOCK_ATTACHMENT = 12   // [m x [value, [n x [id, mdnode]]]
   };
   // The constants block (CONSTANTS_BLOCK_ID) describes emission for each
   // constant and maintains an implicit current type value.
Index: docs/LangRef.html
===================================================================
--- docs/LangRef.html	(revision 156419)
+++ docs/LangRef.html	(working copy)
@@ -2898,12 +2898,12 @@
 
 <div>
 
-<p>LLVM IR allows metadata to be attached to instructions in the program that
-   can convey extra information about the code to the optimizers and code
-   generator.  One example application of metadata is source-level debug
-   information.  There are two metadata primitives: strings and nodes. All
-   metadata has the <tt>metadata</tt> type and is identified in syntax by a
-   preceding exclamation point ('<tt>!</tt>').</p>
+<p>LLVM IR allows metadata to be attached to instructions and basic blocks
+   in the program that can convey extra information about the code to the
+   optimizers and code generator. One example application of metadata is
+   source-level debug information. There are two metadata primitives: strings
+   and nodes. All metadata has the <tt>metadata</tt> type and is identified
+   in syntax by a preceding exclamation point ('<tt>!</tt>').</p>
 
 <p>A metadata string is a string surrounded by double quotes.  It can contain
    any character by escaping non-printable characters with "<tt>\xx</tt>" where
@@ -2931,7 +2931,7 @@
 </pre>
 </div>
 
-<p>Metadata can be used as function arguments. Here <tt>llvm.dbg.value</tt> 
+<p>Metadata can be used as function arguments. Here, <tt>llvm.dbg.value</tt> 
    function is using two metadata arguments:</p>
 
 <div class="doc_code">
@@ -2940,7 +2940,7 @@
 </pre>
 </div>
 
-<p>Metadata can be attached with an instruction. Here metadata <tt>!21</tt> is
+<p>Metadata can be attached to an instruction. Here, metadata <tt>!21</tt> is
    attached to the <tt>add</tt> instruction using the <tt>!dbg</tt>
    identifier:</p>
 
@@ -2950,6 +2950,19 @@
 </pre>
 </div>
 
+<p>Metadata can be attached to a basic block. Here, metadata <tt>!42</tt> is
+   attached to the basic block <tt>entry</tt> using the <tt>!divergent</tt>
+   identifier:</p>
+
+<div class="doc_code">
+<pre>
+if.else:
+    !divergent !42
+  %x = fadd float %a, %b
+  br label %if.end
+</pre>
+</div>
+
 <p>More information about specific metadata nodes recognized by the optimizers
    and code generator is found below.</p>
 
Index: lib/VMCore/AsmWriter.cpp
===================================================================
--- lib/VMCore/AsmWriter.cpp	(revision 156419)
+++ lib/VMCore/AsmWriter.cpp	(working copy)
@@ -484,7 +484,7 @@
 
   ST_DEBUG("Inserting Instructions:\n");
 
-  SmallVector<std::pair<unsigned, MDNode*>, 4> MDForInst;
+  SmallVector<std::pair<unsigned, MDNode*>, 4> MDForInstOrBlock;
 
   // Add all of the basic blocks and instructions with no names.
   for (Function::const_iterator BB = TheFunction->begin(),
@@ -492,6 +492,12 @@
     if (!BB->hasName())
       CreateFunctionSlot(BB);
 
+    // Process metadata attached with this block.
+    BB->getAllMetadata(MDForInstOrBlock);
+    for (unsigned i = 0, e = MDForInstOrBlock.size(); i != e; ++i)
+      CreateMetadataSlot(MDForInstOrBlock[i].second);
+    MDForInstOrBlock.clear();
+
     for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E;
          ++I) {
       if (!I->getType()->isVoidTy() && !I->hasName())
@@ -509,10 +515,10 @@
       }
 
       // Process metadata attached with this instruction.
-      I->getAllMetadata(MDForInst);
-      for (unsigned i = 0, e = MDForInst.size(); i != e; ++i)
-        CreateMetadataSlot(MDForInst[i].second);
-      MDForInst.clear();
+      I->getAllMetadata(MDForInstOrBlock);
+      for (unsigned i = 0, e = MDForInstOrBlock.size(); i != e; ++i)
+        CreateMetadataSlot(MDForInstOrBlock[i].second);
+      MDForInstOrBlock.clear();
     }
   }
 
@@ -1640,6 +1646,28 @@
 
   Out << "\n";
 
+  // Print Metadata info.
+  SmallVector<std::pair<unsigned, MDNode*>, 4> BlockMD;
+  BB->getAllMetadata(BlockMD);
+  if (!BlockMD.empty()) {
+    Out << "    ";
+    SmallVector<StringRef, 8> MDNames;
+    BB->getType()->getContext().getMDKindNames(MDNames);
+    for (unsigned i = 0, e = BlockMD.size(); i != e; ++i) {
+      unsigned Kind = BlockMD[i].first;
+      if (i != 0) Out << ',';
+      if (Kind < MDNames.size()) {
+        Out << " !" << MDNames[Kind];
+      } else {
+        Out << ", !<unknown kind #" << Kind << ">";
+      }
+      Out << ' ';
+      WriteAsOperandInternal(Out, BlockMD[i].second, &TypePrinter, &Machine,
+                             TheModule);
+    }
+    Out << "\n";
+  }
+
   if (AnnotationWriter) AnnotationWriter->emitBasicBlockStartAnnot(BB, Out);
 
   // Output all of the instructions in the basic block...
Index: lib/VMCore/LLVMContextImpl.h
===================================================================
--- lib/VMCore/LLVMContextImpl.h	(revision 156419)
+++ lib/VMCore/LLVMContextImpl.h	(working copy)
@@ -333,6 +333,9 @@
   /// MetadataStore - Collection of per-instruction metadata used in this
   /// context.
   DenseMap<const Instruction *, MDMapTy> MetadataStore;
+  /// MetadataBlockStore - Collection of per-block metadata used in this
+  /// context.
+  DenseMap<const BasicBlock *, MDMapTy> MetadataBlockStore;
   
   /// ScopeRecordIdx - This is the index in ScopeRecords for an MDNode scope
   /// entry with no "inlined at" element.
Index: lib/VMCore/Metadata.cpp
===================================================================
--- lib/VMCore/Metadata.cpp	(revision 156419)
+++ lib/VMCore/Metadata.cpp	(working copy)
@@ -16,6 +16,7 @@
 #include "llvm/LLVMContext.h"
 #include "llvm/Module.h"
 #include "llvm/Instruction.h"
+#include "llvm/BasicBlock.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/SmallString.h"
@@ -592,3 +593,109 @@
   setHasMetadataHashEntry(false);
 }
 
+
+//===----------------------------------------------------------------------===//
+// BasicBlock Metadata method implementations.
+//
+
+void BasicBlock::setMetadata(StringRef Kind, MDNode *Node) {
+  if (Node == 0 && !hasMetadata()) return;
+  setMetadata(getContext().getMDKindID(Kind), Node);
+}
+
+MDNode *BasicBlock::getMetadataImpl(StringRef Kind) const {
+  return getMetadataImpl(getContext().getMDKindID(Kind));
+}
+
+/// setMetadata - Set the metadata of of the specified kind to the specified
+/// node.  This updates/replaces metadata if already present, or removes it if
+/// Node is null.
+void BasicBlock::setMetadata(unsigned KindID, MDNode *Node) {
+  if (Node == 0 && !hasMetadata()) return;
+
+  // Handle the case when we're adding/updating metadata on a BasicBlock.
+  if (Node) {
+    LLVMContextImpl::MDMapTy &Info = getContext().pImpl->MetadataBlockStore[this];
+    assert(!Info.empty() == hasMetadataHashEntry() &&
+           "HasMetadata bit is wonked");
+    if (Info.empty()) {
+      setHasMetadataHashEntry(true);
+    } else {
+      // Handle replacement of an existing value.
+      for (unsigned i = 0, e = Info.size(); i != e; ++i)
+        if (Info[i].first == KindID) {
+          Info[i].second = Node;
+          return;
+        }
+    }
+
+    // No replacement, just add it to the list.
+    Info.push_back(std::make_pair(KindID, Node));
+    return;
+  }
+
+  // Otherwise, we're removing metadata from a BasicBlock.
+  assert((hasMetadataHashEntry() ==
+          getContext().pImpl->MetadataBlockStore.count(this)) &&
+         "HasMetadata bit out of date!");
+  if (!hasMetadataHashEntry())
+    return;  // Nothing to remove!
+  LLVMContextImpl::MDMapTy &Info = getContext().pImpl->MetadataBlockStore[this];
+
+  // Common case is removing the only entry.
+  if (Info.size() == 1 && Info[0].first == KindID) {
+    getContext().pImpl->MetadataBlockStore.erase(this);
+    setHasMetadataHashEntry(false);
+    return;
+  }
+
+  // Handle removal of an existing value.
+  for (unsigned i = 0, e = Info.size(); i != e; ++i)
+    if (Info[i].first == KindID) {
+      Info[i] = Info.back();
+      Info.pop_back();
+      assert(!Info.empty() && "Removing last entry should be handled above");
+      return;
+    }
+  // Otherwise, removing an entry that doesn't exist on the BasicBlock.
+}
+
+MDNode *BasicBlock::getMetadataImpl(unsigned KindID) const {
+  if (!hasMetadataHashEntry()) return 0;
+  
+  LLVMContextImpl::MDMapTy &Info = getContext().pImpl->MetadataBlockStore[this];
+  assert(!Info.empty() && "bit out of sync with hash table");
+
+  for (LLVMContextImpl::MDMapTy::iterator I = Info.begin(), E = Info.end();
+       I != E; ++I)
+    if (I->first == KindID)
+      return I->second;
+  return 0;
+}
+
+void BasicBlock::getAllMetadataImpl(SmallVectorImpl<std::pair<unsigned,
+                                    MDNode*> > &Result) const {
+  Result.clear();
+  
+  assert(hasMetadataHashEntry() &&
+         getContext().pImpl->MetadataBlockStore.count(this) &&
+         "Shouldn't have called this");
+  const LLVMContextImpl::MDMapTy &Info =
+    getContext().pImpl->MetadataBlockStore.find(this)->second;
+  assert(!Info.empty() && "Shouldn't have called this");
+
+  Result.append(Info.begin(), Info.end());
+
+  // Sort the resulting array so it is stable.
+  if (Result.size() > 1)
+    array_pod_sort(Result.begin(), Result.end());
+}
+
+/// clearMetadataHashEntries - Clear all hashtable-based metadata from
+/// this BasicBlock.
+void BasicBlock::clearMetadataHashEntries() {
+  assert(hasMetadataHashEntry() && "Caller should check");
+  getContext().pImpl->MetadataBlockStore.erase(this);
+  setHasMetadataHashEntry(false);
+}
+
Index: lib/AsmParser/LLParser.cpp
===================================================================
--- lib/AsmParser/LLParser.cpp	(revision 156419)
+++ lib/AsmParser/LLParser.cpp	(working copy)
@@ -45,6 +45,26 @@
 /// ValidateEndOfModule - Do final validity and sanity checks at the end of the
 /// module.
 bool LLParser::ValidateEndOfModule() {
+  // Handle any block metadata forward references.
+  if (!ForwardRefBlockMetadata.empty()) {
+    for (DenseMap<BasicBlock*, std::vector<MDRef> >::iterator
+         BB = ForwardRefBlockMetadata.begin(), E = ForwardRefBlockMetadata.end();
+         BB != E; ++BB) {
+      BasicBlock *Block = BB->first;
+      const std::vector<MDRef> &MDList = BB->second;
+      
+      for (unsigned i = 0, e = MDList.size(); i != e; ++i) {
+        unsigned SlotNo = MDList[i].MDSlot;
+        
+        if (SlotNo >= NumberedMetadata.size() || NumberedMetadata[SlotNo] == 0)
+          return Error(MDList[i].Loc, "use of undefined metadata '!" +
+                       Twine(SlotNo) + "'");
+        Block->setMetadata(MDList[i].MDKind, NumberedMetadata[SlotNo]);
+      }
+    }
+    ForwardRefBlockMetadata.clear();
+  }
+
   // Handle any instruction metadata forward references.
   if (!ForwardRefInstMetadata.empty()) {
     for (DenseMap<Instruction*, std::vector<MDRef> >::iterator
@@ -1054,6 +1074,53 @@
   return false;
 }
 
+/// ParseBasicBlockMetadata
+///   ::= !propertyA !42 (',' !propertyB !57)*
+bool LLParser::ParseBasicBlockMetadata(BasicBlock *Block,
+                                       PerFunctionState *PFS) {
+  do {
+    if (Lex.getKind() != lltok::MetadataVar)
+      return TokError("expected metadata");
+
+    std::string Name = Lex.getStrVal();
+    unsigned MDK = M->getMDKindID(Name);
+    Lex.Lex();
+
+    MDNode *Node;
+    SMLoc Loc = Lex.getLoc();
+
+    if (ParseToken(lltok::exclaim, "expected '!' here"))
+      return true;
+
+    // This code is similar to that of ParseMetadataValue, however it needs to
+    // have special-case code for a forward reference; see the comments on
+    // ForwardRefInstMetadata for details. Also, MDStrings are not supported
+    // at the top level here.
+    if (Lex.getKind() == lltok::lbrace) {
+      ValID ID;
+      if (ParseMetadataListValue(ID, PFS))
+        return true;
+      assert(ID.Kind == ValID::t_MDNode);
+      Block->setMetadata(MDK, ID.MDNodeVal);
+    } else {
+      unsigned NodeID = 0;
+      if (ParseMDNodeID(Node, NodeID))
+        return true;
+      if (Node) {
+        // If we got the node, add it to the block.
+        Block->setMetadata(MDK, Node);
+      } else {
+        MDRef R = { Loc, MDK, NodeID };
+        // Otherwise, remember that this should be resolved later.
+        ForwardRefBlockMetadata[Block].push_back(R);
+      }
+    }
+
+    // If this is the end of the list, we're done.
+  } while (EatIfPresent(lltok::comma));
+  return false;
+}
+
 /// ParseInstructionMetadata
 ///   ::= !dbg !42 (',' !dbg !57)*
 bool LLParser::ParseInstructionMetadata(Instruction *Inst,
@@ -2799,7 +2866,7 @@
 }
 
 /// ParseBasicBlock
-///   ::= LabelStr? Instruction*
+///   ::= LabelStr? Metadata? Instruction*
 bool LLParser::ParseBasicBlock(PerFunctionState &PFS) {
   // If this basic block starts out with a name, remember it.
   std::string Name;
@@ -2812,6 +2879,11 @@
   BasicBlock *BB = PFS.DefineBB(Name, NameLoc);
   if (BB == 0) return true;
 
+  // Check if the block has metadata attached.
+  if (Lex.getKind() == lltok::MetadataVar) {
+    ParseBasicBlockMetadata(BB, &PFS);
+  }
+
   std::string NameStr;
 
   // Parse the instructions in this block until we get a terminator.
Index: lib/AsmParser/LLParser.h
===================================================================
--- lib/AsmParser/LLParser.h	(revision 156419)
+++ lib/AsmParser/LLParser.h	(working copy)
@@ -104,6 +104,7 @@
       SMLoc Loc;
       unsigned MDKind, MDSlot;
     };
+    DenseMap<BasicBlock*, std::vector<MDRef> > ForwardRefBlockMetadata;
     DenseMap<Instruction*, std::vector<MDRef> > ForwardRefInstMetadata;
 
     // Type resolution handling data structures.  The location is set when we
@@ -320,6 +321,7 @@
     bool ParseMetadataListValue(ValID &ID, PerFunctionState *PFS);
     bool ParseMetadataValue(ValID &ID, PerFunctionState *PFS);
     bool ParseMDNodeVector(SmallVectorImpl<Value*> &, PerFunctionState *PFS);
+    bool ParseBasicBlockMetadata(BasicBlock *Block, PerFunctionState *PFS);
     bool ParseInstructionMetadata(Instruction *Inst, PerFunctionState *PFS);
 
     // Function Parsing.
Index: lib/Bitcode/Reader/BitcodeReader.cpp
===================================================================
--- lib/Bitcode/Reader/BitcodeReader.cpp	(revision 156419)
+++ lib/Bitcode/Reader/BitcodeReader.cpp	(working copy)
@@ -1846,7 +1846,23 @@
       }
       break;
     }
+    case bitc::METADATA_BLOCK_ATTACHMENT: {
+      unsigned RecordLength = Record.size();
+      if (Record.empty() || (RecordLength - 1) % 2 == 1)
+        return Error ("Invalid METADATA_BLOCK_ATTACHMENT reader!");
+      BasicBlock *Block = getBasicBlock(Record[0]);
+      for (unsigned i = 1; i != RecordLength; i = i+2) {
+        unsigned Kind = Record[i];
+        DenseMap<unsigned, unsigned>::iterator I =
+          MDKindMap.find(Kind);
+        if (I == MDKindMap.end())
+          return Error("Invalid metadata kind ID");
+        Value *Node = MDValueList.getValueFwdRef(Record[i+1]);
+        Block->setMetadata(I->second, cast<MDNode>(Node));
+      }
+      break;
     }
+    }
   }
   return false;
 }
Index: lib/Bitcode/Writer/ValueEnumerator.cpp
===================================================================
--- lib/Bitcode/Writer/ValueEnumerator.cpp	(revision 156419)
+++ lib/Bitcode/Writer/ValueEnumerator.cpp	(working copy)
@@ -74,7 +74,19 @@
          I != E; ++I)
       EnumerateType(I->getType());
 
-    for (Function::const_iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
+    for (Function::const_iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
+      // Enumerate metadata attached with this block.
+      MDs.clear();
+      BB->getAllMetadataOtherThanDebugLoc(MDs);
+      for (unsigned i = 0, e = MDs.size(); i != e; ++i)
+        EnumerateMetadata(MDs[i].second);
+      if (!BB->getDebugLoc().isUnknown()) {
+        MDNode *Scope, *BBA;
+        BB->getDebugLoc().getScopeAndInlinedAt(Scope, BBA, BB->getContext());
+        if (Scope) EnumerateMetadata(Scope);
+        if (BBA) EnumerateMetadata(BBA);
+      }
+
       for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E;++I){
         for (User::const_op_iterator OI = I->op_begin(), E = I->op_end();
              OI != E; ++OI) {
@@ -103,6 +115,7 @@
           if (IA) EnumerateMetadata(IA);
         }
       }
+    }
   }
 
   // Optimize constant ordering.
@@ -465,6 +478,14 @@
   SmallVector<MDNode *, 8> FnLocalMDVector;
   // Add all of the instructions.
   for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB) {
+    SmallVector<std::pair<unsigned, MDNode*>, 8> MDs;
+    BB->getAllMetadataOtherThanDebugLoc(MDs);
+    for (unsigned i = 0, e = MDs.size(); i != e; ++i) {
+    MDNode *N = MDs[i].second;
+    if (N->isFunctionLocal() && N->getFunction())
+      FnLocalMDVector.push_back(N);
+    }
+        
     for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E; ++I) {
       for (User::const_op_iterator OI = I->op_begin(), E = I->op_end();
            OI != E; ++OI) {
Index: lib/Bitcode/Writer/BitcodeWriter.cpp
===================================================================
--- lib/Bitcode/Writer/BitcodeWriter.cpp	(revision 156419)
+++ lib/Bitcode/Writer/BitcodeWriter.cpp	(working copy)
@@ -670,10 +670,26 @@
   SmallVector<uint64_t, 64> Record;
 
   // Write metadata attachments
-  // METADATA_ATTACHMENT - [m x [value, [n x [id, mdnode]]]
+  // METADATA_ATTACHMENT       - [m x [value, [n x [id, mdnode]]]
+  // METADATA_BLOCK_ATTACHMENT - [m x [value, [n x [id, mdnode]]]
   SmallVector<std::pair<unsigned, MDNode*>, 4> MDs;
   
-  for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
+  for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB) {
+    // Write block metadata
+    MDs.clear();
+    BB->getAllMetadataOtherThanDebugLoc(MDs);
+    if (!MDs.empty()) {
+      //Record.push_back(VE.getGlobalBasicBlockID(BB));
+      Record.push_back(VE.getValueID(BB));
+      for (unsigned i = 0, e = MDs.size(); i != e; ++i) {
+        Record.push_back(MDs[i].first);
+        Record.push_back(VE.getValueID(MDs[i].second));
+      }
+      Stream.EmitRecord(bitc::METADATA_BLOCK_ATTACHMENT, Record, 0);
+      Record.clear();
+    }
+
+    // Write instruction metadata
     for (BasicBlock::const_iterator I = BB->begin(), E = BB->end();
          I != E; ++I) {
       MDs.clear();
@@ -691,6 +707,7 @@
       Stream.EmitRecord(bitc::METADATA_ATTACHMENT, Record, 0);
       Record.clear();
     }
+  }
 
   Stream.ExitBlock();
 }
@@ -1406,7 +1423,31 @@
   DebugLoc LastDL;
   
   // Finally, emit all the instructions, in order.
-  for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
+  for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB) {
+    // If the block has metadata, write a metadata attachment later.
+    NeedsMetadataAttachment |= BB->hasMetadataOtherThanDebugLoc();
+
+    // If the block has a debug location, emit it.
+    DebugLoc DL = BB->getDebugLoc();
+    if (DL.isUnknown()) {
+      // nothing todo.
+    } else if (DL == LastDL) {
+      // Just repeat the same debug loc as last time.
+      Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_LOC_AGAIN, Vals);
+    } else {
+      MDNode *Scope, *BBA;
+      DL.getScopeAndInlinedAt(Scope, BBA, BB->getContext());
+
+      Vals.push_back(DL.getLine());
+      Vals.push_back(DL.getCol());
+      Vals.push_back(Scope ? VE.getValueID(Scope)+1 : 0);
+      Vals.push_back(BBA ? VE.getValueID(BBA)+1 : 0);
+      Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_LOC, Vals);
+      Vals.clear();
+
+      LastDL = DL;
+    }
+
     for (BasicBlock::const_iterator I = BB->begin(), E = BB->end();
          I != E; ++I) {
       WriteInstruction(*I, InstID, VE, Stream, Vals);
@@ -1438,6 +1479,7 @@
         LastDL = DL;
       }
     }
+  }
 
   // Emit names for all the instructions etc.
   WriteValueSymbolTable(F.getValueSymbolTable(), VE, Stream);


More information about the llvm-commits mailing list