[llvm-commits] [llvm] r68420 - in /llvm/trunk: docs/LangRef.html include/llvm/Bitcode/LLVMBitCodes.h include/llvm/Constants.h include/llvm/Type.h include/llvm/Value.h lib/AsmParser/LLLexer.cpp lib/AsmParser/LLParser.cpp lib/AsmParser/LLParser.h lib/AsmParser/LLToken.h lib/Bitcode/Reader/BitcodeReader.cpp lib/Bitcode/Writer/BitcodeWriter.cpp lib/VMCore/AsmWriter.cpp lib/VMCore/Constants.cpp lib/VMCore/Type.cpp lib/VMCore/Verifier.cpp test/Feature/embeddedmetadata.ll unittests/VMCore/MetadataTest.cpp

Nick Lewycky nicholas at mxc.ca
Sat Apr 4 00:22:02 PDT 2009


Author: nicholas
Date: Sat Apr  4 02:22:01 2009
New Revision: 68420

URL: http://llvm.org/viewvc/llvm-project?rev=68420&view=rev
Log:
Add support for embedded metadata to LLVM. This introduces two new types of
Constant, MDString and MDNode which can only be used by globals with a name
that starts with "llvm." or as arguments to a function with the same naming
restriction.

Added:
    llvm/trunk/test/Feature/embeddedmetadata.ll
    llvm/trunk/unittests/VMCore/MetadataTest.cpp
Modified:
    llvm/trunk/docs/LangRef.html
    llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
    llvm/trunk/include/llvm/Constants.h
    llvm/trunk/include/llvm/Type.h
    llvm/trunk/include/llvm/Value.h
    llvm/trunk/lib/AsmParser/LLLexer.cpp
    llvm/trunk/lib/AsmParser/LLParser.cpp
    llvm/trunk/lib/AsmParser/LLParser.h
    llvm/trunk/lib/AsmParser/LLToken.h
    llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
    llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
    llvm/trunk/lib/VMCore/AsmWriter.cpp
    llvm/trunk/lib/VMCore/Constants.cpp
    llvm/trunk/lib/VMCore/Type.cpp
    llvm/trunk/lib/VMCore/Verifier.cpp

Modified: llvm/trunk/docs/LangRef.html
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.html?rev=68420&r1=68419&r2=68420&view=diff

==============================================================================
--- llvm/trunk/docs/LangRef.html (original)
+++ llvm/trunk/docs/LangRef.html Sat Apr  4 02:22:01 2009
@@ -65,6 +65,7 @@
       <li><a href="#globalconstants">Global Variable and Function Addresses</a></li>
       <li><a href="#undefvalues">Undefined Values</a></li>
       <li><a href="#constantexprs">Constant Expressions</a></li>
+      <li><a href="#metadata">Embedded Metadata</a></li>
     </ol>
   </li>
   <li><a href="#othervalues">Other Values</a>
@@ -1847,6 +1848,14 @@
   large arrays) and is always exactly equivalent to using explicit zero
   initializers.
   </dd>
+
+  <dt><b>Metadata node</b></dt>
+
+  <dd>A metadata node is a structure-like constant with the type of an empty
+  struct.  For example: "<tt>{ } !{ i32 0, { } !"test" }</tt>". Unlike other
+  constants that are meant to be interpreted as part of the instruction stream,
+  metadata is a place to attach additional information such as debug info.
+  </dd>
 </dl>
 
 </div>
@@ -2015,6 +2024,35 @@
 </dl>
 </div>
 
+<!-- ======================================================================= -->
+<div class="doc_subsection"><a name="metadata">Embedded Metadata</a>
+</div>
+
+<div class="doc_text">
+
+<p>Embedded metadata provides a way to attach arbitrary data to the
+instruction stream without affecting the behaviour of the program.  There are
+two metadata primitives, strings and nodes. All metadata has the type of an
+empty struct 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 "\xx" where "xx" is
+the two digit hex code.  For example: "<tt>!"test\00"</tt>".
+</p>
+
+<p>Metadata nodes are represented with notation similar to structure constants
+(a comma separated list of elements, surrounded by braces and preceeded by an
+exclamation point).  For example: "<tt>!{ { } !"test\00", i32 10}</tt>".
+</p>
+
+<p>Optimizations may rely on metadata to provide additional information about
+the program that isn't available in the instructions, or that isn't easily
+computable. Similarly, the code generator may expect a certain metadata format
+to be used to express debugging information.</p>
+</div>
+
 <!-- *********************************************************************** -->
 <div class="doc_section"> <a name="othervalues">Other Values</a> </div>
 <!-- *********************************************************************** -->

