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"
15#include "llvm/IR/Constants.h"
21#include "llvm/IR/Intrinsics.h"
22#include "llvm/IR/IntrinsicsDirectX.h"
23#include "llvm/IR/Metadata.h"
24#include "llvm/IR/Module.h"
28#include <cstdint>
29
30#define DEBUG_TYPE "dxil-resource"
31
32using namespace llvm;
33using namespace dxil;
34
36 switch (RK) {
37 case ResourceKind::Texture1D:
38 return "Texture1D";
39 case ResourceKind::Texture2D:
40 return "Texture2D";
41 case ResourceKind::Texture2DMS:
42 return "Texture2DMS";
43 case ResourceKind::Texture3D:
44 return "Texture3D";
45 case ResourceKind::TextureCube:
46 return "TextureCube";
47 case ResourceKind::Texture1DArray:
48 return "Texture1DArray";
49 case ResourceKind::Texture2DArray:
50 return "Texture2DArray";
51 case ResourceKind::Texture2DMSArray:
52 return "Texture2DMSArray";
53 case ResourceKind::TextureCubeArray:
54 return "TextureCubeArray";
55 case ResourceKind::TypedBuffer:
56 return "Buffer";
57 case ResourceKind::RawBuffer:
58 return "RawBuffer";
59 case ResourceKind::StructuredBuffer:
60 return "StructuredBuffer";
61 case ResourceKind::CBuffer:
62 return "CBuffer";
63 case ResourceKind::Sampler:
64 return "Sampler";
65 case ResourceKind::TBuffer:
66 return "TBuffer";
67 case ResourceKind::RTAccelerationStructure:
68 return "RTAccelerationStructure";
69 case ResourceKind::FeedbackTexture2D:
70 return "FeedbackTexture2D";
71 case ResourceKind::FeedbackTexture2DArray:
72 return "FeedbackTexture2DArray";
73 case ResourceKind::NumEntries:
74 case ResourceKind::Invalid:
75 return "<invalid>";
76 }
77 llvm_unreachable("Unhandled ResourceKind");
78}
79
81 switch (ET) {
82 case ElementType::I1:
83 return "i1";
84 case ElementType::I16:
85 return "i16";
86 case ElementType::U16:
87 return "u16";
88 case ElementType::I32:
89 return "i32";
90 case ElementType::U32:
91 return "u32";
92 case ElementType::I64:
93 return "i64";
94 case ElementType::U64:
95 return "u64";
96 case ElementType::F16:
97 return "f16";
98 case ElementType::F32:
99 return "f32";
100 case ElementType::F64:
101 return "f64";
102 case ElementType::SNormF16:
103 return "snorm_f16";
104 case ElementType::UNormF16:
105 return "unorm_f16";
106 case ElementType::SNormF32:
107 return "snorm_f32";
108 case ElementType::UNormF32:
109 return "unorm_f32";
110 case ElementType::SNormF64:
111 return "snorm_f64";
112 case ElementType::UNormF64:
113 return "unorm_f64";
114 case ElementType::PackedS8x32:
115 return "p32i8";
116 case ElementType::PackedU8x32:
117 return "p32u8";
118 case ElementType::Invalid:
119 return "<invalid>";
120 }
121 llvm_unreachable("Unhandled ElementType");
122}
123
125 switch (ET) {
126 case ElementType::I1:
127 return "bool";
128 case ElementType::I16:
129 return "int16_t";
130 case ElementType::U16:
131 return "uint16_t";
132 case ElementType::I32:
133 return "int32_t";
134 case ElementType::U32:
135 return "uint32_t";
136 case ElementType::I64:
137 return "int64_t";
138 case ElementType::U64:
139 return "uint32_t";
140 case ElementType::F16:
141 case ElementType::SNormF16:
142 case ElementType::UNormF16:
143 return "half";
144 case ElementType::F32:
145 case ElementType::SNormF32:
146 case ElementType::UNormF32:
147 return "float";
148 case ElementType::F64:
149 case ElementType::SNormF64:
150 case ElementType::UNormF64:
151 return "double";
152 case ElementType::PackedS8x32:
153 return "int8_t4_packed";
154 case ElementType::PackedU8x32:
155 return "uint8_t4_packed";
156 case ElementType::Invalid:
157 return "<invalid>";
158 }
159 llvm_unreachable("Unhandled ElementType");
160}
161
163 switch (ST) {
164 case SamplerType::Default:
165 return "Default";
166 case SamplerType::Comparison:
167 return "Comparison";
168 case SamplerType::Mono:
169 return "Mono";
170 }
171 llvm_unreachable("Unhandled SamplerType");
172}
173
175 switch (SFT) {
176 case SamplerFeedbackType::MinMip:
177 return "MinMip";
178 case SamplerFeedbackType::MipRegionUsed:
179 return "MipRegionUsed";
180 }
181 llvm_unreachable("Unhandled SamplerFeedbackType");
182}
183
191
193 const dxil::ResourceClass RC_,
194 const dxil::ResourceKind Kind_)
195 : HandleTy(HandleTy) {
196 // If we're provided a resource class and kind, trust them.
197 if (Kind_ != dxil::ResourceKind::Invalid) {
198 RC = RC_;
199 Kind = Kind_;
200 return;
201 }
202
203 if (auto *Ty = dyn_cast<RawBufferExtType>(HandleTy)) {
204 RC = Ty->isWriteable() ? ResourceClass::UAV : ResourceClass::SRV;
205 Kind = Ty->isStructured() ? ResourceKind::StructuredBuffer
207 } else if (auto *Ty = dyn_cast<TypedBufferExtType>(HandleTy)) {
208 RC = Ty->isWriteable() ? ResourceClass::UAV : ResourceClass::SRV;
210 } else if (auto *Ty = dyn_cast<TextureExtType>(HandleTy)) {
211 RC = Ty->isWriteable() ? ResourceClass::UAV : ResourceClass::SRV;
212 Kind = Ty->getDimension();
213 } else if (auto *Ty = dyn_cast<MSTextureExtType>(HandleTy)) {
214 RC = Ty->isWriteable() ? ResourceClass::UAV : ResourceClass::SRV;
215 Kind = Ty->getDimension();
216 } else if (auto *Ty = dyn_cast<FeedbackTextureExtType>(HandleTy)) {
218 Kind = Ty->getDimension();
219 } else if (isa<CBufferExtType>(HandleTy)) {
222 } else if (isa<SamplerExtType>(HandleTy)) {
225 } else
226 llvm_unreachable("Unknown handle type");
227}
228
230 bool IsWriteable, bool IsROV,
231 Type *ContainedType = nullptr,
232 bool IsSigned = true) {
233 raw_svector_ostream DestStream(Dest);
234 if (IsWriteable)
235 DestStream << (IsROV ? "RasterizerOrdered" : "RW");
236 DestStream << Name;
237
238 if (!ContainedType)
239 return;
240
241 SmallVector<uint64_t> ArrayDimensions;
242 while (ArrayType *AT = dyn_cast<ArrayType>(ContainedType)) {
243 ArrayDimensions.push_back(AT->getNumElements());
244 ContainedType = AT->getElementType();
245 }
246
247 StringRef ElementName;
248 ElementType ET = hlsl::getDXILElementType(ContainedType, IsSigned);
249 if (ET != ElementType::Invalid) {
250 ElementName = getElementTypeNameForTemplate(ET);
251 } else {
252 assert(isa<StructType>(ContainedType) &&
253 "invalid element type for raw buffer");
254 StructType *ST = cast<StructType>(ContainedType);
255 if (!ST->hasName())
256 return;
257 ElementName = ST->getStructName();
258 }
259
260 DestStream << "<" << ElementName;
261 if (const FixedVectorType *VTy = dyn_cast<FixedVectorType>(ContainedType))
262 DestStream << VTy->getNumElements();
263 for (uint64_t Dim : ArrayDimensions)
264 DestStream << "[" << Dim << "]";
265 DestStream << ">";
266}
267
269 StructType *Ty = StructType::getTypeByName(ElemType->getContext(), Name);
270 if (Ty && Ty->getNumElements() == 1 && Ty->getElementType(0) == ElemType)
271 return Ty;
272 return StructType::create(ElemType, Name);
273}
274
276 // Recursively remove padding from structures.
277 if (auto *ST = dyn_cast<StructType>(Ty)) {
278 LLVMContext &Ctx = Ty->getContext();
279 SmallVector<Type *> ElementTypes;
280 ElementTypes.reserve(ST->getNumElements());
281 for (Type *ElTy : ST->elements()) {
282 if (isa<PaddingExtType>(ElTy))
283 continue;
284 ElementTypes.push_back(getTypeWithoutPadding(ElTy));
285 }
286
287 // Handle explicitly padded cbuffer arrays like { [ n x paddedty ], ty }
288 if (ElementTypes.size() == 2)
289 if (auto *AT = dyn_cast<ArrayType>(ElementTypes[0]))
290 if (ElementTypes[1] == AT->getElementType())
291 return ArrayType::get(ElementTypes[1], AT->getNumElements() + 1);
292
293 // If we only have a single element, don't wrap it in a struct.
294 if (ElementTypes.size() == 1)
295 return ElementTypes[0];
296
297 return StructType::get(Ctx, ElementTypes, /*IsPacked=*/false);
298 }
299 // Arrays just need to have their element type adjusted.
300 if (auto *AT = dyn_cast<ArrayType>(Ty))
301 return ArrayType::get(getTypeWithoutPadding(AT->getElementType()),
302 AT->getNumElements());
303 // Anything else should be good as is.
304 return Ty;
305}
306
308 SmallString<64> TypeName;
309
310 switch (Kind) {
318 auto *RTy = cast<TextureExtType>(HandleTy);
319 formatTypeName(TypeName, getResourceKindName(Kind), RTy->isWriteable(),
320 RTy->isROV(), RTy->getResourceType(), RTy->isSigned());
321 return getOrCreateElementStruct(RTy->getResourceType(), TypeName);
322 }
325 auto *RTy = cast<MSTextureExtType>(HandleTy);
326 formatTypeName(TypeName, getResourceKindName(Kind), RTy->isWriteable(),
327 /*IsROV=*/false, RTy->getResourceType(), RTy->isSigned());
328 return getOrCreateElementStruct(RTy->getResourceType(), TypeName);
329 }
331 auto *RTy = cast<TypedBufferExtType>(HandleTy);
332 formatTypeName(TypeName, getResourceKindName(Kind), RTy->isWriteable(),
333 RTy->isROV(), RTy->getResourceType(), RTy->isSigned());
334 return getOrCreateElementStruct(RTy->getResourceType(), TypeName);
335 }
337 auto *RTy = cast<RawBufferExtType>(HandleTy);
338 formatTypeName(TypeName, "ByteAddressBuffer", RTy->isWriteable(),
339 RTy->isROV());
340 return getOrCreateElementStruct(Type::getInt32Ty(HandleTy->getContext()),
341 TypeName);
342 }
344 auto *RTy = cast<RawBufferExtType>(HandleTy);
345 Type *Ty = RTy->getResourceType();
346 formatTypeName(TypeName, "StructuredBuffer", RTy->isWriteable(),
347 RTy->isROV(), RTy->getResourceType(), true);
348 return getOrCreateElementStruct(Ty, TypeName);
349 }
352 auto *RTy = cast<FeedbackTextureExtType>(HandleTy);
353 TypeName = formatv("{0}<{1}>", getResourceKindName(Kind),
354 llvm::to_underlying(RTy->getFeedbackType()));
355 return getOrCreateElementStruct(Type::getInt32Ty(HandleTy->getContext()),
356 TypeName);
357 }
359 auto *RTy = cast<CBufferExtType>(HandleTy);
361 if (!CBufferName.empty()) {
362 Name.append(".");
363 Name.append(CBufferName);
364 }
365
366 // TODO: Remove this when we update the frontend to use explicit padding.
367 if (LayoutExtType *LayoutType =
368 dyn_cast<LayoutExtType>(RTy->getResourceType())) {
369 StructType *Ty = cast<StructType>(LayoutType->getWrappedType());
370 return StructType::create(Ty->elements(), Name);
371 }
372
374 getTypeWithoutPadding(RTy->getResourceType()), Name);
375 }
377 auto *RTy = cast<SamplerExtType>(HandleTy);
378 TypeName = formatv("SamplerState<{0}>",
379 llvm::to_underlying(RTy->getSamplerType()));
380 return getOrCreateElementStruct(Type::getInt32Ty(HandleTy->getContext()),
381 TypeName);
382 }
385 llvm_unreachable("Unhandled resource kind");
388 llvm_unreachable("Invalid resource kind");
389 }
390 llvm_unreachable("Unhandled ResourceKind enum");
391}
392
393bool ResourceTypeInfo::isUAV() const { return RC == ResourceClass::UAV; }
394
396 return RC == ResourceClass::CBuffer;
397}
398
400 return RC == ResourceClass::Sampler;
401}
402
404 return Kind == ResourceKind::StructuredBuffer;
405}
406
435
440
445
446static bool isROV(dxil::ResourceKind Kind, TargetExtType *Ty) {
447 switch (Kind) {
455 return cast<TextureExtType>(Ty)->isROV();
457 return cast<TypedBufferExtType>(Ty)->isROV();
460 return cast<RawBufferExtType>(Ty)->isROV();
465 return false;
472 llvm_unreachable("Resource cannot be ROV");
473 }
474 llvm_unreachable("Unhandled ResourceKind enum");
475}
476
478 assert(isUAV() && "Not a UAV");
479 return {isROV(Kind, HandleTy)};
480}
481
483 assert(isCBuffer() && "Not a CBuffer");
484
485 Type *ElTy = cast<CBufferExtType>(HandleTy)->getResourceType();
486
487 // TODO: Remove this when we update the frontend to use explicit padding.
488 if (auto *LayoutTy = dyn_cast<LayoutExtType>(ElTy))
489 return LayoutTy->getSize();
490
491 return DL.getTypeAllocSize(ElTy);
492}
493
495 assert(isSampler() && "Not a Sampler");
496 return cast<SamplerExtType>(HandleTy)->getSamplerType();
497}
498
501 assert(isStruct() && "Not a Struct");
502
503 Type *ElTy = cast<RawBufferExtType>(HandleTy)->getResourceType();
504
505 uint32_t Stride = DL.getTypeAllocSize(ElTy);
506 MaybeAlign Alignment;
507 if (auto *STy = dyn_cast<StructType>(ElTy))
508 Alignment = DL.getStructLayout(STy)->getAlignment();
509 uint32_t AlignLog2 = Alignment ? Log2(*Alignment) : 0;
510 return {Stride, AlignLog2};
511}
512
513static std::pair<Type *, bool> getTypedElementType(dxil::ResourceKind Kind,
514 TargetExtType *Ty) {
515 switch (Kind) {
523 auto *RTy = cast<TextureExtType>(Ty);
524 return {RTy->getResourceType(), RTy->isSigned()};
525 }
528 auto *RTy = cast<MSTextureExtType>(Ty);
529 return {RTy->getResourceType(), RTy->isSigned()};
530 }
532 auto *RTy = cast<TypedBufferExtType>(Ty);
533 return {RTy->getResourceType(), RTy->isSigned()};
534 }
545 llvm_unreachable("Resource is not typed");
546 }
547 llvm_unreachable("Unhandled ResourceKind enum");
548}
549
551 assert(isTyped() && "Not typed");
552
553 auto [ElTy, IsSigned] = getTypedElementType(Kind, HandleTy);
554 dxil::ElementType ET = hlsl::getDXILElementType(ElTy, IsSigned);
555 dxil::ElementType DXILStorageTy = toDXILStorageType(ET);
556 uint32_t Count = 1;
557 if (auto *VTy = dyn_cast<FixedVectorType>(ElTy))
558 Count = VTy->getNumElements();
559 return {ET, DXILStorageTy, Count};
560}
561
563 assert(isFeedback() && "Not Feedback");
564 return cast<FeedbackTextureExtType>(HandleTy)->getFeedbackType();
565}
567 assert(isMultiSample() && "Not MultiSampled");
568 return cast<MSTextureExtType>(HandleTy)->getSampleCount();
569}
570
572 return HandleTy == RHS.HandleTy;
573}
574
576 // An empty datalayout is sufficient for sorting purposes.
577 DataLayout DummyDL;
578 if (std::tie(RC, Kind) < std::tie(RHS.RC, RHS.Kind))
579 return true;
580 if (isCBuffer() && RHS.isCBuffer() &&
581 getCBufferSize(DummyDL) < RHS.getCBufferSize(DummyDL))
582 return true;
583 if (isSampler() && RHS.isSampler() && getSamplerType() < RHS.getSamplerType())
584 return true;
585 if (isUAV() && RHS.isUAV() && getUAV() < RHS.getUAV())
586 return true;
587 if (isStruct() && RHS.isStruct() &&
588 getStruct(DummyDL) < RHS.getStruct(DummyDL))
589 return true;
590 if (isFeedback() && RHS.isFeedback() &&
591 getFeedbackType() < RHS.getFeedbackType())
592 return true;
593 if (isTyped() && RHS.isTyped() && getTyped() < RHS.getTyped())
594 return true;
595 if (isMultiSample() && RHS.isMultiSample() &&
596 getMultiSampleCount() < RHS.getMultiSampleCount())
597 return true;
598 return false;
599}
600
602 OS << " Class: " << getResourceClassName(RC) << "\n"
603 << " Kind: " << getResourceKindName(Kind) << "\n";
604
605 if (isCBuffer()) {
606 OS << " CBuffer size: " << getCBufferSize(DL) << "\n";
607 } else if (isSampler()) {
608 OS << " Sampler Type: " << getSamplerTypeName(getSamplerType()) << "\n";
609 } else {
610 if (isUAV()) {
611 UAVInfo UAVFlags = getUAV();
612 OS << " IsROV: " << UAVFlags.IsROV << "\n";
613 }
614 if (isMultiSample())
615 OS << " Sample Count: " << getMultiSampleCount() << "\n";
616
617 if (isStruct()) {
618 StructInfo Struct = getStruct(DL);
619 OS << " Buffer Stride: " << Struct.Stride << "\n";
620 OS << " Alignment: " << Struct.AlignLog2 << "\n";
621 } else if (isTyped()) {
622 TypedInfo Typed = getTyped();
623 OS << " Element Type: " << getElementTypeName(Typed.ElementTy);
624 if (Typed.ElementTy != Typed.DXILStorageTy)
625 OS << " (stored as " << getElementTypeName(Typed.DXILStorageTy) << ")";
626 OS << "\n"
627 << " Element Count: " << Typed.ElementCount << "\n";
628 } else if (isFeedback())
629 OS << " Feedback Type: " << getSamplerFeedbackTypeName(getFeedbackType())
630 << "\n";
631 }
632}
633
635 assert(!Symbol && "Symbol has already been created");
636 Type *ResTy = Ty;
637 int64_t Size = getSize();
638 if (Size != 1)
639 // unbounded arrays are represented as zero-sized arrays in LLVM IR
640 ResTy = ArrayType::get(Ty, Size == ~0u ? 0 : Size);
641 Symbol = new GlobalVariable(M, ResTy, /*isConstant=*/true,
643 /*Initializer=*/nullptr, Name);
644 return Symbol;
645}
646
648 dxil::ResourceTypeInfo &RTI) const {
649 assert(hasBinding() && "Resource must not be from heap to get metadata");
650 const ResourceBinding &Binding = getBinding();
651
652 LLVMContext &Ctx = M.getContext();
653 const DataLayout &DL = M.getDataLayout();
654
656
657 Type *I32Ty = Type::getInt32Ty(Ctx);
658 Type *I1Ty = Type::getInt1Ty(Ctx);
659 auto getIntMD = [&I32Ty](uint32_t V) {
661 Constant::getIntegerValue(I32Ty, APInt(32, V)));
662 };
663 auto getBoolMD = [&I1Ty](uint32_t V) {
665 Constant::getIntegerValue(I1Ty, APInt(1, V)));
666 };
667
668 MDVals.push_back(getIntMD(Binding.BindingID));
669 assert(Symbol && "Cannot yet create useful resource metadata without symbol");
670 MDVals.push_back(ValueAsMetadata::get(Symbol));
671 MDVals.push_back(MDString::get(Ctx, Name));
672 MDVals.push_back(getIntMD(Binding.Space));
673 MDVals.push_back(getIntMD(Binding.LowerBound));
674 MDVals.push_back(getIntMD(Binding.Size == 0 ? ~0u : Binding.Size));
675
676 if (RTI.isCBuffer()) {
677 MDVals.push_back(getIntMD(RTI.getCBufferSize(DL)));
678 MDVals.push_back(nullptr);
679 } else if (RTI.isSampler()) {
680 MDVals.push_back(getIntMD(llvm::to_underlying(RTI.getSamplerType())));
681 MDVals.push_back(nullptr);
682 } else {
683 MDVals.push_back(getIntMD(llvm::to_underlying(RTI.getResourceKind())));
684
685 if (RTI.isUAV()) {
686 ResourceTypeInfo::UAVInfo UAVFlags = RTI.getUAV();
687 MDVals.push_back(getBoolMD(GloballyCoherent));
688 MDVals.push_back(getBoolMD(hasCounter()));
689 MDVals.push_back(getBoolMD(UAVFlags.IsROV));
690 } else {
691 // All SRVs include sample count in the metadata, but it's only meaningful
692 // for multi-sampled textured. Also, UAVs can be multisampled in SM6.7+,
693 // but this just isn't reflected in the metadata at all.
694 uint32_t SampleCount =
695 RTI.isMultiSample() ? RTI.getMultiSampleCount() : 0;
696 MDVals.push_back(getIntMD(SampleCount));
697 }
698
699 // Further properties are attached to a metadata list of tag-value pairs.
701 if (RTI.isStruct()) {
702 Tags.push_back(
704 Tags.push_back(getIntMD(RTI.getStruct(DL).Stride));
705 } else if (RTI.isTyped()) {
707 Tags.push_back(
709 } else if (RTI.isFeedback()) {
710 Tags.push_back(
712 Tags.push_back(getIntMD(llvm::to_underlying(RTI.getFeedbackType())));
713 }
714 MDVals.push_back(Tags.empty() ? nullptr : MDNode::get(Ctx, Tags));
715 }
716
717 return MDNode::get(Ctx, MDVals);
718}
719
720std::pair<uint32_t, uint32_t>
722 const DataLayout &DL = M.getDataLayout();
723
725 uint32_t AlignLog2 = RTI.isStruct() ? RTI.getStruct(DL).AlignLog2 : 0;
726 bool IsUAV = RTI.isUAV();
728 IsUAV ? RTI.getUAV() : ResourceTypeInfo::UAVInfo{};
729 bool IsROV = IsUAV && UAVFlags.IsROV;
730 bool IsGloballyCoherent = IsUAV && GloballyCoherent;
731 uint8_t SamplerCmpOrHasCounter = 0;
732 if (IsUAV)
733 SamplerCmpOrHasCounter = hasCounter();
734 else if (RTI.isSampler())
735 SamplerCmpOrHasCounter = RTI.getSamplerType() == SamplerType::Comparison;
736
737 // TODO: Document this format. Currently the only reference is the
738 // implementation of dxc's DxilResourceProperties struct.
739 uint32_t Word0 = 0;
740 Word0 |= ResourceKind & 0xFF;
741 Word0 |= (AlignLog2 & 0xF) << 8;
742 Word0 |= (IsUAV & 1) << 12;
743 Word0 |= (IsROV & 1) << 13;
744 Word0 |= (IsGloballyCoherent & 1) << 14;
745 Word0 |= (SamplerCmpOrHasCounter & 1) << 15;
746
747 uint32_t Word1 = 0;
748 if (RTI.isStruct())
749 Word1 = RTI.getStruct(DL).Stride;
750 else if (RTI.isCBuffer())
751 Word1 = RTI.getCBufferSize(DL);
752 else if (RTI.isFeedback())
754 else if (RTI.isTyped()) {
756 uint32_t CompType = llvm::to_underlying(Typed.ElementTy);
757 uint32_t CompCount = Typed.ElementCount;
758 uint32_t SampleCount = RTI.isMultiSample() ? RTI.getMultiSampleCount() : 0;
759
760 Word1 |= (CompType & 0xFF) << 0;
761 Word1 |= (CompCount & 0xFF) << 8;
762 Word1 |= (SampleCount & 0xFF) << 16;
763 }
764
765 return {Word0, Word1};
766}
767
769 const DataLayout &DL) const {
770 if (!Name.empty())
771 OS << " Name: " << Name << "\n";
772
773 if (Symbol) {
774 OS << " Symbol: ";
775 Symbol->printAsOperand(OS);
776 OS << "\n";
777 }
778
779 if (hasBinding()) {
780 const ResourceBinding &Binding = getBinding();
781 OS << " Binding:\n"
782 << " Binding ID: " << Binding.BindingID << "\n"
783 << " Space: " << Binding.Space << "\n"
784 << " Lower Bound: " << Binding.LowerBound << "\n"
785 << " Size: " << Binding.Size << "\n";
786 } else {
787 OS << " HeapIndexID: " << getHeapID() << "\n";
788 }
789
790 OS << " Globally Coherent: " << GloballyCoherent << "\n";
791 OS << " Has Atomic64 Use: " << HasAtomic64Use << "\n";
792 OS << " Counter Direction: ";
793
794 switch (CounterDirection) {
796 OS << "Increment\n";
797 break;
799 OS << "Decrement\n";
800 break;
802 OS << "Unknown\n";
803 break;
805 OS << "Invalid\n";
806 break;
807 }
808
809 RTI.print(OS, DL);
810}
811
812//===----------------------------------------------------------------------===//
813
815 ModuleAnalysisManager::Invalidator &Inv) {
816 // Passes that introduce resource types must explicitly invalidate this pass.
817 auto PAC = PA.getChecker<DXILResourceTypeAnalysis>();
818 return !PAC.preservedWhenStateless();
819}
820
821//===----------------------------------------------------------------------===//
823 Value *Op = nullptr;
824 switch (CI->getCalledFunction()->getIntrinsicID()) {
825 default:
826 llvm_unreachable("unexpected handle creation intrinsic");
827 case Intrinsic::dx_resource_handlefrombinding:
828 case Intrinsic::dx_resource_handlefromimplicitbinding:
829 Op = CI->getArgOperand(4);
830 break;
831 }
832
834 if (!GV)
835 return "";
836
837 auto *CA = dyn_cast<ConstantDataArray>(GV->getInitializer());
838 assert(CA && CA->isString() && "expected constant string");
839 StringRef Name = CA->getAsString();
840 // strip trailing 0
841 if (Name.ends_with('\0'))
842 Name = Name.drop_back(1);
843 return Name;
844}
845
846void DXILResourceMap::populateResourceInfos(Module &M,
847 DXILResourceTypeMap &DRTM) {
849
850 // We need to assign a unique ID to each resource that is created
851 // from a heap. The ID must be unique for each unique Index value so
852 // we can differentiate between resources instances of the same type.
854 uint32_t NextHeapResID = 0;
855
856 for (Function &F : M.functions()) {
857 if (!F.isDeclaration())
858 continue;
859 LLVM_DEBUG(dbgs() << "Function: " << F.getName() << "\n");
860 Intrinsic::ID ID = F.getIntrinsicID();
861 switch (ID) {
862 default:
863 continue;
864 case Intrinsic::dx_resource_handlefrombinding: {
865 auto *HandleTy = cast<TargetExtType>(F.getReturnType());
866 ResourceTypeInfo &RTI = DRTM[HandleTy];
867
868 for (User *U : F.users())
869 if (CallInst *CI = dyn_cast<CallInst>(U)) {
870 LLVM_DEBUG(dbgs() << " Visiting: " << *U << "\n");
871 uint32_t Space =
872 cast<ConstantInt>(CI->getArgOperand(0))->getZExtValue();
873 uint32_t LowerBound =
874 cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
875 uint32_t Size =
876 cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
878
879 ResourceInfo RI =
880 ResourceInfo{Space, LowerBound, Size, HandleTy, Name};
881
882 CIToInfos.emplace_back(CI, RI, RTI);
883 }
884
885 break;
886 }
887 case Intrinsic::dx_resource_handlefromheap: {
888 auto *HandleTy = cast<TargetExtType>(F.getReturnType());
889 ResourceTypeInfo &RTI = DRTM[HandleTy];
890
891 for (User *U : F.users()) {
892 if (CallInst *CI = dyn_cast<CallInst>(U)) {
893 LLVM_DEBUG(dbgs() << " Visiting: " << *U << "\n");
894 Value *Index = CI->getArgOperand(0);
895 uint32_t HeapResID;
896 auto Pos = IndexToHeapResID.find(Index);
897 if (Pos == IndexToHeapResID.end()) {
898 HeapResID = NextHeapResID++;
899 IndexToHeapResID[Index] = HeapResID;
900 } else {
901 HeapResID = Pos->second;
902 }
903 ResourceInfo RI = ResourceInfo{HeapResID, HandleTy};
904 CIToInfos.emplace_back(CI, RI, RTI);
905 }
906 }
907 break;
908 }
909 }
910 }
911
912 llvm::stable_sort(CIToInfos, [](auto &LHS, auto &RHS) {
913 const auto &[LCI, LRI, LRTI] = LHS;
914 const auto &[RCI, RRI, RRTI] = RHS;
915 // Sort by resource class first for grouping purposes, and then by the
916 // binding and type so we can remove duplicates.
917 ResourceClass LRC = LRTI.getResourceClass();
918 ResourceClass RRC = RRTI.getResourceClass();
919
920 return std::tie(LRC, LRI, LRTI) < std::tie(RRC, RRI, RRTI);
921 });
922 for (auto [CI, RI, RTI] : CIToInfos) {
923 if (Infos.empty() || RI != Infos.back())
924 Infos.push_back(RI);
925 CallMap[CI] = Infos.size() - 1;
926 }
927
928 unsigned Size = Infos.size();
929 // In DXC, Binding ID is unique per resource type. Match that.
930 FirstUAV = FirstCBuffer = FirstSampler = Size;
931 uint32_t NextID = 0;
932 for (unsigned I = 0, E = Size; I != E; ++I) {
933 ResourceInfo &RI = Infos[I];
934 ResourceTypeInfo &RTI = DRTM[RI.getHandleTy()];
935 if (RTI.isUAV() && FirstUAV == Size) {
936 FirstUAV = I;
937 NextID = 0;
938 } else if (RTI.isCBuffer() && FirstCBuffer == Size) {
939 FirstCBuffer = I;
940 NextID = 0;
941 } else if (RTI.isSampler() && FirstSampler == Size) {
942 FirstSampler = I;
943 NextID = 0;
944 }
945
946 // We need to make sure the types of resource are ordered even if some are
947 // missing.
948 FirstCBuffer = std::min({FirstCBuffer, FirstSampler});
949 FirstUAV = std::min({FirstUAV, FirstCBuffer});
950
951 if (RI.hasBinding())
952 RI.setBindingID(NextID++);
953 }
954}
955
957 Ptr = Ptr->stripPointerCasts();
958 while (auto *GEP = dyn_cast<GetElementPtrInst>(Ptr))
959 Ptr = GEP->getPointerOperand()->stripPointerCasts();
960 auto *II = dyn_cast<IntrinsicInst>(Ptr);
961 if (II && II->getIntrinsicID() == Intrinsic::dx_resource_getpointer)
962 return II->getArgOperand(0);
963 return nullptr;
964}
965
966void DXILResourceMap::populateAtomicUses(Instruction &I) {
967 auto MarkFromHandle = [this](Value *Handle) {
968 if (!Handle)
969 return;
970 for (ResourceInfo *RI : findByUse(Handle))
971 RI->HasAtomic64Use = true;
972 };
973
974 // Handles both `atomicrmw`/`cmpxchg` (before `DXILResourceAccess`) and the
975 // lowered `llvm.dx.resource.atomic.binop` intrinsic (after it).
976 if (auto *AI = dyn_cast<AtomicRMWInst>(&I)) {
977 if (AI->getValOperand()->getType()->isIntegerTy(64))
978 MarkFromHandle(findResourceHandleFromPointer(AI->getPointerOperand()));
979 return;
980 }
981 if (auto *CX = dyn_cast<AtomicCmpXchgInst>(&I)) {
982 if (CX->getNewValOperand()->getType()->isIntegerTy(64))
983 MarkFromHandle(findResourceHandleFromPointer(CX->getPointerOperand()));
984 return;
985 }
986 if (auto *CI = dyn_cast<CallInst>(&I)) {
987 if (CI->getIntrinsicID() == Intrinsic::dx_resource_atomic_binop &&
988 CI->getType()->isIntegerTy(64))
989 MarkFromHandle(CI->getArgOperand(0));
990 }
991}
992
993void DXILResourceMap::populateRecordCounterDirection(Instruction &I) {
994 auto *CI = dyn_cast<CallInst>(&I);
995 if (!CI || CI->getIntrinsicID() != Intrinsic::dx_resource_updatecounter)
996 return;
997 ConstantInt *CountValue = cast<ConstantInt>(CI->getArgOperand(1));
998 int64_t CountLiteral = CountValue->getSExtValue();
999 if (CountLiteral == 0)
1000 return;
1002 CountLiteral > 0 ? ResourceCounterDirection::Increment
1004 for (ResourceInfo *RBInfo : findByUse(CI->getArgOperand(0))) {
1005 if (RBInfo->CounterDirection == ResourceCounterDirection::Unknown)
1006 RBInfo->CounterDirection = Direction;
1007 else if (RBInfo->CounterDirection != Direction) {
1008 RBInfo->CounterDirection = ResourceCounterDirection::Invalid;
1009 HasInvalidDirection = true;
1010 }
1011 }
1012}
1013
1014void DXILResourceMap::populateFromInstructions(Module &M) {
1015 for (Function &F : M.functions()) {
1016 for (Instruction &I : instructions(F)) {
1017 populateAtomicUses(I);
1018 populateRecordCounterDirection(I);
1019 }
1020 }
1021}
1022
1023void DXILResourceMap::populate(Module &M, DXILResourceTypeMap &DRTM) {
1024 populateResourceInfos(M, DRTM);
1025 populateFromInstructions(M);
1026}
1027
1029 const DataLayout &DL) const {
1030 for (unsigned I = 0, E = Infos.size(); I != E; ++I) {
1031 OS << "Resource " << I << ":\n";
1032 const dxil::ResourceInfo &RI = Infos[I];
1033 RI.print(OS, DRTM[RI.getHandleTy()], DL);
1034 OS << "\n";
1035 }
1036
1037 for (const auto &[CI, Index] : CallMap) {
1038 OS << "Call bound to " << Index << ":";
1039 CI->print(OS);
1040 OS << "\n";
1041 }
1042}
1043
1044SmallVector<dxil::ResourceInfo *> DXILResourceMap::findByUse(const Value *Key) {
1045 if (const PHINode *Phi = dyn_cast<PHINode>(Key)) {
1047 for (const Value *V : Phi->operands()) {
1048 Children.append(findByUse(V));
1049 }
1050 return Children;
1051 }
1052
1053 const CallInst *CI = dyn_cast<CallInst>(Key);
1054 if (!CI)
1055 return {};
1056
1057 switch (CI->getIntrinsicID()) {
1058 // Found the create, return the binding
1059 case Intrinsic::dx_resource_handlefrombinding:
1060 case Intrinsic::dx_resource_handlefromheap: {
1061 auto Pos = CallMap.find(CI);
1062 assert(Pos != CallMap.end() &&
1063 "handle initialization call must be in resource map");
1064 return {&Infos[Pos->second]};
1065 }
1066 default:
1067 break;
1068 }
1069
1070 // Check if any of the parameters are the resource we are following. If so
1071 // keep searching. If none of them are return an empty list
1072 const Type *UseType = CI->getType();
1074 for (const Value *V : CI->args()) {
1075 if (V->getType() != UseType)
1076 continue;
1077
1078 Children.append(findByUse(V));
1079 }
1080
1081 return Children;
1082}
1083
1084//===----------------------------------------------------------------------===//
1085
1086void DXILResourceBindingInfo::populate(Module &M, DXILResourceTypeMap &DRTM) {
1087 hlsl::BindingInfoBuilder Builder;
1088
1089 // collect all of the llvm.dx.resource.handlefrombinding calls;
1090 // make a note if there is llvm.dx.resource.handlefromimplicitbinding
1091 for (Function &F : M.functions()) {
1092 if (!F.isDeclaration())
1093 continue;
1094
1095 switch (F.getIntrinsicID()) {
1096 default:
1097 continue;
1098 case Intrinsic::dx_resource_handlefrombinding: {
1099 auto *HandleTy = cast<TargetExtType>(F.getReturnType());
1100 ResourceTypeInfo &RTI = DRTM[HandleTy];
1101
1102 for (User *U : F.users())
1103 if (CallInst *CI = dyn_cast<CallInst>(U)) {
1104 uint32_t Space =
1105 cast<ConstantInt>(CI->getArgOperand(0))->getZExtValue();
1106 uint32_t LowerBound =
1107 cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
1108 uint32_t Size =
1109 cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
1110 Value *Name = CI->getArgOperand(4);
1111
1112 // 0 size means unbounded resource array;
1113 // upper bound register overflow should be detected in Sema
1114 assert((Size == 0 || (uint64_t)LowerBound + (uint64_t)Size - 1ULL <=
1115 (uint64_t)UINT32_MAX) &&
1116 "upper bound register overflow");
1117 uint32_t UpperBound = Size == 0 ? UINT32_MAX : LowerBound + Size - 1;
1118 Builder.trackBinding(RTI.getResourceClass(), Space, LowerBound,
1119 UpperBound, Name);
1120 }
1121 break;
1122 }
1123 case Intrinsic::dx_resource_handlefromimplicitbinding: {
1124 HasImplicitBinding = true;
1125 break;
1126 }
1127 }
1128 }
1129
1130 Bindings = Builder.calculateBindingInfo(
1131 [this](auto, auto) { this->HasOverlappingBinding = true; });
1132}
1133
1134//===----------------------------------------------------------------------===//
1135
1136AnalysisKey DXILResourceTypeAnalysis::Key;
1137AnalysisKey DXILResourceAnalysis::Key;
1138AnalysisKey DXILResourceBindingAnalysis::Key;
1139
1147
1155
1160
1161 DRM.print(OS, DRTM, M.getDataLayout());
1162 return PreservedAnalyses::all();
1163}
1164
1165void DXILResourceTypeWrapperPass::anchor() {}
1166
1169
1170INITIALIZE_PASS(DXILResourceTypeWrapperPass, "dxil-resource-type",
1171 "DXIL Resource Type Analysis", false, true)
1173
1175 return new DXILResourceTypeWrapperPass();
1176}
1177
1179
1181
1186
1188 Map.reset(new DXILResourceMap());
1189
1190 DRTM = &getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();
1191 Map->populate(M, *DRTM);
1192
1193 return false;
1194}
1195
1197
1199 if (!Map) {
1200 OS << "No resource map has been built!\n";
1201 return;
1202 }
1203 Map->print(OS, *DRTM, M->getDataLayout());
1204}
1205
1206#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1208void DXILResourceWrapperPass::dump() const { print(dbgs(), nullptr); }
1209#endif
1210
1212 "DXIL Resources Analysis", false, true)
1214
1216 return new DXILResourceWrapperPass();
1217}
1218
1221
1223
1228
1230 BindingInfo.reset(new DXILResourceBindingInfo());
1231
1232 DXILResourceTypeMap &DRTM =
1233 getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();
1234 BindingInfo->populate(M, DRTM);
1235
1236 return false;
1237}
1238
1240
1241INITIALIZE_PASS(DXILResourceBindingWrapperPass, "dxil-resource-binding",
1242 "DXIL Resource Binding Analysis", false, true)
1244
1246 return new DXILResourceWrapperPass();
1247}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
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 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
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
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:223
iterator end()
Definition DenseMap.h:141
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
uint32_t getSize() const
LLVM_ABI void print(raw_ostream &OS, dxil::ResourceTypeInfo &RTI, const DataLayout &DL) const
void setBindingID(unsigned ID)
uint32_t getHeapID() const
const ResourceBinding & getBinding() const
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)
LLVM_ABI dxil::ElementType getDXILElementType(Type *Ty, bool IsSigned)
Converts a scalar or vector LLVM type to its DXIL element type.
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