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