Path: blob/21.2-virgl/src/gallium/drivers/swr/rasterizer/jitter/JitManager.h
4574 views
/****************************************************************************1* Copyright (C) 2014-2015 Intel Corporation. All Rights Reserved.2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS20* IN THE SOFTWARE.21*22* @file JitManager.h23*24* @brief JitManager contains the LLVM data structures used for JIT generation25*26* Notes:27*28******************************************************************************/29#pragma once3031#include "jit_pch.hpp"32#include "common/isa.hpp"33#include <llvm/IR/AssemblyAnnotationWriter.h>343536//////////////////////////////////////////////////////////////////////////37/// JitInstructionSet38/// @brief Subclass of InstructionSet that allows users to override39/// the reporting of support for certain ISA features. This allows capping40/// the jitted code to a certain feature level, e.g. jit AVX level code on41/// a platform that supports AVX2.42//////////////////////////////////////////////////////////////////////////43class JitInstructionSet : public InstructionSet44{45public:46JitInstructionSet(const char* requestedIsa) : isaRequest(requestedIsa)47{48std::transform(isaRequest.begin(), isaRequest.end(), isaRequest.begin(), ::tolower);4950if (isaRequest == "avx")51{52bForceAVX = true;53bForceAVX2 = false;54bForceAVX512 = false;55}56else if (isaRequest == "avx2")57{58bForceAVX = false;59bForceAVX2 = true;60bForceAVX512 = false;61}62else if (isaRequest == "avx512")63{64bForceAVX = false;65bForceAVX2 = false;66bForceAVX512 = true;67}68};6970bool AVX2(void) { return bForceAVX ? 0 : InstructionSet::AVX2(); }71bool AVX512F(void) { return (bForceAVX | bForceAVX2) ? 0 : InstructionSet::AVX512F(); }72bool AVX512ER(void) { return (bForceAVX | bForceAVX2) ? 0 : InstructionSet::AVX512ER(); }73bool BMI2(void) { return bForceAVX ? 0 : InstructionSet::BMI2(); }7475private:76bool bForceAVX = false;77bool bForceAVX2 = false;78bool bForceAVX512 = false;79std::string isaRequest;80};8182struct JitLLVMContext : llvm::LLVMContext83{84};8586//////////////////////////////////////////////////////////////////////////87/// JitCache88//////////////////////////////////////////////////////////////////////////89struct JitManager; // Forward Decl90class JitCache : public llvm::ObjectCache91{92public:93/// constructor94JitCache();95virtual ~JitCache() {}9697void Init(JitManager* pJitMgr, const llvm::StringRef& cpu, llvm::CodeGenOpt::Level level)98{99mCpu = cpu.str();100mpJitMgr = pJitMgr;101mOptLevel = level;102}103104/// notifyObjectCompiled - Provides a pointer to compiled code for Module M.105void notifyObjectCompiled(const llvm::Module* M, llvm::MemoryBufferRef Obj) override;106107/// Returns a pointer to a newly allocated MemoryBuffer that contains the108/// object which corresponds with Module M, or 0 if an object is not109/// available.110std::unique_ptr<llvm::MemoryBuffer> getObject(const llvm::Module* M) override;111112const char* GetModuleCacheDir() { return mModuleCacheDir.c_str(); }113114private:115std::string mCpu;116llvm::SmallString<MAX_PATH> mCacheDir;117llvm::SmallString<MAX_PATH> mModuleCacheDir;118uint32_t mCurrentModuleCRC = 0;119JitManager* mpJitMgr = nullptr;120llvm::CodeGenOpt::Level mOptLevel = llvm::CodeGenOpt::None;121122/// Calculate actual directory where module will be cached.123/// This is always a subdirectory of mCacheDir. Full absolute124/// path name will be stored in mCurrentModuleCacheDir125void CalcModuleCacheDir();126};127128//////////////////////////////////////////////////////////////////////////129/// JitManager130//////////////////////////////////////////////////////////////////////////131struct JitManager132{133JitManager(uint32_t w, const char* arch, const char* core);134~JitManager()135{136for (auto* pExec : mvExecEngines)137{138delete pExec;139}140}141142JitLLVMContext mContext; ///< LLVM compiler143llvm::IRBuilder<> mBuilder; ///< LLVM IR Builder144llvm::ExecutionEngine* mpExec;145std::vector<llvm::ExecutionEngine*> mvExecEngines;146JitCache mCache;147llvm::StringRef mHostCpuName;148llvm::CodeGenOpt::Level mOptLevel;149150// Need to be rebuilt after a JIT and before building new IR151llvm::Module* mpCurrentModule;152bool mIsModuleFinalized;153uint32_t mJitNumber;154155uint32_t mVWidth;156157bool mUsingAVX512 = false;158159// fetch shader types160llvm::FunctionType* mFetchShaderTy;161162JitInstructionSet mArch;163164// Debugging support165std::unordered_map<llvm::StructType*, llvm::DIType*> mDebugStructMap;166167void CreateExecEngine(std::unique_ptr<llvm::Module> M);168void SetupNewModule();169170void DumpAsm(llvm::Function* pFunction, const char* fileName);171static void DumpToFile(llvm::Function* f, const char* fileName);172static void DumpToFile(llvm::Module* M,173const char* fileName,174llvm::AssemblyAnnotationWriter* annotater = nullptr);175static std::string GetOutputDir();176177// Debugging support methods178llvm::DIType* GetDebugType(llvm::Type* pTy);179llvm::DIType* GetDebugIntegerType(llvm::Type* pTy);180llvm::DIType* GetDebugArrayType(llvm::Type* pTy);181llvm::DIType* GetDebugVectorType(llvm::Type* pTy);182llvm::DIType* GetDebugFunctionType(llvm::Type* pTy);183184llvm::DIType* GetDebugStructType(llvm::Type* pType)185{186llvm::StructType* pStructTy = llvm::cast<llvm::StructType>(pType);187if (mDebugStructMap.find(pStructTy) == mDebugStructMap.end())188{189return nullptr;190}191return mDebugStructMap[pStructTy];192}193194llvm::DIType*195CreateDebugStructType(llvm::StructType* pType,196const std::string& name,197llvm::DIFile* pFile,198uint32_t lineNum,199const std::vector<std::pair<std::string, uint32_t>>& members);200};201202class InterleaveAssemblyAnnotater : public llvm::AssemblyAnnotationWriter203{204public:205void emitInstructionAnnot(const llvm::Instruction* pInst,206llvm::formatted_raw_ostream& OS) override;207std::vector<std::string> mAssembly;208209private:210uint32_t mCurrentLineNo = 0;211};212213214