Modified: llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h?rev=68420&r1=68419&r2=68420&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h (original)
+++ llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h Sat Apr  4 02:22:01 2009
@@ -126,7 +126,9 @@
     CST_CODE_CE_SHUFFLEVEC = 16,  // CE_SHUFFLEVEC: [opval, opval, opval]
     CST_CODE_CE_CMP        = 17,  // CE_CMP:        [opty, opval, opval, pred]
     CST_CODE_INLINEASM     = 18,  // INLINEASM:     [sideeffect,asmstr,conststr]
-    CST_CODE_CE_SHUFVEC_EX = 19   // SHUFVEC_EX:    [opty, opval, opval, opval]
+    CST_CODE_CE_SHUFVEC_EX = 19,  // SHUFVEC_EX:    [opty, opval, opval, opval]
+    CST_CODE_MDSTRING      = 20,  // MDSTRING:      [values]
+    CST_CODE_MDNODE        = 21   // MDNODE:        [n x (type num, value num)]
   };
 
   /// CastOpcodes - These are values used in the bitcode files to encode which

Modified: llvm/trunk/include/llvm/Constants.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Constants.h?rev=68420&r1=68419&r2=68420&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Constants.h (original)
+++ llvm/trunk/include/llvm/Constants.h Sat Apr  4 02:22:01 2009
@@ -26,6 +26,7 @@
 #include "llvm/OperandTraits.h"
 #include "llvm/ADT/APInt.h"
 #include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/SmallVector.h"
 
 namespace llvm {
@@ -813,6 +814,109 @@
   }
 };
 
+//===----------------------------------------------------------------------===//
+/// MDString - a single uniqued string.
+/// These are used to efficiently contain a byte sequence for metadata.
+///
+class MDString : public Constant {
+  MDString(const MDString &);            // DO NOT IMPLEMENT
+  void *operator new(size_t, unsigned);  // DO NOT IMPLEMENT
+  MDString(const char *begin, const char *end);
+
+  const char *StrBegin, *StrEnd;
+protected:
+  // allocate space for exactly zero operands
+  void *operator new(size_t s) {
+    return User::operator new(s, 0);
+  }
+public:
+  /// get() - Static factory methods - Return objects of the specified value.
+  ///
+  static MDString *get(const char *StrBegin, const char *StrEnd);
+
+  /// size() - The length of this string.
+  ///
+  unsigned size() const { return StrEnd - StrBegin; }
+
+  /// begin() - Pointer to the first byte of the string.
+  ///
+  const char *begin() const { return StrBegin; }
+
+  /// end() - Pointer to one byte past the end of the string.
+  ///
+  const char *end() const { return StrEnd; }
+
+  /// getType() specialization - Type is always an empty struct.
+  ///
+  inline const Type *getType() const {
+    return Type::EmptyStructTy;
+  }
+
+  /// isNullValue - Return true if this is the value that would be returned by
+  /// getNullValue.  This always returns false because getNullValue will never
+  /// produce metadata.
+  virtual bool isNullValue() const {
+    return false;
+  }
+
+  virtual void destroyConstant();
+
+  /// Methods for support type inquiry through isa, cast, and dyn_cast:
+  static inline bool classof(const MDString *) { return true; }
+  static bool classof(const Value *V) {
+    return V->getValueID() == MDStringVal;
+  }
+};
+
+//===----------------------------------------------------------------------===//
+/// MDNode - a tuple of other values.
+/// These contain a list of the Constants that represent the metadata.
+///
+class MDNode : public Constant, public FoldingSetNode {
+  MDNode(const MDNode &);      // DO NOT IMPLEMENT
+protected:
+  explicit MDNode(Constant*const* Vals, unsigned NumVals);
+public:
+  /// get() - Static factory methods - Return objects of the specified value.
+  ///
+  static MDNode *get(Constant*const* Vals, unsigned NumVals);
+
+  // Transparently provide more efficient getOperand methods.
+  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant);
+
+  /// getType() specialization - Type is always an empty struct.
+  ///
+  inline const Type *getType() const {
+    return Type::EmptyStructTy;
+  }
+
+  /// isNullValue - Return true if this is the value that would be returned by
+  /// getNullValue.  This always returns false because getNullValue will never
+  /// produce metadata.
+  virtual bool isNullValue() const {
+    return false;
+  }
+
+  /// Profile - calculate a unique identifier for this MDNode to collapse
+  /// duplicates
+  void Profile(FoldingSetNodeID &ID);
+
+  virtual void destroyConstant();
+  virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U);
+
+  /// Methods for support type inquiry through isa, cast, and dyn_cast:
+  static inline bool classof(const MDNode *) { return true; }
+  static bool classof(const Value *V) {
+    return V->getValueID() == MDNodeVal;
+  }
+};
+
+template <>
+struct OperandTraits<MDNode> : VariadicOperandTraits<> {
+};
+
+DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(MDNode, Constant)
+
 } // End llvm namespace
 
 #endif

