LinkerTest.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664
  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(RunLinkMatArrayParam);
  41. TEST_METHOD(RunLinkMatParam);
  42. TEST_METHOD(RunLinkMatParamToLib);
  43. TEST_METHOD(RunLinkResRet);
  44. TEST_METHOD(RunLinkToLib);
  45. TEST_METHOD(RunLinkToLibExport);
  46. TEST_METHOD(RunLinkFailReDefineGlobal);
  47. TEST_METHOD(RunLinkFailProfileMismatch);
  48. TEST_METHOD(RunLinkFailEntryNoProps);
  49. TEST_METHOD(RunLinkFailSelectRes);
  50. TEST_METHOD(RunLinkToLibWithUnresolvedFunctions);
  51. TEST_METHOD(RunLinkToLibWithUnresolvedFunctionsExports);
  52. TEST_METHOD(RunLinkToLibWithExportNamesSwapped);
  53. TEST_METHOD(RunLinkToLibWithExportCollision);
  54. TEST_METHOD(RunLinkToLibWithUnusedExport);
  55. TEST_METHOD(RunLinkToLibWithNoExports);
  56. TEST_METHOD(RunLinkWithPotentialIntrinsicNameCollisions);
  57. TEST_METHOD(RunLinkWithValidatorVersion);
  58. dxc::DxcDllSupport m_dllSupport;
  59. VersionSupportInfo m_ver;
  60. void CreateLinker(IDxcLinker **pResultLinker) {
  61. VERIFY_SUCCEEDED(
  62. m_dllSupport.CreateInstance(CLSID_DxcLinker, pResultLinker));
  63. }
  64. void CompileLib(LPCWSTR filename, IDxcBlob **pResultBlob,
  65. llvm::ArrayRef<LPCWSTR> pArguments = {},
  66. LPCWSTR pShaderTarget = L"lib_6_x") {
  67. std::wstring fullPath = hlsl_test::GetPathToHlslDataFile(filename);
  68. CComPtr<IDxcBlobEncoding> pSource;
  69. CComPtr<IDxcLibrary> pLibrary;
  70. VERIFY_SUCCEEDED(m_dllSupport.CreateInstance(CLSID_DxcLibrary, &pLibrary));
  71. VERIFY_SUCCEEDED(
  72. pLibrary->CreateBlobFromFile(fullPath.c_str(), nullptr, &pSource));
  73. CComPtr<IDxcCompiler> pCompiler;
  74. CComPtr<IDxcOperationResult> pResult;
  75. CComPtr<IDxcBlob> pProgram;
  76. VERIFY_SUCCEEDED(
  77. m_dllSupport.CreateInstance(CLSID_DxcCompiler, &pCompiler));
  78. VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"hlsl.hlsl", L"", pShaderTarget,
  79. const_cast<LPCWSTR*>(pArguments.data()), pArguments.size(),
  80. nullptr, 0,
  81. nullptr, &pResult));
  82. VERIFY_SUCCEEDED(pResult->GetResult(pResultBlob));
  83. }
  84. void RegisterDxcModule(LPCWSTR pLibName, IDxcBlob *pBlob,
  85. IDxcLinker *pLinker) {
  86. VERIFY_SUCCEEDED(pLinker->RegisterLibrary(pLibName, pBlob));
  87. }
  88. void Link(LPCWSTR pEntryName, LPCWSTR pShaderModel, IDxcLinker *pLinker,
  89. ArrayRef<LPCWSTR> libNames, llvm::ArrayRef<LPCSTR> pCheckMsgs,
  90. llvm::ArrayRef<LPCSTR> pCheckNotMsgs,
  91. llvm::ArrayRef<LPCWSTR> pArguments = {},
  92. bool bRegEx = false) {
  93. CComPtr<IDxcOperationResult> pResult;
  94. VERIFY_SUCCEEDED(pLinker->Link(pEntryName, pShaderModel, libNames.data(),
  95. libNames.size(),
  96. pArguments.data(), pArguments.size(),
  97. &pResult));
  98. CComPtr<IDxcBlob> pProgram;
  99. CheckOperationSucceeded(pResult, &pProgram);
  100. CComPtr<IDxcCompiler> pCompiler;
  101. CComPtr<IDxcBlobEncoding> pDisassembly;
  102. VERIFY_SUCCEEDED(
  103. m_dllSupport.CreateInstance(CLSID_DxcCompiler, &pCompiler));
  104. VERIFY_SUCCEEDED(pCompiler->Disassemble(pProgram, &pDisassembly));
  105. std::string IR = BlobToUtf8(pDisassembly);
  106. CheckMsgs(IR.c_str(), IR.size(), pCheckMsgs.data(), pCheckMsgs.size(), bRegEx);
  107. CheckNotMsgs(IR.c_str(), IR.size(), pCheckNotMsgs.data(), pCheckNotMsgs.size(), bRegEx);
  108. }
  109. void LinkCheckMsg(LPCWSTR pEntryName, LPCWSTR pShaderModel, IDxcLinker *pLinker,
  110. ArrayRef<LPCWSTR> libNames, llvm::ArrayRef<LPCSTR> pErrorMsgs,
  111. llvm::ArrayRef<LPCWSTR> pArguments = {}) {
  112. CComPtr<IDxcOperationResult> pResult;
  113. VERIFY_SUCCEEDED(pLinker->Link(pEntryName, pShaderModel,
  114. libNames.data(), libNames.size(),
  115. pArguments.data(), pArguments.size(),
  116. &pResult));
  117. CheckOperationResultMsgs(pResult, pErrorMsgs.data(), pErrorMsgs.size(),
  118. false, false);
  119. }
  120. };
  121. bool LinkerTest::InitSupport() {
  122. if (!m_dllSupport.IsEnabled()) {
  123. VERIFY_SUCCEEDED(m_dllSupport.Initialize());
  124. m_ver.Initialize(m_dllSupport);
  125. }
  126. return true;
  127. }
  128. TEST_F(LinkerTest, RunLinkResource) {
  129. CComPtr<IDxcBlob> pResLib;
  130. CompileLib(L"..\\CodeGenHLSL\\lib_resource2.hlsl", &pResLib);
  131. CComPtr<IDxcBlob> pEntryLib;
  132. CompileLib(L"..\\CodeGenHLSL\\lib_cs_entry.hlsl", &pEntryLib);
  133. CComPtr<IDxcLinker> pLinker;
  134. CreateLinker(&pLinker);
  135. LPCWSTR libName = L"entry";
  136. RegisterDxcModule(libName, pEntryLib, pLinker);
  137. LPCWSTR libResName = L"res";
  138. RegisterDxcModule(libResName, pResLib, pLinker);
  139. Link(L"entry", L"cs_6_0", pLinker, {libResName, libName}, {} ,{});
  140. }
  141. TEST_F(LinkerTest, RunLinkAllProfiles) {
  142. CComPtr<IDxcLinker> pLinker;
  143. CreateLinker(&pLinker);
  144. LPCWSTR libName = L"entry";
  145. LPCWSTR option[] = { L"-Zi", L"-Qembed_debug" };
  146. CComPtr<IDxcBlob> pEntryLib;
  147. CompileLib(L"..\\CodeGenHLSL\\lib_entries2.hlsl", &pEntryLib, option);
  148. RegisterDxcModule(libName, pEntryLib, pLinker);
  149. Link(L"vs_main", L"vs_6_0", pLinker, {libName}, {},{});
  150. Link(L"hs_main", L"hs_6_0", pLinker, {libName}, {},{});
  151. Link(L"ds_main", L"ds_6_0", pLinker, {libName}, {},{});
  152. Link(L"gs_main", L"gs_6_0", pLinker, {libName}, {},{});
  153. Link(L"ps_main", L"ps_6_0", pLinker, {libName}, {},{});
  154. CComPtr<IDxcBlob> pResLib;
  155. CompileLib(L"..\\CodeGenHLSL\\lib_resource2.hlsl", &pResLib);
  156. LPCWSTR libResName = L"res";
  157. RegisterDxcModule(libResName, pResLib, pLinker);
  158. Link(L"cs_main", L"cs_6_0", pLinker, {libName, libResName}, {},{});
  159. }
  160. TEST_F(LinkerTest, RunLinkFailNoDefine) {
  161. CComPtr<IDxcBlob> pEntryLib;
  162. CompileLib(L"..\\CodeGenHLSL\\lib_cs_entry.hlsl", &pEntryLib);
  163. CComPtr<IDxcLinker> pLinker;
  164. CreateLinker(&pLinker);
  165. LPCWSTR libName = L"entry";
  166. RegisterDxcModule(libName, pEntryLib, pLinker);
  167. LinkCheckMsg(L"entry", L"cs_6_0", pLinker, {libName},
  168. {"Cannot find definition of function"});
  169. }
  170. TEST_F(LinkerTest, RunLinkFailReDefine) {
  171. CComPtr<IDxcBlob> pEntryLib;
  172. CompileLib(L"..\\CodeGenHLSL\\lib_cs_entry.hlsl", &pEntryLib);
  173. CComPtr<IDxcLinker> pLinker;
  174. CreateLinker(&pLinker);
  175. LPCWSTR libName = L"entry";
  176. RegisterDxcModule(libName, pEntryLib, pLinker);
  177. LPCWSTR libName2 = L"entry2";
  178. RegisterDxcModule(libName2, pEntryLib, pLinker);
  179. LinkCheckMsg(L"entry", L"cs_6_0", pLinker, {libName, libName2},
  180. {"Definition already exists for function"});
  181. }
  182. TEST_F(LinkerTest, RunLinkGlobalInit) {
  183. CComPtr<IDxcBlob> pEntryLib;
  184. CompileLib(L"..\\CodeGenHLSL\\lib_global.hlsl", &pEntryLib, {}, L"lib_6_3");
  185. CComPtr<IDxcLinker> pLinker;
  186. CreateLinker(&pLinker);
  187. LPCWSTR libName = L"entry";
  188. RegisterDxcModule(libName, pEntryLib, pLinker);
  189. Link(L"test", L"ps_6_0", pLinker, {libName},
  190. // Make sure cbuffer load is generated.
  191. {"dx.op.cbufferLoad"},{});
  192. }
  193. TEST_F(LinkerTest, RunLinkFailReDefineGlobal) {
  194. CComPtr<IDxcBlob> pEntryLib;
  195. CompileLib(L"..\\CodeGenHLSL\\lib_global2.hlsl", &pEntryLib);
  196. CComPtr<IDxcBlob> pLib0;
  197. CompileLib(L"..\\CodeGenHLSL\\lib_global3.hlsl", &pLib0);
  198. CComPtr<IDxcBlob> pLib1;
  199. CompileLib(L"..\\CodeGenHLSL\\lib_global4.hlsl", &pLib1);
  200. CComPtr<IDxcLinker> pLinker;
  201. CreateLinker(&pLinker);
  202. LPCWSTR libName = L"entry";
  203. RegisterDxcModule(libName, pEntryLib, pLinker);
  204. LPCWSTR libName1 = L"lib0";
  205. RegisterDxcModule(libName1, pLib0, pLinker);
  206. LPCWSTR libName2 = L"lib1";
  207. RegisterDxcModule(libName2, pLib1, pLinker);
  208. LinkCheckMsg(L"entry", L"cs_6_0", pLinker, {libName, libName1, libName2},
  209. {"Definition already exists for global variable", "Resource already exists"});
  210. }
  211. TEST_F(LinkerTest, RunLinkFailProfileMismatch) {
  212. CComPtr<IDxcBlob> pEntryLib;
  213. CompileLib(L"..\\CodeGenHLSL\\lib_global.hlsl", &pEntryLib);
  214. CComPtr<IDxcLinker> pLinker;
  215. CreateLinker(&pLinker);
  216. LPCWSTR libName = L"entry";
  217. RegisterDxcModule(libName, pEntryLib, pLinker);
  218. LinkCheckMsg(L"test", L"cs_6_0", pLinker, {libName},
  219. {"Profile mismatch between entry function and target profile"});
  220. }
  221. TEST_F(LinkerTest, RunLinkFailEntryNoProps) {
  222. CComPtr<IDxcBlob> pEntryLib;
  223. CompileLib(L"..\\CodeGenHLSL\\lib_global.hlsl", &pEntryLib);
  224. CComPtr<IDxcLinker> pLinker;
  225. CreateLinker(&pLinker);
  226. LPCWSTR libName = L"entry";
  227. RegisterDxcModule(libName, pEntryLib, pLinker);
  228. LinkCheckMsg(L"\01?update@@YAXXZ", L"cs_6_0", pLinker, {libName},
  229. {"Cannot find function property for entry function"});
  230. }
  231. TEST_F(LinkerTest, RunLinkNoAlloca) {
  232. CComPtr<IDxcBlob> pEntryLib;
  233. CompileLib(L"..\\CodeGenHLSL\\lib_no_alloca.hlsl", &pEntryLib);
  234. CComPtr<IDxcBlob> pLib;
  235. CompileLib(L"..\\CodeGenHLSL\\lib_no_alloca.h", &pLib);
  236. CComPtr<IDxcLinker> pLinker;
  237. CreateLinker(&pLinker);
  238. LPCWSTR libName = L"ps_main";
  239. RegisterDxcModule(libName, pEntryLib, pLinker);
  240. LPCWSTR libName2 = L"test";
  241. RegisterDxcModule(libName2, pLib, pLinker);
  242. Link(L"ps_main", L"ps_6_0", pLinker, {libName, libName2}, {}, {"alloca"});
  243. }
  244. TEST_F(LinkerTest, RunLinkMatArrayParam) {
  245. CComPtr<IDxcBlob> pEntryLib;
  246. CompileLib(L"..\\CodeGenHLSL\\linker\\lib_mat_entry.hlsl", &pEntryLib);
  247. CComPtr<IDxcBlob> pLib;
  248. CompileLib(L"..\\CodeGenHLSL\\linker\\lib_mat_cast.hlsl", &pLib);
  249. CComPtr<IDxcLinker> pLinker;
  250. CreateLinker(&pLinker);
  251. LPCWSTR libName = L"ps_main";
  252. RegisterDxcModule(libName, pEntryLib, pLinker);
  253. LPCWSTR libName2 = L"test";
  254. RegisterDxcModule(libName2, pLib, pLinker);
  255. Link(L"main", L"ps_6_0", pLinker, {libName, libName2},
  256. {"alloca [24 x float]", "getelementptr [12 x float], [12 x float]*"},
  257. {});
  258. }
  259. TEST_F(LinkerTest, RunLinkMatParam) {
  260. CComPtr<IDxcBlob> pEntryLib;
  261. CompileLib(L"..\\CodeGenHLSL\\linker\\lib_mat_entry2.hlsl", &pEntryLib);
  262. CComPtr<IDxcBlob> pLib;
  263. CompileLib(L"..\\CodeGenHLSL\\linker\\lib_mat_cast2.hlsl", &pLib);
  264. CComPtr<IDxcLinker> pLinker;
  265. CreateLinker(&pLinker);
  266. LPCWSTR libName = L"ps_main";
  267. RegisterDxcModule(libName, pEntryLib, pLinker);
  268. LPCWSTR libName2 = L"test";
  269. RegisterDxcModule(libName2, pLib, pLinker);
  270. Link(L"main", L"ps_6_0", pLinker, {libName, libName2},
  271. {"alloca [12 x float]"},
  272. {});
  273. }
  274. TEST_F(LinkerTest, RunLinkMatParamToLib) {
  275. CComPtr<IDxcBlob> pEntryLib;
  276. CompileLib(L"..\\CodeGenHLSL\\linker\\lib_mat_entry2.hlsl", &pEntryLib);
  277. CComPtr<IDxcLinker> pLinker;
  278. CreateLinker(&pLinker);
  279. LPCWSTR libName = L"ps_main";
  280. RegisterDxcModule(libName, pEntryLib, pLinker);
  281. Link(L"", L"lib_6_3", pLinker, {libName},
  282. // The bitcast cannot be removed because user function call use it as
  283. // argument.
  284. {"bitcast <12 x float>\\* %.* to %class\\.matrix\\.float\\.4\\.3\\*"}, {}, {}, true);
  285. }
  286. TEST_F(LinkerTest, RunLinkResRet) {
  287. CComPtr<IDxcBlob> pEntryLib;
  288. CompileLib(L"..\\CodeGenHLSL\\linker\\lib_out_param_res.hlsl", &pEntryLib);
  289. CComPtr<IDxcBlob> pLib;
  290. CompileLib(L"..\\CodeGenHLSL\\linker\\lib_out_param_res_imp.hlsl", &pLib);
  291. CComPtr<IDxcLinker> pLinker;
  292. CreateLinker(&pLinker);
  293. LPCWSTR libName = L"ps_main";
  294. RegisterDxcModule(libName, pEntryLib, pLinker);
  295. LPCWSTR libName2 = L"test";
  296. RegisterDxcModule(libName2, pLib, pLinker);
  297. Link(L"test", L"ps_6_0", pLinker, {libName, libName2}, {}, {"alloca"});
  298. }
  299. TEST_F(LinkerTest, RunLinkToLib) {
  300. LPCWSTR option[] = {L"-Zi", L"-Qembed_debug"};
  301. CComPtr<IDxcBlob> pEntryLib;
  302. CompileLib(L"..\\CodeGenHLSL\\linker\\lib_mat_entry2.hlsl",
  303. &pEntryLib, option);
  304. CComPtr<IDxcBlob> pLib;
  305. CompileLib(
  306. L"..\\CodeGenHLSL\\linker\\lib_mat_cast2.hlsl",
  307. &pLib, option);
  308. CComPtr<IDxcLinker> pLinker;
  309. CreateLinker(&pLinker);
  310. LPCWSTR libName = L"ps_main";
  311. RegisterDxcModule(libName, pEntryLib, pLinker);
  312. LPCWSTR libName2 = L"test";
  313. RegisterDxcModule(libName2, pLib, pLinker);
  314. Link(L"", L"lib_6_3", pLinker, {libName, libName2}, {"!llvm.dbg.cu"}, {}, option);
  315. }
  316. TEST_F(LinkerTest, RunLinkToLibExport) {
  317. CComPtr<IDxcBlob> pEntryLib;
  318. CompileLib(L"..\\CodeGenHLSL\\linker\\lib_mat_entry2.hlsl",
  319. &pEntryLib);
  320. CComPtr<IDxcBlob> pLib;
  321. CompileLib(L"..\\CodeGenHLSL\\linker\\lib_mat_cast2.hlsl",
  322. &pLib);
  323. CComPtr<IDxcLinker> pLinker;
  324. CreateLinker(&pLinker);
  325. LPCWSTR libName = L"ps_main";
  326. RegisterDxcModule(libName, pEntryLib, pLinker);
  327. LPCWSTR libName2 = L"test";
  328. RegisterDxcModule(libName2, pLib, pLinker);
  329. Link(L"", L"lib_6_3", pLinker, {libName, libName2},
  330. { "@\"\\01?renamed_test@@","@\"\\01?cloned_test@@","@main" },
  331. { "@\"\\01?mat_test", "@renamed_test", "@cloned_test" },
  332. {L"-exports", L"renamed_test,cloned_test=\\01?mat_test@@YA?AV?$vector@M$02@@V?$vector@M$03@@0AIAV?$matrix@M$03$02@@@Z;main"});
  333. }
  334. TEST_F(LinkerTest, RunLinkFailSelectRes) {
  335. if (m_ver.SkipDxilVersion(1, 3)) return;
  336. CComPtr<IDxcBlob> pEntryLib;
  337. CompileLib(L"..\\CodeGenHLSL\\lib_select_res_entry.hlsl", &pEntryLib);
  338. CComPtr<IDxcBlob> pLib;
  339. CompileLib(L"..\\CodeGenHLSL\\lib_select_res.hlsl", &pLib);
  340. CComPtr<IDxcLinker> pLinker;
  341. CreateLinker(&pLinker);
  342. LPCWSTR libName = L"main";
  343. RegisterDxcModule(libName, pEntryLib, pLinker);
  344. LPCWSTR libName2 = L"test";
  345. RegisterDxcModule(libName2, pLib, pLinker);
  346. LinkCheckMsg(L"main", L"ps_6_0", pLinker, {libName, libName2},
  347. {"local resource not guaranteed to map to unique global resource"});
  348. }
  349. TEST_F(LinkerTest, RunLinkToLibWithUnresolvedFunctions) {
  350. LPCWSTR option[] = { L"-Zi", L"-Qembed_debug" };
  351. CComPtr<IDxcBlob> pLib1;
  352. CompileLib(L"..\\CodeGenHLSL\\linker\\lib_unresolved_func1.hlsl",
  353. &pLib1, option);
  354. CComPtr<IDxcBlob> pLib2;
  355. CompileLib(L"..\\CodeGenHLSL\\linker\\lib_unresolved_func2.hlsl",
  356. &pLib2, option);
  357. CComPtr<IDxcLinker> pLinker;
  358. CreateLinker(&pLinker);
  359. LPCWSTR libName1 = L"lib1";
  360. RegisterDxcModule(libName1, pLib1, pLinker);
  361. LPCWSTR libName2 = L"lib2";
  362. RegisterDxcModule(libName2, pLib2, pLinker);
  363. Link(L"", L"lib_6_3", pLinker, { libName1, libName2 }, {
  364. "declare float @\"\\01?external_fn1@@YAMXZ\"()",
  365. "declare float @\"\\01?external_fn2@@YAMXZ\"()",
  366. "declare float @\"\\01?external_fn@@YAMXZ\"()",
  367. "define float @\"\\01?lib1_fn@@YAMXZ\"()",
  368. "define float @\"\\01?lib2_fn@@YAMXZ\"()",
  369. "define float @\"\\01?call_lib1@@YAMXZ\"()",
  370. "define float @\"\\01?call_lib2@@YAMXZ\"()"
  371. }, {"declare float @\"\\01?unused_fn1", "declare float @\"\\01?unused_fn2"});
  372. }
  373. TEST_F(LinkerTest, RunLinkToLibWithUnresolvedFunctionsExports) {
  374. LPCWSTR option[] = { L"-Zi", L"-Qembed_debug" };
  375. CComPtr<IDxcBlob> pLib1;
  376. CompileLib(L"..\\CodeGenHLSL\\linker\\lib_unresolved_func1.hlsl",
  377. &pLib1, option);
  378. CComPtr<IDxcBlob> pLib2;
  379. CompileLib(L"..\\CodeGenHLSL\\linker\\lib_unresolved_func2.hlsl",
  380. &pLib2, option);
  381. CComPtr<IDxcLinker> pLinker;
  382. CreateLinker(&pLinker);
  383. LPCWSTR libName1 = L"lib1";
  384. RegisterDxcModule(libName1, pLib1, pLinker);
  385. LPCWSTR libName2 = L"lib2";
  386. RegisterDxcModule(libName2, pLib2, pLinker);
  387. Link(L"", L"lib_6_3", pLinker, { libName1, libName2 },
  388. { "declare float @\"\\01?external_fn1@@YAMXZ\"()",
  389. "declare float @\"\\01?external_fn2@@YAMXZ\"()",
  390. "declare float @\"\\01?external_fn@@YAMXZ\"()",
  391. "define float @\"\\01?renamed_lib1@@YAMXZ\"()",
  392. "define float @\"\\01?call_lib2@@YAMXZ\"()"
  393. },
  394. { "float @\"\\01?unused_fn1", "float @\"\\01?unused_fn2",
  395. "float @\"\\01?lib1_fn", "float @\"\\01?lib2_fn",
  396. "float @\"\\01?call_lib1"
  397. },
  398. { L"-exports", L"renamed_lib1=call_lib1",
  399. L"-exports", L"call_lib2"
  400. });
  401. }
  402. TEST_F(LinkerTest, RunLinkToLibWithExportNamesSwapped) {
  403. LPCWSTR option[] = { L"-Zi", L"-Qembed_debug" };
  404. CComPtr<IDxcBlob> pLib1;
  405. CompileLib(L"..\\CodeGenHLSL\\linker\\lib_unresolved_func1.hlsl",
  406. &pLib1, option);
  407. CComPtr<IDxcBlob> pLib2;
  408. CompileLib(L"..\\CodeGenHLSL\\linker\\lib_unresolved_func2.hlsl",
  409. &pLib2, option);
  410. CComPtr<IDxcLinker> pLinker;
  411. CreateLinker(&pLinker);
  412. LPCWSTR libName1 = L"lib1";
  413. RegisterDxcModule(libName1, pLib1, pLinker);
  414. LPCWSTR libName2 = L"lib2";
  415. RegisterDxcModule(libName2, pLib2, pLinker);
  416. Link(L"", L"lib_6_3", pLinker, { libName1, libName2 },
  417. { "declare float @\"\\01?external_fn1@@YAMXZ\"()",
  418. "declare float @\"\\01?external_fn2@@YAMXZ\"()",
  419. "declare float @\"\\01?external_fn@@YAMXZ\"()",
  420. "define float @\"\\01?call_lib1@@YAMXZ\"()",
  421. "define float @\"\\01?call_lib2@@YAMXZ\"()"
  422. },
  423. { "float @\"\\01?unused_fn1", "float @\"\\01?unused_fn2",
  424. "float @\"\\01?lib1_fn", "float @\"\\01?lib2_fn"
  425. },
  426. { L"-exports", L"call_lib2=call_lib1;call_lib1=call_lib2" });
  427. }
  428. TEST_F(LinkerTest, RunLinkToLibWithExportCollision) {
  429. LPCWSTR option[] = { L"-Zi", L"-Qembed_debug" };
  430. CComPtr<IDxcBlob> pLib1;
  431. CompileLib(L"..\\CodeGenHLSL\\linker\\lib_unresolved_func1.hlsl",
  432. &pLib1, option);
  433. CComPtr<IDxcBlob> pLib2;
  434. CompileLib(L"..\\CodeGenHLSL\\linker\\lib_unresolved_func2.hlsl",
  435. &pLib2, option);
  436. CComPtr<IDxcLinker> pLinker;
  437. CreateLinker(&pLinker);
  438. LPCWSTR libName1 = L"lib1";
  439. RegisterDxcModule(libName1, pLib1, pLinker);
  440. LPCWSTR libName2 = L"lib2";
  441. RegisterDxcModule(libName2, pLib2, pLinker);
  442. LinkCheckMsg(L"", L"lib_6_3", pLinker, { libName1, libName2 },
  443. { "Export name collides with another export: \\01?call_lib2@@YAMXZ"
  444. },
  445. { L"-exports", L"call_lib2=call_lib1;call_lib2" });
  446. }
  447. TEST_F(LinkerTest, RunLinkToLibWithUnusedExport) {
  448. LPCWSTR option[] = { L"-Zi", L"-Qembed_debug" };
  449. CComPtr<IDxcBlob> pLib1;
  450. CompileLib(L"..\\CodeGenHLSL\\linker\\lib_unresolved_func1.hlsl",
  451. &pLib1, option);
  452. CComPtr<IDxcBlob> pLib2;
  453. CompileLib(L"..\\CodeGenHLSL\\linker\\lib_unresolved_func2.hlsl",
  454. &pLib2, option);
  455. CComPtr<IDxcLinker> pLinker;
  456. CreateLinker(&pLinker);
  457. LPCWSTR libName1 = L"lib1";
  458. RegisterDxcModule(libName1, pLib1, pLinker);
  459. LPCWSTR libName2 = L"lib2";
  460. RegisterDxcModule(libName2, pLib2, pLinker);
  461. LinkCheckMsg(L"", L"lib_6_3", pLinker, { libName1, libName2 },
  462. { "Could not find target for export: call_lib"
  463. },
  464. { L"-exports", L"call_lib2=call_lib;call_lib1" });
  465. }
  466. TEST_F(LinkerTest, RunLinkToLibWithNoExports) {
  467. LPCWSTR option[] = { L"-Zi", L"-Qembed_debug" };
  468. CComPtr<IDxcBlob> pLib1;
  469. CompileLib(L"..\\CodeGenHLSL\\linker\\lib_unresolved_func1.hlsl",
  470. &pLib1, option);
  471. CComPtr<IDxcBlob> pLib2;
  472. CompileLib(L"..\\CodeGenHLSL\\linker\\lib_unresolved_func2.hlsl",
  473. &pLib2, option);
  474. CComPtr<IDxcLinker> pLinker;
  475. CreateLinker(&pLinker);
  476. LPCWSTR libName1 = L"lib1";
  477. RegisterDxcModule(libName1, pLib1, pLinker);
  478. LPCWSTR libName2 = L"lib2";
  479. RegisterDxcModule(libName2, pLib2, pLinker);
  480. LinkCheckMsg(L"", L"lib_6_3", pLinker, { libName1, libName2 },
  481. { "Library has no functions to export"
  482. },
  483. { L"-exports", L"call_lib2=call_lib" });
  484. }
  485. TEST_F(LinkerTest, RunLinkWithPotentialIntrinsicNameCollisions) {
  486. LPCWSTR option[] = { L"-Zi", L"-Qembed_debug" };
  487. CComPtr<IDxcBlob> pLib1;
  488. CompileLib(L"..\\CodeGenHLSL\\linker\\createHandle_multi.hlsl",
  489. &pLib1, option);
  490. CComPtr<IDxcBlob> pLib2;
  491. CompileLib(L"..\\CodeGenHLSL\\linker\\createHandle_multi2.hlsl",
  492. &pLib2, option);
  493. CComPtr<IDxcLinker> pLinker;
  494. CreateLinker(&pLinker);
  495. LPCWSTR libName1 = L"lib1";
  496. RegisterDxcModule(libName1, pLib1, pLinker);
  497. LPCWSTR libName2 = L"lib2";
  498. RegisterDxcModule(libName2, pLib2, pLinker);
  499. Link(L"", L"lib_6_3", pLinker, { libName1, libName2 }, {
  500. "declare %dx.types.Handle @\"dx.op.createHandleForLib.class.Texture2D<vector<float, 4> >\"(i32, %\"class.Texture2D<vector<float, 4> >\")",
  501. "declare %dx.types.Handle @\"dx.op.createHandleForLib.class.Texture2D<float>\"(i32, %\"class.Texture2D<float>\")"
  502. }, { });
  503. }
  504. TEST_F(LinkerTest, RunLinkWithValidatorVersion) {
  505. if (m_ver.SkipDxilVersion(1, 4)) return;
  506. CComPtr<IDxcBlob> pEntryLib;
  507. CompileLib(L"..\\CodeGenHLSL\\linker\\lib_mat_entry2.hlsl",
  508. &pEntryLib, {});
  509. CComPtr<IDxcBlob> pLib;
  510. CompileLib(
  511. L"..\\CodeGenHLSL\\linker\\lib_mat_cast2.hlsl",
  512. &pLib, {});
  513. CComPtr<IDxcLinker> pLinker;
  514. CreateLinker(&pLinker);
  515. LPCWSTR libName = L"ps_main";
  516. RegisterDxcModule(libName, pEntryLib, pLinker);
  517. LPCWSTR libName2 = L"test";
  518. RegisterDxcModule(libName2, pLib, pLinker);
  519. Link(L"", L"lib_6_3", pLinker, {libName, libName2},
  520. {"!dx.valver = !{(![0-9]+)}.*\n\\1 = !{i32 1, i32 3}"},
  521. {}, {L"-validator-version", L"1.3"}, /*regex*/ true);
  522. }