blob: a3b28f038b5033c87ca0431abee84d0e0c253b09 [file] [log] [blame]
Francis Visoiu Mistrih105b05e2018-10-10 18:43:42 +00001//===- unittest/Support/OptRemarksParsingTest.cpp - OptTable tests --------===//
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-c/OptRemarks.h"
11#include "gtest/gtest.h"
12
13using namespace llvm;
14
15template <size_t N> bool tryParse(const char (&Buf)[N]) {
16 LLVMOptRemarkParserRef Parser = LLVMOptRemarkParserCreate(Buf, N - 1);
17 LLVMOptRemarkEntry *Remark = nullptr;
18 while (LLVMOptRemarkEntry *NewRemark = LLVMOptRemarkParserGetNext(Parser)) {
19 EXPECT_TRUE(Remark == nullptr); // Only one remark per test.
20 Remark = NewRemark;
21 }
22 EXPECT_TRUE(Remark != nullptr); // We need *exactly* one remark per test.
23 bool HasError = LLVMOptRemarkParserHasError(Parser);
24 LLVMOptRemarkParserDispose(Parser);
25 return !HasError;
26}
27
28template <size_t N>
29bool parseExpectError(const char (&Buf)[N], const char *Error) {
30 LLVMOptRemarkParserRef Parser = LLVMOptRemarkParserCreate(Buf, N - 1);
31 LLVMOptRemarkEntry *Remark = nullptr;
32 while (LLVMOptRemarkEntry *NewRemark = LLVMOptRemarkParserGetNext(Parser)) {
33 EXPECT_FALSE(NewRemark);
34 }
35 EXPECT_TRUE(Remark == nullptr); // We are parsing only one malformed remark.
36 EXPECT_TRUE(LLVMOptRemarkParserHasError(Parser));
37 bool MatchesError =
38 StringRef(LLVMOptRemarkParserGetErrorMessage(Parser)).contains(Error);
39 LLVMOptRemarkParserDispose(Parser);
40
41 return MatchesError;
42}
43
44TEST(OptRemarks, OptRemarksParsingEmpty) {
45 StringRef Buf = "\n"
46 "\n";
47 LLVMOptRemarkParserRef Parser =
48 LLVMOptRemarkParserCreate(Buf.data(), Buf.size());
49 LLVMOptRemarkEntry *NewRemark = LLVMOptRemarkParserGetNext(Parser);
50 EXPECT_TRUE(NewRemark == nullptr); // No remark expected.
51 EXPECT_TRUE(LLVMOptRemarkParserHasError(Parser));
52 EXPECT_TRUE(StringRef(LLVMOptRemarkParserGetErrorMessage(Parser))
53 .contains("document root is not of mapping type."));
54 LLVMOptRemarkParserDispose(Parser);
55}
56
57TEST(OptRemarks, OptRemarksParsingGood) {
58 EXPECT_TRUE(tryParse("\n"
59"--- !Missed\n"
60"Pass: inline\n"
61"Name: NoDefinition\n"
62"DebugLoc: { File: file.c, Line: 3, Column: 12 }\n"
63"Function: foo\n"
64"Args:\n"
65" - Callee: bar\n"
66" - String: ' will not be inlined into '\n"
67" - Caller: foo\n"
68" DebugLoc: { File: file.c, Line: 2, Column: 0 }\n"
69" - String: ' because its definition is unavailable'\n"
70""));
71
72 // No debug loc should also pass.
73 EXPECT_TRUE(tryParse("\n"
74"--- !Missed\n"
75"Pass: inline\n"
76"Name: NoDefinition\n"
77"Function: foo\n"
78"Args:\n"
79" - Callee: bar\n"
80" - String: ' will not be inlined into '\n"
81" - Caller: foo\n"
82" DebugLoc: { File: file.c, Line: 2, Column: 0 }\n"
83" - String: ' because its definition is unavailable'\n"
84""));
85
86 // No args is also ok.
87 EXPECT_TRUE(tryParse("\n"
88"--- !Missed\n"
89"Pass: inline\n"
90"Name: NoDefinition\n"
91"DebugLoc: { File: file.c, Line: 3, Column: 12 }\n"
92"Function: foo\n"
93""));
94
95 // Different order.
96 EXPECT_TRUE(tryParse("\n"
97"--- !Missed\n"
98"DebugLoc: { Line: 3, Column: 12, File: file.c }\n"
99"Function: foo\n"
100"Name: NoDefinition\n"
101"Args:\n"
102" - Callee: bar\n"
103" - String: ' will not be inlined into '\n"
104" - Caller: foo\n"
105" DebugLoc: { File: file.c, Line: 2, Column: 0 }\n"
106" - String: ' because its definition is unavailable'\n"
107"Pass: inline\n"
108""));
109}
110
111// Mandatory common part of a remark.
112#define COMMON_REMARK "\nPass: inline\nName: NoDefinition\nFunction: foo\n\n"
113// Test all the types.
114TEST(OptRemarks, OptRemarksParsingTypes) {
115 // Type: Passed
116 EXPECT_TRUE(tryParse("--- !Passed" COMMON_REMARK));
117 // Type: Missed
118 EXPECT_TRUE(tryParse("--- !Missed" COMMON_REMARK));
119 // Type: Analysis
120 EXPECT_TRUE(tryParse("--- !Analysis" COMMON_REMARK));
121 // Type: AnalysisFPCompute
122 EXPECT_TRUE(tryParse("--- !AnalysisFPCompute" COMMON_REMARK));
123 // Type: AnalysisAliasing
124 EXPECT_TRUE(tryParse("--- !AnalysisAliasing" COMMON_REMARK));
125 // Type: Failure
126 EXPECT_TRUE(tryParse("--- !Failure" COMMON_REMARK));
127}
128#undef COMMON_REMARK
129
130TEST(OptRemarks, OptRemarksParsingMissingFields) {
131 // No type.
132 EXPECT_TRUE(parseExpectError("\n"
133"---\n"
134"Pass: inline\n"
135"Name: NoDefinition\n"
136"Function: foo\n"
137"",
138 "error: Type, Pass, Name or Function missing."));
139 // No pass.
140 EXPECT_TRUE(parseExpectError("\n"
141"--- !Missed\n"
142"Name: NoDefinition\n"
143"Function: foo\n"
144"",
145 "error: Type, Pass, Name or Function missing."));
146 // No name.
147 EXPECT_TRUE(parseExpectError("\n"
148"--- !Missed\n"
149"Pass: inline\n"
150"Function: foo\n"
151"",
152 "error: Type, Pass, Name or Function missing."));
153 // No function.
154 EXPECT_TRUE(parseExpectError("\n"
155"--- !Missed\n"
156"Pass: inline\n"
157"Name: NoDefinition\n"
158"",
159 "error: Type, Pass, Name or Function missing."));
160 // Debug loc but no file.
161 EXPECT_TRUE(parseExpectError("\n"
162"--- !Missed\n"
163"Pass: inline\n"
164"Name: NoDefinition\n"
165"Function: foo\n"
166"DebugLoc: { Line: 3, Column: 12 }\n"
167"",
168 "DebugLoc node incomplete."));
169 // Debug loc but no line.
170 EXPECT_TRUE(parseExpectError("\n"
171"--- !Missed\n"
172"Pass: inline\n"
173"Name: NoDefinition\n"
174"Function: foo\n"
175"DebugLoc: { File: file.c, Column: 12 }\n"
176"",
177 "DebugLoc node incomplete."));
178 // Debug loc but no column.
179 EXPECT_TRUE(parseExpectError("\n"
180"--- !Missed\n"
181"Pass: inline\n"
182"Name: NoDefinition\n"
183"Function: foo\n"
184"DebugLoc: { File: file.c, Line: 3 }\n"
185"",
186 "DebugLoc node incomplete."));
187}
188
189TEST(OptRemarks, OptRemarksParsingWrongTypes) {
190 // Wrong debug loc type.
191 EXPECT_TRUE(parseExpectError("\n"
192"--- !Missed\n"
193"Pass: inline\n"
194"Name: NoDefinition\n"
195"Function: foo\n"
196"DebugLoc: foo\n"
197"",
198 "expected a value of mapping type."));
199 // Wrong line type.
200 EXPECT_TRUE(parseExpectError("\n"
201"--- !Missed\n"
202"Pass: inline\n"
203"Name: NoDefinition\n"
204"Function: foo\n"
205"DebugLoc: { File: file.c, Line: b, Column: 12 }\n"
206"",
207 "expected a value of integer type."));
208 // Wrong column type.
209 EXPECT_TRUE(parseExpectError("\n"
210"--- !Missed\n"
211"Pass: inline\n"
212"Name: NoDefinition\n"
213"Function: foo\n"
214"DebugLoc: { File: file.c, Line: 3, Column: c }\n"
215"",
216 "expected a value of integer type."));
217 // Wrong args type.
218 EXPECT_TRUE(parseExpectError("\n"
219"--- !Missed\n"
220"Pass: inline\n"
221"Name: NoDefinition\n"
222"Function: foo\n"
223"Args: foo\n"
224"",
225 "wrong value type for key."));
226 // Wrong key type.
227 EXPECT_TRUE(parseExpectError("\n"
228"--- !Missed\n"
229"{ A: a }: inline\n"
230"Name: NoDefinition\n"
231"Function: foo\n"
232"",
233 "key is not a string."));
234 // Debug loc with unknown entry.
235 EXPECT_TRUE(parseExpectError("\n"
236"--- !Missed\n"
237"Pass: inline\n"
238"Name: NoDefinition\n"
239"Function: foo\n"
240"DebugLoc: { File: file.c, Column: 12, Unknown: 12 }\n"
241"",
242 "unknown entry in DebugLoc map."));
243 // Unknown entry.
244 EXPECT_TRUE(parseExpectError("\n"
245"--- !Missed\n"
246"Unknown: inline\n"
247"",
248 "unknown key."));
249 // Not a scalar.
250 EXPECT_TRUE(parseExpectError("\n"
251"--- !Missed\n"
252"Pass: { File: a, Line: 1, Column: 2 }\n"
253"Name: NoDefinition\n"
254"Function: foo\n"
255"",
256 "expected a value of scalar type."));
257 // Not a string file in debug loc.
258 EXPECT_TRUE(parseExpectError("\n"
259"--- !Missed\n"
260"Pass: inline\n"
261"Name: NoDefinition\n"
262"Function: foo\n"
263"DebugLoc: { File: { a: b }, Column: 12, Line: 12 }\n"
264"",
265 "expected a value of scalar type."));
266 // Not a integer column in debug loc.
267 EXPECT_TRUE(parseExpectError("\n"
268"--- !Missed\n"
269"Pass: inline\n"
270"Name: NoDefinition\n"
271"Function: foo\n"
272"DebugLoc: { File: file.c, Column: { a: b }, Line: 12 }\n"
273"",
274 "expected a value of scalar type."));
275 // Not a integer line in debug loc.
276 EXPECT_TRUE(parseExpectError("\n"
277"--- !Missed\n"
278"Pass: inline\n"
279"Name: NoDefinition\n"
280"Function: foo\n"
281"DebugLoc: { File: file.c, Column: 12, Line: { a: b } }\n"
282"",
283 "expected a value of scalar type."));
284 // Not a mapping type value for args.
285 EXPECT_TRUE(parseExpectError("\n"
286"--- !Missed\n"
287"Pass: inline\n"
288"Name: NoDefinition\n"
289"Function: foo\n"
290"DebugLoc: { File: file.c, Column: 12, Line: { a: b } }\n"
291"",
292 "expected a value of scalar type."));
293}
294
295TEST(OptRemarks, OptRemarksParsingWrongArgs) {
296 // Multiple debug locs per arg.
297 EXPECT_TRUE(
298 parseExpectError("\n"
299"--- !Missed\n"
300"Pass: inline\n"
301"Name: NoDefinition\n"
302"Function: foo\n"
303"Args:\n"
304" - Str: string\n"
305" DebugLoc: { File: a, Line: 1, Column: 2 }\n"
306" DebugLoc: { File: a, Line: 1, Column: 2 }\n"
307"",
308 "only one DebugLoc entry is allowed per argument."));
309 // Multiple strings per arg.
310 EXPECT_TRUE(
311 parseExpectError("\n"
312"--- !Missed\n"
313"Pass: inline\n"
314"Name: NoDefinition\n"
315"Function: foo\n"
316"Args:\n"
317" - Str: string\n"
318" Str2: string\n"
319" DebugLoc: { File: a, Line: 1, Column: 2 }\n"
320"",
321 "only one string entry is allowed per argument."));
322 // No arg value.
323 EXPECT_TRUE(parseExpectError("\n"
324"--- !Missed\n"
325"Pass: inline\n"
326"Name: NoDefinition\n"
327"Function: foo\n"
328"Args:\n"
329" - Callee: ''\n"
330" - DebugLoc: { File: a, Line: 1, Column: 2 }\n"
331"",
332 "argument value is missing."));
333 // No arg value.
334 EXPECT_TRUE(parseExpectError("\n"
335"--- !Missed\n"
336"Pass: inline\n"
337"Name: NoDefinition\n"
338"Function: foo\n"
339"Args:\n"
340" - DebugLoc: { File: a, Line: 1, Column: 2 }\n"
341"",
342 "argument key is missing."));
343
344}
345
346TEST(OptRemarks, OptRemarksGoodStruct) {
347 StringRef Buf = "\n"
348"--- !Missed\n"
349"Pass: inline\n"
350"Name: NoDefinition\n"
351"DebugLoc: { File: file.c, Line: 3, Column: 12 }\n"
352"Function: foo\n"
353"Args:\n"
354" - Callee: bar\n"
355" - String: ' will not be inlined into '\n"
356" - Caller: foo\n"
357" DebugLoc: { File: file.c, Line: 2, Column: 0 }\n"
358" - String: ' because its definition is unavailable'\n"
359"\n";
360
361 LLVMOptRemarkParserRef Parser =
362 LLVMOptRemarkParserCreate(Buf.data(), Buf.size());
363 LLVMOptRemarkEntry *Remark = LLVMOptRemarkParserGetNext(Parser);
364 EXPECT_FALSE(Remark == nullptr);
365 EXPECT_EQ(StringRef(Remark->RemarkType.Str, 7), "!Missed");
366 EXPECT_EQ(Remark->RemarkType.Len, 7U);
367 EXPECT_EQ(StringRef(Remark->PassName.Str, 6), "inline");
368 EXPECT_EQ(Remark->PassName.Len, 6U);
369 EXPECT_EQ(StringRef(Remark->RemarkName.Str, 12), "NoDefinition");
370 EXPECT_EQ(Remark->RemarkName.Len, 12U);
371 EXPECT_EQ(StringRef(Remark->FunctionName.Str, 3), "foo");
372 EXPECT_EQ(Remark->FunctionName.Len, 3U);
373 EXPECT_EQ(StringRef(Remark->DebugLoc.SourceFile.Str, 6), "file.c");
374 EXPECT_EQ(Remark->DebugLoc.SourceFile.Len, 6U);
375 EXPECT_EQ(Remark->DebugLoc.SourceLineNumber, 3U);
376 EXPECT_EQ(Remark->DebugLoc.SourceColumnNumber, 12U);
377 EXPECT_EQ(Remark->Hotness, 0U);
378 EXPECT_EQ(Remark->NumArgs, 4U);
379 // Arg 0
380 {
381 LLVMOptRemarkArg &Arg = Remark->Args[0];
382 EXPECT_EQ(StringRef(Arg.Key.Str, 6), "Callee");
383 EXPECT_EQ(Arg.Key.Len, 6U);
384 EXPECT_EQ(StringRef(Arg.Value.Str, 3), "bar");
385 EXPECT_EQ(Arg.Value.Len, 3U);
386 EXPECT_EQ(StringRef(Arg.DebugLoc.SourceFile.Str, 0), "");
387 EXPECT_EQ(Arg.DebugLoc.SourceFile.Len, 0U);
388 EXPECT_EQ(Arg.DebugLoc.SourceLineNumber, 0U);
389 EXPECT_EQ(Arg.DebugLoc.SourceColumnNumber, 0U);
390 }
391 // Arg 1
392 {
393 LLVMOptRemarkArg &Arg = Remark->Args[1];
394 EXPECT_EQ(StringRef(Arg.Key.Str, 6), "String");
395 EXPECT_EQ(Arg.Key.Len, 6U);
396 EXPECT_EQ(StringRef(Arg.Value.Str, 26), " will not be inlined into ");
397 EXPECT_EQ(Arg.Value.Len, 26U);
398 EXPECT_EQ(StringRef(Arg.DebugLoc.SourceFile.Str, 0), "");
399 EXPECT_EQ(Arg.DebugLoc.SourceFile.Len, 0U);
400 EXPECT_EQ(Arg.DebugLoc.SourceLineNumber, 0U);
401 EXPECT_EQ(Arg.DebugLoc.SourceColumnNumber, 0U);
402 }
403 // Arg 2
404 {
405 LLVMOptRemarkArg &Arg = Remark->Args[2];
406 EXPECT_EQ(StringRef(Arg.Key.Str, 6), "Caller");
407 EXPECT_EQ(Arg.Key.Len, 6U);
408 EXPECT_EQ(StringRef(Arg.Value.Str, 3), "foo");
409 EXPECT_EQ(Arg.Value.Len, 3U);
410 EXPECT_EQ(StringRef(Arg.DebugLoc.SourceFile.Str, 6), "file.c");
411 EXPECT_EQ(Arg.DebugLoc.SourceFile.Len, 6U);
412 EXPECT_EQ(Arg.DebugLoc.SourceLineNumber, 2U);
413 EXPECT_EQ(Arg.DebugLoc.SourceColumnNumber, 0U);
414 }
415 // Arg 3
416 {
417 LLVMOptRemarkArg &Arg = Remark->Args[3];
418 EXPECT_EQ(StringRef(Arg.Key.Str, 6), "String");
419 EXPECT_EQ(Arg.Key.Len, 6U);
420 EXPECT_EQ(StringRef(Arg.Value.Str, 38),
421 " because its definition is unavailable");
422 EXPECT_EQ(Arg.Value.Len, 38U);
423 EXPECT_EQ(StringRef(Arg.DebugLoc.SourceFile.Str, 0), "");
424 EXPECT_EQ(Arg.DebugLoc.SourceFile.Len, 0U);
425 EXPECT_EQ(Arg.DebugLoc.SourceLineNumber, 0U);
426 EXPECT_EQ(Arg.DebugLoc.SourceColumnNumber, 0U);
427 }
428
429 EXPECT_EQ(LLVMOptRemarkParserGetNext(Parser), nullptr);
430
431 EXPECT_FALSE(LLVMOptRemarkParserHasError(Parser));
432 LLVMOptRemarkParserDispose(Parser);
433}