Modified: llvm/trunk/include/llvm/Type.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Type.h?rev=68420&r1=68419&r2=68420&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Type.h (original)
+++ llvm/trunk/include/llvm/Type.h Sat Apr  4 02:22:01 2009
@@ -326,7 +326,7 @@
   //===--------------------------------------------------------------------===//
   // These are the builtin types that are always available...
   //
-  static const Type *VoidTy, *LabelTy, *FloatTy, *DoubleTy;
+  static const Type *VoidTy, *LabelTy, *FloatTy, *DoubleTy, *EmptyStructTy;
   static const Type *X86_FP80Ty, *FP128Ty, *PPC_FP128Ty;
   static const IntegerType *Int1Ty, *Int8Ty, *Int16Ty, *Int32Ty, *Int64Ty;
 

Modified: llvm/trunk/include/llvm/Value.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Value.h?rev=68420&r1=68419&r2=68420&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Value.h (original)
+++ llvm/trunk/include/llvm/Value.h Sat Apr  4 02:22:01 2009
@@ -203,13 +203,15 @@
     ConstantStructVal,        // This is an instance of ConstantStruct
     ConstantVectorVal,        // This is an instance of ConstantVector
     ConstantPointerNullVal,   // This is an instance of ConstantPointerNull
+    MDStringVal,              // This is an instance of MDString
+    MDNodeVal,                // This is an instance of MDNode
     InlineAsmVal,             // This is an instance of InlineAsm
     PseudoSourceValueVal,     // This is an instance of PseudoSourceValue
     InstructionVal,           // This is an instance of Instruction
     
     // Markers:
     ConstantFirstVal = FunctionVal,
-    ConstantLastVal  = ConstantPointerNullVal
+    ConstantLastVal  = MDNodeVal
   };
 
   /// getValueID - Return an ID for the concrete type of this object.  This is

Modified: llvm/trunk/lib/AsmParser/LLLexer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLLexer.cpp?rev=68420&r1=68419&r2=68420&view=diff

==============================================================================
--- llvm/trunk/lib/AsmParser/LLLexer.cpp (original)
+++ llvm/trunk/lib/AsmParser/LLLexer.cpp Sat Apr  4 02:22:01 2009
@@ -265,6 +265,7 @@
   case ';':
     SkipLineComment();
     return LexToken();
+  case '!': return lltok::Metadata;
   case '0': case '1': case '2': case '3': case '4':
   case '5': case '6': case '7': case '8': case '9':
   case '-':

Modified: llvm/trunk/lib/AsmParser/LLParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=68420&r1=68419&r2=68420&view=diff

==============================================================================
--- llvm/trunk/lib/AsmParser/LLParser.cpp (original)
+++ llvm/trunk/lib/AsmParser/LLParser.cpp Sat Apr  4 02:22:01 2009
@@ -1561,6 +1561,29 @@
     ID.StrVal = Lex.getStrVal();
     ID.Kind = ValID::t_LocalName;
     break;
+  case lltok::Metadata: {  // !{...} MDNode, !"foo" MDString
+    ID.Kind = ValID::t_Constant;
+    Lex.Lex();
+    if (Lex.getKind() == lltok::lbrace) {
+      // MDNode:
+      //  ::= '!' '{' TypeAndValue (',' TypeAndValue)* '}'
+      SmallVector<Constant*, 16> Elts;
+      if (ParseMDNodeVector(Elts) ||
+          ParseToken(lltok::rbrace, "expected end of metadata node"))
+        return true;
+    
+      ID.ConstantVal = MDNode::get(&Elts[0], Elts.size());
+      return false;
+    }
+
+    // MDString:
+    //   ::= '!' STRINGCONSTANT
+    std::string Str;
+    if (ParseStringConstant(Str)) return true;
+
+    ID.ConstantVal = MDString::get(Str.data(), Str.data() + Str.size());
+    return false;
+  }
   case lltok::APSInt:
     ID.APSIntVal = Lex.getAPSIntVal(); 
     ID.Kind = ValID::t_APSInt;
@@ -1661,7 +1684,7 @@
                      "array element #" + utostr(i) +
                      " is not of type '" +Elts[0]->getType()->getDescription());
     }
