FileTestUtils.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. //===- FileTestUtils.cpp ---- Implementation of FileTestUtils -------------===//
  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 "FileTestUtils.h"
  10. #include <algorithm>
  11. #include <sstream>
  12. #include "SpirvTestOptions.h"
  13. #include "gtest/gtest.h"
  14. namespace clang {
  15. namespace spirv {
  16. namespace utils {
  17. bool disassembleSpirvBinary(std::vector<uint32_t> &binary,
  18. std::string *generatedSpirvAsm,
  19. bool generateHeader) {
  20. spvtools::SpirvTools spirvTools(SPV_ENV_VULKAN_1_0);
  21. spirvTools.SetMessageConsumer(
  22. [](spv_message_level_t, const char *, const spv_position_t &,
  23. const char *message) { fprintf(stdout, "%s\n", message); });
  24. uint32_t options = SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES;
  25. if (!generateHeader)
  26. options |= SPV_BINARY_TO_TEXT_OPTION_NO_HEADER;
  27. return spirvTools.Disassemble(binary, generatedSpirvAsm, options);
  28. }
  29. bool validateSpirvBinary(std::vector<uint32_t> &binary) {
  30. spvtools::SpirvTools spirvTools(SPV_ENV_VULKAN_1_0);
  31. spirvTools.SetMessageConsumer(
  32. [](spv_message_level_t, const char *, const spv_position_t &,
  33. const char *message) { fprintf(stdout, "%s\n", message); });
  34. return spirvTools.Validate(binary);
  35. }
  36. bool processRunCommandArgs(const llvm::StringRef runCommandLine,
  37. std::string *targetProfile, std::string *entryPoint,
  38. std::vector<std::string> *restArgs) {
  39. std::istringstream buf(runCommandLine);
  40. std::istream_iterator<std::string> start(buf), end;
  41. std::vector<std::string> tokens(start, end);
  42. if (tokens.size() < 3 || tokens[1].find("Run") == std::string::npos ||
  43. tokens[2].find("%dxc") == std::string::npos) {
  44. fprintf(stderr, "The only supported format is: \"// Run: %%dxc -T "
  45. "<profile> -E <entry>\"\n");
  46. return false;
  47. }
  48. std::ostringstream rest;
  49. for (uint32_t i = 3; i < tokens.size(); ++i) {
  50. if (tokens[i] == "-T" && (++i) < tokens.size())
  51. *targetProfile = tokens[i];
  52. else if (tokens[i] == "-E" && (++i) < tokens.size())
  53. *entryPoint = tokens[i];
  54. else
  55. restArgs->push_back(tokens[i]);
  56. }
  57. if (targetProfile->empty()) {
  58. fprintf(stderr, "Error: Missing target profile argument (-T).\n");
  59. return false;
  60. }
  61. if (entryPoint->empty()) {
  62. fprintf(stderr, "Error: Missing entry point argument (-E).\n");
  63. return false;
  64. }
  65. return true;
  66. }
  67. void convertIDxcBlobToUint32(const CComPtr<IDxcBlob> &blob,
  68. std::vector<uint32_t> *binaryWords) {
  69. size_t num32BitWords = (blob->GetBufferSize() + 3) / 4;
  70. std::string binaryStr((char *)blob->GetBufferPointer(),
  71. blob->GetBufferSize());
  72. binaryStr.resize(num32BitWords * 4, 0);
  73. binaryWords->resize(num32BitWords, 0);
  74. memcpy(binaryWords->data(), binaryStr.data(), binaryStr.size());
  75. }
  76. std::string getAbsPathOfInputDataFile(const llvm::StringRef filename) {
  77. std::string path = clang::spirv::testOptions::inputDataDir;
  78. #ifdef _WIN32
  79. const char sep = '\\';
  80. std::replace(path.begin(), path.end(), '/', '\\');
  81. #else
  82. const char sep = '/';
  83. #endif
  84. if (path[path.size() - 1] != sep) {
  85. path = path + sep;
  86. }
  87. path += filename;
  88. return path;
  89. }
  90. bool runCompilerWithSpirvGeneration(const llvm::StringRef inputFilePath,
  91. const llvm::StringRef entryPoint,
  92. const llvm::StringRef targetProfile,
  93. const std::vector<std::string> &restArgs,
  94. std::vector<uint32_t> *generatedBinary,
  95. std::string *errorMessages) {
  96. std::wstring srcFile(inputFilePath.begin(), inputFilePath.end());
  97. std::wstring entry(entryPoint.begin(), entryPoint.end());
  98. std::wstring profile(targetProfile.begin(), targetProfile.end());
  99. std::vector<std::wstring> rest;
  100. for (const auto &arg : restArgs)
  101. rest.emplace_back(arg.begin(), arg.end());
  102. bool success = true;
  103. try {
  104. dxc::DxcDllSupport dllSupport;
  105. IFT(dllSupport.Initialize());
  106. CComPtr<IDxcLibrary> pLibrary;
  107. CComPtr<IDxcCompiler> pCompiler;
  108. CComPtr<IDxcOperationResult> pResult;
  109. CComPtr<IDxcBlobEncoding> pSource;
  110. CComPtr<IDxcBlobEncoding> pErrorBuffer;
  111. CComPtr<IDxcBlob> pCompiledBlob;
  112. CComPtr<IDxcIncludeHandler> pIncludeHandler;
  113. HRESULT resultStatus;
  114. std::vector<LPCWSTR> flags;
  115. flags.push_back(L"-E");
  116. flags.push_back(entry.c_str());
  117. flags.push_back(L"-T");
  118. flags.push_back(profile.c_str());
  119. flags.push_back(L"-spirv");
  120. flags.push_back(L"-fcgl"); // Disable legalization for testing
  121. flags.push_back(L"-O0"); // Disable optimization for testing
  122. for (const auto &arg : rest)
  123. flags.push_back(arg.c_str());
  124. IFT(dllSupport.CreateInstance(CLSID_DxcLibrary, &pLibrary));
  125. IFT(pLibrary->CreateBlobFromFile(srcFile.c_str(), nullptr, &pSource));
  126. IFT(pLibrary->CreateIncludeHandler(&pIncludeHandler));
  127. IFT(dllSupport.CreateInstance(CLSID_DxcCompiler, &pCompiler));
  128. IFT(pCompiler->Compile(pSource, srcFile.c_str(), entry.c_str(),
  129. profile.c_str(), flags.data(), flags.size(), nullptr,
  130. 0, pIncludeHandler, &pResult));
  131. // Get compilation results.
  132. IFT(pResult->GetStatus(&resultStatus));
  133. // Get diagnostics string and print warnings and errors to stderr.
  134. IFT(pResult->GetErrorBuffer(&pErrorBuffer));
  135. const std::string diagnostics((char *)pErrorBuffer->GetBufferPointer(),
  136. pErrorBuffer->GetBufferSize());
  137. fprintf(stderr, "%s\n", diagnostics.c_str());
  138. *errorMessages = diagnostics;
  139. if (SUCCEEDED(resultStatus)) {
  140. CComPtr<IDxcBlobEncoding> pStdErr;
  141. IFT(pResult->GetResult(&pCompiledBlob));
  142. convertIDxcBlobToUint32(pCompiledBlob, generatedBinary);
  143. success = true;
  144. } else {
  145. success = false;
  146. }
  147. } catch (...) {
  148. // An exception has occured while running the compiler with SPIR-V
  149. // Generation
  150. success = false;
  151. }
  152. return success;
  153. }
  154. } // end namespace utils
  155. } // end namespace spirv
  156. } // end namespace clang