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 auto *VT = cast<FixedVectorType>(Ty); 234 ASSERT_TRUE(VT->getNumElements() == 5); 235 ASSERT_TRUE(VT->getPrimitiveSizeInBits().getFixedSize() == 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 ASSERT_TRUE(PT->isOpaqueOrPointeeTypeMatches(Type::getIntNTy(Ctx, 32))); 256 257 // Two indirections. 258 Ty = parseType("i32**", Error, M, &Mapping); 259 ASSERT_TRUE(Ty); 260 ASSERT_TRUE(Ty->isPointerTy()); 261 262 PT = cast<PointerType>(Ty); 263 Type *ExpectedElemTy = PointerType::getUnqual(Type::getIntNTy(Ctx, 32)); 264 ASSERT_TRUE(PT->isOpaqueOrPointeeTypeMatches(ExpectedElemTy)); 265 266 // Check that we reject types with garbage. 267 Ty = parseType("i32 garbage", Error, M, &Mapping); 268 ASSERT_TRUE(!Ty); 269 } 270 271 TEST(AsmParserTest, TypeAtBeginningWithSlotMappingParsing) { 272 LLVMContext Ctx; 273 SMDiagnostic Error; 274 StringRef Source = 275 "%st = type { i32, i32 }\n" 276 "@v = common global [50 x %st] zeroinitializer, align 16\n" 277 "%0 = type { i32, i32, i32, i32 }\n" 278 "@g = common global [50 x %0] zeroinitializer, align 16\n" 279 "define void @marker4(i64 %d) {\n" 280 "entry:\n" 281 " %conv = trunc i64 %d to i32\n" 282 " store i32 %conv, i32* getelementptr inbounds " 283 " ([50 x %st], [50 x %st]* @v, i64 0, i64 0, i32 0), align 16\n" 284 " store i32 %conv, i32* getelementptr inbounds " 285 " ([50 x %0], [50 x %0]* @g, i64 0, i64 0, i32 0), align 16\n" 286 " ret void\n" 287 "}"; 288 SlotMapping Mapping; 289 auto Mod = parseAssemblyString(Source, Error, Ctx, &Mapping); 290 ASSERT_TRUE(Mod != nullptr); 291 auto &M = *Mod; 292 unsigned Read; 293 294 // Check we properly parse integer types. 295 Type *Ty; 296 Ty = parseTypeAtBeginning("i32", Read, Error, M, &Mapping); 297 ASSERT_TRUE(Ty); 298 ASSERT_TRUE(Ty->isIntegerTy()); 299 ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32); 300 ASSERT_TRUE(Read == 3); 301 302 // Check we properly parse integer types with exotic size. 303 Ty = parseTypeAtBeginning("i13", Read, Error, M, &Mapping); 304 ASSERT_TRUE(Ty); 305 ASSERT_TRUE(Ty->isIntegerTy()); 306 ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 13); 307 ASSERT_TRUE(Read == 3); 308 309 // Check we properly parse floating point types. 310 Ty = parseTypeAtBeginning("float", Read, Error, M, &Mapping); 311 ASSERT_TRUE(Ty); 312 ASSERT_TRUE(Ty->isFloatTy()); 313 ASSERT_TRUE(Read == 5); 314 315 Ty = parseTypeAtBeginning("double", Read, Error, M, &Mapping); 316 ASSERT_TRUE(Ty); 317 ASSERT_TRUE(Ty->isDoubleTy()); 318 ASSERT_TRUE(Read == 6); 319 320 // Check we properly parse struct types. 321 // Named struct. 322 Ty = parseTypeAtBeginning("%st", Read, Error, M, &Mapping); 323 ASSERT_TRUE(Ty); 324 ASSERT_TRUE(Ty->isStructTy()); 325 ASSERT_TRUE(Read == 3); 326 327 // Check the details of the struct. 328 StructType *ST = cast<StructType>(Ty); 329 ASSERT_TRUE(ST->getNumElements() == 2); 330 for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) { 331 Ty = ST->getElementType(i); 332 ASSERT_TRUE(Ty->isIntegerTy()); 333 ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32); 334 } 335 336 // Anonymous struct. 337 Ty = parseTypeAtBeginning("%0", Read, Error, M, &Mapping); 338 ASSERT_TRUE(Ty); 339 ASSERT_TRUE(Ty->isStructTy()); 340 ASSERT_TRUE(Read == 2); 341 342 // Check the details of the struct. 343 ST = cast<StructType>(Ty); 344 ASSERT_TRUE(ST->getNumElements() == 4); 345 for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) { 346 Ty = ST->getElementType(i); 347 ASSERT_TRUE(Ty->isIntegerTy()); 348 ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32); 349 } 350 351 // Check we properly parse vector types. 352 Ty = parseTypeAtBeginning("<5 x i32>", Read, Error, M, &Mapping); 353 ASSERT_TRUE(Ty); 354 ASSERT_TRUE(Ty->isVectorTy()); 355 ASSERT_TRUE(Read == 9); 356 357 // Check the details of the vector. 358 auto *VT = cast<FixedVectorType>(Ty); 359 ASSERT_TRUE(VT->getNumElements() == 5); 360 ASSERT_TRUE(VT->getPrimitiveSizeInBits().getFixedSize() == 160); 361 Ty = VT->getElementType(); 362 ASSERT_TRUE(Ty->isIntegerTy()); 363 ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32); 364 365 // Opaque struct. 366 Ty = parseTypeAtBeginning("%opaque", Read, Error, M, &Mapping); 367 ASSERT_TRUE(Ty); 368 ASSERT_TRUE(Ty->isStructTy()); 369 ASSERT_TRUE(Read == 7); 370 371 ST = cast<StructType>(Ty); 372 ASSERT_TRUE(ST->isOpaque()); 373 374 // Check we properly parse pointer types. 375 // One indirection. 376 Ty = parseTypeAtBeginning("i32*", Read, Error, M, &Mapping); 377 ASSERT_TRUE(Ty); 378 ASSERT_TRUE(Ty->isPointerTy()); 379 ASSERT_TRUE(Read == 4); 380 381 PointerType *PT = cast<PointerType>(Ty); 382 ASSERT_TRUE(PT->isOpaqueOrPointeeTypeMatches(Type::getIntNTy(Ctx, 32))); 383 384 // Two indirections. 385 Ty = parseTypeAtBeginning("i32**", Read, Error, M, &Mapping); 386 ASSERT_TRUE(Ty); 387 ASSERT_TRUE(Ty->isPointerTy()); 388 ASSERT_TRUE(Read == 5); 389 390 PT = cast<PointerType>(Ty); 391 Type *ExpectedElemTy = PointerType::getUnqual(Type::getIntNTy(Ctx, 32)); 392 ASSERT_TRUE(PT->isOpaqueOrPointeeTypeMatches(ExpectedElemTy)); 393 394 // Check that we reject types with garbage. 395 Ty = parseTypeAtBeginning("i32 garbage", Read, Error, M, &Mapping); 396 ASSERT_TRUE(Ty); 397 ASSERT_TRUE(Ty->isIntegerTy()); 398 ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32); 399 // We go to the next token, i.e., we read "i32" + ' '. 400 ASSERT_TRUE(Read == 4); 401 } 402 403 } // end anonymous namespace 404