DxilLinker.cpp 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557
  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. // Fix issues when link to different shader model.
  312. void FixShaderModelMismatch(llvm::Module &M);
  313. void RunPreparePass(llvm::Module &M);
  314. void AddFunction(std::pair<DxilFunctionLinkInfo *, DxilLib *> &linkPair);
  315. void AddFunction(llvm::Function *F);
  316. private:
  317. void LinkNamedMDNodes(Module *pM, ValueToValueMapTy &vmap);
  318. void AddFunctionDecls(Module *pM);
  319. bool AddGlobals(DxilModule &DM, ValueToValueMapTy &vmap);
  320. void EmitCtorListForLib(Module *pM);
  321. void CloneFunctions(ValueToValueMapTy &vmap);
  322. void AddFunctions(DxilModule &DM, ValueToValueMapTy &vmap);
  323. bool AddResource(DxilResourceBase *res, llvm::GlobalVariable *GV);
  324. void AddResourceToDM(DxilModule &DM);
  325. llvm::MapVector<DxilFunctionLinkInfo *, DxilLib *> m_functionDefs;
  326. // Function decls, in order added.
  327. llvm::MapVector<llvm::StringRef,
  328. std::pair<llvm::SmallPtrSet<llvm::FunctionType *, 2>,
  329. llvm::SmallVector<llvm::Function *, 2>>>
  330. m_functionDecls;
  331. // New created functions, in order added.
  332. llvm::MapVector<llvm::StringRef, llvm::Function *> m_newFunctions;
  333. // New created globals, in order added.
  334. llvm::MapVector<llvm::StringRef, llvm::GlobalVariable *> m_newGlobals;
  335. // Map for resource, ordered by name.
  336. std::map<llvm::StringRef,
  337. std::pair<DxilResourceBase *, llvm::GlobalVariable *>>
  338. m_resourceMap;
  339. LLVMContext &m_ctx;
  340. dxilutil::ExportMap &m_exportMap;
  341. unsigned m_valMajor, m_valMinor;
  342. };
  343. } // namespace
  344. namespace {
  345. const char kUndefFunction[] = "Cannot find definition of function ";
  346. const char kRedefineFunction[] = "Definition already exists for function ";
  347. const char kRedefineGlobal[] = "Definition already exists for global variable ";
  348. const char kInvalidProfile[] = " is invalid profile to link";
  349. const char kExportOnlyForLib[] = "export map is only for library";
  350. const char kShaderKindMismatch[] =
  351. "Profile mismatch between entry function and target profile:";
  352. const char kNoEntryProps[] =
  353. "Cannot find function property for entry function ";
  354. const char kRedefineResource[] =
  355. "Resource already exists as ";
  356. const char kInvalidValidatorVersion[] = "Validator version does not support target profile ";
  357. const char kExportNameCollision[] = "Export name collides with another export: ";
  358. const char kExportFunctionMissing[] = "Could not find target for export: ";
  359. const char kNoFunctionsToExport[] = "Library has no functions to export";
  360. } // namespace
  361. //------------------------------------------------------------------------------
  362. //
  363. // DxilLinkJob methods.
  364. //
  365. namespace {
  366. // Helper function to check type match.
  367. bool IsMatchedType(Type *Ty0, Type *Ty);
  368. StringRef RemoveNameSuffix(StringRef Name) {
  369. size_t DotPos = Name.rfind('.');
  370. if (DotPos != StringRef::npos && Name.back() != '.' &&
  371. isdigit(static_cast<unsigned char>(Name[DotPos + 1])))
  372. Name = Name.substr(0, DotPos);
  373. return Name;
  374. }
  375. bool IsMatchedStructType(StructType *ST0, StructType *ST) {
  376. StringRef Name0 = RemoveNameSuffix(ST0->getName());
  377. StringRef Name = RemoveNameSuffix(ST->getName());
  378. if (Name0 != Name)
  379. return false;
  380. if (ST0->getNumElements() != ST->getNumElements())
  381. return false;
  382. if (ST0->isLayoutIdentical(ST))
  383. return true;
  384. for (unsigned i = 0; i < ST->getNumElements(); i++) {
  385. Type *Ty = ST->getElementType(i);
  386. Type *Ty0 = ST0->getElementType(i);
  387. if (!IsMatchedType(Ty, Ty0))
  388. return false;
  389. }
  390. return true;
  391. }
  392. bool IsMatchedArrayType(ArrayType *AT0, ArrayType *AT) {
  393. if (AT0->getNumElements() != AT->getNumElements())
  394. return false;
  395. return IsMatchedType(AT0->getElementType(), AT->getElementType());
  396. }
  397. bool IsMatchedType(Type *Ty0, Type *Ty) {
  398. if (Ty0->isStructTy() && Ty->isStructTy()) {
  399. StructType *ST0 = cast<StructType>(Ty0);
  400. StructType *ST = cast<StructType>(Ty);
  401. return IsMatchedStructType(ST0, ST);
  402. }
  403. if (Ty0->isArrayTy() && Ty->isArrayTy()) {
  404. ArrayType *AT0 = cast<ArrayType>(Ty0);
  405. ArrayType *AT = cast<ArrayType>(Ty);
  406. return IsMatchedArrayType(AT0, AT);
  407. }
  408. if (Ty0->isPointerTy() && Ty->isPointerTy()) {
  409. if (Ty0->getPointerAddressSpace() != Ty->getPointerAddressSpace())
  410. return false;
  411. return IsMatchedType(Ty0->getPointerElementType(),
  412. Ty->getPointerElementType());
  413. }
  414. return Ty0 == Ty;
  415. }
  416. } // namespace
  417. bool DxilLinkJob::AddResource(DxilResourceBase *res, llvm::GlobalVariable *GV) {
  418. if (m_resourceMap.count(res->GetGlobalName())) {
  419. DxilResourceBase *res0 = m_resourceMap[res->GetGlobalName()].first;
  420. Type *Ty0 = res0->GetHLSLType()->getPointerElementType();
  421. Type *Ty = res->GetHLSLType()->getPointerElementType();
  422. // Make sure res0 match res.
  423. bool bMatch = IsMatchedType(Ty0, Ty);
  424. if (!bMatch) {
  425. // Report error.
  426. dxilutil::EmitErrorOnGlobalVariable(dyn_cast<GlobalVariable>(res->GetGlobalSymbol()),
  427. Twine(kRedefineResource) + res->GetResClassName() + " for " +
  428. res->GetGlobalName());
  429. return false;
  430. }
  431. } else {
  432. m_resourceMap[res->GetGlobalName()] = std::make_pair(res, GV);
  433. }
  434. return true;
  435. }
  436. void DxilLinkJob::AddResourceToDM(DxilModule &DM) {
  437. for (auto &it : m_resourceMap) {
  438. DxilResourceBase *res = it.second.first;
  439. GlobalVariable *GV = it.second.second;
  440. unsigned ID = 0;
  441. DxilResourceBase *basePtr = nullptr;
  442. switch (res->GetClass()) {
  443. case DXIL::ResourceClass::UAV: {
  444. std::unique_ptr<DxilResource> pUAV = llvm::make_unique<DxilResource>();
  445. DxilResource *ptr = pUAV.get();
  446. // Copy the content.
  447. *ptr = *(static_cast<DxilResource *>(res));
  448. ID = DM.AddUAV(std::move(pUAV));
  449. basePtr = &DM.GetUAV(ID);
  450. } break;
  451. case DXIL::ResourceClass::SRV: {
  452. std::unique_ptr<DxilResource> pSRV = llvm::make_unique<DxilResource>();
  453. DxilResource *ptr = pSRV.get();
  454. // Copy the content.
  455. *ptr = *(static_cast<DxilResource *>(res));
  456. ID = DM.AddSRV(std::move(pSRV));
  457. basePtr = &DM.GetSRV(ID);
  458. } break;
  459. case DXIL::ResourceClass::CBuffer: {
  460. std::unique_ptr<DxilCBuffer> pCBuf = llvm::make_unique<DxilCBuffer>();
  461. DxilCBuffer *ptr = pCBuf.get();
  462. // Copy the content.
  463. *ptr = *(static_cast<DxilCBuffer *>(res));
  464. ID = DM.AddCBuffer(std::move(pCBuf));
  465. basePtr = &DM.GetCBuffer(ID);
  466. } break;
  467. case DXIL::ResourceClass::Sampler: {
  468. std::unique_ptr<DxilSampler> pSampler = llvm::make_unique<DxilSampler>();
  469. DxilSampler *ptr = pSampler.get();
  470. // Copy the content.
  471. *ptr = *(static_cast<DxilSampler *>(res));
  472. ID = DM.AddSampler(std::move(pSampler));
  473. basePtr = &DM.GetSampler(ID);
  474. }
  475. default:
  476. DXASSERT(res->GetClass() == DXIL::ResourceClass::Sampler,
  477. "else invalid resource");
  478. break;
  479. }
  480. // Update ID.
  481. basePtr->SetID(ID);
  482. basePtr->SetGlobalSymbol(GV);
  483. DM.GetLLVMUsed().push_back(GV);
  484. }
  485. // Prevent global vars used for resources from being deleted through optimizations
  486. // while we still have hidden uses (pointers in resource vectors).
  487. DM.EmitLLVMUsed();
  488. }
  489. void DxilLinkJob::LinkNamedMDNodes(Module *pM, ValueToValueMapTy &vmap) {
  490. SetVector<Module *> moduleSet;
  491. for (auto &it : m_functionDefs) {
  492. DxilLib *pLib = it.second;
  493. moduleSet.insert(pLib->GetDxilModule().GetModule());
  494. }
  495. // Link normal NamedMDNode.
  496. // TODO: skip duplicate operands.
  497. for (Module *pSrcM : moduleSet) {
  498. const NamedMDNode *pSrcModFlags = pSrcM->getModuleFlagsMetadata();
  499. for (const NamedMDNode &NMD : pSrcM->named_metadata()) {
  500. // Don't link module flags here. Do them separately.
  501. if (&NMD == pSrcModFlags)
  502. continue;
  503. // Skip dxil metadata which will be regenerated.
  504. if (DxilMDHelper::IsKnownNamedMetaData(NMD))
  505. continue;
  506. NamedMDNode *DestNMD = pM->getOrInsertNamedMetadata(NMD.getName());
  507. // Add Src elements into Dest node.
  508. for (const MDNode *op : NMD.operands())
  509. DestNMD->addOperand(MapMetadata(op, vmap, RF_None, /*TypeMap*/ nullptr,
  510. /*ValMaterializer*/ nullptr));
  511. }
  512. }
  513. // Link mod flags.
  514. SetVector<MDNode *> flagSet;
  515. for (Module *pSrcM : moduleSet) {
  516. NamedMDNode *pSrcModFlags = pSrcM->getModuleFlagsMetadata();
  517. if (pSrcModFlags) {
  518. for (MDNode *flag : pSrcModFlags->operands()) {
  519. flagSet.insert(flag);
  520. }
  521. }
  522. }
  523. // TODO: check conflict in flags.
  524. if (!flagSet.empty()) {
  525. NamedMDNode *ModFlags = pM->getOrInsertModuleFlagsMetadata();
  526. for (MDNode *flag : flagSet) {
  527. ModFlags->addOperand(flag);
  528. }
  529. }
  530. }
  531. void DxilLinkJob::AddFunctionDecls(Module *pM) {
  532. for (auto &it : m_functionDecls) {
  533. for (auto F : it.second.second) {
  534. Function *NewF = pM->getFunction(F->getName());
  535. if (!NewF || F->getFunctionType() != NewF->getFunctionType()) {
  536. NewF = Function::Create(F->getFunctionType(), F->getLinkage(),
  537. F->getName(), pM);
  538. NewF->setAttributes(F->getAttributes());
  539. }
  540. m_newFunctions[F->getName()] = NewF;
  541. }
  542. }
  543. }
  544. bool DxilLinkJob::AddGlobals(DxilModule &DM, ValueToValueMapTy &vmap) {
  545. DxilTypeSystem &typeSys = DM.GetTypeSystem();
  546. Module *pM = DM.GetModule();
  547. bool bSuccess = true;
  548. for (auto &it : m_functionDefs) {
  549. DxilFunctionLinkInfo *linkInfo = it.first;
  550. DxilLib *pLib = it.second;
  551. DxilModule &tmpDM = pLib->GetDxilModule();
  552. DxilTypeSystem &tmpTypeSys = tmpDM.GetTypeSystem();
  553. for (GlobalVariable *GV : linkInfo->usedGVs) {
  554. // Skip added globals.
  555. if (m_newGlobals.count(GV->getName())) {
  556. if (vmap.find(GV) == vmap.end()) {
  557. if (DxilResourceBase *res = pLib->GetResource(GV)) {
  558. // For resource of same name, if class and type match, just map to
  559. // same NewGV.
  560. GlobalVariable *NewGV = m_newGlobals[GV->getName()];
  561. if (AddResource(res, NewGV)) {
  562. vmap[GV] = NewGV;
  563. } else {
  564. bSuccess = false;
  565. }
  566. continue;
  567. }
  568. // Redefine of global.
  569. dxilutil::EmitErrorOnGlobalVariable(GV, Twine(kRedefineGlobal) + GV->getName());
  570. bSuccess = false;
  571. }
  572. continue;
  573. }
  574. Constant *Initializer = nullptr;
  575. if (GV->hasInitializer())
  576. Initializer = GV->getInitializer();
  577. Type *Ty = GV->getType()->getElementType();
  578. GlobalVariable *NewGV = new GlobalVariable(
  579. *pM, Ty, GV->isConstant(), GV->getLinkage(), Initializer,
  580. GV->getName(),
  581. /*InsertBefore*/ nullptr, GV->getThreadLocalMode(),
  582. GV->getType()->getAddressSpace(), GV->isExternallyInitialized());
  583. m_newGlobals[GV->getName()] = NewGV;
  584. vmap[GV] = NewGV;
  585. typeSys.CopyTypeAnnotation(Ty, tmpTypeSys);
  586. if (DxilResourceBase *res = pLib->GetResource(GV)) {
  587. bSuccess &= AddResource(res, NewGV);
  588. }
  589. }
  590. }
  591. return bSuccess;
  592. }
  593. void DxilLinkJob::CloneFunctions(ValueToValueMapTy &vmap) {
  594. for (auto &it : m_functionDefs) {
  595. DxilFunctionLinkInfo *linkInfo = it.first;
  596. Function *F = linkInfo->func;
  597. Function *NewF = m_newFunctions[F->getName()];
  598. // Add dxil functions to vmap.
  599. for (Function *UsedF : linkInfo->usedFunctions) {
  600. if (!vmap.count(UsedF)) {
  601. // Extern function need match by name
  602. DXASSERT(m_newFunctions.count(UsedF->getName()),
  603. "Must have new function.");
  604. vmap[UsedF] = m_newFunctions[UsedF->getName()];
  605. }
  606. }
  607. CloneFunction(F, NewF, vmap);
  608. }
  609. }
  610. void DxilLinkJob::AddFunctions(DxilModule &DM, ValueToValueMapTy &vmap) {
  611. DxilTypeSystem &typeSys = DM.GetTypeSystem();
  612. Module *pM = DM.GetModule();
  613. for (auto &it : m_functionDefs) {
  614. DxilFunctionLinkInfo *linkInfo = it.first;
  615. DxilLib *pLib = it.second;
  616. DxilModule &tmpDM = pLib->GetDxilModule();
  617. DxilTypeSystem &tmpTypeSys = tmpDM.GetTypeSystem();
  618. Function *F = linkInfo->func;
  619. Function *NewF = Function::Create(F->getFunctionType(), F->getLinkage(),
  620. F->getName(), pM);
  621. NewF->setAttributes(F->getAttributes());
  622. if (!NewF->hasFnAttribute(llvm::Attribute::NoInline))
  623. NewF->addFnAttr(llvm::Attribute::AlwaysInline);
  624. if (DxilFunctionAnnotation *funcAnnotation =
  625. tmpTypeSys.GetFunctionAnnotation(F)) {
  626. // Clone funcAnnotation to typeSys.
  627. typeSys.CopyFunctionAnnotation(NewF, F, tmpTypeSys);
  628. }
  629. // Add to function map.
  630. m_newFunctions[NewF->getName()] = NewF;
  631. vmap[F] = NewF;
  632. }
  633. }
  634. std::unique_ptr<Module>
  635. DxilLinkJob::Link(std::pair<DxilFunctionLinkInfo *, DxilLib *> &entryLinkPair,
  636. const ShaderModel *pSM) {
  637. Function *entryFunc = entryLinkPair.first->func;
  638. DxilModule &entryDM = entryLinkPair.second->GetDxilModule();
  639. if (!entryDM.HasDxilFunctionProps(entryFunc)) {
  640. // Cannot get function props.
  641. dxilutil::EmitErrorOnFunction(entryFunc, Twine(kNoEntryProps) + entryFunc->getName());
  642. return nullptr;
  643. }
  644. DxilFunctionProps props = entryDM.GetDxilFunctionProps(entryFunc);
  645. if (pSM->GetKind() != props.shaderKind) {
  646. // Shader kind mismatch.
  647. dxilutil::EmitErrorOnFunction(entryFunc, Twine(kShaderKindMismatch) +
  648. ShaderModel::GetKindName(pSM->GetKind()) + " and " +
  649. ShaderModel::GetKindName(props.shaderKind));
  650. return nullptr;
  651. }
  652. // Create new module.
  653. std::unique_ptr<Module> pM =
  654. llvm::make_unique<Module>(entryFunc->getName(), entryDM.GetCtx());
  655. // Set target.
  656. pM->setTargetTriple(entryDM.GetModule()->getTargetTriple());
  657. // Add dxil operation functions before create DxilModule.
  658. AddFunctionDecls(pM.get());
  659. // Create DxilModule.
  660. const bool bSkipInit = true;
  661. DxilModule &DM = pM->GetOrCreateDxilModule(bSkipInit);
  662. DM.SetShaderModel(pSM, entryDM.GetUseMinPrecision());
  663. // Set Validator version.
  664. DM.SetValidatorVersion(m_valMajor, m_valMinor);
  665. ValueToValueMapTy vmap;
  666. // Add function
  667. AddFunctions(DM, vmap);
  668. // Set Entry
  669. Function *NewEntryFunc = m_newFunctions[entryFunc->getName()];
  670. DM.SetEntryFunction(NewEntryFunc);
  671. DM.SetEntryFunctionName(entryFunc->getName());
  672. DxilEntryPropsMap EntryPropMap;
  673. std::unique_ptr<DxilEntryProps> pProps =
  674. llvm::make_unique<DxilEntryProps>(entryDM.GetDxilEntryProps(entryFunc));
  675. EntryPropMap[NewEntryFunc] = std::move(pProps);
  676. DM.ResetEntryPropsMap(std::move(EntryPropMap));
  677. if (NewEntryFunc->hasFnAttribute(llvm::Attribute::AlwaysInline))
  678. NewEntryFunc->removeFnAttr(llvm::Attribute::AlwaysInline);
  679. if (props.IsHS()) {
  680. Function *patchConstantFunc = props.ShaderProps.HS.patchConstantFunc;
  681. Function *newPatchConstantFunc =
  682. m_newFunctions[patchConstantFunc->getName()];
  683. props.ShaderProps.HS.patchConstantFunc = newPatchConstantFunc;
  684. if (newPatchConstantFunc->hasFnAttribute(llvm::Attribute::AlwaysInline))
  685. newPatchConstantFunc->removeFnAttr(llvm::Attribute::AlwaysInline);
  686. }
  687. // Set EntryProps
  688. DM.SetShaderProperties(&props);
  689. // Add global
  690. bool bSuccess = AddGlobals(DM, vmap);
  691. if (!bSuccess)
  692. return nullptr;
  693. // Clone functions.
  694. CloneFunctions(vmap);
  695. // Call global constrctor.
  696. IRBuilder<> Builder(dxilutil::FindAllocaInsertionPt(DM.GetEntryFunction()));
  697. for (auto &it : m_functionDefs) {
  698. DxilFunctionLinkInfo *linkInfo = it.first;
  699. DxilLib *pLib = it.second;
  700. // Skip constructor in entry lib which is already called for entries inside
  701. // entry lib.
  702. if (pLib == entryLinkPair.second)
  703. continue;
  704. Function *F = linkInfo->func;
  705. if (pLib->IsInitFunc(F)) {
  706. Function *NewF = m_newFunctions[F->getName()];
  707. Builder.CreateCall(NewF);
  708. }
  709. }
  710. // Refresh intrinsic cache.
  711. DM.GetOP()->RefreshCache();
  712. // Add resource to DM.
  713. // This should be after functions cloned.
  714. AddResourceToDM(DM);
  715. // Link metadata like debug info.
  716. LinkNamedMDNodes(pM.get(), vmap);
  717. RunPreparePass(*pM);
  718. return pM;
  719. }
  720. // Based on CodeGenModule::EmitCtorList.
  721. void DxilLinkJob::EmitCtorListForLib(Module *pM) {
  722. LLVMContext &Ctx = pM->getContext();
  723. Type *VoidTy = Type::getVoidTy(Ctx);
  724. Type *Int32Ty = Type::getInt32Ty(Ctx);
  725. Type *VoidPtrTy = Type::getInt8PtrTy(Ctx);
  726. // Ctor function type is void()*.
  727. llvm::FunctionType *CtorFTy = llvm::FunctionType::get(VoidTy, false);
  728. llvm::Type *CtorPFTy = llvm::PointerType::getUnqual(CtorFTy);
  729. // Get the type of a ctor entry, { i32, void ()*, i8* }.
  730. llvm::StructType *CtorStructTy = llvm::StructType::get(
  731. Int32Ty, llvm::PointerType::getUnqual(CtorFTy), VoidPtrTy, nullptr);
  732. // Construct the constructor and destructor arrays.
  733. SmallVector<llvm::Constant *, 8> Ctors;
  734. for (auto &it : m_functionDefs) {
  735. DxilFunctionLinkInfo *linkInfo = it.first;
  736. DxilLib *pLib = it.second;
  737. Function *F = linkInfo->func;
  738. if (pLib->IsInitFunc(F)) {
  739. Function *NewF = m_newFunctions[F->getName()];
  740. llvm::Constant *S[] = {
  741. llvm::ConstantInt::get(Int32Ty, 65535, false),
  742. llvm::ConstantExpr::getBitCast(NewF, CtorPFTy),
  743. (llvm::Constant::getNullValue(VoidPtrTy))};
  744. Ctors.push_back(llvm::ConstantStruct::get(CtorStructTy, S));
  745. }
  746. }
  747. if (!Ctors.empty()) {
  748. const StringRef GlobalName = "llvm.global_ctors";
  749. llvm::ArrayType *AT = llvm::ArrayType::get(CtorStructTy, Ctors.size());
  750. new llvm::GlobalVariable(*pM, AT, false,
  751. llvm::GlobalValue::AppendingLinkage,
  752. llvm::ConstantArray::get(AT, Ctors), GlobalName);
  753. }
  754. }
  755. std::unique_ptr<Module>
  756. DxilLinkJob::LinkToLib(const ShaderModel *pSM) {
  757. if (m_functionDefs.empty()) {
  758. m_ctx.emitError(Twine(kNoFunctionsToExport));
  759. return nullptr;
  760. }
  761. DxilLib *pLib = m_functionDefs.begin()->second;
  762. DxilModule &tmpDM = pLib->GetDxilModule();
  763. // Create new module.
  764. std::unique_ptr<Module> pM =
  765. llvm::make_unique<Module>("merged_lib", tmpDM.GetCtx());
  766. // Set target.
  767. pM->setTargetTriple(tmpDM.GetModule()->getTargetTriple());
  768. // Add dxil operation functions and external decls before create DxilModule.
  769. AddFunctionDecls(pM.get());
  770. // Create DxilModule.
  771. const bool bSkipInit = true;
  772. DxilModule &DM = pM->GetOrCreateDxilModule(bSkipInit);
  773. DM.SetShaderModel(pSM, tmpDM.GetUseMinPrecision());
  774. // Set Validator version.
  775. DM.SetValidatorVersion(m_valMajor, m_valMinor);
  776. ValueToValueMapTy vmap;
  777. // Add function
  778. AddFunctions(DM, vmap);
  779. // Set DxilFunctionProps.
  780. DxilEntryPropsMap EntryPropMap;
  781. for (auto &it : m_functionDefs) {
  782. DxilFunctionLinkInfo *linkInfo = it.first;
  783. DxilLib *pLib = it.second;
  784. DxilModule &tmpDM = pLib->GetDxilModule();
  785. Function *F = linkInfo->func;
  786. if (tmpDM.HasDxilEntryProps(F)) {
  787. Function *NewF = m_newFunctions[F->getName()];
  788. DxilEntryProps &props = tmpDM.GetDxilEntryProps(F);
  789. std::unique_ptr<DxilEntryProps> pProps =
  790. llvm::make_unique<DxilEntryProps>(props);
  791. EntryPropMap[NewF] = std::move(pProps);
  792. }
  793. }
  794. DM.ResetEntryPropsMap(std::move(EntryPropMap));
  795. // Add global
  796. bool bSuccess = AddGlobals(DM, vmap);
  797. if (!bSuccess)
  798. return nullptr;
  799. // Clone functions.
  800. CloneFunctions(vmap);
  801. // Refresh intrinsic cache.
  802. DM.GetOP()->RefreshCache();
  803. // Add resource to DM.
  804. // This should be after functions cloned.
  805. AddResourceToDM(DM);
  806. // Link metadata like debug info.
  807. LinkNamedMDNodes(pM.get(), vmap);
  808. // Build global.ctors.
  809. EmitCtorListForLib(pM.get());
  810. RunPreparePass(*pM);
  811. if (!m_exportMap.empty()) {
  812. m_exportMap.BeginProcessing();
  813. DM.ClearDxilMetadata(*pM);
  814. for (auto it = pM->begin(); it != pM->end();) {
  815. Function *F = it++;
  816. if (F->isDeclaration())
  817. continue;
  818. if (!m_exportMap.ProcessFunction(F, true)) {
  819. // Remove Function not in exportMap.
  820. DM.RemoveFunction(F);
  821. F->eraseFromParent();
  822. }
  823. }
  824. if(!m_exportMap.EndProcessing()) {
  825. for (auto &name : m_exportMap.GetNameCollisions()) {
  826. std::string escaped;
  827. llvm::raw_string_ostream os(escaped);
  828. dxilutil::PrintEscapedString(name, os);
  829. m_ctx.emitError(Twine(kExportNameCollision) + os.str());
  830. }
  831. for (auto &name : m_exportMap.GetUnusedExports()) {
  832. std::string escaped;
  833. llvm::raw_string_ostream os(escaped);
  834. dxilutil::PrintEscapedString(name, os);
  835. m_ctx.emitError(Twine(kExportFunctionMissing) + os.str());
  836. }
  837. return nullptr;
  838. }
  839. // Rename the original, if necessary, then clone the rest
  840. for (auto &it : m_exportMap.GetFunctionRenames()) {
  841. Function *F = it.first;
  842. auto &renames = it.second;
  843. if (renames.empty())
  844. continue;
  845. auto itName = renames.begin();
  846. // Rename the original, if necessary, then clone the rest
  847. if (renames.find(F->getName()) == renames.end())
  848. F->setName(*(itName++));
  849. while (itName != renames.end()) {
  850. if (F->getName() != *itName) {
  851. Function *NewF = Function::Create(F->getFunctionType(),
  852. GlobalValue::LinkageTypes::ExternalLinkage,
  853. *itName, DM.GetModule());
  854. ValueToValueMapTy vmap;
  855. CloneFunction(F, NewF, vmap, &DM.GetTypeSystem());
  856. // add DxilFunctionProps if entry
  857. if (DM.HasDxilFunctionProps(F)) {
  858. DM.CloneDxilEntryProps(F, NewF);
  859. }
  860. }
  861. itName++;
  862. }
  863. }
  864. DM.EmitDxilMetadata();
  865. }
  866. return pM;
  867. }
  868. void DxilLinkJob::AddFunction(
  869. std::pair<DxilFunctionLinkInfo *, DxilLib *> &linkPair) {
  870. m_functionDefs[linkPair.first] = linkPair.second;
  871. }
  872. void DxilLinkJob::AddFunction(llvm::Function *F) {
  873. // Rarely, DXIL op overloads could collide, due to different types with same name.
  874. // Later, we will rename these functions, but for now, we need to prevent clobbering
  875. // an existing entry.
  876. auto &entry = m_functionDecls[F->getName()];
  877. if (entry.first.insert(F->getFunctionType()).second)
  878. entry.second.push_back(F);
  879. }
  880. // Clone of StripDeadDebugInfo::runOnModule.
  881. // Also remove function which not not in current Module.
  882. void DxilLinkJob::StripDeadDebugInfo(Module &M) {
  883. LLVMContext &C = M.getContext();
  884. // Find all debug info in F. This is actually overkill in terms of what we
  885. // want to do, but we want to try and be as resilient as possible in the face
  886. // of potential debug info changes by using the formal interfaces given to us
  887. // as much as possible.
  888. DebugInfoFinder F;
  889. F.processModule(M);
  890. // For each compile unit, find the live set of global variables/functions and
  891. // replace the current list of potentially dead global variables/functions
  892. // with the live list.
  893. SmallVector<Metadata *, 64> LiveGlobalVariables;
  894. SmallVector<Metadata *, 64> LiveSubprograms;
  895. DenseSet<const MDNode *> VisitedSet;
  896. for (DICompileUnit *DIC : F.compile_units()) {
  897. // Create our live subprogram list.
  898. bool SubprogramChange = false;
  899. for (DISubprogram *DISP : DIC->getSubprograms()) {
  900. // Make sure we visit each subprogram only once.
  901. if (!VisitedSet.insert(DISP).second)
  902. continue;
  903. // If the function referenced by DISP is not null, the function is live.
  904. if (Function *Func = DISP->getFunction()) {
  905. if (Func->getParent() == &M)
  906. LiveSubprograms.push_back(DISP);
  907. else
  908. SubprogramChange = true;
  909. } else {
  910. SubprogramChange = true;
  911. }
  912. }
  913. // Create our live global variable list.
  914. bool GlobalVariableChange = false;
  915. for (DIGlobalVariable *DIG : DIC->getGlobalVariables()) {
  916. // Make sure we only visit each global variable only once.
  917. if (!VisitedSet.insert(DIG).second)
  918. continue;
  919. // If the global variable referenced by DIG is not null, the global
  920. // variable is live.
  921. if (Constant *CV = DIG->getVariable()) {
  922. if (GlobalVariable *GV = dyn_cast<GlobalVariable>(CV)) {
  923. if (GV->getParent() == &M) {
  924. LiveGlobalVariables.push_back(DIG);
  925. } else {
  926. GlobalVariableChange = true;
  927. }
  928. } else {
  929. LiveGlobalVariables.push_back(DIG);
  930. }
  931. } else {
  932. GlobalVariableChange = true;
  933. }
  934. }
  935. // If we found dead subprograms or global variables, replace the current
  936. // subprogram list/global variable list with our new live subprogram/global
  937. // variable list.
  938. if (SubprogramChange) {
  939. DIC->replaceSubprograms(MDTuple::get(C, LiveSubprograms));
  940. }
  941. if (GlobalVariableChange) {
  942. DIC->replaceGlobalVariables(MDTuple::get(C, LiveGlobalVariables));
  943. }
  944. // Reset lists for the next iteration.
  945. LiveSubprograms.clear();
  946. LiveGlobalVariables.clear();
  947. }
  948. }
  949. // TODO: move FixShaderModelMismatch to separate file.
  950. #include "dxc/DXIL/DxilInstructions.h"
  951. namespace {
  952. bool onlyUsedByAnnotateHandle(Value *V) {
  953. bool bResult = true;
  954. for (User *U : V->users()) {
  955. CallInst *CI = dyn_cast<CallInst>(U);
  956. if (!CI) {
  957. bResult = false;
  958. break;
  959. }
  960. DxilInst_AnnotateHandle Hdl(CI);
  961. if (!Hdl) {
  962. bResult = false;
  963. break;
  964. }
  965. }
  966. return bResult;
  967. }
  968. DxilResourceBase *
  969. findResourceFromPtr(Value *Ptr, DxilModule &DM,
  970. DenseMap<Value *, DxilResourceBase *> &PtrResMap) {
  971. auto it = PtrResMap.find(Ptr);
  972. if (Ptr)
  973. return it->second;
  974. DxilResourceBase *Res = nullptr;
  975. if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Ptr)) {
  976. DXASSERT(false, "global resource should already in map");
  977. } else {
  978. // Not support allocaInst of resource when missing annotateHandle.
  979. GEPOperator *GEP = cast<GEPOperator>(Ptr);
  980. Res = findResourceFromPtr(GEP->getPointerOperand(), DM, PtrResMap);
  981. }
  982. PtrResMap[Ptr] = Res;
  983. return Res;
  984. }
  985. template <typename T>
  986. void addGVFromResTable(T &Tab,
  987. DenseMap<Value *, DxilResourceBase *> &PtrResMap) {
  988. for (auto &it : Tab) {
  989. PtrResMap[it->GetGlobalSymbol()] = it.get();
  990. }
  991. }
  992. // Make sure createHandleForLib is annotated before use.
  993. bool addAnnotHandle(Module &M, DxilModule &DM) {
  994. hlsl::OP *hlslOP = DM.GetOP();
  995. auto *pSM = DM.GetShaderModel();
  996. if (!pSM->IsSM66Plus())
  997. return false;
  998. // If no createHandleForLib, do nothing.
  999. if (!hlslOP->IsDxilOpUsed(DXIL::OpCode::CreateHandleForLib))
  1000. return false;
  1001. Type *pVoidTy = Type::getVoidTy(M.getContext());
  1002. SmallVector<CallInst *, 4> Candidates;
  1003. for (Function &F : M) {
  1004. if (!F.isDeclaration())
  1005. continue;
  1006. if (!hlslOP->IsDxilOpFunc(&F))
  1007. continue;
  1008. DXIL::OpCodeClass opClass;
  1009. if (!hlslOP->GetOpCodeClass(&F, opClass))
  1010. continue;
  1011. if (opClass != DXIL::OpCodeClass::CreateHandleForLib)
  1012. continue;
  1013. for (User *U : F.users()) {
  1014. CallInst *CI = cast<CallInst>(U);
  1015. // Check user is annotateHandle.
  1016. if (onlyUsedByAnnotateHandle(CI))
  1017. continue;
  1018. Candidates.emplace_back(CI);
  1019. }
  1020. }
  1021. if (Candidates.empty())
  1022. return false;
  1023. DenseMap<Value *, DxilResourceBase *> PtrResMap;
  1024. // Add GV from resTable first.
  1025. addGVFromResTable(DM.GetCBuffers(), PtrResMap);
  1026. addGVFromResTable(DM.GetSRVs(), PtrResMap);
  1027. addGVFromResTable(DM.GetUAVs(), PtrResMap);
  1028. addGVFromResTable(DM.GetSamplers(), PtrResMap);
  1029. Function *annotHandleFn =
  1030. hlslOP->GetOpFunc(DXIL::OpCode::AnnotateHandle, pVoidTy);
  1031. Value *annotHandleArg =
  1032. hlslOP->GetI32Const((unsigned)DXIL::OpCode::AnnotateHandle);
  1033. // Replace createHandle with annotateHandle and createHandleFromBinding.
  1034. Type *resPropertyTy = hlslOP->GetResourcePropertiesType();
  1035. for (CallInst *CI : Candidates) {
  1036. DxilInst_CreateHandleForLib Hdl(CI);
  1037. LoadInst *Ld = cast<LoadInst>(Hdl.get_Resource());
  1038. Value *Ptr = Ld->getPointerOperand();
  1039. DxilResourceBase *Res = findResourceFromPtr(Ptr, DM, PtrResMap);
  1040. DXASSERT(Res, "fail to find resource when missing annotateHandle");
  1041. DxilResourceProperties RP = resource_helper::loadPropsFromResourceBase(Res);
  1042. Value *propertiesV =
  1043. resource_helper::getAsConstant(RP, resPropertyTy, *DM.GetShaderModel());
  1044. IRBuilder<> B(CI->getNextNode());
  1045. CallInst *annotHdl =
  1046. B.CreateCall(annotHandleFn, {annotHandleArg, CI, propertiesV});
  1047. CI->replaceAllUsesWith(annotHdl);
  1048. annotHdl->setArgOperand(DxilInst_AnnotateHandle::arg_res, CI);
  1049. }
  1050. return true;
  1051. }
  1052. } // namespace
  1053. void DxilLinkJob::FixShaderModelMismatch(llvm::Module &M) {
  1054. // TODO: fix more issues.
  1055. addAnnotHandle(M, M.GetDxilModule());
  1056. }
  1057. void DxilLinkJob::RunPreparePass(Module &M) {
  1058. StripDeadDebugInfo(M);
  1059. FixShaderModelMismatch(M);
  1060. DxilModule &DM = M.GetDxilModule();
  1061. const ShaderModel *pSM = DM.GetShaderModel();
  1062. legacy::PassManager PM;
  1063. PM.add(createAlwaysInlinerPass(/*InsertLifeTime*/ false));
  1064. // Remove unused functions.
  1065. PM.add(createDxilDeadFunctionEliminationPass());
  1066. // SROA
  1067. PM.add(createSROAPass(/*RequiresDomTree*/false, /*SkipHLSLMat*/false));
  1068. // For static global handle.
  1069. PM.add(createLowerStaticGlobalIntoAlloca());
  1070. // Remove MultiDimArray from function call arg.
  1071. PM.add(createMultiDimArrayToOneDimArrayPass());
  1072. // Lower matrix bitcast.
  1073. PM.add(createMatrixBitcastLowerPass());
  1074. // mem2reg.
  1075. PM.add(createPromoteMemoryToRegisterPass());
  1076. // Clean up vectors, and run mem2reg again
  1077. PM.add(createScalarizerPass());
  1078. PM.add(createPromoteMemoryToRegisterPass());
  1079. PM.add(createSimplifyInstPass());
  1080. PM.add(createCFGSimplificationPass());
  1081. PM.add(createDeadCodeEliminationPass());
  1082. PM.add(createGlobalDCEPass());
  1083. if (pSM->IsSM66Plus() && pSM->IsLib())
  1084. PM.add(createDxilMutateResourceToHandlePass());
  1085. PM.add(createDxilLowerCreateHandleForLibPass());
  1086. PM.add(createDxilTranslateRawBuffer());
  1087. PM.add(createDxilFinalizeModulePass());
  1088. PM.add(createComputeViewIdStatePass());
  1089. PM.add(createDxilDeadFunctionEliminationPass());
  1090. PM.add(createNoPausePassesPass());
  1091. PM.add(createDxilEmitMetadataPass());
  1092. PM.run(M);
  1093. }
  1094. //------------------------------------------------------------------------------
  1095. //
  1096. // DxilLinkerImpl methods.
  1097. //
  1098. bool DxilLinkerImpl::HasLibNameRegistered(StringRef name) {
  1099. return m_LibMap.count(name);
  1100. }
  1101. bool DxilLinkerImpl::RegisterLib(StringRef name,
  1102. std::unique_ptr<llvm::Module> pModule,
  1103. std::unique_ptr<llvm::Module> pDebugModule) {
  1104. if (m_LibMap.count(name))
  1105. return false;
  1106. std::unique_ptr<llvm::Module> pM =
  1107. pDebugModule ? std::move(pDebugModule) : std::move(pModule);
  1108. if (!pM)
  1109. return false;
  1110. pM->setModuleIdentifier(name);
  1111. std::unique_ptr<DxilLib> pLib =
  1112. llvm::make_unique<DxilLib>(std::move(pM));
  1113. m_LibMap[name] = std::move(pLib);
  1114. return true;
  1115. }
  1116. bool DxilLinkerImpl::AttachLib(StringRef name) {
  1117. auto iter = m_LibMap.find(name);
  1118. if (iter == m_LibMap.end()) {
  1119. return false;
  1120. }
  1121. return AttachLib(iter->second.get());
  1122. }
  1123. bool DxilLinkerImpl::DetachLib(StringRef name) {
  1124. auto iter = m_LibMap.find(name);
  1125. if (iter == m_LibMap.end()) {
  1126. return false;
  1127. }
  1128. return DetachLib(iter->second.get());
  1129. }
  1130. void DxilLinkerImpl::DetachAll() {
  1131. m_functionNameMap.clear();
  1132. m_attachedLibs.clear();
  1133. }
  1134. bool DxilLinkerImpl::AttachLib(DxilLib *lib) {
  1135. if (!lib) {
  1136. // Invalid arg.
  1137. return false;
  1138. }
  1139. if (m_attachedLibs.count(lib))
  1140. return false;
  1141. StringMap<std::unique_ptr<DxilFunctionLinkInfo>> &funcTable =
  1142. lib->GetFunctionTable();
  1143. bool bSuccess = true;
  1144. for (auto it = funcTable.begin(), e = funcTable.end(); it != e; it++) {
  1145. StringRef name = it->getKey();
  1146. if (m_functionNameMap.count(name)) {
  1147. // Redefine of function.
  1148. const DxilFunctionLinkInfo *DFLI = it->getValue().get();
  1149. dxilutil::EmitErrorOnFunction(DFLI->func, Twine(kRedefineFunction) + name);
  1150. bSuccess = false;
  1151. continue;
  1152. }
  1153. m_functionNameMap[name] = std::make_pair(it->second.get(), lib);
  1154. }
  1155. if (bSuccess) {
  1156. m_attachedLibs.insert(lib);
  1157. } else {
  1158. for (auto it = funcTable.begin(), e = funcTable.end(); it != e; it++) {
  1159. StringRef name = it->getKey();
  1160. auto iter = m_functionNameMap.find(name);
  1161. if (iter == m_functionNameMap.end())
  1162. continue;
  1163. // Remove functions of lib.
  1164. if (m_functionNameMap[name].second == lib)
  1165. m_functionNameMap.erase(name);
  1166. }
  1167. }
  1168. return bSuccess;
  1169. }
  1170. bool DxilLinkerImpl::DetachLib(DxilLib *lib) {
  1171. if (!lib) {
  1172. // Invalid arg.
  1173. return false;
  1174. }
  1175. if (!m_attachedLibs.count(lib))
  1176. return false;
  1177. m_attachedLibs.erase(lib);
  1178. // Remove functions from lib.
  1179. StringMap<std::unique_ptr<DxilFunctionLinkInfo>> &funcTable =
  1180. lib->GetFunctionTable();
  1181. for (auto it = funcTable.begin(), e = funcTable.end(); it != e; it++) {
  1182. StringRef name = it->getKey();
  1183. m_functionNameMap.erase(name);
  1184. }
  1185. return true;
  1186. }
  1187. bool DxilLinkerImpl::AddFunctions(SmallVector<StringRef, 4> &workList,
  1188. SetVector<DxilLib *> &libSet,
  1189. SetVector<StringRef> &addedFunctionSet,
  1190. DxilLinkJob &linkJob, bool bLazyLoadDone,
  1191. bool bAllowFuncionDecls) {
  1192. while (!workList.empty()) {
  1193. StringRef name = workList.pop_back_val();
  1194. // Ignore added function.
  1195. if (addedFunctionSet.count(name))
  1196. continue;
  1197. if (!m_functionNameMap.count(name)) {
  1198. // Cannot find function, report error.
  1199. m_ctx.emitError(Twine(kUndefFunction) + name);
  1200. return false;
  1201. }
  1202. std::pair<DxilFunctionLinkInfo *, DxilLib *> &linkPair =
  1203. m_functionNameMap[name];
  1204. linkJob.AddFunction(linkPair);
  1205. DxilLib *pLib = linkPair.second;
  1206. libSet.insert(pLib);
  1207. if (!bLazyLoadDone) {
  1208. Function *F = linkPair.first->func;
  1209. pLib->LazyLoadFunction(F);
  1210. }
  1211. for (Function *F : linkPair.first->usedFunctions) {
  1212. if (hlsl::OP::IsDxilOpFunc(F) || F->isIntrinsic()) {
  1213. // Add dxil operations directly.
  1214. linkJob.AddFunction(F);
  1215. } else if (addedFunctionSet.count(F->getName()) == 0) {
  1216. if (bAllowFuncionDecls && F->isDeclaration() && !m_functionNameMap.count(F->getName())) {
  1217. // When linking to lib, use of undefined function is allowed; add directly.
  1218. linkJob.AddFunction(F);
  1219. } else {
  1220. // Push function name to work list.
  1221. workList.emplace_back(F->getName());
  1222. }
  1223. }
  1224. }
  1225. addedFunctionSet.insert(name);
  1226. }
  1227. return true;
  1228. }
  1229. std::unique_ptr<llvm::Module>
  1230. DxilLinkerImpl::Link(StringRef entry, StringRef profile, dxilutil::ExportMap &exportMap) {
  1231. const ShaderModel *pSM = ShaderModel::GetByName(profile.data());
  1232. DXIL::ShaderKind kind = pSM->GetKind();
  1233. if (kind == DXIL::ShaderKind::Invalid ||
  1234. (kind >= DXIL::ShaderKind::RayGeneration &&
  1235. kind <= DXIL::ShaderKind::Callable)) {
  1236. m_ctx.emitError(profile + Twine(kInvalidProfile));
  1237. // Invalid profile.
  1238. return nullptr;
  1239. }
  1240. if (!exportMap.empty() && kind != DXIL::ShaderKind::Library) {
  1241. m_ctx.emitError(Twine(kExportOnlyForLib));
  1242. return nullptr;
  1243. }
  1244. // Verifying validator version supports the requested profile
  1245. unsigned minValMajor, minValMinor;
  1246. pSM->GetMinValidatorVersion(minValMajor, minValMinor);
  1247. if (minValMajor > m_valMajor ||
  1248. (minValMajor == m_valMajor && minValMinor > m_valMinor)) {
  1249. m_ctx.emitError(Twine(kInvalidValidatorVersion) + profile);
  1250. return nullptr;
  1251. }
  1252. DxilLinkJob linkJob(m_ctx, exportMap, m_valMajor, m_valMinor);
  1253. SetVector<DxilLib *> libSet;
  1254. SetVector<StringRef> addedFunctionSet;
  1255. bool bIsLib = pSM->IsLib();
  1256. if (!bIsLib) {
  1257. SmallVector<StringRef, 4> workList;
  1258. workList.emplace_back(entry);
  1259. if (!AddFunctions(workList, libSet, addedFunctionSet, linkJob,
  1260. /*bLazyLoadDone*/ false,
  1261. /*bAllowFuncionDecls*/ false))
  1262. return nullptr;
  1263. } else {
  1264. if (exportMap.empty()) {
  1265. // Add every function for lib profile.
  1266. for (auto &it : m_functionNameMap) {
  1267. StringRef name = it.getKey();
  1268. std::pair<DxilFunctionLinkInfo *, DxilLib *> &linkPair = it.second;
  1269. DxilFunctionLinkInfo *linkInfo = linkPair.first;
  1270. DxilLib *pLib = linkPair.second;
  1271. Function *F = linkInfo->func;
  1272. pLib->LazyLoadFunction(F);
  1273. linkJob.AddFunction(linkPair);
  1274. libSet.insert(pLib);
  1275. addedFunctionSet.insert(name);
  1276. }
  1277. // Add every dxil function and llvm intrinsic.
  1278. for (auto *pLib : libSet) {
  1279. auto &DM = pLib->GetDxilModule();
  1280. DM.GetOP();
  1281. auto *pM = DM.GetModule();
  1282. for (Function &F : pM->functions()) {
  1283. if (hlsl::OP::IsDxilOpFunc(&F) || F.isIntrinsic() ||
  1284. (F.isDeclaration() && m_functionNameMap.count(F.getName()) == 0)) {
  1285. // Add intrinsics and function decls still not defined in any lib
  1286. linkJob.AddFunction(&F);
  1287. }
  1288. }
  1289. }
  1290. } else {
  1291. SmallVector<StringRef, 4> workList;
  1292. // Only add exported functions.
  1293. for (auto &it : m_functionNameMap) {
  1294. StringRef name = it.getKey();
  1295. // Only add names exist in exportMap.
  1296. if (exportMap.IsExported(name))
  1297. workList.emplace_back(name);
  1298. }
  1299. if (!AddFunctions(workList, libSet, addedFunctionSet, linkJob,
  1300. /*bLazyLoadDone*/ false,
  1301. /*bAllowFuncionDecls*/ true))
  1302. return nullptr;
  1303. }
  1304. }
  1305. // Save global users.
  1306. for (auto &pLib : libSet) {
  1307. pLib->BuildGlobalUsage();
  1308. }
  1309. SmallVector<StringRef, 4> workList;
  1310. // Save global ctor users.
  1311. for (auto &pLib : libSet) {
  1312. pLib->CollectUsedInitFunctions(addedFunctionSet, workList);
  1313. }
  1314. for (auto &pLib : libSet) {
  1315. pLib->FixIntrinsicOverloads();
  1316. }
  1317. // Add init functions if used.
  1318. // All init function already loaded in BuildGlobalUsage,
  1319. // so set bLazyLoadDone to true here.
  1320. // Decls should have been added to addedFunctionSet if lib,
  1321. // so set bAllowFuncionDecls is false here.
  1322. if (!AddFunctions(workList, libSet, addedFunctionSet, linkJob,
  1323. /*bLazyLoadDone*/ true,
  1324. /*bAllowFuncionDecls*/ false))
  1325. return nullptr;
  1326. if (!bIsLib) {
  1327. std::pair<DxilFunctionLinkInfo *, DxilLib *> &entryLinkPair =
  1328. m_functionNameMap[entry];
  1329. return linkJob.Link(entryLinkPair, pSM);
  1330. } else {
  1331. return linkJob.LinkToLib(pSM);
  1332. }
  1333. }
  1334. namespace hlsl {
  1335. DxilLinker *DxilLinker::CreateLinker(LLVMContext &Ctx, unsigned valMajor, unsigned valMinor) {
  1336. return new DxilLinkerImpl(Ctx, valMajor, valMinor);
  1337. }
  1338. } // namespace hlsl