[llvm-commits] [llvm] r142288 - in /llvm/trunk: include/llvm/Target/TargetData.h lib/AsmParser/LLParser.cpp lib/Target/TargetData.cpp

Lang Hames lhames at gmail.com
Mon Oct 17 15:05:35 PDT 2011


Author: lhames
Date: Mon Oct 17 17:05:34 2011
New Revision: 142288

URL: http://llvm.org/viewvc/llvm-project?rev=142288&view=rev
Log:
Validate target data layout strings.
Invalid strings in asm files will result in parse errors. Invalid string literals passed to TargetData constructors will result in an assertion.

Modified:
    llvm/trunk/include/llvm/Target/TargetData.h
    llvm/trunk/lib/AsmParser/LLParser.cpp
    llvm/trunk/lib/Target/TargetData.cpp

Modified: llvm/trunk/include/llvm/Target/TargetData.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetData.h?rev=142288&r1=142287&r2=142288&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Target/TargetData.h (original)
+++ llvm/trunk/include/llvm/Target/TargetData.h Mon Oct 17 17:05:34 2011
@@ -44,7 +44,7 @@
   AGGREGATE_ALIGN = 'a',             ///< Aggregate alignment
   STACK_ALIGN = 's'                  ///< Stack objects alignment
 };
-  
+
 /// Target alignment element.
 ///
 /// Stores the alignment data associated with a given alignment type (pointer,
@@ -80,7 +80,7 @@
   unsigned      StackNaturalAlign;     ///< Stack natural alignment
 
   SmallVector<unsigned char, 8> LegalIntWidths; ///< Legal Integers.
-  
+
   /// Alignments- Where the primitive type alignment data is stored.
   ///
   /// @sa init().
@@ -88,7 +88,7 @@
   /// pointers vs. 64-bit pointers by extending TargetAlignment, but for now,
   /// we don't.
   SmallVector<TargetAlignElem, 16> Alignments;
-  
+
   /// InvalidAlignmentElem - This member is a signal that a requested alignment
   /// type and bit width were not found in the SmallVector.
   static const TargetAlignElem InvalidAlignmentElem;
@@ -112,19 +112,30 @@
     return &align != &InvalidAlignmentElem;
   }
 
+  /// Initialise a TargetData object with default values, ensure that the
+  /// target data pass is registered.
+  void init();
+
 public:
   /// Default ctor.
   ///
   /// @note This has to exist, because this is a pass, but it should never be
   /// used.
   TargetData();
-  
+
   /// Constructs a TargetData from a specification string. See init().
   explicit TargetData(StringRef TargetDescription)
     : ImmutablePass(ID) {
-    init(TargetDescription);
+    std::string errMsg = parseSpecifier(TargetDescription, this);
+    assert(errMsg == "" && "Invalid target data layout string.");
+    (void)errMsg;
   }
 
+  /// Parses a target data specification string. Returns an error message
+  /// if the string is malformed, or the empty string on success. Optionally
+  /// initialises a TargetData object if passed a non-null pointer.
+  static std::string parseSpecifier(StringRef TargetDescription, TargetData* td = 0);
+
   /// Initialize target data from properties stored in the module.
   explicit TargetData(const Module *M);
 
@@ -141,9 +152,6 @@
 
   ~TargetData();  // Not virtual, do not subclass this class
 
-  //! Parse a target data layout string and initialize TargetData alignments.
-  void init(StringRef TargetDescription);
-
   /// Target endianness...
   bool isLittleEndian() const { return LittleEndian; }
   bool isBigEndian() const { return !LittleEndian; }
@@ -152,7 +160,7 @@
   /// TargetData.  This representation is in the same format accepted by the
   /// string constructor above.
   std::string getStringRepresentation() const;
-  
+
   /// isLegalInteger - This function returns true if the specified type is
   /// known to be a native integer type supported by the CPU.  For example,
   /// i64 is not native on most 32-bit CPUs and i37 is not native on any known
@@ -166,7 +174,7 @@
         return true;
     return false;
   }
-  
+
   bool isIllegalInteger(unsigned Width) const {
     return !isLegalInteger(Width);
   }
@@ -251,11 +259,11 @@
   /// getABITypeAlignment - Return the minimum ABI-required alignment for the
   /// specified type.
   unsigned getABITypeAlignment(Type *Ty) const;
