xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/DirectX/DXILMetadata.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1bdd1243dSDimitry Andric //===- DXILMetadata.cpp - DXIL Metadata helper objects --------------------===//
2bdd1243dSDimitry Andric //
3bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6bdd1243dSDimitry Andric //
7bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
8bdd1243dSDimitry Andric ///
9bdd1243dSDimitry Andric /// \file This file contains helper objects for working with DXIL metadata.
10bdd1243dSDimitry Andric ///
11bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
12bdd1243dSDimitry Andric 
13bdd1243dSDimitry Andric #include "DXILMetadata.h"
14bdd1243dSDimitry Andric #include "llvm/IR/Constants.h"
15bdd1243dSDimitry Andric #include "llvm/IR/IRBuilder.h"
16bdd1243dSDimitry Andric #include "llvm/IR/Metadata.h"
17bdd1243dSDimitry Andric #include "llvm/IR/Module.h"
18bdd1243dSDimitry Andric #include "llvm/Support/VersionTuple.h"
1906c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
20bdd1243dSDimitry Andric 
21bdd1243dSDimitry Andric using namespace llvm;
22bdd1243dSDimitry Andric using namespace llvm::dxil;
23bdd1243dSDimitry Andric 
24bdd1243dSDimitry Andric ValidatorVersionMD::ValidatorVersionMD(Module &M)
25bdd1243dSDimitry Andric     : Entry(M.getOrInsertNamedMetadata("dx.valver")) {}
26bdd1243dSDimitry Andric 
27bdd1243dSDimitry Andric void ValidatorVersionMD::update(VersionTuple ValidatorVer) {
28bdd1243dSDimitry Andric   auto &Ctx = Entry->getParent()->getContext();
29bdd1243dSDimitry Andric   IRBuilder<> B(Ctx);
30bdd1243dSDimitry Andric   Metadata *MDVals[2];
31bdd1243dSDimitry Andric   MDVals[0] = ConstantAsMetadata::get(B.getInt32(ValidatorVer.getMajor()));
32bdd1243dSDimitry Andric   MDVals[1] =
33bdd1243dSDimitry Andric       ConstantAsMetadata::get(B.getInt32(ValidatorVer.getMinor().value_or(0)));
34bdd1243dSDimitry Andric 
35bdd1243dSDimitry Andric   if (isEmpty())
36bdd1243dSDimitry Andric     Entry->addOperand(MDNode::get(Ctx, MDVals));
37bdd1243dSDimitry Andric   else
38bdd1243dSDimitry Andric     Entry->setOperand(0, MDNode::get(Ctx, MDVals));
39bdd1243dSDimitry Andric }
40bdd1243dSDimitry Andric 
41bdd1243dSDimitry Andric bool ValidatorVersionMD::isEmpty() { return Entry->getNumOperands() == 0; }
42bdd1243dSDimitry Andric 
43*0fca6ea1SDimitry Andric VersionTuple ValidatorVersionMD::getAsVersionTuple() {
44*0fca6ea1SDimitry Andric   if (isEmpty())
45*0fca6ea1SDimitry Andric     return VersionTuple(1, 0);
46*0fca6ea1SDimitry Andric   auto *ValVerMD = cast<MDNode>(Entry->getOperand(0));
47*0fca6ea1SDimitry Andric   auto *MajorMD = mdconst::extract<ConstantInt>(ValVerMD->getOperand(0));
48*0fca6ea1SDimitry Andric   auto *MinorMD = mdconst::extract<ConstantInt>(ValVerMD->getOperand(1));
49*0fca6ea1SDimitry Andric   return VersionTuple(MajorMD->getZExtValue(), MinorMD->getZExtValue());
50*0fca6ea1SDimitry Andric }
51*0fca6ea1SDimitry Andric 
52bdd1243dSDimitry Andric static StringRef getShortShaderStage(Triple::EnvironmentType Env) {
53bdd1243dSDimitry Andric   switch (Env) {
54bdd1243dSDimitry Andric   case Triple::Pixel:
55bdd1243dSDimitry Andric     return "ps";
56bdd1243dSDimitry Andric   case Triple::Vertex:
57bdd1243dSDimitry Andric     return "vs";
58bdd1243dSDimitry Andric   case Triple::Geometry:
59bdd1243dSDimitry Andric     return "gs";
60bdd1243dSDimitry Andric   case Triple::Hull:
61bdd1243dSDimitry Andric     return "hs";
62bdd1243dSDimitry Andric   case Triple::Domain:
63bdd1243dSDimitry Andric     return "ds";
64bdd1243dSDimitry Andric   case Triple::Compute:
65bdd1243dSDimitry Andric     return "cs";
66bdd1243dSDimitry Andric   case Triple::Library:
67bdd1243dSDimitry Andric     return "lib";
68bdd1243dSDimitry Andric   case Triple::Mesh:
69bdd1243dSDimitry Andric     return "ms";
70bdd1243dSDimitry Andric   case Triple::Amplification:
71bdd1243dSDimitry Andric     return "as";
72bdd1243dSDimitry Andric   default:
73bdd1243dSDimitry Andric     break;
74bdd1243dSDimitry Andric   }
75bdd1243dSDimitry Andric   llvm_unreachable("Unsupported environment for DXIL generation.");
76bdd1243dSDimitry Andric   return "";
77bdd1243dSDimitry Andric }
78bdd1243dSDimitry Andric 
79bdd1243dSDimitry Andric void dxil::createShaderModelMD(Module &M) {
80bdd1243dSDimitry Andric   NamedMDNode *Entry = M.getOrInsertNamedMetadata("dx.shaderModel");
81bdd1243dSDimitry Andric   Triple TT(M.getTargetTriple());
82bdd1243dSDimitry Andric   VersionTuple Ver = TT.getOSVersion();
83bdd1243dSDimitry Andric   LLVMContext &Ctx = M.getContext();
84bdd1243dSDimitry Andric   IRBuilder<> B(Ctx);
85bdd1243dSDimitry Andric 
86bdd1243dSDimitry Andric   Metadata *Vals[3];
87bdd1243dSDimitry Andric   Vals[0] = MDString::get(Ctx, getShortShaderStage(TT.getEnvironment()));
88bdd1243dSDimitry Andric   Vals[1] = ConstantAsMetadata::get(B.getInt32(Ver.getMajor()));
89bdd1243dSDimitry Andric   Vals[2] = ConstantAsMetadata::get(B.getInt32(Ver.getMinor().value_or(0)));
90bdd1243dSDimitry Andric   Entry->addOperand(MDNode::get(Ctx, Vals));
91bdd1243dSDimitry Andric }
92bdd1243dSDimitry Andric 
93*0fca6ea1SDimitry Andric void dxil::createDXILVersionMD(Module &M) {
94*0fca6ea1SDimitry Andric   Triple TT(Triple::normalize(M.getTargetTriple()));
95*0fca6ea1SDimitry Andric   VersionTuple Ver = TT.getDXILVersion();
96*0fca6ea1SDimitry Andric   LLVMContext &Ctx = M.getContext();
97*0fca6ea1SDimitry Andric   IRBuilder<> B(Ctx);
98*0fca6ea1SDimitry Andric   NamedMDNode *Entry = M.getOrInsertNamedMetadata("dx.version");
99*0fca6ea1SDimitry Andric   Metadata *Vals[2];
100*0fca6ea1SDimitry Andric   Vals[0] = ConstantAsMetadata::get(B.getInt32(Ver.getMajor()));
101*0fca6ea1SDimitry Andric   Vals[1] = ConstantAsMetadata::get(B.getInt32(Ver.getMinor().value_or(0)));
102*0fca6ea1SDimitry Andric   Entry->addOperand(MDNode::get(Ctx, Vals));
103*0fca6ea1SDimitry Andric }
104*0fca6ea1SDimitry Andric 
105bdd1243dSDimitry Andric static uint32_t getShaderStage(Triple::EnvironmentType Env) {
106bdd1243dSDimitry Andric   return (uint32_t)Env - (uint32_t)llvm::Triple::Pixel;
107bdd1243dSDimitry Andric }
108bdd1243dSDimitry Andric 
109bdd1243dSDimitry Andric namespace {
110bdd1243dSDimitry Andric 
111bdd1243dSDimitry Andric struct EntryProps {
112bdd1243dSDimitry Andric   Triple::EnvironmentType ShaderKind;
113bdd1243dSDimitry Andric   // FIXME: support more shader profiles.
114bdd1243dSDimitry Andric   // See https://github.com/llvm/llvm-project/issues/57927.
115bdd1243dSDimitry Andric   struct {
116bdd1243dSDimitry Andric     unsigned NumThreads[3];
117bdd1243dSDimitry Andric   } CS;
118bdd1243dSDimitry Andric 
119bdd1243dSDimitry Andric   EntryProps(Function &F, Triple::EnvironmentType ModuleShaderKind)
120bdd1243dSDimitry Andric       : ShaderKind(ModuleShaderKind) {
121bdd1243dSDimitry Andric 
122bdd1243dSDimitry Andric     if (ShaderKind == Triple::EnvironmentType::Library) {
123bdd1243dSDimitry Andric       Attribute EntryAttr = F.getFnAttribute("hlsl.shader");
124bdd1243dSDimitry Andric       StringRef EntryProfile = EntryAttr.getValueAsString();
125bdd1243dSDimitry Andric       Triple T("", "", "", EntryProfile);
126bdd1243dSDimitry Andric       ShaderKind = T.getEnvironment();
127bdd1243dSDimitry Andric     }
128bdd1243dSDimitry Andric 
129bdd1243dSDimitry Andric     if (ShaderKind == Triple::EnvironmentType::Compute) {
130bdd1243dSDimitry Andric       auto NumThreadsStr =
131bdd1243dSDimitry Andric           F.getFnAttribute("hlsl.numthreads").getValueAsString();
132bdd1243dSDimitry Andric       SmallVector<StringRef> NumThreads;
133bdd1243dSDimitry Andric       NumThreadsStr.split(NumThreads, ',');
134bdd1243dSDimitry Andric       assert(NumThreads.size() == 3 && "invalid numthreads");
135bdd1243dSDimitry Andric       auto Zip =
136bdd1243dSDimitry Andric           llvm::zip(NumThreads, MutableArrayRef<unsigned>(CS.NumThreads));
137bdd1243dSDimitry Andric       for (auto It : Zip) {
138bdd1243dSDimitry Andric         StringRef Str = std::get<0>(It);
139bdd1243dSDimitry Andric         APInt V;
140bdd1243dSDimitry Andric         [[maybe_unused]] bool Result = Str.getAsInteger(10, V);
141bdd1243dSDimitry Andric         assert(!Result && "Failed to parse numthreads");
142bdd1243dSDimitry Andric 
143bdd1243dSDimitry Andric         unsigned &Num = std::get<1>(It);
144bdd1243dSDimitry Andric         Num = V.getLimitedValue();
145bdd1243dSDimitry Andric       }
146bdd1243dSDimitry Andric     }
147bdd1243dSDimitry Andric   }
148bdd1243dSDimitry Andric 
149bdd1243dSDimitry Andric   MDTuple *emitDXILEntryProps(uint64_t RawShaderFlag, LLVMContext &Ctx,
150bdd1243dSDimitry Andric                               bool IsLib) {
151bdd1243dSDimitry Andric     std::vector<Metadata *> MDVals;
152bdd1243dSDimitry Andric 
153bdd1243dSDimitry Andric     if (RawShaderFlag != 0)
154bdd1243dSDimitry Andric       appendShaderFlags(MDVals, RawShaderFlag, Ctx);
155bdd1243dSDimitry Andric 
156bdd1243dSDimitry Andric     // Add shader kind for lib entrys.
157bdd1243dSDimitry Andric     if (IsLib && ShaderKind != Triple::EnvironmentType::Library)
158bdd1243dSDimitry Andric       appendShaderKind(MDVals, Ctx);
159bdd1243dSDimitry Andric 
160bdd1243dSDimitry Andric     if (ShaderKind == Triple::EnvironmentType::Compute)
161bdd1243dSDimitry Andric       appendNumThreads(MDVals, Ctx);
162bdd1243dSDimitry Andric     // FIXME: support more props.
163bdd1243dSDimitry Andric     // See https://github.com/llvm/llvm-project/issues/57948.
164bdd1243dSDimitry Andric     return MDNode::get(Ctx, MDVals);
165bdd1243dSDimitry Andric   }
166bdd1243dSDimitry Andric 
167bdd1243dSDimitry Andric   static MDTuple *emitEntryPropsForEmptyEntry(uint64_t RawShaderFlag,
168bdd1243dSDimitry Andric                                               LLVMContext &Ctx) {
169bdd1243dSDimitry Andric     if (RawShaderFlag == 0)
170bdd1243dSDimitry Andric       return nullptr;
171bdd1243dSDimitry Andric 
172bdd1243dSDimitry Andric     std::vector<Metadata *> MDVals;
173bdd1243dSDimitry Andric 
174bdd1243dSDimitry Andric     appendShaderFlags(MDVals, RawShaderFlag, Ctx);
175bdd1243dSDimitry Andric     // FIXME: support more props.
176bdd1243dSDimitry Andric     // See https://github.com/llvm/llvm-project/issues/57948.
177bdd1243dSDimitry Andric     return MDNode::get(Ctx, MDVals);
178bdd1243dSDimitry Andric   }
179bdd1243dSDimitry Andric 
180bdd1243dSDimitry Andric private:
181bdd1243dSDimitry Andric   enum EntryPropsTag {
182bdd1243dSDimitry Andric     ShaderFlagsTag = 0,
183bdd1243dSDimitry Andric     GSStateTag,
184bdd1243dSDimitry Andric     DSStateTag,
185bdd1243dSDimitry Andric     HSStateTag,
186bdd1243dSDimitry Andric     NumThreadsTag,
187bdd1243dSDimitry Andric     AutoBindingSpaceTag,
188bdd1243dSDimitry Andric     RayPayloadSizeTag,
189bdd1243dSDimitry Andric     RayAttribSizeTag,
190bdd1243dSDimitry Andric     ShaderKindTag,
191bdd1243dSDimitry Andric     MSStateTag,
192bdd1243dSDimitry Andric     ASStateTag,
193bdd1243dSDimitry Andric     WaveSizeTag,
194bdd1243dSDimitry Andric     EntryRootSigTag,
195bdd1243dSDimitry Andric   };
196bdd1243dSDimitry Andric 
197bdd1243dSDimitry Andric   void appendNumThreads(std::vector<Metadata *> &MDVals, LLVMContext &Ctx) {
198bdd1243dSDimitry Andric     MDVals.emplace_back(ConstantAsMetadata::get(
199bdd1243dSDimitry Andric         ConstantInt::get(Type::getInt32Ty(Ctx), NumThreadsTag)));
200bdd1243dSDimitry Andric 
201bdd1243dSDimitry Andric     std::vector<Metadata *> NumThreadVals;
202bdd1243dSDimitry Andric     for (auto Num : ArrayRef<unsigned>(CS.NumThreads))
203bdd1243dSDimitry Andric       NumThreadVals.emplace_back(ConstantAsMetadata::get(
204bdd1243dSDimitry Andric           ConstantInt::get(Type::getInt32Ty(Ctx), Num)));
205bdd1243dSDimitry Andric     MDVals.emplace_back(MDNode::get(Ctx, NumThreadVals));
206bdd1243dSDimitry Andric   }
207bdd1243dSDimitry Andric 
208bdd1243dSDimitry Andric   static void appendShaderFlags(std::vector<Metadata *> &MDVals,
209bdd1243dSDimitry Andric                                 uint64_t RawShaderFlag, LLVMContext &Ctx) {
210bdd1243dSDimitry Andric     MDVals.emplace_back(ConstantAsMetadata::get(
211bdd1243dSDimitry Andric         ConstantInt::get(Type::getInt32Ty(Ctx), ShaderFlagsTag)));
212bdd1243dSDimitry Andric     MDVals.emplace_back(ConstantAsMetadata::get(
213bdd1243dSDimitry Andric         ConstantInt::get(Type::getInt64Ty(Ctx), RawShaderFlag)));
214bdd1243dSDimitry Andric   }
215bdd1243dSDimitry Andric 
216bdd1243dSDimitry Andric   void appendShaderKind(std::vector<Metadata *> &MDVals, LLVMContext &Ctx) {
217bdd1243dSDimitry Andric     MDVals.emplace_back(ConstantAsMetadata::get(
218bdd1243dSDimitry Andric         ConstantInt::get(Type::getInt32Ty(Ctx), ShaderKindTag)));
219bdd1243dSDimitry Andric     MDVals.emplace_back(ConstantAsMetadata::get(
220bdd1243dSDimitry Andric         ConstantInt::get(Type::getInt32Ty(Ctx), getShaderStage(ShaderKind))));
221bdd1243dSDimitry Andric   }
222bdd1243dSDimitry Andric };
223bdd1243dSDimitry Andric 
224bdd1243dSDimitry Andric class EntryMD {
225bdd1243dSDimitry Andric   Function &F;
226bdd1243dSDimitry Andric   LLVMContext &Ctx;
227bdd1243dSDimitry Andric   EntryProps Props;
228bdd1243dSDimitry Andric 
229bdd1243dSDimitry Andric public:
230bdd1243dSDimitry Andric   EntryMD(Function &F, Triple::EnvironmentType ModuleShaderKind)
231bdd1243dSDimitry Andric       : F(F), Ctx(F.getContext()), Props(F, ModuleShaderKind) {}
232bdd1243dSDimitry Andric 
233bdd1243dSDimitry Andric   MDTuple *emitEntryTuple(MDTuple *Resources, uint64_t RawShaderFlag) {
234bdd1243dSDimitry Andric     // FIXME: add signature for profile other than CS.
235bdd1243dSDimitry Andric     // See https://github.com/llvm/llvm-project/issues/57928.
236bdd1243dSDimitry Andric     MDTuple *Signatures = nullptr;
237*0fca6ea1SDimitry Andric     return emitDXILEntryPointTuple(
238bdd1243dSDimitry Andric         &F, F.getName().str(), Signatures, Resources,
239bdd1243dSDimitry Andric         Props.emitDXILEntryProps(RawShaderFlag, Ctx, /*IsLib*/ false), Ctx);
240bdd1243dSDimitry Andric   }
241bdd1243dSDimitry Andric 
242bdd1243dSDimitry Andric   MDTuple *emitEntryTupleForLib(uint64_t RawShaderFlag) {
243bdd1243dSDimitry Andric     // FIXME: add signature for profile other than CS.
244bdd1243dSDimitry Andric     // See https://github.com/llvm/llvm-project/issues/57928.
245bdd1243dSDimitry Andric     MDTuple *Signatures = nullptr;
246*0fca6ea1SDimitry Andric     return emitDXILEntryPointTuple(
247bdd1243dSDimitry Andric         &F, F.getName().str(), Signatures,
248bdd1243dSDimitry Andric         /*entry in lib doesn't need resources metadata*/ nullptr,
249bdd1243dSDimitry Andric         Props.emitDXILEntryProps(RawShaderFlag, Ctx, /*IsLib*/ true), Ctx);
250bdd1243dSDimitry Andric   }
251bdd1243dSDimitry Andric 
252bdd1243dSDimitry Andric   // Library will have empty entry metadata which only store the resource table
253bdd1243dSDimitry Andric   // metadata.
254bdd1243dSDimitry Andric   static MDTuple *emitEmptyEntryForLib(MDTuple *Resources,
255bdd1243dSDimitry Andric                                        uint64_t RawShaderFlag,
256bdd1243dSDimitry Andric                                        LLVMContext &Ctx) {
257*0fca6ea1SDimitry Andric     return emitDXILEntryPointTuple(
258bdd1243dSDimitry Andric         nullptr, "", nullptr, Resources,
259bdd1243dSDimitry Andric         EntryProps::emitEntryPropsForEmptyEntry(RawShaderFlag, Ctx), Ctx);
260bdd1243dSDimitry Andric   }
261bdd1243dSDimitry Andric 
262bdd1243dSDimitry Andric private:
263*0fca6ea1SDimitry Andric   static MDTuple *emitDXILEntryPointTuple(Function *Fn, const std::string &Name,
264bdd1243dSDimitry Andric                                           MDTuple *Signatures,
265bdd1243dSDimitry Andric                                           MDTuple *Resources,
266bdd1243dSDimitry Andric                                           MDTuple *Properties,
267bdd1243dSDimitry Andric                                           LLVMContext &Ctx) {
268bdd1243dSDimitry Andric     Metadata *MDVals[5];
269bdd1243dSDimitry Andric     MDVals[0] = Fn ? ValueAsMetadata::get(Fn) : nullptr;
270bdd1243dSDimitry Andric     MDVals[1] = MDString::get(Ctx, Name.c_str());
271bdd1243dSDimitry Andric     MDVals[2] = Signatures;
272bdd1243dSDimitry Andric     MDVals[3] = Resources;
273bdd1243dSDimitry Andric     MDVals[4] = Properties;
274bdd1243dSDimitry Andric     return MDNode::get(Ctx, MDVals);
275bdd1243dSDimitry Andric   }
276bdd1243dSDimitry Andric };
277bdd1243dSDimitry Andric } // namespace
278bdd1243dSDimitry Andric 
279bdd1243dSDimitry Andric void dxil::createEntryMD(Module &M, const uint64_t ShaderFlags) {
280bdd1243dSDimitry Andric   SmallVector<Function *> EntryList;
281bdd1243dSDimitry Andric   for (auto &F : M.functions()) {
282bdd1243dSDimitry Andric     if (!F.hasFnAttribute("hlsl.shader"))
283bdd1243dSDimitry Andric       continue;
284bdd1243dSDimitry Andric     EntryList.emplace_back(&F);
285bdd1243dSDimitry Andric   }
286bdd1243dSDimitry Andric 
287bdd1243dSDimitry Andric   auto &Ctx = M.getContext();
288bdd1243dSDimitry Andric   // FIXME: generate metadata for resource.
289bdd1243dSDimitry Andric   // See https://github.com/llvm/llvm-project/issues/57926.
290bdd1243dSDimitry Andric   MDTuple *MDResources = nullptr;
291bdd1243dSDimitry Andric   if (auto *NamedResources = M.getNamedMetadata("dx.resources"))
292bdd1243dSDimitry Andric     MDResources = dyn_cast<MDTuple>(NamedResources->getOperand(0));
293bdd1243dSDimitry Andric 
294bdd1243dSDimitry Andric   std::vector<MDNode *> Entries;
295bdd1243dSDimitry Andric   Triple T = Triple(M.getTargetTriple());
296bdd1243dSDimitry Andric   switch (T.getEnvironment()) {
297bdd1243dSDimitry Andric   case Triple::EnvironmentType::Library: {
298bdd1243dSDimitry Andric     // Add empty entry to put resource metadata.
299bdd1243dSDimitry Andric     MDTuple *EmptyEntry =
300bdd1243dSDimitry Andric         EntryMD::emitEmptyEntryForLib(MDResources, ShaderFlags, Ctx);
301bdd1243dSDimitry Andric     Entries.emplace_back(EmptyEntry);
302bdd1243dSDimitry Andric 
303bdd1243dSDimitry Andric     for (Function *Entry : EntryList) {
304bdd1243dSDimitry Andric       EntryMD MD(*Entry, T.getEnvironment());
305bdd1243dSDimitry Andric       Entries.emplace_back(MD.emitEntryTupleForLib(0));
306bdd1243dSDimitry Andric     }
307bdd1243dSDimitry Andric   } break;
308bdd1243dSDimitry Andric   case Triple::EnvironmentType::Compute:
309bdd1243dSDimitry Andric   case Triple::EnvironmentType::Amplification:
310bdd1243dSDimitry Andric   case Triple::EnvironmentType::Mesh:
311bdd1243dSDimitry Andric   case Triple::EnvironmentType::Vertex:
312bdd1243dSDimitry Andric   case Triple::EnvironmentType::Hull:
313bdd1243dSDimitry Andric   case Triple::EnvironmentType::Domain:
314bdd1243dSDimitry Andric   case Triple::EnvironmentType::Geometry:
315bdd1243dSDimitry Andric   case Triple::EnvironmentType::Pixel: {
316bdd1243dSDimitry Andric     assert(EntryList.size() == 1 &&
317bdd1243dSDimitry Andric            "non-lib profiles should only have one entry");
318bdd1243dSDimitry Andric     EntryMD MD(*EntryList.front(), T.getEnvironment());
319bdd1243dSDimitry Andric     Entries.emplace_back(MD.emitEntryTuple(MDResources, ShaderFlags));
320bdd1243dSDimitry Andric   } break;
321bdd1243dSDimitry Andric   default:
322bdd1243dSDimitry Andric     assert(0 && "invalid profile");
323bdd1243dSDimitry Andric     break;
324bdd1243dSDimitry Andric   }
325bdd1243dSDimitry Andric 
326bdd1243dSDimitry Andric   NamedMDNode *EntryPointsNamedMD =
327bdd1243dSDimitry Andric       M.getOrInsertNamedMetadata("dx.entryPoints");
328bdd1243dSDimitry Andric   for (auto *Entry : Entries)
329bdd1243dSDimitry Andric     EntryPointsNamedMD->addOperand(Entry);
330bdd1243dSDimitry Andric }
331