FileTestUtils.cpp 6.4 KB

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