llvm.org GIT mirror llvm / 5dafafd
implement support for CHECK-NEXT: in filecheck. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79123 91177308-0d34-0410-b5e6-96231b3b80d8 Chris Lattner 10 years ago
3 changed file(s) with 159 addition(s) and 39 deletion(s). Raw diff Collapse all Expand all
517517 that would not count: "grep subl" matches if subl exists anywhere in the
518518 file.

519519
520
521
522
520523
521524 name="FileCheck-check-prefix">The FileCheck -check-prefix option
525
526
522527
523528

The FileCheck -check-prefix option allows multiple test configurations to be

524529 driven from one .ll file. This is useful in many circumstances, for example,
525530 testing different architectural variants with llc. Here's a simple example:

526
527531
528532
529533

                  
                
547551

In this case, we're testing that we get the expected code generation with

548552 both 32-bit and 64-bit code generation.

549553
554
555
556
557
558 name="FileCheck-CHECK-NEXT">The "CHECK-NEXT:" directive
559
560
561
562

Sometimes you want to match lines and would like to verify that matches

563 happen on exactly consequtive lines with no other lines in between them. In
564 this case, you can use CHECK: and CHECK-NEXT: directives to specify this. If
565 you specified a custom check prefix, just use "<PREFIX>-NEXT:". For
566 example, something like this works as you'd expect:

567
568
569

                  
                
570 define void @t2(<2 x double>* %r, <2 x double>* %A, double %B) nounwind {
571 %tmp3 = load <2 x double>* %A, align 16
572 %tmp7 = insertelement <2 x double> undef, double %B, i32 0
573 %tmp9 = shufflevector <2 x double> %tmp3, <2 x double> %tmp7, <2 x i32> < i32 0, i32 2 >
574 store <2 x double> %tmp9, <2 x double>* %r, align 16
575 ret void
576
577 ; CHECK: t2:
578 ; CHECK: movl 8(%esp), %eax
579 ; CHECK-NEXT: movapd (%eax), %xmm0
580 ; CHECK-NEXT: movhpd 12(%esp), %xmm0
581 ; CHECK-NEXT: movl 4(%esp), %eax
582 ; CHECK-NEXT: movapd %xmm0, (%eax)
583 ; CHECK-NEXT: ret
584 }
585
586
587
588

CHECK-NEXT: directives reject the input unless there is exactly one newline

589 between it an the previous directive. A CHECK-NEXT cannot be the first
590 directive in a file.

