[llvm-commits] [llvm] r79123 - in /llvm/trunk: docs/TestingGuide.html test/CodeGen/X86/sse2.ll utils/FileCheck/FileCheck.cpp

Chris Lattner sabre at nondot.org
Sat Aug 15 11:32:21 PDT 2009


Author: lattner
Date: Sat Aug 15 13:32:21 2009
New Revision: 79123

URL: http://llvm.org/viewvc/llvm-project?rev=79123&view=rev
Log:
implement support for CHECK-NEXT: in filecheck.

Modified:
    llvm/trunk/docs/TestingGuide.html
    llvm/trunk/test/CodeGen/X86/sse2.ll
    llvm/trunk/utils/FileCheck/FileCheck.cpp

Modified: llvm/trunk/docs/TestingGuide.html
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/TestingGuide.html?rev=79123&r1=79122&r2=79123&view=diff

==============================================================================
--- llvm/trunk/docs/TestingGuide.html (original)
+++ llvm/trunk/docs/TestingGuide.html Sat Aug 15 13:32:21 2009
@@ -518,14 +518,18 @@
 that would not count: "grep subl" matches if subl exists anywhere in the
 file.</p>
 
+</div>
+
+<!-- _______________________________________________________________________ -->
 <div class="doc_subsubsection"><a 
 name="FileCheck-check-prefix">The FileCheck -check-prefix option</a></div>
 
+<div class="doc_text">
+
 <p>The FileCheck -check-prefix option allows multiple test configurations to be
 driven from one .ll file.  This is useful in many circumstances, for example,
 testing different architectural variants with llc.  Here's a simple example:</p>
 
-
 <div class="doc_code">
 <pre>
 ; RUN: llvm-as < %s | llc -mtriple=i686-apple-darwin9 -mattr=sse41 \
@@ -548,6 +552,43 @@
 <p>In this case, we're testing that we get the expected code generation with
 both 32-bit and 64-bit code generation.</p>
 
+</div>
+
+<!-- _______________________________________________________________________ -->
+<div class="doc_subsubsection"><a 
+name="FileCheck-CHECK-NEXT">The "CHECK-NEXT:" directive</a></div>
+
+<div class="doc_text">
+
+<p>Sometimes you want to match lines and would like to verify that matches
+happen on exactly consequtive lines with no other lines in between them.  In
+this case, you can use CHECK: and CHECK-NEXT: directives to specify this.  If
+you specified a custom check prefix, just use "<PREFIX>-NEXT:".  For
+example, something like this works as you'd expect:</p>
+
+<div class="doc_code">
+<pre>
+define void @t2(<2 x double>* %r, <2 x double>* %A, double %B) nounwind  {
+	%tmp3 = load <2 x double>* %A, align 16
+	%tmp7 = insertelement <2 x double> undef, double %B, i32 0
+	%tmp9 = shufflevector <2 x double> %tmp3, <2 x double> %tmp7, <2 x i32> < i32 0, i32 2 >
+	store <2 x double> %tmp9, <2 x double>* %r, align 16
+	ret void
+        
+; <b>CHECK:</b> t2:
+; <b>CHECK:</b> 	movl	8(%esp), %eax
+; <b>CHECK-NEXT:</b> 	movapd	(%eax), %xmm0
+; <b>CHECK-NEXT:</b> 	movhpd	12(%esp), %xmm0
+; <b>CHECK-NEXT:</b> 	movl	4(%esp), %eax
+; <b>CHECK-NEXT:</b> 	movapd	%xmm0, (%eax)
+; <b>CHECK-NEXT:</b> 	ret
+}
+</pre>
+</div>
+
+<p>CHECK-NEXT: directives reject the input unless there is exactly one newline
+between it an the previous directive.  A CHECK-NEXT cannot be the first
+directive in a file.</p>
 
 </div>
 

Modified: llvm/trunk/test/CodeGen/X86/sse2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/sse2.ll?rev=79123&r1=79122&r2=79123&view=diff

==============================================================================
--- llvm/trunk/test/CodeGen/X86/sse2.ll (original)
+++ llvm/trunk/test/CodeGen/X86/sse2.ll Sat Aug 15 13:32:21 2009
@@ -10,11 +10,11 @@
         
 ; CHECK: t1:
 ; CHECK: 	movl	8(%esp), %eax
