llvm.org GIT mirror llvm / cbd4dbb
[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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@262884 91177308-0d34-0410-b5e6-96231b3b80d8 Quentin Colombet 4 years ago
5 changed file(s) with 180 addition(s) and 5 deletion(s). Raw diff Collapse all Expand all
9999 Type *parseType(StringRef Asm, SMDiagnostic &Err, const Module &M,
100100 const SlotMapping *Slots = nullptr);
101101
102 /// Parse a string \p Asm that starts with a type.
103 /// \p Read[out] gives the number of characters that have been read to parse
104 /// the type in \p Asm.
105 ///
106 /// \param Slots The optional slot mapping that will restore the parsing state
107 /// of the module.
108 /// \return null on error.
109 Type *parseTypeAtBeginning(StringRef Asm, unsigned &Read, SMDiagnostic &Err,
110 const Module &M, const SlotMapping *Slots = nullptr);
111
102112 } // End llvm namespace
103113
104114 #endif
6262 return false;
6363 }
6464
65 bool LLParser::parseStandaloneType(Type *&Ty, const SlotMapping *Slots) {
65 bool LLParser::parseTypeAtBeginning(Type *&Ty, unsigned &Read,
66 const SlotMapping *Slots) {
6667 restoreParsingState(Slots);
6768 Lex.Lex();
6869
70 Read = 0;
71 SMLoc Start = Lex.getLoc();
6972 Ty = nullptr;
7073 if (ParseType(Ty))
7174 return true;
72 if (Lex.getKind() != lltok::Eof)
73 return Error(Lex.getLoc(), "expected end of string");
75 SMLoc End = Lex.getLoc();
76 Read = End.getPointer() - Start.getPointer();
77
7478 return false;
7579 }
7680
147147
148148 bool parseStandaloneConstantValue(Constant *&C, const SlotMapping *Slots);
149149
150 bool parseStandaloneType(Type *&Ty, const SlotMapping *Slots);
150 bool parseTypeAtBeginning(Type *&Ty, unsigned &Read,
151 const SlotMapping *Slots);
151152
152153 LLVMContext &getContext() { return Context; }
153154
8080
8181 Type *llvm::parseType(StringRef Asm, SMDiagnostic &Err, const Module &M,
8282 const SlotMapping *Slots) {
83 unsigned Read;
84 Type *Ty = parseTypeAtBeginning(Asm, Read, Err, M, Slots);
85 if (!Ty)
86 return nullptr;
87 if (Read != Asm.size()) {
88 SourceMgr SM;
89 std::unique_ptr Buf = MemoryBuffer::getMemBuffer(Asm);
90 SM.AddNewSourceBuffer(std::move(Buf), SMLoc());
91 Err = SM.GetMessage(SMLoc::getFromPointer(Asm.begin() + Read),
92 SourceMgr::DK_Error, "expected end of string");
93 return nullptr;
94 }
95 return Ty;
96 }
97 Type *llvm::parseTypeAtBeginning(StringRef Asm, unsigned &Read,
98 SMDiagnostic &Err, const Module &M,
99 const SlotMapping *Slots) {
83100 SourceMgr SM;
84101 std::unique_ptr Buf = MemoryBuffer::getMemBuffer(Asm);
85102 SM.AddNewSourceBuffer(std::move(Buf), SMLoc());
86103 Type *Ty;
87104 if (LLParser(Asm, SM, Err, const_cast(&M))
88 .parseStandaloneType(Ty, Slots))
105 .parseTypeAtBeginning(Ty, Read, Slots))
89106 return nullptr;
90107 return Ty;
91108 }
269269 Ty = PT->getElementType();
270270 ASSERT_TRUE(Ty->isIntegerTy());
271271 ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32);
272
273 // Check that we reject types with garbage.
274 Ty = parseType("i32 garbage", Error, M, &Mapping);
275 ASSERT_TRUE(!Ty);
276 }
277
278 TEST(AsmParserTest, TypeAtBeginningWithSlotMappingParsing) {
279 LLVMContext &Ctx = getGlobalContext();
280 SMDiagnostic Error;
281 StringRef Source =
282 "%st = type { i32, i32 }\n"
283 "@v = common global [50 x %st] zeroinitializer, align 16\n"
284 "%0 = type { i32, i32, i32, i32 }\n"
285 "@g = common global [50 x %0] zeroinitializer, align 16\n"
286 "define void @marker4(i64 %d) {\n"
287 "entry:\n"
288 " %conv = trunc i64 %d to i32\n"
289 " store i32 %conv, i32* getelementptr inbounds "
290 " ([50 x %st], [50 x %st]* @v, i64 0, i64 0, i32 0), align 16\n"
291 " store i32 %conv, i32* getelementptr inbounds "
292 " ([50 x %0], [50 x %0]* @g, i64 0, i64 0, i32 0), align 16\n"
293 " ret void\n"
294 "}";
295 SlotMapping Mapping;
296 auto Mod = parseAssemblyString(Source, Error, Ctx, &Mapping);
297 ASSERT_TRUE(Mod != nullptr);
298 auto &M = *Mod;
299 unsigned Read;
300
301 // Check we properly parse integer types.
302 Type *Ty;
303 Ty = parseTypeAtBeginning("i32", Read, Error, M, &Mapping);
304 ASSERT_TRUE(Ty);
305 ASSERT_TRUE(Ty->isIntegerTy());
306 ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32);
307 ASSERT_TRUE(Read == 3);
308
309 // Check we properly parse integer types with exotic size.
310 Ty = parseTypeAtBeginning("i13", Read, Error, M, &Mapping);
311 ASSERT_TRUE(Ty);
312 ASSERT_TRUE(Ty->isIntegerTy());
313 ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 13);
314 ASSERT_TRUE(Read == 3);
315
316 // Check we properly parse floating point types.
317 Ty = parseTypeAtBeginning("float", Read, Error, M, &Mapping);
318 ASSERT_TRUE(Ty);
319 ASSERT_TRUE(Ty->isFloatTy());
320 ASSERT_TRUE(Read == 5);
321
322 Ty = parseTypeAtBeginning("double", Read, Error, M, &Mapping);
323 ASSERT_TRUE(Ty);
324 ASSERT_TRUE(Ty->isDoubleTy());
325 ASSERT_TRUE(Read == 6);
326
327 // Check we properly parse struct types.
328 // Named struct.
329 Ty = parseTypeAtBeginning("%st", Read, Error, M, &Mapping);
330 ASSERT_TRUE(Ty);
331 ASSERT_TRUE(Ty->isStructTy());
332 ASSERT_TRUE(Read == 3);
333
334 // Check the details of the struct.
335 StructType *ST = cast(Ty);
336 ASSERT_TRUE(ST->getNumElements() == 2);
337 for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) {
338 Ty = ST->getElementType(i);
339 ASSERT_TRUE(Ty->isIntegerTy());
340 ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32);
341 }
342
343 // Anonymous struct.
344 Ty = parseTypeAtBeginning("%0", Read, Error, M, &Mapping);
345 ASSERT_TRUE(Ty);
346 ASSERT_TRUE(Ty->isStructTy());
347 ASSERT_TRUE(Read == 2);
348
349 // Check the details of the struct.
350 ST = cast(Ty);
351 ASSERT_TRUE(ST->getNumElements() == 4);
352 for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) {
353 Ty = ST->getElementType(i);
354 ASSERT_TRUE(Ty->isIntegerTy());
355 ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32);
356 }
357
358 // Check we properly parse vector types.
359 Ty = parseTypeAtBeginning("<5 x i32>", Read, Error, M, &Mapping);
360 ASSERT_TRUE(Ty);
361 ASSERT_TRUE(Ty->isVectorTy());
362 ASSERT_TRUE(Read == 9);
363
364 // Check the details of the vector.
365 VectorType *VT = cast(Ty);
366 ASSERT_TRUE(VT->getNumElements() == 5);
367 ASSERT_TRUE(VT->getBitWidth() == 160);
368 Ty = VT->getElementType();
369 ASSERT_TRUE(Ty->isIntegerTy());
370 ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32);
371
372 // Opaque struct.
373 Ty = parseTypeAtBeginning("%opaque", Read, Error, M, &Mapping);
374 ASSERT_TRUE(Ty);
375 ASSERT_TRUE(Ty->isStructTy());
376 ASSERT_TRUE(Read == 7);
377
378 ST = cast(Ty);
379 ASSERT_TRUE(ST->isOpaque());
380
381 // Check we properly parse pointer types.
382 // One indirection.
383 Ty = parseTypeAtBeginning("i32*", Read, Error, M, &Mapping);
384 ASSERT_TRUE(Ty);
385 ASSERT_TRUE(Ty->isPointerTy());
386 ASSERT_TRUE(Read == 4);
387
388 PointerType *PT = cast(Ty);
389 Ty = PT->getElementType();
390 ASSERT_TRUE(Ty->isIntegerTy());
391 ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32);
392
393 // Two indirections.
394 Ty = parseTypeAtBeginning("i32**", Read, Error, M, &Mapping);
395 ASSERT_TRUE(Ty);
396 ASSERT_TRUE(Ty->isPointerTy());
397 ASSERT_TRUE(Read == 5);
398
399 PT = cast(Ty);
400 Ty = PT->getElementType();
401 ASSERT_TRUE(Ty->isPointerTy());
402
403 PT = cast(Ty);
404 Ty = PT->getElementType();
405 ASSERT_TRUE(Ty->isIntegerTy());
406 ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32);
407
408 // Check that we reject types with garbage.
409 Ty = parseTypeAtBeginning("i32 garbage", Read, Error, M, &Mapping);
410 ASSERT_TRUE(Ty);
411 ASSERT_TRUE(Ty->isIntegerTy());
412 ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32);
413 // We go to the next token, i.e., we read "i32" + ' '.
414 ASSERT_TRUE(Read == 4);
272415 }
273416
274417 } // end anonymous namespace