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/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"
24 TEST(AsmParserTest
, NullTerminatedInput
) {
26 StringRef Source
= "; Empty module \n";
28 auto Mod
= parseAssemblyString(Source
, Error
, Ctx
);
30 EXPECT_TRUE(Mod
!= nullptr);
31 EXPECT_TRUE(Error
.getMessage().empty());
34 #ifdef GTEST_HAS_DEATH_TEST
37 TEST(AsmParserTest
, NonNullTerminatedInput
) {
39 StringRef Source
= "; Empty module \n\1\2";
41 std::unique_ptr
<Module
> Mod
;
42 EXPECT_DEATH(Mod
= parseAssemblyString(Source
.substr(0, Source
.size() - 2),
44 "Buffer is not null terminated!");
50 TEST(AsmParserTest
, SlotMappingTest
) {
52 StringRef Source
= "@0 = global i32 0\n !0 = !{}\n !42 = !{i32 42}";
55 auto Mod
= parseAssemblyString(Source
, Error
, Ctx
, &Mapping
);
57 EXPECT_TRUE(Mod
!= nullptr);
58 EXPECT_TRUE(Error
.getMessage().empty());
60 ASSERT_EQ(Mapping
.GlobalValues
.size(), 1u);
61 EXPECT_TRUE(isa
<GlobalVariable
>(Mapping
.GlobalValues
[0]));
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);
69 TEST(AsmParserTest
, TypeAndConstantValueParsing
) {
72 StringRef Source
= "define void @test() {\n entry:\n ret void\n}";
73 auto Mod
= parseAssemblyString(Source
, Error
, Ctx
);
74 ASSERT_TRUE(Mod
!= nullptr);
78 V
= parseConstantValue("double 3.5", Error
, M
);
80 EXPECT_TRUE(V
->getType()->isDoubleTy());
81 ASSERT_TRUE(isa
<ConstantFP
>(V
));
82 EXPECT_TRUE(cast
<ConstantFP
>(V
)->isExactlyValue(3.5));
84 V
= parseConstantValue("i32 42", Error
, M
);
86 EXPECT_TRUE(V
->getType()->isIntegerTy());
87 ASSERT_TRUE(isa
<ConstantInt
>(V
));
88 EXPECT_TRUE(cast
<ConstantInt
>(V
)->equalsInt(42));
90 V
= parseConstantValue("<4 x i32> <i32 0, i32 1, i32 2, i32 3>", Error
, M
);
92 EXPECT_TRUE(V
->getType()->isVectorTy());
93 ASSERT_TRUE(isa
<ConstantDataVector
>(V
));
95 V
= parseConstantValue("i32 add (i32 1, i32 2)", Error
, M
);
97 ASSERT_TRUE(isa
<ConstantInt
>(V
));
99 V
= parseConstantValue("ptr blockaddress(@test, %entry)", Error
, M
);
101 ASSERT_TRUE(isa
<BlockAddress
>(V
));
103 V
= parseConstantValue("ptr undef", Error
, M
);
105 ASSERT_TRUE(isa
<UndefValue
>(V
));
107 EXPECT_FALSE(parseConstantValue("duble 3.25", Error
, M
));
108 EXPECT_EQ(Error
.getMessage(), "expected type");
110 EXPECT_FALSE(parseConstantValue("i32 3.25", Error
, M
));
111 EXPECT_EQ(Error
.getMessage(), "floating point constant invalid for type");
113 EXPECT_FALSE(parseConstantValue("ptr @foo", Error
, M
));
114 EXPECT_EQ(Error
.getMessage(), "expected a constant value");
116 EXPECT_FALSE(parseConstantValue("i32 3, ", Error
, M
));
117 EXPECT_EQ(Error
.getMessage(), "expected end of string");
120 TEST(AsmParserTest
, TypeAndConstantValueWithSlotMappingParsing
) {
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"
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"
138 auto Mod
= parseAssemblyString(Source
, Error
, Ctx
, &Mapping
);
139 ASSERT_TRUE(Mod
!= nullptr);
143 V
= parseConstantValue("ptr getelementptr inbounds ([50 x %st], ptr "
144 "@v, i64 0, i64 1, i32 0)",
147 ASSERT_TRUE(isa
<ConstantExpr
>(V
));
149 V
= parseConstantValue("ptr getelementptr inbounds ([50 x %0], ptr "
150 "@g, i64 0, i64 1, i32 0)",
153 ASSERT_TRUE(isa
<ConstantExpr
>(V
));
156 TEST(AsmParserTest
, TypeWithSlotMappingParsing
) {
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"
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"
174 auto Mod
= parseAssemblyString(Source
, Error
, Ctx
, &Mapping
);
175 ASSERT_TRUE(Mod
!= nullptr);
178 // Check we properly parse integer types.
180 Ty
= parseType("i32", Error
, M
, &Mapping
);
182 ASSERT_TRUE(Ty
->isIntegerTy());
183 ASSERT_TRUE(Ty
->getPrimitiveSizeInBits() == 32);
185 // Check we properly parse integer types with exotic size.
186 Ty
= parseType("i13", Error
, M
, &Mapping
);
188 ASSERT_TRUE(Ty
->isIntegerTy());
189 ASSERT_TRUE(Ty
->getPrimitiveSizeInBits() == 13);
191 // Check we properly parse floating point types.
192 Ty
= parseType("float", Error
, M
, &Mapping
);
194 ASSERT_TRUE(Ty
->isFloatTy());
196 Ty
= parseType("double", Error
, M
, &Mapping
);
198 ASSERT_TRUE(Ty
->isDoubleTy());
200 // Check we properly parse struct types.
202 Ty
= parseType("%st", Error
, M
, &Mapping
);
204 ASSERT_TRUE(Ty
->isStructTy());
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);
216 Ty
= parseType("%0", Error
, M
, &Mapping
);
218 ASSERT_TRUE(Ty
->isStructTy());
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);
229 // Check we properly parse vector types.
230 Ty
= parseType("<5 x i32>", Error
, M
, &Mapping
);
232 ASSERT_TRUE(Ty
->isVectorTy());
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);
243 Ty
= parseType("%opaque", Error
, M
, &Mapping
);
245 ASSERT_TRUE(Ty
->isStructTy());
247 ST
= cast
<StructType
>(Ty
);
248 ASSERT_TRUE(ST
->isOpaque());
250 // Check we properly parse pointer types.
251 Ty
= parseType("ptr", Error
, M
, &Mapping
);
253 ASSERT_TRUE(Ty
->isPointerTy());
255 // Check that we reject types with garbage.
256 Ty
= parseType("i32 garbage", Error
, M
, &Mapping
);
260 TEST(AsmParserTest
, TypeAtBeginningWithSlotMappingParsing
) {
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"
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"
278 auto Mod
= parseAssemblyString(Source
, Error
, Ctx
, &Mapping
);
279 ASSERT_TRUE(Mod
!= nullptr);
283 // Check we properly parse integer types.
285 Ty
= parseTypeAtBeginning("i32", Read
, Error
, M
, &Mapping
);
287 ASSERT_TRUE(Ty
->isIntegerTy());
288 ASSERT_TRUE(Ty
->getPrimitiveSizeInBits() == 32);
289 ASSERT_TRUE(Read
== 3);
291 // Check we properly parse integer types with exotic size.
292 Ty
= parseTypeAtBeginning("i13", Read
, Error
, M
, &Mapping
);
294 ASSERT_TRUE(Ty
->isIntegerTy());
295 ASSERT_TRUE(Ty
->getPrimitiveSizeInBits() == 13);
296 ASSERT_TRUE(Read
== 3);
298 // Check we properly parse floating point types.
299 Ty
= parseTypeAtBeginning("float", Read
, Error
, M
, &Mapping
);
301 ASSERT_TRUE(Ty
->isFloatTy());
302 ASSERT_TRUE(Read
== 5);
304 Ty
= parseTypeAtBeginning("double", Read
, Error
, M
, &Mapping
);
306 ASSERT_TRUE(Ty
->isDoubleTy());
307 ASSERT_TRUE(Read
== 6);
309 // Check we properly parse struct types.
311 Ty
= parseTypeAtBeginning("%st", Read
, Error
, M
, &Mapping
);
313 ASSERT_TRUE(Ty
->isStructTy());
314 ASSERT_TRUE(Read
== 3);
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);
326 Ty
= parseTypeAtBeginning("%0", Read
, Error
, M
, &Mapping
);
328 ASSERT_TRUE(Ty
->isStructTy());
329 ASSERT_TRUE(Read
== 2);
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);
340 // Check we properly parse vector types.
341 Ty
= parseTypeAtBeginning("<5 x i32>", Read
, Error
, M
, &Mapping
);
343 ASSERT_TRUE(Ty
->isVectorTy());
344 ASSERT_TRUE(Read
== 9);
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);
355 Ty
= parseTypeAtBeginning("%opaque", Read
, Error
, M
, &Mapping
);
357 ASSERT_TRUE(Ty
->isStructTy());
358 ASSERT_TRUE(Read
== 7);
360 ST
= cast
<StructType
>(Ty
);
361 ASSERT_TRUE(ST
->isOpaque());
363 // Check we properly parse pointer types.
365 Ty
= parseTypeAtBeginning("ptr", Read
, Error
, M
, &Mapping
);
367 ASSERT_TRUE(Ty
->isPointerTy());
368 ASSERT_TRUE(Read
== 3);
370 // Check that we reject types with garbage.
371 Ty
= parseTypeAtBeginning("i32 garbage", Read
, Error
, M
, &Mapping
);
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);
379 TEST(AsmParserTest
, InvalidDataLayoutStringCallback
) {
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>");
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);
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
};
410 ASSERT_TRUE(Mod2
!= nullptr);
411 EXPECT_EQ(Mod2
->getDataLayout(), FixedDL
);
414 } // end anonymous namespace