DxilLinker.cpp 46 KB

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