File indexing completed on 2026-05-10 08:43:12
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLVM_ANALYSIS_DXILRESOURCE_H
0010 #define LLVM_ANALYSIS_DXILRESOURCE_H
0011
0012 #include "llvm/ADT/MapVector.h"
0013 #include "llvm/ADT/StringRef.h"
0014 #include "llvm/IR/DerivedTypes.h"
0015 #include "llvm/IR/GlobalVariable.h"
0016 #include "llvm/IR/PassManager.h"
0017 #include "llvm/Pass.h"
0018 #include "llvm/Support/Alignment.h"
0019 #include "llvm/Support/DXILABI.h"
0020
0021 namespace llvm {
0022 class CallInst;
0023 class DataLayout;
0024 class LLVMContext;
0025 class MDTuple;
0026 class Value;
0027
0028 class DXILResourceTypeMap;
0029
0030 namespace dxil {
0031
0032
0033
0034
0035 class RawBufferExtType : public TargetExtType {
0036 public:
0037 RawBufferExtType() = delete;
0038 RawBufferExtType(const RawBufferExtType &) = delete;
0039 RawBufferExtType &operator=(const RawBufferExtType &) = delete;
0040
0041 bool isStructured() const {
0042
0043
0044
0045 Type *Ty = getTypeParameter(0);
0046 return !Ty->isVoidTy() && !Ty->isIntegerTy(8);
0047 }
0048
0049 Type *getResourceType() const {
0050 return isStructured() ? getTypeParameter(0) : nullptr;
0051 }
0052 bool isWriteable() const { return getIntParameter(0); }
0053 bool isROV() const { return getIntParameter(1); }
0054
0055 static bool classof(const TargetExtType *T) {
0056 return T->getName() == "dx.RawBuffer";
0057 }
0058 static bool classof(const Type *T) {
0059 return isa<TargetExtType>(T) && classof(cast<TargetExtType>(T));
0060 }
0061 };
0062
0063
0064
0065
0066 class TypedBufferExtType : public TargetExtType {
0067 public:
0068 TypedBufferExtType() = delete;
0069 TypedBufferExtType(const TypedBufferExtType &) = delete;
0070 TypedBufferExtType &operator=(const TypedBufferExtType &) = delete;
0071
0072 Type *getResourceType() const { return getTypeParameter(0); }
0073 bool isWriteable() const { return getIntParameter(0); }
0074 bool isROV() const { return getIntParameter(1); }
0075 bool isSigned() const { return getIntParameter(2); }
0076
0077 static bool classof(const TargetExtType *T) {
0078 return T->getName() == "dx.TypedBuffer";
0079 }
0080 static bool classof(const Type *T) {
0081 return isa<TargetExtType>(T) && classof(cast<TargetExtType>(T));
0082 }
0083 };
0084
0085
0086
0087
0088 class TextureExtType : public TargetExtType {
0089 public:
0090 TextureExtType() = delete;
0091 TextureExtType(const TextureExtType &) = delete;
0092 TextureExtType &operator=(const TextureExtType &) = delete;
0093
0094 Type *getResourceType() const { return getTypeParameter(0); }
0095 bool isWriteable() const { return getIntParameter(0); }
0096 bool isROV() const { return getIntParameter(1); }
0097 bool isSigned() const { return getIntParameter(2); }
0098 dxil::ResourceKind getDimension() const {
0099 return static_cast<dxil::ResourceKind>(getIntParameter(3));
0100 }
0101
0102 static bool classof(const TargetExtType *T) {
0103 return T->getName() == "dx.Texture";
0104 }
0105 static bool classof(const Type *T) {
0106 return isa<TargetExtType>(T) && classof(cast<TargetExtType>(T));
0107 }
0108 };
0109
0110
0111
0112
0113 class MSTextureExtType : public TargetExtType {
0114 public:
0115 MSTextureExtType() = delete;
0116 MSTextureExtType(const MSTextureExtType &) = delete;
0117 MSTextureExtType &operator=(const MSTextureExtType &) = delete;
0118
0119 Type *getResourceType() const { return getTypeParameter(0); }
0120 bool isWriteable() const { return getIntParameter(0); }
0121 uint32_t getSampleCount() const { return getIntParameter(1); }
0122 bool isSigned() const { return getIntParameter(2); }
0123 dxil::ResourceKind getDimension() const {
0124 return static_cast<dxil::ResourceKind>(getIntParameter(3));
0125 }
0126
0127 static bool classof(const TargetExtType *T) {
0128 return T->getName() == "dx.MSTexture";
0129 }
0130 static bool classof(const Type *T) {
0131 return isa<TargetExtType>(T) && classof(cast<TargetExtType>(T));
0132 }
0133 };
0134
0135
0136
0137
0138 class FeedbackTextureExtType : public TargetExtType {
0139 public:
0140 FeedbackTextureExtType() = delete;
0141 FeedbackTextureExtType(const FeedbackTextureExtType &) = delete;
0142 FeedbackTextureExtType &operator=(const FeedbackTextureExtType &) = delete;
0143
0144 dxil::SamplerFeedbackType getFeedbackType() const {
0145 return static_cast<dxil::SamplerFeedbackType>(getIntParameter(0));
0146 }
0147 dxil::ResourceKind getDimension() const {
0148 return static_cast<dxil::ResourceKind>(getIntParameter(1));
0149 }
0150
0151 static bool classof(const TargetExtType *T) {
0152 return T->getName() == "dx.FeedbackTexture";
0153 }
0154 static bool classof(const Type *T) {
0155 return isa<TargetExtType>(T) && classof(cast<TargetExtType>(T));
0156 }
0157 };
0158
0159
0160
0161
0162 class CBufferExtType : public TargetExtType {
0163 public:
0164 CBufferExtType() = delete;
0165 CBufferExtType(const CBufferExtType &) = delete;
0166 CBufferExtType &operator=(const CBufferExtType &) = delete;
0167
0168 Type *getResourceType() const { return getTypeParameter(0); }
0169 uint32_t getCBufferSize() const { return getIntParameter(0); }
0170
0171 static bool classof(const TargetExtType *T) {
0172 return T->getName() == "dx.CBuffer";
0173 }
0174 static bool classof(const Type *T) {
0175 return isa<TargetExtType>(T) && classof(cast<TargetExtType>(T));
0176 }
0177 };
0178
0179
0180
0181
0182 class SamplerExtType : public TargetExtType {
0183 public:
0184 SamplerExtType() = delete;
0185 SamplerExtType(const SamplerExtType &) = delete;
0186 SamplerExtType &operator=(const SamplerExtType &) = delete;
0187
0188 dxil::SamplerType getSamplerType() const {
0189 return static_cast<dxil::SamplerType>(getIntParameter(0));
0190 }
0191
0192 static bool classof(const TargetExtType *T) {
0193 return T->getName() == "dx.Sampler";
0194 }
0195 static bool classof(const Type *T) {
0196 return isa<TargetExtType>(T) && classof(cast<TargetExtType>(T));
0197 }
0198 };
0199
0200
0201
0202 class ResourceTypeInfo {
0203 public:
0204 struct UAVInfo {
0205 bool GloballyCoherent;
0206 bool HasCounter;
0207 bool IsROV;
0208
0209 bool operator==(const UAVInfo &RHS) const {
0210 return std::tie(GloballyCoherent, HasCounter, IsROV) ==
0211 std::tie(RHS.GloballyCoherent, RHS.HasCounter, RHS.IsROV);
0212 }
0213 bool operator!=(const UAVInfo &RHS) const { return !(*this == RHS); }
0214 bool operator<(const UAVInfo &RHS) const {
0215 return std::tie(GloballyCoherent, HasCounter, IsROV) <
0216 std::tie(RHS.GloballyCoherent, RHS.HasCounter, RHS.IsROV);
0217 }
0218 };
0219
0220 struct StructInfo {
0221 uint32_t Stride;
0222
0223
0224
0225
0226 uint32_t AlignLog2;
0227
0228 bool operator==(const StructInfo &RHS) const {
0229 return std::tie(Stride, AlignLog2) == std::tie(RHS.Stride, RHS.AlignLog2);
0230 }
0231 bool operator!=(const StructInfo &RHS) const { return !(*this == RHS); }
0232 bool operator<(const StructInfo &RHS) const {
0233 return std::tie(Stride, AlignLog2) < std::tie(RHS.Stride, RHS.AlignLog2);
0234 }
0235 };
0236
0237 struct TypedInfo {
0238 dxil::ElementType ElementTy;
0239 uint32_t ElementCount;
0240
0241 bool operator==(const TypedInfo &RHS) const {
0242 return std::tie(ElementTy, ElementCount) ==
0243 std::tie(RHS.ElementTy, RHS.ElementCount);
0244 }
0245 bool operator!=(const TypedInfo &RHS) const { return !(*this == RHS); }
0246 bool operator<(const TypedInfo &RHS) const {
0247 return std::tie(ElementTy, ElementCount) <
0248 std::tie(RHS.ElementTy, RHS.ElementCount);
0249 }
0250 };
0251
0252 private:
0253 TargetExtType *HandleTy;
0254
0255
0256
0257
0258 bool GloballyCoherent;
0259 bool HasCounter;
0260
0261 dxil::ResourceClass RC;
0262 dxil::ResourceKind Kind;
0263
0264 public:
0265 ResourceTypeInfo(TargetExtType *HandleTy, const dxil::ResourceClass RC,
0266 const dxil::ResourceKind Kind, bool GloballyCoherent = false,
0267 bool HasCounter = false);
0268 ResourceTypeInfo(TargetExtType *HandleTy, bool GloballyCoherent = false,
0269 bool HasCounter = false)
0270 : ResourceTypeInfo(HandleTy, {}, dxil::ResourceKind::Invalid,
0271 GloballyCoherent, HasCounter) {}
0272
0273 TargetExtType *getHandleTy() const { return HandleTy; }
0274 StructType *createElementStruct();
0275
0276
0277 bool isUAV() const;
0278 bool isCBuffer() const;
0279 bool isSampler() const;
0280 bool isStruct() const;
0281 bool isTyped() const;
0282 bool isFeedback() const;
0283 bool isMultiSample() const;
0284
0285
0286 UAVInfo getUAV() const;
0287 uint32_t getCBufferSize(const DataLayout &DL) const;
0288 dxil::SamplerType getSamplerType() const;
0289 StructInfo getStruct(const DataLayout &DL) const;
0290 TypedInfo getTyped() const;
0291 dxil::SamplerFeedbackType getFeedbackType() const;
0292 uint32_t getMultiSampleCount() const;
0293
0294 dxil::ResourceClass getResourceClass() const { return RC; }
0295 dxil::ResourceKind getResourceKind() const { return Kind; }
0296
0297 void setGloballyCoherent(bool V) { GloballyCoherent = V; }
0298 void setHasCounter(bool V) { HasCounter = V; }
0299
0300 bool operator==(const ResourceTypeInfo &RHS) const;
0301 bool operator!=(const ResourceTypeInfo &RHS) const { return !(*this == RHS); }
0302 bool operator<(const ResourceTypeInfo &RHS) const;
0303
0304 void print(raw_ostream &OS, const DataLayout &DL) const;
0305 };
0306
0307
0308
0309 class ResourceBindingInfo {
0310 public:
0311 struct ResourceBinding {
0312 uint32_t RecordID;
0313 uint32_t Space;
0314 uint32_t LowerBound;
0315 uint32_t Size;
0316
0317 bool operator==(const ResourceBinding &RHS) const {
0318 return std::tie(RecordID, Space, LowerBound, Size) ==
0319 std::tie(RHS.RecordID, RHS.Space, RHS.LowerBound, RHS.Size);
0320 }
0321 bool operator!=(const ResourceBinding &RHS) const {
0322 return !(*this == RHS);
0323 }
0324 bool operator<(const ResourceBinding &RHS) const {
0325 return std::tie(RecordID, Space, LowerBound, Size) <
0326 std::tie(RHS.RecordID, RHS.Space, RHS.LowerBound, RHS.Size);
0327 }
0328 };
0329
0330 private:
0331 ResourceBinding Binding;
0332 TargetExtType *HandleTy;
0333 GlobalVariable *Symbol = nullptr;
0334
0335 public:
0336 ResourceBindingInfo(uint32_t RecordID, uint32_t Space, uint32_t LowerBound,
0337 uint32_t Size, TargetExtType *HandleTy,
0338 GlobalVariable *Symbol = nullptr)
0339 : Binding{RecordID, Space, LowerBound, Size}, HandleTy(HandleTy),
0340 Symbol(Symbol) {}
0341
0342 void setBindingID(unsigned ID) { Binding.RecordID = ID; }
0343
0344 const ResourceBinding &getBinding() const { return Binding; }
0345 TargetExtType *getHandleTy() const { return HandleTy; }
0346 const StringRef getName() const { return Symbol ? Symbol->getName() : ""; }
0347
0348 bool hasSymbol() const { return Symbol; }
0349 GlobalVariable *createSymbol(Module &M, StructType *Ty, StringRef Name = "");
0350 MDTuple *getAsMetadata(Module &M, dxil::ResourceTypeInfo &RTI) const;
0351
0352 std::pair<uint32_t, uint32_t>
0353 getAnnotateProps(Module &M, dxil::ResourceTypeInfo &RTI) const;
0354
0355 bool operator==(const ResourceBindingInfo &RHS) const {
0356 return std::tie(Binding, HandleTy, Symbol) ==
0357 std::tie(RHS.Binding, RHS.HandleTy, RHS.Symbol);
0358 }
0359 bool operator!=(const ResourceBindingInfo &RHS) const {
0360 return !(*this == RHS);
0361 }
0362 bool operator<(const ResourceBindingInfo &RHS) const {
0363 return Binding < RHS.Binding;
0364 }
0365
0366 void print(raw_ostream &OS, dxil::ResourceTypeInfo &RTI,
0367 const DataLayout &DL) const;
0368 };
0369
0370 }
0371
0372
0373
0374 class DXILResourceTypeMap {
0375 DenseMap<TargetExtType *, dxil::ResourceTypeInfo> Infos;
0376
0377 public:
0378 bool invalidate(Module &M, const PreservedAnalyses &PA,
0379 ModuleAnalysisManager::Invalidator &Inv);
0380
0381 dxil::ResourceTypeInfo &operator[](TargetExtType *Ty) {
0382 auto It = Infos.find(Ty);
0383 if (It != Infos.end())
0384 return It->second;
0385 auto [NewIt, Inserted] = Infos.try_emplace(Ty, Ty);
0386 return NewIt->second;
0387 }
0388 };
0389
0390 class DXILResourceTypeAnalysis
0391 : public AnalysisInfoMixin<DXILResourceTypeAnalysis> {
0392 friend AnalysisInfoMixin<DXILResourceTypeAnalysis>;
0393
0394 static AnalysisKey Key;
0395
0396 public:
0397 using Result = DXILResourceTypeMap;
0398
0399 DXILResourceTypeMap run(Module &M, ModuleAnalysisManager &AM) {
0400
0401
0402 return Result();
0403 }
0404 };
0405
0406 class DXILResourceTypeWrapperPass : public ImmutablePass {
0407 DXILResourceTypeMap DRTM;
0408
0409 virtual void anchor();
0410
0411 public:
0412 static char ID;
0413 DXILResourceTypeWrapperPass();
0414
0415 DXILResourceTypeMap &getResourceTypeMap() { return DRTM; }
0416 const DXILResourceTypeMap &getResourceTypeMap() const { return DRTM; }
0417 };
0418
0419 ModulePass *createDXILResourceTypeWrapperPassPass();
0420
0421
0422
0423 class DXILBindingMap {
0424 SmallVector<dxil::ResourceBindingInfo> Infos;
0425 DenseMap<CallInst *, unsigned> CallMap;
0426 unsigned FirstUAV = 0;
0427 unsigned FirstCBuffer = 0;
0428 unsigned FirstSampler = 0;
0429
0430
0431 void populate(Module &M, DXILResourceTypeMap &DRTM);
0432
0433 public:
0434 using iterator = SmallVector<dxil::ResourceBindingInfo>::iterator;
0435 using const_iterator = SmallVector<dxil::ResourceBindingInfo>::const_iterator;
0436
0437 iterator begin() { return Infos.begin(); }
0438 const_iterator begin() const { return Infos.begin(); }
0439 iterator end() { return Infos.end(); }
0440 const_iterator end() const { return Infos.end(); }
0441
0442 bool empty() const { return Infos.empty(); }
0443
0444 iterator find(const CallInst *Key) {
0445 auto Pos = CallMap.find(Key);
0446 return Pos == CallMap.end() ? Infos.end() : (Infos.begin() + Pos->second);
0447 }
0448
0449 const_iterator find(const CallInst *Key) const {
0450 auto Pos = CallMap.find(Key);
0451 return Pos == CallMap.end() ? Infos.end() : (Infos.begin() + Pos->second);
0452 }
0453
0454 iterator srv_begin() { return begin(); }
0455 const_iterator srv_begin() const { return begin(); }
0456 iterator srv_end() { return begin() + FirstUAV; }
0457 const_iterator srv_end() const { return begin() + FirstUAV; }
0458 iterator_range<iterator> srvs() { return make_range(srv_begin(), srv_end()); }
0459 iterator_range<const_iterator> srvs() const {
0460 return make_range(srv_begin(), srv_end());
0461 }
0462
0463 iterator uav_begin() { return begin() + FirstUAV; }
0464 const_iterator uav_begin() const { return begin() + FirstUAV; }
0465 iterator uav_end() { return begin() + FirstCBuffer; }
0466 const_iterator uav_end() const { return begin() + FirstCBuffer; }
0467 iterator_range<iterator> uavs() { return make_range(uav_begin(), uav_end()); }
0468 iterator_range<const_iterator> uavs() const {
0469 return make_range(uav_begin(), uav_end());
0470 }
0471
0472 iterator cbuffer_begin() { return begin() + FirstCBuffer; }
0473 const_iterator cbuffer_begin() const { return begin() + FirstCBuffer; }
0474 iterator cbuffer_end() { return begin() + FirstSampler; }
0475 const_iterator cbuffer_end() const { return begin() + FirstSampler; }
0476 iterator_range<iterator> cbuffers() {
0477 return make_range(cbuffer_begin(), cbuffer_end());
0478 }
0479 iterator_range<const_iterator> cbuffers() const {
0480 return make_range(cbuffer_begin(), cbuffer_end());
0481 }
0482
0483 iterator sampler_begin() { return begin() + FirstSampler; }
0484 const_iterator sampler_begin() const { return begin() + FirstSampler; }
0485 iterator sampler_end() { return end(); }
0486 const_iterator sampler_end() const { return end(); }
0487 iterator_range<iterator> samplers() {
0488 return make_range(sampler_begin(), sampler_end());
0489 }
0490 iterator_range<const_iterator> samplers() const {
0491 return make_range(sampler_begin(), sampler_end());
0492 }
0493
0494 void print(raw_ostream &OS, DXILResourceTypeMap &DRTM,
0495 const DataLayout &DL) const;
0496
0497 friend class DXILResourceBindingAnalysis;
0498 friend class DXILResourceBindingWrapperPass;
0499 };
0500
0501 class DXILResourceBindingAnalysis
0502 : public AnalysisInfoMixin<DXILResourceBindingAnalysis> {
0503 friend AnalysisInfoMixin<DXILResourceBindingAnalysis>;
0504
0505 static AnalysisKey Key;
0506
0507 public:
0508 using Result = DXILBindingMap;
0509
0510
0511 DXILBindingMap run(Module &M, ModuleAnalysisManager &AM);
0512 };
0513
0514
0515 class DXILResourceBindingPrinterPass
0516 : public PassInfoMixin<DXILResourceBindingPrinterPass> {
0517 raw_ostream &OS;
0518
0519 public:
0520 explicit DXILResourceBindingPrinterPass(raw_ostream &OS) : OS(OS) {}
0521
0522 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
0523
0524 static bool isRequired() { return true; }
0525 };
0526
0527 class DXILResourceBindingWrapperPass : public ModulePass {
0528 std::unique_ptr<DXILBindingMap> Map;
0529 DXILResourceTypeMap *DRTM;
0530
0531 public:
0532 static char ID;
0533
0534 DXILResourceBindingWrapperPass();
0535 ~DXILResourceBindingWrapperPass() override;
0536
0537 const DXILBindingMap &getBindingMap() const { return *Map; }
0538 DXILBindingMap &getBindingMap() { return *Map; }
0539
0540 void getAnalysisUsage(AnalysisUsage &AU) const override;
0541 bool runOnModule(Module &M) override;
0542 void releaseMemory() override;
0543
0544 void print(raw_ostream &OS, const Module *M) const override;
0545 void dump() const;
0546 };
0547
0548 ModulePass *createDXILResourceBindingWrapperPassPass();
0549
0550 }
0551
0552 #endif