FileTestFixture.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. //===- FileTestFixture.cpp ------------- File Test Fixture Implementation -===//
  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. #include "FileTestFixture.h"
  10. #include <fstream>
  11. #include "FileTestUtils.h"
  12. #include "effcee/effcee.h"
  13. namespace clang {
  14. namespace spirv {
  15. bool FileTest::parseInputFile() {
  16. const char hlslStartLabel[] = "// Run:";
  17. std::stringstream inputSS;
  18. std::ifstream inputFile;
  19. inputFile.exceptions(std::ifstream::failbit);
  20. try {
  21. inputFile.open(inputFilePath);
  22. inputSS << inputFile.rdbuf();
  23. } catch (...) {
  24. fprintf(
  25. stderr,
  26. "Error: Exception occurred while opening/reading the input file %s\n",
  27. inputFilePath.c_str());
  28. return false;
  29. }
  30. // Close the input file.
  31. inputFile.close();
  32. // Effcee skips any input line which doesn't have a CHECK directive, therefore
  33. // we can pass the entire input to effcee. This way, any warning/error message
  34. // provided by effcee also reflects the correct line number in the input file.
  35. checkCommands = inputSS.str();
  36. const auto runCmdStartPos = checkCommands.find(hlslStartLabel);
  37. if (runCmdStartPos != std::string::npos) {
  38. const auto runCmdEndPos = checkCommands.find('\n', runCmdStartPos);
  39. const auto runCommand = checkCommands.substr(runCmdStartPos, runCmdEndPos);
  40. if (!utils::processRunCommandArgs(runCommand, &targetProfile, &entryPoint,
  41. &restArgs)) {
  42. // An error has occured when parsing the Run command.
  43. return false;
  44. }
  45. } else {
  46. fprintf(stderr, "Error: Missing \"Run:\" command.\n");
  47. return false;
  48. }
  49. // Everything was successful.
  50. return true;
  51. }
  52. void FileTest::runFileTest(llvm::StringRef filename, Expect expect,
  53. bool runValidation, bool relaxLogicalPointer) {
  54. if (relaxLogicalPointer)
  55. assert(runValidation);
  56. inputFilePath = utils::getAbsPathOfInputDataFile(filename);
  57. // Parse the input file.
  58. ASSERT_TRUE(parseInputFile());
  59. std::string errorMessages;
  60. // Feed the HLSL source into the Compiler.
  61. const bool compileOk = utils::runCompilerWithSpirvGeneration(
  62. inputFilePath, entryPoint, targetProfile, restArgs, &generatedBinary,
  63. &errorMessages);
  64. effcee::Result result(effcee::Result::Status::Ok);
  65. if (expect == Expect::Success) {
  66. ASSERT_TRUE(compileOk);
  67. // Disassemble the generated SPIR-V binary.
  68. ASSERT_TRUE(utils::disassembleSpirvBinary(
  69. generatedBinary, &generatedSpirvAsm, true /* generateHeader */));
  70. auto options = effcee::Options()
  71. .SetChecksName(filename.str())
  72. .SetInputName("<codegen>");
  73. // Run CHECK commands via effcee on disassembly.
  74. result = effcee::Match(generatedSpirvAsm, checkCommands, options);
  75. } else if (expect == Expect::Warning) {
  76. ASSERT_TRUE(compileOk);
  77. // Still check that we can disassemble the generated SPIR-V binary.
  78. ASSERT_TRUE(utils::disassembleSpirvBinary(
  79. generatedBinary, &generatedSpirvAsm, true /* generateHeader */));
  80. auto options = effcee::Options()
  81. .SetChecksName(filename.str())
  82. .SetInputName("<message>");
  83. // Run CHECK commands via effcee on warning messages.
  84. result = effcee::Match(errorMessages, checkCommands, options);
  85. } else {
  86. ASSERT_FALSE(compileOk);
  87. auto options = effcee::Options()
  88. .SetChecksName(filename.str())
  89. .SetInputName("<message>");
  90. // Run CHECK commands via effcee on error messages.
  91. result = effcee::Match(errorMessages, checkCommands, options);
  92. }
  93. // Print effcee's error message (if any).
  94. if (result.status() != effcee::Result::Status::Ok) {
  95. fprintf(stderr, "%s\n", result.message().c_str());
  96. }
  97. // All checks must have passed.
  98. ASSERT_EQ(result.status(), effcee::Result::Status::Ok);
  99. // Run SPIR-V validation for successful compilations
  100. if (runValidation && expect != Expect::Failure) {
  101. EXPECT_TRUE(utils::validateSpirvBinary(targetEnv, generatedBinary,
  102. relaxLogicalPointer));
  103. }
  104. }
  105. } // end namespace spirv
  106. } // end namespace clang