-; CHECK: 	movapd	(%eax), %xmm0
-; CHECK: 	movlpd	12(%esp), %xmm0
-; CHECK: 	movl	4(%esp), %eax
-; CHECK: 	movapd	%xmm0, (%eax)
-; CHECK: 	ret
+; CHECK-NEXT: 	movapd	(%eax), %xmm0
+; CHECK-NEXT: 	movlpd	12(%esp), %xmm0
+; CHECK-NEXT: 	movl	4(%esp), %eax
+; CHECK-NEXT: 	movapd	%xmm0, (%eax)
+; CHECK-NEXT: 	ret
 }
 
 define void @t2(<2 x double>* %r, <2 x double>* %A, double %B) nounwind  {
@@ -26,9 +26,9 @@
         
 ; CHECK: t2:
 ; CHECK: 	movl	8(%esp), %eax
-; CHECK: 	movapd	(%eax), %xmm0
-; CHECK: 	movhpd	12(%esp), %xmm0
-; CHECK: 	movl	4(%esp), %eax
-; CHECK: 	movapd	%xmm0, (%eax)
-; CHECK: 	ret
+; CHECK-NEXT: 	movapd	(%eax), %xmm0
+; CHECK-NEXT: 	movhpd	12(%esp), %xmm0
+; CHECK-NEXT: 	movl	4(%esp), %eax
+; CHECK-NEXT: 	movapd	%xmm0, (%eax)
+; CHECK-NEXT: 	ret
 }

Modified: llvm/trunk/utils/FileCheck/FileCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/FileCheck/FileCheck.cpp?rev=79123&r1=79122&r2=79123&view=diff

==============================================================================
--- llvm/trunk/utils/FileCheck/FileCheck.cpp (original)
+++ llvm/trunk/utils/FileCheck/FileCheck.cpp Sat Aug 15 13:32:21 2009
@@ -47,7 +47,12 @@
   /// Loc - The location in the match file that the check string was specified.
   SMLoc Loc;
   
-  CheckString(const std::string &S, SMLoc L) : Str(S), Loc(L) {}
+  /// IsCheckNext - This is true if this is a CHECK-NEXT: directive (as opposed
+  /// to a CHECK: directive.
+  bool IsCheckNext;
+  
+  CheckString(const std::string &S, SMLoc L, bool isCheckNext)
+    : Str(S), Loc(L), IsCheckNext(isCheckNext) {}
 };
 
 
@@ -106,16 +111,27 @@
     if (Ptr == BufferEnd)
       break;
     
+    const char *CheckPrefixStart = Ptr;
+    
+    // When we find a check prefix, keep track of whether we find CHECK: or
+    // CHECK-NEXT:
+    bool IsCheckNext;
+    
     // Verify that the : is present after the prefix.
-    if (Ptr[CheckPrefix.size()] != ':') {
+    if (Ptr[CheckPrefix.size()] == ':') {
+      Ptr += CheckPrefix.size()+1;
+      IsCheckNext = false;
+    } else if (BufferEnd-Ptr > 6 &&
+               memcmp(Ptr+CheckPrefix.size(), "-NEXT:", 6) == 0) {
+      Ptr += CheckPrefix.size()+7;
+      IsCheckNext = true;
+    } else {
       CurPtr = Ptr+1;
       continue;
     }
     
     // Okay, we found the prefix, yay.  Remember the rest of the line, but
     // ignore leading and trailing whitespace.
-    Ptr += CheckPrefix.size()+1;
-    
     while (*Ptr == ' ' || *Ptr == '\t')
       ++Ptr;
     
@@ -136,9 +152,18 @@
       return true;
     }
     
+    // Verify that CHECK-NEXT lines have at least one CHECK line before them.
+    if (IsCheckNext && CheckStrings.empty()) {
+      SM.PrintMessage(SMLoc::getFromPointer(CheckPrefixStart),
+                      "found '"+CheckPrefix+"-NEXT:' without previous '"+
+                      CheckPrefix+ ": line", "error");
+      return true;
+    }
+    
     // Okay, add the string we captured to the output vector and move on.
     CheckStrings.push_back(CheckString(std::string(Ptr, CurPtr),
-                                       SMLoc::getFromPointer(Ptr)));
+                                       SMLoc::getFromPointer(Ptr),
+                                       IsCheckNext));
   }
   
   if (CheckStrings.empty()) {
@@ -204,6 +229,45 @@
 }
 
 