-          
+    
     ID.ConstantVal = ConstantArray::get(ATy, &Elts[0], Elts.size());
     ID.Kind = ValID::t_Constant;
     return false;
@@ -3221,3 +3244,21 @@
   Inst = InsertValueInst::Create(Val0, Val1, Indices.begin(), Indices.end());
   return false;
 }
+
+//===----------------------------------------------------------------------===//
+// Embedded metadata.
+//===----------------------------------------------------------------------===//
+
+/// ParseMDNodeVector
+///   ::= TypeAndValue (',' TypeAndValue)*
+bool LLParser::ParseMDNodeVector(SmallVectorImpl<Constant*> &Elts) {
+  assert(Lex.getKind() == lltok::lbrace);
+  Lex.Lex();
+  do {
+    Constant *C;
+    if (ParseGlobalTypeAndValue(C)) return true;
+    Elts.push_back(C);
+  } while (EatIfPresent(lltok::comma));
+
+  return false;
+}

Modified: llvm/trunk/lib/AsmParser/LLParser.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.h?rev=68420&r1=68419&r2=68420&view=diff

==============================================================================
--- llvm/trunk/lib/AsmParser/LLParser.h (original)
+++ llvm/trunk/lib/AsmParser/LLParser.h Sat Apr  4 02:22:01 2009
@@ -27,6 +27,8 @@
   class Instruction;
   class Constant;
   class GlobalValue;
+  class MDString;
+  class MDNode;
   struct ValID;
 
   class LLParser {
@@ -156,6 +158,7 @@
     bool ParseGlobalValue(const Type *Ty, Constant *&V);
     bool ParseGlobalTypeAndValue(Constant *&V);
     bool ParseGlobalValueVector(SmallVectorImpl<Constant*> &Elts);
+    bool ParseMDNodeVector(SmallVectorImpl<Constant*> &);
 
 
     // Function Semantic Analysis.

Modified: llvm/trunk/lib/AsmParser/LLToken.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLToken.h?rev=68420&r1=68419&r2=68420&view=diff

==============================================================================
--- llvm/trunk/lib/AsmParser/LLToken.h (original)
+++ llvm/trunk/lib/AsmParser/LLToken.h Sat Apr  4 02:22:01 2009
@@ -115,6 +115,9 @@
     LocalVar,          // %foo %"foo"
     StringConstant,    // "foo"
 
+    // Metadata valued tokens.
+    Metadata,          // !"foo" !{i8 42}
+
     // Type valued tokens (TyVal).
     Type,
 

Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=68420&r1=68419&r2=68420&view=diff

==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
+++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Sat Apr  4 02:22:01 2009
@@ -286,10 +286,12 @@
                                    UserCS->getType()->isPacked());
       } else if (isa<ConstantVector>(UserC)) {
         NewC = ConstantVector::get(&NewOps[0], NewOps.size());
-      } else {
-        // Must be a constant expression.
+      } else if (isa<ConstantExpr>(UserC)) {
         NewC = cast<ConstantExpr>(UserC)->getWithOperands(&NewOps[0],
                                                           NewOps.size());
+      } else {
+        assert(isa<MDNode>(UserC) && "Must be a metadata node.");
+        NewC = MDNode::get(&NewOps[0], NewOps.size());
       }
       
       UserC->replaceAllUsesWith(NewC);
@@ -999,6 +1001,29 @@
                          AsmStr, ConstrStr, HasSideEffects);
       break;
     }
+    case bitc::CST_CODE_MDSTRING: {
+      if (Record.size() < 2) return Error("Invalid MDSTRING record");
+      unsigned MDStringLength = Record.size();
+      SmallString<8> String;
+      String.resize(MDStringLength);
+      for (unsigned i = 0; i != MDStringLength; ++i)
+        String[i] = Record[i];
+      V = MDString::get(String.c_str(), String.c_str() + MDStringLength);
+      break;
+    }
+    case bitc::CST_CODE_MDNODE: {
+      if (Record.empty() || Record.size() % 2 == 1)
+        return Error("Invalid CST_MDNODE record");
+      
+      unsigned Size = Record.size();
+      SmallVector<Constant*, 8> Elts;
+      for (unsigned i = 0; i != Size; i += 2) {
+        const Type *Ty = getTypeByID(Record[i], false);
+        Elts.push_back(ValueList.getConstantFwdRef(Record[i+1], Ty));
+      }
+      V = MDNode::get(&Elts[0], Elts.size());
+      break;
+    }
     }
     
     ValueList.AssignValue(V, NextCstNo);

