DxilUtil.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // DxilUtil.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. // Dxil helper functions. //
  9. // //
  10. ///////////////////////////////////////////////////////////////////////////////
  11. #include "dxc/DXIL/DxilTypeSystem.h"
  12. #include "dxc/DXIL/DxilUtil.h"
  13. #include "dxc/DXIL/DxilModule.h"
  14. #include "dxc/Support/Global.h"
  15. #include "llvm/ADT/StringExtras.h"
  16. #include "llvm/ADT/Twine.h"
  17. #include "llvm/Bitcode/ReaderWriter.h"
  18. #include "llvm/IR/DiagnosticInfo.h"
  19. #include "llvm/IR/DiagnosticPrinter.h"
  20. #include "llvm/IR/GlobalVariable.h"
  21. #include "llvm/IR/IntrinsicInst.h"
  22. #include "llvm/IR/LLVMContext.h"
  23. #include "llvm/IR/Module.h"
  24. #include "llvm/Support/MemoryBuffer.h"
  25. #include "llvm/Support/raw_ostream.h"
  26. #include "llvm/IR/Instructions.h"
  27. #include "llvm/IR/Constants.h"
  28. #include "llvm/IR/DIBuilder.h"
  29. #include "llvm/IR/IRBuilder.h"
  30. using namespace llvm;
  31. using namespace hlsl;
  32. namespace hlsl {
  33. namespace dxilutil {
  34. const char ManglingPrefix[] = "\01?";
  35. const char EntryPrefix[] = "dx.entry.";
  36. Type *GetArrayEltTy(Type *Ty) {
  37. if (isa<PointerType>(Ty))
  38. Ty = Ty->getPointerElementType();
  39. while (isa<ArrayType>(Ty)) {
  40. Ty = Ty->getArrayElementType();
  41. }
  42. return Ty;
  43. }
  44. bool HasDynamicIndexing(Value *V) {
  45. for (auto User : V->users()) {
  46. if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(User)) {
  47. for (auto Idx = GEP->idx_begin(); Idx != GEP->idx_end(); ++Idx) {
  48. if (!isa<ConstantInt>(Idx))
  49. return true;
  50. }
  51. }
  52. }
  53. return false;
  54. }
  55. unsigned
  56. GetLegacyCBufferFieldElementSize(DxilFieldAnnotation &fieldAnnotation,
  57. llvm::Type *Ty,
  58. DxilTypeSystem &typeSys) {
  59. while (isa<ArrayType>(Ty)) {
  60. Ty = Ty->getArrayElementType();
  61. }
  62. // Bytes.
  63. CompType compType = fieldAnnotation.GetCompType();
  64. unsigned compSize = compType.Is64Bit() ? 8 : compType.Is16Bit() && !typeSys.UseMinPrecision() ? 2 : 4;
  65. unsigned fieldSize = compSize;
  66. if (Ty->isVectorTy()) {
  67. fieldSize *= Ty->getVectorNumElements();
  68. } else if (StructType *ST = dyn_cast<StructType>(Ty)) {
  69. DxilStructAnnotation *EltAnnotation = typeSys.GetStructAnnotation(ST);
  70. if (EltAnnotation) {
  71. fieldSize = EltAnnotation->GetCBufferSize();
  72. } else {
  73. // Calculate size when don't have annotation.
  74. if (fieldAnnotation.HasMatrixAnnotation()) {
  75. const DxilMatrixAnnotation &matAnnotation =
  76. fieldAnnotation.GetMatrixAnnotation();
  77. unsigned rows = matAnnotation.Rows;
  78. unsigned cols = matAnnotation.Cols;
  79. if (matAnnotation.Orientation == MatrixOrientation::ColumnMajor) {
  80. rows = cols;
  81. cols = matAnnotation.Rows;
  82. } else if (matAnnotation.Orientation != MatrixOrientation::RowMajor) {
  83. // Invalid matrix orientation.
  84. fieldSize = 0;
  85. }
  86. fieldSize = (rows - 1) * 16 + cols * 4;
  87. } else {
  88. // Cannot find struct annotation.
  89. fieldSize = 0;
  90. }
  91. }
  92. }
  93. return fieldSize;
  94. }
  95. bool IsStaticGlobal(GlobalVariable *GV) {
  96. return GV->getLinkage() == GlobalValue::LinkageTypes::InternalLinkage &&
  97. GV->getType()->getPointerAddressSpace() == DXIL::kDefaultAddrSpace;
  98. }
  99. bool IsSharedMemoryGlobal(llvm::GlobalVariable *GV) {
  100. return GV->getType()->getPointerAddressSpace() == DXIL::kTGSMAddrSpace;
  101. }
  102. bool RemoveUnusedFunctions(Module &M, Function *EntryFunc,
  103. Function *PatchConstantFunc, bool IsLib) {
  104. std::vector<Function *> deadList;
  105. for (auto &F : M.functions()) {
  106. if (&F == EntryFunc || &F == PatchConstantFunc)
  107. continue;
  108. if (F.isDeclaration() || !IsLib) {
  109. if (F.user_empty())
  110. deadList.emplace_back(&F);
  111. }
  112. }
  113. bool bUpdated = deadList.size();
  114. for (Function *F : deadList)
  115. F->eraseFromParent();
  116. return bUpdated;
  117. }
  118. void PrintDiagnosticHandler(const llvm::DiagnosticInfo &DI, void *Context) {
  119. DiagnosticPrinter *printer = reinterpret_cast<DiagnosticPrinter *>(Context);
  120. DI.print(*printer);
  121. }
  122. StringRef DemangleFunctionName(StringRef name) {
  123. if (!name.startswith(ManglingPrefix)) {
  124. // Name isn't mangled.
  125. return name;
  126. }
  127. size_t nameEnd = name.find_first_of("@");
  128. DXASSERT(nameEnd != StringRef::npos, "else Name isn't mangled but has \01?");
  129. return name.substr(2, nameEnd - 2);
  130. }
  131. std::string ReplaceFunctionName(StringRef originalName, StringRef newName) {
  132. if (originalName.startswith(ManglingPrefix)) {
  133. return (Twine(ManglingPrefix) + newName +
  134. originalName.substr(originalName.find_first_of('@'))).str();
  135. } else if (originalName.startswith(EntryPrefix)) {
  136. return (Twine(EntryPrefix) + newName).str();
  137. }
  138. return newName.str();
  139. }
  140. // From AsmWriter.cpp
  141. // PrintEscapedString - Print each character of the specified string, escaping
  142. // it if it is not printable or if it is an escape char.
  143. void PrintEscapedString(StringRef Name, raw_ostream &Out) {
  144. for (unsigned i = 0, e = Name.size(); i != e; ++i) {
  145. unsigned char C = Name[i];
  146. if (isprint(C) && C != '\\' && C != '"')
  147. Out << C;
  148. else
  149. Out << '\\' << hexdigit(C >> 4) << hexdigit(C & 0x0F);
  150. }
  151. }
  152. void PrintUnescapedString(StringRef Name, raw_ostream &Out) {
  153. for (unsigned i = 0, e = Name.size(); i != e; ++i) {
  154. unsigned char C = Name[i];
  155. if (C == '\\') {
  156. C = Name[++i];
  157. unsigned value = hexDigitValue(C);
  158. if (value != -1U) {
  159. C = (unsigned char)value;
  160. unsigned value2 = hexDigitValue(Name[i+1]);
  161. assert(value2 != -1U && "otherwise, not a two digit hex escape");
  162. if (value2 != -1U) {
  163. C = (C << 4) + (unsigned char)value2;
  164. ++i;
  165. }
  166. } // else, the next character (in C) should be the escaped character
  167. }
  168. Out << C;
  169. }
  170. }
  171. std::unique_ptr<llvm::Module> LoadModuleFromBitcode(llvm::MemoryBuffer *MB,
  172. llvm::LLVMContext &Ctx,
  173. std::string &DiagStr) {
  174. // Note: the DiagStr is not used.
  175. auto pModule = llvm::parseBitcodeFile(MB->getMemBufferRef(), Ctx);
  176. if (!pModule) {
  177. return nullptr;
  178. }
  179. return std::unique_ptr<llvm::Module>(pModule.get().release());
  180. }
  181. std::unique_ptr<llvm::Module> LoadModuleFromBitcode(llvm::StringRef BC,
  182. llvm::LLVMContext &Ctx,
  183. std::string &DiagStr) {
  184. std::unique_ptr<llvm::MemoryBuffer> pBitcodeBuf(
  185. llvm::MemoryBuffer::getMemBuffer(BC, "", false));
  186. return LoadModuleFromBitcode(pBitcodeBuf.get(), Ctx, DiagStr);
  187. }
  188. // If we don't have debug location and this is select/phi,
  189. // try recursing users to find instruction with debug info.
  190. // Only recurse phi/select and limit depth to prevent doing
  191. // too much work if no debug location found.
  192. static bool EmitErrorOnInstructionFollowPhiSelect(
  193. Instruction *I, StringRef Msg, unsigned depth=0) {
  194. if (depth > 4)
  195. return false;
  196. if (I->getDebugLoc().get()) {
  197. EmitErrorOnInstruction(I, Msg);
  198. return true;
  199. }
  200. if (isa<PHINode>(I) || isa<SelectInst>(I)) {
  201. for (auto U : I->users())
  202. if (Instruction *UI = dyn_cast<Instruction>(U))
  203. if (EmitErrorOnInstructionFollowPhiSelect(UI, Msg, depth+1))
  204. return true;
  205. }
  206. return false;
  207. }
  208. std::string FormatMessageAtLocation(const DebugLoc &DL, const Twine& Msg) {
  209. std::string locString;
  210. raw_string_ostream os(locString);
  211. DL.print(os);
  212. os << ": " << Msg;
  213. return os.str();
  214. }
  215. Twine FormatMessageWithoutLocation(const Twine& Msg) {
  216. return Msg + " Use /Zi for source location.";
  217. }
  218. void EmitErrorOnInstruction(Instruction *I, StringRef Msg) {
  219. const DebugLoc &DL = I->getDebugLoc();
  220. if (DL.get()) {
  221. I->getContext().emitError(FormatMessageAtLocation(DL, Msg));
  222. return;
  223. } else if (isa<PHINode>(I) || isa<SelectInst>(I)) {
  224. if (EmitErrorOnInstructionFollowPhiSelect(I, Msg))
  225. return;
  226. }
  227. I->getContext().emitError(FormatMessageWithoutLocation(Msg));
  228. }
  229. const StringRef kResourceMapErrorMsg =
  230. "local resource not guaranteed to map to unique global resource.";
  231. void EmitResMappingError(Instruction *Res) {
  232. EmitErrorOnInstruction(Res, kResourceMapErrorMsg);
  233. }
  234. void CollectSelect(llvm::Instruction *Inst,
  235. std::unordered_set<llvm::Instruction *> &selectSet) {
  236. unsigned startOpIdx = 0;
  237. // Skip Cond for Select.
  238. if (isa<SelectInst>(Inst)) {
  239. startOpIdx = 1;
  240. } else if (!isa<PHINode>(Inst)) {
  241. // Only check phi and select here.
  242. return;
  243. }
  244. // Already add.
  245. if (selectSet.count(Inst))
  246. return;
  247. selectSet.insert(Inst);
  248. // Scan operand to add node which is phi/select.
  249. unsigned numOperands = Inst->getNumOperands();
  250. for (unsigned i = startOpIdx; i < numOperands; i++) {
  251. Value *V = Inst->getOperand(i);
  252. if (Instruction *I = dyn_cast<Instruction>(V)) {
  253. CollectSelect(I, selectSet);
  254. }
  255. }
  256. }
  257. Value *MergeSelectOnSameValue(Instruction *SelInst, unsigned startOpIdx,
  258. unsigned numOperands) {
  259. Value *op0 = nullptr;
  260. for (unsigned i = startOpIdx; i < numOperands; i++) {
  261. Value *op = SelInst->getOperand(i);
  262. if (i == startOpIdx) {
  263. op0 = op;
  264. } else {
  265. if (op0 != op)
  266. return nullptr;
  267. }
  268. }
  269. if (op0) {
  270. SelInst->replaceAllUsesWith(op0);
  271. SelInst->eraseFromParent();
  272. }
  273. return op0;
  274. }
  275. bool SimplifyTrivialPHIs(BasicBlock *BB) {
  276. bool Changed = false;
  277. SmallVector<Instruction *, 16> Removed;
  278. for (Instruction &I : *BB) {
  279. PHINode *PN = dyn_cast<PHINode>(&I);
  280. if (!PN)
  281. continue;
  282. if (PN->getNumIncomingValues() == 1) {
  283. Value *V = PN->getIncomingValue(0);
  284. PN->replaceAllUsesWith(V);
  285. Removed.push_back(PN);
  286. Changed = true;
  287. }
  288. }
  289. for (Instruction *I : Removed)
  290. I->eraseFromParent();
  291. return Changed;
  292. }
  293. static DbgValueInst *FindDbgValueInst(Value *Val) {
  294. if (auto *ValAsMD = LocalAsMetadata::getIfExists(Val)) {
  295. if (auto *ValMDAsVal = MetadataAsValue::getIfExists(Val->getContext(), ValAsMD)) {
  296. for (User *ValMDUser : ValMDAsVal->users()) {
  297. if (DbgValueInst *DbgValInst = dyn_cast<DbgValueInst>(ValMDUser))
  298. return DbgValInst;
  299. }
  300. }
  301. }
  302. return nullptr;
  303. }
  304. void MigrateDebugValue(Value *Old, Value *New) {
  305. DbgValueInst *DbgValInst = FindDbgValueInst(Old);
  306. if (DbgValInst == nullptr) return;
  307. DbgValInst->setOperand(0, MetadataAsValue::get(New->getContext(), ValueAsMetadata::get(New)));
  308. // Move the dbg value after the new instruction
  309. if (Instruction *NewInst = dyn_cast<Instruction>(New)) {
  310. if (NewInst->getNextNode() != DbgValInst) {
  311. DbgValInst->removeFromParent();
  312. DbgValInst->insertAfter(NewInst);
  313. }
  314. }
  315. }
  316. // Propagates any llvm.dbg.value instruction for a given vector
  317. // to the elements that were used to create it through a series
  318. // of insertelement instructions.
  319. //
  320. // This is used after lowering a vector-returning intrinsic.
  321. // If we just keep the debug info on the recomposed vector,
  322. // we will lose it when we break it apart again during later
  323. // optimization stages.
  324. void TryScatterDebugValueToVectorElements(Value *Val) {
  325. if (!isa<InsertElementInst>(Val) || !Val->getType()->isVectorTy()) return;
  326. DbgValueInst *VecDbgValInst = FindDbgValueInst(Val);
  327. if (VecDbgValInst == nullptr) return;
  328. Type *ElemTy = Val->getType()->getVectorElementType();
  329. DIBuilder DbgInfoBuilder(*VecDbgValInst->getModule());
  330. unsigned ElemSizeInBits = VecDbgValInst->getModule()->getDataLayout().getTypeSizeInBits(ElemTy);
  331. DIExpression *ParentBitPiece = VecDbgValInst->getExpression();
  332. if (ParentBitPiece != nullptr && !ParentBitPiece->isBitPiece())
  333. ParentBitPiece = nullptr;
  334. while (InsertElementInst *InsertElt = dyn_cast<InsertElementInst>(Val)) {
  335. Value *NewElt = InsertElt->getOperand(1);
  336. unsigned EltIdx = static_cast<unsigned>(cast<ConstantInt>(InsertElt->getOperand(2))->getLimitedValue());
  337. unsigned OffsetInBits = EltIdx * ElemSizeInBits;
  338. if (ParentBitPiece) {
  339. assert(OffsetInBits + ElemSizeInBits <= ParentBitPiece->getBitPieceSize()
  340. && "Nested bit piece expression exceeds bounds of its parent.");
  341. OffsetInBits += ParentBitPiece->getBitPieceOffset();
  342. }
  343. DIExpression *DIExpr = DbgInfoBuilder.createBitPieceExpression(OffsetInBits, ElemSizeInBits);
  344. // Offset is basically unused and deprecated in later LLVM versions.
  345. // Emit it as zero otherwise later versions of the bitcode reader will drop the intrinsic.
  346. DbgInfoBuilder.insertDbgValueIntrinsic(NewElt, /* Offset */ 0, VecDbgValInst->getVariable(),
  347. DIExpr, VecDbgValInst->getDebugLoc(), InsertElt);
  348. Val = InsertElt->getOperand(0);
  349. }
  350. }
  351. Value *SelectOnOperation(llvm::Instruction *Inst, unsigned operandIdx) {
  352. Instruction *prototype = Inst;
  353. for (unsigned i = 0; i < prototype->getNumOperands(); i++) {
  354. if (i == operandIdx)
  355. continue;
  356. if (!isa<Constant>(prototype->getOperand(i)))
  357. return nullptr;
  358. }
  359. Value *V = prototype->getOperand(operandIdx);
  360. if (SelectInst *SI = dyn_cast<SelectInst>(V)) {
  361. IRBuilder<> Builder(SI);
  362. Instruction *trueClone = Inst->clone();
  363. trueClone->setOperand(operandIdx, SI->getTrueValue());
  364. Builder.Insert(trueClone);
  365. Instruction *falseClone = Inst->clone();
  366. falseClone->setOperand(operandIdx, SI->getFalseValue());
  367. Builder.Insert(falseClone);
  368. Value *newSel =
  369. Builder.CreateSelect(SI->getCondition(), trueClone, falseClone);
  370. return newSel;
  371. }
  372. if (PHINode *Phi = dyn_cast<PHINode>(V)) {
  373. Type *Ty = Inst->getType();
  374. unsigned numOperands = Phi->getNumOperands();
  375. IRBuilder<> Builder(Phi);
  376. PHINode *newPhi = Builder.CreatePHI(Ty, numOperands);
  377. for (unsigned i = 0; i < numOperands; i++) {
  378. BasicBlock *b = Phi->getIncomingBlock(i);
  379. Value *V = Phi->getIncomingValue(i);
  380. Instruction *iClone = Inst->clone();
  381. IRBuilder<> iBuilder(b->getTerminator()->getPrevNode());
  382. iClone->setOperand(operandIdx, V);
  383. iBuilder.Insert(iClone);
  384. newPhi->addIncoming(iClone, b);
  385. }
  386. return newPhi;
  387. }
  388. return nullptr;
  389. }
  390. llvm::Instruction *SkipAllocas(llvm::Instruction *I) {
  391. // Step past any allocas:
  392. while (I && isa<AllocaInst>(I))
  393. I = I->getNextNode();
  394. return I;
  395. }
  396. llvm::Instruction *FindAllocaInsertionPt(llvm::BasicBlock* BB) {
  397. return &*BB->getFirstInsertionPt();
  398. }
  399. llvm::Instruction *FindAllocaInsertionPt(llvm::Function* F) {
  400. return FindAllocaInsertionPt(&F->getEntryBlock());
  401. }
  402. llvm::Instruction *FindAllocaInsertionPt(llvm::Instruction* I) {
  403. Function *F = I->getParent()->getParent();
  404. if (F)
  405. return FindAllocaInsertionPt(F);
  406. else // BB with no parent function
  407. return FindAllocaInsertionPt(I->getParent());
  408. }
  409. llvm::Instruction *FirstNonAllocaInsertionPt(llvm::Instruction* I) {
  410. return SkipAllocas(FindAllocaInsertionPt(I));
  411. }
  412. llvm::Instruction *FirstNonAllocaInsertionPt(llvm::BasicBlock* BB) {
  413. return SkipAllocas(FindAllocaInsertionPt(BB));
  414. }
  415. llvm::Instruction *FirstNonAllocaInsertionPt(llvm::Function* F) {
  416. return SkipAllocas(FindAllocaInsertionPt(F));
  417. }
  418. static bool ConsumePrefix(StringRef &Str, StringRef Prefix) {
  419. if (!Str.startswith(Prefix)) return false;
  420. Str = Str.substr(Prefix.size());
  421. return true;
  422. }
  423. bool IsHLSLResourceType(llvm::Type *Ty) {
  424. if (llvm::StructType *ST = dyn_cast<llvm::StructType>(Ty)) {
  425. StringRef name = ST->getName();
  426. ConsumePrefix(name, "class.");
  427. ConsumePrefix(name, "struct.");
  428. if (name == "SamplerState")
  429. return true;
  430. if (name == "SamplerComparisonState")
  431. return true;
  432. if (name.startswith("AppendStructuredBuffer<"))
  433. return true;
  434. if (name.startswith("ConsumeStructuredBuffer<"))
  435. return true;
  436. if (name.startswith("ConstantBuffer<"))
  437. return true;
  438. if (name == "RaytracingAccelerationStructure")
  439. return true;
  440. if (ConsumePrefix(name, "FeedbackTexture2D")) {
  441. ConsumePrefix(name, "Array");
  442. return name == "MinLOD" || name == "Tiled";
  443. }
  444. ConsumePrefix(name, "RasterizerOrdered");
  445. ConsumePrefix(name, "RW");
  446. if (name == "ByteAddressBuffer")
  447. return true;
  448. if (name.startswith("Buffer<"))
  449. return true;
  450. if (name.startswith("StructuredBuffer<"))
  451. return true;
  452. if (ConsumePrefix(name, "Texture")) {
  453. if (name.startswith("1D<"))
  454. return true;
  455. if (name.startswith("1DArray<"))
  456. return true;
  457. if (name.startswith("2D<"))
  458. return true;
  459. if (name.startswith("2DArray<"))
  460. return true;
  461. if (name.startswith("3D<"))
  462. return true;
  463. if (name.startswith("Cube<"))
  464. return true;
  465. if (name.startswith("CubeArray<"))
  466. return true;
  467. if (name.startswith("2DMS<"))
  468. return true;
  469. if (name.startswith("2DMSArray<"))
  470. return true;
  471. return false;
  472. }
  473. }
  474. return false;
  475. }
  476. bool IsHLSLObjectType(llvm::Type *Ty) {
  477. if (llvm::StructType *ST = dyn_cast<llvm::StructType>(Ty)) {
  478. StringRef name = ST->getName();
  479. // TODO: don't check names.
  480. if (name.startswith("dx.types.wave_t"))
  481. return true;
  482. if (name.endswith("_slice_type"))
  483. return false;
  484. if (IsHLSLResourceType(Ty))
  485. return true;
  486. ConsumePrefix(name, "class.");
  487. ConsumePrefix(name, "struct.");
  488. if (name.startswith("TriangleStream<"))
  489. return true;
  490. if (name.startswith("PointStream<"))
  491. return true;
  492. if (name.startswith("LineStream<"))
  493. return true;
  494. }
  495. return false;
  496. }
  497. bool IsIntegerOrFloatingPointType(llvm::Type *Ty) {
  498. return Ty->isIntegerTy() || Ty->isFloatingPointTy();
  499. }
  500. bool ContainsHLSLObjectType(llvm::Type *Ty) {
  501. // Unwrap pointer/array
  502. while (llvm::isa<llvm::PointerType>(Ty))
  503. Ty = llvm::cast<llvm::PointerType>(Ty)->getPointerElementType();
  504. while (llvm::isa<llvm::ArrayType>(Ty))
  505. Ty = llvm::cast<llvm::ArrayType>(Ty)->getArrayElementType();
  506. if (llvm::StructType *ST = llvm::dyn_cast<llvm::StructType>(Ty)) {
  507. if (ST->getName().startswith("dx.types."))
  508. return true;
  509. // TODO: How is this suppoed to check for Input/OutputPatch types if
  510. // these have already been eliminated in function arguments during CG?
  511. if (IsHLSLObjectType(Ty))
  512. return true;
  513. // Otherwise, recurse elements of UDT
  514. for (auto ETy : ST->elements()) {
  515. if (ContainsHLSLObjectType(ETy))
  516. return true;
  517. }
  518. }
  519. return false;
  520. }
  521. // Based on the implementation available in LLVM's trunk:
  522. // http://llvm.org/doxygen/Constants_8cpp_source.html#l02734
  523. bool IsSplat(llvm::ConstantDataVector *cdv) {
  524. const char *Base = cdv->getRawDataValues().data();
  525. // Compare elements 1+ to the 0'th element.
  526. unsigned EltSize = cdv->getElementByteSize();
  527. for (unsigned i = 1, e = cdv->getNumElements(); i != e; ++i)
  528. if (memcmp(Base, Base + i * EltSize, EltSize))
  529. return false;
  530. return true;
  531. }
  532. llvm::Type* StripArrayTypes(llvm::Type *Ty, llvm::SmallVectorImpl<unsigned> *OuterToInnerLengths) {
  533. DXASSERT_NOMSG(Ty);
  534. while (Ty->isArrayTy()) {
  535. if (OuterToInnerLengths) {
  536. OuterToInnerLengths->push_back(Ty->getArrayNumElements());
  537. }
  538. Ty = Ty->getArrayElementType();
  539. }
  540. return Ty;
  541. }
  542. llvm::Type* WrapInArrayTypes(llvm::Type *Ty, llvm::ArrayRef<unsigned> OuterToInnerLengths) {
  543. DXASSERT_NOMSG(Ty);
  544. for (auto it = OuterToInnerLengths.rbegin(), E = OuterToInnerLengths.rend(); it != E; ++it) {
  545. Ty = ArrayType::get(Ty, *it);
  546. }
  547. return Ty;
  548. }
  549. }
  550. }
  551. ///////////////////////////////////////////////////////////////////////////////
  552. namespace {
  553. class DxilLoadMetadata : public ModulePass {
  554. public:
  555. static char ID; // Pass identification, replacement for typeid
  556. explicit DxilLoadMetadata () : ModulePass(ID) {}
  557. const char *getPassName() const override { return "HLSL load DxilModule from metadata"; }
  558. bool runOnModule(Module &M) override {
  559. if (!M.HasDxilModule()) {
  560. (void)M.GetOrCreateDxilModule();
  561. return true;
  562. }
  563. return false;
  564. }
  565. };
  566. }
  567. char DxilLoadMetadata::ID = 0;
  568. ModulePass *llvm::createDxilLoadMetadataPass() {
  569. return new DxilLoadMetadata();
  570. }
  571. INITIALIZE_PASS(DxilLoadMetadata, "hlsl-dxilload", "HLSL load DxilModule from metadata", false, false)