LLVM 24.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"
20#include "llvm/IR/Intrinsics.h"
21#include "llvm/IR/IntrinsicsDirectX.h"
22#include "llvm/IR/Metadata.h"
23#include "llvm/IR/Module.h"
27#include <cstdint>
28
29#define DEBUG_TYPE "dxil-resource"
30
31using namespace llvm;
32using namespace dxil;
33
35 switch (RK) {
36 case ResourceKind::Texture1D:
37 return "Texture1D";
38 case ResourceKind::Texture2D:
39 return "Texture2D";
40 case ResourceKind::Texture2DMS:
41 return "Texture2DMS";
42 case ResourceKind::Texture3D:
43 return "Texture3D";
44 case ResourceKind::TextureCube:
45 return "TextureCube";
46 case ResourceKind::Texture1DArray:
47 return "Texture1DArray";
48 case ResourceKind::Texture2DArray:
49 return "Texture2DArray";
50 case ResourceKind::Texture2DMSArray:
51 return "Texture2DMSArray";
52 case ResourceKind::TextureCubeArray:
53 return "TextureCubeArray";
54 case ResourceKind::TypedBuffer:
55 return "Buffer";
56 case ResourceKind::RawBuffer:
57 return "RawBuffer";
58 case ResourceKind::StructuredBuffer:
59 return "StructuredBuffer";
60 case ResourceKind::CBuffer:
61 return "CBuffer";
62 case ResourceKind::Sampler:
63 return "Sampler";
64 case ResourceKind::TBuffer:
65 return "TBuffer";
66 case ResourceKind::RTAccelerationStructure:
67 return "RTAccelerationStructure";
68 case ResourceKind::FeedbackTexture2D:
69 return "FeedbackTexture2D";
70 case ResourceKind::FeedbackTexture2DArray:
71 return "FeedbackTexture2DArray";
72 case ResourceKind::NumEntries:
73 case ResourceKind::Invalid:
74 return "<invalid>";
75 }
76 llvm_unreachable("Unhandled ResourceKind");
77}
78
80 switch (ET) {
81 case ElementType::I1:
82 return "i1";
83 case ElementType::I16:
84 return "i16";
85 case ElementType::U16:
86 return "u16";
87 case ElementType::I32:
88 return "i32";
89 case ElementType::U32:
90 return "u32";
91 case ElementType::I64:
92 return "i64";
93 case ElementType::U64:
94 return "u64";
95 case ElementType::F16:
96 return "f16";
97 case ElementType::F32:
98 return "f32";
99 case ElementType::F64:
100 return "f64";
101 case ElementType::SNormF16:
102 return "snorm_f16";
103 case ElementType::UNormF16:
104 return "unorm_f16";
105 case ElementType::SNormF32:
106 return "snorm_f32";
107 case ElementType::UNormF32:
108 return "unorm_f32";
109 case ElementType::SNormF64:
110 return "snorm_f64";
111 case ElementType::UNormF64:
112 return "unorm_f64";
113 case ElementType::PackedS8x32:
114 return "p32i8";
115 case ElementType::PackedU8x32:
116 return "p32u8";
117 case ElementType::Invalid:
118 return "<invalid>";
119 }
120 llvm_unreachable("Unhandled ElementType");
121}
122
124 switch (ET) {
125 case ElementType::I1:
126 return "bool";
127 case ElementType::I16:
128 return "int16_t";
129 case ElementType::U16:
130 return "uint16_t";
131 case ElementType::I32:
132 return "int32_t";
133 case ElementType::U32:
134 return "uint32_t";
135 case ElementType::I64:
136 return "int64_t";
137 case ElementType::U64:
138 return "uint32_t";
139 case ElementType::F16:
140 case ElementType::SNormF16:
141 case ElementType::UNormF16:
142 return "half";
143 case ElementType::F32:
144 case ElementType::SNormF32:
145 case ElementType::UNormF32:
146 return "float";
147 case ElementType::F64:
148 case ElementType::SNormF64:
149 case ElementType::UNormF64:
150 return "double";
151 case ElementType::PackedS8x32:
152 return "int8_t4_packed";
153 case ElementType::PackedU8x32:
154 return "uint8_t4_packed";
155 case ElementType::Invalid:
156 return "<invalid>";
157 }
158 llvm_unreachable("Unhandled ElementType");
159}
160
162 switch (ST) {
163 case SamplerType::Default:
164 return "Default";
165 case SamplerType::Comparison:
166 return "Comparison";
167 case SamplerType::Mono:
168 return "Mono";
169 }
170 llvm_unreachable("Unhandled SamplerType");
171}
172
174 switch (SFT) {
175 case SamplerFeedbackType::MinMip:
176 return "MinMip";
177 case SamplerFeedbackType::MipRegionUsed:
178 return "MipRegionUsed";
179 }
180 llvm_unreachable("Unhandled SamplerFeedbackType");
181}
182
183static dxil::ElementType toDXILElementType(Type *Ty, bool IsSigned) {
184 // TODO: Handle unorm, snorm, and packed.
185 Ty = Ty->getScalarType();
186
187 if (Ty->isIntegerTy()) {
188 switch (Ty->getIntegerBitWidth()) {
189 case 16:
190 return IsSigned ? ElementType::I16 : ElementType::U16;
191 case 32:
192 return IsSigned ? ElementType::I32 : ElementType::U32;
193 case 64:
194 return IsSigned ? ElementType::I64 : ElementType::U64;
195 case 1:
196 default:
197 return ElementType::Invalid;
198 }
199 } else if (Ty->isFloatTy()) {
200 return ElementType::F32;
201 } else if (Ty->isDoubleTy()) {
202 return ElementType::F64;
203 } else if (Ty->isHalfTy()) {
204 return ElementType::F16;
205 }
206
207 return ElementType::Invalid;
208}
209
217
219 const dxil::ResourceClass RC_,
220 const dxil::ResourceKind Kind_)
221 : HandleTy(HandleTy) {
222 // If we're provided a resource class and kind, trust them.
223 if (Kind_ != dxil::ResourceKind::Invalid) {
224 RC = RC_;
225 Kind = Kind_;
226 return;
227 }
228
229 if (auto *Ty = dyn_cast<RawBufferExtType>(HandleTy)) {
230 RC = Ty->isWriteable() ? ResourceClass::UAV : ResourceClass::SRV;
231 Kind = Ty->isStructured() ? ResourceKind::StructuredBuffer
233 } else if (auto *Ty = dyn_cast<TypedBufferExtType>(HandleTy)) {
234 RC = Ty->isWriteable() ? ResourceClass::UAV : ResourceClass::SRV;
236 } else if (auto *Ty = dyn_cast<TextureExtType>(HandleTy)) {
237 RC = Ty->isWriteable() ? ResourceClass::UAV : ResourceClass::SRV;
238 Kind = Ty->getDimension();
239 } else if (auto *Ty = dyn_cast<MSTextureExtType>(HandleTy)) {
240 RC = Ty->isWriteable() ? ResourceClass::UAV : ResourceClass::SRV;
241 Kind = Ty->getDimension();
242 } else if (auto *Ty = dyn_cast<FeedbackTextureExtType>(HandleTy)) {
244 Kind = Ty->getDimension();
245 } else if (isa<CBufferExtType>(HandleTy)) {
248 } else if (isa<SamplerExtType>(HandleTy)) {
251 } else
252 llvm_unreachable("Unknown handle type");
253}
254
256 bool IsWriteable, bool IsROV,
257 Type *ContainedType = nullptr,
258 bool IsSigned = true) {
259 raw_svector_ostream DestStream(Dest);
260 if (IsWriteable)
261 DestStream << (IsROV ? "RasterizerOrdered" : "RW");
262 DestStream << Name;
263
264 if (!ContainedType)
265 return;
266
267 SmallVector<uint64_t> ArrayDimensions;
268 while (ArrayType *AT = dyn_cast<ArrayType>(ContainedType)) {
269 ArrayDimensions.push_back(AT->getNumElements());
270 ContainedType = AT->getElementType();
271 }
272
273 StringRef ElementName;
274 ElementType ET = toDXILElementType(ContainedType, IsSigned);
275 if (ET != ElementType::Invalid) {
276 ElementName = getElementTypeNameForTemplate(ET);
277 } else {
278 assert(isa<StructType>(ContainedType) &&
279 "invalid element type for raw buffer");
280 StructType *ST = cast<StructType>(ContainedType);
281 if (!ST->hasName())
282 return;
283 ElementName = ST->getStructName();
284 }
285
286 DestStream << "<" << ElementName;
287 if (const FixedVectorType *VTy = dyn_cast<FixedVectorType>(ContainedType))
288 DestStream << VTy->getNumElements();
289 for (uint64_t Dim : ArrayDimensions)
290 DestStream << "[" << Dim << "]";
291 DestStream << ">";
292}
293
295 StructType *Ty = StructType::getTypeByName(ElemType->getContext(), Name);
296 if (Ty && Ty->getNumElements() == 1 && Ty->getElementType(0) == ElemType)
297 return Ty;
298 return StructType::create(ElemType, Name);
299}
300
302 // Recursively remove padding from structures.
303 if (auto *ST = dyn_cast<StructType>(Ty)) {
304 LLVMContext &Ctx = Ty->getContext();
305 SmallVector<Type *> ElementTypes;
306 ElementTypes.reserve(ST->getNumElements());
307 for (Type *ElTy : ST->elements()) {
308 if (isa<PaddingExtType>(ElTy))
309 continue;
310 ElementTypes.push_back(getTypeWithoutPadding(ElTy));
311 }
312
313 // Handle explicitly padded cbuffer arrays like { [ n x paddedty ], ty }
314 if (ElementTypes.size() == 2)
315 if (auto *AT = dyn_cast<ArrayType>(ElementTypes[0]))
316 if (ElementTypes[1] == AT->getElementType())
317 return ArrayType::get(ElementTypes[1], AT->getNumElements() + 1);
318
319 // If we only have a single element, don't wrap it in a struct.
320 if (ElementTypes.size() == 1)
321 return ElementTypes[0];
322
323 return StructType::get(Ctx, ElementTypes, /*IsPacked=*/false);
324 }
325 // Arrays just need to have their element type adjusted.
326 if (auto *AT = dyn_cast<ArrayType>(Ty))
327 return ArrayType::get(getTypeWithoutPadding(AT->getElementType()),
328 AT->getNumElements());
329 // Anything else should be good as is.
330 return Ty;
331}
332
334 SmallString<64> TypeName;
335
336 switch (Kind) {
344 auto *RTy = cast<TextureExtType>(HandleTy);
345 formatTypeName(TypeName, getResourceKindName(Kind), RTy->isWriteable(),
346 RTy->isROV(), RTy->getResourceType(), RTy->isSigned());
347 return getOrCreateElementStruct(RTy->getResourceType(), TypeName);
348 }
351 auto *RTy = cast<MSTextureExtType>(HandleTy);
352 formatTypeName(TypeName, getResourceKindName(Kind), RTy->isWriteable(),
353 /*IsROV=*/false, RTy->getResourceType(), RTy->isSigned());
354 return getOrCreateElementStruct(RTy->getResourceType(), TypeName);
355 }
357 auto *RTy = cast<TypedBufferExtType>(HandleTy);
358 formatTypeName(TypeName, getResourceKindName(Kind), RTy->isWriteable(),
359 RTy->isROV(), RTy->getResourceType(), RTy->isSigned());
360 return getOrCreateElementStruct(RTy->getResourceType(), TypeName);
361 }
363 auto *RTy = cast<RawBufferExtType>(HandleTy);
364 formatTypeName(TypeName, "ByteAddressBuffer", RTy->isWriteable(),
365 RTy->isROV());
366 return getOrCreateElementStruct(Type::getInt32Ty(HandleTy->getContext()),
367 TypeName);
368 }
370 auto *RTy = cast<RawBufferExtType>(HandleTy);
371 Type *Ty = RTy->getResourceType();
372 formatTypeName(TypeName, "StructuredBuffer", RTy->isWriteable(),
373 RTy->isROV(), RTy->getResourceType(), true);
374 return getOrCreateElementStruct(Ty, TypeName);
375 }
378 auto *RTy = cast<FeedbackTextureExtType>(HandleTy);
379 TypeName = formatv("{0}<{1}>", getResourceKindName(Kind),
380 llvm::to_underlying(RTy->getFeedbackType()));
381 return getOrCreateElementStruct(Type::getInt32Ty(HandleTy->getContext()),
382 TypeName);
383 }
385 auto *RTy = cast<CBufferExtType>(HandleTy);
387 if (!CBufferName.empty()) {
388 Name.append(".");
389 Name.append(CBufferName);
390 }
391
392 // TODO: Remove this when we update the frontend to use explicit padding.
393 if (LayoutExtType *LayoutType =
394 dyn_cast<LayoutExtType>(RTy->getResourceType())) {
395 StructType *Ty = cast<StructType>(LayoutType->getWrappedType());
396 return StructType::create(Ty->elements(), Name);
397 }
398
400 getTypeWithoutPadding(RTy->getResourceType()), Name);
401 }
403 auto *RTy = cast<SamplerExtType>(HandleTy);
404 TypeName = formatv("SamplerState<{0}>",
405 llvm::to_underlying(RTy->getSamplerType()));
406 return getOrCreateElementStruct(Type::getInt32Ty(HandleTy->getContext()),
407 TypeName);
408 }
411 llvm_unreachable("Unhandled resource kind");
414 llvm_unreachable("Invalid resource kind");
415 }
416 llvm_unreachable("Unhandled ResourceKind enum");
417}
418
419bool ResourceTypeInfo::isUAV() const { return RC == ResourceClass::UAV; }
420
422 return RC == ResourceClass::CBuffer;
423}
424
426 return RC == ResourceClass::Sampler;
427}
428
430 return Kind == ResourceKind::StructuredBuffer;
431}
432
461
466
471
472static bool isROV(dxil::ResourceKind Kind, TargetExtType *Ty) {
473 switch (Kind) {
481 return cast<TextureExtType>(Ty)->isROV();
483 return cast<TypedBufferExtType>(Ty)->isROV();
486 return cast<RawBufferExtType>(Ty)->isROV();
491 return false;
498 llvm_unreachable("Resource cannot be ROV");
499 }
500 llvm_unreachable("Unhandled ResourceKind enum");
501}
502
504 assert(isUAV() && "Not a UAV");
505 return {isROV(Kind, HandleTy)};
506}
507
509 assert(isCBuffer() && "Not a CBuffer");
510
511 Type *ElTy = cast<CBufferExtType>(HandleTy)->getResourceType();
512
513 // TODO: Remove this when we update the frontend to use explicit padding.
514 if (auto *LayoutTy = dyn_cast<LayoutExtType>(ElTy))
515 return LayoutTy->getSize();
516
517 return DL.getTypeAllocSize(ElTy);
518}
519
521 assert(isSampler() && "Not a Sampler");
522 return cast<SamplerExtType>(HandleTy)->getSamplerType();
523}
524
527 assert(isStruct() && "Not a Struct");
528
529 Type *ElTy = cast<RawBufferExtType>(HandleTy)->getResourceType();
530
531 uint32_t Stride = DL.getTypeAllocSize(ElTy);
532 MaybeAlign Alignment;
533 if (auto *STy = dyn_cast<StructType>(ElTy))
534 Alignment = DL.getStructLayout(STy)->getAlignment();
535 uint32_t AlignLog2 = Alignment ? Log2(*Alignment) : 0;
536 return {Stride, AlignLog2};
537}
538
539static std::pair<Type *, bool> getTypedElementType(dxil::ResourceKind Kind,
540 TargetExtType *Ty) {
541 switch (Kind) {
549 auto *RTy = cast<TextureExtType>(Ty);
550 return {RTy->getResourceType(), RTy->isSigned()};
551 }
554 auto *RTy = cast<MSTextureExtType>(Ty);
555 return {RTy->getResourceType(), RTy->isSigned()};
556 }
558 auto *RTy = cast<TypedBufferExtType>(Ty);
559 return {RTy->getResourceType(), RTy->isSigned()};
560 }
571 llvm_unreachable("Resource is not typed");
572 }
573 llvm_unreachable("Unhandled ResourceKind enum");
574}
575
577 assert(isTyped() && "Not typed");
578
579 auto [ElTy, IsSigned] = getTypedElementType(Kind, HandleTy);
580 dxil::ElementType ET = toDXILElementType(ElTy, IsSigned);
581 dxil::ElementType DXILStorageTy = toDXILStorageType(ET);
582 uint32_t Count = 1;
583 if (auto *VTy = dyn_cast<FixedVectorType>(ElTy))
584 Count = VTy->getNumElements();
585 return {ET, DXILStorageTy, Count};
586}
587
589 assert(isFeedback() && "Not Feedback");
590 return cast<FeedbackTextureExtType>(HandleTy)->getFeedbackType();
591}
593 assert(isMultiSample() && "Not MultiSampled");
594 return cast<MSTextureExtType>(HandleTy)->getSampleCount();
595}
596
598 return HandleTy == RHS.HandleTy;
599}
600
602 // An empty datalayout is sufficient for sorting purposes.
603 DataLayout DummyDL;
604 if (std::tie(RC, Kind) < std::tie(RHS.RC, RHS.Kind))
605 return true;
606 if (isCBuffer() && RHS.isCBuffer() &&
607 getCBufferSize(DummyDL) < RHS.getCBufferSize(DummyDL))
608 return true;
609 if (isSampler() && RHS.isSampler() && getSamplerType() < RHS.getSamplerType())
610 return true;
611 if (isUAV() && RHS.isUAV() && getUAV() < RHS.getUAV())
612 return true;
613 if (isStruct() && RHS.isStruct() &&
614 getStruct(DummyDL) < RHS.getStruct(DummyDL))
615 return true;
616 if (isFeedback() && RHS.isFeedback() &&
617 getFeedbackType() < RHS.getFeedbackType())
618 return true;
619 if (isTyped() && RHS.isTyped() && getTyped() < RHS.getTyped())
620 return true;
621 if (isMultiSample() && RHS.isMultiSample() &&
622 getMultiSampleCount() < RHS.getMultiSampleCount())
623 return true;
624 return false;
625}
626
628 OS << " Class: " << getResourceClassName(RC) << "\n"
629 << " Kind: " << getResourceKindName(Kind) << "\n";
630
631 if (isCBuffer()) {
632 OS << " CBuffer size: " << getCBufferSize(DL) << "\n";
633 } else if (isSampler()) {
634 OS << " Sampler Type: " << getSamplerTypeName(getSamplerType()) << "\n";
635 } else {
636 if (isUAV()) {
637 UAVInfo UAVFlags = getUAV();
638 OS << " IsROV: " << UAVFlags.IsROV << "\n";
639 }
640 if (isMultiSample())
641 OS << " Sample Count: " << getMultiSampleCount() << "\n";
642
643 if (isStruct()) {
644 StructInfo Struct = getStruct(DL);
645 OS << " Buffer Stride: " << Struct.Stride << "\n";
646 OS << " Alignment: " << Struct.AlignLog2 << "\n";
647 } else if (isTyped()) {
648 TypedInfo Typed = getTyped();
649 OS << " Element Type: " << getElementTypeName(Typed.ElementTy);
650 if (Typed.ElementTy != Typed.DXILStorageTy)
651 OS << " (stored as " << getElementTypeName(Typed.DXILStorageTy) << ")";
652 OS << "\n"
653 << " Element Count: " << Typed.ElementCount << "\n";
654 } else if (isFeedback())
655 OS << " Feedback Type: " << getSamplerFeedbackTypeName(getFeedbackType())
656 << "\n";
657 }
658}
659
661 assert(!Symbol && "Symbol has already been created");
662 Type *ResTy = Ty;
663 int64_t Size = Binding.Size;
664 if (Size != 1)
665 // unbounded arrays are represented as zero-sized arrays in LLVM IR
666 ResTy = ArrayType::get(Ty, Size == ~0u ? 0 : Size);
667 Symbol = new GlobalVariable(M, ResTy, /*isConstant=*/true,
669 /*Initializer=*/nullptr, Name);
670 return Symbol;
671}
672
674 dxil::ResourceTypeInfo &RTI) const {
675 LLVMContext &Ctx = M.getContext();
676 const DataLayout &DL = M.getDataLayout();
677
679
680 Type *I32Ty = Type::getInt32Ty(Ctx);
681 Type *I1Ty = Type::getInt1Ty(Ctx);
682 auto getIntMD = [&I32Ty](uint32_t V) {
684 Constant::getIntegerValue(I32Ty, APInt(32, V)));
685 };
686 auto getBoolMD = [&I1Ty](uint32_t V) {
688 Constant::getIntegerValue(I1Ty, APInt(1, V)));
689 };
690
691 MDVals.push_back(getIntMD(Binding.RecordID));
692 assert(Symbol && "Cannot yet create useful resource metadata without symbol");
693 MDVals.push_back(ValueAsMetadata::get(Symbol));
694 MDVals.push_back(MDString::get(Ctx, Name));
695 MDVals.push_back(getIntMD(Binding.Space));
696 MDVals.push_back(getIntMD(Binding.LowerBound));
697 MDVals.push_back(getIntMD(Binding.Size == 0 ? ~0u : Binding.Size));
698
699 if (RTI.isCBuffer()) {
700 MDVals.push_back(getIntMD(RTI.getCBufferSize(DL)));
701 MDVals.push_back(nullptr);
702 } else if (RTI.isSampler()) {
703 MDVals.push_back(getIntMD(llvm::to_underlying(RTI.getSamplerType())));
704 MDVals.push_back(nullptr);
705 } else {
706 MDVals.push_back(getIntMD(llvm::to_underlying(RTI.getResourceKind())));
707
708 if (RTI.isUAV()) {
709 ResourceTypeInfo::UAVInfo UAVFlags = RTI.getUAV();
710 MDVals.push_back(getBoolMD(GloballyCoherent));
711 MDVals.push_back(getBoolMD(hasCounter()));
712 MDVals.push_back(getBoolMD(UAVFlags.IsROV));
713 } else {
714 // All SRVs include sample count in the metadata, but it's only meaningful
715 // for multi-sampled textured. Also, UAVs can be multisampled in SM6.7+,
716 // but this just isn't reflected in the metadata at all.
717 uint32_t SampleCount =
718 RTI.isMultiSample() ? RTI.getMultiSampleCount() : 0;
719 MDVals.push_back(getIntMD(SampleCount));
720 }
721
722 // Further properties are attached to a metadata list of tag-value pairs.
724 if (RTI.isStruct()) {
725 Tags.push_back(
727 Tags.push_back(getIntMD(RTI.getStruct(DL).Stride));
728 } else if (RTI.isTyped()) {
730 Tags.push_back(
732 } else if (RTI.isFeedback()) {
733 Tags.push_back(
735 Tags.push_back(getIntMD(llvm::to_underlying(RTI.getFeedbackType())));
736 }
737 MDVals.push_back(Tags.empty() ? nullptr : MDNode::get(Ctx, Tags));
738 }
739
740 return MDNode::get(Ctx, MDVals);
741}
742
743std::pair<uint32_t, uint32_t>
745 const DataLayout &DL = M.getDataLayout();
746
748 uint32_t AlignLog2 = RTI.isStruct() ? RTI.getStruct(DL).AlignLog2 : 0;
749 bool IsUAV = RTI.isUAV();
751 IsUAV ? RTI.getUAV() : ResourceTypeInfo::UAVInfo{};
752 bool IsROV = IsUAV && UAVFlags.IsROV;
753 bool IsGloballyCoherent = IsUAV && GloballyCoherent;
754 uint8_t SamplerCmpOrHasCounter = 0;
755 if (IsUAV)
756 SamplerCmpOrHasCounter = hasCounter();
757 else if (RTI.isSampler())
758 SamplerCmpOrHasCounter = RTI.getSamplerType() == SamplerType::Comparison;
759
760 // TODO: Document this format. Currently the only reference is the
761 // implementation of dxc's DxilResourceProperties struct.
762 uint32_t Word0 = 0;
763 Word0 |= ResourceKind & 0xFF;
764 Word0 |= (AlignLog2 & 0xF) << 8;
765 Word0 |= (IsUAV & 1) << 12;
766 Word0 |= (IsROV & 1) << 13;
767 Word0 |= (IsGloballyCoherent & 1) << 14;
768 Word0 |= (SamplerCmpOrHasCounter & 1) << 15;
769
770 uint32_t Word1 = 0;
771 if (RTI.isStruct())
772 Word1 = RTI.getStruct(DL).Stride;
773 else if (RTI.isCBuffer())
774 Word1 = RTI.getCBufferSize(DL);
775 else if (RTI.isFeedback())
777 else if (RTI.isTyped()) {
779 uint32_t CompType = llvm::to_underlying(Typed.ElementTy);
780 uint32_t CompCount = Typed.ElementCount;
781 uint32_t SampleCount = RTI.isMultiSample() ? RTI.getMultiSampleCount() : 0;
782
783 Word1 |= (CompType & 0xFF) << 0;
784 Word1 |= (CompCount & 0xFF) << 8;
785 Word1 |= (SampleCount & 0xFF) << 16;
786 }
787
788 return {Word0, Word1};
789}
790
792 const DataLayout &DL) const {
793 if (!Name.empty())
794 OS << " Name: " << Name << "\n";
795
796 if (Symbol) {
797 OS << " Symbol: ";
798 Symbol->printAsOperand(OS);
799 OS << "\n";
800 }
801
802 OS << " Binding:\n"
803 << " Record ID: " << Binding.RecordID << "\n"
804 << " Space: " << Binding.Space << "\n"
805 << " Lower Bound: " << Binding.LowerBound << "\n"
806 << " Size: " << Binding.Size << "\n";
807
808 OS << " Globally Coherent: " << GloballyCoherent << "\n";
809 OS << " Has Atomic64 Use: " << HasAtomic64Use << "\n";
810 OS << " Counter Direction: ";
811
812 switch (CounterDirection) {
814 OS << "Increment\n";
815 break;
817 OS << "Decrement\n";
818 break;
820 OS << "Unknown\n";
821 break;
823 OS << "Invalid\n";
824 break;
825 }
826
827 RTI.print(OS, DL);
828}
829
830//===----------------------------------------------------------------------===//
831
833 ModuleAnalysisManager::Invalidator &Inv) {
834 // Passes that introduce resource types must explicitly invalidate this pass.
835 auto PAC = PA.getChecker<DXILResourceTypeAnalysis>();
836 return !PAC.preservedWhenStateless();
837}
838
839//===----------------------------------------------------------------------===//
841 Value *Op = nullptr;
842 switch (CI->getCalledFunction()->getIntrinsicID()) {
843 default:
844 llvm_unreachable("unexpected handle creation intrinsic");
845 case Intrinsic::dx_resource_handlefrombinding:
846 case Intrinsic::dx_resource_handlefromimplicitbinding:
847 Op = CI->getArgOperand(4);
848 break;
849 }
850
852 if (!GV)
853 return "";
854
855 auto *CA = dyn_cast<ConstantDataArray>(GV->getInitializer());
856 assert(CA && CA->isString() && "expected constant string");
857 StringRef Name = CA->getAsString();
858 // strip trailing 0
859 if (Name.ends_with('\0'))
860 Name = Name.drop_back(1);
861 return Name;
862}
863
864void DXILResourceMap::populateResourceInfos(Module &M,
865 DXILResourceTypeMap &DRTM) {
867
868 for (Function &F : M.functions()) {
869 if (!F.isDeclaration())
870 continue;
871 LLVM_DEBUG(dbgs() << "Function: " << F.getName() << "\n");
872 Intrinsic::ID ID = F.getIntrinsicID();
873 switch (ID) {
874 default:
875 continue;
876 case Intrinsic::dx_resource_handlefrombinding: {
877 auto *HandleTy = cast<TargetExtType>(F.getReturnType());
878 ResourceTypeInfo &RTI = DRTM[HandleTy];
879
880 for (User *U : F.users())
881 if (CallInst *CI = dyn_cast<CallInst>(U)) {
882 LLVM_DEBUG(dbgs() << " Visiting: " << *U << "\n");
883 uint32_t Space =
884 cast<ConstantInt>(CI->getArgOperand(0))->getZExtValue();
885 uint32_t LowerBound =
886 cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
887 uint32_t Size =
888 cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
890
891 ResourceInfo RI =
892 ResourceInfo{/*RecordID=*/0, Space, LowerBound,
893 Size, HandleTy, Name};
894
895 CIToInfos.emplace_back(CI, RI, RTI);
896 }
897
898 break;
899 }
900 }
901 }
902
903 llvm::stable_sort(CIToInfos, [](auto &LHS, auto &RHS) {
904 const auto &[LCI, LRI, LRTI] = LHS;
905 const auto &[RCI, RRI, RRTI] = RHS;
906 // Sort by resource class first for grouping purposes, and then by the
907 // binding and type so we can remove duplicates.
908 ResourceClass LRC = LRTI.getResourceClass();
909 ResourceClass RRC = RRTI.getResourceClass();
910
911 return std::tie(LRC, LRI, LRTI) < std::tie(RRC, RRI, RRTI);
912 });
913 for (auto [CI, RI, RTI] : CIToInfos) {
914 if (Infos.empty() || RI != Infos.back())
915 Infos.push_back(RI);
916 CallMap[CI] = Infos.size() - 1;
917 }
918
919 unsigned Size = Infos.size();
920 // In DXC, Record ID is unique per resource type. Match that.
921 FirstUAV = FirstCBuffer = FirstSampler = Size;
922 uint32_t NextID = 0;
923 for (unsigned I = 0, E = Size; I != E; ++I) {
924 ResourceInfo &RI = Infos[I];
925 ResourceTypeInfo &RTI = DRTM[RI.getHandleTy()];
926 if (RTI.isUAV() && FirstUAV == Size) {
927 FirstUAV = I;
928 NextID = 0;
929 } else if (RTI.isCBuffer() && FirstCBuffer == Size) {
930 FirstCBuffer = I;
931 NextID = 0;
932 } else if (RTI.isSampler() && FirstSampler == Size) {
933 FirstSampler = I;
934 NextID = 0;
935 }
936
937 // We need to make sure the types of resource are ordered even if some are
938 // missing.
939 FirstCBuffer = std::min({FirstCBuffer, FirstSampler});
940 FirstUAV = std::min({FirstUAV, FirstCBuffer});
941
942 // Adjust the resource binding to use the next ID.
943 RI.setBindingID(NextID++);
944 }
945}
946
948 Ptr = Ptr->stripPointerCasts();
949 while (auto *GEP = dyn_cast<GetElementPtrInst>(Ptr))
950 Ptr = GEP->getPointerOperand()->stripPointerCasts();
951 auto *II = dyn_cast<IntrinsicInst>(Ptr);
952 if (II && II->getIntrinsicID() == Intrinsic::dx_resource_getpointer)
953 return II->getArgOperand(0);
954 return nullptr;
955}
956
957void DXILResourceMap::populateAtomicUses(Instruction &I) {
958 auto MarkFromHandle = [this](Value *Handle) {
959 if (!Handle)
960 return;
961 for (ResourceInfo *RI : findByUse(Handle))
962 RI->HasAtomic64Use = true;
963 };
964
965 // Handles both `atomicrmw`/`cmpxchg` (before `DXILResourceAccess`) and the
966 // lowered `llvm.dx.resource.atomic.binop` intrinsic (after it).
967 if (auto *AI = dyn_cast<AtomicRMWInst>(&I)) {
968 if (AI->getValOperand()->getType()->isIntegerTy(64))
969 MarkFromHandle(findResourceHandleFromPointer(AI->getPointerOperand()));
970 return;
971 }
972 if (auto *CX = dyn_cast<AtomicCmpXchgInst>(&I)) {
973 if (CX->getNewValOperand()->getType()->isIntegerTy(64))
974 MarkFromHandle(findResourceHandleFromPointer(CX->getPointerOperand()));
975 return;
976 }
977 if (auto *CI = dyn_cast<CallInst>(&I)) {
978 if (CI->getIntrinsicID() == Intrinsic::dx_resource_atomic_binop &&
979 CI->getType()->isIntegerTy(64))
980 MarkFromHandle(CI->getArgOperand(0));
981 }
982}
983
984void DXILResourceMap::populateRecordCounterDirection(Instruction &I) {
985 auto *CI = dyn_cast<CallInst>(&I);
986 if (!CI || CI->getIntrinsicID() != Intrinsic::dx_resource_updatecounter)
987 return;
988 ConstantInt *CountValue = cast<ConstantInt>(CI->getArgOperand(1));
989 int64_t CountLiteral = CountValue->getSExtValue();
990 if (CountLiteral == 0)
991 return;
993 CountLiteral > 0 ? ResourceCounterDirection::Increment
995 for (ResourceInfo *RBInfo : findByUse(CI->getArgOperand(0))) {
996 if (RBInfo->CounterDirection == ResourceCounterDirection::Unknown)
997 RBInfo->CounterDirection = Direction;
998 else if (RBInfo->CounterDirection != Direction) {
999 RBInfo->CounterDirection = ResourceCounterDirection::Invalid;
1000 HasInvalidDirection = true;
1001 }
1002 }
1003}
1004
1005void DXILResourceMap::populateFromInstructions(Module &M) {
1006 for (Function &F : M.functions()) {
1007 for (Instruction &I : instructions(F)) {
1008 populateAtomicUses(I);
1009 populateRecordCounterDirection(I);
1010 }
1011 }
1012}
1013
1014void DXILResourceMap::populate(Module &M, DXILResourceTypeMap &DRTM) {
1015 populateResourceInfos(M, DRTM);
1016 populateFromInstructions(M);
1017}
1018
1020 const DataLayout &DL) const {
1021 for (unsigned I = 0, E = Infos.size(); I != E; ++I) {
1022 OS << "Resource " << I << ":\n";
1023 const dxil::ResourceInfo &RI = Infos[I];
1024 RI.print(OS, DRTM[RI.getHandleTy()], DL);
1025 OS << "\n";
1026 }
1027
1028 for (const auto &[CI, Index] : CallMap) {
1029 OS << "Call bound to " << Index << ":";
1030 CI->print(OS);
1031 OS << "\n";
1032 }
1033}
1034
1035SmallVector<dxil::ResourceInfo *> DXILResourceMap::findByUse(const Value *Key) {
1036 if (const PHINode *Phi = dyn_cast<PHINode>(Key)) {
1038 for (const Value *V : Phi->operands()) {
1039 Children.append(findByUse(V));
1040 }
1041 return Children;
1042 }
1043
1044 const CallInst *CI = dyn_cast<CallInst>(Key);
1045 if (!CI)
1046 return {};
1047
1048 switch (CI->getIntrinsicID()) {
1049 // Found the create, return the binding
1050 case Intrinsic::dx_resource_handlefrombinding: {
1051 auto Pos = CallMap.find(CI);
1052 assert(Pos != CallMap.end() && "HandleFromBinding must be in resource map");
1053 return {&Infos[Pos->second]};
1054 }
1055 default:
1056 break;
1057 }
1058
1059 // Check if any of the parameters are the resource we are following. If so
1060 // keep searching. If none of them are return an empty list
1061 const Type *UseType = CI->getType();
1063 for (const Value *V : CI->args()) {
1064 if (V->getType() != UseType)
1065 continue;
1066
1067 Children.append(findByUse(V));
1068 }
1069
1070 return Children;
1071}
1072
1073//===----------------------------------------------------------------------===//
1074
1075void DXILResourceBindingInfo::populate(Module &M, DXILResourceTypeMap &DRTM) {
1076 hlsl::BindingInfoBuilder Builder;
1077
1078 // collect all of the llvm.dx.resource.handlefrombinding calls;
1079 // make a note if there is llvm.dx.resource.handlefromimplicitbinding
1080 for (Function &F : M.functions()) {
1081 if (!F.isDeclaration())
1082 continue;
1083
1084 switch (F.getIntrinsicID()) {
1085 default:
1086 continue;
1087 case Intrinsic::dx_resource_handlefrombinding: {
1088 auto *HandleTy = cast<TargetExtType>(F.getReturnType());
1089 ResourceTypeInfo &RTI = DRTM[HandleTy];
1090
1091 for (User *U : F.users())
1092 if (CallInst *CI = dyn_cast<CallInst>(U)) {
1093 uint32_t Space =
1094 cast<ConstantInt>(CI->getArgOperand(0))->getZExtValue();
1095 uint32_t LowerBound =
1096 cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
1097 uint32_t Size =
1098 cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
1099 Value *Name = CI->getArgOperand(4);
1100
1101 // 0 size means unbounded resource array;
1102 // upper bound register overflow should be detected in Sema
1103 assert((Size == 0 || (uint64_t)LowerBound + (uint64_t)Size - 1ULL <=
1104 (uint64_t)UINT32_MAX) &&
1105 "upper bound register overflow");
1106 uint32_t UpperBound = Size == 0 ? UINT32_MAX : LowerBound + Size - 1;
1107 Builder.trackBinding(RTI.getResourceClass(), Space, LowerBound,
1108 UpperBound, Name);
1109 }
1110 break;
1111 }
1112 case Intrinsic::dx_resource_handlefromimplicitbinding: {
1113 HasImplicitBinding = true;
1114 break;
1115 }
1116 }
1117 }
1118
1119 Bindings = Builder.calculateBindingInfo(
1120 [this](auto, auto) { this->HasOverlappingBinding = true; });
1121}
1122
1123//===----------------------------------------------------------------------===//
1124
1125AnalysisKey DXILResourceTypeAnalysis::Key;
1126AnalysisKey DXILResourceAnalysis::Key;
1127AnalysisKey DXILResourceBindingAnalysis::Key;
1128
1136
1144
1149
1150 DRM.print(OS, DRTM, M.getDataLayout());
1151 return PreservedAnalyses::all();
1152}
1153
1154void DXILResourceTypeWrapperPass::anchor() {}
1155
1158
1159INITIALIZE_PASS(DXILResourceTypeWrapperPass, "dxil-resource-type",
1160 "DXIL Resource Type Analysis", false, true)
1162
1164 return new DXILResourceTypeWrapperPass();
1165}
1166
1168
1170
1175
1177 Map.reset(new DXILResourceMap());
1178
1179 DRTM = &getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();
1180 Map->populate(M, *DRTM);
1181
1182 return false;
1183}
1184
1186
1188 if (!Map) {
1189 OS << "No resource map has been built!\n";
1190 return;
1191 }
1192 Map->print(OS, *DRTM, M->getDataLayout());
1193}
1194
1195#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1197void DXILResourceWrapperPass::dump() const { print(dbgs(), nullptr); }
1198#endif
1199
1201 "DXIL Resources Analysis", false, true)
1203
1205 return new DXILResourceWrapperPass();
1206}
1207
1210
1212
1217
1219 BindingInfo.reset(new DXILResourceBindingInfo());
1220
1221 DXILResourceTypeMap &DRTM =
1222 getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();
1223 BindingInfo->populate(M, DRTM);
1224
1225 return false;
1226}
1227
1229
1230INITIALIZE_PASS(DXILResourceBindingWrapperPass, "dxil-resource-binding",
1231 "DXIL Resource Binding Analysis", false, true)
1233
1235 return new DXILResourceWrapperPass();
1236}
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
Expand Atomic instructions
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:678
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static dxil::ElementType toDXILElementType(Type *Ty, bool IsSigned)
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)
static Value * findResourceHandleFromPointer(Value *Ptr)
Hexagon Common GEP
Module.h This file contains the declarations for the Module class.
Loop::LoopBounds::Direction Direction
Definition LoopInfo.cpp:253
#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.
uint64_t IntrinsicInst * II
#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:119
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:537
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:174
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:64
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:246
@ 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:1567
static LLVM_ABI MDString * get(LLVMContext &Context, StringRef Str)
Definition Metadata.cpp:615
Tuple of metadata.
Definition Metadata.h:1484
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.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
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:477
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:802
static LLVM_ABI StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
Definition Type.cpp:683
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:46
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:309
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
Definition Type.h:130
static LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)
Definition Type.cpp:306
static LLVM_ABI ValueAsMetadata * get(Value *V)
Definition Metadata.cpp:510
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:255
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
Definition Value.cpp:713
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.
LLVM_ABI StringRef getResourceClassName(ResourceClass RC)
Definition DXILABI.cpp:21
ResourceKind
The kind of resource for an SRV or UAV resource.
Definition DXILABI.h:44
SamplerFeedbackType
Definition DXILABI.h:105
ElementType
The element type of an SRV or UAV resource.
Definition DXILABI.h:68
LLVM_ABI StringRef getResourceNameFromBindingCall(CallInst *CI)
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI ModulePass * createDXILResourceBindingWrapperPassPass()
void stable_sort(R &&Range)
Definition STLExtras.h:2116
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()
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
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:209
constexpr std::underlying_type_t< Enum > to_underlying(Enum E)
Returns underlying integer value of an enum.
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
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
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