Modified: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp?rev=68420&r1=68419&r2=68420&view=diff

==============================================================================
--- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp (original)
+++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp Sat Apr  4 02:22:01 2009
@@ -458,6 +458,8 @@
   unsigned String8Abbrev = 0;
   unsigned CString7Abbrev = 0;
   unsigned CString6Abbrev = 0;
+  unsigned MDString8Abbrev = 0;
+  unsigned MDString6Abbrev = 0;
   // If this is a constant pool for the module, emit module-specific abbrevs.
   if (isGlobal) {
     // Abbrev for CST_CODE_AGGREGATE.
@@ -485,6 +487,19 @@
     Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
     Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6));
     CString6Abbrev = Stream.EmitAbbrev(Abbv);
+
+    // Abbrev for CST_CODE_MDSTRING.
+    Abbv = new BitCodeAbbrev();
+    Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_MDSTRING));
+    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
+    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8));
+    MDString8Abbrev = Stream.EmitAbbrev(Abbv);
+    // Abbrev for CST_CODE_MDSTRING.
+    Abbv = new BitCodeAbbrev();
+    Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_MDSTRING));
+    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
+    Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6));
+    MDString6Abbrev = Stream.EmitAbbrev(Abbv);
   }  
   
   SmallVector<uint64_t, 64> Record;
@@ -678,6 +693,22 @@
         Record.push_back(CE->getPredicate());
         break;
       }
+    } else if (const MDString *S = dyn_cast<MDString>(C)) {
+      Code = bitc::CST_CODE_MDSTRING;
+      AbbrevToUse = MDString6Abbrev;
+      for (unsigned i = 0, e = S->size(); i != e; ++i) {
+        char V = S->begin()[i];
+        Record.push_back(V);
+
+        if (!BitCodeAbbrevOp::isChar6(V))
+          AbbrevToUse = MDString8Abbrev;
+      }
+    } else if (const MDNode *N = dyn_cast<MDNode>(C)) {
+      Code = bitc::CST_CODE_MDNODE;
+      for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
+        Record.push_back(VE.getTypeID(N->getOperand(i)->getType()));
+        Record.push_back(VE.getValueID(N->getOperand(i)));
+      }
     } else {
       assert(0 && "Unknown constant!");
     }

Modified: llvm/trunk/lib/VMCore/AsmWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/AsmWriter.cpp?rev=68420&r1=68419&r2=68420&view=diff

==============================================================================
--- llvm/trunk/lib/VMCore/AsmWriter.cpp (original)
+++ llvm/trunk/lib/VMCore/AsmWriter.cpp Sat Apr  4 02:22:01 2009
@@ -23,6 +23,7 @@
 #include "llvm/InlineAsm.h"
 #include "llvm/Instruction.h"
 #include "llvm/Instructions.h"
+#include "llvm/Metadata.h"
 #include "llvm/Module.h"
 #include "llvm/ValueSymbolTable.h"
 #include "llvm/TypeSymbolTable.h"
@@ -361,8 +362,8 @@
         return;
       
       // If this is a structure or opaque type, add a name for the type.
-      if ((isa<StructType>(Ty) || isa<OpaqueType>(Ty))
-          && !TP.hasTypeName(Ty)) {
+      if (((isa<StructType>(Ty) && cast<StructType>(Ty)->getNumElements())
+            || isa<OpaqueType>(Ty)) && !TP.hasTypeName(Ty)) {
         TP.addTypeName(Ty, "%"+utostr(unsigned(NumberedTypes.size())));
         NumberedTypes.push_back(Ty);
       }
@@ -935,7 +936,27 @@
     Out << "undef";
     return;
   }
+  
+  if (const MDString *S = dyn_cast<MDString>(CV)) {
+    Out << "!\"";
+    PrintEscapedString(S->begin(), S->size(), Out);
+    Out << '"';
+    return;
+  }
 
+  if (const MDNode *N = dyn_cast<MDNode>(CV)) {
+    Out << "!{";
+    for (MDNode::const_op_iterator I = N->op_begin(), E = N->op_end(); I != E;){
+      TypePrinter.print((*I)->getType(), Out);
+      Out << ' ';
+      WriteAsOperandInternal(Out, *I, TypePrinter, Machine);
+      if (++I != E)
+        Out << ", ";
+    }
+    Out << "}";
+    return;
+  }
+  
   if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
     Out << CE->getOpcodeName();
     if (CE->isCompare())

Modified: llvm/trunk/lib/VMCore/Constants.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Constants.cpp?rev=68420&r1=68419&r2=68420&view=diff

