LLVM 20.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"
12#include "llvm/IR/Constants.h"
16#include "llvm/IR/Intrinsics.h"
17#include "llvm/IR/IntrinsicsDirectX.h"
18#include "llvm/IR/Metadata.h"
19#include "llvm/IR/Module.h"
22
23#define DEBUG_TYPE "dxil-resource"
24
25using namespace llvm;
26using namespace dxil;
27
29 switch (RC) {
30 case ResourceClass::SRV:
31 return "SRV";
32 case ResourceClass::UAV:
33 return "UAV";
34 case ResourceClass::CBuffer:
35 return "CBuffer";
36 case ResourceClass::Sampler:
37 return "Sampler";
38 }
39 llvm_unreachable("Unhandled ResourceClass");
40}
41
43 switch (RK) {
44 case ResourceKind::Texture1D:
45 return "Texture1D";
46 case ResourceKind::Texture2D:
47 return "Texture2D";
48 case ResourceKind::Texture2DMS:
49 return "Texture2DMS";
50 case ResourceKind::Texture3D:
51 return "Texture3D";
52 case ResourceKind::TextureCube:
53 return "TextureCube";
54 case ResourceKind::Texture1DArray:
55 return "Texture1DArray";
56 case ResourceKind::Texture2DArray:
57 return "Texture2DArray";
58 case ResourceKind::Texture2DMSArray:
59 return "Texture2DMSArray";
60 case ResourceKind::TextureCubeArray:
61 return "TextureCubeArray";
62 case ResourceKind::TypedBuffer:
63 return "TypedBuffer";
64 case ResourceKind::RawBuffer:
65 return "RawBuffer";
66 case ResourceKind::StructuredBuffer:
67 return "StructuredBuffer";
68 case ResourceKind::CBuffer:
69 return "CBuffer";
70 case ResourceKind::Sampler:
71 return "Sampler";
72 case ResourceKind::TBuffer:
73 return "TBuffer";
74 case ResourceKind::RTAccelerationStructure:
75 return "RTAccelerationStructure";
76 case ResourceKind::FeedbackTexture2D:
77 return "FeedbackTexture2D";
78 case ResourceKind::FeedbackTexture2DArray:
79 return "FeedbackTexture2DArray";
80 case ResourceKind::NumEntries:
81 case ResourceKind::Invalid:
82 return "<invalid>";
83 }
84 llvm_unreachable("Unhandled ResourceKind");
85}
86
88 switch (ET) {
89 case ElementType::I1:
90 return "i1";
91 case ElementType::I16:
92 return "i16";
93 case ElementType::U16:
94 return "u16";
95 case ElementType::I32:
96 return "i32";
97 case ElementType::U32:
98 return "u32";
99 case ElementType::I64:
100 return "i64";
101 case ElementType::U64:
102 return "u64";
103 case ElementType::F16:
104 return "f16";
105 case ElementType::F32:
106 return "f32";
107 case ElementType::F64:
108 return "f64";
109 case ElementType::SNormF16:
110 return "snorm_f16";
111 case ElementType::UNormF16:
112 return "unorm_f16";
113 case ElementType::SNormF32:
114 return "snorm_f32";
115 case ElementType::UNormF32:
116 return "unorm_f32";
117 case ElementType::SNormF64:
118 return "snorm_f64";
119 case ElementType::UNormF64:
120 return "unorm_f64";
121 case ElementType::PackedS8x32:
122 return "p32i8";
123 case ElementType::PackedU8x32:
124 return "p32u8";
125 case ElementType::Invalid:
126 return "<invalid>";
127 }
128 llvm_unreachable("Unhandled ElementType");
129}
130
132 switch (ST) {
133 case SamplerType::Default:
134 return "Default";
135 case SamplerType::Comparison:
136 return "Comparison";
137 case SamplerType::Mono:
138 return "Mono";
139 }
140 llvm_unreachable("Unhandled SamplerType");
141}
142
144 switch (SFT) {
145 case SamplerFeedbackType::MinMip:
146 return "MinMip";
147 case SamplerFeedbackType::MipRegionUsed:
148 return "MipRegionUsed";
149 }
150 llvm_unreachable("Unhandled SamplerFeedbackType");
151}
152
153static dxil::ElementType toDXILElementType(Type *Ty, bool IsSigned) {
154 // TODO: Handle unorm, snorm, and packed.
155 Ty = Ty->getScalarType();
156
157 if (Ty->isIntegerTy()) {
158 switch (Ty->getIntegerBitWidth()) {
159 case 16:
160 return IsSigned ? ElementType::I16 : ElementType::U16;
161 case 32:
162 return IsSigned ? ElementType::I32 : ElementType::U32;
163 case 64:
164 return IsSigned ? ElementType::I64 : ElementType::U64;
165 case 1:
166 default:
167 return ElementType::Invalid;
168 }
169 } else if (Ty->isFloatTy()) {
170 return ElementType::F32;
171 } else if (Ty->isDoubleTy()) {
172 return ElementType::F64;
173 } else if (Ty->isHalfTy()) {
174 return ElementType::F16;
175 }
176
177 return ElementType::Invalid;
178}
179
181 const dxil::ResourceClass RC_,
182 const dxil::ResourceKind Kind_,
183 bool GloballyCoherent, bool HasCounter)
184 : HandleTy(HandleTy), GloballyCoherent(GloballyCoherent),
185 HasCounter(HasCounter) {
186 // If we're provided a resource class and kind, trust them.
187 if (Kind_ != dxil::ResourceKind::Invalid) {
188 RC = RC_;
189 Kind = Kind_;
190 return;
191 }
192
193 if (auto *Ty = dyn_cast<RawBufferExtType>(HandleTy)) {
194 RC = Ty->isWriteable() ? ResourceClass::UAV : ResourceClass::SRV;
195 Kind = Ty->isStructured() ? ResourceKind::StructuredBuffer
197 } else if (auto *Ty = dyn_cast<TypedBufferExtType>(HandleTy)) {
198 RC = Ty->isWriteable() ? ResourceClass::UAV : ResourceClass::SRV;
200 } else if (auto *Ty = dyn_cast<TextureExtType>(HandleTy)) {
201 RC = Ty->isWriteable() ? ResourceClass::UAV : ResourceClass::SRV;
202 Kind = Ty->getDimension();
203 } else if (auto *Ty = dyn_cast<MSTextureExtType>(HandleTy)) {
204 RC = Ty->isWriteable() ? ResourceClass::UAV : ResourceClass::SRV;
205 Kind = Ty->getDimension();
206 } else if (auto *Ty = dyn_cast<FeedbackTextureExtType>(HandleTy)) {
208 Kind = Ty->getDimension();
209 } else if (isa<CBufferExtType>(HandleTy)) {
212 } else if (isa<SamplerExtType>(HandleTy)) {
215 } else
216 llvm_unreachable("Unknown handle type");
217}
218
220 bool isWriteable, bool isROV) {
221 Dest = isWriteable ? (isROV ? "RasterizerOrdered" : "RW") : "";
222 Dest += Name;
223}
224
226 SmallString<64> TypeName;
227
228 switch (Kind) {
236 auto *RTy = cast<TextureExtType>(HandleTy);
237 formatTypeName(TypeName, getResourceKindName(Kind), RTy->isWriteable(),
238 RTy->isROV());
239 return StructType::create(RTy->getResourceType(), TypeName);
240 }
243 auto *RTy = cast<MSTextureExtType>(HandleTy);
244 formatTypeName(TypeName, getResourceKindName(Kind), RTy->isWriteable(),
245 /*IsROV=*/false);
246 return StructType::create(RTy->getResourceType(), TypeName);
247 }
249 auto *RTy = cast<TypedBufferExtType>(HandleTy);
250 formatTypeName(TypeName, getResourceKindName(Kind), RTy->isWriteable(),
251 RTy->isROV());
252 return StructType::create(RTy->getResourceType(), TypeName);
253 }
255 auto *RTy = cast<RawBufferExtType>(HandleTy);
256 formatTypeName(TypeName, "ByteAddressBuffer", RTy->isWriteable(),
257 RTy->isROV());
259 TypeName);
260 }
262 auto *RTy = cast<RawBufferExtType>(HandleTy);
263 formatTypeName(TypeName, "StructuredBuffer", RTy->isWriteable(),
264 RTy->isROV());
265 return StructType::create(RTy->getResourceType(), TypeName);
266 }
269 auto *RTy = cast<FeedbackTextureExtType>(HandleTy);
270 TypeName = formatv("{0}<{1}>", getResourceKindName(Kind),
271 llvm::to_underlying(RTy->getFeedbackType()));
273 TypeName);
274 }
276 return StructType::create(HandleTy->getContext(), "cbuffer");
278 auto *RTy = cast<SamplerExtType>(HandleTy);
279 TypeName = formatv("SamplerState<{0}>",
280 llvm::to_underlying(RTy->getSamplerType()));
282 TypeName);
283 }
286 llvm_unreachable("Unhandled resource kind");
289 llvm_unreachable("Invalid resource kind");
290 }
291 llvm_unreachable("Unhandled ResourceKind enum");
292}
293
294bool ResourceTypeInfo::isUAV() const { return RC == ResourceClass::UAV; }
295
297 return RC == ResourceClass::CBuffer;
298}
299
301 return RC == ResourceClass::Sampler;
302}
303
305 return Kind == ResourceKind::StructuredBuffer;
306}
307
309 switch (Kind) {
320 return true;
329 return false;
332 llvm_unreachable("Invalid resource kind");
333 }
334 llvm_unreachable("Unhandled ResourceKind enum");
335}
336
338 return Kind == ResourceKind::FeedbackTexture2D ||
340}
341
343 return Kind == ResourceKind::Texture2DMS ||
345}
346
347static bool isROV(dxil::ResourceKind Kind, TargetExtType *Ty) {
348 switch (Kind) {
356 return cast<TextureExtType>(Ty)->isROV();
358 return cast<TypedBufferExtType>(Ty)->isROV();
361 return cast<RawBufferExtType>(Ty)->isROV();
366 return false;
373 llvm_unreachable("Resource cannot be ROV");
374 }
375 llvm_unreachable("Unhandled ResourceKind enum");
376}
377
379 assert(isUAV() && "Not a UAV");
380 return {GloballyCoherent, HasCounter, isROV(Kind, HandleTy)};
381}
382
384 assert(isCBuffer() && "Not a CBuffer");
385 return cast<CBufferExtType>(HandleTy)->getCBufferSize();
386}
387
389 assert(isSampler() && "Not a Sampler");
390 return cast<SamplerExtType>(HandleTy)->getSamplerType();
391}
392
395 assert(isStruct() && "Not a Struct");
396
397 Type *ElTy = cast<RawBufferExtType>(HandleTy)->getResourceType();
398
399 uint32_t Stride = DL.getTypeAllocSize(ElTy);
400 MaybeAlign Alignment;
401 if (auto *STy = dyn_cast<StructType>(ElTy))
402 Alignment = DL.getStructLayout(STy)->getAlignment();
403 uint32_t AlignLog2 = Alignment ? Log2(*Alignment) : 0;
404 return {Stride, AlignLog2};
405}
406
407static std::pair<Type *, bool> getTypedElementType(dxil::ResourceKind Kind,
408 TargetExtType *Ty) {
409 switch (Kind) {
417 auto *RTy = cast<TextureExtType>(Ty);
418 return {RTy->getResourceType(), RTy->isSigned()};
419 }
422 auto *RTy = cast<MSTextureExtType>(Ty);
423 return {RTy->getResourceType(), RTy->isSigned()};
424 }
426 auto *RTy = cast<TypedBufferExtType>(Ty);
427 return {RTy->getResourceType(), RTy->isSigned()};
428 }
439 llvm_unreachable("Resource is not typed");
440 }
441 llvm_unreachable("Unhandled ResourceKind enum");
442}
443
445 assert(isTyped() && "Not typed");
446
447 auto [ElTy, IsSigned] = getTypedElementType(Kind, HandleTy);
448 dxil::ElementType ET = toDXILElementType(ElTy, IsSigned);
449 uint32_t Count = 1;
450 if (auto *VTy = dyn_cast<FixedVectorType>(ElTy))
451 Count = VTy->getNumElements();
452 return {ET, Count};
453}
454
456 assert(isFeedback() && "Not Feedback");
457 return cast<FeedbackTextureExtType>(HandleTy)->getFeedbackType();
458}
460 assert(isMultiSample() && "Not MultiSampled");
461 return cast<MSTextureExtType>(HandleTy)->getSampleCount();
462}
463
465 return std::tie(HandleTy, GloballyCoherent, HasCounter) ==
466 std::tie(RHS.HandleTy, RHS.GloballyCoherent, RHS.HasCounter);
467}
468
470 // An empty datalayout is sufficient for sorting purposes.
471 DataLayout DummyDL;
472 if (std::tie(RC, Kind) < std::tie(RHS.RC, RHS.Kind))
473 return true;
474 if (isCBuffer() && RHS.isCBuffer() &&
475 getCBufferSize(DummyDL) < RHS.getCBufferSize(DummyDL))
476 return true;
477 if (isSampler() && RHS.isSampler() && getSamplerType() < RHS.getSamplerType())
478 return true;
479 if (isUAV() && RHS.isUAV() && getUAV() < RHS.getUAV())
480 return true;
481 if (isStruct() && RHS.isStruct() &&
482 getStruct(DummyDL) < RHS.getStruct(DummyDL))
483 return true;
484 if (isFeedback() && RHS.isFeedback() &&
485 getFeedbackType() < RHS.getFeedbackType())
486 return true;
487 if (isTyped() && RHS.isTyped() && getTyped() < RHS.getTyped())
488 return true;
489 if (isMultiSample() && RHS.isMultiSample() &&
490 getMultiSampleCount() < RHS.getMultiSampleCount())
491 return true;
492 return false;
493}
494
496 OS << " Class: " << getResourceClassName(RC) << "\n"
497 << " Kind: " << getResourceKindName(Kind) << "\n";
498
499 if (isCBuffer()) {
500 OS << " CBuffer size: " << getCBufferSize(DL) << "\n";
501 } else if (isSampler()) {
502 OS << " Sampler Type: " << getSamplerTypeName(getSamplerType()) << "\n";
503 } else {
504 if (isUAV()) {
505 UAVInfo UAVFlags = getUAV();
506 OS << " Globally Coherent: " << UAVFlags.GloballyCoherent << "\n"
507 << " HasCounter: " << UAVFlags.HasCounter << "\n"
508 << " IsROV: " << UAVFlags.IsROV << "\n";
509 }
510 if (isMultiSample())
511 OS << " Sample Count: " << getMultiSampleCount() << "\n";
512
513 if (isStruct()) {
515 OS << " Buffer Stride: " << Struct.Stride << "\n";
516 OS << " Alignment: " << Struct.AlignLog2 << "\n";
517 } else if (isTyped()) {
518 TypedInfo Typed = getTyped();
519 OS << " Element Type: " << getElementTypeName(Typed.ElementTy) << "\n"
520 << " Element Count: " << Typed.ElementCount << "\n";
521 } else if (isFeedback())
522 OS << " Feedback Type: " << getSamplerFeedbackTypeName(getFeedbackType())
523 << "\n";
524 }
525}
526
528 StringRef Name) {
529 assert(!Symbol && "Symbol has already been created");
530 Symbol = new GlobalVariable(M, Ty, /*isConstant=*/true,
532 /*Initializer=*/nullptr, Name);
533 return Symbol;
534}
535
537 dxil::ResourceTypeInfo &RTI) const {
538 LLVMContext &Ctx = M.getContext();
539 const DataLayout &DL = M.getDataLayout();
540
542
543 Type *I32Ty = Type::getInt32Ty(Ctx);
544 Type *I1Ty = Type::getInt1Ty(Ctx);
545 auto getIntMD = [&I32Ty](uint32_t V) {
547 Constant::getIntegerValue(I32Ty, APInt(32, V)));
548 };
549 auto getBoolMD = [&I1Ty](uint32_t V) {
551 Constant::getIntegerValue(I1Ty, APInt(1, V)));
552 };
553
554 MDVals.push_back(getIntMD(Binding.RecordID));
555 assert(Symbol && "Cannot yet create useful resource metadata without symbol");
556 MDVals.push_back(ValueAsMetadata::get(Symbol));
557 MDVals.push_back(MDString::get(Ctx, Symbol->getName()));
558 MDVals.push_back(getIntMD(Binding.Space));
559 MDVals.push_back(getIntMD(Binding.LowerBound));
560 MDVals.push_back(getIntMD(Binding.Size));
561
562 if (RTI.isCBuffer()) {
563 MDVals.push_back(getIntMD(RTI.getCBufferSize(DL)));
564 MDVals.push_back(nullptr);
565 } else if (RTI.isSampler()) {
566 MDVals.push_back(getIntMD(llvm::to_underlying(RTI.getSamplerType())));
567 MDVals.push_back(nullptr);
568 } else {
569 MDVals.push_back(getIntMD(llvm::to_underlying(RTI.getResourceKind())));
570
571 if (RTI.isUAV()) {
572 ResourceTypeInfo::UAVInfo UAVFlags = RTI.getUAV();
573 MDVals.push_back(getBoolMD(UAVFlags.GloballyCoherent));
574 MDVals.push_back(getBoolMD(UAVFlags.HasCounter));
575 MDVals.push_back(getBoolMD(UAVFlags.IsROV));
576 } else {
577 // All SRVs include sample count in the metadata, but it's only meaningful
578 // for multi-sampled textured. Also, UAVs can be multisampled in SM6.7+,
579 // but this just isn't reflected in the metadata at all.
580 uint32_t SampleCount =
581 RTI.isMultiSample() ? RTI.getMultiSampleCount() : 0;
582 MDVals.push_back(getIntMD(SampleCount));
583 }
584
585 // Further properties are attached to a metadata list of tag-value pairs.
587 if (RTI.isStruct()) {
588 Tags.push_back(
590 Tags.push_back(getIntMD(RTI.getStruct(DL).Stride));
591 } else if (RTI.isTyped()) {
593 Tags.push_back(getIntMD(llvm::to_underlying(RTI.getTyped().ElementTy)));
594 } else if (RTI.isFeedback()) {
595 Tags.push_back(
597 Tags.push_back(getIntMD(llvm::to_underlying(RTI.getFeedbackType())));
598 }
599 MDVals.push_back(Tags.empty() ? nullptr : MDNode::get(Ctx, Tags));
600 }
601
602 return MDNode::get(Ctx, MDVals);
603}
604
605std::pair<uint32_t, uint32_t>
607 dxil::ResourceTypeInfo &RTI) const {
608 const DataLayout &DL = M.getDataLayout();
609
611 uint32_t AlignLog2 = RTI.isStruct() ? RTI.getStruct(DL).AlignLog2 : 0;
612 bool IsUAV = RTI.isUAV();
614 IsUAV ? RTI.getUAV() : ResourceTypeInfo::UAVInfo{};
615 bool IsROV = IsUAV && UAVFlags.IsROV;
616 bool IsGloballyCoherent = IsUAV && UAVFlags.GloballyCoherent;
617 uint8_t SamplerCmpOrHasCounter = 0;
618 if (IsUAV)
619 SamplerCmpOrHasCounter = UAVFlags.HasCounter;
620 else if (RTI.isSampler())
621 SamplerCmpOrHasCounter = RTI.getSamplerType() == SamplerType::Comparison;
622
623 // TODO: Document this format. Currently the only reference is the
624 // implementation of dxc's DxilResourceProperties struct.
625 uint32_t Word0 = 0;
626 Word0 |= ResourceKind & 0xFF;
627 Word0 |= (AlignLog2 & 0xF) << 8;
628 Word0 |= (IsUAV & 1) << 12;
629 Word0 |= (IsROV & 1) << 13;
630 Word0 |= (IsGloballyCoherent & 1) << 14;
631 Word0 |= (SamplerCmpOrHasCounter & 1) << 15;
632
633 uint32_t Word1 = 0;
634 if (RTI.isStruct())
635 Word1 = RTI.getStruct(DL).Stride;
636 else if (RTI.isCBuffer())
637 Word1 = RTI.getCBufferSize(DL);
638 else if (RTI.isFeedback())
640 else if (RTI.isTyped()) {
642 uint32_t CompType = llvm::to_underlying(Typed.ElementTy);
643 uint32_t CompCount = Typed.ElementCount;
644 uint32_t SampleCount = RTI.isMultiSample() ? RTI.getMultiSampleCount() : 0;
645
646 Word1 |= (CompType & 0xFF) << 0;
647 Word1 |= (CompCount & 0xFF) << 8;
648 Word1 |= (SampleCount & 0xFF) << 16;
649 }
650
651 return {Word0, Word1};
652}
653
655 const DataLayout &DL) const {
656 if (Symbol) {
657 OS << " Symbol: ";
658 Symbol->printAsOperand(OS);
659 OS << "\n";
660 }
661
662 OS << " Binding:\n"
663 << " Record ID: " << Binding.RecordID << "\n"
664 << " Space: " << Binding.Space << "\n"
665 << " Lower Bound: " << Binding.LowerBound << "\n"
666 << " Size: " << Binding.Size << "\n";
667
668 RTI.print(OS, DL);
669}
670
671//===----------------------------------------------------------------------===//
672
675 // Passes that introduce resource types must explicitly invalidate this pass.
676 auto PAC = PA.getChecker<DXILResourceTypeAnalysis>();
677 return !PAC.preservedWhenStateless();
678}
679
680//===----------------------------------------------------------------------===//
681
682void DXILBindingMap::populate(Module &M, DXILResourceTypeMap &DRTM) {
684 CIToInfos;
685
686 for (Function &F : M.functions()) {
687 if (!F.isDeclaration())
688 continue;
689 LLVM_DEBUG(dbgs() << "Function: " << F.getName() << "\n");
690 Intrinsic::ID ID = F.getIntrinsicID();
691 switch (ID) {
692 default:
693 continue;
694 case Intrinsic::dx_resource_handlefrombinding: {
695 auto *HandleTy = cast<TargetExtType>(F.getReturnType());
696 ResourceTypeInfo &RTI = DRTM[HandleTy];
697
698 for (User *U : F.users())
699 if (CallInst *CI = dyn_cast<CallInst>(U)) {
700 LLVM_DEBUG(dbgs() << " Visiting: " << *U << "\n");
701 uint32_t Space =
702 cast<ConstantInt>(CI->getArgOperand(0))->getZExtValue();
703 uint32_t LowerBound =
704 cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
705 uint32_t Size =
706 cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
708 /*RecordID=*/0, Space, LowerBound, Size, HandleTy};
709
710 CIToInfos.emplace_back(CI, RBI, RTI);
711 }
712
713 break;
714 }
715 }
716 }
717
718 llvm::stable_sort(CIToInfos, [](auto &LHS, auto &RHS) {
719 const auto &[LCI, LRBI, LRTI] = LHS;
720 const auto &[RCI, RRBI, RRTI] = RHS;
721 // Sort by resource class first for grouping purposes, and then by the
722 // binding and type so we can remove duplicates.
723 ResourceClass LRC = LRTI.getResourceClass();
724 ResourceClass RRC = RRTI.getResourceClass();
725
726 return std::tie(LRC, LRBI, LRTI) < std::tie(RRC, RRBI, RRTI);
727 });
728 for (auto [CI, RBI, RTI] : CIToInfos) {
729 if (Infos.empty() || RBI != Infos.back())
730 Infos.push_back(RBI);
731 CallMap[CI] = Infos.size() - 1;
732 }
733
734 unsigned Size = Infos.size();
735 // In DXC, Record ID is unique per resource type. Match that.
736 FirstUAV = FirstCBuffer = FirstSampler = Size;
737 uint32_t NextID = 0;
738 for (unsigned I = 0, E = Size; I != E; ++I) {
739 ResourceBindingInfo &RBI = Infos[I];
740 ResourceTypeInfo &RTI = DRTM[RBI.getHandleTy()];
741 if (RTI.isUAV() && FirstUAV == Size) {
742 FirstUAV = I;
743 NextID = 0;
744 } else if (RTI.isCBuffer() && FirstCBuffer == Size) {
745 FirstCBuffer = I;
746 NextID = 0;
747 } else if (RTI.isSampler() && FirstSampler == Size) {
748 FirstSampler = I;
749 NextID = 0;
750 }
751
752 // Adjust the resource binding to use the next ID.
753 RBI.setBindingID(NextID++);
754 }
755}
756
758 const DataLayout &DL) const {
759 for (unsigned I = 0, E = Infos.size(); I != E; ++I) {
760 OS << "Binding " << I << ":\n";
761 const dxil::ResourceBindingInfo &RBI = Infos[I];
762 RBI.print(OS, DRTM[RBI.getHandleTy()], DL);
763 OS << "\n";
764 }
765
766 for (const auto &[CI, Index] : CallMap) {
767 OS << "Call bound to " << Index << ":";
768 CI->print(OS);
769 OS << "\n";
770 }
771}
772
773//===----------------------------------------------------------------------===//
774
775AnalysisKey DXILResourceTypeAnalysis::Key;
776AnalysisKey DXILResourceBindingAnalysis::Key;
777
782 Data.populate(M, DRTM);
783 return Data;
784}
785
790
791 DBM.print(OS, DRTM, M.getDataLayout());
792 return PreservedAnalyses::all();
793}
794
795void DXILResourceTypeWrapperPass::anchor() {}
796
799}
800
801INITIALIZE_PASS(DXILResourceTypeWrapperPass, "dxil-resource-type",
802 "DXIL Resource Type Analysis", false, true)
804
806 return new DXILResourceTypeWrapperPass();
807}
808
810 : ModulePass(ID) {
813}
814
816
819 AU.setPreservesAll();
820}
821
823 Map.reset(new DXILBindingMap());
824
825 DRTM = &getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();
826 Map->populate(M, *DRTM);
827
828 return false;
829}
830
832
834 const Module *M) const {
835 if (!Map) {
836 OS << "No resource map has been built!\n";
837 return;
838 }
839 Map->print(OS, *DRTM, M->getDataLayout());
840}
841
842#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
845#endif
846
847INITIALIZE_PASS(DXILResourceBindingWrapperPass, "dxil-resource-binding",
848 "DXIL Resource Binding Analysis", false, true)
850
853}
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static dxil::ElementType toDXILElementType(Type *Ty, bool IsSigned)
static StringRef getResourceClassName(ResourceClass RC)
static StringRef getElementTypeName(ElementType ET)
static void formatTypeName(SmallString< 64 > &Dest, StringRef Name, bool isWriteable, bool isROV)
static std::pair< Type *, bool > getTypedElementType(dxil::ResourceKind Kind, TargetExtType *Ty)
static bool isROV(dxil::ResourceKind Kind, TargetExtType *Ty)
static StringRef getResourceKindName(ResourceKind RK)
static StringRef getSamplerTypeName(SamplerType ST)
static StringRef getSamplerFeedbackTypeName(SamplerFeedbackType SFT)
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition: Compiler.h:622
This file contains the declarations for the subclasses of Constant, which represent the different fla...
#define LLVM_DEBUG(...)
Definition: Debug.h:106
std::string Name
uint64_t Size
Module.h This file contains the declarations for the Module class.
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
This file contains the declarations for metadata subclasses.
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
This file defines the SmallString class.
@ Struct
Value * RHS
Value * LHS
Class for arbitrary precision integers.
Definition: APInt.h:78
API to communicate dependencies between analyses during invalidation.
Definition: PassManager.h:292
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:253
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Definition: PassManager.h:410
Represent the analysis usage information of a pass.
void setPreservesAll()
Set by analyses that do not transform their input at all.
AnalysisUsage & addRequiredTransitive()
This class represents a function call, abstracting a target machine's calling convention.
static ConstantAsMetadata * get(Constant *C)
Definition: Metadata.h:528
static 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...
Definition: Constants.cpp:403
void print(raw_ostream &OS, DXILResourceTypeMap &DRTM, const DataLayout &DL) const
DXILBindingMap run(Module &M, ModuleAnalysisManager &AM)
Gather resource info for the module M.
PreservedAnalyses 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 print(raw_ostream &OS, const Module *M) const override
print - Print out the internal state of the pass.
void releaseMemory() override
releaseMemory() - This member can be implemented by a pass if it wants to be able to release its memo...
bool invalidate(Module &M, const PreservedAnalyses &PA, ModuleAnalysisManager::Invalidator &Inv)
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:63
@ ExternalLinkage
Externally visible function.
Definition: GlobalValue.h:52
ImmutablePass class - This class is used to provide information that does not need to be run.
Definition: Pass.h:281
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:67
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition: Metadata.h:1543
static MDString * get(LLVMContext &Context, StringRef Str)
Definition: Metadata.cpp:606
Tuple of metadata.
Definition: Metadata.h:1473
Align getAlignment() const
Return alignment of the basic block.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:251
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
A set of analyses that are preserved following a run of a transformation pass.
Definition: Analysis.h:111
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: Analysis.h:117
PreservedAnalysisChecker getChecker() const
Build a checker for this PreservedAnalyses and the specified analysis type.
Definition: Analysis.h:264
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
bool empty() const
Definition: SmallVector.h:81
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:937
void push_back(const T &Elt)
Definition: SmallVector.h:413
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
Class to represent struct types.
Definition: DerivedTypes.h:218
static StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
Definition: Type.cpp:612
Class to represent target extensions types, which are generally unintrospectable from target-independ...
Definition: DerivedTypes.h:744
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
unsigned getIntegerBitWidth() const
static IntegerType * getInt1Ty(LLVMContext &C)
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
Definition: Type.h:153
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
Definition: Type.h:142
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
Definition: Type.h:128
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
Definition: Type.h:156
static IntegerType * getInt32Ty(LLVMContext &C)
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition: Type.h:237
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
Definition: Type.h:355
static ValueAsMetadata * get(Value *V)
Definition: Metadata.cpp:501
void printAsOperand(raw_ostream &O, bool PrintType=true, const Module *M=nullptr) const
Print the name of this Value out to the specified raw_ostream.
Definition: AsmWriter.cpp:5144
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:309
void setBindingID(unsigned ID)
Definition: DXILResource.h:342
GlobalVariable * createSymbol(Module &M, StructType *Ty, StringRef Name="")
std::pair< uint32_t, uint32_t > getAnnotateProps(Module &M, dxil::ResourceTypeInfo &RTI) const
TargetExtType * getHandleTy() const
Definition: DXILResource.h:345
MDTuple * getAsMetadata(Module &M, dxil::ResourceTypeInfo &RTI) const
void print(raw_ostream &OS, dxil::ResourceTypeInfo &RTI, const DataLayout &DL) const
uint32_t getMultiSampleCount() const
uint32_t getCBufferSize(const DataLayout &DL) const
bool operator<(const ResourceTypeInfo &RHS) const
dxil::SamplerType getSamplerType() const
StructType * createElementStruct()
StructInfo getStruct(const DataLayout &DL) const
ResourceTypeInfo(TargetExtType *HandleTy, const dxil::ResourceClass RC, const dxil::ResourceKind Kind, bool GloballyCoherent=false, bool HasCounter=false)
dxil::SamplerFeedbackType getFeedbackType() const
bool operator==(const ResourceTypeInfo &RHS) const
dxil::ResourceKind getResourceKind() const
Definition: DXILResource.h:295
void print(raw_ostream &OS, const DataLayout &DL) const
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ RRC
Y = RRC X, rotate right via carry.
ResourceKind
The kind of resource for an SRV or UAV resource.
Definition: DXILABI.h:34
ResourceClass
Definition: DXILABI.h:25
SamplerFeedbackType
Definition: DXILABI.h:94
ElementType
The element type of an SRV or UAV resource.
Definition: DXILABI.h:58
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
void stable_sort(R &&Range)
Definition: STLExtras.h:2037
void initializeDXILResourceTypeWrapperPassPass(PassRegistry &)
ModulePass * createDXILResourceTypeWrapperPassPass()
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
void initializeDXILResourceBindingWrapperPassPass(PassRegistry &)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
constexpr std::underlying_type_t< Enum > to_underlying(Enum E)
Returns underlying integer value of an enum.
unsigned Log2(Align A)
Returns the log2 of the alignment.
Definition: Alignment.h:208
ModulePass * createDXILResourceBindingWrapperPassPass()
A special type used by analysis passes to provide an address that identifies that particular analysis...
Definition: Analysis.h:28
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Definition: Alignment.h:117