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/DataLayout.h" 14 #include "llvm/IR/DebugInfoMetadata.h" 15 #include "llvm/IR/LLVMContext.h" 16 #include "llvm/IR/Module.h" 17 #include "llvm/Support/Error.h" 18 #include "llvm/Support/SourceMgr.h" 19 #include "gtest/gtest.h" 20 21 using namespace llvm; 22 23 namespace { 24 25 TEST(AsmParserTest, NullTerminatedInput) { 26 LLVMContext Ctx; 27 StringRef Source = "; Empty module \n"; 28 SMDiagnostic Error; 29 auto Mod = parseAssemblyString(Source, Error, Ctx); 30 31 EXPECT_TRUE(Mod != nullptr); 32 EXPECT_TRUE(Error.getMessage().empty()); 33 } 34 35 #ifdef GTEST_HAS_DEATH_TEST 36 #ifndef NDEBUG 37 38 TEST(AsmParserTest, NonNullTerminatedInput) { 39 LLVMContext Ctx; 40 StringRef Source = "; Empty module \n\1\2"; 41 SMDiagnostic Error; 42 std::unique_ptr<Module> Mod; 43 EXPECT_DEATH(Mod = parseAssemblyString(Source.substr(0, Source.size() - 2), 44 Error, Ctx), 45 "Buffer is not null terminated!"); 46 } 47 48 #endif 49 #endif 50 51 TEST(AsmParserTest, SlotMappingTest) { 52 LLVMContext Ctx; 53 StringRef Source = "@0 = global i32 0\n !0 = !{}\n !42 = !{i32 42}"; 54 SMDiagnostic Error; 55 SlotMapping Mapping; 56 auto Mod = parseAssemblyString(Source, Error, Ctx, &Mapping); 57 58 EXPECT_TRUE(Mod != nullptr); 59 EXPECT_TRUE(Error.getMessage().empty()); 60 61 ASSERT_EQ(Mapping.GlobalValues.getNext(), 1u); 62 EXPECT_TRUE(isa<GlobalVariable>(Mapping.GlobalValues.get(0))); 63 64 EXPECT_EQ(Mapping.MetadataNodes.size(), 2u); 65 EXPECT_EQ(Mapping.MetadataNodes.count(0), 1u); 66 EXPECT_EQ(Mapping.MetadataNodes.count(42), 1u); 67 EXPECT_EQ(Mapping.MetadataNodes.count(1), 0u); 68 } 69 70 TEST(AsmParserTest, TypeAndConstantValueParsing) { 71 LLVMContext Ctx; 72 SMDiagnostic Error; 73 StringRef Source = "define void @test() {\n entry:\n ret void\n}"; 74 auto Mod = parseAssemblyString(Source, Error, Ctx); 75 ASSERT_TRUE(Mod != nullptr); 76 auto &M = *Mod; 77 78 const Value *V; 79 V = parseConstantValue("double 3.5", Error, M); 80 ASSERT_TRUE(V); 81 EXPECT_TRUE(V->getType()->isDoubleTy()); 82 ASSERT_TRUE(isa<ConstantFP>(V)); 83 EXPECT_TRUE(cast<ConstantFP>(V)->isExactlyValue(3.5)); 84 85 V = parseConstantValue("i32 42", Error, M); 86 ASSERT_TRUE(V); 87 EXPECT_TRUE(V->getType()->isIntegerTy()); 88 ASSERT_TRUE(isa<ConstantInt>(V)); 89 EXPECT_TRUE(cast<ConstantInt>(V)->equalsInt(42)); 90 91 V = parseConstantValue("<4 x i32> <i32 0, i32 1, i32 2, i32 3>", Error, M); 92 ASSERT_TRUE(V); 93 EXPECT_TRUE(V->getType()->isVectorTy()); 94 ASSERT_TRUE(isa<ConstantDataVector>(V)); 95 96 V = parseConstantValue("i32 add (i32 1, i32 2)", Error, M); 97 ASSERT_TRUE(V); 98 ASSERT_TRUE(isa<ConstantInt>(V)); 99 100 V = parseConstantValue("ptr blockaddress(@test, %entry)", Error, M); 101 ASSERT_TRUE(V); 102 ASSERT_TRUE(isa<BlockAddress>(V)); 103 104 V = parseConstantValue("ptr undef", Error, M); 105 ASSERT_TRUE(V); 106 ASSERT_TRUE(isa<UndefValue>(V)); 107 108 EXPECT_FALSE(parseConstantValue("duble 3.25", Error, M)); 109 EXPECT_EQ(Error.getMessage(), "expected type"); 110 111 EXPECT_FALSE(parseConstantValue("i32 3.25", Error, M)); 112 EXPECT_EQ(Error.getMessage(), "floating point constant invalid for type"); 113 114 EXPECT_FALSE(parseConstantValue("ptr @foo", Error, M)); 115 EXPECT_EQ(Error.getMessage(), "expected a constant value"); 116 117 EXPECT_FALSE(parseConstantValue("i32 3, ", Error, M)); 118 EXPECT_EQ(Error.getMessage(), "expected end of string"); 119 } 120 121 TEST(AsmParserTest, TypeAndConstantValueWithSlotMappingParsing) { 122 LLVMContext Ctx; 123 SMDiagnostic Error; 124 StringRef Source = 125 "%st = type { i32, i32 }\n" 126 "@v = common global [50 x %st] zeroinitializer, align 16\n" 127 "%0 = type { i32, i32, i32, i32 }\n" 128 "@g = common global [50 x %0] zeroinitializer, align 16\n" 129 "define void @marker4(i64 %d) {\n" 130 "entry:\n" 131 " %conv = trunc i64 %d to i32\n" 132 " store i32 %conv, ptr getelementptr inbounds " 133 " ([50 x %st], ptr @v, i64 0, i64 1, i32 0), align 16\n" 134 " store i32 %conv, ptr getelementptr inbounds " 135 " ([50 x %0], ptr @g, i64 0, i64 1, i32 0), align 16\n" 136 " ret void\n" 137 "}"; 138 SlotMapping Mapping; 139 auto Mod = parseAssemblyString(Source, Error, Ctx, &Mapping); 140 ASSERT_TRUE(Mod != nullptr); 141 auto &M = *Mod; 142 143 const Value *V; 144 V = parseConstantValue("ptr getelementptr inbounds ([50 x %st], ptr " 145 "@v, i64 0, i64 1, i32 0)", 146 Error, M, &Mapping); 147 ASSERT_TRUE(V); 148 ASSERT_TRUE(isa<ConstantExpr>(V)); 149 150 V = parseConstantValue("ptr getelementptr inbounds ([50 x %0], ptr " 151 "@g, i64 0, i64 1, i32 0)", 152 Error, M, &Mapping); 153 ASSERT_TRUE(V); 154 ASSERT_TRUE(isa<ConstantExpr>(V)); 155 } 156 157 TEST(AsmParserTest, TypeWithSlotMappingParsing) { 158 LLVMContext Ctx; 159 SMDiagnostic Error; 160 StringRef Source = 161 "%st = type { i32, i32 }\n" 162 "@v = common global [50 x %st] zeroinitializer, align 16\n" 163 "%0 = type { i32, i32, i32, i32 }\n" 164 "@g = common global [50 x %0] zeroinitializer, align 16\n" 165 "define void @marker4(i64 %d) {\n" 166 "entry:\n" 167 " %conv = trunc i64 %d to i32\n" 168 " store i32 %conv, ptr getelementptr inbounds " 169 " ([50 x %st], ptr @v, i64 0, i64 0, i32 0), align 16\n" 170 " store i32 %conv, ptr getelementptr inbounds " 171 " ([50 x %0], ptr @g, i64 0, i64 0, i32 0), align 16\n" 172 " ret void\n" 173 "}"; 174 SlotMapping Mapping; 175 auto Mod = parseAssemblyString(Source, Error, Ctx, &Mapping); 176 ASSERT_TRUE(Mod != nullptr); 177 auto &M = *Mod; 178 179 // Check we properly parse integer types. 180 Type *Ty; 181 Ty = parseType("i32", Error, M, &Mapping); 182 ASSERT_TRUE(Ty); 183 ASSERT_TRUE(Ty->isIntegerTy()); 184 ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32); 185 186 // Check we properly parse integer types with exotic size. 187 Ty = parseType("i13", Error, M, &Mapping); 188 ASSERT_TRUE(Ty); 189 ASSERT_TRUE(Ty->isIntegerTy()); 190 ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 13); 191 192 // Check we properly parse floating point types. 193 Ty = parseType("float", Error, M, &Mapping); 194 ASSERT_TRUE(Ty); 195 ASSERT_TRUE(Ty->isFloatTy()); 196 197 Ty = parseType("double", Error, M, &Mapping); 198 ASSERT_TRUE(Ty); 199 ASSERT_TRUE(Ty->isDoubleTy()); 200 201 // Check we properly parse struct types. 202 // Named struct. 203 Ty = parseType("%st", Error, M, &Mapping); 204 ASSERT_TRUE(Ty); 205 ASSERT_TRUE(Ty->isStructTy()); 206 207 // Check the details of the struct. 208 StructType *ST = cast<StructType>(Ty); 209 ASSERT_TRUE(ST->getNumElements() == 2); 210 for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) { 211 Ty = ST->getElementType(i); 212 ASSERT_TRUE(Ty->isIntegerTy()); 213 ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32); 214 } 215 216 // Anonymous struct. 217 Ty = parseType("%0", Error, M, &Mapping); 218 ASSERT_TRUE(Ty); 219 ASSERT_TRUE(Ty->isStructTy()); 220 221 // Check the details of the struct. 222 ST = cast<StructType>(Ty); 223 ASSERT_TRUE(ST->getNumElements() == 4); 224 for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) { 225 Ty = ST->getElementType(i); 226 ASSERT_TRUE(Ty->isIntegerTy()); 227 ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32); 228 } 229 230 // Check we properly parse vector types. 231 Ty = parseType("<5 x i32>", Error, M, &Mapping); 232 ASSERT_TRUE(Ty); 233 ASSERT_TRUE(Ty->isVectorTy()); 234 235 // Check the details of the vector. 236 auto *VT = cast<FixedVectorType>(Ty); 237 ASSERT_TRUE(VT->getNumElements() == 5); 238 ASSERT_TRUE(VT->getPrimitiveSizeInBits().getFixedValue() == 160); 239 Ty = VT->getElementType(); 240 ASSERT_TRUE(Ty->isIntegerTy()); 241 ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32); 242 243 // Opaque struct. 244 Ty = parseType("%opaque", Error, M, &Mapping); 245 ASSERT_TRUE(Ty); 246 ASSERT_TRUE(Ty->isStructTy()); 247 248 ST = cast<StructType>(Ty); 249 ASSERT_TRUE(ST->isOpaque()); 250 251 // Check we properly parse pointer types. 252 Ty = parseType("ptr", Error, M, &Mapping); 253 ASSERT_TRUE(Ty); 254 ASSERT_TRUE(Ty->isPointerTy()); 255 256 // Check that we reject types with garbage. 257 Ty = parseType("i32 garbage", Error, M, &Mapping); 258 ASSERT_TRUE(!Ty); 259 } 260 261 TEST(AsmParserTest, TypeAtBeginningWithSlotMappingParsing) { 262 LLVMContext Ctx; 263 SMDiagnostic Error; 264 StringRef Source = 265 "%st = type { i32, i32 }\n" 266 "@v = common global [50 x %st] zeroinitializer, align 16\n" 267 "%0 = type { i32, i32, i32, i32 }\n" 268 "@g = common global [50 x %0] zeroinitializer, align 16\n" 269 "define void @marker4(i64 %d) {\n" 270 "entry:\n" 271 " %conv = trunc i64 %d to i32\n" 272 " store i32 %conv, ptr getelementptr inbounds " 273 " ([50 x %st], ptr @v, i64 0, i64 0, i32 0), align 16\n" 274 " store i32 %conv, ptr getelementptr inbounds " 275 " ([50 x %0], ptr @g, i64 0, i64 0, i32 0), align 16\n" 276 " ret void\n" 277 "}"; 278 SlotMapping Mapping; 279 auto Mod = parseAssemblyString(Source, Error, Ctx, &Mapping); 280 ASSERT_TRUE(Mod != nullptr); 281 auto &M = *Mod; 282 unsigned Read; 283 284 // Check we properly parse integer types. 285 Type *Ty; 286 Ty = parseTypeAtBeginning("i32", Read, Error, M, &Mapping); 287 ASSERT_TRUE(Ty); 288 ASSERT_TRUE(Ty->isIntegerTy()); 289 ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32); 290 ASSERT_TRUE(Read == 3); 291 292 // Check we properly parse integer types with exotic size. 293 Ty = parseTypeAtBeginning("i13", Read, Error, M, &Mapping); 294 ASSERT_TRUE(Ty); 295 ASSERT_TRUE(Ty->isIntegerTy()); 296 ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 13); 297 ASSERT_TRUE(Read == 3); 298 299 // Check we properly parse floating point types. 300 Ty = parseTypeAtBeginning("float", Read, Error, M, &Mapping); 301 ASSERT_TRUE(Ty); 302 ASSERT_TRUE(Ty->isFloatTy()); 303 ASSERT_TRUE(Read == 5); 304 305 Ty = parseTypeAtBeginning("double", Read, Error, M, &Mapping); 306 ASSERT_TRUE(Ty); 307 ASSERT_TRUE(Ty->isDoubleTy()); 308 ASSERT_TRUE(Read == 6); 309 310 // Check we properly parse struct types. 311 // Named struct. 312 Ty = parseTypeAtBeginning("%st", Read, Error, M, &Mapping); 313 ASSERT_TRUE(Ty); 314 ASSERT_TRUE(Ty->isStructTy()); 315 ASSERT_TRUE(Read == 3); 316 317 // Check the details of the struct. 318 StructType *ST = cast<StructType>(Ty); 319 ASSERT_TRUE(ST->getNumElements() == 2); 320 for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) { 321 Ty = ST->getElementType(i); 322 ASSERT_TRUE(Ty->isIntegerTy()); 323 ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32); 324 } 325 326 // Anonymous struct. 327 Ty = parseTypeAtBeginning("%0", Read, Error, M, &Mapping); 328 ASSERT_TRUE(Ty); 329 ASSERT_TRUE(Ty->isStructTy()); 330 ASSERT_TRUE(Read == 2); 331 332 // Check the details of the struct. 333 ST = cast<StructType>(Ty); 334 ASSERT_TRUE(ST->getNumElements() == 4); 335 for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) { 336 Ty = ST->getElementType(i); 337 ASSERT_TRUE(Ty->isIntegerTy()); 338 ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32); 339 } 340 341 // Check we properly parse vector types. 342 Ty = parseTypeAtBeginning("<5 x i32>", Read, Error, M, &Mapping); 343 ASSERT_TRUE(Ty); 344 ASSERT_TRUE(Ty->isVectorTy()); 345 ASSERT_TRUE(Read == 9); 346 347 // Check the details of the vector. 348 auto *VT = cast<FixedVectorType>(Ty); 349 ASSERT_TRUE(VT->getNumElements() == 5); 350 ASSERT_TRUE(VT->getPrimitiveSizeInBits().getFixedValue() == 160); 351 Ty = VT->getElementType(); 352 ASSERT_TRUE(Ty->isIntegerTy()); 353 ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32); 354 355 // Opaque struct. 356 Ty = parseTypeAtBeginning("%opaque", Read, Error, M, &Mapping); 357 ASSERT_TRUE(Ty); 358 ASSERT_TRUE(Ty->isStructTy()); 359 ASSERT_TRUE(Read == 7); 360 361 ST = cast<StructType>(Ty); 362 ASSERT_TRUE(ST->isOpaque()); 363 364 // Check we properly parse pointer types. 365 // One indirection. 366 Ty = parseTypeAtBeginning("ptr", Read, Error, M, &Mapping); 367 ASSERT_TRUE(Ty); 368 ASSERT_TRUE(Ty->isPointerTy()); 369 ASSERT_TRUE(Read == 3); 370 371 // Check that we reject types with garbage. 372 Ty = parseTypeAtBeginning("i32 garbage", Read, Error, M, &Mapping); 373 ASSERT_TRUE(Ty); 374 ASSERT_TRUE(Ty->isIntegerTy()); 375 ASSERT_TRUE(Ty->getPrimitiveSizeInBits() == 32); 376 // We go to the next token, i.e., we read "i32" + ' '. 377 ASSERT_TRUE(Read == 4); 378 } 379 380 TEST(AsmParserTest, InvalidDataLayoutStringCallback) { 381 LLVMContext Ctx; 382 SMDiagnostic Error; 383 // Note the invalid i8:7 part 384 // Overalign i32 as marker so we can check that indeed this DL was used, 385 // and not some default. 386 StringRef InvalidDLStr = 387 "e-m:e-p:64:64-i8:7-i16:16-i32:64-i64:64-f80:128-n8:16:32:64"; 388 StringRef FixedDLStr = 389 "e-m:e-p:64:64-i8:8-i16:16-i32:64-i64:64-f80:128-n8:16:32:64"; 390 Expected<DataLayout> ExpectedFixedDL = DataLayout::parse(FixedDLStr); 391 ASSERT_TRUE(!ExpectedFixedDL.takeError()); 392 DataLayout FixedDL = ExpectedFixedDL.get(); 393 std::string Source = ("target datalayout = \"" + InvalidDLStr + "\"\n").str(); 394 MemoryBufferRef SourceBuffer(Source, "<string>"); 395 396 // Check that we reject the source without a DL override. 397 SlotMapping Mapping1; 398 auto Mod1 = parseAssembly(SourceBuffer, Error, Ctx, &Mapping1); 399 EXPECT_TRUE(Mod1 == nullptr); 400 401 // Check that we pass the correct DL str to the callback, 402 // that fixing the DL str from the callback works, 403 // and that the resulting module has the correct DL. 404 SlotMapping Mapping2; 405 auto Mod2 = parseAssembly( 406 SourceBuffer, Error, Ctx, &Mapping2, 407 [&](StringRef Triple, StringRef DLStr) -> std::optional<std::string> { 408 EXPECT_EQ(DLStr, InvalidDLStr); 409 return std::string{FixedDLStr}; 410 }); 411 ASSERT_TRUE(Mod2 != nullptr); 412 EXPECT_EQ(Mod2->getDataLayout(), FixedDL); 413 } 414 415 TEST(AsmParserTest, DIExpressionBodyAtBeginningWithSlotMappingParsing) { 416 LLVMContext Ctx; 417 SMDiagnostic Error; 418 StringRef Source = ""; 419 SlotMapping Mapping; 420 auto Mod = parseAssemblyString(Source, Error, Ctx, &Mapping); 421 ASSERT_TRUE(Mod != nullptr); 422 auto &M = *Mod; 423 unsigned Read; 424 425 ASSERT_EQ(Mapping.MetadataNodes.size(), 0u); 426 427 DIExpression *Expr; 428 429 Expr = parseDIExpressionBodyAtBeginning("()", Read, Error, M, &Mapping); 430 ASSERT_TRUE(Expr); 431 ASSERT_EQ(Expr->getNumElements(), 0u); 432 433 Expr = parseDIExpressionBodyAtBeginning("(0)", Read, Error, M, &Mapping); 434 ASSERT_TRUE(Expr); 435 ASSERT_EQ(Expr->getNumElements(), 1u); 436 437 Expr = parseDIExpressionBodyAtBeginning("(DW_OP_LLVM_fragment, 0, 1)", Read, 438 Error, M, &Mapping); 439 ASSERT_TRUE(Expr); 440 ASSERT_EQ(Expr->getNumElements(), 3u); 441 442 Expr = parseDIExpressionBodyAtBeginning( 443 "(DW_OP_LLVM_fragment, 0, 1) trailing source", Read, Error, M, &Mapping); 444 ASSERT_TRUE(Expr); 445 ASSERT_EQ(Expr->getNumElements(), 3u); 446 ASSERT_EQ(Read, StringRef("(DW_OP_LLVM_fragment, 0, 1) ").size()); 447 448 Error = {}; 449 Expr = parseDIExpressionBodyAtBeginning("i32", Read, Error, M, &Mapping); 450 ASSERT_FALSE(Expr); 451 ASSERT_EQ(Error.getMessage(), "expected '(' here"); 452 453 Error = {}; 454 Expr = parseDIExpressionBodyAtBeginning( 455 "!DIExpression(DW_OP_LLVM_fragment, 0, 1)", Read, Error, M, &Mapping); 456 ASSERT_FALSE(Expr); 457 ASSERT_EQ(Error.getMessage(), "expected '(' here"); 458 459 ASSERT_EQ(Mapping.MetadataNodes.size(), 0u); 460 } 461 462 } // end anonymous namespace 463