[llvm] r262884 - [AsmParser] Expose an API to parse a string starting with a type.

Quentin Colombet via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 7 16:37:08 PST 2016


Author: qcolombet
Date: Mon Mar  7 18:37:07 2016
New Revision: 262884

URL: http://llvm.org/viewvc/llvm-project?rev=262884&view=rev
Log:
[AsmParser] Expose an API to parse a string starting with a type.

Without actually parsing a type it is difficult to perdict where
the type definition ends. In other words, instead of expecting
the user of the parser API to hand over only the relevant bits
of the string being parsed, take the whole string, parse the type,
and get back the number of characters that have been read.

This will be used by the MIR testing infrastructure.

Modified:
    llvm/trunk/include/llvm/AsmParser/Parser.h
    llvm/trunk/lib/AsmParser/LLParser.cpp
    llvm/trunk/lib/AsmParser/LLParser.h
    llvm/trunk/lib/AsmParser/Parser.cpp
    llvm/trunk/unittests/AsmParser/AsmParserTest.cpp

Modified: llvm/trunk/include/llvm/AsmParser/Parser.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/AsmParser/Parser.h?rev=262884&r1=262883&r2=262884&view=diff
==============================================================================
--- llvm/trunk/include/llvm/AsmParser/Parser.h (original)
+++ llvm/trunk/include/llvm/AsmParser/Parser.h Mon Mar  7 18:37:07 2016
@@ -100,6 +100,16 @@ Constant *parseConstantValue(StringRef A
 Type *parseType(StringRef Asm, SMDiagnostic &Err, const Module &M,
                 const SlotMapping *Slots = nullptr);
 
+/// Parse a string \p Asm that starts with a type.
+/// \p Read[out] gives the number of characters that have been read to parse
+/// the type in \p Asm.
+///
+/// \param Slots The optional slot mapping that will restore the parsing state
+/// of the module.
+/// \return null on error.
+Type *parseTypeAtBeginning(StringRef Asm, unsigned &Read, SMDiagnostic &Err,
+                           const Module &M, const SlotMapping *Slots = nullptr);
+
 } // End llvm namespace
 
 #endif

Modified: llvm/trunk/lib/AsmParser/LLParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=262884&r1=262883&r2=262884&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLParser.cpp (original)
+++ llvm/trunk/lib/AsmParser/LLParser.cpp Mon Mar  7 18:37:07 2016
@@ -63,15 +63,19 @@ bool LLParser::parseStandaloneConstantVa
   return false;
 }
 
-bool LLParser::parseStandaloneType(Type *&Ty, const SlotMapping *Slots) {
+bool LLParser::parseTypeAtBeginning(Type *&Ty, unsigned &Read,
+                                    const SlotMapping *Slots) {
   restoreParsingState(Slots);
   Lex.Lex();
 
+  Read = 0;
+  SMLoc Start = Lex.getLoc();
   Ty = nullptr;
   if (ParseType(Ty))
     return true;
-  if (Lex.getKind() != lltok::Eof)
-    return Error(Lex.getLoc(), "expected end of string");
+  SMLoc End = Lex.getLoc();
+  Read = End.getPointer() - Start.getPointer();
+
   return false;
 }
 

Modified: llvm/trunk/lib/AsmParser/LLParser.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.h?rev=262884&r1=262883&r2=262884&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLParser.h (original)
+++ llvm/trunk/lib/AsmParser/LLParser.h Mon Mar  7 18:37:07 2016
@@ -148,7 +148,8 @@ namespace llvm {
 
     bool parseStandaloneConstantValue(Constant *&C, const SlotMapping *Slots);
 
-    bool parseStandaloneType(Type *&Ty, const SlotMapping *Slots);
+    bool parseTypeAtBeginning(Type *&Ty, unsigned &Read,
+                              const SlotMapping *Slots);
 
     LLVMContext &getContext() { return Context; }
 

Modified: llvm/trunk/lib/AsmParser/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/Parser.cpp?rev=262884&r1=262883&r2=262884&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/Parser.cpp (original)
+++ llvm/trunk/lib/AsmParser/Parser.cpp Mon Mar  7 18:37:07 2016
@@ -81,12 +81,29 @@ Constant *llvm::parseConstantValue(Strin
 
 Type *llvm::parseType(StringRef Asm, SMDiagnostic &Err, const Module &M,
                       const SlotMapping *Slots) {
+  unsigned Read;
+  Type *Ty = parseTypeAtBeginning(Asm, Read, Err, M, Slots);
+  if (!Ty)
+    return nullptr;
+  if (Read != Asm.size()) {
+    SourceMgr SM;
+    std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Asm);
+    SM.AddNewSourceBuffer(std::move(Buf), SMLoc());
+    Err = SM.GetMessage(SMLoc::getFromPointer(Asm.begin() + Read),
+                        SourceMgr::DK_Error, "expected end of string");
+    return nullptr;
+  }
+  return Ty;
+}
+Type *llvm::parseTypeAtBeginning(StringRef Asm, unsigned &Read,
+                                 SMDiagnostic &Err, const Module &M,
+                                 const SlotMapping *Slots) {
   SourceMgr SM;
   std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Asm);
   SM.AddNewSourceBuffer(std::move(Buf), SMLoc());
   Type *Ty;
   if (LLParser(Asm, SM, Err, const_cast<Module *>(&M))
-          .parseStandaloneType(Ty, Slots))
+          .parseTypeAtBeginning(Ty, Read, Slots))
     return nullptr;
   return Ty;
 }

