93 lines · cpp
1//===- DXILCBufferAccess.cpp - Translate CBuffer Loads --------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "DXILCBufferAccess.h"10#include "DirectX.h"11#include "llvm/Analysis/DXILResource.h"12#include "llvm/Frontend/HLSL/CBuffer.h"13#include "llvm/Frontend/HLSL/HLSLResource.h"14#include "llvm/IR/IRBuilder.h"15#include "llvm/IR/IntrinsicInst.h"16#include "llvm/IR/IntrinsicsDirectX.h"17#include "llvm/IR/ReplaceConstant.h"18#include "llvm/InitializePasses.h"19#include "llvm/Pass.h"20#include "llvm/Support/FormatVariadic.h"21#include "llvm/Transforms/Utils/Local.h"22 23#define DEBUG_TYPE "dxil-cbuffer-access"24using namespace llvm;25 26static void replaceUsersOfGlobal(GlobalVariable *Global,27 GlobalVariable *HandleGV, size_t Offset) {28 for (Use &U : make_early_inc_range(Global->uses())) {29 auto UseInst = dyn_cast<Instruction>(U.getUser());30 // TODO: Constants? Metadata?31 assert(UseInst && "Non-instruction use of cbuffer");32 33 IRBuilder<> Builder(UseInst);34 LoadInst *Handle = Builder.CreateLoad(HandleGV->getValueType(), HandleGV,35 HandleGV->getName());36 Value *Ptr = Builder.CreateIntrinsic(37 Global->getType(), Intrinsic::dx_resource_getpointer,38 ArrayRef<Value *>{Handle,39 ConstantInt::get(Builder.getInt32Ty(), Offset)});40 U.set(Ptr);41 }42 43 Global->removeFromParent();44}45 46static bool replaceCBufferAccesses(Module &M) {47 std::optional<hlsl::CBufferMetadata> CBufMD = hlsl::CBufferMetadata::get(48 M, [](Type *Ty) { return isa<llvm::dxil::PaddingExtType>(Ty); });49 if (!CBufMD)50 return false;51 52 SmallVector<Constant *> CBufferGlobals;53 for (const hlsl::CBufferMapping &Mapping : *CBufMD)54 for (const hlsl::CBufferMember &Member : Mapping.Members)55 CBufferGlobals.push_back(Member.GV);56 convertUsersOfConstantsToInstructions(CBufferGlobals);57 58 for (const hlsl::CBufferMapping &Mapping : *CBufMD)59 for (const hlsl::CBufferMember &Member : Mapping.Members)60 replaceUsersOfGlobal(Member.GV, Mapping.Handle, Member.Offset);61 62 CBufMD->eraseFromModule();63 return true;64}65 66PreservedAnalyses DXILCBufferAccess::run(Module &M, ModuleAnalysisManager &AM) {67 PreservedAnalyses PA;68 bool Changed = replaceCBufferAccesses(M);69 70 if (!Changed)71 return PreservedAnalyses::all();72 return PA;73}74 75namespace {76class DXILCBufferAccessLegacy : public ModulePass {77public:78 bool runOnModule(Module &M) override { return replaceCBufferAccesses(M); }79 StringRef getPassName() const override { return "DXIL CBuffer Access"; }80 DXILCBufferAccessLegacy() : ModulePass(ID) {}81 82 static char ID; // Pass identification.83};84char DXILCBufferAccessLegacy::ID = 0;85} // end anonymous namespace86 87INITIALIZE_PASS(DXILCBufferAccessLegacy, DEBUG_TYPE, "DXIL CBuffer Access",88 false, false)89 90ModulePass *llvm::createDXILCBufferAccessLegacyPass() {91 return new DXILCBufferAccessLegacy();92}93