1 //===- llvm/unittest/AsmParser/AsmParserTest.cpp - asm parser unittests ---===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/ADT/StringRef.h" 10 #include "llvm/AsmParser/Parser.h" 11 #include "llvm/AsmParser/SlotMapping.h" 12 #include "llvm/IR/Constants.h" 13 #include "llvm/IR/LLVMContext.h" 14 #include "llvm/IR/Module.h" 15 #include "llvm/Support/SourceMgr.h" 16 #include "gtest/gtest.h" 17 18 using namespace llvm; 19 20 namespace { 21 22 TEST(AsmParserTest, NullTerminatedInput) { 23 LLVMContext Ctx; 24 StringRef Source = "; Empty module \n"; 25 SMDiagnostic Error; 26 auto Mod = parseAssemblyString(Source, Error, Ctx); 27 28 EXPECT_TRUE(Mod != nullptr); 29 EXPECT_TRUE(Error.getMessage().empty()); 30 } 31 32 #ifdef GTEST_HAS_DEATH_TEST 33 #ifndef NDEBUG 34 35 TEST(AsmParserTest, NonNullTerminatedInput) { 36 LLVMContext Ctx; 37 StringRef Source = "; Empty module \n\1\2"; 38 SMDiagnostic Error; 39 std::unique_ptr<Module> Mod; 40 EXPECT_DEATH(Mod = parseAssemblyString(Source.substr(0, Source.size() - 2), 41 Error, Ctx), 42 "Buffer is not null terminated!"); 43 } 44 45 #endif 46 #endif 47 48 TEST(AsmParserTest, SlotMappingTest) { 49 LLVMContext Ctx; 50 StringRef Source = "@0 = global i32 0\n !0 = !{}\n !42 = !{i32 42}"; 51 SMDiagnostic Error; 52 SlotMapping Mapping; 53 auto Mod = parseAssemblyString(Source, Error, Ctx, &Mapping); 54 55 EXPECT_TRUE(Mod != nullptr); 56 EXPECT_TRUE(Error.getMessage().empty()); 57 58 ASSERT_EQ(Mapping.GlobalValues.size(), 1u); 59 EXPECT_TRUE(isa<GlobalVariable>(Mapping.GlobalValues[0])); 60 61 EXPECT_EQ(Mapping.MetadataNodes.size(), 2u); 62 EXPECT_EQ(Mapping.MetadataNodes.count(0), 1u); 63 EXPECT_EQ(Mapping.MetadataNodes.count(42), 1u); 64 EXPECT_EQ(Mapping.MetadataNodes.count(1), 0u); 65 } 66 67 TEST(AsmParserTest, TypeAndConstantValueParsing) { 68 LLVMContext Ctx; 69 SMDiagnostic Error; 70 StringRef Source = "define void @test() {\n entry:\n ret void\n}"; 71 auto Mod = parseAssemblyString(Source, Error, Ctx); 72 ASSERT_TRUE(Mod != nullptr); 73 auto &M = *Mod; 74 75 const Value *V; 76 V = parseConstantValue("double 3.5", Error, M); 77 ASSERT_TRUE(V); 78 EXPECT_TRUE(V->getType()->isDoubleTy()); 79 ASSERT_TRUE(isa<ConstantFP>(V)); 80 EXPECT_TRUE(cast<ConstantFP>(V)->isExactlyValue(3.5)); 81 82 V = parseConstantValue("i32 42", Error, M); 83 ASSERT_TRUE(V); 84 EXPECT_TRUE(V->getType()->isIntegerTy()); 85 ASSERT_TRUE(isa<ConstantInt>(V)); 86 EXPECT_TRUE(cast<ConstantInt>(V)->equalsInt(42)); 87 88 V = parseConstantValue("<4 x i32> <i32 0, i32 1, i32 2, i32 3>", Error, M); 89 ASSERT_TRUE(V); 90 EXPECT_TRUE(V->getType()->isVectorTy()); 91 ASSERT_TRUE(isa<ConstantDataVector>(V)); 92 93 V = parseConstantValue("i32 add (i32 1, i32 2)", Error, M); 94 ASSERT_TRUE(V); 95 ASSERT_TRUE(isa<ConstantInt>(V)); 96 97 V = parseConstantValue("i8* blockaddress(@test, %entry)", Error, M); 98 ASSERT_TRUE(V); 99 ASSERT_TRUE(isa<BlockAddress>(V)); 100 101 V = parseConstantValue("i8** undef", Error, M); 102 ASSERT_TRUE(V); 103 ASSERT_TRUE(isa<UndefValue>(V)); 104 105 EXPECT_FALSE(parseConstantValue("duble 3.25", Error, M)); 106 EXPECT_EQ(Error.getMessage(), "expected type"); 107 108 EXPECT_FALSE(parseConstantValue("i32 3.25", Error, M)); 109 EXPECT_EQ(Error.getMessage(), "floating point constant invalid for type"); 110 111 EXPECT_FALSE(parseConstantValue("i32* @foo", Error, M)); 112 EXPECT_EQ(Error.getMessage(), "expected a constant value"); 113 114 EXPECT_FALSE(parseConstantValue("i32 3, ", Error, M)); 115 EXPECT_EQ(Error.getMessage(), "expected end of string"); 116 } 117 118 TEST(AsmParserTest, TypeAndConstantValueWithSlotMappingParsing) { 119 LLVMContext Ctx; 120 SMDiagnostic Error; 121 StringRef Source = 122 "%st = type { i32, i32 }\n" 123 "@v = common global [50 x %st] zeroinitializer, align 16\n" 124 "%0 = type { i32, i32, i32, i32 }\n" 125 "@g = common global [50 x %0] zeroinitializer, align 16\n" 126 "define void @marker4(i64 %d) {\n" 127 "entry:\n" 128 " %conv = trunc i64 %d to i32\n" 129 " store i32 %conv, i32* getelementptr inbounds " 130 " ([50 x %st], [50 x %st]* @v, i64 0, i64 0, i32 0), align 16\n" 131 " store i32 %conv, i32* getelementptr inbounds " 132 " ([50 x %0], [50 x %0]* @g, i64 0, i64 0, i32 0), align 16\n" 133 " ret void\n" 134 "}"; 135 SlotMapping Mapping; 136 auto Mod = parseAssemblyString(Source, Error, Ctx, &Mapping); 137 ASSERT_TRUE(Mod != nullptr); 138 auto &M = *Mod; 139 140 const Value *V; 141 V = parseConstantValue("i32* getelementptr inbounds ([50 x %st], [50 x %st]* " 142 "@v, i64 0, i64 0, i32 0)", 143 Error, M, &Mapping); 144 ASSERT_TRUE(V); 145 ASSERT_TRUE(isa<ConstantExpr>(V)); 146 147 V = parseConstantValue("i32* getelementptr inbounds ([50 x %0], [50 x %0]* " 148 "@g, i64 0, i64 0, i32 0)", 149 Error, M, &Mapping); 150 ASSERT_TRUE(V); 151 ASSERT_TRUE(isa<ConstantExpr>(V)); 152 } 153 154 TEST(AsmParserTest, TypeWithSlotMappingParsing) { 155 LLVMContext Ctx; 156 SMDiagnostic Error; 157 StringRef Source = 158 "%st = type { i32, i32 }\n" 159 "@v = common global [50 x %st] zeroinitializer, align 16\n" 160 "%0 = type { i32, i32, i32, i32 }\n" 161 "@g = common global [50 x %0] zeroinitializer, align 16\n" 162 "define void @marker4(i64 %d) {\n" 163 "entry:\n" 164 " %conv = trunc i64 %d to i32\n" 165 " store i32 %conv, i32* getelementptr inbounds " 166 " ([50 x %st], [50 x %st]* @v, i64 0, i64 0, i32 0), align 16\n" 167 " store i32 %conv, i32* getelementptr inbounds " 168 " ([50 x %0], [50 x %0]* @g, i64 0, i64 0, i32 0), align 16\n" 169 " ret void\n" 170 "}"; 171 SlotMapping Mapping; 172 auto Mod = parseAssemblyString(Source, Error, Ctx, &Mapping); 173 ASSERT_TRUE(Mod != nullptr); 174 auto &M = *Mod; 175 176 // Check we properly parse integer types. 177 Type *Ty; 178 Ty = parseType("i32", Error, M, &Mapping); 179 ASSERT_TRUE(Ty); 180 ASSERT_TRUE(Ty->isIntegerTy()); 181 ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32); 182 183 // Check we properly parse integer types with exotic size. 184 Ty = parseType("i13", Error, M, &Mapping); 185 ASSERT_TRUE(Ty); 186 ASSERT_TRUE(Ty->isIntegerTy()); 187 ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 13); 188 189 // Check we properly parse floating point types. 190 Ty = parseType("float", Error, M, &Mapping); 191 ASSERT_TRUE(Ty); 192 ASSERT_TRUE(Ty->isFloatTy()); 193 194 Ty = parseType("double", Error, M, &Mapping); 195 ASSERT_TRUE(Ty); 196 ASSERT_TRUE(Ty->isDoubleTy()); 197 198 // Check we properly parse struct types. 199 // Named struct. 200 Ty = parseType("%st", Error, M, &Mapping); 201 ASSERT_TRUE(Ty); 202 ASSERT_TRUE(Ty->isStructTy()); 203 204 // Check the details of the struct. 205 StructType *ST = cast<StructType>(Ty); 206 ASSERT_TRUE(ST->getNumElements() == 2); 207 for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) { 208 Ty = ST->getElementType(i); 209 ASSERT_TRUE(Ty->isIntegerTy()); 210 ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32); 211 } 212 213 // Anonymous struct. 214 Ty = parseType("%0", Error, M, &Mapping); 215 ASSERT_TRUE(Ty); 216 ASSERT_TRUE(Ty->isStructTy()); 217 218 // Check the details of the struct. 219 ST = cast<StructType>(Ty); 220 ASSERT_TRUE(ST->getNumElements() == 4); 221 for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) { 222 Ty = ST->getElementType(i); 223 ASSERT_TRUE(Ty->isIntegerTy()); 224 ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32); 225 } 226 227 // Check we properly parse vector types. 228 Ty = parseType("<5 x i32>", Error, M, &Mapping); 229 ASSERT_TRUE(Ty); 230 ASSERT_TRUE(Ty->isVectorTy()); 231 232 // Check the details of the vector. 233 VectorType *VT = cast<VectorType>(Ty); 234 ASSERT_TRUE(VT->getNumElements() == 5); 235 ASSERT_TRUE(VT->getBitWidth() == 160); 236 Ty = VT->getElementType(); 237 ASSERT_TRUE(Ty->isIntegerTy()); 238 ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32); 239 240 // Opaque struct. 241 Ty = parseType("%opaque", Error, M, &Mapping); 242 ASSERT_TRUE(Ty); 243 ASSERT_TRUE(Ty->isStructTy()); 244 245 ST = cast<StructType>(Ty); 246 ASSERT_TRUE(ST->isOpaque()); 247 248 // Check we properly parse pointer types. 249 // One indirection. 250 Ty = parseType("i32*", Error, M, &Mapping); 251 ASSERT_TRUE(Ty); 252 ASSERT_TRUE(Ty->isPointerTy()); 253 254 PointerType *PT = cast<PointerType>(Ty); 255 Ty = PT->getElementType(); 256 ASSERT_TRUE(Ty->isIntegerTy()); 257 ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32); 258 259 // Two indirections. 260 Ty = parseType("i32**", Error, M, &Mapping); 261 ASSERT_TRUE(Ty); 262 ASSERT_TRUE(Ty->isPointerTy()); 263 264 PT = cast<PointerType>(Ty); 265 Ty = PT->getElementType(); 266 ASSERT_TRUE(Ty->isPointerTy()); 267 268 PT = cast<PointerType>(Ty); 269 Ty = PT->getElementType(); 270 ASSERT_TRUE(Ty->isIntegerTy()); 271 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; 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<StructType>(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<StructType>(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<VectorType>(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<StructType>(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<PointerType>(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<PointerType>(Ty); 400 Ty = PT->getElementType(); 401 ASSERT_TRUE(Ty->isPointerTy()); 402 403 PT = cast<PointerType>(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); 415 } 416 417 } // end anonymous namespace 418