-  
+
   /// getABIIntegerTypeAlignment - Return the minimum ABI-required alignment for
   /// an integer type of the specified bitwidth.
   unsigned getABIIntegerTypeAlignment(unsigned BitWidth) const;
-  
+
 
   /// getCallFrameTypeAlignment - Return the minimum ABI-required alignment
   /// for the specified type when it is part of a call frame.
@@ -305,7 +313,7 @@
     assert((Alignment & (Alignment-1)) == 0 && "Alignment must be power of 2!");
     return (Val + (Alignment-1)) & ~UIntTy(Alignment-1);
   }
-  
+
   static char ID; // Pass identification, replacement for typeid
 };
 

Modified: llvm/trunk/lib/AsmParser/LLParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=142288&r1=142287&r2=142288&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLParser.cpp (original)
+++ llvm/trunk/lib/AsmParser/LLParser.cpp Mon Oct 17 17:05:34 2011
@@ -24,6 +24,7 @@
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetData.h"
 using namespace llvm;
 
 static std::string getTypeString(Type *T) {
@@ -260,9 +261,14 @@
     return false;
   case lltok::kw_datalayout:
     Lex.Lex();
+    LocTy SpecifierLoc = Lex.getLoc();
     if (ParseToken(lltok::equal, "expected '=' after target datalayout") ||
         ParseStringConstant(Str))
       return true;
+    std::string errMsg = TargetData::parseSpecifier(Str);
+    if (errMsg != "") {
+      return Error(SpecifierLoc, errMsg);
+    }
     M->setDataLayout(Str);
     return false;
   }

Modified: llvm/trunk/lib/Target/TargetData.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/TargetData.cpp?rev=142288&r1=142287&r2=142288&view=diff
==============================================================================
--- llvm/trunk/lib/Target/TargetData.cpp (original)
+++ llvm/trunk/lib/Target/TargetData.cpp Mon Oct 17 17:05:34 2011
@@ -125,15 +125,15 @@
 //===----------------------------------------------------------------------===//
 
 /// getInt - Get an integer ignoring errors.
