1 //=- DXILMetadataAnalysis.cpp - Representation of Module metadata -*- C++ -*=// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/Analysis/DXILMetadataAnalysis.h" 10 #include "llvm/ADT/APInt.h" 11 #include "llvm/ADT/StringExtras.h" 12 #include "llvm/ADT/StringRef.h" 13 #include "llvm/IR/Constants.h" 14 #include "llvm/IR/Instructions.h" 15 #include "llvm/IR/Metadata.h" 16 #include "llvm/IR/Module.h" 17 #include "llvm/InitializePasses.h" 18 #include "llvm/Support/ErrorHandling.h" 19 20 #define DEBUG_TYPE "dxil-metadata-analysis" 21 22 using namespace llvm; 23 using namespace dxil; 24 25 static ModuleMetadataInfo collectMetadataInfo(Module &M) { 26 ModuleMetadataInfo MMDAI; 27 Triple TT(Triple(M.getTargetTriple())); 28 MMDAI.DXILVersion = TT.getDXILVersion(); 29 MMDAI.ShaderModelVersion = TT.getOSVersion(); 30 MMDAI.ShaderProfile = TT.getEnvironment(); 31 NamedMDNode *ValidatorVerNode = M.getNamedMetadata("dx.valver"); 32 if (ValidatorVerNode) { 33 auto *ValVerMD = cast<MDNode>(ValidatorVerNode->getOperand(0)); 34 auto *MajorMD = mdconst::extract<ConstantInt>(ValVerMD->getOperand(0)); 35 auto *MinorMD = mdconst::extract<ConstantInt>(ValVerMD->getOperand(1)); 36 MMDAI.ValidatorVersion = 37 VersionTuple(MajorMD->getZExtValue(), MinorMD->getZExtValue()); 38 } 39 40 // For all HLSL Shader functions 41 for (auto &F : M.functions()) { 42 if (!F.hasFnAttribute("hlsl.shader")) 43 continue; 44 45 EntryProperties EFP(&F); 46 // Get "hlsl.shader" attribute 47 Attribute EntryAttr = F.getFnAttribute("hlsl.shader"); 48 assert(EntryAttr.isValid() && 49 "Invalid value specified for HLSL function attribute hlsl.shader"); 50 StringRef EntryProfile = EntryAttr.getValueAsString(); 51 Triple T("", "", "", EntryProfile); 52 EFP.ShaderStage = T.getEnvironment(); 53 // Get numthreads attribute value, if one exists 54 StringRef NumThreadsStr = 55 F.getFnAttribute("hlsl.numthreads").getValueAsString(); 56 if (!NumThreadsStr.empty()) { 57 SmallVector<StringRef> NumThreadsVec; 58 NumThreadsStr.split(NumThreadsVec, ','); 59 assert(NumThreadsVec.size() == 3 && "Invalid numthreads specified"); 60 // Read in the three component values of numthreads 61 [[maybe_unused]] bool Success = 62 llvm::to_integer(NumThreadsVec[0], EFP.NumThreadsX, 10); 63 assert(Success && "Failed to parse X component of numthreads"); 64 Success = llvm::to_integer(NumThreadsVec[1], EFP.NumThreadsY, 10); 65 assert(Success && "Failed to parse Y component of numthreads"); 66 Success = llvm::to_integer(NumThreadsVec[2], EFP.NumThreadsZ, 10); 67 assert(Success && "Failed to parse Z component of numthreads"); 68 } 69 MMDAI.EntryPropertyVec.push_back(EFP); 70 } 71 return MMDAI; 72 } 73 74 void ModuleMetadataInfo::print(raw_ostream &OS) const { 75 OS << "Shader Model Version : " << ShaderModelVersion.getAsString() << "\n"; 76 OS << "DXIL Version : " << DXILVersion.getAsString() << "\n"; 77 OS << "Target Shader Stage : " 78 << Triple::getEnvironmentTypeName(ShaderProfile) << "\n"; 79 OS << "Validator Version : " << ValidatorVersion.getAsString() << "\n"; 80 for (const auto &EP : EntryPropertyVec) { 81 OS << " " << EP.Entry->getName() << "\n"; 82 OS << " Function Shader Stage : " 83 << Triple::getEnvironmentTypeName(EP.ShaderStage) << "\n"; 84 OS << " NumThreads: " << EP.NumThreadsX << "," << EP.NumThreadsY << "," 85 << EP.NumThreadsZ << "\n"; 86 } 87 } 88 89 //===----------------------------------------------------------------------===// 90 // DXILMetadataAnalysis and DXILMetadataAnalysisPrinterPass 91 92 // Provide an explicit template instantiation for the static ID. 93 AnalysisKey DXILMetadataAnalysis::Key; 94 95 llvm::dxil::ModuleMetadataInfo 96 DXILMetadataAnalysis::run(Module &M, ModuleAnalysisManager &AM) { 97 return collectMetadataInfo(M); 98 } 99 100 PreservedAnalyses 101 DXILMetadataAnalysisPrinterPass::run(Module &M, ModuleAnalysisManager &AM) { 102 llvm::dxil::ModuleMetadataInfo &Data = AM.getResult<DXILMetadataAnalysis>(M); 103 104 Data.print(OS); 105 return PreservedAnalyses::all(); 106 } 107 108 //===----------------------------------------------------------------------===// 109 // DXILMetadataAnalysisWrapperPass 110 111 DXILMetadataAnalysisWrapperPass::DXILMetadataAnalysisWrapperPass() 112 : ModulePass(ID) { 113 initializeDXILMetadataAnalysisWrapperPassPass( 114 *PassRegistry::getPassRegistry()); 115 } 116 117 DXILMetadataAnalysisWrapperPass::~DXILMetadataAnalysisWrapperPass() = default; 118 119 void DXILMetadataAnalysisWrapperPass::getAnalysisUsage( 120 AnalysisUsage &AU) const { 121 AU.setPreservesAll(); 122 } 123 124 bool DXILMetadataAnalysisWrapperPass::runOnModule(Module &M) { 125 MetadataInfo.reset(new ModuleMetadataInfo(collectMetadataInfo(M))); 126 return false; 127 } 128 129 void DXILMetadataAnalysisWrapperPass::releaseMemory() { MetadataInfo.reset(); } 130 131 void DXILMetadataAnalysisWrapperPass::print(raw_ostream &OS, 132 const Module *) const { 133 if (!MetadataInfo) { 134 OS << "No module metadata info has been built!\n"; 135 return; 136 } 137 MetadataInfo->print(dbgs()); 138 } 139 140 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 141 LLVM_DUMP_METHOD 142 void DXILMetadataAnalysisWrapperPass::dump() const { print(dbgs(), nullptr); } 143 #endif 144 145 INITIALIZE_PASS(DXILMetadataAnalysisWrapperPass, "dxil-metadata-analysis", 146 "DXIL Module Metadata analysis", false, true) 147 char DXILMetadataAnalysisWrapperPass::ID = 0; 148