dxl.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // dxl.cpp //
  4. // Copyright (C) Microsoft Corporation. All rights reserved. //
  5. // This file is distributed under the University of Illinois Open Source //
  6. // License. See LICENSE.TXT for details. //
  7. // //
  8. // Provides the entry point for the dxl console program. //
  9. // //
  10. ///////////////////////////////////////////////////////////////////////////////
  11. #include "dxc/Support/Global.h"
  12. #include "dxc/Support/Unicode.h"
  13. #include "dxc/Support/WinIncludes.h"
  14. #include "dxc/dxcapi.h"
  15. #include "dxc/Support/dxcapi.use.h"
  16. #include "dxc/Support/HLSLOptions.h"
  17. #include "dxc/HLSL/DxilContainer.h"
  18. #include "llvm/Support/CommandLine.h"
  19. #include "llvm/Support//MSFileSystem.h"
  20. #include "llvm/Support/FileSystem.h"
  21. #include <dia2.h>
  22. #include <intsafe.h>
  23. using namespace llvm;
  24. using namespace llvm::opt;
  25. using namespace dxc;
  26. using namespace hlsl::options;
  27. static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden);
  28. static cl::opt<std::string>
  29. InputFiles(cl::Positional, cl::desc("<input .lib files seperate with ;>"),
  30. cl::init(""));
  31. static cl::opt<std::string> EntryName("E", cl::desc("Entry function name"),
  32. cl::value_desc("entryfunction"),
  33. cl::init("main"));
  34. static cl::opt<std::string> TargetProfile("T", cl::desc("Target profile"),
  35. cl::value_desc("profile"),
  36. cl::init("ps_6_1"));
  37. static cl::opt<std::string> OutputFilename("Fo",
  38. cl::desc("Override output filename"),
  39. cl::value_desc("filename"));
  40. class DxlContext {
  41. private:
  42. DxcDllSupport &m_dxcSupport;
  43. template <typename TInterface>
  44. HRESULT CreateInstance(REFCLSID clsid, _Outptr_ TInterface **pResult) {
  45. return m_dxcSupport.CreateInstance(clsid, pResult);
  46. }
  47. public:
  48. DxlContext(DxcDllSupport &dxcSupport) : m_dxcSupport(dxcSupport) {}
  49. int Link();
  50. };
  51. int DxlContext::Link() {
  52. std::string entry = EntryName;
  53. std::string profile = TargetProfile;
  54. CComPtr<IDxcLinker> pLinker;
  55. IFT(CreateInstance(CLSID_DxcLinker, &pLinker));
  56. StringRef InputFilesRef(InputFiles);
  57. SmallVector<StringRef, 2> InputFileList;
  58. InputFilesRef.split(InputFileList, ";");
  59. std::vector<std::wstring> wInputFiles;
  60. wInputFiles.reserve(InputFileList.size());
  61. std::vector<LPCWSTR> wpInputFiles;
  62. wpInputFiles.reserve(InputFileList.size());
  63. for (auto &file : InputFileList) {
  64. wInputFiles.emplace_back(StringRefUtf16(file.str()));
  65. wpInputFiles.emplace_back(wInputFiles.back().c_str());
  66. CComPtr<IDxcBlobEncoding> pLib;
  67. ReadFileIntoBlob(m_dxcSupport, wInputFiles.back().c_str(), &pLib);
  68. IFT(pLinker->RegisterLibrary(wInputFiles.back().c_str(), pLib));
  69. }
  70. CComPtr<IDxcOperationResult> pLinkResult;
  71. IFT(pLinker->Link(StringRefUtf16(entry), StringRefUtf16(profile),
  72. wpInputFiles.data(), wpInputFiles.size(), nullptr, 0,
  73. &pLinkResult));
  74. HRESULT status;
  75. IFT(pLinkResult->GetStatus(&status));
  76. if (SUCCEEDED(status)) {
  77. CComPtr<IDxcBlob> pContainer;
  78. IFT(pLinkResult->GetResult(&pContainer));
  79. if (pContainer.p != nullptr) {
  80. // Infer the output filename if needed.
  81. if (OutputFilename.empty()) {
  82. OutputFilename = EntryName + ".dxbc";
  83. }
  84. WriteBlobToFile(pContainer, StringRefUtf16(OutputFilename));
  85. }
  86. } else {
  87. CComPtr<IDxcBlobEncoding> pErrors;
  88. IFT(pLinkResult->GetErrorBuffer(&pErrors));
  89. if (pErrors != nullptr) {
  90. printf("Link failed:\n%s",
  91. static_cast<char *>(pErrors->GetBufferPointer()));
  92. }
  93. }
  94. return status;
  95. }
  96. using namespace hlsl::options;
  97. int __cdecl main(int argc, _In_reads_z_(argc) char **argv) {
  98. const char *pStage = "Operation";
  99. int retVal = 0;
  100. if (llvm::sys::fs::SetupPerThreadFileSystem())
  101. return 1;
  102. llvm::sys::fs::AutoCleanupPerThreadFileSystem auto_cleanup_fs;
  103. if (FAILED(DxcInitThreadMalloc())) return 1;
  104. DxcSetThreadMallocOrDefault(nullptr);
  105. try {
  106. llvm::sys::fs::MSFileSystem *msfPtr;
  107. IFT(CreateMSFileSystemForDisk(&msfPtr));
  108. std::unique_ptr<::llvm::sys::fs::MSFileSystem> msf(msfPtr);
  109. ::llvm::sys::fs::AutoPerThreadSystem pts(msf.get());
  110. IFTLLVM(pts.error_code());
  111. pStage = "Argument processing";
  112. // Parse command line options.
  113. cl::ParseCommandLineOptions(argc, argv, "dxil linker\n");
  114. if (InputFiles == "" || Help) {
  115. cl::PrintHelpMessage();
  116. return 2;
  117. }
  118. DxcDllSupport dxcSupport;
  119. // Read options and check errors.
  120. dxc::EnsureEnabled(dxcSupport);
  121. DxlContext context(dxcSupport);
  122. pStage = "Linking";
  123. retVal = context.Link();
  124. } catch (const ::hlsl::Exception &hlslException) {
  125. try {
  126. const char *msg = hlslException.what();
  127. Unicode::acp_char printBuffer[128]; // printBuffer is safe to treat as
  128. // UTF-8 because we use ASCII only errors
  129. // only
  130. if (msg == nullptr || *msg == '\0') {
  131. sprintf_s(printBuffer, _countof(printBuffer),
  132. "Link failed - error code 0x%08x.", hlslException.hr);
  133. msg = printBuffer;
  134. }
  135. printf("%s\n", msg);
  136. } catch (...) {
  137. printf("%s failed - unable to retrieve error message.\n", pStage);
  138. }
  139. return 1;
  140. } catch (std::bad_alloc &) {
  141. printf("%s failed - out of memory.\n", pStage);
  142. return 1;
  143. } catch (...) {
  144. printf("%s failed - unknown error.\n", pStage);
  145. return 1;
  146. }
  147. return retVal;
  148. }