==============================================================================
--- llvm/trunk/lib/VMCore/Constants.cpp (original)
+++ llvm/trunk/lib/VMCore/Constants.cpp Sat Apr  4 02:22:01 2009
@@ -17,7 +17,9 @@
 #include "llvm/GlobalValue.h"
 #include "llvm/Instructions.h"
 #include "llvm/Module.h"
+#include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ManagedStatic.h"
@@ -1657,6 +1659,63 @@
   destroyConstantImpl();
 }
 
+//---- MDString::get() implementation
+//
+
+MDString::MDString(const char *begin, const char *end)
+  : Constant(Type::EmptyStructTy, MDStringVal, 0, 0),
+    StrBegin(begin), StrEnd(end) {}
+
+static ManagedStatic<StringMap<MDString*> > MDStringCache;
+
+MDString *MDString::get(const char *StrBegin, const char *StrEnd) {
+  StringMapEntry<MDString *> &Entry = MDStringCache->GetOrCreateValue(StrBegin,
+                                                                      StrEnd);
+  MDString *&S = Entry.getValue();
+  if (!S) S = new MDString(Entry.getKeyData(),
+                           Entry.getKeyData() + Entry.getKeyLength());
+  return S;
+}
+
+void MDString::destroyConstant() {
+  MDStringCache->erase(MDStringCache->find(StrBegin, StrEnd));
+  destroyConstantImpl();
+}
+
+//---- MDNode::get() implementation
+//
+
+static ManagedStatic<FoldingSet<MDNode> > MDNodeSet;
+
+MDNode::MDNode(Constant*const* Vals, unsigned NumVals)
+  : Constant(Type::EmptyStructTy, MDNodeVal,
+             OperandTraits<MDNode>::op_end(this) - NumVals, NumVals) {
+  std::copy(Vals, Vals + NumVals, OperandList);
+}
+
+void MDNode::Profile(FoldingSetNodeID &ID) {
+  for (op_iterator I = op_begin(), E = op_end(); I != E; ++I)
+    ID.AddPointer(*I);
+}
+
+MDNode *MDNode::get(Constant*const* Vals, unsigned NumVals) {
+  FoldingSetNodeID ID;
+  for (unsigned i = 0; i != NumVals; ++i)
+    ID.AddPointer(Vals[i]);
+
+  void *InsertPoint;
+  if (MDNode *N = MDNodeSet->FindNodeOrInsertPos(ID, InsertPoint))
+    return N;
+
+  // InsertPoint will have been set by the FindNodeOrInsertPos call.
+  MDNode *N = new(NumVals) MDNode(Vals, NumVals);
+  MDNodeSet->InsertNode(N, InsertPoint);
+  return N;
+}
+
+void MDNode::destroyConstant() {
+  destroyConstantImpl();
+}
 
 //---- ConstantExpr::get() implementations...
 //
@@ -2741,3 +2800,24 @@
   // Delete the old constant!
   destroyConstant();
 }
+
+void MDNode::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) {
+  assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
+  
+  SmallVector<Constant*, 8> Values;
+  Values.reserve(getNumOperands());  // Build replacement array...
+  for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
+    Constant *Val = getOperand(i);
+    if (Val == From) Val = cast<Constant>(To);
+    Values.push_back(Val);
+  }
+  
+  Constant *Replacement = MDNode::get(&Values[0], Values.size());
+  assert(Replacement != this && "I didn't contain From!");
+  
+  // Everyone using this now uses the replacement.
+  uncheckedReplaceAllUsesWith(Replacement);
+  
+  // Delete the old constant!
+  destroyConstant();
+}

Modified: llvm/trunk/lib/VMCore/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Type.cpp?rev=68420&r1=68419&r2=68420&view=diff

==============================================================================
--- llvm/trunk/lib/VMCore/Type.cpp (original)
+++ llvm/trunk/lib/VMCore/Type.cpp Sat Apr  4 02:22:01 2009
@@ -288,6 +288,8 @@
 const IntegerType *Type::Int32Ty = new BuiltinIntegerType(32);
 const IntegerType *Type::Int64Ty = new BuiltinIntegerType(64);
 
+const Type *Type::EmptyStructTy = StructType::get(NULL, NULL);
+
 
 //===----------------------------------------------------------------------===//
 //                          Derived Type Constructors

Modified: llvm/trunk/lib/VMCore/Verifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Verifier.cpp?rev=68420&r1=68419&r2=68420&view=diff

