[LLVMdev] teaching FileCheck to handle variations in order

Matthew Curtis mcurtis at codeaurora.org
Fri Sep 7 05:20:37 PDT 2012


Hello all,

For the hexagon target, we have a couple of tests that are failing due 
to variations in the order of checked text. In these cases the ordering 
is not directly relevant to the functionality being tested.

For example:

    ; CHECK: memw(##a)
    ; CHECK: memw(##b)

    %0 = load i32* @a, align 4
    %1 = load i32* @b, align 4

requires that the compiler emit the memory operations for 'a' and 'b' in 
that order, even though the intent of the test might simply be to ensure 
that each 'load' results in a memory read.

I'd like to teach FileCheck to allow tests to be more tolerant of these 
incidental variations.

The attached patch implements one possible solution. It introduces a 
position stack and a couple of directives:

  * 'CHECK-PUSH:' pushes the current match position onto the stack.
  * 'CHECK-POP:' pops the top value off of the stack and uses it to set
    the current match position.

The above test can now be re-written as:

    ; CHECK-PUSH:
    ; CHECK: memw(##a)
    ; CHECK-POP:
    ; CHECK: memw(##b)

    %0 = load i32* @a, align 4
    %1 = load i32* @b, align 4

which handles either ordering of memory reads for 'a' and 'b'.

Thoughts?

Thanks,
Matthew Curtis

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20120907/dc2bf4af/attachment.html>
-------------- next part --------------
diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp
index 33f04ce..9f6a64a 100644
--- a/utils/FileCheck/FileCheck.cpp
+++ b/utils/FileCheck/FileCheck.cpp
@@ -50,11 +50,23 @@ NoCanonicalizeWhiteSpace("strict-whitespace",
 //===----------------------------------------------------------------------===//
 
 class Pattern {
+public:
+  enum MatchType {
+    MatchStr,
+    MatchCurrent,
+    MatchEndOfFile
+  };
+
+private:
   SMLoc PatternLoc;
 
-  /// MatchEOF - When set, this pattern only matches the end of file. This is
-  /// used for trailing CHECK-NOTs.
-  bool MatchEOF;
+  /// MatchType - When set to ...
+  ///   MatchStr, this pattern matches according to FixedStr or RegExStr.
+  ///   MatchCurrent, this pattern matches (the empty string at) the current
+  ///     position. This is used for CHECK-PUSHes without preceding CHECKs.
+  ///   MatchEndOfFile, this pattern only matches the end of file. This is used
+  ///     for trailing CHECK-NOTs.
+  enum MatchType Type;
 
   /// FixedStr - If non-empty, this pattern is a fixed string match with the
   /// specified fixed string.
@@ -77,7 +89,7 @@ class Pattern {
 
 public:
 
-  Pattern(bool matchEOF = false) : MatchEOF(matchEOF) { }
+  Pattern(enum MatchType t = MatchStr) : Type(t) { }
 
   bool ParsePattern(StringRef PatternStr, SourceMgr &SM);
 
@@ -285,9 +297,18 @@ bool Pattern::AddRegExToRegEx(StringRef RegexStr, unsigned &CurParen,
 size_t Pattern::Match(StringRef Buffer, size_t &MatchLen,
                       StringMap<StringRef> &VariableTable) const {
   // If this is the EOF pattern, match it immediately.
-  if (MatchEOF) {
+  switch (Type) {
+  case MatchStr:
+    break;
+  case MatchCurrent:
+    MatchLen = 0;
+    return 0;
+  case MatchEndOfFile:
     MatchLen = 0;
     return Buffer.size();
+  default:
+    assert("Unknown match type");
+    break;
   }
 
   // If this is a fixed string pattern, just match it now.
@@ -447,6 +468,9 @@ struct CheckString {
   /// IsCheckNext - This is true if this is a CHECK-NEXT: directive (as opposed
   /// to a CHECK: directive.
   bool IsCheckNext;
+  int PushPos;
+  int PopPos;
+  SMLoc PopLoc;
 
   /// NotStrings - These are all of the strings that are disallowed from
   /// occurring between this match string and the previous one (or start of
@@ -454,7 +478,7 @@ struct CheckString {
   std::vector<std::pair<SMLoc, Pattern> > NotStrings;
 
   CheckString(const Pattern &P, SMLoc L, bool isCheckNext)
-    : Pat(P), Loc(L), IsCheckNext(isCheckNext) {}
+    : Pat(P), Loc(L), IsCheckNext(isCheckNext), PushPos(0), PopPos(0) {}
 };
 
 /// CanonicalizeInputFile - Remove duplicate horizontal space from the specified
@@ -517,6 +541,8 @@ static bool ReadCheckFile(SourceMgr &SM,
   StringRef Buffer = F->getBuffer();
 
   std::vector<std::pair<SMLoc, Pattern> > NotMatches;
+  int NextCheckPopPos= 0;
+  SMLoc NextCheckPopLoc;
 
   while (1) {
     // See if Prefix occurs in the memory buffer.
@@ -531,6 +557,7 @@ static bool ReadCheckFile(SourceMgr &SM,
     // When we find a check prefix, keep track of whether we find CHECK: or
     // CHECK-NEXT:
     bool IsCheckNext = false, IsCheckNot = false;
+    bool IsCheckPush = false, IsCheckPop = false;
 
     // Verify that the : is present after the prefix.
     if (Buffer[CheckPrefix.size()] == ':') {
@@ -543,6 +570,14 @@ static bool ReadCheckFile(SourceMgr &SM,
                memcmp(Buffer.data()+CheckPrefix.size(), "-NOT:", 5) == 0) {
       Buffer = Buffer.substr(CheckPrefix.size()+6);
       IsCheckNot = true;
+    } else if (Buffer.size() > CheckPrefix.size()+6 &&
+               memcmp(Buffer.data()+CheckPrefix.size(), "-PUSH:", 6) == 0) {
+      Buffer = Buffer.substr(CheckPrefix.size()+7);
+      IsCheckPush = true;
+    } else if (Buffer.size() > CheckPrefix.size()+5 &&
+               memcmp(Buffer.data()+CheckPrefix.size(), "-POP:", 5) == 0) {
+      Buffer = Buffer.substr(CheckPrefix.size()+6);
+      IsCheckPop = true;
     } else {
       Buffer = Buffer.substr(1);
       continue;
@@ -555,6 +590,22 @@ static bool ReadCheckFile(SourceMgr &SM,
     // Scan ahead to the end of line.
     size_t EOL = Buffer.find_first_of("\n\r");
 
+    if (IsCheckPush) {
+      if (CheckStrings.empty()) {
+        CheckStrings.push_back(CheckString(Pattern(Pattern::MatchCurrent),
+                                           SMLoc::getFromPointer(Buffer.data()),
+                                           false));
+      }
+      CheckStrings.back().PushPos++;
+      continue;
+    }
+
+    if (IsCheckPop) {
+      NextCheckPopLoc = SMLoc::getFromPointer(CheckPrefixStart);
+      NextCheckPopPos++;
+      continue;
+    }
+
     // Remember the location of the start of the pattern, for diagnostics.
     SMLoc PatternLoc = SMLoc::getFromPointer(Buffer.data());
 
@@ -587,14 +638,22 @@ static bool ReadCheckFile(SourceMgr &SM,
     CheckStrings.push_back(CheckString(P,
                                        PatternLoc,
                                        IsCheckNext));
+    CheckStrings.back().PopPos= NextCheckPopPos;
+    CheckStrings.back().PopLoc= NextCheckPopLoc;
+    NextCheckPopPos= 0;
+    NextCheckPopLoc= SMLoc();
     std::swap(NotMatches, CheckStrings.back().NotStrings);
   }
 
   // Add an EOF pattern for any trailing CHECK-NOTs.
   if (!NotMatches.empty()) {
-    CheckStrings.push_back(CheckString(Pattern(true),
+    CheckStrings.push_back(CheckString(Pattern(Pattern::MatchEndOfFile),
                                        SMLoc::getFromPointer(Buffer.data()),
                                        false));
+    CheckStrings.back().PopPos= NextCheckPopPos;
+    CheckStrings.back().PopLoc= NextCheckPopLoc;
+    NextCheckPopPos= 0;
+    NextCheckPopLoc= SMLoc();
     std::swap(NotMatches, CheckStrings.back().NotStrings);
   }
 
@@ -686,10 +745,22 @@ int main(int argc, char **argv) {
   StringRef Buffer = F->getBuffer();
 
   const char *LastMatch = Buffer.data();
+  std::vector<StringRef> BufferStack;
 
   for (unsigned StrNo = 0, e = CheckStrings.size(); StrNo != e; ++StrNo) {
     const CheckString &CheckStr = CheckStrings[StrNo];
 
+    for (int i = CheckStr.PopPos; i; --i) {
+      if (BufferStack.empty()) {
+        SM.PrintMessage(CheckStr.PopLoc, SourceMgr::DK_Error,
+                        "attempting to '"+CheckPrefix+"-POP:' without previous '"+
+                        CheckPrefix+ "-PUSH:'");
+        return 1;
+      }
+      Buffer= BufferStack.back();
+      BufferStack.pop_back();
+    }
+
     StringRef SearchFrom = Buffer;
 
     // Find StrNo in the file.
@@ -756,6 +827,9 @@ int main(int argc, char **argv) {
     // the position after the match as the end of the last match.
     Buffer = Buffer.substr(MatchLen);
     LastMatch = Buffer.data();
+    for (int i= CheckStr.PushPos; i; --i) {
+      BufferStack.push_back(Buffer);
+    }
   }
 
   return 0;


More information about the llvm-dev mailing list