1 //===- llvm/unittest/AsmParser/AsmParserTest.cpp - asm parser unittests ---===//
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
7 //===----------------------------------------------------------------------===//
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"
25 TEST(AsmParserTest
, NullTerminatedInput
) {
27 StringRef Source
= "; Empty module \n";
29 auto Mod
= parseAssemblyString(Source
, Error
, Ctx
);
31 EXPECT_TRUE(Mod
!= nullptr);
32 EXPECT_TRUE(Error
.getMessage().empty());
35 #ifdef GTEST_HAS_DEATH_TEST
38 TEST(AsmParserTest
, NonNullTerminatedInput
) {
40 StringRef Source
= "; Empty module \n\1\2";
42 std::unique_ptr
<Module
> Mod
;
43 EXPECT_DEATH(Mod
= parseAssemblyString(Source
.substr(0, Source
.size() - 2),
45 "Buffer is not null terminated!");
51 TEST(AsmParserTest
, SlotMappingTest
) {
53 StringRef Source
= "@0 = global i32 0\n !0 = !{}\n !42 = !{i32 42}";
56 auto Mod
= parseAssemblyString(Source
, Error
, Ctx
, &Mapping
);
58 EXPECT_TRUE(Mod
!= nullptr);
59 EXPECT_TRUE(Error
.getMessage().empty());
61 ASSERT_EQ(Mapping
.GlobalValues
.getNext(), 1u);
62 EXPECT_TRUE(isa
<GlobalVariable
>(Mapping
.GlobalValues
.get(0)));
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);
70 TEST(AsmParserTest
, TypeAndConstantValueParsing
) {
73 StringRef Source
= "define void @test() {\n entry:\n ret void\n}";
74 auto Mod
= parseAssemblyString(Source
, Error
, Ctx
);
75 ASSERT_TRUE(Mod
!= nullptr);
79 V
= parseConstantValue("double 3.5", Error
, M
);
81 EXPECT_TRUE(V
->getType()->isDoubleTy());
82 ASSERT_TRUE(isa
<ConstantFP
>(V
));
83 EXPECT_TRUE(cast
<ConstantFP
>(V
)->isExactlyValue(3.5));
85 V
= parseConstantValue("i32 42", Error
, M
);
87 EXPECT_TRUE(V
->getType()->isIntegerTy());
88 ASSERT_TRUE(isa
<ConstantInt
>(V
));
89 EXPECT_TRUE(cast
<ConstantInt
>(V
)->equalsInt(42));
91 V
= parseConstantValue("<4 x i32> <i32 0, i32 1, i32 2, i32 3>", Error
, M
);
93 EXPECT_TRUE(V
->getType()->isVectorTy());
94 ASSERT_TRUE(isa
<ConstantDataVector
>(V
));
96 V
= parseConstantValue("i32 add (i32 1, i32 2)", Error
, M
);
98 ASSERT_TRUE(isa
<ConstantInt
>(V
));
100 V
= parseConstantValue("ptr blockaddress(@test, %entry)", Error
, M
);
102 ASSERT_TRUE(isa
<BlockAddress
>(V
));
104 V
= parseConstantValue("ptr undef", Error
, M
);
106 ASSERT_TRUE(isa
<UndefValue
>(V
));
108 EXPECT_FALSE(parseConstantValue("duble 3.25", Error
, M
));
109 EXPECT_EQ(Error
.getMessage(), "expected type");
111 EXPECT_FALSE(parseConstantValue("i32 3.25", Error
, M
));
112 EXPECT_EQ(Error
.getMessage(), "floating point constant invalid for type");
114 EXPECT_FALSE(parseConstantValue("ptr @foo", Error
, M
));
115 EXPECT_EQ(Error
.getMessage(), "expected a constant value");
117 EXPECT_FALSE(parseConstantValue("i32 3, ", Error
, M
));
118 EXPECT_EQ(Error
.getMessage(), "expected end of string");
121 TEST(AsmParserTest
, TypeAndConstantValueWithSlotMappingParsing
) {
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"
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"
139 auto Mod
= parseAssemblyString(Source
, Error
, Ctx
, &Mapping
);
140 ASSERT_TRUE(Mod
!= nullptr);
144 V
= parseConstantValue("ptr getelementptr inbounds ([50 x %st], ptr "
145 "@v, i64 0, i64 1, i32 0)",
148 ASSERT_TRUE(isa
<ConstantExpr
>(V
));
150 V
= parseConstantValue("ptr getelementptr inbounds ([50 x %0], ptr "
151 "@g, i64 0, i64 1, i32 0)",
154 ASSERT_TRUE(isa
<ConstantExpr
>(V
));
157 TEST(AsmParserTest
, TypeWithSlotMappingParsing
) {
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"
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"
175 auto Mod
= parseAssemblyString(Source
, Error
, Ctx
, &Mapping
);
176 ASSERT_TRUE(Mod
!= nullptr);
179 // Check we properly parse integer types.
181 Ty
= parseType("i32", Error
, M
, &Mapping
);
183 ASSERT_TRUE(Ty
->isIntegerTy());
184 ASSERT_TRUE(Ty
->getPrimitiveSizeInBits() == 32);
186 // Check we properly parse integer types with exotic size.
187 Ty
= parseType("i13", Error
, M
, &Mapping
);
189 ASSERT_TRUE(Ty
->isIntegerTy());
190 ASSERT_TRUE(Ty
->getPrimitiveSizeInBits() == 13);
192 // Check we properly parse floating point types.
193 Ty
= parseType("float", Error
, M
, &Mapping
);
195 ASSERT_TRUE(Ty
->isFloatTy());
197 Ty
= parseType("double", Error
, M
, &Mapping
);
199 ASSERT_TRUE(Ty
->isDoubleTy());
201 // Check we properly parse struct types.
203 Ty
= parseType("%st", Error
, M
, &Mapping
);
205 ASSERT_TRUE(Ty
->isStructTy());
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);
217 Ty
= parseType("%0", Error
, M
, &Mapping
);
219 ASSERT_TRUE(Ty
->isStructTy());
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);
230 // Check we properly parse vector types.
231 Ty
= parseType("<5 x i32>", Error
, M
, &Mapping
);
233 ASSERT_TRUE(Ty
->isVectorTy());
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);
244 Ty
= parseType("%opaque", Error
, M
, &Mapping
);
246 ASSERT_TRUE(Ty
->isStructTy());
248 ST
= cast
<StructType
>(Ty
);
249 ASSERT_TRUE(ST
->isOpaque());
251 // Check we properly parse pointer types.
252 Ty
= parseType("ptr", Error
, M
, &Mapping
);
254 ASSERT_TRUE(Ty
->isPointerTy());
256 // Check that we reject types with garbage.
257 Ty
= parseType("i32 garbage", Error
, M
, &Mapping
);
261 TEST(AsmParserTest
, TypeAtBeginningWithSlotMappingParsing
) {
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"
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"
279 auto Mod
= parseAssemblyString(Source
, Error
, Ctx
, &Mapping
);
280 ASSERT_TRUE(Mod
!= nullptr);
284 // Check we properly parse integer types.
286 Ty
= parseTypeAtBeginning("i32", Read
, Error
, M
, &Mapping
);
288 ASSERT_TRUE(Ty
->isIntegerTy());
289 ASSERT_TRUE(Ty
->getPrimitiveSizeInBits() == 32);
290 ASSERT_TRUE(Read
== 3);
292 // Check we properly parse integer types with exotic size.
293 Ty
= parseTypeAtBeginning("i13", Read
, Error
, M
, &Mapping
);
295 ASSERT_TRUE(Ty
->isIntegerTy());
296 ASSERT_TRUE(Ty
->getPrimitiveSizeInBits() == 13);
297 ASSERT_TRUE(Read
== 3);
299 // Check we properly parse floating point types.
300 Ty
= parseTypeAtBeginning("float", Read
, Error
, M
, &Mapping
);
302 ASSERT_TRUE(Ty
->isFloatTy());
303 ASSERT_TRUE(Read
== 5);
305 Ty
= parseTypeAtBeginning("double", Read
, Error
, M
, &Mapping
);
307 ASSERT_TRUE(Ty
->isDoubleTy());
308 ASSERT_TRUE(Read
== 6);
310 // Check we properly parse struct types.
312 Ty
= parseTypeAtBeginning("%st", Read
, Error
, M
, &Mapping
);
314 ASSERT_TRUE(Ty
->isStructTy());
315 ASSERT_TRUE(Read
== 3);
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);
327 Ty
= parseTypeAtBeginning("%0", Read
, Error
, M
, &Mapping
);
329 ASSERT_TRUE(Ty
->isStructTy());
330 ASSERT_TRUE(Read
== 2);
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);
341 // Check we properly parse vector types.
342 Ty
= parseTypeAtBeginning("<5 x i32>", Read
, Error
, M
, &Mapping
);
344 ASSERT_TRUE(Ty
->isVectorTy());
345 ASSERT_TRUE(Read
== 9);
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);
356 Ty
= parseTypeAtBeginning("%opaque", Read
, Error
, M
, &Mapping
);
358 ASSERT_TRUE(Ty
->isStructTy());
359 ASSERT_TRUE(Read
== 7);
361 ST
= cast
<StructType
>(Ty
);
362 ASSERT_TRUE(ST
->isOpaque());
364 // Check we properly parse pointer types.
366 Ty
= parseTypeAtBeginning("ptr", Read
, Error
, M
, &Mapping
);
368 ASSERT_TRUE(Ty
->isPointerTy());
369 ASSERT_TRUE(Read
== 3);
371 // Check that we reject types with garbage.
372 Ty
= parseTypeAtBeginning("i32 garbage", Read
, Error
, M
, &Mapping
);
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);
380 TEST(AsmParserTest
, InvalidDataLayoutStringCallback
) {
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>");
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);
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
};
411 ASSERT_TRUE(Mod2
!= nullptr);
412 EXPECT_EQ(Mod2
->getDataLayout(), FixedDL
);
415 TEST(AsmParserTest
, DIExpressionBodyAtBeginningWithSlotMappingParsing
) {
418 StringRef Source
= "";
420 auto Mod
= parseAssemblyString(Source
, Error
, Ctx
, &Mapping
);
421 ASSERT_TRUE(Mod
!= nullptr);
425 ASSERT_EQ(Mapping
.MetadataNodes
.size(), 0u);
429 Expr
= parseDIExpressionBodyAtBeginning("()", Read
, Error
, M
, &Mapping
);
431 ASSERT_EQ(Expr
->getNumElements(), 0u);
433 Expr
= parseDIExpressionBodyAtBeginning("(0)", Read
, Error
, M
, &Mapping
);
435 ASSERT_EQ(Expr
->getNumElements(), 1u);
437 Expr
= parseDIExpressionBodyAtBeginning("(DW_OP_LLVM_fragment, 0, 1)", Read
,
440 ASSERT_EQ(Expr
->getNumElements(), 3u);
442 Expr
= parseDIExpressionBodyAtBeginning(
443 "(DW_OP_LLVM_fragment, 0, 1) trailing source", Read
, Error
, M
, &Mapping
);
445 ASSERT_EQ(Expr
->getNumElements(), 3u);
446 ASSERT_EQ(Read
, StringRef("(DW_OP_LLVM_fragment, 0, 1) ").size());
449 Expr
= parseDIExpressionBodyAtBeginning("i32", Read
, Error
, M
, &Mapping
);
451 ASSERT_EQ(Error
.getMessage(), "expected '(' here");
454 Expr
= parseDIExpressionBodyAtBeginning(
455 "!DIExpression(DW_OP_LLVM_fragment, 0, 1)", Read
, Error
, M
, &Mapping
);
457 ASSERT_EQ(Error
.getMessage(), "expected '(' here");
459 ASSERT_EQ(Mapping
.MetadataNodes
.size(), 0u);
462 } // end anonymous namespace