550591
551592
552593
99
1010 ; CHECK: t1:
1111 ; CHECK: movl 8(%esp), %eax
12 ; CHECK: movapd (%eax), %xmm0
13 ; CHECK: movlpd 12(%esp), %xmm0
14 ; CHECK: movl 4(%esp), %eax
15 ; CHECK: movapd %xmm0, (%eax)
16 ; CHECK: ret
12 ; CHECK-NEXT: movapd (%eax), %xmm0
13 ; CHECK-NEXT: movlpd 12(%esp), %xmm0
14 ; CHECK-NEXT: movl 4(%esp), %eax
15 ; CHECK-NEXT: movapd %xmm0, (%eax)
16 ; CHECK-NEXT: ret
1717 }
1818
1919 define void @t2(<2 x double>* %r, <2 x double>* %A, double %B) nounwind {
2525
2626 ; CHECK: t2:
2727 ; CHECK: movl 8(%esp), %eax
28 ; CHECK: movapd (%eax), %xmm0
29 ; CHECK: movhpd 12(%esp), %xmm0
30 ; CHECK: movl 4(%esp), %eax
31 ; CHECK: movapd %xmm0, (%eax)
32 ; CHECK: ret
28 ; CHECK-NEXT: movapd (%eax), %xmm0
29 ; CHECK-NEXT: movhpd 12(%esp), %xmm0
30 ; CHECK-NEXT: movl 4(%esp), %eax
31 ; CHECK-NEXT: movapd %xmm0, (%eax)
32 ; CHECK-NEXT: ret
3333 }
4646 /// Loc - The location in the match file that the check string was specified.
4747 SMLoc Loc;
4848
49 CheckString(const std::string &S, SMLoc L) : Str(S), Loc(L) {}
49 /// IsCheckNext - This is true if this is a CHECK-NEXT: directive (as opposed
50 /// to a CHECK: directive.
51 bool IsCheckNext;
52
53 CheckString(const std::string &S, SMLoc L, bool isCheckNext)
54 : Str(S), Loc(L), IsCheckNext(isCheckNext) {}
5055 };
5156
5257
105110 if (Ptr == BufferEnd)
106111 break;
107112
113 const char *CheckPrefixStart = Ptr;
114
115 // When we find a check prefix, keep track of whether we find CHECK: or
116 // CHECK-NEXT:
117 bool IsCheckNext;
118
108119 // Verify that the : is present after the prefix.
109 if (Ptr[CheckPrefix.size()] != ':') {
120 if (Ptr[CheckPrefix.size()] == ':') {
121 Ptr += CheckPrefix.size()+1;
122 IsCheckNext = false;
123 } else if (BufferEnd-Ptr > 6 &&
124 memcmp(Ptr+CheckPrefix.size(), "-NEXT:", 6) == 0) {
125 Ptr += CheckPrefix.size()+7;
126 IsCheckNext = true;
127 } else {
110128 CurPtr = Ptr+1;
111129 continue;
112130 }
113131
114132 // Okay, we found the prefix, yay. Remember the rest of the line, but
115133 // ignore leading and trailing whitespace.
116 Ptr += CheckPrefix.size()+1;
117
118134 while (*Ptr == ' ' || *Ptr == '\t')
119135 ++Ptr;
120136
135151 return true;
136152 }
137153
154 // Verify that CHECK-NEXT lines have at least one CHECK line before them.
155 if (IsCheckNext && CheckStrings.empty()) {
156 SM.PrintMessage(SMLoc::getFromPointer(CheckPrefixStart),
157 "found '"+CheckPrefix+"-NEXT:' without previous '"+
158 CheckPrefix+ ": line", "error");
159 return true;
160 }
161
138162 // Okay, add the string we captured to the output vector and move on.
139163 CheckStrings.push_back(CheckString(std::string(Ptr, CurPtr),
140 SMLoc::getFromPointer(Ptr)));
164 SMLoc::getFromPointer(Ptr),
165 IsCheckNext));
141166 }
142167
143168 if (CheckStrings.empty()) {
203228 }
204229
205230
231 static void PrintCheckFailed(const SourceMgr &SM, const CheckString &CheckStr,
232 const char *CurPtr, const char *BufferEnd) {
233 // Otherwise, we have an error, emit an error message.
234 SM.PrintMessage(CheckStr.Loc, "expected string not found in input",
235 "error");
236
237 // Print the "scanning from here" line. If the current position is at the
238 // end of a line, advance to the start of the next line.
239 const char *Scan = CurPtr;
240 while (Scan != BufferEnd &&
241 (*Scan == ' ' || *Scan == '\t'))
242 ++Scan;
243 if (*Scan == '\n' || *Scan == '\r')
244 CurPtr = Scan+1;
245
246
247 SM.PrintMessage(SMLoc::getFromPointer(CurPtr), "scanning from here",
248 "note");
249 }
250
251 static unsigned CountNumNewlinesBetween(const char *Start, const char *End) {
252 unsigned NumNewLines = 0;
253 for (; Start != End; ++Start) {
254 // Scan for newline.
255 if (Start[0] != '\n' && Start[0] != '\r')
256 continue;
257
258 ++NumNewLines;
259
260 // Handle \n\r and \r\n as a single newline.
261 if (Start+1 != End &&
262 (Start[0] == '\n' || Start[0] == '\r') &&
263 (Start[0] != Start[1]))
264 ++Start;
265 }
266
267 return NumNewLines;
268 }
269
206270 int main(int argc, char **argv) {
207271 sys::PrintStackTraceOnErrorSignal();
208272 PrettyStackTraceProgram X(argc, argv);
239303 // file.
240304 const char *CurPtr = F->getBufferStart(), *BufferEnd = F->getBufferEnd();
241305
306 const char *LastMatch = 0;
242307 for (unsigned StrNo = 0, e = CheckStrings.size(); StrNo != e; ++StrNo) {
243308 const CheckString &CheckStr = CheckStrings[StrNo];
244309
245310 // Find StrNo in the file.
246311 const char *Ptr = FindFixedStringInBuffer(CheckStr.Str, CurPtr, *F);
247312
248 // If we found a match, we're done, move on.
249 if (Ptr != BufferEnd) {
250 CurPtr = Ptr + CheckStr.Str.size();
251 continue;
252 }
253
254 // Otherwise, we have an error, emit an error message.
255 SM.PrintMessage(CheckStr.Loc, "expected string not found in input",
256 "error");
257
258 // Print the "scanning from here" line. If the current position is at the
259 // end of a line, advance to the start of the next line.
260 const char *Scan = CurPtr;
261 while (Scan != BufferEnd &&
262 (*Scan == ' ' || *Scan == '\t'))
263 ++Scan;
264 if (*Scan == '\n' || *Scan == '\r')
265 CurPtr = Scan+1;
266
267
268 SM.PrintMessage(SMLoc::getFromPointer(CurPtr), "scanning from here",
269 "note");
270 return 1;
313 // If we didn't find a match, reject the input.
314 if (Ptr == BufferEnd) {
315 PrintCheckFailed(SM, CheckStr, CurPtr, BufferEnd);
316 return 1;
317 }
318
319 // If this check is a "CHECK-NEXT", verify that the previous match was on
320 // the previous line (i.e. that there is one newline between them).
321 if (CheckStr.IsCheckNext) {
322 // Count the number of newlines between the previous match and this one.
323 assert(LastMatch && "CHECK-NEXT can't be the first check in a file");
324
325 unsigned NumNewLines = CountNumNewlinesBetween(LastMatch, Ptr);
326 if (NumNewLines == 0) {
327 SM.PrintMessage(SMLoc::getFromPointer(Ptr),
328 CheckPrefix+"-NEXT: is on the same line as previous match",
329 "error");
330 SM.PrintMessage(SMLoc::getFromPointer(LastMatch),
331 "previous match was here", "note");
332 return 1;
333 }
334
335 if (NumNewLines != 1) {
336 SM.PrintMessage(SMLoc::getFromPointer(Ptr),
337 CheckPrefix+
338 "-NEXT: is not on the line after the previous match",
339 "error");
340 SM.PrintMessage(SMLoc::getFromPointer(LastMatch),
341 "previous match was here", "note");
342 return 1;
343 }
344 }
345
346 // Otherwise, everything is good. Remember this as the last match and move
347 // on to the next one.
348 LastMatch = Ptr;
349 CurPtr = Ptr + CheckStr.Str.size();
271350 }
272351
273352 return 0;