LLVM 22.0.0git
DXILResource.cpp
Go to the documentation of this file.
1//===- DXILResource.cpp - Representations of DXIL resources ---------------===//
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
10#include "llvm/ADT/APInt.h"
11#include "llvm/ADT/STLExtras.h"
14#include "llvm/IR/Constants.h"
18#include "llvm/IR/Intrinsics.h"
19#include "llvm/IR/IntrinsicsDirectX.h"
20#include "llvm/IR/Metadata.h"
21#include "llvm/IR/Module.h"
25#include <cstdint>
26
27#define DEBUG_TYPE "dxil-resource"
28
29using namespace llvm;
30using namespace dxil;
31
33 switch (RK) {
34 case ResourceKind::Texture1D:
35 return "Texture1D";
36 case ResourceKind::Texture2D:
37 return "Texture2D";
38 case ResourceKind::Texture2DMS:
39 return "Texture2DMS";
40 case ResourceKind::Texture3D:
41 return "Texture3D";
42 case ResourceKind::TextureCube:
43 return "TextureCube";
44 case ResourceKind::Texture1DArray:
45 return "Texture1DArray";
46 case ResourceKind::Texture2DArray:
47 return "Texture2DArray";
48 case ResourceKind::Texture2DMSArray:
49 return "Texture2DMSArray";
50 case ResourceKind::TextureCubeArray:
51 return "TextureCubeArray";
52 case ResourceKind::TypedBuffer:
53 return "Buffer";
54 case ResourceKind::RawBuffer:
55 return "RawBuffer";
56 case ResourceKind::StructuredBuffer:
57 return "StructuredBuffer";
58 case ResourceKind::CBuffer:
59 return "CBuffer";
60 case ResourceKind::Sampler:
61 return "Sampler";
62 case ResourceKind::TBuffer:
63 return "TBuffer";
64 case ResourceKind::RTAccelerationStructure:
65 return "RTAccelerationStructure";
66 case ResourceKind::FeedbackTexture2D:
67 return "FeedbackTexture2D";
68 case ResourceKind::FeedbackTexture2DArray:
69 return "FeedbackTexture2DArray";
70 case ResourceKind::NumEntries:
71 case ResourceKind::Invalid:
72 return "<invalid>";
73 }
74 llvm_unreachable("Unhandled ResourceKind");
75}
76
78 switch (ET) {
79 case ElementType::I1:
80 return "i1";
81 case ElementType::I16:
82 return "i16";
83 case ElementType::U16:
84 return "u16";
85 case ElementType::I32:
86 return "i32";
87 case ElementType::U32:
88 return "u32";
89 case ElementType::I64:
90 return "i64";
91 case ElementType::U64:
92 return "u64";
93 case ElementType::F16:
94 return "f16";
95 case ElementType::F32:
96 return "f32";
97 case ElementType::F64:
98 return "f64";
99 case ElementType::SNormF16:
100 return "snorm_f16";
101 case ElementType::UNormF16:
102 return "unorm_f16";
103 case ElementType::SNormF32:
104 return "snorm_f32";
105 case ElementType::UNormF32:
106 return "unorm_f32";
107 case ElementType::SNormF64:
108 return "snorm_f64";
109 case ElementType::UNormF64:
110 return "unorm_f64";
111 case ElementType::PackedS8x32:
112 return "p32i8";
113 case ElementType::PackedU8x32:
114 return "p32u8";
115 case ElementType::Invalid:
116 return "<invalid>";
117 }
118 llvm_unreachable("Unhandled ElementType");
119}
120
122 switch (ET) {
123 case ElementType::I1:
124 return "bool";
125 case ElementType::I16:
126 return "int16_t";
127 case ElementType::U16:
128 return "uint16_t";
129 case ElementType::I32:
130 return "int32_t";
131 case ElementType::U32:
132 return "uint32_t";
133 case ElementType::I64:
134 return "int64_t";
135 case ElementType::U64:
136 return "uint32_t";
137 case ElementType::F16:
138 case ElementType::SNormF16:
139 case ElementType::UNormF16:
140 return "half";
141 case ElementType::F32:
142 case ElementType::SNormF32:
143 case ElementType::UNormF32:
144 return "float";
145 case ElementType::F64:
146 case ElementType::SNormF64:
147 case ElementType::UNormF64:
148 return "double";
149 case ElementType::PackedS8x32:
150 return "int8_t4_packed";
151 case ElementType::PackedU8x32:
152 return "uint8_t4_packed";
153 case ElementType::Invalid:
154 return "<invalid>";
155 }
156 llvm_unreachable("Unhandled ElementType");
157}
158
160 switch (ST) {
161 case SamplerType::Default:
162 return "Default";
163 case SamplerType::Comparison:
164 return "Comparison";
165 case SamplerType::Mono:
166 return "Mono";
167 }
168 llvm_unreachable("Unhandled SamplerType");
169}
170
172 switch (SFT) {
173 case SamplerFeedbackType::MinMip:
174 return "MinMip";
175 case SamplerFeedbackType::MipRegionUsed:
176 return "MipRegionUsed";
177 }
178 llvm_unreachable("Unhandled SamplerFeedbackType");
179}
180
181static dxil::ElementType toDXILElementType(Type *Ty, bool IsSigned) {
182 // TODO: Handle unorm, snorm, and packed.
183 Ty = Ty->getScalarType();
184
185 if (Ty->isIntegerTy()) {
186 switch (Ty->getIntegerBitWidth()) {
187 case 16:
188 return IsSigned ? ElementType::I16 : ElementType::U16;
189 case 32:
190 return IsSigned ? ElementType::I32 : ElementType::U32;
191 case 64:
192 return IsSigned ? ElementType::I64 : ElementType::U64;
193 case 1:
194 default:
195 return ElementType::Invalid;
196 }
197 } else if (Ty->isFloatTy()) {
198 return ElementType::F32;
199 } else if (Ty->isDoubleTy()) {
200 return ElementType::F64;
201 } else if (Ty->isHalfTy()) {
202 return ElementType::F16;
203 }
204
205 return ElementType::Invalid;
206}
207
215
217 const dxil::ResourceClass RC_,
218 const dxil::ResourceKind Kind_)
219 : HandleTy(HandleTy) {
220 // If we're provided a resource class and kind, trust them.
221 if (Kind_ != dxil::ResourceKind::Invalid) {
222 RC = RC_;
223 Kind = Kind_;
224 return;
225 }
226
227 if (auto *Ty = dyn_cast<RawBufferExtType>(HandleTy)) {
228 RC = Ty->isWriteable() ? ResourceClass::UAV : ResourceClass::SRV;
229 Kind = Ty->isStructured() ? ResourceKind::StructuredBuffer
231 } else if (auto *Ty = dyn_cast<TypedBufferExtType>(HandleTy)) {
232 RC = Ty->isWriteable() ? ResourceClass::UAV : ResourceClass::SRV;
234 } else if (auto *Ty = dyn_cast<TextureExtType>(HandleTy)) {
235 RC = Ty->isWriteable() ? ResourceClass::UAV : ResourceClass::SRV;
236 Kind = Ty->getDimension();
237 } else if (auto *Ty = dyn_cast<MSTextureExtType>(HandleTy)) {
238 RC = Ty->isWriteable() ? ResourceClass::UAV : ResourceClass::SRV;
239 Kind = Ty->getDimension();
240 } else if (auto *Ty = dyn_cast<FeedbackTextureExtType>(HandleTy)) {
242 Kind = Ty->getDimension();
243 } else if (isa<CBufferExtType>(HandleTy)) {
246 } else if (isa<SamplerExtType>(HandleTy)) {
249 } else
250 llvm_unreachable("Unknown handle type");
251}
252
254 bool IsWriteable, bool IsROV,
255 Type *ContainedType = nullptr,
256 bool IsSigned = true) {
257 raw_svector_ostream DestStream(Dest);
258 if (IsWriteable)
259 DestStream << (IsROV ? "RasterizerOrdered" : "RW");
260 DestStream << Name;
261
262 if (!ContainedType)
263 return;
264
265 SmallVector<uint64_t> ArrayDimensions;
266 while (ArrayType *AT = dyn_cast<ArrayType>(ContainedType)) {
267 ArrayDimensions.push_back(AT->getNumElements());
268 ContainedType = AT->getElementType();
269 }
270
271 StringRef ElementName;
272 ElementType ET = toDXILElementType(ContainedType, IsSigned);
273 if (ET != ElementType::Invalid) {
274 ElementName = getElementTypeNameForTemplate(ET);
275 } else {
276 assert(isa<StructType>(ContainedType) &&
277 "invalid element type for raw buffer");
278 StructType *ST = cast<StructType>(ContainedType);
279 if (!ST->hasName())
280 return;
281 ElementName = ST->getStructName();
282 }
283
284 DestStream << "<" << ElementName;
285 if (const FixedVectorType *VTy = dyn_cast<FixedVectorType>(ContainedType))
286 DestStream << VTy->getNumElements();
287 for (uint64_t Dim : ArrayDimensions)
288 DestStream << "[" << Dim << "]";
289 DestStream << ">";
290}
291
293 StructType *Ty = StructType::getTypeByName(ElemType->getContext(), Name);
294 if (Ty && Ty->getNumElements() == 1 && Ty->getElementType(0) == ElemType)
295 return Ty;
296 return StructType::create(ElemType, Name);
297}
298
300 // Recursively remove padding from structures.
301 if (auto *ST = dyn_cast<StructType>(Ty)) {
302 LLVMContext &Ctx = Ty->getContext();
303 SmallVector<Type *> ElementTypes;
304 ElementTypes.reserve(ST->getNumElements());
305 for (Type *ElTy : ST->elements()) {
306 if (isa<PaddingExtType>(ElTy))
307 continue;
308 ElementTypes.push_back(getTypeWithoutPadding(ElTy));
309 }
310
311 // Handle explicitly padded cbuffer arrays like { [ n x paddedty ], ty }
312 if (ElementTypes.size() == 2)
313 if (auto *AT = dyn_cast<ArrayType>(ElementTypes[0]))
314 if (ElementTypes[1] == AT->getElementType())
315 return ArrayType::get(ElementTypes[1], AT->getNumElements() + 1);
316
317 // If we only have a single element, don't wrap it in a struct.
318 if (ElementTypes.size() == 1)
319 return ElementTypes[0];
320
321 return StructType::get(Ctx, ElementTypes, /*IsPacked=*/false);
322 }
323 // Arrays just need to have their element type adjusted.
324 if (auto *AT = dyn_cast<ArrayType>(Ty))
325 return ArrayType::get(getTypeWithoutPadding(AT->getElementType()),
326 AT->getNumElements());
327 // Anything else should be good as is.
328 return Ty;
329}
330
332 SmallString<64> TypeName;
333
334 switch (Kind) {
342 auto *RTy = cast<TextureExtType>(HandleTy);
343 formatTypeName(TypeName, getResourceKindName(Kind), RTy->isWriteable(),
344 RTy->isROV(), RTy->getResourceType(), RTy->isSigned());
345 return getOrCreateElementStruct(RTy->getResourceType(), TypeName);
346 }
349 auto *RTy = cast<MSTextureExtType>(HandleTy);
350 formatTypeName(TypeName, getResourceKindName(Kind), RTy->isWriteable(),
351 /*IsROV=*/false, RTy->getResourceType(), RTy->isSigned());
352 return getOrCreateElementStruct(RTy->getResourceType(), TypeName);
353 }
355 auto *RTy = cast<TypedBufferExtType>(HandleTy);
356 formatTypeName(TypeName, getResourceKindName(Kind), RTy->isWriteable(),
357 RTy->isROV(), RTy->getResourceType(), RTy->isSigned());
358 return getOrCreateElementStruct(RTy->getResourceType(), TypeName);
359 }
361 auto *RTy = cast<RawBufferExtType>(HandleTy);
362 formatTypeName(TypeName, "ByteAddressBuffer", RTy->isWriteable(),
363 RTy->isROV());
364 return getOrCreateElementStruct(Type::getInt32Ty(HandleTy->getContext()),
365 TypeName);
366 }
368 auto *RTy = cast<RawBufferExtType>(HandleTy);
369 Type *Ty = RTy->getResourceType();
370 formatTypeName(TypeName, "StructuredBuffer", RTy->isWriteable(),
371 RTy->isROV(), RTy->getResourceType(), true);
372 return getOrCreateElementStruct(Ty, TypeName);
373 }
376 auto *RTy = cast<FeedbackTextureExtType>(HandleTy);
377 TypeName = formatv("{0}<{1}>", getResourceKindName(Kind),
378 llvm::to_underlying(RTy->getFeedbackType()));
379 return getOrCreateElementStruct(Type::getInt32Ty(HandleTy->getContext()),
380 TypeName);
381 }
383 auto *RTy = cast<CBufferExtType>(HandleTy);
385 if (!CBufferName.empty()) {
386 Name.append(".");
387 Name.append(CBufferName);
388 }
389
390 // TODO: Remove this when we update the frontend to use explicit padding.
391 if (LayoutExtType *LayoutType =
392 dyn_cast<LayoutExtType>(RTy->getResourceType())) {
393 StructType *Ty = cast<StructType>(LayoutType->getWrappedType());
394 return StructType::create(Ty->elements(), Name);
395 }
396
398 getTypeWithoutPadding(RTy->getResourceType()), Name);
399 }
401 auto *RTy = cast<SamplerExtType>(HandleTy);
402 TypeName = formatv("SamplerState<{0}>",
403 llvm::to_underlying(RTy->getSamplerType()));
404 return getOrCreateElementStruct(Type::getInt32Ty(HandleTy->getContext()),
405 TypeName);
406 }
409 llvm_unreachable("Unhandled resource kind");
412 llvm_unreachable("Invalid resource kind");
413 }
414 llvm_unreachable("Unhandled ResourceKind enum");
415}
416
417bool ResourceTypeInfo::isUAV() const { return RC == ResourceClass::UAV; }
418
420 return RC == ResourceClass::CBuffer;
421}
422
424 return RC == ResourceClass::Sampler;
425}
426
428 return Kind == ResourceKind::StructuredBuffer;
429}
430
459
464
469
470static bool isROV(dxil::ResourceKind Kind, TargetExtType *Ty) {
471 switch (Kind) {
479 return cast<TextureExtType>(Ty)->isROV();
481 return cast<TypedBufferExtType>(Ty)->isROV();
484 return cast<RawBufferExtType>(Ty)->isROV();
489 return false;
496 llvm_unreachable("Resource cannot be ROV");
497 }
498 llvm_unreachable("Unhandled ResourceKind enum");
499}
500
502 assert(isUAV() && "Not a UAV");
503 return {isROV(Kind, HandleTy)};
504}
505
507 assert(isCBuffer() && "Not a CBuffer");
508
509 Type *ElTy = cast<CBufferExtType>(HandleTy)->getResourceType();
510
511 // TODO: Remove this when we update the frontend to use explicit padding.
512 if (auto *LayoutTy = dyn_cast<LayoutExtType>(ElTy))
513 return LayoutTy->getSize();
514
515 return DL.getTypeAllocSize(ElTy);
516}
517
519 assert(isSampler() && "Not a Sampler");
520 return cast<SamplerExtType>(HandleTy)->getSamplerType();
521}
522
525 assert(isStruct() && "Not a Struct");
526
527 Type *ElTy = cast<RawBufferExtType>(HandleTy)->getResourceType();
528
529 uint32_t Stride = DL.getTypeAllocSize(ElTy);
530 MaybeAlign Alignment;
531 if (auto *STy = dyn_cast<StructType>(ElTy))
532 Alignment = DL.getStructLayout(STy)->getAlignment();
533 uint32_t AlignLog2 = Alignment ? Log2(*Alignment) : 0;
534 return {Stride, AlignLog2};
535}
536
537static std::pair<Type *, bool> getTypedElementType(dxil::ResourceKind Kind,
538 TargetExtType *Ty) {
539 switch (Kind) {
547 auto *RTy = cast<TextureExtType>(Ty);
548 return {RTy->getResourceType(), RTy->isSigned()};
549 }
552 auto *RTy = cast<MSTextureExtType>(Ty);
553 return {RTy->getResourceType(), RTy->isSigned()};
554 }
556 auto *RTy = cast<TypedBufferExtType>(Ty);
557 return {RTy->getResourceType(), RTy->isSigned()};
558 }
569 llvm_unreachable("Resource is not typed");
570 }
571 llvm_unreachable("Unhandled ResourceKind enum");
572}
573
575 assert(isTyped() && "Not typed");
576
577 auto [ElTy, IsSigned] = getTypedElementType(Kind, HandleTy);
578 dxil::ElementType ET = toDXILElementType(ElTy, IsSigned);
579 dxil::ElementType DXILStorageTy = toDXILStorageType(ET);
580 uint32_t Count = 1;
581 if (auto *VTy = dyn_cast<FixedVectorType>(ElTy))
582 Count = VTy->getNumElements();
583 return {ET, DXILStorageTy, Count};
584}
585
587 assert(isFeedback() && "Not Feedback");
588 return cast<FeedbackTextureExtType>(HandleTy)->getFeedbackType();
589}
591 assert(isMultiSample() && "Not MultiSampled");
592 return cast<MSTextureExtType>(HandleTy)->getSampleCount();
593}
594
596 return HandleTy == RHS.HandleTy;
597}
598
600 // An empty datalayout is sufficient for sorting purposes.
601 DataLayout DummyDL;
602 if (std::tie(RC, Kind) < std::tie(RHS.RC, RHS.Kind))
603 return true;
604 if (isCBuffer() && RHS.isCBuffer() &&
605 getCBufferSize(DummyDL) < RHS.getCBufferSize(DummyDL))
606 return true;
607 if (isSampler() && RHS.isSampler() && getSamplerType() < RHS.getSamplerType())
608 return true;
609 if (isUAV() && RHS.isUAV() && getUAV() < RHS.getUAV())
610 return true;
611 if (isStruct() && RHS.isStruct() &&
612 getStruct(DummyDL) < RHS.getStruct(DummyDL))
613 return true;
614 if (isFeedback() && RHS.isFeedback() &&
615 getFeedbackType() < RHS.getFeedbackType())
616 return true;
617 if (isTyped() && RHS.isTyped() && getTyped() < RHS.getTyped())
618 return true;
619 if (isMultiSample() && RHS.isMultiSample() &&
620 getMultiSampleCount() < RHS.getMultiSampleCount())
621 return true;
622 return false;
623}
624
626 OS << " Class: " << getResourceClassName(RC) << "\n"
627 << " Kind: " << getResourceKindName(Kind) << "\n";
628
629 if (isCBuffer()) {
630 OS << " CBuffer size: " << getCBufferSize(DL) << "\n";
631 } else if (isSampler()) {
632 OS << " Sampler Type: " << getSamplerTypeName(getSamplerType()) << "\n";
633 } else {
634 if (isUAV()) {
635 UAVInfo UAVFlags = getUAV();
636 OS << " IsROV: " << UAVFlags.IsROV << "\n";
637 }
638 if (isMultiSample())
639 OS << " Sample Count: " << getMultiSampleCount() << "\n";
640
641 if (isStruct()) {
642 StructInfo Struct = getStruct(DL);
643 OS << " Buffer Stride: " << Struct.Stride << "\n";
644 OS << " Alignment: " << Struct.AlignLog2 << "\n";
645 } else if (isTyped()) {
646 TypedInfo Typed = getTyped();
647 OS << " Element Type: " << getElementTypeName(Typed.ElementTy);
648 if (Typed.ElementTy != Typed.DXILStorageTy)
649 OS << " (stored as " << getElementTypeName(Typed.DXILStorageTy) << ")";
650 OS << "\n"
651 << " Element Count: " << Typed.ElementCount << "\n";
652 } else if (isFeedback())
653 OS << " Feedback Type: " << getSamplerFeedbackTypeName(getFeedbackType())
654 << "\n";
655 }
656}
657
659 assert(!Symbol && "Symbol has already been created");
660 Type *ResTy = Ty;
661 int64_t Size = Binding.Size;
662 if (Size != 1)
663 // unbounded arrays are represented as zero-sized arrays in LLVM IR
664 ResTy = ArrayType::get(Ty, Size == ~0u ? 0 : Size);
665 Symbol = new GlobalVariable(M, ResTy, /*isConstant=*/true,
667 /*Initializer=*/nullptr, Name);
668 return Symbol;
669}
670
672 dxil::ResourceTypeInfo &RTI) const {
673 LLVMContext &Ctx = M.getContext();
674 const DataLayout &DL = M.getDataLayout();
675
677
678 Type *I32Ty = Type::getInt32Ty(Ctx);
679 Type *I1Ty = Type::getInt1Ty(Ctx);
680 auto getIntMD = [&I32Ty](uint32_t V) {
682 Constant::getIntegerValue(I32Ty, APInt(32, V)));
683 };
684 auto getBoolMD = [&I1Ty](uint32_t V) {
686 Constant::getIntegerValue(I1Ty, APInt(1, V)));
687 };
688
689 MDVals.push_back(getIntMD(Binding.RecordID));
690 assert(Symbol && "Cannot yet create useful resource metadata without symbol");
691 MDVals.push_back(ValueAsMetadata::get(Symbol));
692 MDVals.push_back(MDString::get(Ctx, Name));
693 MDVals.push_back(getIntMD(Binding.Space));
694 MDVals.push_back(getIntMD(Binding.LowerBound));
695 MDVals.push_back(getIntMD(Binding.Size));
696
697 if (RTI.isCBuffer()) {
698 MDVals.push_back(getIntMD(RTI.getCBufferSize(DL)));
699 MDVals.push_back(nullptr);
700 } else if (RTI.isSampler()) {
701 MDVals.push_back(getIntMD(llvm::to_underlying(RTI.getSamplerType())));
702 MDVals.push_back(nullptr);
703 } else {
704 MDVals.push_back(getIntMD(llvm::to_underlying(RTI.getResourceKind())));
705
706 if (RTI.isUAV()) {
707 ResourceTypeInfo::UAVInfo UAVFlags = RTI.getUAV();
708 MDVals.push_back(getBoolMD(GloballyCoherent));
709 MDVals.push_back(getBoolMD(hasCounter()));
710 MDVals.push_back(getBoolMD(UAVFlags.IsROV));
711 } else {
712 // All SRVs include sample count in the metadata, but it's only meaningful
713 // for multi-sampled textured. Also, UAVs can be multisampled in SM6.7+,
714 // but this just isn't reflected in the metadata at all.
715 uint32_t SampleCount =
716 RTI.isMultiSample() ? RTI.getMultiSampleCount() : 0;
717 MDVals.push_back(getIntMD(SampleCount));
718 }
719
720 // Further properties are attached to a metadata list of tag-value pairs.
722 if (RTI.isStruct()) {
723 Tags.push_back(
725 Tags.push_back(getIntMD(RTI.getStruct(DL).Stride));
726 } else if (RTI.isTyped()) {
728 Tags.push_back(
730 } else if (RTI.isFeedback()) {
731 Tags.push_back(
733 Tags.push_back(getIntMD(llvm::to_underlying(RTI.getFeedbackType())));
734 }
735 MDVals.push_back(Tags.empty() ? nullptr : MDNode::get(Ctx, Tags));
736 }
737
738 return MDNode::get(Ctx, MDVals);
739}
740
741std::pair<uint32_t, uint32_t>
743 const DataLayout &DL = M.getDataLayout();
744
746 uint32_t AlignLog2 = RTI.isStruct() ? RTI.getStruct(DL).AlignLog2 : 0;
747 bool IsUAV = RTI.isUAV();
749 IsUAV ? RTI.getUAV() : ResourceTypeInfo::UAVInfo{};
750 bool IsROV = IsUAV && UAVFlags.IsROV;
751 bool IsGloballyCoherent = IsUAV && GloballyCoherent;
752 uint8_t SamplerCmpOrHasCounter = 0;
753 if (IsUAV)
754 SamplerCmpOrHasCounter = hasCounter();
755 else if (RTI.isSampler())
756 SamplerCmpOrHasCounter = RTI.getSamplerType() == SamplerType::Comparison;
757
758 // TODO: Document this format. Currently the only reference is the
759 // implementation of dxc's DxilResourceProperties struct.
760 uint32_t Word0 = 0;
761 Word0 |= ResourceKind & 0xFF;
762 Word0 |= (AlignLog2 & 0xF) << 8;
763 Word0 |= (IsUAV & 1) << 12;
764 Word0 |= (IsROV & 1) << 13;
765 Word0 |= (IsGloballyCoherent & 1) << 14;
766 Word0 |= (SamplerCmpOrHasCounter & 1) << 15;
767
768 uint32_t Word1 = 0;
769 if (RTI.isStruct())
770 Word1 = RTI.getStruct(DL).Stride;
771 else if (RTI.isCBuffer())
772 Word1 = RTI.getCBufferSize(DL);
773 else if (RTI.isFeedback())
775 else if (RTI.isTyped()) {
777 uint32_t CompType = llvm::to_underlying(Typed.ElementTy);
778 uint32_t CompCount = Typed.ElementCount;
779 uint32_t SampleCount = RTI.isMultiSample() ? RTI.getMultiSampleCount() : 0;
780
781 Word1 |= (CompType & 0xFF) << 0;
782 Word1 |= (CompCount & 0xFF) << 8;
783 Word1 |= (SampleCount & 0xFF) << 16;
784 }
785
786 return {Word0, Word1};
787}
788
790 const DataLayout &DL) const {
791 if (!Name.empty())
792 OS << " Name: " << Name << "\n";
793
794 if (Symbol) {
795 OS << " Symbol: ";
796 Symbol->printAsOperand(OS);
797 OS << "\n";
798 }
799
800 OS << " Binding:\n"
801 << " Record ID: " << Binding.RecordID << "\n"
802 << " Space: " << Binding.Space << "\n"
803 << " Lower Bound: " << Binding.LowerBound << "\n"
804 << " Size: " << Binding.Size << "\n";
805
806 OS << " Globally Coherent: " << GloballyCoherent << "\n";
807 OS << " Counter Direction: ";
808
809 switch (CounterDirection) {
811 OS << "Increment\n";
812 break;
814 OS << "Decrement\n";
815 break;
817 OS << "Unknown\n";
818 break;
820 OS << "Invalid\n";
821 break;
822 }
823
824 RTI.print(OS, DL);
825}
826
827//===----------------------------------------------------------------------===//
828
830 ModuleAnalysisManager::Invalidator &Inv) {
831 // Passes that introduce resource types must explicitly invalidate this pass.
832 auto PAC = PA.getChecker<DXILResourceTypeAnalysis>();
833 return !PAC.preservedWhenStateless();
834}
835
836//===----------------------------------------------------------------------===//
838 return F.getIntrinsicID() == Intrinsic::dx_resource_updatecounter;
839}
840
842 Value *Op = nullptr;
843 switch (CI->getCalledFunction()->getIntrinsicID()) {
844 default:
845 llvm_unreachable("unexpected handle creation intrinsic");
846 case Intrinsic::dx_resource_handlefrombinding:
847 case Intrinsic::dx_resource_handlefromimplicitbinding:
848 Op = CI->getArgOperand(4);
849 break;
850 }
851
853 if (!GV)
854 return "";
855
856 auto *CA = dyn_cast<ConstantDataArray>(GV->getInitializer());
857 assert(CA && CA->isString() && "expected constant string");
858 StringRef Name = CA->getAsString();
859 // strip trailing 0
860 if (Name.ends_with('\0'))
861 Name = Name.drop_back(1);
862 return Name;
863}
864
865void DXILResourceMap::populateResourceInfos(Module &M,
866 DXILResourceTypeMap &DRTM) {
868
869 for (Function &F : M.functions()) {
870 if (!F.isDeclaration())
871 continue;
872 LLVM_DEBUG(dbgs() << "Function: " << F.getName() << "\n");
873 Intrinsic::ID ID = F.getIntrinsicID();
874 switch (ID) {
875 default:
876 continue;
877 case Intrinsic::dx_resource_handlefrombinding: {
878 auto *HandleTy = cast<TargetExtType>(F.getReturnType());
879 ResourceTypeInfo &RTI = DRTM[HandleTy];
880
881 for (User *U : F.users())
882 if (CallInst *CI = dyn_cast<CallInst>(U)) {
883 LLVM_DEBUG(dbgs() << " Visiting: " << *U << "\n");
884 uint32_t Space =
885 cast<ConstantInt>(CI->getArgOperand(0))->getZExtValue();
886 uint32_t LowerBound =
887 cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
888 uint32_t Size =
889 cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
891
892 ResourceInfo RI =
893 ResourceInfo{/*RecordID=*/0, Space, LowerBound,
894 Size, HandleTy, Name};
895
896 CIToInfos.emplace_back(CI, RI, RTI);
897 }
898
899 break;
900 }
901 }
902 }
903
904 llvm::stable_sort(CIToInfos, [](auto &LHS, auto &RHS) {
905 const auto &[LCI, LRI, LRTI] = LHS;
906 const auto &[RCI, RRI, RRTI] = RHS;
907 // Sort by resource class first for grouping purposes, and then by the
908 // binding and type so we can remove duplicates.
909 ResourceClass LRC = LRTI.getResourceClass();
910 ResourceClass RRC = RRTI.getResourceClass();
911
912 return std::tie(LRC, LRI, LRTI) < std::tie(RRC, RRI, RRTI);
913 });
914 for (auto [CI, RI, RTI] : CIToInfos) {
915 if (Infos.empty() || RI != Infos.back())
916 Infos.push_back(RI);
917 CallMap[CI] = Infos.size() - 1;
918 }
919
920 unsigned Size = Infos.size();
921 // In DXC, Record ID is unique per resource type. Match that.
922 FirstUAV = FirstCBuffer = FirstSampler = Size;
923 uint32_t NextID = 0;
924 for (unsigned I = 0, E = Size; I != E; ++I) {
925 ResourceInfo &RI = Infos[I];
926 ResourceTypeInfo &RTI = DRTM[RI.getHandleTy()];
927 if (RTI.isUAV() && FirstUAV == Size) {
928 FirstUAV = I;
929 NextID = 0;
930 } else if (RTI.isCBuffer() && FirstCBuffer == Size) {
931 FirstCBuffer = I;
932 NextID = 0;
933 } else if (RTI.isSampler() && FirstSampler == Size) {
934 FirstSampler = I;
935 NextID = 0;
936 }
937
938 // We need to make sure the types of resource are ordered even if some are
939 // missing.
940 FirstCBuffer = std::min({FirstCBuffer, FirstSampler});
941 FirstUAV = std::min({FirstUAV, FirstCBuffer});
942
943 // Adjust the resource binding to use the next ID.
944 RI.setBindingID(NextID++);
945 }
946}
947
948void DXILResourceMap::populateCounterDirections(Module &M) {
949 for (Function &F : M.functions()) {
951 continue;
952
953 LLVM_DEBUG(dbgs() << "Update Counter Function: " << F.getName() << "\n");
954
955 for (const User *U : F.users()) {
956 const CallInst *CI = dyn_cast<CallInst>(U);
957 assert(CI && "Users of dx_resource_updateCounter must be call instrs");
958
959 // Determine if the use is an increment or decrement
960 Value *CountArg = CI->getArgOperand(1);
961 ConstantInt *CountValue = cast<ConstantInt>(CountArg);
962 int64_t CountLiteral = CountValue->getSExtValue();
963
964 // 0 is an unknown direction and shouldn't result in an insert
965 if (CountLiteral == 0)
966 continue;
967
969 if (CountLiteral > 0)
971
972 // Collect all potential creation points for the handle arg
973 Value *HandleArg = CI->getArgOperand(0);
974 SmallVector<ResourceInfo *> RBInfos = findByUse(HandleArg);
975 for (ResourceInfo *RBInfo : RBInfos) {
976 if (RBInfo->CounterDirection == ResourceCounterDirection::Unknown)
977 RBInfo->CounterDirection = Direction;
978 else if (RBInfo->CounterDirection != Direction) {
979 RBInfo->CounterDirection = ResourceCounterDirection::Invalid;
980 HasInvalidDirection = true;
981 }
982 }
983 }
984 }
985}
986
987void DXILResourceMap::populate(Module &M, DXILResourceTypeMap &DRTM) {
988 populateResourceInfos(M, DRTM);
989 populateCounterDirections(M);
990}
991
993 const DataLayout &DL) const {
994 for (unsigned I = 0, E = Infos.size(); I != E; ++I) {
995 OS << "Resource " << I << ":\n";
996 const dxil::ResourceInfo &RI = Infos[I];
997 RI.print(OS, DRTM[RI.getHandleTy()], DL);
998 OS << "\n";
999 }
1000
1001 for (const auto &[CI, Index] : CallMap) {
1002 OS << "Call bound to " << Index << ":";
1003 CI->print(OS);
1004 OS << "\n";
1005 }
1006}
1007
1008SmallVector<dxil::ResourceInfo *> DXILResourceMap::findByUse(const Value *Key) {
1009 if (const PHINode *Phi = dyn_cast<PHINode>(Key)) {
1011 for (const Value *V : Phi->operands()) {
1012 Children.append(findByUse(V));
1013 }
1014 return Children;
1015 }
1016
1017 const CallInst *CI = dyn_cast<CallInst>(Key);
1018 if (!CI)
1019 return {};
1020
1021 switch (CI->getIntrinsicID()) {
1022 // Found the create, return the binding
1023 case Intrinsic::dx_resource_handlefrombinding: {
1024 auto Pos = CallMap.find(CI);
1025 assert(Pos != CallMap.end() && "HandleFromBinding must be in resource map");
1026 return {&Infos[Pos->second]};
1027 }
1028 default:
1029 break;
1030 }
1031
1032 // Check if any of the parameters are the resource we are following. If so
1033 // keep searching. If none of them are return an empty list
1034 const Type *UseType = CI->getType();
1036 for (const Value *V : CI->args()) {
1037 if (V->getType() != UseType)
1038 continue;
1039
1040 Children.append(findByUse(V));
1041 }
1042
1043 return Children;
1044}
1045
1046//===----------------------------------------------------------------------===//
1047
1048void DXILResourceBindingInfo::populate(Module &M, DXILResourceTypeMap &DRTM) {
1049 hlsl::BindingInfoBuilder Builder;
1050
1051 // collect all of the llvm.dx.resource.handlefrombinding calls;
1052 // make a note if there is llvm.dx.resource.handlefromimplicitbinding
1053 for (Function &F : M.functions()) {
1054 if (!F.isDeclaration())
1055 continue;
1056
1057 switch (F.getIntrinsicID()) {
1058 default:
1059 continue;
1060 case Intrinsic::dx_resource_handlefrombinding: {
1061 auto *HandleTy = cast<TargetExtType>(F.getReturnType());
1062 ResourceTypeInfo &RTI = DRTM[HandleTy];
1063
1064 for (User *U : F.users())
1065 if (CallInst *CI = dyn_cast<CallInst>(U)) {
1066 uint32_t Space =
1067 cast<ConstantInt>(CI->getArgOperand(0))->getZExtValue();
1068 uint32_t LowerBound =
1069 cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
1070 int32_t Size =
1071 cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
1072 Value *Name = CI->getArgOperand(4);
1073
1074 // negative size means unbounded resource array;
1075 // upper bound register overflow should be detected in Sema
1076 assert((Size < 0 || (unsigned)LowerBound + Size - 1 <= UINT32_MAX) &&
1077 "upper bound register overflow");
1078 uint32_t UpperBound = Size < 0 ? UINT32_MAX : LowerBound + Size - 1;
1079 Builder.trackBinding(RTI.getResourceClass(), Space, LowerBound,
1080 UpperBound, Name);
1081 }
1082 break;
1083 }
1084 case Intrinsic::dx_resource_handlefromimplicitbinding: {
1085 HasImplicitBinding = true;
1086 break;
1087 }
1088 }
1089 }
1090
1091 Bindings = Builder.calculateBindingInfo(
1092 [this](auto, auto) { this->HasOverlappingBinding = true; });
1093}
1094
1095//===----------------------------------------------------------------------===//
1096
1097AnalysisKey DXILResourceTypeAnalysis::Key;
1098AnalysisKey DXILResourceAnalysis::Key;
1099AnalysisKey DXILResourceBindingAnalysis::Key;
1100
1108
1116
1121
1122 DRM.print(OS, DRTM, M.getDataLayout());
1123 return PreservedAnalyses::all();
1124}
1125
1126void DXILResourceTypeWrapperPass::anchor() {}
1127
1130
1131INITIALIZE_PASS(DXILResourceTypeWrapperPass, "dxil-resource-type",
1132 "DXIL Resource Type Analysis", false, true)
1134
1136 return new DXILResourceTypeWrapperPass();
1137}
1138
1140
1142
1147
1149 Map.reset(new DXILResourceMap());
1150
1151 DRTM = &getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();
1152 Map->populate(M, *DRTM);
1153
1154 return false;
1155}
1156
1158
1160 if (!Map) {
1161 OS << "No resource map has been built!\n";
1162 return;
1163 }
1164 Map->print(OS, *DRTM, M->getDataLayout());
1165}
1166
1167#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1169void DXILResourceWrapperPass::dump() const { print(dbgs(), nullptr); }
1170#endif
1171
1173 "DXIL Resources Analysis", false, true)
1175
1177 return new DXILResourceWrapperPass();
1178}
1179
1182
1184
1189
1191 BindingInfo.reset(new DXILResourceBindingInfo());
1192
1193 DXILResourceTypeMap &DRTM =
1194 getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();
1195 BindingInfo->populate(M, DRTM);
1196
1197 return false;
1198}
1199
1201
1202INITIALIZE_PASS(DXILResourceBindingWrapperPass, "dxil-resource-binding",
1203 "DXIL Resource Binding Analysis", false, true)
1205
1207 return new DXILResourceWrapperPass();
1208}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition Compiler.h:638
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static dxil::ElementType toDXILElementType(Type *Ty, bool IsSigned)
static bool isUpdateCounterIntrinsic(Function &F)
static StructType * getOrCreateElementStruct(Type *ElemType, StringRef Name)
static void formatTypeName(SmallString< 64 > &Dest, StringRef Name, bool IsWriteable, bool IsROV, Type *ContainedType=nullptr, bool IsSigned=true)
static StringRef getElementTypeName(ElementType ET)
static std::pair< Type *, bool > getTypedElementType(dxil::ResourceKind Kind, TargetExtType *Ty)
static dxil::ElementType toDXILStorageType(dxil::ElementType ET)
static bool isROV(dxil::ResourceKind Kind, TargetExtType *Ty)
static Type * getTypeWithoutPadding(Type *Ty)
static StringRef getResourceKindName(ResourceKind RK)
static StringRef getSamplerTypeName(SamplerType ST)
static StringRef getSamplerFeedbackTypeName(SamplerFeedbackType SFT)
static StringRef getElementTypeNameForTemplate(ElementType ET)
Module.h This file contains the declarations for the Module class.
Loop::LoopBounds::Direction Direction
Definition LoopInfo.cpp:231
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Machine Check Debug Module
This file contains the declarations for metadata subclasses.
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallString class.
This file defines the SmallVector class.
#define LLVM_DEBUG(...)
Definition Debug.h:114
Value * RHS
Value * LHS
Class for arbitrary precision integers.
Definition APInt.h:78
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
AnalysisUsage & addRequiredTransitive()
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
Value * getArgOperand(unsigned i) const
LLVM_ABI Intrinsic::ID getIntrinsicID() const
Returns the intrinsic ID of the intrinsic called or Intrinsic::not_intrinsic if the called function i...
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
This class represents a function call, abstracting a target machine's calling convention.
static ConstantAsMetadata * get(Constant *C)
Definition Metadata.h:536
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
Definition Constants.h:169
static LLVM_ABI Constant * getIntegerValue(Type *Ty, const APInt &V)
Return the value for an integer or pointer constant, or a vector thereof, with the given scalar value...
LLVM_ABI DXILResourceMap run(Module &M, ModuleAnalysisManager &AM)
Gather resource info for the module M.
LLVM_ABI DXILResourceBindingInfo run(Module &M, ModuleAnalysisManager &AM)
bool runOnModule(Module &M) override
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
void releaseMemory() override
releaseMemory() - This member can be implemented by a pass if it wants to be able to release its memo...
LLVM_ABI void print(raw_ostream &OS, DXILResourceTypeMap &DRTM, const DataLayout &DL) const
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
LLVM_ABI bool invalidate(Module &M, const PreservedAnalyses &PA, ModuleAnalysisManager::Invalidator &Inv)
bool runOnModule(Module &M) override
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
void releaseMemory() override
releaseMemory() - This member can be implemented by a pass if it wants to be able to release its memo...
void print(raw_ostream &OS, const Module *M) const override
print - Print out the internal state of the pass.
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:63
Class to represent fixed width SIMD vectors.
Intrinsic::ID getIntrinsicID() const LLVM_READONLY
getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...
Definition Function.h:244
@ ExternalLinkage
Externally visible function.
Definition GlobalValue.h:53
ImmutablePass(char &pid)
Definition Pass.h:287
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1569
static LLVM_ABI MDString * get(LLVMContext &Context, StringRef Str)
Definition Metadata.cpp:608
Tuple of metadata.
Definition Metadata.h:1497
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition Pass.h:255
ModulePass(char &pid)
Definition Pass.h:257
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalysisChecker getChecker() const
Build a checker for this PreservedAnalyses and the specified analysis type.
Definition Analysis.h:275
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
constexpr bool empty() const
empty - Check if the string is empty.
Definition StringRef.h:143
Class to represent struct types.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
Definition Type.cpp:413
static LLVM_ABI StructType * getTypeByName(LLVMContext &C, StringRef Name)
Return the type with the specified name, or null if there is none by that name.
Definition Type.cpp:738
static LLVM_ABI StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
Definition Type.cpp:619
Class to represent target extensions types, which are generally unintrospectable from target-independ...
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:296
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
Definition Type.h:128
static LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)
Definition Type.cpp:293
static LLVM_ABI ValueAsMetadata * get(Value *V)
Definition Metadata.cpp:503
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:256
LLVM_ABI void print(raw_ostream &O, bool IsForDebug=false) const
Implement operator<< on Value.
The dx.Layout target extension type.
TargetExtType * getHandleTy() const
LLVM_ABI std::pair< uint32_t, uint32_t > getAnnotateProps(Module &M, dxil::ResourceTypeInfo &RTI) const
LLVM_ABI void print(raw_ostream &OS, dxil::ResourceTypeInfo &RTI, const DataLayout &DL) const
void setBindingID(unsigned ID)
LLVM_ABI GlobalVariable * createSymbol(Module &M, StructType *Ty)
LLVM_ABI MDTuple * getAsMetadata(Module &M, dxil::ResourceTypeInfo &RTI) const
ResourceCounterDirection CounterDirection
dxil::ResourceClass getResourceClass() const
LLVM_ABI uint32_t getMultiSampleCount() const
LLVM_ABI uint32_t getCBufferSize(const DataLayout &DL) const
LLVM_ABI bool operator<(const ResourceTypeInfo &RHS) const
LLVM_ABI bool isUAV() const
LLVM_ABI bool isMultiSample() const
LLVM_ABI bool isSampler() const
LLVM_ABI bool isTyped() const
LLVM_ABI dxil::SamplerType getSamplerType() const
LLVM_ABI ResourceTypeInfo(TargetExtType *HandleTy, const dxil::ResourceClass RC, const dxil::ResourceKind Kind)
LLVM_ABI bool isCBuffer() const
LLVM_ABI TypedInfo getTyped() const
LLVM_ABI StructType * createElementStruct(StringRef CBufferName="")
LLVM_ABI bool isFeedback() const
LLVM_ABI UAVInfo getUAV() const
LLVM_ABI StructInfo getStruct(const DataLayout &DL) const
LLVM_ABI bool isStruct() const
LLVM_ABI dxil::SamplerFeedbackType getFeedbackType() const
LLVM_ABI bool operator==(const ResourceTypeInfo &RHS) const
dxil::ResourceKind getResourceKind() const
LLVM_ABI void print(raw_ostream &OS, const DataLayout &DL) const
void trackBinding(dxil::ResourceClass RC, uint32_t Space, uint32_t LowerBound, uint32_t UpperBound, const void *Cookie)
LLVM_ABI BindingInfo calculateBindingInfo(llvm::function_ref< void(const BindingInfoBuilder &Builder, const Binding &Overlapping)> ReportOverlap)
Calculate the binding info - ReportOverlap will be called once for each overlapping binding.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
A raw_ostream that writes to an SmallVector or SmallString.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
LLVM_ABI StringRef getResourceClassName(ResourceClass RC)
Definition DXILABI.cpp:21
ResourceKind
The kind of resource for an SRV or UAV resource.
Definition DXILABI.h:36
SamplerFeedbackType
Definition DXILABI.h:96
ElementType
The element type of an SRV or UAV resource.
Definition DXILABI.h:60
LLVM_ABI StringRef getResourceNameFromBindingCall(CallInst *CI)
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
LLVM_ABI ModulePass * createDXILResourceBindingWrapperPassPass()
void stable_sort(R &&Range)
Definition STLExtras.h:2058
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
LLVM_ABI ModulePass * createDXILResourceTypeWrapperPassPass()
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
constexpr std::underlying_type_t< Enum > to_underlying(Enum E)
Returns underlying integer value of an enum.
FunctionAddr VTableAddr Count
Definition InstrProf.h:139
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:189
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
unsigned Log2(Align A)
Returns the log2 of the alignment.
Definition Alignment.h:197
LLVM_ABI ModulePass * createDXILResourceWrapperPassPass()
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Definition Alignment.h:106