Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Analysis/DXILResource.cpp
213765 views
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
9
#include "llvm/Analysis/DXILResource.h"
10
#include "llvm/ADT/APInt.h"
11
#include "llvm/ADT/STLExtras.h"
12
#include "llvm/ADT/SmallString.h"
13
#include "llvm/ADT/SmallVector.h"
14
#include "llvm/IR/Constants.h"
15
#include "llvm/IR/DerivedTypes.h"
16
#include "llvm/IR/DiagnosticInfo.h"
17
#include "llvm/IR/Instructions.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"
22
#include "llvm/InitializePasses.h"
23
#include "llvm/Support/FormatVariadic.h"
24
#include <cstdint>
25
#include <optional>
26
27
#define DEBUG_TYPE "dxil-resource"
28
29
using namespace llvm;
30
using namespace dxil;
31
32
static StringRef getResourceClassName(ResourceClass RC) {
33
switch (RC) {
34
case ResourceClass::SRV:
35
return "SRV";
36
case ResourceClass::UAV:
37
return "UAV";
38
case ResourceClass::CBuffer:
39
return "CBuffer";
40
case ResourceClass::Sampler:
41
return "Sampler";
42
}
43
llvm_unreachable("Unhandled ResourceClass");
44
}
45
46
static StringRef getResourceKindName(ResourceKind RK) {
47
switch (RK) {
48
case ResourceKind::Texture1D:
49
return "Texture1D";
50
case ResourceKind::Texture2D:
51
return "Texture2D";
52
case ResourceKind::Texture2DMS:
53
return "Texture2DMS";
54
case ResourceKind::Texture3D:
55
return "Texture3D";
56
case ResourceKind::TextureCube:
57
return "TextureCube";
58
case ResourceKind::Texture1DArray:
59
return "Texture1DArray";
60
case ResourceKind::Texture2DArray:
61
return "Texture2DArray";
62
case ResourceKind::Texture2DMSArray:
63
return "Texture2DMSArray";
64
case ResourceKind::TextureCubeArray:
65
return "TextureCubeArray";
66
case ResourceKind::TypedBuffer:
67
return "Buffer";
68
case ResourceKind::RawBuffer:
69
return "RawBuffer";
70
case ResourceKind::StructuredBuffer:
71
return "StructuredBuffer";
72
case ResourceKind::CBuffer:
73
return "CBuffer";
74
case ResourceKind::Sampler:
75
return "Sampler";
76
case ResourceKind::TBuffer:
77
return "TBuffer";
78
case ResourceKind::RTAccelerationStructure:
79
return "RTAccelerationStructure";
80
case ResourceKind::FeedbackTexture2D:
81
return "FeedbackTexture2D";
82
case ResourceKind::FeedbackTexture2DArray:
83
return "FeedbackTexture2DArray";
84
case ResourceKind::NumEntries:
85
case ResourceKind::Invalid:
86
return "<invalid>";
87
}
88
llvm_unreachable("Unhandled ResourceKind");
89
}
90
91
static StringRef getElementTypeName(ElementType ET) {
92
switch (ET) {
93
case ElementType::I1:
94
return "i1";
95
case ElementType::I16:
96
return "i16";
97
case ElementType::U16:
98
return "u16";
99
case ElementType::I32:
100
return "i32";
101
case ElementType::U32:
102
return "u32";
103
case ElementType::I64:
104
return "i64";
105
case ElementType::U64:
106
return "u64";
107
case ElementType::F16:
108
return "f16";
109
case ElementType::F32:
110
return "f32";
111
case ElementType::F64:
112
return "f64";
113
case ElementType::SNormF16:
114
return "snorm_f16";
115
case ElementType::UNormF16:
116
return "unorm_f16";
117
case ElementType::SNormF32:
118
return "snorm_f32";
119
case ElementType::UNormF32:
120
return "unorm_f32";
121
case ElementType::SNormF64:
122
return "snorm_f64";
123
case ElementType::UNormF64:
124
return "unorm_f64";
125
case ElementType::PackedS8x32:
126
return "p32i8";
127
case ElementType::PackedU8x32:
128
return "p32u8";
129
case ElementType::Invalid:
130
return "<invalid>";
131
}
132
llvm_unreachable("Unhandled ElementType");
133
}
134
135
static StringRef getElementTypeNameForTemplate(ElementType ET) {
136
switch (ET) {
137
case ElementType::I1:
138
return "bool";
139
case ElementType::I16:
140
return "int16_t";
141
case ElementType::U16:
142
return "uint16_t";
143
case ElementType::I32:
144
return "int32_t";
145
case ElementType::U32:
146
return "uint32_t";
147
case ElementType::I64:
148
return "int64_t";
149
case ElementType::U64:
150
return "uint32_t";
151
case ElementType::F16:
152
case ElementType::SNormF16:
153
case ElementType::UNormF16:
154
return "half";
155
case ElementType::F32:
156
case ElementType::SNormF32:
157
case ElementType::UNormF32:
158
return "float";
159
case ElementType::F64:
160
case ElementType::SNormF64:
161
case ElementType::UNormF64:
162
return "double";
163
case ElementType::PackedS8x32:
164
return "int8_t4_packed";
165
case ElementType::PackedU8x32:
166
return "uint8_t4_packed";
167
case ElementType::Invalid:
168
return "<invalid>";
169
}
170
llvm_unreachable("Unhandled ElementType");
171
}
172
173
static StringRef getSamplerTypeName(SamplerType ST) {
174
switch (ST) {
175
case SamplerType::Default:
176
return "Default";
177
case SamplerType::Comparison:
178
return "Comparison";
179
case SamplerType::Mono:
180
return "Mono";
181
}
182
llvm_unreachable("Unhandled SamplerType");
183
}
184
185
static StringRef getSamplerFeedbackTypeName(SamplerFeedbackType SFT) {
186
switch (SFT) {
187
case SamplerFeedbackType::MinMip:
188
return "MinMip";
189
case SamplerFeedbackType::MipRegionUsed:
190
return "MipRegionUsed";
191
}
192
llvm_unreachable("Unhandled SamplerFeedbackType");
193
}
194
195
static dxil::ElementType toDXILElementType(Type *Ty, bool IsSigned) {
196
// TODO: Handle unorm, snorm, and packed.
197
Ty = Ty->getScalarType();
198
199
if (Ty->isIntegerTy()) {
200
switch (Ty->getIntegerBitWidth()) {
201
case 16:
202
return IsSigned ? ElementType::I16 : ElementType::U16;
203
case 32:
204
return IsSigned ? ElementType::I32 : ElementType::U32;
205
case 64:
206
return IsSigned ? ElementType::I64 : ElementType::U64;
207
case 1:
208
default:
209
return ElementType::Invalid;
210
}
211
} else if (Ty->isFloatTy()) {
212
return ElementType::F32;
213
} else if (Ty->isDoubleTy()) {
214
return ElementType::F64;
215
} else if (Ty->isHalfTy()) {
216
return ElementType::F16;
217
}
218
219
return ElementType::Invalid;
220
}
221
222
ResourceTypeInfo::ResourceTypeInfo(TargetExtType *HandleTy,
223
const dxil::ResourceClass RC_,
224
const dxil::ResourceKind Kind_)
225
: HandleTy(HandleTy) {
226
// If we're provided a resource class and kind, trust them.
227
if (Kind_ != dxil::ResourceKind::Invalid) {
228
RC = RC_;
229
Kind = Kind_;
230
return;
231
}
232
233
if (auto *Ty = dyn_cast<RawBufferExtType>(HandleTy)) {
234
RC = Ty->isWriteable() ? ResourceClass::UAV : ResourceClass::SRV;
235
Kind = Ty->isStructured() ? ResourceKind::StructuredBuffer
236
: ResourceKind::RawBuffer;
237
} else if (auto *Ty = dyn_cast<TypedBufferExtType>(HandleTy)) {
238
RC = Ty->isWriteable() ? ResourceClass::UAV : ResourceClass::SRV;
239
Kind = ResourceKind::TypedBuffer;
240
} else if (auto *Ty = dyn_cast<TextureExtType>(HandleTy)) {
241
RC = Ty->isWriteable() ? ResourceClass::UAV : ResourceClass::SRV;
242
Kind = Ty->getDimension();
243
} else if (auto *Ty = dyn_cast<MSTextureExtType>(HandleTy)) {
244
RC = Ty->isWriteable() ? ResourceClass::UAV : ResourceClass::SRV;
245
Kind = Ty->getDimension();
246
} else if (auto *Ty = dyn_cast<FeedbackTextureExtType>(HandleTy)) {
247
RC = ResourceClass::UAV;
248
Kind = Ty->getDimension();
249
} else if (isa<CBufferExtType>(HandleTy)) {
250
RC = ResourceClass::CBuffer;
251
Kind = ResourceKind::CBuffer;
252
} else if (isa<SamplerExtType>(HandleTy)) {
253
RC = ResourceClass::Sampler;
254
Kind = ResourceKind::Sampler;
255
} else
256
llvm_unreachable("Unknown handle type");
257
}
258
259
static void formatTypeName(SmallString<64> &Dest, StringRef Name,
260
bool IsWriteable, bool IsROV,
261
Type *ContainedType = nullptr,
262
bool IsSigned = true) {
263
raw_svector_ostream DestStream(Dest);
264
if (IsWriteable)
265
DestStream << (IsROV ? "RasterizerOrdered" : "RW");
266
DestStream << Name;
267
268
if (!ContainedType)
269
return;
270
271
StringRef ElementName;
272
ElementType ET = toDXILElementType(ContainedType, IsSigned);
273
if (ET != ElementType::Invalid) {
274
ElementName = getElementTypeNameForTemplate(ET);
275
} else {
276
assert(isa<StructType>(ContainedType) &&
277
"invalid element type for raw buffer");
278
StructType *ST = cast<StructType>(ContainedType);
279
if (!ST->hasName())
280
return;
281
ElementName = ST->getStructName();
282
}
283
284
DestStream << "<" << ElementName;
285
if (const FixedVectorType *VTy = dyn_cast<FixedVectorType>(ContainedType))
286
DestStream << VTy->getNumElements();
287
DestStream << ">";
288
}
289
290
static StructType *getOrCreateElementStruct(Type *ElemType, StringRef Name) {
291
StructType *Ty = StructType::getTypeByName(ElemType->getContext(), Name);
292
if (Ty && Ty->getNumElements() == 1 && Ty->getElementType(0) == ElemType)
293
return Ty;
294
return StructType::create(ElemType, Name);
295
}
296
297
StructType *ResourceTypeInfo::createElementStruct(StringRef CBufferName) {
298
SmallString<64> TypeName;
299
300
switch (Kind) {
301
case ResourceKind::Texture1D:
302
case ResourceKind::Texture2D:
303
case ResourceKind::Texture3D:
304
case ResourceKind::TextureCube:
305
case ResourceKind::Texture1DArray:
306
case ResourceKind::Texture2DArray:
307
case ResourceKind::TextureCubeArray: {
308
auto *RTy = cast<TextureExtType>(HandleTy);
309
formatTypeName(TypeName, getResourceKindName(Kind), RTy->isWriteable(),
310
RTy->isROV(), RTy->getResourceType(), RTy->isSigned());
311
return getOrCreateElementStruct(RTy->getResourceType(), TypeName);
312
}
313
case ResourceKind::Texture2DMS:
314
case ResourceKind::Texture2DMSArray: {
315
auto *RTy = cast<MSTextureExtType>(HandleTy);
316
formatTypeName(TypeName, getResourceKindName(Kind), RTy->isWriteable(),
317
/*IsROV=*/false, RTy->getResourceType(), RTy->isSigned());
318
return getOrCreateElementStruct(RTy->getResourceType(), TypeName);
319
}
320
case ResourceKind::TypedBuffer: {
321
auto *RTy = cast<TypedBufferExtType>(HandleTy);
322
formatTypeName(TypeName, getResourceKindName(Kind), RTy->isWriteable(),
323
RTy->isROV(), RTy->getResourceType(), RTy->isSigned());
324
return getOrCreateElementStruct(RTy->getResourceType(), TypeName);
325
}
326
case ResourceKind::RawBuffer: {
327
auto *RTy = cast<RawBufferExtType>(HandleTy);
328
formatTypeName(TypeName, "ByteAddressBuffer", RTy->isWriteable(),
329
RTy->isROV());
330
return getOrCreateElementStruct(Type::getInt32Ty(HandleTy->getContext()),
331
TypeName);
332
}
333
case ResourceKind::StructuredBuffer: {
334
auto *RTy = cast<RawBufferExtType>(HandleTy);
335
Type *Ty = RTy->getResourceType();
336
formatTypeName(TypeName, "StructuredBuffer", RTy->isWriteable(),
337
RTy->isROV(), RTy->getResourceType(), true);
338
return getOrCreateElementStruct(Ty, TypeName);
339
}
340
case ResourceKind::FeedbackTexture2D:
341
case ResourceKind::FeedbackTexture2DArray: {
342
auto *RTy = cast<FeedbackTextureExtType>(HandleTy);
343
TypeName = formatv("{0}<{1}>", getResourceKindName(Kind),
344
llvm::to_underlying(RTy->getFeedbackType()));
345
return getOrCreateElementStruct(Type::getInt32Ty(HandleTy->getContext()),
346
TypeName);
347
}
348
case ResourceKind::CBuffer: {
349
auto *RTy = cast<CBufferExtType>(HandleTy);
350
LayoutExtType *LayoutType = cast<LayoutExtType>(RTy->getResourceType());
351
StructType *Ty = cast<StructType>(LayoutType->getWrappedType());
352
SmallString<64> Name = getResourceKindName(Kind);
353
if (!CBufferName.empty()) {
354
Name.append(".");
355
Name.append(CBufferName);
356
}
357
return StructType::create(Ty->elements(), Name);
358
}
359
case ResourceKind::Sampler: {
360
auto *RTy = cast<SamplerExtType>(HandleTy);
361
TypeName = formatv("SamplerState<{0}>",
362
llvm::to_underlying(RTy->getSamplerType()));
363
return getOrCreateElementStruct(Type::getInt32Ty(HandleTy->getContext()),
364
TypeName);
365
}
366
case ResourceKind::TBuffer:
367
case ResourceKind::RTAccelerationStructure:
368
llvm_unreachable("Unhandled resource kind");
369
case ResourceKind::Invalid:
370
case ResourceKind::NumEntries:
371
llvm_unreachable("Invalid resource kind");
372
}
373
llvm_unreachable("Unhandled ResourceKind enum");
374
}
375
376
bool ResourceTypeInfo::isUAV() const { return RC == ResourceClass::UAV; }
377
378
bool ResourceTypeInfo::isCBuffer() const {
379
return RC == ResourceClass::CBuffer;
380
}
381
382
bool ResourceTypeInfo::isSampler() const {
383
return RC == ResourceClass::Sampler;
384
}
385
386
bool ResourceTypeInfo::isStruct() const {
387
return Kind == ResourceKind::StructuredBuffer;
388
}
389
390
bool ResourceTypeInfo::isTyped() const {
391
switch (Kind) {
392
case ResourceKind::Texture1D:
393
case ResourceKind::Texture2D:
394
case ResourceKind::Texture2DMS:
395
case ResourceKind::Texture3D:
396
case ResourceKind::TextureCube:
397
case ResourceKind::Texture1DArray:
398
case ResourceKind::Texture2DArray:
399
case ResourceKind::Texture2DMSArray:
400
case ResourceKind::TextureCubeArray:
401
case ResourceKind::TypedBuffer:
402
return true;
403
case ResourceKind::RawBuffer:
404
case ResourceKind::StructuredBuffer:
405
case ResourceKind::FeedbackTexture2D:
406
case ResourceKind::FeedbackTexture2DArray:
407
case ResourceKind::CBuffer:
408
case ResourceKind::Sampler:
409
case ResourceKind::TBuffer:
410
case ResourceKind::RTAccelerationStructure:
411
return false;
412
case ResourceKind::Invalid:
413
case ResourceKind::NumEntries:
414
llvm_unreachable("Invalid resource kind");
415
}
416
llvm_unreachable("Unhandled ResourceKind enum");
417
}
418
419
bool ResourceTypeInfo::isFeedback() const {
420
return Kind == ResourceKind::FeedbackTexture2D ||
421
Kind == ResourceKind::FeedbackTexture2DArray;
422
}
423
424
bool ResourceTypeInfo::isMultiSample() const {
425
return Kind == ResourceKind::Texture2DMS ||
426
Kind == ResourceKind::Texture2DMSArray;
427
}
428
429
static bool isROV(dxil::ResourceKind Kind, TargetExtType *Ty) {
430
switch (Kind) {
431
case ResourceKind::Texture1D:
432
case ResourceKind::Texture2D:
433
case ResourceKind::Texture3D:
434
case ResourceKind::TextureCube:
435
case ResourceKind::Texture1DArray:
436
case ResourceKind::Texture2DArray:
437
case ResourceKind::TextureCubeArray:
438
return cast<TextureExtType>(Ty)->isROV();
439
case ResourceKind::TypedBuffer:
440
return cast<TypedBufferExtType>(Ty)->isROV();
441
case ResourceKind::RawBuffer:
442
case ResourceKind::StructuredBuffer:
443
return cast<RawBufferExtType>(Ty)->isROV();
444
case ResourceKind::Texture2DMS:
445
case ResourceKind::Texture2DMSArray:
446
case ResourceKind::FeedbackTexture2D:
447
case ResourceKind::FeedbackTexture2DArray:
448
return false;
449
case ResourceKind::CBuffer:
450
case ResourceKind::Sampler:
451
case ResourceKind::TBuffer:
452
case ResourceKind::RTAccelerationStructure:
453
case ResourceKind::Invalid:
454
case ResourceKind::NumEntries:
455
llvm_unreachable("Resource cannot be ROV");
456
}
457
llvm_unreachable("Unhandled ResourceKind enum");
458
}
459
460
ResourceTypeInfo::UAVInfo ResourceTypeInfo::getUAV() const {
461
assert(isUAV() && "Not a UAV");
462
return {isROV(Kind, HandleTy)};
463
}
464
465
uint32_t ResourceTypeInfo::getCBufferSize(const DataLayout &DL) const {
466
assert(isCBuffer() && "Not a CBuffer");
467
468
Type *ElTy = cast<CBufferExtType>(HandleTy)->getResourceType();
469
470
if (auto *LayoutTy = dyn_cast<LayoutExtType>(ElTy))
471
return LayoutTy->getSize();
472
473
// TODO: What should we do with unannotated arrays?
474
return DL.getTypeAllocSize(ElTy);
475
}
476
477
dxil::SamplerType ResourceTypeInfo::getSamplerType() const {
478
assert(isSampler() && "Not a Sampler");
479
return cast<SamplerExtType>(HandleTy)->getSamplerType();
480
}
481
482
ResourceTypeInfo::StructInfo
483
ResourceTypeInfo::getStruct(const DataLayout &DL) const {
484
assert(isStruct() && "Not a Struct");
485
486
Type *ElTy = cast<RawBufferExtType>(HandleTy)->getResourceType();
487
488
uint32_t Stride = DL.getTypeAllocSize(ElTy);
489
MaybeAlign Alignment;
490
if (auto *STy = dyn_cast<StructType>(ElTy))
491
Alignment = DL.getStructLayout(STy)->getAlignment();
492
uint32_t AlignLog2 = Alignment ? Log2(*Alignment) : 0;
493
return {Stride, AlignLog2};
494
}
495
496
static std::pair<Type *, bool> getTypedElementType(dxil::ResourceKind Kind,
497
TargetExtType *Ty) {
498
switch (Kind) {
499
case ResourceKind::Texture1D:
500
case ResourceKind::Texture2D:
501
case ResourceKind::Texture3D:
502
case ResourceKind::TextureCube:
503
case ResourceKind::Texture1DArray:
504
case ResourceKind::Texture2DArray:
505
case ResourceKind::TextureCubeArray: {
506
auto *RTy = cast<TextureExtType>(Ty);
507
return {RTy->getResourceType(), RTy->isSigned()};
508
}
509
case ResourceKind::Texture2DMS:
510
case ResourceKind::Texture2DMSArray: {
511
auto *RTy = cast<MSTextureExtType>(Ty);
512
return {RTy->getResourceType(), RTy->isSigned()};
513
}
514
case ResourceKind::TypedBuffer: {
515
auto *RTy = cast<TypedBufferExtType>(Ty);
516
return {RTy->getResourceType(), RTy->isSigned()};
517
}
518
case ResourceKind::RawBuffer:
519
case ResourceKind::StructuredBuffer:
520
case ResourceKind::FeedbackTexture2D:
521
case ResourceKind::FeedbackTexture2DArray:
522
case ResourceKind::CBuffer:
523
case ResourceKind::Sampler:
524
case ResourceKind::TBuffer:
525
case ResourceKind::RTAccelerationStructure:
526
case ResourceKind::Invalid:
527
case ResourceKind::NumEntries:
528
llvm_unreachable("Resource is not typed");
529
}
530
llvm_unreachable("Unhandled ResourceKind enum");
531
}
532
533
ResourceTypeInfo::TypedInfo ResourceTypeInfo::getTyped() const {
534
assert(isTyped() && "Not typed");
535
536
auto [ElTy, IsSigned] = getTypedElementType(Kind, HandleTy);
537
dxil::ElementType ET = toDXILElementType(ElTy, IsSigned);
538
uint32_t Count = 1;
539
if (auto *VTy = dyn_cast<FixedVectorType>(ElTy))
540
Count = VTy->getNumElements();
541
return {ET, Count};
542
}
543
544
dxil::SamplerFeedbackType ResourceTypeInfo::getFeedbackType() const {
545
assert(isFeedback() && "Not Feedback");
546
return cast<FeedbackTextureExtType>(HandleTy)->getFeedbackType();
547
}
548
uint32_t ResourceTypeInfo::getMultiSampleCount() const {
549
assert(isMultiSample() && "Not MultiSampled");
550
return cast<MSTextureExtType>(HandleTy)->getSampleCount();
551
}
552
553
bool ResourceTypeInfo::operator==(const ResourceTypeInfo &RHS) const {
554
return HandleTy == RHS.HandleTy;
555
}
556
557
bool ResourceTypeInfo::operator<(const ResourceTypeInfo &RHS) const {
558
// An empty datalayout is sufficient for sorting purposes.
559
DataLayout DummyDL;
560
if (std::tie(RC, Kind) < std::tie(RHS.RC, RHS.Kind))
561
return true;
562
if (isCBuffer() && RHS.isCBuffer() &&
563
getCBufferSize(DummyDL) < RHS.getCBufferSize(DummyDL))
564
return true;
565
if (isSampler() && RHS.isSampler() && getSamplerType() < RHS.getSamplerType())
566
return true;
567
if (isUAV() && RHS.isUAV() && getUAV() < RHS.getUAV())
568
return true;
569
if (isStruct() && RHS.isStruct() &&
570
getStruct(DummyDL) < RHS.getStruct(DummyDL))
571
return true;
572
if (isFeedback() && RHS.isFeedback() &&
573
getFeedbackType() < RHS.getFeedbackType())
574
return true;
575
if (isTyped() && RHS.isTyped() && getTyped() < RHS.getTyped())
576
return true;
577
if (isMultiSample() && RHS.isMultiSample() &&
578
getMultiSampleCount() < RHS.getMultiSampleCount())
579
return true;
580
return false;
581
}
582
583
void ResourceTypeInfo::print(raw_ostream &OS, const DataLayout &DL) const {
584
OS << " Class: " << getResourceClassName(RC) << "\n"
585
<< " Kind: " << getResourceKindName(Kind) << "\n";
586
587
if (isCBuffer()) {
588
OS << " CBuffer size: " << getCBufferSize(DL) << "\n";
589
} else if (isSampler()) {
590
OS << " Sampler Type: " << getSamplerTypeName(getSamplerType()) << "\n";
591
} else {
592
if (isUAV()) {
593
UAVInfo UAVFlags = getUAV();
594
OS << " IsROV: " << UAVFlags.IsROV << "\n";
595
}
596
if (isMultiSample())
597
OS << " Sample Count: " << getMultiSampleCount() << "\n";
598
599
if (isStruct()) {
600
StructInfo Struct = getStruct(DL);
601
OS << " Buffer Stride: " << Struct.Stride << "\n";
602
OS << " Alignment: " << Struct.AlignLog2 << "\n";
603
} else if (isTyped()) {
604
TypedInfo Typed = getTyped();
605
OS << " Element Type: " << getElementTypeName(Typed.ElementTy) << "\n"
606
<< " Element Count: " << Typed.ElementCount << "\n";
607
} else if (isFeedback())
608
OS << " Feedback Type: " << getSamplerFeedbackTypeName(getFeedbackType())
609
<< "\n";
610
}
611
}
612
613
GlobalVariable *ResourceInfo::createSymbol(Module &M, StructType *Ty) {
614
assert(!Symbol && "Symbol has already been created");
615
Symbol = new GlobalVariable(M, Ty, /*isConstant=*/true,
616
GlobalValue::ExternalLinkage,
617
/*Initializer=*/nullptr, Name);
618
return Symbol;
619
}
620
621
MDTuple *ResourceInfo::getAsMetadata(Module &M,
622
dxil::ResourceTypeInfo &RTI) const {
623
LLVMContext &Ctx = M.getContext();
624
const DataLayout &DL = M.getDataLayout();
625
626
SmallVector<Metadata *, 11> MDVals;
627
628
Type *I32Ty = Type::getInt32Ty(Ctx);
629
Type *I1Ty = Type::getInt1Ty(Ctx);
630
auto getIntMD = [&I32Ty](uint32_t V) {
631
return ConstantAsMetadata::get(
632
Constant::getIntegerValue(I32Ty, APInt(32, V)));
633
};
634
auto getBoolMD = [&I1Ty](uint32_t V) {
635
return ConstantAsMetadata::get(
636
Constant::getIntegerValue(I1Ty, APInt(1, V)));
637
};
638
639
MDVals.push_back(getIntMD(Binding.RecordID));
640
assert(Symbol && "Cannot yet create useful resource metadata without symbol");
641
MDVals.push_back(ValueAsMetadata::get(Symbol));
642
MDVals.push_back(MDString::get(Ctx, Name));
643
MDVals.push_back(getIntMD(Binding.Space));
644
MDVals.push_back(getIntMD(Binding.LowerBound));
645
MDVals.push_back(getIntMD(Binding.Size));
646
647
if (RTI.isCBuffer()) {
648
MDVals.push_back(getIntMD(RTI.getCBufferSize(DL)));
649
MDVals.push_back(nullptr);
650
} else if (RTI.isSampler()) {
651
MDVals.push_back(getIntMD(llvm::to_underlying(RTI.getSamplerType())));
652
MDVals.push_back(nullptr);
653
} else {
654
MDVals.push_back(getIntMD(llvm::to_underlying(RTI.getResourceKind())));
655
656
if (RTI.isUAV()) {
657
ResourceTypeInfo::UAVInfo UAVFlags = RTI.getUAV();
658
MDVals.push_back(getBoolMD(GloballyCoherent));
659
MDVals.push_back(getBoolMD(hasCounter()));
660
MDVals.push_back(getBoolMD(UAVFlags.IsROV));
661
} else {
662
// All SRVs include sample count in the metadata, but it's only meaningful
663
// for multi-sampled textured. Also, UAVs can be multisampled in SM6.7+,
664
// but this just isn't reflected in the metadata at all.
665
uint32_t SampleCount =
666
RTI.isMultiSample() ? RTI.getMultiSampleCount() : 0;
667
MDVals.push_back(getIntMD(SampleCount));
668
}
669
670
// Further properties are attached to a metadata list of tag-value pairs.
671
SmallVector<Metadata *> Tags;
672
if (RTI.isStruct()) {
673
Tags.push_back(
674
getIntMD(llvm::to_underlying(ExtPropTags::StructuredBufferStride)));
675
Tags.push_back(getIntMD(RTI.getStruct(DL).Stride));
676
} else if (RTI.isTyped()) {
677
Tags.push_back(getIntMD(llvm::to_underlying(ExtPropTags::ElementType)));
678
Tags.push_back(getIntMD(llvm::to_underlying(RTI.getTyped().ElementTy)));
679
} else if (RTI.isFeedback()) {
680
Tags.push_back(
681
getIntMD(llvm::to_underlying(ExtPropTags::SamplerFeedbackKind)));
682
Tags.push_back(getIntMD(llvm::to_underlying(RTI.getFeedbackType())));
683
}
684
MDVals.push_back(Tags.empty() ? nullptr : MDNode::get(Ctx, Tags));
685
}
686
687
return MDNode::get(Ctx, MDVals);
688
}
689
690
std::pair<uint32_t, uint32_t>
691
ResourceInfo::getAnnotateProps(Module &M, dxil::ResourceTypeInfo &RTI) const {
692
const DataLayout &DL = M.getDataLayout();
693
694
uint32_t ResourceKind = llvm::to_underlying(RTI.getResourceKind());
695
uint32_t AlignLog2 = RTI.isStruct() ? RTI.getStruct(DL).AlignLog2 : 0;
696
bool IsUAV = RTI.isUAV();
697
ResourceTypeInfo::UAVInfo UAVFlags =
698
IsUAV ? RTI.getUAV() : ResourceTypeInfo::UAVInfo{};
699
bool IsROV = IsUAV && UAVFlags.IsROV;
700
bool IsGloballyCoherent = IsUAV && GloballyCoherent;
701
uint8_t SamplerCmpOrHasCounter = 0;
702
if (IsUAV)
703
SamplerCmpOrHasCounter = hasCounter();
704
else if (RTI.isSampler())
705
SamplerCmpOrHasCounter = RTI.getSamplerType() == SamplerType::Comparison;
706
707
// TODO: Document this format. Currently the only reference is the
708
// implementation of dxc's DxilResourceProperties struct.
709
uint32_t Word0 = 0;
710
Word0 |= ResourceKind & 0xFF;
711
Word0 |= (AlignLog2 & 0xF) << 8;
712
Word0 |= (IsUAV & 1) << 12;
713
Word0 |= (IsROV & 1) << 13;
714
Word0 |= (IsGloballyCoherent & 1) << 14;
715
Word0 |= (SamplerCmpOrHasCounter & 1) << 15;
716
717
uint32_t Word1 = 0;
718
if (RTI.isStruct())
719
Word1 = RTI.getStruct(DL).Stride;
720
else if (RTI.isCBuffer())
721
Word1 = RTI.getCBufferSize(DL);
722
else if (RTI.isFeedback())
723
Word1 = llvm::to_underlying(RTI.getFeedbackType());
724
else if (RTI.isTyped()) {
725
ResourceTypeInfo::TypedInfo Typed = RTI.getTyped();
726
uint32_t CompType = llvm::to_underlying(Typed.ElementTy);
727
uint32_t CompCount = Typed.ElementCount;
728
uint32_t SampleCount = RTI.isMultiSample() ? RTI.getMultiSampleCount() : 0;
729
730
Word1 |= (CompType & 0xFF) << 0;
731
Word1 |= (CompCount & 0xFF) << 8;
732
Word1 |= (SampleCount & 0xFF) << 16;
733
}
734
735
return {Word0, Word1};
736
}
737
738
void ResourceInfo::print(raw_ostream &OS, dxil::ResourceTypeInfo &RTI,
739
const DataLayout &DL) const {
740
if (!Name.empty())
741
OS << " Name: " << Name << "\n";
742
743
if (Symbol) {
744
OS << " Symbol: ";
745
Symbol->printAsOperand(OS);
746
OS << "\n";
747
}
748
749
OS << " Binding:\n"
750
<< " Record ID: " << Binding.RecordID << "\n"
751
<< " Space: " << Binding.Space << "\n"
752
<< " Lower Bound: " << Binding.LowerBound << "\n"
753
<< " Size: " << Binding.Size << "\n";
754
755
OS << " Globally Coherent: " << GloballyCoherent << "\n";
756
OS << " Counter Direction: ";
757
758
switch (CounterDirection) {
759
case ResourceCounterDirection::Increment:
760
OS << "Increment\n";
761
break;
762
case ResourceCounterDirection::Decrement:
763
OS << "Decrement\n";
764
break;
765
case ResourceCounterDirection::Unknown:
766
OS << "Unknown\n";
767
break;
768
case ResourceCounterDirection::Invalid:
769
OS << "Invalid\n";
770
break;
771
}
772
773
RTI.print(OS, DL);
774
}
775
776
//===----------------------------------------------------------------------===//
777
778
bool DXILResourceTypeMap::invalidate(Module &M, const PreservedAnalyses &PA,
779
ModuleAnalysisManager::Invalidator &Inv) {
780
// Passes that introduce resource types must explicitly invalidate this pass.
781
auto PAC = PA.getChecker<DXILResourceTypeAnalysis>();
782
return !PAC.preservedWhenStateless();
783
}
784
785
//===----------------------------------------------------------------------===//
786
static bool isUpdateCounterIntrinsic(Function &F) {
787
return F.getIntrinsicID() == Intrinsic::dx_resource_updatecounter;
788
}
789
790
StringRef dxil::getResourceNameFromBindingCall(CallInst *CI) {
791
Value *Op = nullptr;
792
switch (CI->getCalledFunction()->getIntrinsicID()) {
793
default:
794
llvm_unreachable("unexpected handle creation intrinsic");
795
case Intrinsic::dx_resource_handlefrombinding:
796
case Intrinsic::dx_resource_handlefromimplicitbinding:
797
Op = CI->getArgOperand(5);
798
break;
799
}
800
801
auto *GV = dyn_cast<llvm::GlobalVariable>(Op);
802
if (!GV)
803
return "";
804
805
auto *CA = dyn_cast<ConstantDataArray>(GV->getInitializer());
806
assert(CA && CA->isString() && "expected constant string");
807
StringRef Name = CA->getAsString();
808
// strip trailing 0
809
if (Name.ends_with('\0'))
810
Name = Name.drop_back(1);
811
return Name;
812
}
813
814
void DXILResourceMap::populateResourceInfos(Module &M,
815
DXILResourceTypeMap &DRTM) {
816
SmallVector<std::tuple<CallInst *, ResourceInfo, ResourceTypeInfo>> CIToInfos;
817
818
for (Function &F : M.functions()) {
819
if (!F.isDeclaration())
820
continue;
821
LLVM_DEBUG(dbgs() << "Function: " << F.getName() << "\n");
822
Intrinsic::ID ID = F.getIntrinsicID();
823
switch (ID) {
824
default:
825
continue;
826
case Intrinsic::dx_resource_handlefrombinding: {
827
auto *HandleTy = cast<TargetExtType>(F.getReturnType());
828
ResourceTypeInfo &RTI = DRTM[HandleTy];
829
830
for (User *U : F.users())
831
if (CallInst *CI = dyn_cast<CallInst>(U)) {
832
LLVM_DEBUG(dbgs() << " Visiting: " << *U << "\n");
833
uint32_t Space =
834
cast<ConstantInt>(CI->getArgOperand(0))->getZExtValue();
835
uint32_t LowerBound =
836
cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
837
uint32_t Size =
838
cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
839
StringRef Name = getResourceNameFromBindingCall(CI);
840
841
ResourceInfo RI =
842
ResourceInfo{/*RecordID=*/0, Space, LowerBound,
843
Size, HandleTy, Name};
844
845
CIToInfos.emplace_back(CI, RI, RTI);
846
}
847
848
break;
849
}
850
}
851
}
852
853
llvm::stable_sort(CIToInfos, [](auto &LHS, auto &RHS) {
854
const auto &[LCI, LRI, LRTI] = LHS;
855
const auto &[RCI, RRI, RRTI] = RHS;
856
// Sort by resource class first for grouping purposes, and then by the
857
// binding and type so we can remove duplicates.
858
ResourceClass LRC = LRTI.getResourceClass();
859
ResourceClass RRC = RRTI.getResourceClass();
860
861
return std::tie(LRC, LRI, LRTI) < std::tie(RRC, RRI, RRTI);
862
});
863
for (auto [CI, RI, RTI] : CIToInfos) {
864
if (Infos.empty() || RI != Infos.back())
865
Infos.push_back(RI);
866
CallMap[CI] = Infos.size() - 1;
867
}
868
869
unsigned Size = Infos.size();
870
// In DXC, Record ID is unique per resource type. Match that.
871
FirstUAV = FirstCBuffer = FirstSampler = Size;
872
uint32_t NextID = 0;
873
for (unsigned I = 0, E = Size; I != E; ++I) {
874
ResourceInfo &RI = Infos[I];
875
ResourceTypeInfo &RTI = DRTM[RI.getHandleTy()];
876
if (RTI.isUAV() && FirstUAV == Size) {
877
FirstUAV = I;
878
NextID = 0;
879
} else if (RTI.isCBuffer() && FirstCBuffer == Size) {
880
FirstCBuffer = I;
881
NextID = 0;
882
} else if (RTI.isSampler() && FirstSampler == Size) {
883
FirstSampler = I;
884
NextID = 0;
885
}
886
887
// We need to make sure the types of resource are ordered even if some are
888
// missing.
889
FirstCBuffer = std::min({FirstCBuffer, FirstSampler});
890
FirstUAV = std::min({FirstUAV, FirstCBuffer});
891
892
// Adjust the resource binding to use the next ID.
893
RI.setBindingID(NextID++);
894
}
895
}
896
897
void DXILResourceMap::populateCounterDirections(Module &M) {
898
for (Function &F : M.functions()) {
899
if (!isUpdateCounterIntrinsic(F))
900
continue;
901
902
LLVM_DEBUG(dbgs() << "Update Counter Function: " << F.getName() << "\n");
903
904
for (const User *U : F.users()) {
905
const CallInst *CI = dyn_cast<CallInst>(U);
906
assert(CI && "Users of dx_resource_updateCounter must be call instrs");
907
908
// Determine if the use is an increment or decrement
909
Value *CountArg = CI->getArgOperand(1);
910
ConstantInt *CountValue = cast<ConstantInt>(CountArg);
911
int64_t CountLiteral = CountValue->getSExtValue();
912
913
// 0 is an unknown direction and shouldn't result in an insert
914
if (CountLiteral == 0)
915
continue;
916
917
ResourceCounterDirection Direction = ResourceCounterDirection::Decrement;
918
if (CountLiteral > 0)
919
Direction = ResourceCounterDirection::Increment;
920
921
// Collect all potential creation points for the handle arg
922
Value *HandleArg = CI->getArgOperand(0);
923
SmallVector<ResourceInfo *> RBInfos = findByUse(HandleArg);
924
for (ResourceInfo *RBInfo : RBInfos) {
925
if (RBInfo->CounterDirection == ResourceCounterDirection::Unknown)
926
RBInfo->CounterDirection = Direction;
927
else if (RBInfo->CounterDirection != Direction) {
928
RBInfo->CounterDirection = ResourceCounterDirection::Invalid;
929
HasInvalidDirection = true;
930
}
931
}
932
}
933
}
934
}
935
936
void DXILResourceMap::populate(Module &M, DXILResourceTypeMap &DRTM) {
937
populateResourceInfos(M, DRTM);
938
populateCounterDirections(M);
939
}
940
941
void DXILResourceMap::print(raw_ostream &OS, DXILResourceTypeMap &DRTM,
942
const DataLayout &DL) const {
943
for (unsigned I = 0, E = Infos.size(); I != E; ++I) {
944
OS << "Resource " << I << ":\n";
945
const dxil::ResourceInfo &RI = Infos[I];
946
RI.print(OS, DRTM[RI.getHandleTy()], DL);
947
OS << "\n";
948
}
949
950
for (const auto &[CI, Index] : CallMap) {
951
OS << "Call bound to " << Index << ":";
952
CI->print(OS);
953
OS << "\n";
954
}
955
}
956
957
SmallVector<dxil::ResourceInfo *> DXILResourceMap::findByUse(const Value *Key) {
958
if (const PHINode *Phi = dyn_cast<PHINode>(Key)) {
959
SmallVector<dxil::ResourceInfo *> Children;
960
for (const Value *V : Phi->operands()) {
961
Children.append(findByUse(V));
962
}
963
return Children;
964
}
965
966
const CallInst *CI = dyn_cast<CallInst>(Key);
967
if (!CI)
968
return {};
969
970
switch (CI->getIntrinsicID()) {
971
// Found the create, return the binding
972
case Intrinsic::dx_resource_handlefrombinding: {
973
auto Pos = CallMap.find(CI);
974
assert(Pos != CallMap.end() && "HandleFromBinding must be in resource map");
975
return {&Infos[Pos->second]};
976
}
977
default:
978
break;
979
}
980
981
// Check if any of the parameters are the resource we are following. If so
982
// keep searching. If none of them are return an empty list
983
const Type *UseType = CI->getType();
984
SmallVector<dxil::ResourceInfo *> Children;
985
for (const Value *V : CI->args()) {
986
if (V->getType() != UseType)
987
continue;
988
989
Children.append(findByUse(V));
990
}
991
992
return Children;
993
}
994
995
//===----------------------------------------------------------------------===//
996
997
void DXILResourceBindingInfo::populate(Module &M, DXILResourceTypeMap &DRTM) {
998
struct Binding {
999
ResourceClass RC;
1000
uint32_t Space;
1001
uint32_t LowerBound;
1002
uint32_t UpperBound;
1003
Value *Name;
1004
Binding(ResourceClass RC, uint32_t Space, uint32_t LowerBound,
1005
uint32_t UpperBound, Value *Name)
1006
: RC(RC), Space(Space), LowerBound(LowerBound), UpperBound(UpperBound),
1007
Name(Name) {}
1008
};
1009
SmallVector<Binding> Bindings;
1010
1011
// collect all of the llvm.dx.resource.handlefrombinding calls;
1012
// make a note if there is llvm.dx.resource.handlefromimplicitbinding
1013
for (Function &F : M.functions()) {
1014
if (!F.isDeclaration())
1015
continue;
1016
1017
switch (F.getIntrinsicID()) {
1018
default:
1019
continue;
1020
case Intrinsic::dx_resource_handlefrombinding: {
1021
auto *HandleTy = cast<TargetExtType>(F.getReturnType());
1022
ResourceTypeInfo &RTI = DRTM[HandleTy];
1023
1024
for (User *U : F.users())
1025
if (CallInst *CI = dyn_cast<CallInst>(U)) {
1026
uint32_t Space =
1027
cast<ConstantInt>(CI->getArgOperand(0))->getZExtValue();
1028
uint32_t LowerBound =
1029
cast<ConstantInt>(CI->getArgOperand(1))->getZExtValue();
1030
int32_t Size =
1031
cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();
1032
Value *Name = CI->getArgOperand(5);
1033
1034
// negative size means unbounded resource array;
1035
// upper bound register overflow should be detected in Sema
1036
assert((Size < 0 || (unsigned)LowerBound + Size - 1 <= UINT32_MAX) &&
1037
"upper bound register overflow");
1038
uint32_t UpperBound = Size < 0 ? UINT32_MAX : LowerBound + Size - 1;
1039
Bindings.emplace_back(RTI.getResourceClass(), Space, LowerBound,
1040
UpperBound, Name);
1041
}
1042
break;
1043
}
1044
case Intrinsic::dx_resource_handlefromimplicitbinding: {
1045
ImplicitBinding = true;
1046
break;
1047
}
1048
}
1049
}
1050
1051
// sort all the collected bindings
1052
llvm::stable_sort(Bindings, [](auto &LHS, auto &RHS) {
1053
return std::tie(LHS.RC, LHS.Space, LHS.LowerBound) <
1054
std::tie(RHS.RC, RHS.Space, RHS.LowerBound);
1055
});
1056
1057
// remove duplicates
1058
Binding *NewEnd = llvm::unique(Bindings, [](auto &LHS, auto &RHS) {
1059
return std::tie(LHS.RC, LHS.Space, LHS.LowerBound, LHS.UpperBound,
1060
LHS.Name) == std::tie(RHS.RC, RHS.Space, RHS.LowerBound,
1061
RHS.UpperBound, RHS.Name);
1062
});
1063
if (NewEnd != Bindings.end())
1064
Bindings.erase(NewEnd);
1065
1066
// Go over the sorted bindings and build up lists of free register ranges
1067
// for each binding type and used spaces. Bindings are sorted by resource
1068
// class, space, and lower bound register slot.
1069
BindingSpaces *BS = &SRVSpaces;
1070
for (const Binding &B : Bindings) {
1071
if (BS->RC != B.RC)
1072
// move to the next resource class spaces
1073
BS = &getBindingSpaces(B.RC);
1074
1075
RegisterSpace *S = BS->Spaces.empty() ? &BS->Spaces.emplace_back(B.Space)
1076
: &BS->Spaces.back();
1077
assert(S->Space <= B.Space && "bindings not sorted correctly?");
1078
if (B.Space != S->Space)
1079
// add new space
1080
S = &BS->Spaces.emplace_back(B.Space);
1081
1082
// the space is full - set flag to report overlapping binding later
1083
if (S->FreeRanges.empty()) {
1084
OverlappingBinding = true;
1085
continue;
1086
}
1087
1088
// adjust the last free range lower bound, split it in two, or remove it
1089
BindingRange &LastFreeRange = S->FreeRanges.back();
1090
assert(LastFreeRange.UpperBound == UINT32_MAX);
1091
if (LastFreeRange.LowerBound == B.LowerBound) {
1092
if (B.UpperBound < UINT32_MAX)
1093
LastFreeRange.LowerBound = B.UpperBound + 1;
1094
else
1095
S->FreeRanges.pop_back();
1096
} else if (LastFreeRange.LowerBound < B.LowerBound) {
1097
LastFreeRange.UpperBound = B.LowerBound - 1;
1098
if (B.UpperBound < UINT32_MAX)
1099
S->FreeRanges.emplace_back(B.UpperBound + 1, UINT32_MAX);
1100
} else {
1101
OverlappingBinding = true;
1102
if (B.UpperBound < UINT32_MAX)
1103
LastFreeRange.LowerBound =
1104
std::max(LastFreeRange.LowerBound, B.UpperBound + 1);
1105
else
1106
S->FreeRanges.pop_back();
1107
}
1108
}
1109
}
1110
1111
// returns std::nulopt if binding could not be found in given space
1112
std::optional<uint32_t>
1113
DXILResourceBindingInfo::findAvailableBinding(dxil::ResourceClass RC,
1114
uint32_t Space, int32_t Size) {
1115
BindingSpaces &BS = getBindingSpaces(RC);
1116
RegisterSpace &RS = BS.getOrInsertSpace(Space);
1117
return RS.findAvailableBinding(Size);
1118
}
1119
1120
DXILResourceBindingInfo::RegisterSpace &
1121
DXILResourceBindingInfo::BindingSpaces::getOrInsertSpace(uint32_t Space) {
1122
for (auto *I = Spaces.begin(); I != Spaces.end(); ++I) {
1123
if (I->Space == Space)
1124
return *I;
1125
if (I->Space < Space)
1126
continue;
1127
return *Spaces.insert(I, Space);
1128
}
1129
return Spaces.emplace_back(Space);
1130
}
1131
1132
std::optional<uint32_t>
1133
DXILResourceBindingInfo::RegisterSpace::findAvailableBinding(int32_t Size) {
1134
assert((Size == -1 || Size > 0) && "invalid size");
1135
1136
if (FreeRanges.empty())
1137
return std::nullopt;
1138
1139
// unbounded array
1140
if (Size == -1) {
1141
BindingRange &Last = FreeRanges.back();
1142
if (Last.UpperBound != UINT32_MAX)
1143
// this space is already occupied by an unbounded array
1144
return std::nullopt;
1145
uint32_t RegSlot = Last.LowerBound;
1146
FreeRanges.pop_back();
1147
return RegSlot;
1148
}
1149
1150
// single resource or fixed-size array
1151
for (BindingRange &R : FreeRanges) {
1152
// compare the size as uint64_t to prevent overflow for range (0,
1153
// UINT32_MAX)
1154
if ((uint64_t)R.UpperBound - R.LowerBound + 1 < (uint64_t)Size)
1155
continue;
1156
uint32_t RegSlot = R.LowerBound;
1157
// This might create a range where (LowerBound == UpperBound + 1). When
1158
// that happens, the next time this function is called the range will
1159
// skipped over by the check above (at this point Size is always > 0).
1160
R.LowerBound += Size;
1161
return RegSlot;
1162
}
1163
1164
return std::nullopt;
1165
}
1166
1167
//===----------------------------------------------------------------------===//
1168
1169
AnalysisKey DXILResourceTypeAnalysis::Key;
1170
AnalysisKey DXILResourceAnalysis::Key;
1171
AnalysisKey DXILResourceBindingAnalysis::Key;
1172
1173
DXILResourceMap DXILResourceAnalysis::run(Module &M,
1174
ModuleAnalysisManager &AM) {
1175
DXILResourceMap Data;
1176
DXILResourceTypeMap &DRTM = AM.getResult<DXILResourceTypeAnalysis>(M);
1177
Data.populate(M, DRTM);
1178
return Data;
1179
}
1180
1181
DXILResourceBindingInfo
1182
DXILResourceBindingAnalysis::run(Module &M, ModuleAnalysisManager &AM) {
1183
DXILResourceBindingInfo Data;
1184
DXILResourceTypeMap &DRTM = AM.getResult<DXILResourceTypeAnalysis>(M);
1185
Data.populate(M, DRTM);
1186
return Data;
1187
}
1188
1189
PreservedAnalyses DXILResourcePrinterPass::run(Module &M,
1190
ModuleAnalysisManager &AM) {
1191
DXILResourceMap &DRM = AM.getResult<DXILResourceAnalysis>(M);
1192
DXILResourceTypeMap &DRTM = AM.getResult<DXILResourceTypeAnalysis>(M);
1193
1194
DRM.print(OS, DRTM, M.getDataLayout());
1195
return PreservedAnalyses::all();
1196
}
1197
1198
void DXILResourceTypeWrapperPass::anchor() {}
1199
1200
DXILResourceTypeWrapperPass::DXILResourceTypeWrapperPass()
1201
: ImmutablePass(ID) {}
1202
1203
INITIALIZE_PASS(DXILResourceTypeWrapperPass, "dxil-resource-type",
1204
"DXIL Resource Type Analysis", false, true)
1205
char DXILResourceTypeWrapperPass::ID = 0;
1206
1207
ModulePass *llvm::createDXILResourceTypeWrapperPassPass() {
1208
return new DXILResourceTypeWrapperPass();
1209
}
1210
1211
DXILResourceWrapperPass::DXILResourceWrapperPass() : ModulePass(ID) {}
1212
1213
DXILResourceWrapperPass::~DXILResourceWrapperPass() = default;
1214
1215
void DXILResourceWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
1216
AU.addRequiredTransitive<DXILResourceTypeWrapperPass>();
1217
AU.setPreservesAll();
1218
}
1219
1220
bool DXILResourceWrapperPass::runOnModule(Module &M) {
1221
Map.reset(new DXILResourceMap());
1222
1223
DRTM = &getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();
1224
Map->populate(M, *DRTM);
1225
1226
return false;
1227
}
1228
1229
void DXILResourceWrapperPass::releaseMemory() { Map.reset(); }
1230
1231
void DXILResourceWrapperPass::print(raw_ostream &OS, const Module *M) const {
1232
if (!Map) {
1233
OS << "No resource map has been built!\n";
1234
return;
1235
}
1236
Map->print(OS, *DRTM, M->getDataLayout());
1237
}
1238
1239
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1240
LLVM_DUMP_METHOD
1241
void DXILResourceWrapperPass::dump() const { print(dbgs(), nullptr); }
1242
#endif
1243
1244
INITIALIZE_PASS(DXILResourceWrapperPass, "dxil-resources",
1245
"DXIL Resources Analysis", false, true)
1246
char DXILResourceWrapperPass::ID = 0;
1247
1248
ModulePass *llvm::createDXILResourceWrapperPassPass() {
1249
return new DXILResourceWrapperPass();
1250
}
1251
1252
DXILResourceBindingWrapperPass::DXILResourceBindingWrapperPass()
1253
: ModulePass(ID) {}
1254
1255
DXILResourceBindingWrapperPass::~DXILResourceBindingWrapperPass() = default;
1256
1257
void DXILResourceBindingWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
1258
AU.addRequiredTransitive<DXILResourceTypeWrapperPass>();
1259
AU.setPreservesAll();
1260
}
1261
1262
bool DXILResourceBindingWrapperPass::runOnModule(Module &M) {
1263
BindingInfo.reset(new DXILResourceBindingInfo());
1264
1265
DXILResourceTypeMap &DRTM =
1266
getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();
1267
BindingInfo->populate(M, DRTM);
1268
1269
return false;
1270
}
1271
1272
void DXILResourceBindingWrapperPass::releaseMemory() { BindingInfo.reset(); }
1273
1274
INITIALIZE_PASS(DXILResourceBindingWrapperPass, "dxil-resource-binding",
1275
"DXIL Resource Binding Analysis", false, true)
1276
char DXILResourceBindingWrapperPass::ID = 0;
1277
1278
ModulePass *llvm::createDXILResourceBindingWrapperPassPass() {
1279
return new DXILResourceWrapperPass();
1280
}
1281
1282