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