-static unsigned getInt(StringRef R) {
-  unsigned Result = 0;
+static int getInt(StringRef R) {
+  int Result = 0;
   R.getAsInteger(10, Result);
   return Result;
 }
 
-void TargetData::init(StringRef Desc) {
+void TargetData::init() {
   initializeTargetDataPass(*PassRegistry::getPassRegistry());
-  
+
   LayoutMap = 0;
   LittleEndian = false;
   PointerMemSize = 8;
@@ -152,6 +152,12 @@
   setAlignment(VECTOR_ALIGN,    8,  8, 64);  // v2i32, v1i64, ...
   setAlignment(VECTOR_ALIGN,   16, 16, 128); // v16i8, v8i16, v4i32, ...
   setAlignment(AGGREGATE_ALIGN, 0,  8,  0);  // struct
+}
+
+std::string TargetData::parseSpecifier(StringRef Desc, TargetData *td) {
+
+  if (td)
+    td->init();
 
   while (!Desc.empty()) {
     std::pair<StringRef, StringRef> Split = Desc.split('-');
@@ -169,28 +175,54 @@
 
     switch (Specifier[0]) {
     case 'E':
-      LittleEndian = false;
+      if (td)
+        td->LittleEndian = false;
       break;
     case 'e':
-      LittleEndian = true;
+      if (td)
+        td->LittleEndian = true;
       break;
-    case 'p':
+    case 'p': {
+      // Pointer size.
       Split = Token.split(':');
-      PointerMemSize = getInt(Split.first) / 8;
+      int PointerMemSizeBits = getInt(Split.first);
+      if (PointerMemSizeBits < 0 || PointerMemSizeBits % 8 != 0)
+        return "invalid pointer size, must be a positive 8-bit multiple";
+      if (td)
+        td->PointerMemSize = PointerMemSizeBits / 8;
+
+      // Pointer ABI alignment.
       Split = Split.second.split(':');
-      PointerABIAlign = getInt(Split.first) / 8;
+      int PointerABIAlignBits = getInt(Split.first);
+      if (PointerABIAlignBits < 0 || PointerABIAlignBits % 8 != 0) {
+        return "invalid pointer ABI alignment, "
+               "must be a positive 8-bit multiple";
+      }
+      if (td)
+        td->PointerABIAlign = PointerABIAlignBits / 8;
+
+      // Pointer preferred alignment.
       Split = Split.second.split(':');
-      PointerPrefAlign = getInt(Split.first) / 8;
-      if (PointerPrefAlign == 0)
-        PointerPrefAlign = PointerABIAlign;
+      int PointerPrefAlignBits = getInt(Split.first);
+      if (PointerPrefAlignBits < 0 || PointerPrefAlignBits % 8 != 0) {
+        return "invalid pointer preferred alignment, "
+               "must be a positive 8-bit multiple";
+      }
+      if (td) {
+        td->PointerPrefAlign = PointerPrefAlignBits / 8;
+        if (td->PointerPrefAlign == 0)
+          td->PointerPrefAlign = td->PointerABIAlign;
+      }
       break;
+    }
     case 'i':
     case 'v':
     case 'f':
     case 'a':
     case 's': {
       AlignTypeEnum AlignType;
-      switch (Specifier[0]) {
+      char field = Specifier[0];
+      switch (field) {
       default:
       case 'i': AlignType = INTEGER_ALIGN; break;
       case 'v': AlignType = VECTOR_ALIGN; break;
@@ -198,37 +230,66 @@
       case 'a': AlignType = AGGREGATE_ALIGN; break;
       case 's': AlignType = STACK_ALIGN; break;
       }
-      unsigned Size = getInt(Specifier.substr(1));
+      int Size = getInt(Specifier.substr(1));
+      if (Size < 0) {
+        return std::string("invalid ") + field + "-size field, "
+               "must be positive";
+      }
+
       Split = Token.split(':');
-      unsigned ABIAlign = getInt(Split.first) / 8;
+      int ABIAlignBits = getInt(Split.first);
+      if (ABIAlignBits < 0 || ABIAlignBits % 8 != 0) {
+        return std::string("invalid ") + field +"-abi-alignment field, "
+               "must be a positive 8-bit multiple";
+      }
+      unsigned ABIAlign = ABIAlignBits / 8;
 
       Split = Split.second.split(':');
-      unsigned PrefAlign = getInt(Split.first) / 8;
+
+      int PrefAlignBits = getInt(Split.first);
+      if (PrefAlignBits < 0 || PrefAlignBits % 8 != 0) {
+        return std::string("invalid ") + field +"-preferred-alignment field, "
+               "must be a positive 8-bit multiple";
+      }
+      unsigned PrefAlign = PrefAlignBits / 8;
       if (PrefAlign == 0)
         PrefAlign = ABIAlign;
-      setAlignment(AlignType, ABIAlign, PrefAlign, Size);
+      
+      if (td)
+        td->setAlignment(AlignType, ABIAlign, PrefAlign, Size);
       break;
     }
     case 'n':  // Native integer types.
       Specifier = Specifier.substr(1);
       do {
-        if (unsigned Width = getInt(Specifier))
-          LegalIntWidths.push_back(Width);
+        int Width = getInt(Specifier);
+        if (Width <= 0) {
+          return std::string("invalid native integer size \'") + Specifier.str() +
+                 "\', must be a positive integer.";
+        }
+        if (td && Width != 0)
+          td->LegalIntWidths.push_back(Width);
         Split = Token.split(':');
         Specifier = Split.first;
         Token = Split.second;
       } while (!Specifier.empty() || !Token.empty());
       break;
-    case 'S': // Stack natural alignment.
-      StackNaturalAlign = getInt(Specifier.substr(1));
-      StackNaturalAlign /= 8;
-      // FIXME: Should we really be truncating these alingments and
-      // sizes silently?
+    case 'S': { // Stack natural alignment.
+      int StackNaturalAlignBits = getInt(Specifier.substr(1));
+      if (StackNaturalAlignBits < 0 || StackNaturalAlignBits % 8 != 0) {
+        return "invalid natural stack alignment (S-field), "
+               "must be a positive 8-bit multiple";
+      }
+      if (td)
+        td->StackNaturalAlign = StackNaturalAlignBits / 8;
       break;
+    }
     default:
       break;
     }
   }
+
+  return "";
 }
 
 /// Default ctor.
@@ -242,7 +303,9 @@
 
 TargetData::TargetData(const Module *M)
   : ImmutablePass(ID) {
-  init(M->getDataLayout());
+  std::string errMsg = parseSpecifier(M->getDataLayout(), this);
+  assert(errMsg == "" && "Module M has malformed target data layout string.");
+  (void)errMsg;
 }
 
 void





More information about the llvm-commits mailing list