DxilLinker.cpp 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // DxilLinker.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. #include "dxc/HLSL/DxilLinker.h"
  10. #include "dxc/DXIL/DxilCBuffer.h"
  11. #include "dxc/DXIL/DxilFunctionProps.h"
  12. #include "dxc/DXIL/DxilEntryProps.h"
  13. #include "dxc/DXIL/DxilModule.h"
  14. #include "dxc/DXIL/DxilOperations.h"
  15. #include "dxc/DXIL/DxilResource.h"
  16. #include "dxc/DXIL/DxilSampler.h"
  17. #include "dxc/DXIL/DxilUtil.h"
  18. #include "dxc/Support/Global.h"
  19. #include "llvm/ADT/DenseSet.h"
  20. #include "llvm/ADT/MapVector.h"
  21. #include "llvm/ADT/SetVector.h"
  22. #include "llvm/ADT/StringSet.h"
  23. #include "llvm/IR/Constants.h"
  24. #include "llvm/IR/IRBuilder.h"
  25. #include "llvm/IR/Instructions.h"
  26. #include "llvm/IR/Module.h"
  27. #include "llvm/Transforms/Utils/Cloning.h"
  28. #include "llvm/ADT/StringMap.h"
  29. #include "llvm/ADT/SetVector.h"
  30. #include "llvm/ADT/STLExtras.h"
  31. #include "llvm/Support/raw_ostream.h"
  32. #include <memory>
  33. #include <vector>
  34. #include "dxc/DxilContainer/DxilContainer.h"
  35. #include "llvm/IR/DiagnosticPrinter.h"
  36. #include "llvm/IR/LLVMContext.h"
  37. #include "llvm/IR/DebugInfo.h"
  38. #include "dxc/HLSL/DxilGenerationPass.h"
  39. #include "llvm/IR/LegacyPassManager.h"
  40. #include "llvm/Transforms/IPO.h"
  41. #include "llvm/Transforms/Scalar.h"
  42. #include "dxc/HLSL/DxilExportMap.h"
  43. #include "dxc/HLSL/ComputeViewIdState.h"
  44. using namespace llvm;
  45. using namespace hlsl;
  46. namespace {
  47. void CollectUsedFunctions(Constant *C,
  48. llvm::SetVector<Function *> &funcSet) {
  49. for (User *U : C->users()) {
  50. if (Instruction *I = dyn_cast<Instruction>(U)) {
  51. funcSet.insert(I->getParent()->getParent());
  52. } else {
  53. Constant *CU = cast<Constant>(U);
  54. CollectUsedFunctions(CU, funcSet);
  55. }
  56. }
  57. }
  58. template <class T>
  59. void AddResourceMap(
  60. const std::vector<std::unique_ptr<T>> &resTab, DXIL::ResourceClass resClass,
  61. llvm::MapVector<const llvm::Constant *, DxilResourceBase *> &resMap,
  62. DxilModule &DM) {
  63. for (auto &Res : resTab) {
  64. resMap[Res->GetGlobalSymbol()] = Res.get();
  65. }
  66. }
  67. void CloneFunction(Function *F, Function *NewF, ValueToValueMapTy &vmap,
  68. hlsl::DxilTypeSystem *TypeSys = nullptr,
  69. hlsl::DxilTypeSystem *SrcTypeSys = nullptr) {
  70. SmallVector<ReturnInst *, 2> Returns;
  71. // Map params.
  72. auto paramIt = NewF->arg_begin();
  73. for (Argument &param : F->args()) {
  74. vmap[&param] = (paramIt++);
  75. }
  76. llvm::CloneFunctionInto(NewF, F, vmap, /*ModuleLevelChanges*/ true, Returns);
  77. if (TypeSys) {
  78. if (SrcTypeSys == nullptr)
  79. SrcTypeSys = TypeSys;
  80. TypeSys->CopyFunctionAnnotation(NewF, F, *SrcTypeSys);
  81. }
  82. // Remove params from vmap.
  83. for (Argument &param : F->args()) {
  84. vmap.erase(&param);
  85. }
  86. }
  87. } // namespace
  88. namespace {
  89. struct DxilFunctionLinkInfo {
  90. DxilFunctionLinkInfo(llvm::Function *F);
  91. llvm::Function *func;
  92. // SetVectors for deterministic iteration
  93. llvm::SetVector<llvm::Function *> usedFunctions;
  94. llvm::SetVector<llvm::GlobalVariable *> usedGVs;
  95. };
  96. // Library to link.
  97. class DxilLib {
  98. public:
  99. DxilLib(std::unique_ptr<llvm::Module> pModule);
  100. virtual ~DxilLib() {}
  101. bool HasFunction(std::string &name);
  102. llvm::StringMap<std::unique_ptr<DxilFunctionLinkInfo>> &GetFunctionTable() {
  103. return m_functionNameMap;
  104. }
  105. bool IsInitFunc(llvm::Function *F);
  106. bool IsResourceGlobal(const llvm::Constant *GV);
  107. DxilResourceBase *GetResource(const llvm::Constant *GV);
  108. DxilModule &GetDxilModule() { return m_DM; }
  109. void LazyLoadFunction(Function *F);
  110. void BuildGlobalUsage();
  111. void CollectUsedInitFunctions(SetVector<StringRef> &addedFunctionSet,
  112. SmallVector<StringRef, 4> &workList);
  113. private:
  114. std::unique_ptr<llvm::Module> m_pModule;
  115. DxilModule &m_DM;
  116. // Map from name to Link info for extern functions.
  117. llvm::StringMap<std::unique_ptr<DxilFunctionLinkInfo>> m_functionNameMap;
  118. // Map from resource link global to resource. MapVector for deterministic iteration.
  119. llvm::MapVector<const llvm::Constant *, DxilResourceBase *> m_resourceMap;
  120. // Set of initialize functions for global variable. SetVector for deterministic iteration.
  121. llvm::SetVector<llvm::Function *> m_initFuncSet;
  122. };
  123. struct DxilLinkJob;
  124. class DxilLinkerImpl : public hlsl::DxilLinker {
  125. public:
  126. DxilLinkerImpl(LLVMContext &Ctx, unsigned valMajor, unsigned valMinor) : DxilLinker(Ctx, valMajor, valMinor) {}
  127. virtual ~DxilLinkerImpl() {}
  128. bool HasLibNameRegistered(StringRef name) override;
  129. bool RegisterLib(StringRef name, std::unique_ptr<llvm::Module> pModule,
  130. std::unique_ptr<llvm::Module> pDebugModule) override;
  131. bool AttachLib(StringRef name) override;
  132. bool DetachLib(StringRef name) override;
  133. void DetachAll() override;
  134. std::unique_ptr<llvm::Module>
  135. Link(StringRef entry, StringRef profile, dxilutil::ExportMap &exportMap) override;
  136. private:
  137. bool AttachLib(DxilLib *lib);
  138. bool DetachLib(DxilLib *lib);
  139. bool AddFunctions(SmallVector<StringRef, 4> &workList,
  140. SetVector<DxilLib *> &libSet, SetVector<StringRef> &addedFunctionSet,
  141. DxilLinkJob &linkJob, bool bLazyLoadDone,
  142. bool bAllowFuncionDecls);
  143. // Attached libs to link.
  144. std::unordered_set<DxilLib *> m_attachedLibs;
  145. // Owner of all DxilLib.
  146. StringMap<std::unique_ptr<DxilLib>> m_LibMap;
  147. llvm::StringMap<std::pair<DxilFunctionLinkInfo *, DxilLib *>>
  148. m_functionNameMap;
  149. };
  150. } // namespace
  151. //------------------------------------------------------------------------------
  152. //
  153. // DxilFunctionLinkInfo methods.
  154. //
  155. DxilFunctionLinkInfo::DxilFunctionLinkInfo(Function *F) : func(F) {
  156. DXASSERT_NOMSG(F);
  157. }
  158. //------------------------------------------------------------------------------
  159. //
  160. // DxilLib methods.
  161. //
  162. DxilLib::DxilLib(std::unique_ptr<llvm::Module> pModule)
  163. : m_pModule(std::move(pModule)), m_DM(m_pModule->GetOrCreateDxilModule()) {
  164. Module &M = *m_pModule;
  165. const std::string &MID = M.getModuleIdentifier();
  166. // Collect function defines.
  167. for (Function &F : M.functions()) {
  168. if (F.isDeclaration())
  169. continue;
  170. if (F.getLinkage() == GlobalValue::LinkageTypes::InternalLinkage) {
  171. // Add prefix to internal function.
  172. F.setName(MID + F.getName());
  173. }
  174. m_functionNameMap[F.getName()] =
  175. llvm::make_unique<DxilFunctionLinkInfo>(&F);
  176. }
  177. // Update internal global name.
  178. for (GlobalVariable &GV : M.globals()) {
  179. if (GV.getLinkage() == GlobalValue::LinkageTypes::InternalLinkage) {
  180. // Add prefix to internal global.
  181. GV.setName(MID + GV.getName());
  182. }
  183. }
  184. }
  185. void DxilLib::LazyLoadFunction(Function *F) {
  186. DXASSERT(m_functionNameMap.count(F->getName()), "else invalid Function");
  187. DxilFunctionLinkInfo *linkInfo = m_functionNameMap[F->getName()].get();
  188. std::error_code EC = F->materialize();
  189. DXASSERT_LOCALVAR(EC, !EC, "else fail to materialize");
  190. // Build used functions for F.
  191. for (auto &BB : F->getBasicBlockList()) {
  192. for (auto &I : BB.getInstList()) {
  193. if (CallInst *CI = dyn_cast<CallInst>(&I)) {
  194. linkInfo->usedFunctions.insert(CI->getCalledFunction());
  195. }
  196. }
  197. }
  198. if (m_DM.HasDxilFunctionProps(F)) {
  199. DxilFunctionProps &props = m_DM.GetDxilFunctionProps(F);
  200. if (props.IsHS()) {
  201. // Add patch constant function to usedFunctions of entry.
  202. Function *patchConstantFunc = props.ShaderProps.HS.patchConstantFunc;
  203. linkInfo->usedFunctions.insert(patchConstantFunc);
  204. }
  205. }
  206. // Used globals will be build before link.
  207. }
  208. void DxilLib::BuildGlobalUsage() {
  209. Module &M = *m_pModule;
  210. // Collect init functions for static globals.
  211. if (GlobalVariable *Ctors = M.getGlobalVariable("llvm.global_ctors")) {
  212. if (ConstantArray *CA = dyn_cast<ConstantArray>(Ctors->getInitializer())) {
  213. for (User::op_iterator i = CA->op_begin(), e = CA->op_end(); i != e;
  214. ++i) {
  215. if (isa<ConstantAggregateZero>(*i))
  216. continue;
  217. ConstantStruct *CS = cast<ConstantStruct>(*i);
  218. if (isa<ConstantPointerNull>(CS->getOperand(1)))
  219. continue;
  220. // Must have a function or null ptr.
  221. if (!isa<Function>(CS->getOperand(1)))
  222. continue;
  223. Function *Ctor = cast<Function>(CS->getOperand(1));
  224. assert(Ctor->getReturnType()->isVoidTy() && Ctor->arg_size() == 0 &&
  225. "function type must be void (void)");
  226. // Add Ctor.
  227. m_initFuncSet.insert(Ctor);
  228. LazyLoadFunction(Ctor);
  229. }
  230. }
  231. }
  232. // Build used globals.
  233. for (GlobalVariable &GV : M.globals()) {
  234. llvm::SetVector<Function *> funcSet;
  235. CollectUsedFunctions(&GV, funcSet);
  236. for (Function *F : funcSet) {
  237. DXASSERT(m_functionNameMap.count(F->getName()), "must exist in table");
  238. DxilFunctionLinkInfo *linkInfo = m_functionNameMap[F->getName()].get();
  239. linkInfo->usedGVs.insert(&GV);
  240. }
  241. }
  242. // Build resource map.
  243. AddResourceMap(m_DM.GetUAVs(), DXIL::ResourceClass::UAV, m_resourceMap, m_DM);
  244. AddResourceMap(m_DM.GetSRVs(), DXIL::ResourceClass::SRV, m_resourceMap, m_DM);
  245. AddResourceMap(m_DM.GetCBuffers(), DXIL::ResourceClass::CBuffer,
  246. m_resourceMap, m_DM);
  247. AddResourceMap(m_DM.GetSamplers(), DXIL::ResourceClass::Sampler,
  248. m_resourceMap, m_DM);
  249. }
  250. void DxilLib::CollectUsedInitFunctions(SetVector<StringRef> &addedFunctionSet,
  251. SmallVector<StringRef, 4> &workList) {
  252. // Add init functions to used functions.
  253. for (Function *Ctor : m_initFuncSet) {
  254. DXASSERT(m_functionNameMap.count(Ctor->getName()),
  255. "must exist in internal table");
  256. DxilFunctionLinkInfo *linkInfo = m_functionNameMap[Ctor->getName()].get();
  257. // If function other than Ctor used GV of Ctor.
  258. // Add Ctor to usedFunctions for it.
  259. for (GlobalVariable *GV : linkInfo->usedGVs) {
  260. llvm::SetVector<Function *> funcSet;
  261. CollectUsedFunctions(GV, funcSet);
  262. bool bAdded = false;
  263. for (Function *F : funcSet) {
  264. if (F == Ctor)
  265. continue;
  266. // If F is added for link, add init func to workList.
  267. if (addedFunctionSet.count(F->getName())) {
  268. workList.emplace_back(Ctor->getName());
  269. bAdded = true;
  270. break;
  271. }
  272. }
  273. if (bAdded)
  274. break;
  275. }
  276. }
  277. }
  278. bool DxilLib::HasFunction(std::string &name) {
  279. return m_functionNameMap.count(name);
  280. }
  281. bool DxilLib::IsInitFunc(llvm::Function *F) { return m_initFuncSet.count(F); }
  282. bool DxilLib::IsResourceGlobal(const llvm::Constant *GV) {
  283. return m_resourceMap.count(GV);
  284. }
  285. DxilResourceBase *DxilLib::GetResource(const llvm::Constant *GV) {
  286. if (IsResourceGlobal(GV))
  287. return m_resourceMap[GV];
  288. else
  289. return nullptr;
  290. }
  291. namespace {
  292. // Create module from link defines.
  293. struct DxilLinkJob {
  294. DxilLinkJob(LLVMContext &Ctx, dxilutil::ExportMap &exportMap,
  295. unsigned valMajor, unsigned valMinor)
  296. : m_ctx(Ctx), m_exportMap(exportMap), m_valMajor(valMajor),
  297. m_valMinor(valMinor) {}
  298. std::unique_ptr<llvm::Module>
  299. Link(std::pair<DxilFunctionLinkInfo *, DxilLib *> &entryLinkPair,
  300. const ShaderModel *pSM);
  301. std::unique_ptr<llvm::Module> LinkToLib(const ShaderModel *pSM);
  302. void StripDeadDebugInfo(llvm::Module &M);
  303. void RunPreparePass(llvm::Module &M);
  304. void AddFunction(std::pair<DxilFunctionLinkInfo *, DxilLib *> &linkPair);
  305. void AddFunction(llvm::Function *F);
  306. private:
  307. void LinkNamedMDNodes(Module *pM, ValueToValueMapTy &vmap);
  308. void AddFunctionDecls(Module *pM);
  309. bool AddGlobals(DxilModule &DM, ValueToValueMapTy &vmap);
  310. void CloneFunctions(ValueToValueMapTy &vmap);
  311. void AddFunctions(DxilModule &DM, ValueToValueMapTy &vmap);
  312. bool AddResource(DxilResourceBase *res, llvm::GlobalVariable *GV);
  313. void AddResourceToDM(DxilModule &DM);
  314. llvm::MapVector<DxilFunctionLinkInfo *, DxilLib *> m_functionDefs;
  315. llvm::StringMap<llvm::Function *> m_functionDecls;
  316. // New created functions.
  317. llvm::StringMap<llvm::Function *> m_newFunctions;
  318. // New created globals.
  319. llvm::StringMap<llvm::GlobalVariable *> m_newGlobals;
  320. // Map for resource.
  321. llvm::StringMap<std::pair<DxilResourceBase *, llvm::GlobalVariable *>>
  322. m_resourceMap;
  323. LLVMContext &m_ctx;
  324. dxilutil::ExportMap &m_exportMap;
  325. unsigned m_valMajor, m_valMinor;
  326. };
  327. } // namespace
  328. namespace {
  329. const char kUndefFunction[] = "Cannot find definition of function ";
  330. const char kRedefineFunction[] = "Definition already exists for function ";
  331. const char kRedefineGlobal[] = "Definition already exists for global variable ";
  332. const char kInvalidProfile[] = " is invalid profile to link";
  333. const char kExportOnlyForLib[] = "export map is only for library";
  334. const char kShaderKindMismatch[] =
  335. "Profile mismatch between entry function and target profile:";
  336. const char kNoEntryProps[] =
  337. "Cannot find function property for entry function ";
  338. const char kRedefineResource[] =
  339. "Resource already exists as ";
  340. const char kInvalidValidatorVersion[] = "Validator version does not support target profile ";
  341. const char kExportNameCollision[] = "Export name collides with another export: ";
  342. const char kExportFunctionMissing[] = "Could not find target for export: ";
  343. const char kNoFunctionsToExport[] = "Library has no functions to export";
  344. } // namespace
  345. //------------------------------------------------------------------------------
  346. //
  347. // DxilLinkJob methods.
  348. //
  349. namespace {
  350. // Helper function to check type match.
  351. bool IsMatchedType(Type *Ty0, Type *Ty);
  352. StringRef RemoveNameSuffix(StringRef Name) {
  353. size_t DotPos = Name.rfind('.');
  354. if (DotPos != StringRef::npos && Name.back() != '.' &&
  355. isdigit(static_cast<unsigned char>(Name[DotPos + 1])))
  356. Name = Name.substr(0, DotPos);
  357. return Name;
  358. }
  359. bool IsMatchedStructType(StructType *ST0, StructType *ST) {
  360. StringRef Name0 = RemoveNameSuffix(ST0->getName());
  361. StringRef Name = RemoveNameSuffix(ST->getName());
  362. if (Name0 != Name)
  363. return false;
  364. if (ST0->getNumElements() != ST->getNumElements())
  365. return false;
  366. if (ST0->isLayoutIdentical(ST))
  367. return true;
  368. for (unsigned i = 0; i < ST->getNumElements(); i++) {
  369. Type *Ty = ST->getElementType(i);
  370. Type *Ty0 = ST0->getElementType(i);
  371. if (!IsMatchedType(Ty, Ty0))
  372. return false;
  373. }
  374. return true;
  375. }
  376. bool IsMatchedArrayType(ArrayType *AT0, ArrayType *AT) {
  377. if (AT0->getNumElements() != AT->getNumElements())
  378. return false;
  379. return IsMatchedType(AT0->getElementType(), AT->getElementType());
  380. }
  381. bool IsMatchedType(Type *Ty0, Type *Ty) {
  382. if (Ty0->isStructTy() && Ty->isStructTy()) {
  383. StructType *ST0 = cast<StructType>(Ty0);
  384. StructType *ST = cast<StructType>(Ty);
  385. return IsMatchedStructType(ST0, ST);
  386. }
  387. if (Ty0->isArrayTy() && Ty->isArrayTy()) {
  388. ArrayType *AT0 = cast<ArrayType>(Ty0);
  389. ArrayType *AT = cast<ArrayType>(Ty);
  390. return IsMatchedArrayType(AT0, AT);
  391. }
  392. if (Ty0->isPointerTy() && Ty->isPointerTy()) {
  393. if (Ty0->getPointerAddressSpace() != Ty->getPointerAddressSpace())
  394. return false;
  395. return IsMatchedType(Ty0->getPointerElementType(),
  396. Ty->getPointerElementType());
  397. }
  398. return Ty0 == Ty;
  399. }
  400. } // namespace
  401. bool DxilLinkJob::AddResource(DxilResourceBase *res, llvm::GlobalVariable *GV) {
  402. if (m_resourceMap.count(res->GetGlobalName())) {
  403. DxilResourceBase *res0 = m_resourceMap[res->GetGlobalName()].first;
  404. Type *Ty0 = res0->GetGlobalSymbol()->getType()->getPointerElementType();
  405. Type *Ty = res->GetGlobalSymbol()->getType()->getPointerElementType();
  406. // Make sure res0 match res.
  407. bool bMatch = IsMatchedType(Ty0, Ty);
  408. if (!bMatch) {
  409. // Report error.
  410. dxilutil::EmitErrorOnGlobalVariable(dyn_cast<GlobalVariable>(res->GetGlobalSymbol()),
  411. Twine(kRedefineResource) + res->GetResClassName() + " for " +
  412. res->GetGlobalName());
  413. return false;
  414. }
  415. } else {
  416. m_resourceMap[res->GetGlobalName()] = std::make_pair(res, GV);
  417. }
  418. return true;
  419. }
  420. void DxilLinkJob::AddResourceToDM(DxilModule &DM) {
  421. for (auto &it : m_resourceMap) {
  422. DxilResourceBase *res = it.second.first;
  423. GlobalVariable *GV = it.second.second;
  424. unsigned ID = 0;
  425. DxilResourceBase *basePtr = nullptr;
  426. switch (res->GetClass()) {
  427. case DXIL::ResourceClass::UAV: {
  428. std::unique_ptr<DxilResource> pUAV = llvm::make_unique<DxilResource>();
  429. DxilResource *ptr = pUAV.get();
  430. // Copy the content.
  431. *ptr = *(static_cast<DxilResource *>(res));
  432. ID = DM.AddUAV(std::move(pUAV));
  433. basePtr = &DM.GetUAV(ID);
  434. } break;
  435. case DXIL::ResourceClass::SRV: {
  436. std::unique_ptr<DxilResource> pSRV = llvm::make_unique<DxilResource>();
  437. DxilResource *ptr = pSRV.get();
  438. // Copy the content.
  439. *ptr = *(static_cast<DxilResource *>(res));
  440. ID = DM.AddSRV(std::move(pSRV));
  441. basePtr = &DM.GetSRV(ID);
  442. } break;
  443. case DXIL::ResourceClass::CBuffer: {
  444. std::unique_ptr<DxilCBuffer> pCBuf = llvm::make_unique<DxilCBuffer>();
  445. DxilCBuffer *ptr = pCBuf.get();
  446. // Copy the content.
  447. *ptr = *(static_cast<DxilCBuffer *>(res));
  448. ID = DM.AddCBuffer(std::move(pCBuf));
  449. basePtr = &DM.GetCBuffer(ID);
  450. } break;
  451. case DXIL::ResourceClass::Sampler: {
  452. std::unique_ptr<DxilSampler> pSampler = llvm::make_unique<DxilSampler>();
  453. DxilSampler *ptr = pSampler.get();
  454. // Copy the content.
  455. *ptr = *(static_cast<DxilSampler *>(res));
  456. ID = DM.AddSampler(std::move(pSampler));
  457. basePtr = &DM.GetSampler(ID);
  458. }
  459. default:
  460. DXASSERT(res->GetClass() == DXIL::ResourceClass::Sampler,
  461. "else invalid resource");
  462. break;
  463. }
  464. // Update ID.
  465. basePtr->SetID(ID);
  466. basePtr->SetGlobalSymbol(GV);
  467. DM.GetLLVMUsed().push_back(GV);
  468. }
  469. // Prevent global vars used for resources from being deleted through optimizations
  470. // while we still have hidden uses (pointers in resource vectors).
  471. DM.EmitLLVMUsed();
  472. }
  473. void DxilLinkJob::LinkNamedMDNodes(Module *pM, ValueToValueMapTy &vmap) {
  474. SetVector<Module *> moduleSet;
  475. for (auto &it : m_functionDefs) {
  476. DxilLib *pLib = it.second;
  477. moduleSet.insert(pLib->GetDxilModule().GetModule());
  478. }
  479. // Link normal NamedMDNode.
  480. // TODO: skip duplicate operands.
  481. for (Module *pSrcM : moduleSet) {
  482. const NamedMDNode *pSrcModFlags = pSrcM->getModuleFlagsMetadata();
  483. for (const NamedMDNode &NMD : pSrcM->named_metadata()) {
  484. // Don't link module flags here. Do them separately.
  485. if (&NMD == pSrcModFlags)
  486. continue;
  487. // Skip dxil metadata which will be regenerated.
  488. if (DxilMDHelper::IsKnownNamedMetaData(NMD))
  489. continue;
  490. NamedMDNode *DestNMD = pM->getOrInsertNamedMetadata(NMD.getName());
  491. // Add Src elements into Dest node.
  492. for (const MDNode *op : NMD.operands())
  493. DestNMD->addOperand(MapMetadata(op, vmap, RF_None, /*TypeMap*/ nullptr,
  494. /*ValMaterializer*/ nullptr));
  495. }
  496. }
  497. // Link mod flags.
  498. SetVector<MDNode *> flagSet;
  499. for (Module *pSrcM : moduleSet) {
  500. NamedMDNode *pSrcModFlags = pSrcM->getModuleFlagsMetadata();
  501. if (pSrcModFlags) {
  502. for (MDNode *flag : pSrcModFlags->operands()) {
  503. flagSet.insert(flag);
  504. }
  505. }
  506. }
  507. // TODO: check conflict in flags.
  508. if (!flagSet.empty()) {
  509. NamedMDNode *ModFlags = pM->getOrInsertModuleFlagsMetadata();
  510. for (MDNode *flag : flagSet) {
  511. ModFlags->addOperand(flag);
  512. }
  513. }
  514. }
  515. void DxilLinkJob::AddFunctionDecls(Module *pM) {
  516. for (auto &it : m_functionDecls) {
  517. Function *F = it.second;
  518. Function *NewF = Function::Create(F->getFunctionType(), F->getLinkage(),
  519. F->getName(), pM);
  520. NewF->setAttributes(F->getAttributes());
  521. m_newFunctions[NewF->getName()] = NewF;
  522. }
  523. }
  524. bool DxilLinkJob::AddGlobals(DxilModule &DM, ValueToValueMapTy &vmap) {
  525. DxilTypeSystem &typeSys = DM.GetTypeSystem();
  526. Module *pM = DM.GetModule();
  527. bool bSuccess = true;
  528. for (auto &it : m_functionDefs) {
  529. DxilFunctionLinkInfo *linkInfo = it.first;
  530. DxilLib *pLib = it.second;
  531. DxilModule &tmpDM = pLib->GetDxilModule();
  532. DxilTypeSystem &tmpTypeSys = tmpDM.GetTypeSystem();
  533. for (GlobalVariable *GV : linkInfo->usedGVs) {
  534. // Skip added globals.
  535. if (m_newGlobals.count(GV->getName())) {
  536. if (vmap.find(GV) == vmap.end()) {
  537. if (DxilResourceBase *res = pLib->GetResource(GV)) {
  538. // For resource of same name, if class and type match, just map to
  539. // same NewGV.
  540. GlobalVariable *NewGV = m_newGlobals[GV->getName()];
  541. if (AddResource(res, NewGV)) {
  542. vmap[GV] = NewGV;
  543. } else {
  544. bSuccess = false;
  545. }
  546. continue;
  547. }
  548. // Redefine of global.
  549. dxilutil::EmitErrorOnGlobalVariable(GV, Twine(kRedefineGlobal) + GV->getName());
  550. bSuccess = false;
  551. }
  552. continue;
  553. }
  554. Constant *Initializer = nullptr;
  555. if (GV->hasInitializer())
  556. Initializer = GV->getInitializer();
  557. Type *Ty = GV->getType()->getElementType();
  558. GlobalVariable *NewGV = new GlobalVariable(
  559. *pM, Ty, GV->isConstant(), GV->getLinkage(), Initializer,
  560. GV->getName(),
  561. /*InsertBefore*/ nullptr, GV->getThreadLocalMode(),
  562. GV->getType()->getAddressSpace(), GV->isExternallyInitialized());
  563. m_newGlobals[GV->getName()] = NewGV;
  564. vmap[GV] = NewGV;
  565. typeSys.CopyTypeAnnotation(Ty, tmpTypeSys);
  566. if (DxilResourceBase *res = pLib->GetResource(GV)) {
  567. bSuccess &= AddResource(res, NewGV);
  568. }
  569. }
  570. }
  571. return bSuccess;
  572. }
  573. void DxilLinkJob::CloneFunctions(ValueToValueMapTy &vmap) {
  574. for (auto &it : m_functionDefs) {
  575. DxilFunctionLinkInfo *linkInfo = it.first;
  576. Function *F = linkInfo->func;
  577. Function *NewF = m_newFunctions[F->getName()];
  578. // Add dxil functions to vmap.
  579. for (Function *UsedF : linkInfo->usedFunctions) {
  580. if (!vmap.count(UsedF)) {
  581. // Extern function need match by name
  582. DXASSERT(m_newFunctions.count(UsedF->getName()),
  583. "Must have new function.");
  584. vmap[UsedF] = m_newFunctions[UsedF->getName()];
  585. }
  586. }
  587. CloneFunction(F, NewF, vmap);
  588. }
  589. }
  590. void DxilLinkJob::AddFunctions(DxilModule &DM, ValueToValueMapTy &vmap) {
  591. DxilTypeSystem &typeSys = DM.GetTypeSystem();
  592. Module *pM = DM.GetModule();
  593. for (auto &it : m_functionDefs) {
  594. DxilFunctionLinkInfo *linkInfo = it.first;
  595. DxilLib *pLib = it.second;
  596. DxilModule &tmpDM = pLib->GetDxilModule();
  597. DxilTypeSystem &tmpTypeSys = tmpDM.GetTypeSystem();
  598. Function *F = linkInfo->func;
  599. Function *NewF = Function::Create(F->getFunctionType(), F->getLinkage(),
  600. F->getName(), pM);
  601. NewF->setAttributes(F->getAttributes());
  602. if (!NewF->hasFnAttribute(llvm::Attribute::NoInline))
  603. NewF->addFnAttr(llvm::Attribute::AlwaysInline);
  604. if (DxilFunctionAnnotation *funcAnnotation =
  605. tmpTypeSys.GetFunctionAnnotation(F)) {
  606. // Clone funcAnnotation to typeSys.
  607. typeSys.CopyFunctionAnnotation(NewF, F, tmpTypeSys);
  608. }
  609. // Add to function map.
  610. m_newFunctions[NewF->getName()] = NewF;
  611. vmap[F] = NewF;
  612. }
  613. }
  614. std::unique_ptr<Module>
  615. DxilLinkJob::Link(std::pair<DxilFunctionLinkInfo *, DxilLib *> &entryLinkPair,
  616. const ShaderModel *pSM) {
  617. Function *entryFunc = entryLinkPair.first->func;
  618. DxilModule &entryDM = entryLinkPair.second->GetDxilModule();
  619. if (!entryDM.HasDxilFunctionProps(entryFunc)) {
  620. // Cannot get function props.
  621. dxilutil::EmitErrorOnFunction(entryFunc, Twine(kNoEntryProps) + entryFunc->getName());
  622. return nullptr;
  623. }
  624. DxilFunctionProps props = entryDM.GetDxilFunctionProps(entryFunc);
  625. if (pSM->GetKind() != props.shaderKind) {
  626. // Shader kind mismatch.
  627. dxilutil::EmitErrorOnFunction(entryFunc, Twine(kShaderKindMismatch) +
  628. ShaderModel::GetKindName(pSM->GetKind()) + " and " +
  629. ShaderModel::GetKindName(props.shaderKind));
  630. return nullptr;
  631. }
  632. // Create new module.
  633. std::unique_ptr<Module> pM =
  634. llvm::make_unique<Module>(entryFunc->getName(), entryDM.GetCtx());
  635. // Set target.
  636. pM->setTargetTriple(entryDM.GetModule()->getTargetTriple());
  637. // Add dxil operation functions before create DxilModule.
  638. AddFunctionDecls(pM.get());
  639. // Create DxilModule.
  640. const bool bSkipInit = true;
  641. DxilModule &DM = pM->GetOrCreateDxilModule(bSkipInit);
  642. DM.SetShaderModel(pSM, entryDM.GetUseMinPrecision());
  643. // Set Validator version.
  644. DM.SetValidatorVersion(m_valMajor, m_valMinor);
  645. ValueToValueMapTy vmap;
  646. // Add function
  647. AddFunctions(DM, vmap);
  648. // Set Entry
  649. Function *NewEntryFunc = m_newFunctions[entryFunc->getName()];
  650. DM.SetEntryFunction(NewEntryFunc);
  651. DM.SetEntryFunctionName(entryFunc->getName());
  652. DxilEntryPropsMap EntryPropMap;
  653. std::unique_ptr<DxilEntryProps> pProps =
  654. llvm::make_unique<DxilEntryProps>(entryDM.GetDxilEntryProps(entryFunc));
  655. EntryPropMap[NewEntryFunc] = std::move(pProps);
  656. DM.ResetEntryPropsMap(std::move(EntryPropMap));
  657. if (NewEntryFunc->hasFnAttribute(llvm::Attribute::AlwaysInline))
  658. NewEntryFunc->removeFnAttr(llvm::Attribute::AlwaysInline);
  659. if (props.IsHS()) {
  660. Function *patchConstantFunc = props.ShaderProps.HS.patchConstantFunc;
  661. Function *newPatchConstantFunc =
  662. m_newFunctions[patchConstantFunc->getName()];
  663. props.ShaderProps.HS.patchConstantFunc = newPatchConstantFunc;
  664. if (newPatchConstantFunc->hasFnAttribute(llvm::Attribute::AlwaysInline))
  665. newPatchConstantFunc->removeFnAttr(llvm::Attribute::AlwaysInline);
  666. }
  667. // Set EntryProps
  668. DM.SetShaderProperties(&props);
  669. // Add global
  670. bool bSuccess = AddGlobals(DM, vmap);
  671. if (!bSuccess)
  672. return nullptr;
  673. // Clone functions.
  674. CloneFunctions(vmap);
  675. // Call global constrctor.
  676. IRBuilder<> Builder(dxilutil::FirstNonAllocaInsertionPt(DM.GetEntryFunction()));
  677. for (auto &it : m_functionDefs) {
  678. DxilFunctionLinkInfo *linkInfo = it.first;
  679. DxilLib *pLib = it.second;
  680. Function *F = linkInfo->func;
  681. if (pLib->IsInitFunc(F)) {
  682. Function *NewF = m_newFunctions[F->getName()];
  683. Builder.CreateCall(NewF);
  684. }
  685. }
  686. // Refresh intrinsic cache.
  687. DM.GetOP()->RefreshCache();
  688. // Add resource to DM.
  689. // This should be after functions cloned.
  690. AddResourceToDM(DM);
  691. // Link metadata like debug info.
  692. LinkNamedMDNodes(pM.get(), vmap);
  693. RunPreparePass(*pM);
  694. return pM;
  695. }
  696. std::unique_ptr<Module>
  697. DxilLinkJob::LinkToLib(const ShaderModel *pSM) {
  698. if (m_functionDefs.empty()) {
  699. m_ctx.emitError(Twine(kNoFunctionsToExport));
  700. return nullptr;
  701. }
  702. DxilLib *pLib = m_functionDefs.begin()->second;
  703. DxilModule &tmpDM = pLib->GetDxilModule();
  704. // Create new module.
  705. std::unique_ptr<Module> pM =
  706. llvm::make_unique<Module>("merged_lib", tmpDM.GetCtx());
  707. // Set target.
  708. pM->setTargetTriple(tmpDM.GetModule()->getTargetTriple());
  709. // Add dxil operation functions and external decls before create DxilModule.
  710. AddFunctionDecls(pM.get());
  711. // Create DxilModule.
  712. const bool bSkipInit = true;
  713. DxilModule &DM = pM->GetOrCreateDxilModule(bSkipInit);
  714. DM.SetShaderModel(pSM, tmpDM.GetUseMinPrecision());
  715. // Set Validator version.
  716. DM.SetValidatorVersion(m_valMajor, m_valMinor);
  717. ValueToValueMapTy vmap;
  718. // Add function
  719. AddFunctions(DM, vmap);
  720. // Set DxilFunctionProps.
  721. DxilEntryPropsMap EntryPropMap;
  722. for (auto &it : m_functionDefs) {
  723. DxilFunctionLinkInfo *linkInfo = it.first;
  724. DxilLib *pLib = it.second;
  725. DxilModule &tmpDM = pLib->GetDxilModule();
  726. Function *F = linkInfo->func;
  727. if (tmpDM.HasDxilEntryProps(F)) {
  728. Function *NewF = m_newFunctions[F->getName()];
  729. DxilEntryProps &props = tmpDM.GetDxilEntryProps(F);
  730. std::unique_ptr<DxilEntryProps> pProps =
  731. llvm::make_unique<DxilEntryProps>(props);
  732. EntryPropMap[NewF] = std::move(pProps);
  733. }
  734. }
  735. DM.ResetEntryPropsMap(std::move(EntryPropMap));
  736. // Add global
  737. bool bSuccess = AddGlobals(DM, vmap);
  738. if (!bSuccess)
  739. return nullptr;
  740. // Clone functions.
  741. CloneFunctions(vmap);
  742. // Refresh intrinsic cache.
  743. DM.GetOP()->RefreshCache();
  744. // Add resource to DM.
  745. // This should be after functions cloned.
  746. AddResourceToDM(DM);
  747. // Link metadata like debug info.
  748. LinkNamedMDNodes(pM.get(), vmap);
  749. RunPreparePass(*pM);
  750. if (!m_exportMap.empty()) {
  751. m_exportMap.BeginProcessing();
  752. DM.ClearDxilMetadata(*pM);
  753. for (auto it = pM->begin(); it != pM->end();) {
  754. Function *F = it++;
  755. if (F->isDeclaration())
  756. continue;
  757. if (!m_exportMap.ProcessFunction(F, true)) {
  758. // Remove Function not in exportMap.
  759. DM.RemoveFunction(F);
  760. F->eraseFromParent();
  761. }
  762. }
  763. if(!m_exportMap.EndProcessing()) {
  764. for (auto &name : m_exportMap.GetNameCollisions()) {
  765. std::string escaped;
  766. llvm::raw_string_ostream os(escaped);
  767. dxilutil::PrintEscapedString(name, os);
  768. m_ctx.emitError(Twine(kExportNameCollision) + os.str());
  769. }
  770. for (auto &name : m_exportMap.GetUnusedExports()) {
  771. std::string escaped;
  772. llvm::raw_string_ostream os(escaped);
  773. dxilutil::PrintEscapedString(name, os);
  774. m_ctx.emitError(Twine(kExportFunctionMissing) + os.str());
  775. }
  776. return nullptr;
  777. }
  778. // Rename the original, if necessary, then clone the rest
  779. for (auto &it : m_exportMap.GetFunctionRenames()) {
  780. Function *F = it.first;
  781. auto &renames = it.second;
  782. if (renames.empty())
  783. continue;
  784. auto itName = renames.begin();
  785. // Rename the original, if necessary, then clone the rest
  786. if (renames.find(F->getName()) == renames.end())
  787. F->setName(*(itName++));
  788. while (itName != renames.end()) {
  789. if (F->getName() != *itName) {
  790. Function *NewF = Function::Create(F->getFunctionType(),
  791. GlobalValue::LinkageTypes::ExternalLinkage,
  792. *itName, DM.GetModule());
  793. ValueToValueMapTy vmap;
  794. CloneFunction(F, NewF, vmap, &DM.GetTypeSystem());
  795. // add DxilFunctionProps if entry
  796. if (DM.HasDxilFunctionProps(F)) {
  797. DM.CloneDxilEntryProps(F, NewF);
  798. }
  799. }
  800. itName++;
  801. }
  802. }
  803. DM.EmitDxilMetadata();
  804. }
  805. return pM;
  806. }
  807. void DxilLinkJob::AddFunction(
  808. std::pair<DxilFunctionLinkInfo *, DxilLib *> &linkPair) {
  809. m_functionDefs[linkPair.first] = linkPair.second;
  810. }
  811. void DxilLinkJob::AddFunction(llvm::Function *F) {
  812. m_functionDecls[F->getName()] = F;
  813. }
  814. // Clone of StripDeadDebugInfo::runOnModule.
  815. // Also remove function which not not in current Module.
  816. void DxilLinkJob::StripDeadDebugInfo(Module &M) {
  817. LLVMContext &C = M.getContext();
  818. // Find all debug info in F. This is actually overkill in terms of what we
  819. // want to do, but we want to try and be as resilient as possible in the face
  820. // of potential debug info changes by using the formal interfaces given to us
  821. // as much as possible.
  822. DebugInfoFinder F;
  823. F.processModule(M);
  824. // For each compile unit, find the live set of global variables/functions and
  825. // replace the current list of potentially dead global variables/functions
  826. // with the live list.
  827. SmallVector<Metadata *, 64> LiveGlobalVariables;
  828. SmallVector<Metadata *, 64> LiveSubprograms;
  829. DenseSet<const MDNode *> VisitedSet;
  830. for (DICompileUnit *DIC : F.compile_units()) {
  831. // Create our live subprogram list.
  832. bool SubprogramChange = false;
  833. for (DISubprogram *DISP : DIC->getSubprograms()) {
  834. // Make sure we visit each subprogram only once.
  835. if (!VisitedSet.insert(DISP).second)
  836. continue;
  837. // If the function referenced by DISP is not null, the function is live.
  838. if (Function *Func = DISP->getFunction()) {
  839. if (Func->getParent() == &M)
  840. LiveSubprograms.push_back(DISP);
  841. else
  842. SubprogramChange = true;
  843. } else {
  844. SubprogramChange = true;
  845. }
  846. }
  847. // Create our live global variable list.
  848. bool GlobalVariableChange = false;
  849. for (DIGlobalVariable *DIG : DIC->getGlobalVariables()) {
  850. // Make sure we only visit each global variable only once.
  851. if (!VisitedSet.insert(DIG).second)
  852. continue;
  853. // If the global variable referenced by DIG is not null, the global
  854. // variable is live.
  855. if (Constant *CV = DIG->getVariable()) {
  856. if (GlobalVariable *GV = dyn_cast<GlobalVariable>(CV)) {
  857. if (GV->getParent() == &M) {
  858. LiveGlobalVariables.push_back(DIG);
  859. } else {
  860. GlobalVariableChange = true;
  861. }
  862. } else {
  863. LiveGlobalVariables.push_back(DIG);
  864. }
  865. } else {
  866. GlobalVariableChange = true;
  867. }
  868. }
  869. // If we found dead subprograms or global variables, replace the current
  870. // subprogram list/global variable list with our new live subprogram/global
  871. // variable list.
  872. if (SubprogramChange) {
  873. DIC->replaceSubprograms(MDTuple::get(C, LiveSubprograms));
  874. }
  875. if (GlobalVariableChange) {
  876. DIC->replaceGlobalVariables(MDTuple::get(C, LiveGlobalVariables));
  877. }
  878. // Reset lists for the next iteration.
  879. LiveSubprograms.clear();
  880. LiveGlobalVariables.clear();
  881. }
  882. }
  883. void DxilLinkJob::RunPreparePass(Module &M) {
  884. StripDeadDebugInfo(M);
  885. legacy::PassManager PM;
  886. PM.add(createAlwaysInlinerPass(/*InsertLifeTime*/ false));
  887. // Remove unused functions.
  888. PM.add(createDxilDeadFunctionEliminationPass());
  889. // SROA
  890. PM.add(createSROAPass(/*RequiresDomTree*/false, /*SkipHLSLMat*/false));
  891. // Remove MultiDimArray from function call arg.
  892. PM.add(createMultiDimArrayToOneDimArrayPass());
  893. // Lower matrix bitcast.
  894. PM.add(createMatrixBitcastLowerPass());
  895. // mem2reg.
  896. PM.add(createPromoteMemoryToRegisterPass());
  897. // Clean up vectors, and run mem2reg again
  898. PM.add(createScalarizerPass());
  899. PM.add(createPromoteMemoryToRegisterPass());
  900. PM.add(createSimplifyInstPass());
  901. PM.add(createCFGSimplificationPass());
  902. PM.add(createDeadCodeEliminationPass());
  903. PM.add(createGlobalDCEPass());
  904. PM.add(createDxilLowerCreateHandleForLibPass());
  905. PM.add(createDxilTranslateRawBuffer());
  906. PM.add(createDxilFinalizeModulePass());
  907. PM.add(createComputeViewIdStatePass());
  908. PM.add(createDxilDeadFunctionEliminationPass());
  909. PM.add(createNoPausePassesPass());
  910. PM.add(createDxilEmitMetadataPass());
  911. PM.run(M);
  912. }
  913. //------------------------------------------------------------------------------
  914. //
  915. // DxilLinkerImpl methods.
  916. //
  917. bool DxilLinkerImpl::HasLibNameRegistered(StringRef name) {
  918. return m_LibMap.count(name);
  919. }
  920. bool DxilLinkerImpl::RegisterLib(StringRef name,
  921. std::unique_ptr<llvm::Module> pModule,
  922. std::unique_ptr<llvm::Module> pDebugModule) {
  923. if (m_LibMap.count(name))
  924. return false;
  925. std::unique_ptr<llvm::Module> pM =
  926. pDebugModule ? std::move(pDebugModule) : std::move(pModule);
  927. if (!pM)
  928. return false;
  929. pM->setModuleIdentifier(name);
  930. std::unique_ptr<DxilLib> pLib =
  931. llvm::make_unique<DxilLib>(std::move(pM));
  932. m_LibMap[name] = std::move(pLib);
  933. return true;
  934. }
  935. bool DxilLinkerImpl::AttachLib(StringRef name) {
  936. auto iter = m_LibMap.find(name);
  937. if (iter == m_LibMap.end()) {
  938. return false;
  939. }
  940. return AttachLib(iter->second.get());
  941. }
  942. bool DxilLinkerImpl::DetachLib(StringRef name) {
  943. auto iter = m_LibMap.find(name);
  944. if (iter == m_LibMap.end()) {
  945. return false;
  946. }
  947. return DetachLib(iter->second.get());
  948. }
  949. void DxilLinkerImpl::DetachAll() {
  950. m_functionNameMap.clear();
  951. m_attachedLibs.clear();
  952. }
  953. bool DxilLinkerImpl::AttachLib(DxilLib *lib) {
  954. if (!lib) {
  955. // Invalid arg.
  956. return false;
  957. }
  958. if (m_attachedLibs.count(lib))
  959. return false;
  960. StringMap<std::unique_ptr<DxilFunctionLinkInfo>> &funcTable =
  961. lib->GetFunctionTable();
  962. bool bSuccess = true;
  963. for (auto it = funcTable.begin(), e = funcTable.end(); it != e; it++) {
  964. StringRef name = it->getKey();
  965. if (m_functionNameMap.count(name)) {
  966. // Redefine of function.
  967. const DxilFunctionLinkInfo *DFLI = it->getValue().get();
  968. dxilutil::EmitErrorOnFunction(DFLI->func, Twine(kRedefineFunction) + name);
  969. bSuccess = false;
  970. continue;
  971. }
  972. m_functionNameMap[name] = std::make_pair(it->second.get(), lib);
  973. }
  974. if (bSuccess) {
  975. m_attachedLibs.insert(lib);
  976. } else {
  977. for (auto it = funcTable.begin(), e = funcTable.end(); it != e; it++) {
  978. StringRef name = it->getKey();
  979. auto iter = m_functionNameMap.find(name);
  980. if (iter == m_functionNameMap.end())
  981. continue;
  982. // Remove functions of lib.
  983. if (m_functionNameMap[name].second == lib)
  984. m_functionNameMap.erase(name);
  985. }
  986. }
  987. return bSuccess;
  988. }
  989. bool DxilLinkerImpl::DetachLib(DxilLib *lib) {
  990. if (!lib) {
  991. // Invalid arg.
  992. return false;
  993. }
  994. if (!m_attachedLibs.count(lib))
  995. return false;
  996. m_attachedLibs.erase(lib);
  997. // Remove functions from lib.
  998. StringMap<std::unique_ptr<DxilFunctionLinkInfo>> &funcTable =
  999. lib->GetFunctionTable();
  1000. for (auto it = funcTable.begin(), e = funcTable.end(); it != e; it++) {
  1001. StringRef name = it->getKey();
  1002. m_functionNameMap.erase(name);
  1003. }
  1004. return true;
  1005. }
  1006. bool DxilLinkerImpl::AddFunctions(SmallVector<StringRef, 4> &workList,
  1007. SetVector<DxilLib *> &libSet,
  1008. SetVector<StringRef> &addedFunctionSet,
  1009. DxilLinkJob &linkJob, bool bLazyLoadDone,
  1010. bool bAllowFuncionDecls) {
  1011. while (!workList.empty()) {
  1012. StringRef name = workList.pop_back_val();
  1013. // Ignore added function.
  1014. if (addedFunctionSet.count(name))
  1015. continue;
  1016. if (!m_functionNameMap.count(name)) {
  1017. // Cannot find function, report error.
  1018. m_ctx.emitError(Twine(kUndefFunction) + name);
  1019. return false;
  1020. }
  1021. std::pair<DxilFunctionLinkInfo *, DxilLib *> &linkPair =
  1022. m_functionNameMap[name];
  1023. linkJob.AddFunction(linkPair);
  1024. DxilLib *pLib = linkPair.second;
  1025. libSet.insert(pLib);
  1026. if (!bLazyLoadDone) {
  1027. Function *F = linkPair.first->func;
  1028. pLib->LazyLoadFunction(F);
  1029. }
  1030. for (Function *F : linkPair.first->usedFunctions) {
  1031. if (hlsl::OP::IsDxilOpFunc(F) || F->isIntrinsic()) {
  1032. // Add dxil operations directly.
  1033. linkJob.AddFunction(F);
  1034. } else if (addedFunctionSet.count(F->getName()) == 0) {
  1035. if (bAllowFuncionDecls && F->isDeclaration() && !m_functionNameMap.count(F->getName())) {
  1036. // When linking to lib, use of undefined function is allowed; add directly.
  1037. linkJob.AddFunction(F);
  1038. } else {
  1039. // Push function name to work list.
  1040. workList.emplace_back(F->getName());
  1041. }
  1042. }
  1043. }
  1044. addedFunctionSet.insert(name);
  1045. }
  1046. return true;
  1047. }
  1048. std::unique_ptr<llvm::Module>
  1049. DxilLinkerImpl::Link(StringRef entry, StringRef profile, dxilutil::ExportMap &exportMap) {
  1050. const ShaderModel *pSM = ShaderModel::GetByName(profile.data());
  1051. DXIL::ShaderKind kind = pSM->GetKind();
  1052. if (kind == DXIL::ShaderKind::Invalid ||
  1053. (kind >= DXIL::ShaderKind::RayGeneration &&
  1054. kind <= DXIL::ShaderKind::Callable)) {
  1055. m_ctx.emitError(profile + Twine(kInvalidProfile));
  1056. // Invalid profile.
  1057. return nullptr;
  1058. }
  1059. if (!exportMap.empty() && kind != DXIL::ShaderKind::Library) {
  1060. m_ctx.emitError(Twine(kExportOnlyForLib));
  1061. return nullptr;
  1062. }
  1063. // Verifying validator version supports the requested profile
  1064. unsigned minValMajor, minValMinor;
  1065. pSM->GetMinValidatorVersion(minValMajor, minValMinor);
  1066. if (minValMajor > m_valMajor ||
  1067. (minValMajor == m_valMajor && minValMinor > m_valMinor)) {
  1068. m_ctx.emitError(Twine(kInvalidValidatorVersion) + profile);
  1069. return nullptr;
  1070. }
  1071. DxilLinkJob linkJob(m_ctx, exportMap, m_valMajor, m_valMinor);
  1072. SetVector<DxilLib *> libSet;
  1073. SetVector<StringRef> addedFunctionSet;
  1074. bool bIsLib = pSM->IsLib();
  1075. if (!bIsLib) {
  1076. SmallVector<StringRef, 4> workList;
  1077. workList.emplace_back(entry);
  1078. if (!AddFunctions(workList, libSet, addedFunctionSet, linkJob,
  1079. /*bLazyLoadDone*/ false,
  1080. /*bAllowFuncionDecls*/ false))
  1081. return nullptr;
  1082. } else {
  1083. if (exportMap.empty()) {
  1084. // Add every function for lib profile.
  1085. for (auto &it : m_functionNameMap) {
  1086. StringRef name = it.getKey();
  1087. std::pair<DxilFunctionLinkInfo *, DxilLib *> &linkPair = it.second;
  1088. DxilFunctionLinkInfo *linkInfo = linkPair.first;
  1089. DxilLib *pLib = linkPair.second;
  1090. Function *F = linkInfo->func;
  1091. pLib->LazyLoadFunction(F);
  1092. linkJob.AddFunction(linkPair);
  1093. libSet.insert(pLib);
  1094. addedFunctionSet.insert(name);
  1095. }
  1096. // Add every dxil function and llvm intrinsic.
  1097. for (auto *pLib : libSet) {
  1098. auto &DM = pLib->GetDxilModule();
  1099. DM.GetOP();
  1100. auto *pM = DM.GetModule();
  1101. for (Function &F : pM->functions()) {
  1102. if (hlsl::OP::IsDxilOpFunc(&F) || F.isIntrinsic() ||
  1103. (F.isDeclaration() && m_functionNameMap.count(F.getName()) == 0)) {
  1104. // Add intrinsics and function decls still not defined in any lib
  1105. linkJob.AddFunction(&F);
  1106. }
  1107. }
  1108. }
  1109. } else {
  1110. SmallVector<StringRef, 4> workList;
  1111. // Only add exported functions.
  1112. for (auto &it : m_functionNameMap) {
  1113. StringRef name = it.getKey();
  1114. // Only add names exist in exportMap.
  1115. if (exportMap.IsExported(name))
  1116. workList.emplace_back(name);
  1117. }
  1118. if (!AddFunctions(workList, libSet, addedFunctionSet, linkJob,
  1119. /*bLazyLoadDone*/ false,
  1120. /*bAllowFuncionDecls*/ true))
  1121. return nullptr;
  1122. }
  1123. }
  1124. // Save global users.
  1125. for (auto &pLib : libSet) {
  1126. pLib->BuildGlobalUsage();
  1127. }
  1128. SmallVector<StringRef, 4> workList;
  1129. // Save global ctor users.
  1130. for (auto &pLib : libSet) {
  1131. pLib->CollectUsedInitFunctions(addedFunctionSet, workList);
  1132. }
  1133. // Add init functions if used.
  1134. // All init function already loaded in BuildGlobalUsage,
  1135. // so set bLazyLoadDone to true here.
  1136. // Decls should have been added to addedFunctionSet if lib,
  1137. // so set bAllowFuncionDecls is false here.
  1138. if (!AddFunctions(workList, libSet, addedFunctionSet, linkJob,
  1139. /*bLazyLoadDone*/ true,
  1140. /*bAllowFuncionDecls*/ false))
  1141. return nullptr;
  1142. if (!bIsLib) {
  1143. std::pair<DxilFunctionLinkInfo *, DxilLib *> &entryLinkPair =
  1144. m_functionNameMap[entry];
  1145. return linkJob.Link(entryLinkPair, pSM);
  1146. } else {
  1147. return linkJob.LinkToLib(pSM);
  1148. }
  1149. }
  1150. namespace hlsl {
  1151. DxilLinker *DxilLinker::CreateLinker(LLVMContext &Ctx, unsigned valMajor, unsigned valMinor) {
  1152. return new DxilLinkerImpl(Ctx, valMajor, valMinor);
  1153. }
  1154. } // namespace hlsl