/////////////////////////////////////////////////////////////////////////////// // // // HLModule.h // // Copyright (C) Microsoft Corporation. All rights reserved. // // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // // HighLevel DX IR module. // // // /////////////////////////////////////////////////////////////////////////////// #pragma once #include "dxc/Support/Global.h" #include "dxc/HLSL/DxilMetadataHelper.h" #include "dxc/HLSL/DxilConstants.h" #include "dxc/HLSL/HLResource.h" #include "dxc/HLSL/HLOperations.h" #include "dxc/HLSL/DxilSampler.h" #include "dxc/HLSL/DxilShaderModel.h" #include "dxc/HLSL/DxilSignature.h" #include "dxc/HLSL/DxilFunctionProps.h" #include #include #include #include namespace llvm { class LLVMContext; class Module; class Function; class Instruction; class CallInst; class MDTuple; class MDNode; class GlobalVariable; class DIGlobalVariable; class DebugInfoFinder; }; namespace hlsl { class ShaderModel; class OP; class RootSignatureHandle; struct HLOptions { HLOptions() : bDefaultRowMajor(false), bIEEEStrict(false), bDisableOptimizations(false), bLegacyCBufferLoad(false), PackingStrategy(0), unused(0) { } uint32_t GetHLOptionsRaw() const; void SetHLOptionsRaw(uint32_t data); unsigned bDefaultRowMajor : 1; unsigned bIEEEStrict : 1; unsigned bAllResourcesBound : 1; unsigned bDisableOptimizations : 1; unsigned bLegacyCBufferLoad : 1; unsigned PackingStrategy : 2; static_assert((unsigned)DXIL::PackingStrategy::Invalid < 4, "otherwise 2 bits is not enough to store PackingStrategy"); unsigned bUseMinPrecision : 1; unsigned unused : 24; }; /// Use this class to manipulate HLDXIR of a shader. class HLModule { public: HLModule(llvm::Module *pModule); ~HLModule(); using Domain = DXIL::TessellatorDomain; // Subsystems. llvm::LLVMContext &GetCtx() const; llvm::Module *GetModule() const; OP *GetOP() const; void SetShaderModel(const ShaderModel *pSM); const ShaderModel *GetShaderModel() const; void SetValidatorVersion(unsigned ValMajor, unsigned ValMinor); void GetValidatorVersion(unsigned &ValMajor, unsigned &ValMinor) const; // HLOptions void SetHLOptions(HLOptions &opts); const HLOptions &GetHLOptions() const; // Entry function. llvm::Function *GetEntryFunction() const; void SetEntryFunction(llvm::Function *pEntryFunc); const std::string &GetEntryFunctionName() const; void SetEntryFunctionName(const std::string &name); llvm::Function *GetPatchConstantFunction(); // Resources. unsigned AddCBuffer(std::unique_ptr pCB); DxilCBuffer &GetCBuffer(unsigned idx); const DxilCBuffer &GetCBuffer(unsigned idx) const; const std::vector > &GetCBuffers() const; unsigned AddSampler(std::unique_ptr pSampler); DxilSampler &GetSampler(unsigned idx); const DxilSampler &GetSampler(unsigned idx) const; const std::vector > &GetSamplers() const; unsigned AddSRV(std::unique_ptr pSRV); HLResource &GetSRV(unsigned idx); const HLResource &GetSRV(unsigned idx) const; const std::vector > &GetSRVs() const; unsigned AddUAV(std::unique_ptr pUAV); HLResource &GetUAV(unsigned idx); const HLResource &GetUAV(unsigned idx) const; const std::vector > &GetUAVs() const; void RemoveGlobal(llvm::GlobalVariable *GV); void RemoveFunction(llvm::Function *F); void RemoveResources(llvm::GlobalVariable **ppVariables, unsigned count); // ThreadGroupSharedMemory. typedef std::vector::iterator tgsm_iterator; tgsm_iterator tgsm_begin(); tgsm_iterator tgsm_end(); void AddGroupSharedVariable(llvm::GlobalVariable *GV); // Signatures. RootSignatureHandle &GetRootSignature(); // DxilFunctionProps. bool HasDxilFunctionProps(llvm::Function *F); DxilFunctionProps &GetDxilFunctionProps(llvm::Function *F); void AddDxilFunctionProps(llvm::Function *F, std::unique_ptr &info); DxilFunctionAnnotation *GetFunctionAnnotation(llvm::Function *F); DxilFunctionAnnotation *AddFunctionAnnotation(llvm::Function *F); void AddResourceTypeAnnotation(llvm::Type *Ty, DXIL::ResourceClass resClass, DXIL::ResourceKind kind); DXIL::ResourceClass GetResourceClass(llvm::Type *Ty); DXIL::ResourceKind GetResourceKind(llvm::Type *Ty); // Float Denorm mode. void SetFloat32DenormMode(const DXIL::Float32DenormMode mode); DXIL::Float32DenormMode GetFloat32DenormMode() const; // HLDXIR metadata manipulation. /// Serialize HLDXIR in-memory form to metadata form. void EmitHLMetadata(); /// Deserialize HLDXIR metadata form into in-memory form. void LoadHLMetadata(); /// Delete any HLDXIR from the specified module. static void ClearHLMetadata(llvm::Module &M); /// Create Metadata from a resource. llvm::MDNode *DxilSamplerToMDNode(const DxilSampler &S); llvm::MDNode *DxilSRVToMDNode(const DxilResource &SRV); llvm::MDNode *DxilUAVToMDNode(const DxilResource &UAV); llvm::MDNode *DxilCBufferToMDNode(const DxilCBuffer &CB); void LoadDxilResourceBaseFromMDNode(llvm::MDNode *MD, DxilResourceBase &R); void AddResourceWithGlobalVariableAndMDNode(llvm::Constant *GV, llvm::MDNode *MD); // Type related methods. static bool IsStreamOutputPtrType(llvm::Type *Ty); static bool IsStreamOutputType(llvm::Type *Ty); static bool IsHLSLObjectType(llvm::Type *Ty); static void GetParameterRowsAndCols(llvm::Type *Ty, unsigned &rows, unsigned &cols, DxilParameterAnnotation ¶mAnnotation); static void MergeGepUse(llvm::Value *V); // HL code gen. template static llvm::CallInst *EmitHLOperationCall(BuilderTy &Builder, HLOpcodeGroup group, unsigned opcode, llvm::Type *RetType, llvm::ArrayRef paramList, llvm::Module &M); static unsigned FindCastOp(bool fromUnsigned, bool toUnsigned, llvm::Type *SrcTy, llvm::Type *DstTy); // Precise attribute. // Note: Precise will be marked on alloca inst with metadata in code gen. // But mem2reg will remove alloca inst, so need mark precise with // function call before mem2reg. static bool HasPreciseAttributeWithMetadata(llvm::Instruction *I); static void MarkPreciseAttributeWithMetadata(llvm::Instruction *I); static void ClearPreciseAttributeWithMetadata(llvm::Instruction *I); static void MarkPreciseAttributeOnPtrWithFunctionCall(llvm::Value *Ptr, llvm::Module &M); static bool HasPreciseAttribute(llvm::Function *F); // Resource attribute. static void MarkDxilResourceAttrib(llvm::Function *F, llvm::MDNode *MD); static llvm::MDNode *GetDxilResourceAttrib(llvm::Function *F); void MarkDxilResourceAttrib(llvm::Argument *Arg, llvm::MDNode *MD); llvm::MDNode *GetDxilResourceAttrib(llvm::Argument *Arg); static llvm::MDNode *GetDxilResourceAttrib(llvm::Type *Ty, llvm::Module &M); // DXIL type system. DxilTypeSystem &GetTypeSystem(); /// Emit llvm.used array to make sure that optimizations do not remove unreferenced globals. void EmitLLVMUsed(); std::vector &GetLLVMUsed(); // Release functions used to transfer ownership. DxilTypeSystem *ReleaseTypeSystem(); OP *ReleaseOP(); RootSignatureHandle *ReleaseRootSignature(); std::unordered_map> && ReleaseFunctionPropsMap(); llvm::DebugInfoFinder &GetOrCreateDebugInfoFinder(); static llvm::DIGlobalVariable * FindGlobalVariableDebugInfo(llvm::GlobalVariable *GV, llvm::DebugInfoFinder &DbgInfoFinder); // Create global variable debug info for element global variable based on the // whole global variable. static void CreateElementGlobalVariableDebugInfo( llvm::GlobalVariable *GV, llvm::DebugInfoFinder &DbgInfoFinder, llvm::GlobalVariable *EltGV, unsigned sizeInBits, unsigned alignInBits, unsigned offsetInBits, llvm::StringRef eltName); // Replace GV with NewGV in GlobalVariable debug info. static void UpdateGlobalVariableDebugInfo(llvm::GlobalVariable *GV, llvm::DebugInfoFinder &DbgInfoFinder, llvm::GlobalVariable *NewGV); private: // Signatures. std::unique_ptr m_RootSignature; // Shader resources. std::vector > m_SRVs; std::vector > m_UAVs; std::vector > m_CBuffers; std::vector > m_Samplers; // ThreadGroupSharedMemory. std::vector m_TGSMVariables; // High level function info. std::unordered_map> m_DxilFunctionPropsMap; // Resource type annotation. std::unordered_map> m_ResTypeAnnotation; private: llvm::LLVMContext &m_Ctx; llvm::Module *m_pModule; llvm::Function *m_pEntryFunc; std::string m_EntryName; std::unique_ptr m_pMDHelper; std::unique_ptr m_pDebugInfoFinder; const ShaderModel *m_pSM; unsigned m_DxilMajor; unsigned m_DxilMinor; unsigned m_ValMajor; unsigned m_ValMinor; DXIL::Float32DenormMode m_Float32DenormMode; HLOptions m_Options; std::unique_ptr m_pOP; size_t m_pUnused; // DXIL metadata serialization/deserialization. llvm::MDTuple *EmitHLResources(); void LoadHLResources(const llvm::MDOperand &MDO); llvm::MDTuple *EmitHLShaderProperties(); void LoadHLShaderProperties(const llvm::MDOperand &MDO); llvm::MDTuple *EmitDxilShaderProperties(); llvm::MDTuple *EmitResTyAnnotations(); void LoadResTyAnnotations(const llvm::MDOperand &MDO); // LLVM used. std::vector m_LLVMUsed; // Type annotations. std::unique_ptr m_pTypeSystem; // Helpers. template unsigned AddResource(std::vector > &Vec, std::unique_ptr pRes); }; /// Use this class to manipulate metadata of extra metadata record properties that are specific to high-level DX IR. class HLExtraPropertyHelper : public DxilExtraPropertyHelper { public: HLExtraPropertyHelper(llvm::Module *pModule); virtual ~HLExtraPropertyHelper() {} virtual void EmitSignatureElementProperties(const DxilSignatureElement &SE, std::vector &MDVals); virtual void LoadSignatureElementProperties(const llvm::MDOperand &MDO, DxilSignatureElement &SE); }; } // namespace hlsl