浏览代码

Add support for check prefixes and multiple RUN lines in file checker (#2452)

* Fixed encoding to UTF8

* Support prefixes and multiple runlines in FileChecker

* Use min size for memcpy

* CR comment
Vishal Sharma 6 年之前
父节点
当前提交
4a4004523f

+ 1 - 1
tools/clang/test/CodeGenHLSL/batch/expressions/intrinsics/misc/abs1.hlsl

@@ -1,4 +1,4 @@
-// RUN: %dxc -E main -T ps_6_0 -fcgl %s | FileCheck %s
+// RUN: %dxc -E main -T ps_6_0 -fcgl %s | FileCheck %s
 
 // CHECK: main
 // After lowering, these would turn into multiple abs calls rather than a 4 x float

+ 11 - 39
tools/clang/unittests/HLSL/FileCheckerTest.cpp

@@ -43,43 +43,6 @@
 using namespace std;
 using namespace hlsl_test;
 
-static constexpr char whitespaceChars[] = " \t\r\n";
-
-static std::string strltrim(const std::string &value) {
-  size_t first = value.find_first_not_of(whitespaceChars);
-  return first == string::npos ? value : value.substr(first);
-}
-
-static std::string strrtrim(const std::string &value) {
-  size_t last = value.find_last_not_of(whitespaceChars);
-  return last == string::npos ? value : value.substr(0, last + 1);
-}
-
-static std::string strtrim(const std::string &value) {
-  return strltrim(strrtrim(value));
-}
-
-static bool strstartswith(const std::string& value, const char* pattern) {
-  for (size_t i = 0; ; ++i) {
-    if (pattern[i] == '\0') return true;
-    if (i == value.size() || value[i] != pattern[i]) return false;
-  }
-}
-
-static std::vector<std::string> strtok(const std::string &value, const char *delimiters = whitespaceChars) {
-  size_t searchOffset = 0;
-  std::vector<std::string> tokens;
-  while (searchOffset != value.size()) {
-    size_t tokenStartIndex = value.find_first_not_of(delimiters, searchOffset);
-    if (tokenStartIndex == std::string::npos) break;
-    size_t tokenEndIndex = value.find_first_of(delimiters, tokenStartIndex);
-    if (tokenEndIndex == std::string::npos) tokenEndIndex = value.size();
-    tokens.emplace_back(value.substr(tokenStartIndex, tokenEndIndex - tokenStartIndex));
-    searchOffset = tokenEndIndex;
-  }
-  return tokens;
-}
-
 FileRunCommandPart::FileRunCommandPart(const std::string &command, const std::string &arguments, LPCWSTR commandFileName) :
   Command(command), Arguments(arguments), CommandFileName(commandFileName) { }
 
@@ -149,12 +112,18 @@ FileRunCommandResult FileRunCommandPart::RunFileChecker(const FileRunCommandResu
 
   // Parse command arguments
   static constexpr char checkPrefixStr[] = "-check-prefix=";
+  static constexpr char checkPrefixesStr[] = "-check-prefixes=";
   bool hasInputFilename = false;
   for (const std::string& arg : strtok(Arguments)) {
     if (arg == "%s") hasInputFilename = true;
     else if (arg == "-input=stderr") t.InputForStdin = Prior->StdErr;
     else if (strstartswith(arg, checkPrefixStr))
       t.CheckPrefixes.emplace_back(arg.substr(sizeof(checkPrefixStr) - 1));
+    else if (strstartswith(arg, checkPrefixesStr)) {
+      auto prefixes = strtok(arg.substr(sizeof(checkPrefixesStr) - 1), ", ");
+      for (auto &prefix : prefixes)
+        t.CheckPrefixes.emplace_back(prefix);
+    }
     else return FileRunCommandResult::Error("Invalid argument");
   }
   if (!hasInputFilename) return FileRunCommandResult::Error("Missing input filename");
@@ -749,8 +718,11 @@ public:
   FileRunTestResultImpl(dxc::DxcDllSupport &support) : m_support(support) {}
   void RunFileCheckFromFileCommands(LPCWSTR fileName) {
     // Assume UTF-8 files.
-    std::string commands(GetFirstLine(fileName));
-    return RunFileCheckFromCommands(commands.c_str(), fileName);
+    auto cmds = GetRunLines(fileName);
+    // Iterate over all RUN lines
+    for (auto &cmd : cmds) {
+      RunFileCheckFromCommands(cmd.c_str(), fileName);
+    }
   }
 
   void RunHashTestFromFileCommands(LPCWSTR fileName) {

+ 78 - 0
tools/clang/unittests/HLSL/HlslTestUtils.h

@@ -13,6 +13,8 @@
 #include <fstream>
 #include <atomic>
 #include <cmath>
+#include <vector>
+#include <algorithm>
 #ifdef _WIN32
 #include <dxgiformat.h>
 #include "WexTestClass.h"
@@ -22,6 +24,8 @@
 #include "dxc/Support/Unicode.h"
 #include "dxc/DXIL/DxilConstants.h" // DenormMode
 
+using namespace std;
+
 #ifndef HLSLDATAFILEPARAM
 #define HLSLDATAFILEPARAM L"HlslDataDir"
 #endif
@@ -74,6 +78,43 @@
 #endif 
 #endif // VERIFY_ARE_EQUAL
 
+static constexpr char whitespaceChars[] = " \t\r\n";
+
+static std::string strltrim(const std::string &value) {
+  size_t first = value.find_first_not_of(whitespaceChars);
+  return first == string::npos ? value : value.substr(first);
+}
+
+static std::string strrtrim(const std::string &value) {
+  size_t last = value.find_last_not_of(whitespaceChars);
+  return last == string::npos ? value : value.substr(0, last + 1);
+}
+
+static std::string strtrim(const std::string &value) {
+  return strltrim(strrtrim(value));
+}
+
+static bool strstartswith(const std::string& value, const char* pattern) {
+  for (size_t i = 0; ; ++i) {
+    if (pattern[i] == '\0') return true;
+    if (i == value.size() || value[i] != pattern[i]) return false;
+  }
+}
+
+static std::vector<std::string> strtok(const std::string &value, const char *delimiters = whitespaceChars) {
+  size_t searchOffset = 0;
+  std::vector<std::string> tokens;
+  while (searchOffset != value.size()) {
+    size_t tokenStartIndex = value.find_first_not_of(delimiters, searchOffset);
+    if (tokenStartIndex == std::string::npos) break;
+    size_t tokenEndIndex = value.find_first_of(delimiters, tokenStartIndex);
+    if (tokenEndIndex == std::string::npos) tokenEndIndex = value.size();
+    tokens.emplace_back(value.substr(tokenStartIndex, tokenEndIndex - tokenStartIndex));
+    searchOffset = tokenEndIndex;
+  }
+  return tokens;
+}
+
 namespace hlsl_test {
 
 inline std::wstring
@@ -138,6 +179,43 @@ inline bool PathLooksAbsolute(LPCWSTR name) {
 #endif
 }
 
+static bool HasRunLine(std::string &line) {
+  const char *delimiters = " ;/";
+  auto lineelems = strtok(line, delimiters);
+  return !lineelems.empty() &&
+    lineelems.front().compare("RUN:") == 0;
+}
+
+inline std::vector<std::string> GetRunLines(const LPCWSTR name) {
+  const std::wstring path = PathLooksAbsolute(name)
+    ? std::wstring(name)
+    : hlsl_test::GetPathToHlslDataFile(name);
+#ifdef _WIN32
+  std::ifstream infile(path);
+#else
+  std::ifstream infile((CW2A(path.c_str())));
+#endif
+  if (infile.bad()) {
+    std::wstring errMsg(L"Unable to read file ");
+    errMsg += path;
+    WEX::Logging::Log::Error(errMsg.c_str());
+    VERIFY_FAIL();
+  }
+
+  std::vector<std::string> runlines;
+  std::string line;
+  constexpr size_t runlinesize = 300;
+  while (std::getline(infile, line)) {
+    if (!HasRunLine(line))
+      continue;
+    char runline[runlinesize];
+    memset(runline, 0, runlinesize);
+    memcpy(runline, line.c_str(), min(runlinesize, line.size()));
+    runlines.emplace_back(runline);
+  }
+  return runlines;
+}
+
 inline std::string GetFirstLine(LPCWSTR name) {
   char firstLine[300];
   memset(firstLine, 0, sizeof(firstLine));