xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/DirectX/DXILResource.cpp (revision cb14a3fe5122c879eae1fb480ed7ce82a699ddb6)
1bdd1243dSDimitry Andric //===- DXILResource.cpp - DXIL Resource 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 Resources.
10bdd1243dSDimitry Andric ///
11bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
12bdd1243dSDimitry Andric 
13bdd1243dSDimitry Andric #include "DXILResource.h"
14bdd1243dSDimitry Andric #include "CBufferDataLayout.h"
15bdd1243dSDimitry Andric #include "llvm/ADT/StringSwitch.h"
16bdd1243dSDimitry Andric #include "llvm/IR/IRBuilder.h"
17bdd1243dSDimitry Andric #include "llvm/IR/Metadata.h"
18bdd1243dSDimitry Andric #include "llvm/IR/Module.h"
19bdd1243dSDimitry Andric #include "llvm/Support/Debug.h"
20bdd1243dSDimitry Andric #include "llvm/Support/Format.h"
21bdd1243dSDimitry Andric 
22bdd1243dSDimitry Andric using namespace llvm;
23bdd1243dSDimitry Andric using namespace llvm::dxil;
24bdd1243dSDimitry Andric using namespace llvm::hlsl;
25bdd1243dSDimitry Andric 
26bdd1243dSDimitry Andric template <typename T> void ResourceTable<T>::collect(Module &M) {
27bdd1243dSDimitry Andric   NamedMDNode *Entry = M.getNamedMetadata(MDName);
28bdd1243dSDimitry Andric   if (!Entry || Entry->getNumOperands() == 0)
29bdd1243dSDimitry Andric     return;
30bdd1243dSDimitry Andric 
31bdd1243dSDimitry Andric   uint32_t Counter = 0;
32bdd1243dSDimitry Andric   for (auto *Res : Entry->operands()) {
33bdd1243dSDimitry Andric     Data.push_back(T(Counter++, FrontendResource(cast<MDNode>(Res))));
34bdd1243dSDimitry Andric   }
35bdd1243dSDimitry Andric }
36bdd1243dSDimitry Andric 
37bdd1243dSDimitry Andric template <> void ResourceTable<ConstantBuffer>::collect(Module &M) {
38bdd1243dSDimitry Andric   NamedMDNode *Entry = M.getNamedMetadata(MDName);
39bdd1243dSDimitry Andric   if (!Entry || Entry->getNumOperands() == 0)
40bdd1243dSDimitry Andric     return;
41bdd1243dSDimitry Andric 
42bdd1243dSDimitry Andric   uint32_t Counter = 0;
43bdd1243dSDimitry Andric   for (auto *Res : Entry->operands()) {
44bdd1243dSDimitry Andric     Data.push_back(
45bdd1243dSDimitry Andric         ConstantBuffer(Counter++, FrontendResource(cast<MDNode>(Res))));
46bdd1243dSDimitry Andric   }
47bdd1243dSDimitry Andric   // FIXME: share CBufferDataLayout with CBuffer load lowering.
48bdd1243dSDimitry Andric   //   See https://github.com/llvm/llvm-project/issues/58381
49bdd1243dSDimitry Andric   CBufferDataLayout CBDL(M.getDataLayout(), /*IsLegacy*/ true);
50bdd1243dSDimitry Andric   for (auto &CB : Data)
51bdd1243dSDimitry Andric     CB.setSize(CBDL);
52bdd1243dSDimitry Andric }
53bdd1243dSDimitry Andric 
54bdd1243dSDimitry Andric void Resources::collect(Module &M) {
55bdd1243dSDimitry Andric   UAVs.collect(M);
56bdd1243dSDimitry Andric   CBuffers.collect(M);
57bdd1243dSDimitry Andric }
58bdd1243dSDimitry Andric 
59bdd1243dSDimitry Andric ResourceBase::ResourceBase(uint32_t I, FrontendResource R)
60bdd1243dSDimitry Andric     : ID(I), GV(R.getGlobalVariable()), Name(""), Space(R.getSpace()),
61bdd1243dSDimitry Andric       LowerBound(R.getResourceIndex()), RangeSize(1) {
62bdd1243dSDimitry Andric   if (auto *ArrTy = dyn_cast<ArrayType>(GV->getValueType()))
63bdd1243dSDimitry Andric     RangeSize = ArrTy->getNumElements();
64bdd1243dSDimitry Andric }
65bdd1243dSDimitry Andric 
66*cb14a3feSDimitry Andric StringRef ResourceBase::getElementTypeName(ElementType ElTy) {
67*cb14a3feSDimitry Andric   switch (ElTy) {
68*cb14a3feSDimitry Andric   case ElementType::Invalid:
69bdd1243dSDimitry Andric     return "invalid";
70*cb14a3feSDimitry Andric   case ElementType::I1:
71bdd1243dSDimitry Andric     return "i1";
72*cb14a3feSDimitry Andric   case ElementType::I16:
73bdd1243dSDimitry Andric     return "i16";
74*cb14a3feSDimitry Andric   case ElementType::U16:
75bdd1243dSDimitry Andric     return "u16";
76*cb14a3feSDimitry Andric   case ElementType::I32:
77bdd1243dSDimitry Andric     return "i32";
78*cb14a3feSDimitry Andric   case ElementType::U32:
79bdd1243dSDimitry Andric     return "u32";
80*cb14a3feSDimitry Andric   case ElementType::I64:
81bdd1243dSDimitry Andric     return "i64";
82*cb14a3feSDimitry Andric   case ElementType::U64:
83bdd1243dSDimitry Andric     return "u64";
84*cb14a3feSDimitry Andric   case ElementType::F16:
85bdd1243dSDimitry Andric     return "f16";
86*cb14a3feSDimitry Andric   case ElementType::F32:
87bdd1243dSDimitry Andric     return "f32";
88*cb14a3feSDimitry Andric   case ElementType::F64:
89bdd1243dSDimitry Andric     return "f64";
90*cb14a3feSDimitry Andric   case ElementType::SNormF16:
91bdd1243dSDimitry Andric     return "snorm_f16";
92*cb14a3feSDimitry Andric   case ElementType::UNormF16:
93bdd1243dSDimitry Andric     return "unorm_f16";
94*cb14a3feSDimitry Andric   case ElementType::SNormF32:
95bdd1243dSDimitry Andric     return "snorm_f32";
96*cb14a3feSDimitry Andric   case ElementType::UNormF32:
97bdd1243dSDimitry Andric     return "unorm_f32";
98*cb14a3feSDimitry Andric   case ElementType::SNormF64:
99bdd1243dSDimitry Andric     return "snorm_f64";
100*cb14a3feSDimitry Andric   case ElementType::UNormF64:
101bdd1243dSDimitry Andric     return "unorm_f64";
102*cb14a3feSDimitry Andric   case ElementType::PackedS8x32:
103bdd1243dSDimitry Andric     return "p32i8";
104*cb14a3feSDimitry Andric   case ElementType::PackedU8x32:
105bdd1243dSDimitry Andric     return "p32u8";
106bdd1243dSDimitry Andric   }
107*cb14a3feSDimitry Andric   llvm_unreachable("All ElementType enums are handled in switch");
108bdd1243dSDimitry Andric }
109bdd1243dSDimitry Andric 
110*cb14a3feSDimitry Andric void ResourceBase::printElementType(Kinds Kind, ElementType ElTy,
111bdd1243dSDimitry Andric                                     unsigned Alignment, raw_ostream &OS) {
112bdd1243dSDimitry Andric   switch (Kind) {
113bdd1243dSDimitry Andric   default:
114bdd1243dSDimitry Andric     // TODO: add vector size.
115*cb14a3feSDimitry Andric     OS << right_justify(getElementTypeName(ElTy), Alignment);
116bdd1243dSDimitry Andric     break;
117bdd1243dSDimitry Andric   case Kinds::RawBuffer:
118bdd1243dSDimitry Andric     OS << right_justify("byte", Alignment);
119bdd1243dSDimitry Andric     break;
120bdd1243dSDimitry Andric   case Kinds::StructuredBuffer:
121bdd1243dSDimitry Andric     OS << right_justify("struct", Alignment);
122bdd1243dSDimitry Andric     break;
123bdd1243dSDimitry Andric   case Kinds::CBuffer:
124bdd1243dSDimitry Andric   case Kinds::Sampler:
125bdd1243dSDimitry Andric     OS << right_justify("NA", Alignment);
126bdd1243dSDimitry Andric     break;
127bdd1243dSDimitry Andric   case Kinds::Invalid:
128bdd1243dSDimitry Andric   case Kinds::NumEntries:
129bdd1243dSDimitry Andric     break;
130bdd1243dSDimitry Andric   }
131bdd1243dSDimitry Andric }
132bdd1243dSDimitry Andric 
133bdd1243dSDimitry Andric StringRef ResourceBase::getKindName(Kinds Kind) {
134bdd1243dSDimitry Andric   switch (Kind) {
135bdd1243dSDimitry Andric   case Kinds::NumEntries:
136bdd1243dSDimitry Andric   case Kinds::Invalid:
137bdd1243dSDimitry Andric     return "invalid";
138bdd1243dSDimitry Andric   case Kinds::Texture1D:
139bdd1243dSDimitry Andric     return "1d";
140bdd1243dSDimitry Andric   case Kinds::Texture2D:
141bdd1243dSDimitry Andric     return "2d";
142bdd1243dSDimitry Andric   case Kinds::Texture2DMS:
143bdd1243dSDimitry Andric     return "2dMS";
144bdd1243dSDimitry Andric   case Kinds::Texture3D:
145bdd1243dSDimitry Andric     return "3d";
146bdd1243dSDimitry Andric   case Kinds::TextureCube:
147bdd1243dSDimitry Andric     return "cube";
148bdd1243dSDimitry Andric   case Kinds::Texture1DArray:
149bdd1243dSDimitry Andric     return "1darray";
150bdd1243dSDimitry Andric   case Kinds::Texture2DArray:
151bdd1243dSDimitry Andric     return "2darray";
152bdd1243dSDimitry Andric   case Kinds::Texture2DMSArray:
153bdd1243dSDimitry Andric     return "2darrayMS";
154bdd1243dSDimitry Andric   case Kinds::TextureCubeArray:
155bdd1243dSDimitry Andric     return "cubearray";
156bdd1243dSDimitry Andric   case Kinds::TypedBuffer:
157bdd1243dSDimitry Andric     return "buf";
158bdd1243dSDimitry Andric   case Kinds::RawBuffer:
159bdd1243dSDimitry Andric     return "rawbuf";
160bdd1243dSDimitry Andric   case Kinds::StructuredBuffer:
161bdd1243dSDimitry Andric     return "structbuf";
162bdd1243dSDimitry Andric   case Kinds::CBuffer:
163bdd1243dSDimitry Andric     return "cbuffer";
164bdd1243dSDimitry Andric   case Kinds::Sampler:
165bdd1243dSDimitry Andric     return "sampler";
166bdd1243dSDimitry Andric   case Kinds::TBuffer:
167bdd1243dSDimitry Andric     return "tbuffer";
168bdd1243dSDimitry Andric   case Kinds::RTAccelerationStructure:
169bdd1243dSDimitry Andric     return "ras";
170bdd1243dSDimitry Andric   case Kinds::FeedbackTexture2D:
171bdd1243dSDimitry Andric     return "fbtex2d";
172bdd1243dSDimitry Andric   case Kinds::FeedbackTexture2DArray:
173bdd1243dSDimitry Andric     return "fbtex2darray";
174bdd1243dSDimitry Andric   }
17506c3fb27SDimitry Andric   llvm_unreachable("All Kinds enums are handled in switch");
176bdd1243dSDimitry Andric }
177bdd1243dSDimitry Andric 
178bdd1243dSDimitry Andric void ResourceBase::printKind(Kinds Kind, unsigned Alignment, raw_ostream &OS,
179bdd1243dSDimitry Andric                              bool SRV, bool HasCounter, uint32_t SampleCount) {
180bdd1243dSDimitry Andric   switch (Kind) {
181bdd1243dSDimitry Andric   default:
182bdd1243dSDimitry Andric     OS << right_justify(getKindName(Kind), Alignment);
183bdd1243dSDimitry Andric     break;
184bdd1243dSDimitry Andric 
185bdd1243dSDimitry Andric   case Kinds::RawBuffer:
186bdd1243dSDimitry Andric   case Kinds::StructuredBuffer:
187bdd1243dSDimitry Andric     if (SRV)
188bdd1243dSDimitry Andric       OS << right_justify("r/o", Alignment);
189bdd1243dSDimitry Andric     else {
190bdd1243dSDimitry Andric       if (!HasCounter)
191bdd1243dSDimitry Andric         OS << right_justify("r/w", Alignment);
192bdd1243dSDimitry Andric       else
193bdd1243dSDimitry Andric         OS << right_justify("r/w+cnt", Alignment);
194bdd1243dSDimitry Andric     }
195bdd1243dSDimitry Andric     break;
196bdd1243dSDimitry Andric   case Kinds::TypedBuffer:
197bdd1243dSDimitry Andric     OS << right_justify("buf", Alignment);
198bdd1243dSDimitry Andric     break;
199bdd1243dSDimitry Andric   case Kinds::Texture2DMS:
200bdd1243dSDimitry Andric   case Kinds::Texture2DMSArray: {
201bdd1243dSDimitry Andric     std::string DimName = getKindName(Kind).str();
202bdd1243dSDimitry Andric     if (SampleCount)
203bdd1243dSDimitry Andric       DimName += std::to_string(SampleCount);
204bdd1243dSDimitry Andric     OS << right_justify(DimName, Alignment);
205bdd1243dSDimitry Andric   } break;
206bdd1243dSDimitry Andric   case Kinds::CBuffer:
207bdd1243dSDimitry Andric   case Kinds::Sampler:
208bdd1243dSDimitry Andric     OS << right_justify("NA", Alignment);
209bdd1243dSDimitry Andric     break;
210bdd1243dSDimitry Andric   case Kinds::Invalid:
211bdd1243dSDimitry Andric   case Kinds::NumEntries:
212bdd1243dSDimitry Andric     break;
213bdd1243dSDimitry Andric   }
214bdd1243dSDimitry Andric }
215bdd1243dSDimitry Andric 
216bdd1243dSDimitry Andric void ResourceBase::print(raw_ostream &OS, StringRef IDPrefix,
217bdd1243dSDimitry Andric                          StringRef BindingPrefix) const {
218bdd1243dSDimitry Andric   std::string ResID = IDPrefix.str();
219bdd1243dSDimitry Andric   ResID += std::to_string(ID);
220bdd1243dSDimitry Andric   OS << right_justify(ResID, 8);
221bdd1243dSDimitry Andric 
222bdd1243dSDimitry Andric   std::string Bind = BindingPrefix.str();
223bdd1243dSDimitry Andric   Bind += std::to_string(LowerBound);
224bdd1243dSDimitry Andric   if (Space)
225bdd1243dSDimitry Andric     Bind += ",space" + std::to_string(Space);
226bdd1243dSDimitry Andric 
227bdd1243dSDimitry Andric   OS << right_justify(Bind, 15);
228bdd1243dSDimitry Andric   if (RangeSize != UINT_MAX)
229bdd1243dSDimitry Andric     OS << right_justify(std::to_string(RangeSize), 6) << "\n";
230bdd1243dSDimitry Andric   else
231bdd1243dSDimitry Andric     OS << right_justify("unbounded", 6) << "\n";
232bdd1243dSDimitry Andric }
233bdd1243dSDimitry Andric 
234bdd1243dSDimitry Andric void UAVResource::print(raw_ostream &OS) const {
235bdd1243dSDimitry Andric   OS << "; " << left_justify(Name, 31);
236bdd1243dSDimitry Andric 
237bdd1243dSDimitry Andric   OS << right_justify("UAV", 10);
238bdd1243dSDimitry Andric 
239*cb14a3feSDimitry Andric   printElementType(Shape, ExtProps.ElementType.value_or(ElementType::Invalid),
240*cb14a3feSDimitry Andric                    8, OS);
241bdd1243dSDimitry Andric 
242bdd1243dSDimitry Andric   // FIXME: support SampleCount.
243bdd1243dSDimitry Andric   // See https://github.com/llvm/llvm-project/issues/58175
244bdd1243dSDimitry Andric   printKind(Shape, 12, OS, /*SRV*/ false, HasCounter);
245bdd1243dSDimitry Andric   // Print the binding part.
246bdd1243dSDimitry Andric   ResourceBase::print(OS, "U", "u");
247bdd1243dSDimitry Andric }
248bdd1243dSDimitry Andric 
249bdd1243dSDimitry Andric ConstantBuffer::ConstantBuffer(uint32_t I, hlsl::FrontendResource R)
250bdd1243dSDimitry Andric     : ResourceBase(I, R) {}
251bdd1243dSDimitry Andric 
252bdd1243dSDimitry Andric void ConstantBuffer::setSize(CBufferDataLayout &DL) {
253bdd1243dSDimitry Andric   CBufferSizeInBytes = DL.getTypeAllocSizeInBytes(GV->getValueType());
254bdd1243dSDimitry Andric }
255bdd1243dSDimitry Andric 
256bdd1243dSDimitry Andric void ConstantBuffer::print(raw_ostream &OS) const {
257bdd1243dSDimitry Andric   OS << "; " << left_justify(Name, 31);
258bdd1243dSDimitry Andric 
259bdd1243dSDimitry Andric   OS << right_justify("cbuffer", 10);
260bdd1243dSDimitry Andric 
261*cb14a3feSDimitry Andric   printElementType(Kinds::CBuffer, ElementType::Invalid, 8, OS);
262bdd1243dSDimitry Andric 
263bdd1243dSDimitry Andric   printKind(Kinds::CBuffer, 12, OS, /*SRV*/ false, /*HasCounter*/ false);
264bdd1243dSDimitry Andric   // Print the binding part.
265bdd1243dSDimitry Andric   ResourceBase::print(OS, "CB", "cb");
266bdd1243dSDimitry Andric }
267bdd1243dSDimitry Andric 
268bdd1243dSDimitry Andric template <typename T> void ResourceTable<T>::print(raw_ostream &OS) const {
269bdd1243dSDimitry Andric   for (auto &Res : Data)
270bdd1243dSDimitry Andric     Res.print(OS);
271bdd1243dSDimitry Andric }
272bdd1243dSDimitry Andric 
273bdd1243dSDimitry Andric MDNode *ResourceBase::ExtendedProperties::write(LLVMContext &Ctx) const {
274bdd1243dSDimitry Andric   IRBuilder<> B(Ctx);
275bdd1243dSDimitry Andric   SmallVector<Metadata *> Entries;
276bdd1243dSDimitry Andric   if (ElementType) {
277bdd1243dSDimitry Andric     Entries.emplace_back(
278bdd1243dSDimitry Andric         ConstantAsMetadata::get(B.getInt32(TypedBufferElementType)));
279bdd1243dSDimitry Andric     Entries.emplace_back(ConstantAsMetadata::get(
280bdd1243dSDimitry Andric         B.getInt32(static_cast<uint32_t>(*ElementType))));
281bdd1243dSDimitry Andric   }
282bdd1243dSDimitry Andric   if (Entries.empty())
283bdd1243dSDimitry Andric     return nullptr;
284bdd1243dSDimitry Andric   return MDNode::get(Ctx, Entries);
285bdd1243dSDimitry Andric }
286bdd1243dSDimitry Andric 
287bdd1243dSDimitry Andric void ResourceBase::write(LLVMContext &Ctx,
288bdd1243dSDimitry Andric                          MutableArrayRef<Metadata *> Entries) const {
289bdd1243dSDimitry Andric   IRBuilder<> B(Ctx);
290bdd1243dSDimitry Andric   Entries[0] = ConstantAsMetadata::get(B.getInt32(ID));
291bdd1243dSDimitry Andric   Entries[1] = ConstantAsMetadata::get(GV);
292bdd1243dSDimitry Andric   Entries[2] = MDString::get(Ctx, Name);
293bdd1243dSDimitry Andric   Entries[3] = ConstantAsMetadata::get(B.getInt32(Space));
294bdd1243dSDimitry Andric   Entries[4] = ConstantAsMetadata::get(B.getInt32(LowerBound));
295bdd1243dSDimitry Andric   Entries[5] = ConstantAsMetadata::get(B.getInt32(RangeSize));
296bdd1243dSDimitry Andric }
297bdd1243dSDimitry Andric 
298bdd1243dSDimitry Andric MDNode *UAVResource::write() const {
299bdd1243dSDimitry Andric   auto &Ctx = GV->getContext();
300bdd1243dSDimitry Andric   IRBuilder<> B(Ctx);
301bdd1243dSDimitry Andric   Metadata *Entries[11];
302bdd1243dSDimitry Andric   ResourceBase::write(Ctx, Entries);
303bdd1243dSDimitry Andric   Entries[6] =
304bdd1243dSDimitry Andric       ConstantAsMetadata::get(B.getInt32(static_cast<uint32_t>(Shape)));
305bdd1243dSDimitry Andric   Entries[7] = ConstantAsMetadata::get(B.getInt1(GloballyCoherent));
306bdd1243dSDimitry Andric   Entries[8] = ConstantAsMetadata::get(B.getInt1(HasCounter));
307bdd1243dSDimitry Andric   Entries[9] = ConstantAsMetadata::get(B.getInt1(IsROV));
308bdd1243dSDimitry Andric   Entries[10] = ExtProps.write(Ctx);
309bdd1243dSDimitry Andric   return MDNode::get(Ctx, Entries);
310bdd1243dSDimitry Andric }
311bdd1243dSDimitry Andric 
312bdd1243dSDimitry Andric MDNode *ConstantBuffer::write() const {
313bdd1243dSDimitry Andric   auto &Ctx = GV->getContext();
314bdd1243dSDimitry Andric   IRBuilder<> B(Ctx);
315bdd1243dSDimitry Andric   Metadata *Entries[7];
316bdd1243dSDimitry Andric   ResourceBase::write(Ctx, Entries);
317bdd1243dSDimitry Andric 
318bdd1243dSDimitry Andric   Entries[6] = ConstantAsMetadata::get(B.getInt32(CBufferSizeInBytes));
319bdd1243dSDimitry Andric   return MDNode::get(Ctx, Entries);
320bdd1243dSDimitry Andric }
321bdd1243dSDimitry Andric 
322bdd1243dSDimitry Andric template <typename T> MDNode *ResourceTable<T>::write(Module &M) const {
323bdd1243dSDimitry Andric   if (Data.empty())
324bdd1243dSDimitry Andric     return nullptr;
325bdd1243dSDimitry Andric   SmallVector<Metadata *> MDs;
326bdd1243dSDimitry Andric   for (auto &Res : Data)
327bdd1243dSDimitry Andric     MDs.emplace_back(Res.write());
328bdd1243dSDimitry Andric 
329bdd1243dSDimitry Andric   NamedMDNode *Entry = M.getNamedMetadata(MDName);
330bdd1243dSDimitry Andric   if (Entry)
331bdd1243dSDimitry Andric     Entry->eraseFromParent();
332bdd1243dSDimitry Andric 
333bdd1243dSDimitry Andric   return MDNode::get(M.getContext(), MDs);
334bdd1243dSDimitry Andric }
335bdd1243dSDimitry Andric 
336bdd1243dSDimitry Andric void Resources::write(Module &M) const {
337bdd1243dSDimitry Andric   Metadata *ResourceMDs[4] = {nullptr, nullptr, nullptr, nullptr};
338bdd1243dSDimitry Andric 
339bdd1243dSDimitry Andric   ResourceMDs[1] = UAVs.write(M);
340bdd1243dSDimitry Andric 
341bdd1243dSDimitry Andric   ResourceMDs[2] = CBuffers.write(M);
342bdd1243dSDimitry Andric 
343bdd1243dSDimitry Andric   bool HasResource = ResourceMDs[0] != nullptr || ResourceMDs[1] != nullptr ||
344bdd1243dSDimitry Andric                      ResourceMDs[2] != nullptr || ResourceMDs[3] != nullptr;
345bdd1243dSDimitry Andric 
346bdd1243dSDimitry Andric   if (HasResource) {
347bdd1243dSDimitry Andric     NamedMDNode *DXResMD = M.getOrInsertNamedMetadata("dx.resources");
348bdd1243dSDimitry Andric     DXResMD->addOperand(MDNode::get(M.getContext(), ResourceMDs));
349bdd1243dSDimitry Andric   }
350bdd1243dSDimitry Andric 
351bdd1243dSDimitry Andric   NamedMDNode *Entry = M.getNamedMetadata("hlsl.uavs");
352bdd1243dSDimitry Andric   if (Entry)
353bdd1243dSDimitry Andric     Entry->eraseFromParent();
354bdd1243dSDimitry Andric }
355bdd1243dSDimitry Andric 
356bdd1243dSDimitry Andric void Resources::print(raw_ostream &O) const {
357bdd1243dSDimitry Andric   O << ";\n"
358bdd1243dSDimitry Andric     << "; Resource Bindings:\n"
359bdd1243dSDimitry Andric     << ";\n"
360bdd1243dSDimitry Andric     << "; Name                                 Type  Format         Dim      "
361bdd1243dSDimitry Andric        "ID      HLSL Bind  Count\n"
362bdd1243dSDimitry Andric     << "; ------------------------------ ---------- ------- ----------- "
363bdd1243dSDimitry Andric        "------- -------------- ------\n";
364bdd1243dSDimitry Andric 
365bdd1243dSDimitry Andric   CBuffers.print(O);
366bdd1243dSDimitry Andric   UAVs.print(O);
367bdd1243dSDimitry Andric }
368bdd1243dSDimitry Andric 
369bdd1243dSDimitry Andric void Resources::dump() const { print(dbgs()); }
370