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