==============================================================================
--- llvm/trunk/lib/VMCore/Verifier.cpp (original)
+++ llvm/trunk/lib/VMCore/Verifier.cpp Sat Apr  4 02:22:01 2009
@@ -338,6 +338,36 @@
 #define Assert4(C, M, V1, V2, V3, V4) \
   do { if (!(C)) { CheckFailed(M, V1, V2, V3, V4); return; } } while (0)
 
+/// Check whether or not a Value is metadata or made up of a constant
+/// expression involving metadata.
+static bool isMetadata(Value *X) {
+  SmallPtrSet<Value *, 8> Visited;
+  SmallVector<Value *, 8> Queue;
+  Queue.push_back(X);
+
+  while (!Queue.empty()) {
+    Value *V = Queue.back();
+    Queue.pop_back();
+    if (!Visited.insert(V))
+      continue;
+
+    if (isa<MDString>(V) || isa<MDNode>(V))
+      return true;
+    if (!isa<ConstantExpr>(V))
+      continue;
+    ConstantExpr *CE = cast<ConstantExpr>(V);
+
+    if (CE->getType() != Type::EmptyStructTy)
+      continue;
+
+    // The only constant expression that works on metadata type is select.
+    if (CE->getOpcode() != Instruction::Select) return false;
+
+    Queue.push_back(CE->getOperand(1));
+    Queue.push_back(CE->getOperand(2));
+  }
+  return false;
+}
 
 void Verifier::visit(Instruction &I) {
   for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i)
@@ -649,6 +679,7 @@
             "Found return instr that returns non-void in Function of void "
             "return type!", &RI, F->getReturnType());
   else if (N == 1 && F->getReturnType() == RI.getOperand(0)->getType()) {
+    Assert1(!isMetadata(RI.getOperand(0)), "Invalid use of metadata!", &RI);
     // Exactly one return value and it matches the return type. Good.
   } else if (const StructType *STy = dyn_cast<StructType>(F->getReturnType())) {
     // The return type is a struct; check for multiple return values.
@@ -696,6 +727,8 @@
 
   Assert1(SI.getTrueValue()->getType() == SI.getType(),
           "Select values must have same type as select instruction!", &SI);
+  Assert1(!isMetadata(SI.getOperand(1)) && !isMetadata(SI.getOperand(2)),
+          "Invalid use of metadata!", &SI);
   visitInstruction(SI);
 }
 
@@ -951,6 +984,13 @@
     Assert1(PN.getType() == PN.getIncomingValue(i)->getType(),
             "PHI node operands are not the same type as the result!", &PN);
 
+  // Check that it's not a PHI of metadata.
+  if (PN.getType() == Type::EmptyStructTy) {
+    for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i)
+      Assert1(!isMetadata(PN.getIncomingValue(i)),
+              "Invalid use of metadata!", &PN);
+  }
+
   // All other PHI node constraints are checked in the visitBasicBlock method.
 
   visitInstruction(PN);
@@ -981,6 +1021,14 @@
             "Call parameter type does not match function signature!",
             CS.getArgument(i), FTy->getParamType(i), I);
 
+  if (CS.getCalledValue()->getNameLen() < 5 ||
+      strncmp(CS.getCalledValue()->getNameStart(), "llvm.", 5) != 0) {
+    // Verify that none of the arguments are metadata...
+    for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i)
+      Assert2(!isMetadata(CS.getArgument(i)), "Invalid use of metadata!",
+              CS.getArgument(i), I);
+  }
+
   const AttrListPtr &Attrs = CS.getAttributes();
 
   Assert1(VerifyAttributeCount(Attrs, CS.arg_size()),
@@ -1152,6 +1200,7 @@
     cast<PointerType>(SI.getOperand(1)->getType())->getElementType();
   Assert2(ElTy == SI.getOperand(0)->getType(),
           "Stored value type does not match pointer operand type!", &SI, ElTy);
+  Assert1(!isMetadata(SI.getOperand(0)), "Invalid use of metadata!", &SI);
   visitInstruction(SI);
 }
 
@@ -1481,7 +1530,7 @@
     if (EltTy != Ty)
       Suffix += "v" + utostr(NumElts);
 