Modified: llvm/trunk/unittests/AsmParser/AsmParserTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/AsmParser/AsmParserTest.cpp?rev=262884&r1=262883&r2=262884&view=diff
==============================================================================
--- llvm/trunk/unittests/AsmParser/AsmParserTest.cpp (original)
+++ llvm/trunk/unittests/AsmParser/AsmParserTest.cpp Mon Mar  7 18:37:07 2016
@@ -270,6 +270,149 @@ TEST(AsmParserTest, TypeWithSlotMappingP
   Ty = PT->getElementType();
   ASSERT_TRUE(Ty->isIntegerTy());
   ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32);
+
+  // Check that we reject types with garbage.
+  Ty = parseType("i32 garbage", Error, M, &Mapping);
+  ASSERT_TRUE(!Ty);
+}
+
+TEST(AsmParserTest, TypeAtBeginningWithSlotMappingParsing) {
+  LLVMContext &Ctx = getGlobalContext();
+  SMDiagnostic Error;
+  StringRef Source =
+      "%st = type { i32, i32 }\n"
+      "@v = common global [50 x %st] zeroinitializer, align 16\n"
+      "%0 = type { i32, i32, i32, i32 }\n"
+      "@g = common global [50 x %0] zeroinitializer, align 16\n"
+      "define void @marker4(i64 %d) {\n"
+      "entry:\n"
+      "  %conv = trunc i64 %d to i32\n"
+      "  store i32 %conv, i32* getelementptr inbounds "
+      "    ([50 x %st], [50 x %st]* @v, i64 0, i64 0, i32 0), align 16\n"
+      "  store i32 %conv, i32* getelementptr inbounds "
+      "    ([50 x %0], [50 x %0]* @g, i64 0, i64 0, i32 0), align 16\n"
+      "  ret void\n"
+      "}";
+  SlotMapping Mapping;
+  auto Mod = parseAssemblyString(Source, Error, Ctx, &Mapping);
+  ASSERT_TRUE(Mod != nullptr);
+  auto &M = *Mod;
+  unsigned Read;
+
+  // Check we properly parse integer types.
+  Type *Ty;
+  Ty = parseTypeAtBeginning("i32", Read, Error, M, &Mapping);
+  ASSERT_TRUE(Ty);
+  ASSERT_TRUE(Ty->isIntegerTy());
+  ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32);
+  ASSERT_TRUE(Read == 3);
+
+  // Check we properly parse integer types with exotic size.
+  Ty = parseTypeAtBeginning("i13", Read, Error, M, &Mapping);
+  ASSERT_TRUE(Ty);
+  ASSERT_TRUE(Ty->isIntegerTy());
+  ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 13);
+  ASSERT_TRUE(Read == 3);
+
+  // Check we properly parse floating point types.
+  Ty = parseTypeAtBeginning("float", Read, Error, M, &Mapping);
+  ASSERT_TRUE(Ty);
+  ASSERT_TRUE(Ty->isFloatTy());
+  ASSERT_TRUE(Read == 5);
+
+  Ty = parseTypeAtBeginning("double", Read, Error, M, &Mapping);
+  ASSERT_TRUE(Ty);
+  ASSERT_TRUE(Ty->isDoubleTy());
+  ASSERT_TRUE(Read == 6);
+
+  // Check we properly parse struct types.
+  // Named struct.
+  Ty = parseTypeAtBeginning("%st", Read, Error, M, &Mapping);
+  ASSERT_TRUE(Ty);
+  ASSERT_TRUE(Ty->isStructTy());
+  ASSERT_TRUE(Read == 3);
+
+  // Check the details of the struct.
+  StructType *ST = cast<StructType>(Ty);
+  ASSERT_TRUE(ST->getNumElements() == 2);
+  for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) {
+    Ty = ST->getElementType(i);
+    ASSERT_TRUE(Ty->isIntegerTy());
+    ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32);
+  }
+
+  // Anonymous struct.
+  Ty = parseTypeAtBeginning("%0", Read, Error, M, &Mapping);
+  ASSERT_TRUE(Ty);
+  ASSERT_TRUE(Ty->isStructTy());
+  ASSERT_TRUE(Read == 2);
+
+  // Check the details of the struct.
+  ST = cast<StructType>(Ty);
+  ASSERT_TRUE(ST->getNumElements() == 4);
+  for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) {
+    Ty = ST->getElementType(i);
+    ASSERT_TRUE(Ty->isIntegerTy());
+    ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32);
+  }
+
+  // Check we properly parse vector types.
+  Ty = parseTypeAtBeginning("<5 x i32>", Read, Error, M, &Mapping);
+  ASSERT_TRUE(Ty);
+  ASSERT_TRUE(Ty->isVectorTy());
+  ASSERT_TRUE(Read == 9);
+
+  // Check the details of the vector.
+  VectorType *VT = cast<VectorType>(Ty);
+  ASSERT_TRUE(VT->getNumElements() == 5);
+  ASSERT_TRUE(VT->getBitWidth() == 160);
+  Ty = VT->getElementType();
+  ASSERT_TRUE(Ty->isIntegerTy());
+  ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32);
+
+  // Opaque struct.
+  Ty = parseTypeAtBeginning("%opaque", Read, Error, M, &Mapping);
+  ASSERT_TRUE(Ty);
+  ASSERT_TRUE(Ty->isStructTy());
+  ASSERT_TRUE(Read == 7);
+
+  ST = cast<StructType>(Ty);
+  ASSERT_TRUE(ST->isOpaque());
+
+  // Check we properly parse pointer types.
+  // One indirection.
+  Ty = parseTypeAtBeginning("i32*", Read, Error, M, &Mapping);
+  ASSERT_TRUE(Ty);
+  ASSERT_TRUE(Ty->isPointerTy());
+  ASSERT_TRUE(Read == 4);
+
+  PointerType *PT = cast<PointerType>(Ty);
+  Ty = PT->getElementType();
+  ASSERT_TRUE(Ty->isIntegerTy());
+  ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32);
+
+  // Two indirections.
+  Ty = parseTypeAtBeginning("i32**", Read, Error, M, &Mapping);
+  ASSERT_TRUE(Ty);
+  ASSERT_TRUE(Ty->isPointerTy());
+  ASSERT_TRUE(Read == 5);
+
+  PT = cast<PointerType>(Ty);
+  Ty = PT->getElementType();
+  ASSERT_TRUE(Ty->isPointerTy());
+
+  PT = cast<PointerType>(Ty);
+  Ty = PT->getElementType();
+  ASSERT_TRUE(Ty->isIntegerTy());
+  ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32);
+
+  // Check that we reject types with garbage.
+  Ty = parseTypeAtBeginning("i32 garbage", Read, Error, M, &Mapping);
+  ASSERT_TRUE(Ty);
+  ASSERT_TRUE(Ty->isIntegerTy());
+  ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32);
+  // We go to the next token, i.e., we read "i32" + ' '.
+  ASSERT_TRUE(Read == 4);
 }
 
 } // end anonymous namespace




More information about the llvm-commits mailing list