+static void PrintCheckFailed(const SourceMgr &SM, const CheckString &CheckStr,
+                             const char *CurPtr, const char *BufferEnd) {
+  // Otherwise, we have an error, emit an error message.
+  SM.PrintMessage(CheckStr.Loc, "expected string not found in input",
+                  "error");
+  
+  // Print the "scanning from here" line.  If the current position is at the
+  // end of a line, advance to the start of the next line.
+  const char *Scan = CurPtr;
+  while (Scan != BufferEnd &&
+         (*Scan == ' ' || *Scan == '\t'))
+    ++Scan;
+  if (*Scan == '\n' || *Scan == '\r')
+    CurPtr = Scan+1;
+  
+  
+  SM.PrintMessage(SMLoc::getFromPointer(CurPtr), "scanning from here",
+                  "note");
+}
+
+static unsigned CountNumNewlinesBetween(const char *Start, const char *End) {
+  unsigned NumNewLines = 0;
+  for (; Start != End; ++Start) {
+    // Scan for newline.
+    if (Start[0] != '\n' && Start[0] != '\r')
+      continue;
+    
+    ++NumNewLines;
+    
+    // Handle \n\r and \r\n as a single newline.
+    if (Start+1 != End &&
+        (Start[0] == '\n' || Start[0] == '\r') &&
+        (Start[0] != Start[1]))
+      ++Start;
+  }
+  
+  return NumNewLines;
+}
+
 int main(int argc, char **argv) {
   sys::PrintStackTraceOnErrorSignal();
   PrettyStackTraceProgram X(argc, argv);
@@ -240,35 +304,50 @@
   // file.
   const char *CurPtr = F->getBufferStart(), *BufferEnd = F->getBufferEnd();
   
+  const char *LastMatch = 0;
   for (unsigned StrNo = 0, e = CheckStrings.size(); StrNo != e; ++StrNo) {
     const CheckString &CheckStr = CheckStrings[StrNo];
     
     // Find StrNo in the file.
     const char *Ptr = FindFixedStringInBuffer(CheckStr.Str, CurPtr, *F);
     
-    // If we found a match, we're done, move on.
-    if (Ptr != BufferEnd) {
-      CurPtr = Ptr + CheckStr.Str.size();
-      continue;
+    // If we didn't find a match, reject the input.
+    if (Ptr == BufferEnd) {
+      PrintCheckFailed(SM, CheckStr, CurPtr, BufferEnd);
+      return 1;
     }
     
-    // Otherwise, we have an error, emit an error message.
-    SM.PrintMessage(CheckStr.Loc, "expected string not found in input",
-                    "error");
-    
-    // Print the "scanning from here" line.  If the current position is at the
-    // end of a line, advance to the start of the next line.
-    const char *Scan = CurPtr;
-    while (Scan != BufferEnd &&
-           (*Scan == ' ' || *Scan == '\t'))
-      ++Scan;
-    if (*Scan == '\n' || *Scan == '\r')
-      CurPtr = Scan+1;
-    
-    
-    SM.PrintMessage(SMLoc::getFromPointer(CurPtr), "scanning from here",
-                    "note");
-    return 1;
+    // If this check is a "CHECK-NEXT", verify that the previous match was on
+    // the previous line (i.e. that there is one newline between them).
+    if (CheckStr.IsCheckNext) {
+      // Count the number of newlines between the previous match and this one.
+      assert(LastMatch && "CHECK-NEXT can't be the first check in a file");
+
+      unsigned NumNewLines = CountNumNewlinesBetween(LastMatch, Ptr);
+      if (NumNewLines == 0) {
+        SM.PrintMessage(SMLoc::getFromPointer(Ptr),
+                    CheckPrefix+"-NEXT: is on the same line as previous match",
+                        "error");
+        SM.PrintMessage(SMLoc::getFromPointer(LastMatch),
+                        "previous match was here", "note");
+        return 1;
+      }
+      
+      if (NumNewLines != 1) {
+        SM.PrintMessage(SMLoc::getFromPointer(Ptr),
+                        CheckPrefix+
+                        "-NEXT: is not on the line after the previous match",
+                        "error");
+        SM.PrintMessage(SMLoc::getFromPointer(LastMatch),
+                        "previous match was here", "note");
+        return 1;
+      }
+    }
+
+    // Otherwise, everything is good.  Remember this as the last match and move
+    // on to the next one.
+    LastMatch = Ptr;
+    CurPtr = Ptr + CheckStr.Str.size();
   }
   
   return 0;





More information about the llvm-commits mailing list