xref: /llvm-project/llvm/lib/Target/DirectX/DXILTranslateMetadata.cpp (revision 380bb51b70b6d9f3da07a87f56fc3fe44bc78691)
181ee3855SJustin Bogner //===- DXILTranslateMetadata.cpp - Pass to emit DXIL metadata -------------===//
20c7f7f1bSpython3kgae //
30c7f7f1bSpython3kgae // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40c7f7f1bSpython3kgae // See https://llvm.org/LICENSE.txt for license information.
50c7f7f1bSpython3kgae // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60c7f7f1bSpython3kgae //
70c7f7f1bSpython3kgae //===----------------------------------------------------------------------===//
80c7f7f1bSpython3kgae 
981ee3855SJustin Bogner #include "DXILTranslateMetadata.h"
10618e5006SChris Bieneman #include "DXILResource.h"
1122018555SXiang Li #include "DXILResourceAnalysis.h"
12b8615079SXiang Li #include "DXILShaderFlags.h"
130c7f7f1bSpython3kgae #include "DirectX.h"
143734fa8cSS. Bharadwaj Yadavalli #include "llvm/ADT/SmallVector.h"
153734fa8cSS. Bharadwaj Yadavalli #include "llvm/ADT/Twine.h"
16eb2929d3SXiang Li #include "llvm/Analysis/DXILMetadataAnalysis.h"
17daa79232SJustin Bogner #include "llvm/Analysis/DXILResource.h"
18*380bb51bSjoaosaffran #include "llvm/IR/BasicBlock.h"
190c7f7f1bSpython3kgae #include "llvm/IR/Constants.h"
203734fa8cSS. Bharadwaj Yadavalli #include "llvm/IR/DiagnosticInfo.h"
213734fa8cSS. Bharadwaj Yadavalli #include "llvm/IR/DiagnosticPrinter.h"
223734fa8cSS. Bharadwaj Yadavalli #include "llvm/IR/Function.h"
233734fa8cSS. Bharadwaj Yadavalli #include "llvm/IR/IRBuilder.h"
243734fa8cSS. Bharadwaj Yadavalli #include "llvm/IR/LLVMContext.h"
25*380bb51bSjoaosaffran #include "llvm/IR/MDBuilder.h"
26c6c13d4eSpython3kgae #include "llvm/IR/Metadata.h"
270c7f7f1bSpython3kgae #include "llvm/IR/Module.h"
28daa79232SJustin Bogner #include "llvm/InitializePasses.h"
290c7f7f1bSpython3kgae #include "llvm/Pass.h"
303734fa8cSS. Bharadwaj Yadavalli #include "llvm/Support/ErrorHandling.h"
313734fa8cSS. Bharadwaj Yadavalli #include "llvm/Support/VersionTuple.h"
3262c7f035SArchibald Elliott #include "llvm/TargetParser/Triple.h"
333734fa8cSS. Bharadwaj Yadavalli #include <cstdint>
340c7f7f1bSpython3kgae 
350c7f7f1bSpython3kgae using namespace llvm;
36b8615079SXiang Li using namespace llvm::dxil;
370c7f7f1bSpython3kgae 
383734fa8cSS. Bharadwaj Yadavalli namespace {
393734fa8cSS. Bharadwaj Yadavalli /// A simple Wrapper DiagnosticInfo that generates Module-level diagnostic
403734fa8cSS. Bharadwaj Yadavalli /// for TranslateMetadata pass
413734fa8cSS. Bharadwaj Yadavalli class DiagnosticInfoTranslateMD : public DiagnosticInfo {
423734fa8cSS. Bharadwaj Yadavalli private:
433734fa8cSS. Bharadwaj Yadavalli   const Twine &Msg;
443734fa8cSS. Bharadwaj Yadavalli   const Module &Mod;
453734fa8cSS. Bharadwaj Yadavalli 
463734fa8cSS. Bharadwaj Yadavalli public:
473734fa8cSS. Bharadwaj Yadavalli   /// \p M is the module for which the diagnostic is being emitted. \p Msg is
483734fa8cSS. Bharadwaj Yadavalli   /// the message to show. Note that this class does not copy this message, so
493734fa8cSS. Bharadwaj Yadavalli   /// this reference must be valid for the whole life time of the diagnostic.
503734fa8cSS. Bharadwaj Yadavalli   DiagnosticInfoTranslateMD(const Module &M, const Twine &Msg,
513734fa8cSS. Bharadwaj Yadavalli                             DiagnosticSeverity Severity = DS_Error)
523734fa8cSS. Bharadwaj Yadavalli       : DiagnosticInfo(DK_Unsupported, Severity), Msg(Msg), Mod(M) {}
533734fa8cSS. Bharadwaj Yadavalli 
543734fa8cSS. Bharadwaj Yadavalli   void print(DiagnosticPrinter &DP) const override {
553734fa8cSS. Bharadwaj Yadavalli     DP << Mod.getName() << ": " << Msg << '\n';
563734fa8cSS. Bharadwaj Yadavalli   }
573734fa8cSS. Bharadwaj Yadavalli };
583734fa8cSS. Bharadwaj Yadavalli 
593734fa8cSS. Bharadwaj Yadavalli enum class EntryPropsTag {
603734fa8cSS. Bharadwaj Yadavalli   ShaderFlags = 0,
613734fa8cSS. Bharadwaj Yadavalli   GSState,
623734fa8cSS. Bharadwaj Yadavalli   DSState,
633734fa8cSS. Bharadwaj Yadavalli   HSState,
643734fa8cSS. Bharadwaj Yadavalli   NumThreads,
653734fa8cSS. Bharadwaj Yadavalli   AutoBindingSpace,
663734fa8cSS. Bharadwaj Yadavalli   RayPayloadSize,
673734fa8cSS. Bharadwaj Yadavalli   RayAttribSize,
683734fa8cSS. Bharadwaj Yadavalli   ShaderKind,
693734fa8cSS. Bharadwaj Yadavalli   MSState,
703734fa8cSS. Bharadwaj Yadavalli   ASStateTag,
713734fa8cSS. Bharadwaj Yadavalli   WaveSize,
723734fa8cSS. Bharadwaj Yadavalli   EntryRootSig,
733734fa8cSS. Bharadwaj Yadavalli };
743734fa8cSS. Bharadwaj Yadavalli 
753734fa8cSS. Bharadwaj Yadavalli } // namespace
763734fa8cSS. Bharadwaj Yadavalli 
773eca15cbSJustin Bogner static NamedMDNode *emitResourceMetadata(Module &M, DXILBindingMap &DBM,
783eca15cbSJustin Bogner                                          DXILResourceTypeMap &DRTM,
7958eec851SJustin Bogner                                          const dxil::Resources &MDResources) {
80daa79232SJustin Bogner   LLVMContext &Context = M.getContext();
81daa79232SJustin Bogner 
820e2466f6SJustin Bogner   for (ResourceBindingInfo &RI : DBM)
830e2466f6SJustin Bogner     if (!RI.hasSymbol())
840e2466f6SJustin Bogner       RI.createSymbol(M, DRTM[RI.getHandleTy()].createElementStruct());
850e2466f6SJustin Bogner 
86daa79232SJustin Bogner   SmallVector<Metadata *> SRVs, UAVs, CBufs, Smps;
873eca15cbSJustin Bogner   for (const ResourceBindingInfo &RI : DBM.srvs())
883eca15cbSJustin Bogner     SRVs.push_back(RI.getAsMetadata(M, DRTM[RI.getHandleTy()]));
893eca15cbSJustin Bogner   for (const ResourceBindingInfo &RI : DBM.uavs())
903eca15cbSJustin Bogner     UAVs.push_back(RI.getAsMetadata(M, DRTM[RI.getHandleTy()]));
913eca15cbSJustin Bogner   for (const ResourceBindingInfo &RI : DBM.cbuffers())
923eca15cbSJustin Bogner     CBufs.push_back(RI.getAsMetadata(M, DRTM[RI.getHandleTy()]));
933eca15cbSJustin Bogner   for (const ResourceBindingInfo &RI : DBM.samplers())
943eca15cbSJustin Bogner     Smps.push_back(RI.getAsMetadata(M, DRTM[RI.getHandleTy()]));
95daa79232SJustin Bogner 
96daa79232SJustin Bogner   Metadata *SRVMD = SRVs.empty() ? nullptr : MDNode::get(Context, SRVs);
97daa79232SJustin Bogner   Metadata *UAVMD = UAVs.empty() ? nullptr : MDNode::get(Context, UAVs);
98daa79232SJustin Bogner   Metadata *CBufMD = CBufs.empty() ? nullptr : MDNode::get(Context, CBufs);
99daa79232SJustin Bogner   Metadata *SmpMD = Smps.empty() ? nullptr : MDNode::get(Context, Smps);
1003eca15cbSJustin Bogner   bool HasResources = !DBM.empty();
10158eec851SJustin Bogner 
10258eec851SJustin Bogner   if (MDResources.hasUAVs()) {
103daa79232SJustin Bogner     assert(!UAVMD && "Old and new UAV representations can't coexist");
10458eec851SJustin Bogner     UAVMD = MDResources.writeUAVs(M);
10558eec851SJustin Bogner     HasResources = true;
10658eec851SJustin Bogner   }
10758eec851SJustin Bogner 
10858eec851SJustin Bogner   if (MDResources.hasCBuffers()) {
109daa79232SJustin Bogner     assert(!CBufMD && "Old and new cbuffer representations can't coexist");
11058eec851SJustin Bogner     CBufMD = MDResources.writeCBuffers(M);
11158eec851SJustin Bogner     HasResources = true;
11258eec851SJustin Bogner   }
11358eec851SJustin Bogner 
11458eec851SJustin Bogner   if (!HasResources)
1153734fa8cSS. Bharadwaj Yadavalli     return nullptr;
11658eec851SJustin Bogner 
11758eec851SJustin Bogner   NamedMDNode *ResourceMD = M.getOrInsertNamedMetadata("dx.resources");
11858eec851SJustin Bogner   ResourceMD->addOperand(
11958eec851SJustin Bogner       MDNode::get(M.getContext(), {SRVMD, UAVMD, CBufMD, SmpMD}));
1203734fa8cSS. Bharadwaj Yadavalli 
1213734fa8cSS. Bharadwaj Yadavalli   return ResourceMD;
1223734fa8cSS. Bharadwaj Yadavalli }
1233734fa8cSS. Bharadwaj Yadavalli 
1243734fa8cSS. Bharadwaj Yadavalli static StringRef getShortShaderStage(Triple::EnvironmentType Env) {
1253734fa8cSS. Bharadwaj Yadavalli   switch (Env) {
1263734fa8cSS. Bharadwaj Yadavalli   case Triple::Pixel:
1273734fa8cSS. Bharadwaj Yadavalli     return "ps";
1283734fa8cSS. Bharadwaj Yadavalli   case Triple::Vertex:
1293734fa8cSS. Bharadwaj Yadavalli     return "vs";
1303734fa8cSS. Bharadwaj Yadavalli   case Triple::Geometry:
1313734fa8cSS. Bharadwaj Yadavalli     return "gs";
1323734fa8cSS. Bharadwaj Yadavalli   case Triple::Hull:
1333734fa8cSS. Bharadwaj Yadavalli     return "hs";
1343734fa8cSS. Bharadwaj Yadavalli   case Triple::Domain:
1353734fa8cSS. Bharadwaj Yadavalli     return "ds";
1363734fa8cSS. Bharadwaj Yadavalli   case Triple::Compute:
1373734fa8cSS. Bharadwaj Yadavalli     return "cs";
1383734fa8cSS. Bharadwaj Yadavalli   case Triple::Library:
1393734fa8cSS. Bharadwaj Yadavalli     return "lib";
1403734fa8cSS. Bharadwaj Yadavalli   case Triple::Mesh:
1413734fa8cSS. Bharadwaj Yadavalli     return "ms";
1423734fa8cSS. Bharadwaj Yadavalli   case Triple::Amplification:
1433734fa8cSS. Bharadwaj Yadavalli     return "as";
1443734fa8cSS. Bharadwaj Yadavalli   default:
1453734fa8cSS. Bharadwaj Yadavalli     break;
1463734fa8cSS. Bharadwaj Yadavalli   }
1473734fa8cSS. Bharadwaj Yadavalli   llvm_unreachable("Unsupported environment for DXIL generation.");
1483734fa8cSS. Bharadwaj Yadavalli }
1493734fa8cSS. Bharadwaj Yadavalli 
1503734fa8cSS. Bharadwaj Yadavalli static uint32_t getShaderStage(Triple::EnvironmentType Env) {
1513734fa8cSS. Bharadwaj Yadavalli   return (uint32_t)Env - (uint32_t)llvm::Triple::Pixel;
1523734fa8cSS. Bharadwaj Yadavalli }
1533734fa8cSS. Bharadwaj Yadavalli 
1543734fa8cSS. Bharadwaj Yadavalli static SmallVector<Metadata *>
1553734fa8cSS. Bharadwaj Yadavalli getTagValueAsMetadata(EntryPropsTag Tag, uint64_t Value, LLVMContext &Ctx) {
1563734fa8cSS. Bharadwaj Yadavalli   SmallVector<Metadata *> MDVals;
1573734fa8cSS. Bharadwaj Yadavalli   MDVals.emplace_back(ConstantAsMetadata::get(
1583734fa8cSS. Bharadwaj Yadavalli       ConstantInt::get(Type::getInt32Ty(Ctx), static_cast<int>(Tag))));
1593734fa8cSS. Bharadwaj Yadavalli   switch (Tag) {
1603734fa8cSS. Bharadwaj Yadavalli   case EntryPropsTag::ShaderFlags:
1613734fa8cSS. Bharadwaj Yadavalli     MDVals.emplace_back(ConstantAsMetadata::get(
1623734fa8cSS. Bharadwaj Yadavalli         ConstantInt::get(Type::getInt64Ty(Ctx), Value)));
1633734fa8cSS. Bharadwaj Yadavalli     break;
1643734fa8cSS. Bharadwaj Yadavalli   case EntryPropsTag::ShaderKind:
1653734fa8cSS. Bharadwaj Yadavalli     MDVals.emplace_back(ConstantAsMetadata::get(
1663734fa8cSS. Bharadwaj Yadavalli         ConstantInt::get(Type::getInt32Ty(Ctx), Value)));
1673734fa8cSS. Bharadwaj Yadavalli     break;
1683734fa8cSS. Bharadwaj Yadavalli   case EntryPropsTag::GSState:
1693734fa8cSS. Bharadwaj Yadavalli   case EntryPropsTag::DSState:
1703734fa8cSS. Bharadwaj Yadavalli   case EntryPropsTag::HSState:
1713734fa8cSS. Bharadwaj Yadavalli   case EntryPropsTag::NumThreads:
1723734fa8cSS. Bharadwaj Yadavalli   case EntryPropsTag::AutoBindingSpace:
1733734fa8cSS. Bharadwaj Yadavalli   case EntryPropsTag::RayPayloadSize:
1743734fa8cSS. Bharadwaj Yadavalli   case EntryPropsTag::RayAttribSize:
1753734fa8cSS. Bharadwaj Yadavalli   case EntryPropsTag::MSState:
1763734fa8cSS. Bharadwaj Yadavalli   case EntryPropsTag::ASStateTag:
1773734fa8cSS. Bharadwaj Yadavalli   case EntryPropsTag::WaveSize:
1783734fa8cSS. Bharadwaj Yadavalli   case EntryPropsTag::EntryRootSig:
1793734fa8cSS. Bharadwaj Yadavalli     llvm_unreachable("NYI: Unhandled entry property tag");
1803734fa8cSS. Bharadwaj Yadavalli   }
1813734fa8cSS. Bharadwaj Yadavalli   return MDVals;
1823734fa8cSS. Bharadwaj Yadavalli }
1833734fa8cSS. Bharadwaj Yadavalli 
1843734fa8cSS. Bharadwaj Yadavalli static MDTuple *
1853734fa8cSS. Bharadwaj Yadavalli getEntryPropAsMetadata(const EntryProperties &EP, uint64_t EntryShaderFlags,
1863734fa8cSS. Bharadwaj Yadavalli                        const Triple::EnvironmentType ShaderProfile) {
1873734fa8cSS. Bharadwaj Yadavalli   SmallVector<Metadata *> MDVals;
1883734fa8cSS. Bharadwaj Yadavalli   LLVMContext &Ctx = EP.Entry->getContext();
1893734fa8cSS. Bharadwaj Yadavalli   if (EntryShaderFlags != 0)
1903734fa8cSS. Bharadwaj Yadavalli     MDVals.append(getTagValueAsMetadata(EntryPropsTag::ShaderFlags,
1913734fa8cSS. Bharadwaj Yadavalli                                         EntryShaderFlags, Ctx));
1923734fa8cSS. Bharadwaj Yadavalli 
1933734fa8cSS. Bharadwaj Yadavalli   if (EP.Entry != nullptr) {
1943734fa8cSS. Bharadwaj Yadavalli     // FIXME: support more props.
1953734fa8cSS. Bharadwaj Yadavalli     // See https://github.com/llvm/llvm-project/issues/57948.
1963734fa8cSS. Bharadwaj Yadavalli     // Add shader kind for lib entries.
1973734fa8cSS. Bharadwaj Yadavalli     if (ShaderProfile == Triple::EnvironmentType::Library &&
1983734fa8cSS. Bharadwaj Yadavalli         EP.ShaderStage != Triple::EnvironmentType::Library)
1993734fa8cSS. Bharadwaj Yadavalli       MDVals.append(getTagValueAsMetadata(EntryPropsTag::ShaderKind,
2003734fa8cSS. Bharadwaj Yadavalli                                           getShaderStage(EP.ShaderStage), Ctx));
2013734fa8cSS. Bharadwaj Yadavalli 
2023734fa8cSS. Bharadwaj Yadavalli     if (EP.ShaderStage == Triple::EnvironmentType::Compute) {
2033734fa8cSS. Bharadwaj Yadavalli       MDVals.emplace_back(ConstantAsMetadata::get(ConstantInt::get(
2043734fa8cSS. Bharadwaj Yadavalli           Type::getInt32Ty(Ctx), static_cast<int>(EntryPropsTag::NumThreads))));
2053734fa8cSS. Bharadwaj Yadavalli       Metadata *NumThreadVals[] = {ConstantAsMetadata::get(ConstantInt::get(
2063734fa8cSS. Bharadwaj Yadavalli                                        Type::getInt32Ty(Ctx), EP.NumThreadsX)),
2073734fa8cSS. Bharadwaj Yadavalli                                    ConstantAsMetadata::get(ConstantInt::get(
2083734fa8cSS. Bharadwaj Yadavalli                                        Type::getInt32Ty(Ctx), EP.NumThreadsY)),
2093734fa8cSS. Bharadwaj Yadavalli                                    ConstantAsMetadata::get(ConstantInt::get(
2103734fa8cSS. Bharadwaj Yadavalli                                        Type::getInt32Ty(Ctx), EP.NumThreadsZ))};
2113734fa8cSS. Bharadwaj Yadavalli       MDVals.emplace_back(MDNode::get(Ctx, NumThreadVals));
2123734fa8cSS. Bharadwaj Yadavalli     }
2133734fa8cSS. Bharadwaj Yadavalli   }
2143734fa8cSS. Bharadwaj Yadavalli   if (MDVals.empty())
2153734fa8cSS. Bharadwaj Yadavalli     return nullptr;
2163734fa8cSS. Bharadwaj Yadavalli   return MDNode::get(Ctx, MDVals);
2173734fa8cSS. Bharadwaj Yadavalli }
2183734fa8cSS. Bharadwaj Yadavalli 
2193734fa8cSS. Bharadwaj Yadavalli MDTuple *constructEntryMetadata(const Function *EntryFn, MDTuple *Signatures,
2203734fa8cSS. Bharadwaj Yadavalli                                 MDNode *Resources, MDTuple *Properties,
2213734fa8cSS. Bharadwaj Yadavalli                                 LLVMContext &Ctx) {
2223734fa8cSS. Bharadwaj Yadavalli   // Each entry point metadata record specifies:
2233734fa8cSS. Bharadwaj Yadavalli   //  * reference to the entry point function global symbol
2243734fa8cSS. Bharadwaj Yadavalli   //  * unmangled name
2253734fa8cSS. Bharadwaj Yadavalli   //  * list of signatures
2263734fa8cSS. Bharadwaj Yadavalli   //  * list of resources
2273734fa8cSS. Bharadwaj Yadavalli   //  * list of tag-value pairs of shader capabilities and other properties
2283734fa8cSS. Bharadwaj Yadavalli   Metadata *MDVals[5];
2293734fa8cSS. Bharadwaj Yadavalli   MDVals[0] =
2303734fa8cSS. Bharadwaj Yadavalli       EntryFn ? ValueAsMetadata::get(const_cast<Function *>(EntryFn)) : nullptr;
2313734fa8cSS. Bharadwaj Yadavalli   MDVals[1] = MDString::get(Ctx, EntryFn ? EntryFn->getName() : "");
2323734fa8cSS. Bharadwaj Yadavalli   MDVals[2] = Signatures;
2333734fa8cSS. Bharadwaj Yadavalli   MDVals[3] = Resources;
2343734fa8cSS. Bharadwaj Yadavalli   MDVals[4] = Properties;
2353734fa8cSS. Bharadwaj Yadavalli   return MDNode::get(Ctx, MDVals);
2363734fa8cSS. Bharadwaj Yadavalli }
2373734fa8cSS. Bharadwaj Yadavalli 
2383734fa8cSS. Bharadwaj Yadavalli static MDTuple *emitEntryMD(const EntryProperties &EP, MDTuple *Signatures,
2393734fa8cSS. Bharadwaj Yadavalli                             MDNode *MDResources,
2403734fa8cSS. Bharadwaj Yadavalli                             const uint64_t EntryShaderFlags,
2413734fa8cSS. Bharadwaj Yadavalli                             const Triple::EnvironmentType ShaderProfile) {
2423734fa8cSS. Bharadwaj Yadavalli   MDTuple *Properties =
2433734fa8cSS. Bharadwaj Yadavalli       getEntryPropAsMetadata(EP, EntryShaderFlags, ShaderProfile);
2443734fa8cSS. Bharadwaj Yadavalli   return constructEntryMetadata(EP.Entry, Signatures, MDResources, Properties,
2453734fa8cSS. Bharadwaj Yadavalli                                 EP.Entry->getContext());
2463734fa8cSS. Bharadwaj Yadavalli }
2473734fa8cSS. Bharadwaj Yadavalli 
2483734fa8cSS. Bharadwaj Yadavalli static void emitValidatorVersionMD(Module &M, const ModuleMetadataInfo &MMDI) {
2493734fa8cSS. Bharadwaj Yadavalli   if (MMDI.ValidatorVersion.empty())
2503734fa8cSS. Bharadwaj Yadavalli     return;
2513734fa8cSS. Bharadwaj Yadavalli 
2523734fa8cSS. Bharadwaj Yadavalli   LLVMContext &Ctx = M.getContext();
2533734fa8cSS. Bharadwaj Yadavalli   IRBuilder<> IRB(Ctx);
2543734fa8cSS. Bharadwaj Yadavalli   Metadata *MDVals[2];
2553734fa8cSS. Bharadwaj Yadavalli   MDVals[0] =
2563734fa8cSS. Bharadwaj Yadavalli       ConstantAsMetadata::get(IRB.getInt32(MMDI.ValidatorVersion.getMajor()));
2573734fa8cSS. Bharadwaj Yadavalli   MDVals[1] = ConstantAsMetadata::get(
2583734fa8cSS. Bharadwaj Yadavalli       IRB.getInt32(MMDI.ValidatorVersion.getMinor().value_or(0)));
2593734fa8cSS. Bharadwaj Yadavalli   NamedMDNode *ValVerNode = M.getOrInsertNamedMetadata("dx.valver");
2603734fa8cSS. Bharadwaj Yadavalli   // Set validator version obtained from DXIL Metadata Analysis pass
2613734fa8cSS. Bharadwaj Yadavalli   ValVerNode->clearOperands();
2623734fa8cSS. Bharadwaj Yadavalli   ValVerNode->addOperand(MDNode::get(Ctx, MDVals));
2633734fa8cSS. Bharadwaj Yadavalli }
2643734fa8cSS. Bharadwaj Yadavalli 
2653734fa8cSS. Bharadwaj Yadavalli static void emitShaderModelVersionMD(Module &M,
2663734fa8cSS. Bharadwaj Yadavalli                                      const ModuleMetadataInfo &MMDI) {
2673734fa8cSS. Bharadwaj Yadavalli   LLVMContext &Ctx = M.getContext();
2683734fa8cSS. Bharadwaj Yadavalli   IRBuilder<> IRB(Ctx);
2693734fa8cSS. Bharadwaj Yadavalli   Metadata *SMVals[3];
2703734fa8cSS. Bharadwaj Yadavalli   VersionTuple SM = MMDI.ShaderModelVersion;
2713734fa8cSS. Bharadwaj Yadavalli   SMVals[0] = MDString::get(Ctx, getShortShaderStage(MMDI.ShaderProfile));
2723734fa8cSS. Bharadwaj Yadavalli   SMVals[1] = ConstantAsMetadata::get(IRB.getInt32(SM.getMajor()));
2733734fa8cSS. Bharadwaj Yadavalli   SMVals[2] = ConstantAsMetadata::get(IRB.getInt32(SM.getMinor().value_or(0)));
2743734fa8cSS. Bharadwaj Yadavalli   NamedMDNode *SMMDNode = M.getOrInsertNamedMetadata("dx.shaderModel");
2753734fa8cSS. Bharadwaj Yadavalli   SMMDNode->addOperand(MDNode::get(Ctx, SMVals));
2763734fa8cSS. Bharadwaj Yadavalli }
2773734fa8cSS. Bharadwaj Yadavalli 
2783734fa8cSS. Bharadwaj Yadavalli static void emitDXILVersionTupleMD(Module &M, const ModuleMetadataInfo &MMDI) {
2793734fa8cSS. Bharadwaj Yadavalli   LLVMContext &Ctx = M.getContext();
2803734fa8cSS. Bharadwaj Yadavalli   IRBuilder<> IRB(Ctx);
2813734fa8cSS. Bharadwaj Yadavalli   VersionTuple DXILVer = MMDI.DXILVersion;
2823734fa8cSS. Bharadwaj Yadavalli   Metadata *DXILVals[2];
2833734fa8cSS. Bharadwaj Yadavalli   DXILVals[0] = ConstantAsMetadata::get(IRB.getInt32(DXILVer.getMajor()));
2843734fa8cSS. Bharadwaj Yadavalli   DXILVals[1] =
2853734fa8cSS. Bharadwaj Yadavalli       ConstantAsMetadata::get(IRB.getInt32(DXILVer.getMinor().value_or(0)));
2863734fa8cSS. Bharadwaj Yadavalli   NamedMDNode *DXILVerMDNode = M.getOrInsertNamedMetadata("dx.version");
2873734fa8cSS. Bharadwaj Yadavalli   DXILVerMDNode->addOperand(MDNode::get(Ctx, DXILVals));
2883734fa8cSS. Bharadwaj Yadavalli }
2893734fa8cSS. Bharadwaj Yadavalli 
2903734fa8cSS. Bharadwaj Yadavalli static MDTuple *emitTopLevelLibraryNode(Module &M, MDNode *RMD,
2913734fa8cSS. Bharadwaj Yadavalli                                         uint64_t ShaderFlags) {
2923734fa8cSS. Bharadwaj Yadavalli   LLVMContext &Ctx = M.getContext();
2933734fa8cSS. Bharadwaj Yadavalli   MDTuple *Properties = nullptr;
2943734fa8cSS. Bharadwaj Yadavalli   if (ShaderFlags != 0) {
2953734fa8cSS. Bharadwaj Yadavalli     SmallVector<Metadata *> MDVals;
2963734fa8cSS. Bharadwaj Yadavalli     MDVals.append(
2973734fa8cSS. Bharadwaj Yadavalli         getTagValueAsMetadata(EntryPropsTag::ShaderFlags, ShaderFlags, Ctx));
2983734fa8cSS. Bharadwaj Yadavalli     Properties = MDNode::get(Ctx, MDVals);
2993734fa8cSS. Bharadwaj Yadavalli   }
3003734fa8cSS. Bharadwaj Yadavalli   // Library has an entry metadata with resource table metadata and all other
3013734fa8cSS. Bharadwaj Yadavalli   // MDNodes as null.
3023734fa8cSS. Bharadwaj Yadavalli   return constructEntryMetadata(nullptr, nullptr, RMD, Properties, Ctx);
30358eec851SJustin Bogner }
30458eec851SJustin Bogner 
305*380bb51bSjoaosaffran // TODO: We might need to refactor this to be more generic,
306*380bb51bSjoaosaffran // in case we need more metadata to be replaced.
307*380bb51bSjoaosaffran static void translateBranchMetadata(Module &M) {
308*380bb51bSjoaosaffran   for (Function &F : M) {
309*380bb51bSjoaosaffran     for (BasicBlock &BB : F) {
310*380bb51bSjoaosaffran       Instruction *BBTerminatorInst = BB.getTerminator();
311*380bb51bSjoaosaffran 
312*380bb51bSjoaosaffran       MDNode *HlslControlFlowMD =
313*380bb51bSjoaosaffran           BBTerminatorInst->getMetadata("hlsl.controlflow.hint");
314*380bb51bSjoaosaffran 
315*380bb51bSjoaosaffran       if (!HlslControlFlowMD)
316*380bb51bSjoaosaffran         continue;
317*380bb51bSjoaosaffran 
318*380bb51bSjoaosaffran       assert(HlslControlFlowMD->getNumOperands() == 2 &&
319*380bb51bSjoaosaffran              "invalid operands for hlsl.controlflow.hint");
320*380bb51bSjoaosaffran 
321*380bb51bSjoaosaffran       MDBuilder MDHelper(M.getContext());
322*380bb51bSjoaosaffran       ConstantInt *Op1 =
323*380bb51bSjoaosaffran           mdconst::extract<ConstantInt>(HlslControlFlowMD->getOperand(1));
324*380bb51bSjoaosaffran 
325*380bb51bSjoaosaffran       SmallVector<llvm::Metadata *, 2> Vals(
326*380bb51bSjoaosaffran           ArrayRef<Metadata *>{MDHelper.createString("dx.controlflow.hints"),
327*380bb51bSjoaosaffran                                MDHelper.createConstant(Op1)});
328*380bb51bSjoaosaffran 
329*380bb51bSjoaosaffran       MDNode *MDNode = llvm::MDNode::get(M.getContext(), Vals);
330*380bb51bSjoaosaffran 
331*380bb51bSjoaosaffran       BBTerminatorInst->setMetadata("dx.controlflow.hints", MDNode);
332*380bb51bSjoaosaffran       BBTerminatorInst->setMetadata("hlsl.controlflow.hint", nullptr);
333*380bb51bSjoaosaffran     }
334*380bb51bSjoaosaffran   }
335*380bb51bSjoaosaffran }
336*380bb51bSjoaosaffran 
3373eca15cbSJustin Bogner static void translateMetadata(Module &M, DXILBindingMap &DBM,
3383eca15cbSJustin Bogner                               DXILResourceTypeMap &DRTM,
3393734fa8cSS. Bharadwaj Yadavalli                               const Resources &MDResources,
34096547decSS. Bharadwaj Yadavalli                               const ModuleShaderFlags &ShaderFlags,
3413734fa8cSS. Bharadwaj Yadavalli                               const ModuleMetadataInfo &MMDI) {
3423734fa8cSS. Bharadwaj Yadavalli   LLVMContext &Ctx = M.getContext();
3433734fa8cSS. Bharadwaj Yadavalli   IRBuilder<> IRB(Ctx);
3443734fa8cSS. Bharadwaj Yadavalli   SmallVector<MDNode *> EntryFnMDNodes;
34581ee3855SJustin Bogner 
3463734fa8cSS. Bharadwaj Yadavalli   emitValidatorVersionMD(M, MMDI);
3473734fa8cSS. Bharadwaj Yadavalli   emitShaderModelVersionMD(M, MMDI);
3483734fa8cSS. Bharadwaj Yadavalli   emitDXILVersionTupleMD(M, MMDI);
3493eca15cbSJustin Bogner   NamedMDNode *NamedResourceMD =
3503eca15cbSJustin Bogner       emitResourceMetadata(M, DBM, DRTM, MDResources);
3513734fa8cSS. Bharadwaj Yadavalli   auto *ResourceMD =
3523734fa8cSS. Bharadwaj Yadavalli       (NamedResourceMD != nullptr) ? NamedResourceMD->getOperand(0) : nullptr;
3533734fa8cSS. Bharadwaj Yadavalli   // FIXME: Add support to construct Signatures
3543734fa8cSS. Bharadwaj Yadavalli   // See https://github.com/llvm/llvm-project/issues/57928
3553734fa8cSS. Bharadwaj Yadavalli   MDTuple *Signatures = nullptr;
35681ee3855SJustin Bogner 
35796547decSS. Bharadwaj Yadavalli   if (MMDI.ShaderProfile == Triple::EnvironmentType::Library) {
35896547decSS. Bharadwaj Yadavalli     // Get the combined shader flag mask of all functions in the library to be
35996547decSS. Bharadwaj Yadavalli     // used as shader flags mask value associated with top-level library entry
36096547decSS. Bharadwaj Yadavalli     // metadata.
36196547decSS. Bharadwaj Yadavalli     uint64_t CombinedMask = ShaderFlags.getCombinedFlags();
3623734fa8cSS. Bharadwaj Yadavalli     EntryFnMDNodes.emplace_back(
36396547decSS. Bharadwaj Yadavalli         emitTopLevelLibraryNode(M, ResourceMD, CombinedMask));
36496547decSS. Bharadwaj Yadavalli   } else if (MMDI.EntryPropertyVec.size() > 1) {
3653734fa8cSS. Bharadwaj Yadavalli     M.getContext().diagnose(DiagnosticInfoTranslateMD(
3663734fa8cSS. Bharadwaj Yadavalli         M, "Non-library shader: One and only one entry expected"));
3673734fa8cSS. Bharadwaj Yadavalli   }
3683734fa8cSS. Bharadwaj Yadavalli 
3693734fa8cSS. Bharadwaj Yadavalli   for (const EntryProperties &EntryProp : MMDI.EntryPropertyVec) {
37096547decSS. Bharadwaj Yadavalli     const ComputedShaderFlags &EntrySFMask =
37196547decSS. Bharadwaj Yadavalli         ShaderFlags.getFunctionFlags(EntryProp.Entry);
37296547decSS. Bharadwaj Yadavalli 
37396547decSS. Bharadwaj Yadavalli     // If ShaderProfile is Library, mask is already consolidated in the
37496547decSS. Bharadwaj Yadavalli     // top-level library node. Hence it is not emitted.
37596547decSS. Bharadwaj Yadavalli     uint64_t EntryShaderFlags = 0;
3763734fa8cSS. Bharadwaj Yadavalli     if (MMDI.ShaderProfile != Triple::EnvironmentType::Library) {
37796547decSS. Bharadwaj Yadavalli       EntryShaderFlags = EntrySFMask;
3783734fa8cSS. Bharadwaj Yadavalli       if (EntryProp.ShaderStage != MMDI.ShaderProfile) {
3793734fa8cSS. Bharadwaj Yadavalli         M.getContext().diagnose(DiagnosticInfoTranslateMD(
3803734fa8cSS. Bharadwaj Yadavalli             M,
3813734fa8cSS. Bharadwaj Yadavalli             "Shader stage '" +
3823734fa8cSS. Bharadwaj Yadavalli                 Twine(getShortShaderStage(EntryProp.ShaderStage) +
3833734fa8cSS. Bharadwaj Yadavalli                       "' for entry '" + Twine(EntryProp.Entry->getName()) +
3843734fa8cSS. Bharadwaj Yadavalli                       "' different from specified target profile '" +
3853734fa8cSS. Bharadwaj Yadavalli                       Twine(Triple::getEnvironmentTypeName(MMDI.ShaderProfile) +
3863734fa8cSS. Bharadwaj Yadavalli                             "'"))));
3873734fa8cSS. Bharadwaj Yadavalli       }
3883734fa8cSS. Bharadwaj Yadavalli     }
3893734fa8cSS. Bharadwaj Yadavalli     EntryFnMDNodes.emplace_back(emitEntryMD(EntryProp, Signatures, ResourceMD,
3903734fa8cSS. Bharadwaj Yadavalli                                             EntryShaderFlags,
3913734fa8cSS. Bharadwaj Yadavalli                                             MMDI.ShaderProfile));
3923734fa8cSS. Bharadwaj Yadavalli   }
3933734fa8cSS. Bharadwaj Yadavalli 
3943734fa8cSS. Bharadwaj Yadavalli   NamedMDNode *EntryPointsNamedMD =
3953734fa8cSS. Bharadwaj Yadavalli       M.getOrInsertNamedMetadata("dx.entryPoints");
3963734fa8cSS. Bharadwaj Yadavalli   for (auto *Entry : EntryFnMDNodes)
3973734fa8cSS. Bharadwaj Yadavalli     EntryPointsNamedMD->addOperand(Entry);
39881ee3855SJustin Bogner }
39981ee3855SJustin Bogner 
40081ee3855SJustin Bogner PreservedAnalyses DXILTranslateMetadata::run(Module &M,
40181ee3855SJustin Bogner                                              ModuleAnalysisManager &MAM) {
4023eca15cbSJustin Bogner   DXILBindingMap &DBM = MAM.getResult<DXILResourceBindingAnalysis>(M);
4033eca15cbSJustin Bogner   DXILResourceTypeMap &DRTM = MAM.getResult<DXILResourceTypeAnalysis>(M);
40481ee3855SJustin Bogner   const dxil::Resources &MDResources = MAM.getResult<DXILResourceMDAnalysis>(M);
40596547decSS. Bharadwaj Yadavalli   const ModuleShaderFlags &ShaderFlags = MAM.getResult<ShaderFlagsAnalysis>(M);
4063734fa8cSS. Bharadwaj Yadavalli   const dxil::ModuleMetadataInfo MMDI = MAM.getResult<DXILMetadataAnalysis>(M);
40781ee3855SJustin Bogner 
4083eca15cbSJustin Bogner   translateMetadata(M, DBM, DRTM, MDResources, ShaderFlags, MMDI);
409*380bb51bSjoaosaffran   translateBranchMetadata(M);
41081ee3855SJustin Bogner 
41181ee3855SJustin Bogner   return PreservedAnalyses::all();
41281ee3855SJustin Bogner }
41381ee3855SJustin Bogner 
4140c7f7f1bSpython3kgae namespace {
41581ee3855SJustin Bogner class DXILTranslateMetadataLegacy : public ModulePass {
4160c7f7f1bSpython3kgae public:
4170c7f7f1bSpython3kgae   static char ID; // Pass identification, replacement for typeid
41881ee3855SJustin Bogner   explicit DXILTranslateMetadataLegacy() : ModulePass(ID) {}
4190c7f7f1bSpython3kgae 
4208107810cSJustin Bogner   StringRef getPassName() const override { return "DXIL Translate Metadata"; }
4210c7f7f1bSpython3kgae 
42222018555SXiang Li   void getAnalysisUsage(AnalysisUsage &AU) const override {
4233eca15cbSJustin Bogner     AU.addRequired<DXILResourceTypeWrapperPass>();
4243eca15cbSJustin Bogner     AU.addRequired<DXILResourceBindingWrapperPass>();
4251c5f6cfcSJustin Bogner     AU.addRequired<DXILResourceMDWrapper>();
426b8615079SXiang Li     AU.addRequired<ShaderFlagsAnalysisWrapper>();
427eb2929d3SXiang Li     AU.addRequired<DXILMetadataAnalysisWrapperPass>();
4283eca15cbSJustin Bogner     AU.addPreserved<DXILResourceBindingWrapperPass>();
4293734fa8cSS. Bharadwaj Yadavalli     AU.addPreserved<DXILResourceMDWrapper>();
4303734fa8cSS. Bharadwaj Yadavalli     AU.addPreserved<DXILMetadataAnalysisWrapperPass>();
431bfd05102SJustin Bogner     AU.addPreserved<ShaderFlagsAnalysisWrapper>();
43222018555SXiang Li   }
43322018555SXiang Li 
43481ee3855SJustin Bogner   bool runOnModule(Module &M) override {
4353eca15cbSJustin Bogner     DXILBindingMap &DBM =
4363eca15cbSJustin Bogner         getAnalysis<DXILResourceBindingWrapperPass>().getBindingMap();
4373eca15cbSJustin Bogner     DXILResourceTypeMap &DRTM =
4383eca15cbSJustin Bogner         getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();
43981ee3855SJustin Bogner     const dxil::Resources &MDResources =
44081ee3855SJustin Bogner         getAnalysis<DXILResourceMDWrapper>().getDXILResource();
44196547decSS. Bharadwaj Yadavalli     const ModuleShaderFlags &ShaderFlags =
44281ee3855SJustin Bogner         getAnalysis<ShaderFlagsAnalysisWrapper>().getShaderFlags();
4433734fa8cSS. Bharadwaj Yadavalli     dxil::ModuleMetadataInfo MMDI =
4443734fa8cSS. Bharadwaj Yadavalli         getAnalysis<DXILMetadataAnalysisWrapperPass>().getModuleMetadata();
44581ee3855SJustin Bogner 
4463eca15cbSJustin Bogner     translateMetadata(M, DBM, DRTM, MDResources, ShaderFlags, MMDI);
447*380bb51bSjoaosaffran     translateBranchMetadata(M);
44881ee3855SJustin Bogner     return true;
44981ee3855SJustin Bogner   }
4500c7f7f1bSpython3kgae };
4510c7f7f1bSpython3kgae 
4520c7f7f1bSpython3kgae } // namespace
4530c7f7f1bSpython3kgae 
45481ee3855SJustin Bogner char DXILTranslateMetadataLegacy::ID = 0;
4554959bfa0SChris Bieneman 
45681ee3855SJustin Bogner ModulePass *llvm::createDXILTranslateMetadataLegacyPass() {
45781ee3855SJustin Bogner   return new DXILTranslateMetadataLegacy();
4580c7f7f1bSpython3kgae }
4590c7f7f1bSpython3kgae 
46081ee3855SJustin Bogner INITIALIZE_PASS_BEGIN(DXILTranslateMetadataLegacy, "dxil-translate-metadata",
4618107810cSJustin Bogner                       "DXIL Translate Metadata", false, false)
4623eca15cbSJustin Bogner INITIALIZE_PASS_DEPENDENCY(DXILResourceBindingWrapperPass)
4631c5f6cfcSJustin Bogner INITIALIZE_PASS_DEPENDENCY(DXILResourceMDWrapper)
464b8615079SXiang Li INITIALIZE_PASS_DEPENDENCY(ShaderFlagsAnalysisWrapper)
4653734fa8cSS. Bharadwaj Yadavalli INITIALIZE_PASS_DEPENDENCY(DXILMetadataAnalysisWrapperPass)
46681ee3855SJustin Bogner INITIALIZE_PASS_END(DXILTranslateMetadataLegacy, "dxil-translate-metadata",
4678107810cSJustin Bogner                     "DXIL Translate Metadata", false, false)
468