LinkerTest.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // LinkerTest.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. // //
  9. ///////////////////////////////////////////////////////////////////////////////
  10. #include <memory>
  11. #include <vector>
  12. #include <string>
  13. #include "llvm/ADT/ArrayRef.h"
  14. #include "CompilationResult.h"
  15. #include "HLSLTestData.h"
  16. #include "llvm/Support/ManagedStatic.h"
  17. #include <fstream>
  18. #include "WexTestClass.h"
  19. #include "HlslTestUtils.h"
  20. #include "dxc/dxcapi.h"
  21. #include "DxcTestUtils.h"
  22. using namespace std;
  23. using namespace hlsl;
  24. using namespace llvm;
  25. // The test fixture.
  26. class LinkerTest
  27. {
  28. public:
  29. BEGIN_TEST_CLASS(LinkerTest)
  30. TEST_CLASS_PROPERTY(L"Parallel", L"true")
  31. TEST_METHOD_PROPERTY(L"Priority", L"0")
  32. END_TEST_CLASS()
  33. TEST_CLASS_SETUP(InitSupport);
  34. TEST_METHOD(RunLinkResource);
  35. TEST_METHOD(RunLinkAllProfiles);
  36. TEST_METHOD(RunLinkFailNoDefine);
  37. TEST_METHOD(RunLinkFailReDefine);
  38. TEST_METHOD(RunLinkGlobalInit);
  39. TEST_METHOD(RunLinkNoAlloca);
  40. TEST_METHOD(RunLinkFailReDefineGlobal);
  41. TEST_METHOD(RunLinkFailProfileMismatch);
  42. TEST_METHOD(RunLinkFailEntryNoProps);
  43. TEST_METHOD(RunLinkFailSelectRes);
  44. dxc::DxcDllSupport m_dllSupport;
  45. VersionSupportInfo m_ver;
  46. void CreateLinker(IDxcLinker **pResultLinker) {
  47. VERIFY_SUCCEEDED(
  48. m_dllSupport.CreateInstance(CLSID_DxcLinker, pResultLinker));
  49. }
  50. void CompileLib(LPCWSTR filename, IDxcBlob **pResultBlob) {
  51. std::wstring fullPath = hlsl_test::GetPathToHlslDataFile(filename);
  52. CComPtr<IDxcBlobEncoding> pSource;
  53. CComPtr<IDxcLibrary> pLibrary;
  54. VERIFY_SUCCEEDED(m_dllSupport.CreateInstance(CLSID_DxcLibrary, &pLibrary));
  55. VERIFY_SUCCEEDED(
  56. pLibrary->CreateBlobFromFile(fullPath.c_str(), nullptr, &pSource));
  57. CComPtr<IDxcCompiler> pCompiler;
  58. CComPtr<IDxcOperationResult> pResult;
  59. CComPtr<IDxcBlob> pProgram;
  60. CA2W shWide("lib_6_1", CP_UTF8);
  61. VERIFY_SUCCEEDED(
  62. m_dllSupport.CreateInstance(CLSID_DxcCompiler, &pCompiler));
  63. VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"hlsl.hlsl", L"", shWide,
  64. nullptr, 0, nullptr, 0, nullptr,
  65. &pResult));
  66. VERIFY_SUCCEEDED(pResult->GetResult(pResultBlob));
  67. }
  68. void RegisterDxcModule(LPCWSTR pLibName, IDxcBlob *pBlob,
  69. IDxcLinker *pLinker) {
  70. VERIFY_SUCCEEDED(pLinker->RegisterLibrary(pLibName, pBlob));
  71. }
  72. void Link(LPCWSTR pEntryName, LPCWSTR pShaderModel, IDxcLinker *pLinker,
  73. ArrayRef<LPCWSTR> libNames, llvm::ArrayRef<LPCSTR> pCheckMsgs,
  74. llvm::ArrayRef<LPCSTR> pCheckNotMsgs) {
  75. CComPtr<IDxcOperationResult> pResult;
  76. VERIFY_SUCCEEDED(pLinker->Link(pEntryName, pShaderModel, libNames.data(),
  77. libNames.size(), nullptr, 0, &pResult));
  78. CComPtr<IDxcBlob> pProgram;
  79. CheckOperationSucceeded(pResult, &pProgram);
  80. CComPtr<IDxcCompiler> pCompiler;
  81. CComPtr<IDxcBlobEncoding> pDisassembly;
  82. VERIFY_SUCCEEDED(
  83. m_dllSupport.CreateInstance(CLSID_DxcCompiler, &pCompiler));
  84. VERIFY_SUCCEEDED(pCompiler->Disassemble(pProgram, &pDisassembly));
  85. std::string IR = BlobToUtf8(pDisassembly);
  86. CheckMsgs(IR.c_str(), IR.size(), pCheckMsgs.data(), pCheckMsgs.size(), false);
  87. for (auto notMsg : pCheckNotMsgs) {
  88. VERIFY_IS_TRUE(IR.find(notMsg) == std::string::npos);
  89. }
  90. }
  91. void LinkCheckMsg(LPCWSTR pEntryName, LPCWSTR pShaderModel, IDxcLinker *pLinker,
  92. ArrayRef<LPCWSTR> libNames, llvm::ArrayRef<LPCSTR> pErrorMsgs) {
  93. CComPtr<IDxcOperationResult> pResult;
  94. VERIFY_SUCCEEDED(pLinker->Link(pEntryName, pShaderModel, libNames.data(),
  95. libNames.size(), nullptr, 0, &pResult));
  96. CheckOperationResultMsgs(pResult, pErrorMsgs.data(), pErrorMsgs.size(),
  97. false, false);
  98. }
  99. };
  100. bool LinkerTest::InitSupport() {
  101. if (!m_dllSupport.IsEnabled()) {
  102. VERIFY_SUCCEEDED(m_dllSupport.Initialize());
  103. m_ver.Initialize(m_dllSupport);
  104. }
  105. return true;
  106. }
  107. TEST_F(LinkerTest, RunLinkResource) {
  108. CComPtr<IDxcBlob> pResLib;
  109. CompileLib(L"..\\CodeGenHLSL\\lib_resource2.hlsl", &pResLib);
  110. CComPtr<IDxcBlob> pEntryLib;
  111. CompileLib(L"..\\CodeGenHLSL\\lib_cs_entry.hlsl", &pEntryLib);
  112. CComPtr<IDxcLinker> pLinker;
  113. CreateLinker(&pLinker);
  114. LPCWSTR libName = L"entry";
  115. RegisterDxcModule(libName, pEntryLib, pLinker);
  116. LPCWSTR libResName = L"res";
  117. RegisterDxcModule(libResName, pResLib, pLinker);
  118. Link(L"entry", L"cs_6_0", pLinker, {libResName, libName}, {} ,{});
  119. }
  120. TEST_F(LinkerTest, RunLinkAllProfiles) {
  121. CComPtr<IDxcLinker> pLinker;
  122. CreateLinker(&pLinker);
  123. LPCWSTR libName = L"entry";
  124. CComPtr<IDxcBlob> pEntryLib;
  125. CompileLib(L"..\\CodeGenHLSL\\lib_entries2.hlsl", &pEntryLib);
  126. RegisterDxcModule(libName, pEntryLib, pLinker);
  127. Link(L"vs_main", L"vs_6_0", pLinker, {libName}, {},{});
  128. Link(L"hs_main", L"hs_6_0", pLinker, {libName}, {},{});
  129. Link(L"ds_main", L"ds_6_0", pLinker, {libName}, {},{});
  130. Link(L"gs_main", L"gs_6_0", pLinker, {libName}, {},{});
  131. Link(L"ps_main", L"ps_6_0", pLinker, {libName}, {},{});
  132. CComPtr<IDxcBlob> pResLib;
  133. CompileLib(L"..\\CodeGenHLSL\\lib_resource2.hlsl", &pResLib);
  134. LPCWSTR libResName = L"res";
  135. RegisterDxcModule(libResName, pResLib, pLinker);
  136. Link(L"cs_main", L"cs_6_0", pLinker, {libName, libResName}, {},{});
  137. }
  138. TEST_F(LinkerTest, RunLinkFailNoDefine) {
  139. CComPtr<IDxcBlob> pEntryLib;
  140. CompileLib(L"..\\CodeGenHLSL\\lib_cs_entry.hlsl", &pEntryLib);
  141. CComPtr<IDxcLinker> pLinker;
  142. CreateLinker(&pLinker);
  143. LPCWSTR libName = L"entry";
  144. RegisterDxcModule(libName, pEntryLib, pLinker);
  145. LinkCheckMsg(L"entry", L"cs_6_0", pLinker, {libName},
  146. {"Cannot find definition of function"});
  147. }
  148. TEST_F(LinkerTest, RunLinkFailReDefine) {
  149. CComPtr<IDxcBlob> pEntryLib;
  150. CompileLib(L"..\\CodeGenHLSL\\lib_cs_entry.hlsl", &pEntryLib);
  151. CComPtr<IDxcLinker> pLinker;
  152. CreateLinker(&pLinker);
  153. LPCWSTR libName = L"entry";
  154. RegisterDxcModule(libName, pEntryLib, pLinker);
  155. LPCWSTR libName2 = L"entry2";
  156. RegisterDxcModule(libName2, pEntryLib, pLinker);
  157. LinkCheckMsg(L"entry", L"cs_6_0", pLinker, {libName, libName2},
  158. {"Definition already exists for function"});
  159. }
  160. TEST_F(LinkerTest, RunLinkGlobalInit) {
  161. CComPtr<IDxcBlob> pEntryLib;
  162. CompileLib(L"..\\CodeGenHLSL\\lib_global.hlsl", &pEntryLib);
  163. CComPtr<IDxcLinker> pLinker;
  164. CreateLinker(&pLinker);
  165. LPCWSTR libName = L"entry";
  166. RegisterDxcModule(libName, pEntryLib, pLinker);
  167. Link(L"test", L"ps_6_0", pLinker, {libName},
  168. // Make sure cbuffer load is generated.
  169. {"dx.op.cbufferLoad"},{});
  170. }
  171. TEST_F(LinkerTest, RunLinkFailReDefineGlobal) {
  172. CComPtr<IDxcBlob> pEntryLib;
  173. CompileLib(L"..\\CodeGenHLSL\\lib_global2.hlsl", &pEntryLib);
  174. CComPtr<IDxcBlob> pLib0;
  175. CompileLib(L"..\\CodeGenHLSL\\lib_global3.hlsl", &pLib0);
  176. CComPtr<IDxcBlob> pLib1;
  177. CompileLib(L"..\\CodeGenHLSL\\lib_global4.hlsl", &pLib1);
  178. CComPtr<IDxcLinker> pLinker;
  179. CreateLinker(&pLinker);
  180. LPCWSTR libName = L"entry";
  181. RegisterDxcModule(libName, pEntryLib, pLinker);
  182. LPCWSTR libName1 = L"lib0";
  183. RegisterDxcModule(libName1, pLib0, pLinker);
  184. LPCWSTR libName2 = L"lib1";
  185. RegisterDxcModule(libName2, pLib1, pLinker);
  186. LinkCheckMsg(L"entry", L"cs_6_0", pLinker, {libName, libName1, libName2},
  187. {"Definition already exists for global variable", "Resource already exists"});
  188. }
  189. TEST_F(LinkerTest, RunLinkFailProfileMismatch) {
  190. CComPtr<IDxcBlob> pEntryLib;
  191. CompileLib(L"..\\CodeGenHLSL\\lib_global.hlsl", &pEntryLib);
  192. CComPtr<IDxcLinker> pLinker;
  193. CreateLinker(&pLinker);
  194. LPCWSTR libName = L"entry";
  195. RegisterDxcModule(libName, pEntryLib, pLinker);
  196. LinkCheckMsg(L"test", L"cs_6_0", pLinker, {libName},
  197. {"Profile mismatch between entry function and target profile"});
  198. }
  199. TEST_F(LinkerTest, RunLinkFailEntryNoProps) {
  200. CComPtr<IDxcBlob> pEntryLib;
  201. CompileLib(L"..\\CodeGenHLSL\\lib_global.hlsl", &pEntryLib);
  202. CComPtr<IDxcLinker> pLinker;
  203. CreateLinker(&pLinker);
  204. LPCWSTR libName = L"entry";
  205. RegisterDxcModule(libName, pEntryLib, pLinker);
  206. LinkCheckMsg(L"\01?update@@YAXXZ", L"cs_6_0", pLinker, {libName},
  207. {"Cannot find function property for entry function"});
  208. }
  209. TEST_F(LinkerTest, RunLinkNoAlloca) {
  210. CComPtr<IDxcBlob> pEntryLib;
  211. CompileLib(L"..\\CodeGenHLSL\\lib_no_alloca.hlsl", &pEntryLib);
  212. CComPtr<IDxcBlob> pLib;
  213. CompileLib(L"..\\CodeGenHLSL\\lib_no_alloca.h", &pLib);
  214. CComPtr<IDxcLinker> pLinker;
  215. CreateLinker(&pLinker);
  216. LPCWSTR libName = L"ps_main";
  217. RegisterDxcModule(libName, pEntryLib, pLinker);
  218. LPCWSTR libName2 = L"test";
  219. RegisterDxcModule(libName2, pLib, pLinker);
  220. Link(L"ps_main", L"ps_6_0", pLinker, {libName, libName2}, {}, {"alloca"});
  221. }
  222. TEST_F(LinkerTest, RunLinkFailSelectRes) {
  223. if (m_ver.SkipDxilVersion(1, 3)) return;
  224. CComPtr<IDxcBlob> pEntryLib;
  225. CompileLib(L"..\\CodeGenHLSL\\lib_select_res_entry.hlsl", &pEntryLib);
  226. CComPtr<IDxcBlob> pLib;
  227. CompileLib(L"..\\CodeGenHLSL\\lib_select_res.hlsl", &pLib);
  228. CComPtr<IDxcLinker> pLinker;
  229. CreateLinker(&pLinker);
  230. LPCWSTR libName = L"main";
  231. RegisterDxcModule(libName, pEntryLib, pLinker);
  232. LPCWSTR libName2 = L"test";
  233. RegisterDxcModule(libName2, pLib, pLinker);
  234. LinkCheckMsg(L"main", L"ps_6_0", pLinker, {libName, libName2},
  235. {"Local resource must map to global resource"});
  236. }