-    Suffix += "i" + utostr(GotBits);;
+    Suffix += "i" + utostr(GotBits);
 
     // Check some constraints on various intrinsics.
     switch (ID) {

Added: llvm/trunk/test/Feature/embeddedmetadata.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Feature/embeddedmetadata.ll?rev=68420&view=auto

==============================================================================
--- llvm/trunk/test/Feature/embeddedmetadata.ll (added)
+++ llvm/trunk/test/Feature/embeddedmetadata.ll Sat Apr  4 02:22:01 2009
@@ -0,0 +1,11 @@
+; RUN: llvm-as < %s | llvm-dis | not grep undef
+
+declare i8 @llvm.something({ } %a)
+
+ at llvm.foo = internal constant { } !{i17 123, { } !"foobar"}
+
+define void @foo() {
+  %x = call i8 @llvm.something({ } !{{ } !"f\00oa", i42 123})
+  ret void
+}
+

Added: llvm/trunk/unittests/VMCore/MetadataTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/VMCore/MetadataTest.cpp?rev=68420&view=auto

==============================================================================
--- llvm/trunk/unittests/VMCore/MetadataTest.cpp (added)
+++ llvm/trunk/unittests/VMCore/MetadataTest.cpp Sat Apr  4 02:22:01 2009
@@ -0,0 +1,96 @@
+//===- llvm/unittest/VMCore/Metadata.cpp - Metadata unit tests ------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+#include "llvm/Constants.h"
+#include <sstream>
+
+using namespace llvm;
+
+namespace {
+
+// Test that construction of MDString with different value produces different
+// MDString objects, even with the same string pointer and nulls in the string.
+TEST(MDStringTest, CreateDifferent) {
+  char x[3] = { 'f', 0, 'A' };
+  MDString *s1 = MDString::get(&x[0], &x[3]);
+  x[2] = 'B';
+  MDString *s2 = MDString::get(&x[0], &x[3]);
+  EXPECT_NE(s1, s2);
+}
+
+// Test that creation of MDStrings with the same string contents produces the
+// same MDString object, even with different pointers.
+TEST(MDStringTest, CreateSame) {
+  char x[4] = { 'a', 'b', 'c', 'X' };
+  char y[4] = { 'a', 'b', 'c', 'Y' };
+
+  MDString *s1 = MDString::get(&x[0], &x[3]);
+  MDString *s2 = MDString::get(&y[0], &y[3]);
+  EXPECT_EQ(s1, s2);
+}
+
+// Test that MDString prints out the string we fed it.
+TEST(MDStringTest, PrintingSimple) {
+  char *str = new char[13];
+  strncpy(str, "testing 1 2 3", 13);
+  MDString *s = MDString::get(str, str+13);
+  strncpy(str, "aaaaaaaaaaaaa", 13);
+  delete[] str;
+
+  std::ostringstream oss;
+  s->print(oss);
+  EXPECT_STREQ("{ } !\"testing 1 2 3\"", oss.str().c_str());
+}
+
+// Test printing of MDString with non-printable characters.
+TEST(MDStringTest, PrintingComplex) {
+  char str[5] = {0, '\n', '"', '\\', -1};
+  MDString *s = MDString::get(str+0, str+5);
+  std::ostringstream oss;
+  s->print(oss);
+  EXPECT_STREQ("{ } !\"\\00\\0A\\22\\5C\\FF\"", oss.str().c_str());
+}
+
+// Test the two constructors, and containing other Constants.
+TEST(MDNodeTest, Everything) {
+  char x[3] = { 'a', 'b', 'c' };
+  char y[3] = { '1', '2', '3' };
+
+  MDString *s1 = MDString::get(&x[0], &x[3]);
+  MDString *s2 = MDString::get(&y[0], &y[3]);
+  ConstantInt *CI = ConstantInt::get(APInt(8, 0));
+
+  std::vector<Constant *> V;
+  V.push_back(s1);
+  V.push_back(CI);
+  V.push_back(s2);
+
+  MDNode *n1 = MDNode::get(&V[0], 3);
+  MDNode *n2 = MDNode::get((Constant**)&n1, 1);
+  MDNode *n3 = MDNode::get(&V[0], 3);
+  EXPECT_NE(n1, n2);
+  EXPECT_EQ(n1, n3);
+
+  EXPECT_EQ(3u, n1->getNumOperands());
+  EXPECT_EQ(s1, n1->getOperand(0));
+  EXPECT_EQ(CI, n1->getOperand(1));
+  EXPECT_EQ(s2, n1->getOperand(2));
+
+  EXPECT_EQ(1u, n2->getNumOperands());
+  EXPECT_EQ(n1, n2->getOperand(0));
+
+  std::ostringstream oss1, oss2;
+  n1->print(oss1);
+  n2->print(oss2);
+  EXPECT_STREQ("{ } !{{ } !\"abc\", i8 0, { } !\"123\"}", oss1.str().c_str());
+  EXPECT_STREQ("{ } !{{ } !{{ } !\"abc\", i8 0, { } !\"123\"}}",
+               oss2.str().c_str());
+}
+}





More information about the llvm-commits mailing list