Path: blob/21.2-virgl/src/gallium/drivers/swr/rasterizer/jitter/JitManager.cpp
4574 views
/****************************************************************************1* Copyright (C) 2014-2018 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.cpp23*24* @brief Implementation if the Jit Manager.25*26* Notes:27*28******************************************************************************/29#include "jit_pch.hpp"3031#include "JitManager.h"32#include "jit_api.h"33#include "fetch_jit.h"3435#include "core/state.h"3637#include "gen_state_llvm.h"3839#include <sstream>40#if defined(_WIN32)41#include <psapi.h>42#include <cstring>4344#define INTEL_OUTPUT_DIR "c:\\Intel"45#define SWR_OUTPUT_DIR INTEL_OUTPUT_DIR "\\SWR"46#define JITTER_OUTPUT_DIR SWR_OUTPUT_DIR "\\Jitter"47#endif // _WIN324849#if defined(__APPLE__) || defined(FORCE_LINUX) || defined(__linux__) || defined(__gnu_linux__)50#include <pwd.h>51#include <sys/stat.h>52#endif535455using namespace llvm;56using namespace SwrJit;5758//////////////////////////////////////////////////////////////////////////59/// @brief Contructor for JitManager.60/// @param simdWidth - SIMD width to be used in generated program.61JitManager::JitManager(uint32_t simdWidth, const char* arch, const char* core) :62mContext(), mBuilder(mContext), mIsModuleFinalized(true), mJitNumber(0), mVWidth(simdWidth),63mArch(arch)64{65mpCurrentModule = nullptr;66mpExec = nullptr;6768InitializeNativeTarget();69InitializeNativeTargetAsmPrinter();70InitializeNativeTargetDisassembler();717273// force JIT to use the same CPU arch as the rest of swr74if (mArch.AVX512F())75{76#if USE_SIMD16_SHADERS77if (mArch.AVX512ER())78{79mHostCpuName = StringRef("knl");80}81else82{83mHostCpuName = StringRef("skylake-avx512");84}85mUsingAVX512 = true;86#else87mHostCpuName = StringRef("core-avx2");88#endif89if (mVWidth == 0)90{91mVWidth = 8;92}93}94else if (mArch.AVX2())95{96mHostCpuName = StringRef("core-avx2");97if (mVWidth == 0)98{99mVWidth = 8;100}101}102else if (mArch.AVX())103{104if (mArch.F16C())105{106mHostCpuName = StringRef("core-avx-i");107}108else109{110mHostCpuName = StringRef("corei7-avx");111}112if (mVWidth == 0)113{114mVWidth = 8;115}116}117else118{119SWR_INVALID("Jitting requires at least AVX ISA support");120}121122123mOptLevel = CodeGenOpt::Aggressive;124125if (KNOB_JIT_OPTIMIZATION_LEVEL >= CodeGenOpt::None &&126KNOB_JIT_OPTIMIZATION_LEVEL <= CodeGenOpt::Aggressive)127{128mOptLevel = CodeGenOpt::Level(KNOB_JIT_OPTIMIZATION_LEVEL);129}130131if (KNOB_JIT_ENABLE_CACHE)132{133mCache.Init(this, mHostCpuName, mOptLevel);134}135136SetupNewModule();137mIsModuleFinalized = true;138139// fetch function signature140#if USE_SIMD16_SHADERS141// typedef void(__cdecl *PFN_FETCH_FUNC)(SWR_FETCH_CONTEXT& fetchInfo, simd16vertex& out);142#else143// typedef void(__cdecl *PFN_FETCH_FUNC)(SWR_FETCH_CONTEXT& fetchInfo, simdvertex& out);144#endif145std::vector<Type*> fsArgs;146147// llvm5 is picky and does not take a void * type148fsArgs.push_back(PointerType::get(Gen_SWR_FETCH_CONTEXT(this), 0));149150fsArgs.push_back(Type::getInt8PtrTy(mContext));151152fsArgs.push_back(PointerType::get(Gen_SWR_FETCH_CONTEXT(this), 0));153#if USE_SIMD16_SHADERS154fsArgs.push_back(PointerType::get(Gen_simd16vertex(this), 0));155#else156fsArgs.push_back(PointerType::get(Gen_simdvertex(this), 0));157#endif158159mFetchShaderTy = FunctionType::get(Type::getVoidTy(mContext), fsArgs, false);160161#if defined(_MSC_VER)162// explicitly instantiate used symbols from potentially staticly linked libs163sys::DynamicLibrary::AddSymbol("exp2f", &exp2f);164sys::DynamicLibrary::AddSymbol("log2f", &log2f);165sys::DynamicLibrary::AddSymbol("sinf", &sinf);166sys::DynamicLibrary::AddSymbol("cosf", &cosf);167sys::DynamicLibrary::AddSymbol("powf", &powf);168#endif169170#if defined(_WIN32)171if (KNOB_DUMP_SHADER_IR)172{173CreateDirectoryPath(INTEL_OUTPUT_DIR);174CreateDirectoryPath(SWR_OUTPUT_DIR);175CreateDirectoryPath(JITTER_OUTPUT_DIR);176}177#endif178}179180void JitManager::CreateExecEngine(std::unique_ptr<Module> pModule)181{182TargetOptions tOpts;183tOpts.AllowFPOpFusion = FPOpFusion::Fast;184tOpts.NoInfsFPMath = false;185tOpts.NoNaNsFPMath = false;186tOpts.UnsafeFPMath = false;187188// tOpts.PrintMachineCode = true;189190mpExec = EngineBuilder(std::move(pModule))191.setTargetOptions(tOpts)192.setOptLevel(mOptLevel)193.setMCPU(mHostCpuName)194.create();195196if (KNOB_JIT_ENABLE_CACHE)197{198mpExec->setObjectCache(&mCache);199}200201#if LLVM_USE_INTEL_JITEVENTS202JITEventListener* vTune = JITEventListener::createIntelJITEventListener();203mpExec->RegisterJITEventListener(vTune);204#endif205206mvExecEngines.push_back(mpExec);207}208209//////////////////////////////////////////////////////////////////////////210/// @brief Create new LLVM module.211void JitManager::SetupNewModule()212{213SWR_ASSERT(mIsModuleFinalized == true && "Current module is not finalized!");214215std::unique_ptr<Module> newModule(new Module("", mContext));216mpCurrentModule = newModule.get();217mpCurrentModule->setTargetTriple(sys::getProcessTriple());218CreateExecEngine(std::move(newModule));219mIsModuleFinalized = false;220}221222223DIType*224JitManager::CreateDebugStructType(StructType* pType,225const std::string& name,226DIFile* pFile,227uint32_t lineNum,228const std::vector<std::pair<std::string, uint32_t>>& members)229{230DIBuilder builder(*mpCurrentModule);231SmallVector<Metadata*, 8> ElemTypes;232DataLayout DL = DataLayout(mpCurrentModule);233uint32_t size = DL.getTypeAllocSizeInBits(pType);234uint32_t alignment = DL.getABITypeAlignment(pType);235DINode::DIFlags flags = DINode::DIFlags::FlagPublic;236237DICompositeType* pDIStructTy = builder.createStructType(pFile,238name,239pFile,240lineNum,241size,242alignment,243flags,244nullptr,245builder.getOrCreateArray(ElemTypes));246247// Register mapping now to break loops (in case struct contains itself or pointers to itself)248mDebugStructMap[pType] = pDIStructTy;249250uint32_t idx = 0;251for (auto& elem : pType->elements())252{253std::string name = members[idx].first;254uint32_t lineNum = members[idx].second;255size = DL.getTypeAllocSizeInBits(elem);256alignment = DL.getABITypeAlignment(elem);257uint32_t offset = DL.getStructLayout(pType)->getElementOffsetInBits(idx);258llvm::DIType* pDebugTy = GetDebugType(elem);259ElemTypes.push_back(builder.createMemberType(260pDIStructTy, name, pFile, lineNum, size, alignment, offset, flags, pDebugTy));261262idx++;263}264265pDIStructTy->replaceElements(builder.getOrCreateArray(ElemTypes));266return pDIStructTy;267}268269DIType* JitManager::GetDebugArrayType(Type* pTy)270{271DIBuilder builder(*mpCurrentModule);272DataLayout DL = DataLayout(mpCurrentModule);273ArrayType* pArrayTy = cast<ArrayType>(pTy);274uint32_t size = DL.getTypeAllocSizeInBits(pArrayTy);275uint32_t alignment = DL.getABITypeAlignment(pArrayTy);276277SmallVector<Metadata*, 8> Elems;278Elems.push_back(builder.getOrCreateSubrange(0, pArrayTy->getNumElements()));279return builder.createArrayType(280size, alignment, GetDebugType(pArrayTy->getElementType()), builder.getOrCreateArray(Elems));281}282283// Create a DIType from llvm Type284DIType* JitManager::GetDebugType(Type* pTy)285{286DIBuilder builder(*mpCurrentModule);287Type::TypeID id = pTy->getTypeID();288289switch (id)290{291case Type::VoidTyID:292return builder.createUnspecifiedType("void");293break;294case Type::HalfTyID:295return builder.createBasicType("float16", 16, dwarf::DW_ATE_float);296break;297case Type::FloatTyID:298return builder.createBasicType("float", 32, dwarf::DW_ATE_float);299break;300case Type::DoubleTyID:301return builder.createBasicType("double", 64, dwarf::DW_ATE_float);302break;303case Type::IntegerTyID:304return GetDebugIntegerType(pTy);305break;306case Type::StructTyID:307return GetDebugStructType(pTy);308break;309case Type::ArrayTyID:310return GetDebugArrayType(pTy);311break;312case Type::PointerTyID:313return builder.createPointerType(GetDebugType(pTy->getPointerElementType()), 64, 64);314break;315#if LLVM_VERSION_MAJOR >= 11316case Type::FixedVectorTyID:317#else318case Type::VectorTyID:319#endif320return GetDebugVectorType(pTy);321break;322case Type::FunctionTyID:323return GetDebugFunctionType(pTy);324break;325default:326SWR_ASSERT(false, "Unimplemented llvm type");327}328return nullptr;329}330331// Create a DISubroutineType from an llvm FunctionType332DIType* JitManager::GetDebugFunctionType(Type* pTy)333{334SmallVector<Metadata*, 8> ElemTypes;335FunctionType* pFuncTy = cast<FunctionType>(pTy);336DIBuilder builder(*mpCurrentModule);337338// Add result type339ElemTypes.push_back(GetDebugType(pFuncTy->getReturnType()));340341// Add arguments342for (auto& param : pFuncTy->params())343{344ElemTypes.push_back(GetDebugType(param));345}346347return builder.createSubroutineType(builder.getOrCreateTypeArray(ElemTypes));348}349350DIType* JitManager::GetDebugIntegerType(Type* pTy)351{352DIBuilder builder(*mpCurrentModule);353IntegerType* pIntTy = cast<IntegerType>(pTy);354switch (pIntTy->getBitWidth())355{356case 1:357return builder.createBasicType("int1", 1, dwarf::DW_ATE_unsigned);358break;359case 8:360return builder.createBasicType("int8", 8, dwarf::DW_ATE_signed);361break;362case 16:363return builder.createBasicType("int16", 16, dwarf::DW_ATE_signed);364break;365case 32:366return builder.createBasicType("int", 32, dwarf::DW_ATE_signed);367break;368case 64:369return builder.createBasicType("int64", 64, dwarf::DW_ATE_signed);370break;371case 128:372return builder.createBasicType("int128", 128, dwarf::DW_ATE_signed);373break;374default:375SWR_ASSERT(false, "Unimplemented integer bit width");376}377return nullptr;378}379380DIType* JitManager::GetDebugVectorType(Type* pTy)381{382DIBuilder builder(*mpCurrentModule);383#if LLVM_VERSION_MAJOR >= 12384FixedVectorType* pVecTy = cast<FixedVectorType>(pTy);385#elif LLVM_VERSION_MAJOR >= 11386VectorType* pVecTy = cast<VectorType>(pTy);387#else388auto pVecTy = pTy;389#endif390DataLayout DL = DataLayout(mpCurrentModule);391uint32_t size = DL.getTypeAllocSizeInBits(pVecTy);392uint32_t alignment = DL.getABITypeAlignment(pVecTy);393SmallVector<Metadata*, 1> Elems;394395#if LLVM_VERSION_MAJOR >= 11396Elems.push_back(builder.getOrCreateSubrange(0, pVecTy->getNumElements()));397#else398Elems.push_back(builder.getOrCreateSubrange(0, pVecTy->getVectorNumElements()));399#endif400401return builder.createVectorType(size,402alignment,403#if LLVM_VERSION_MAJOR >= 11404GetDebugType(pVecTy->getElementType()),405#else406GetDebugType(pVecTy->getVectorElementType()),407#endif408builder.getOrCreateArray(Elems));409}410411//////////////////////////////////////////////////////////////////////////412/// @brief Dump function x86 assembly to file.413/// @note This should only be called after the module has been jitted to x86 and the414/// module will not be further accessed.415void JitManager::DumpAsm(Function* pFunction, const char* fileName)416{417if (KNOB_DUMP_SHADER_IR)418{419#if defined(_WIN32)420DWORD pid = GetCurrentProcessId();421char procname[MAX_PATH];422GetModuleFileNameA(NULL, procname, MAX_PATH);423const char* pBaseName = strrchr(procname, '\\');424std::stringstream outDir;425outDir << JITTER_OUTPUT_DIR << pBaseName << "_" << pid << std::ends;426CreateDirectoryPath(outDir.str().c_str());427#endif428429std::error_code EC;430Module* pModule = pFunction->getParent();431const char* funcName = pFunction->getName().data();432char fName[256];433#if defined(_WIN32)434sprintf(fName, "%s\\%s.%s.asm", outDir.str().c_str(), funcName, fileName);435#else436sprintf(fName, "%s.%s.asm", funcName, fileName);437#endif438439raw_fd_ostream filestream(fName, EC, llvm::sys::fs::F_None);440441legacy::PassManager* pMPasses = new legacy::PassManager();442auto* pTarget = mpExec->getTargetMachine();443pTarget->Options.MCOptions.AsmVerbose = true;444#if LLVM_VERSION_MAJOR >= 10445pTarget->addPassesToEmitFile(446*pMPasses, filestream, nullptr, CGFT_AssemblyFile);447#elif LLVM_VERSION_MAJOR >= 7448pTarget->addPassesToEmitFile(449*pMPasses, filestream, nullptr, TargetMachine::CGFT_AssemblyFile);450#else451pTarget->addPassesToEmitFile(*pMPasses, filestream, TargetMachine::CGFT_AssemblyFile);452#endif453pMPasses->run(*pModule);454delete pMPasses;455pTarget->Options.MCOptions.AsmVerbose = false;456}457}458459std::string JitManager::GetOutputDir()460{461#if defined(_WIN32)462DWORD pid = GetCurrentProcessId();463char procname[MAX_PATH];464GetModuleFileNameA(NULL, procname, MAX_PATH);465const char* pBaseName = strrchr(procname, '\\');466std::stringstream outDir;467outDir << JITTER_OUTPUT_DIR << pBaseName << "_" << pid;468CreateDirectoryPath(outDir.str().c_str());469return outDir.str();470#endif471return "";472}473474//////////////////////////////////////////////////////////////////////////475/// @brief Dump function to file.476void JitManager::DumpToFile(Module* M,477const char* fileName,478llvm::AssemblyAnnotationWriter* annotater)479{480if (KNOB_DUMP_SHADER_IR)481{482std::string outDir = GetOutputDir();483484std::error_code EC;485const char* funcName = M->getName().data();486char fName[256];487#if defined(_WIN32)488sprintf(fName, "%s\\%s.%s.ll", outDir.c_str(), funcName, fileName);489#else490sprintf(fName, "%s.%s.ll", funcName, fileName);491#endif492raw_fd_ostream fd(fName, EC, llvm::sys::fs::F_None);493M->print(fd, annotater);494fd.flush();495}496}497498//////////////////////////////////////////////////////////////////////////499/// @brief Dump function to file.500void JitManager::DumpToFile(Function* f, const char* fileName)501{502if (KNOB_DUMP_SHADER_IR)503{504std::string outDir = GetOutputDir();505506std::error_code EC;507const char* funcName = f->getName().data();508char fName[256];509#if defined(_WIN32)510sprintf(fName, "%s\\%s.%s.ll", outDir.c_str(), funcName, fileName);511#else512sprintf(fName, "%s.%s.ll", funcName, fileName);513#endif514raw_fd_ostream fd(fName, EC, llvm::sys::fs::F_None);515f->print(fd, nullptr);516517#if defined(_WIN32)518sprintf(fName, "%s\\cfg.%s.%s.dot", outDir.c_str(), funcName, fileName);519#else520sprintf(fName, "cfg.%s.%s.dot", funcName, fileName);521#endif522fd.flush();523524raw_fd_ostream fd_cfg(fName, EC, llvm::sys::fs::F_Text);525WriteGraph(fd_cfg, (const Function*)f);526527fd_cfg.flush();528}529}530531extern "C" {532bool g_DllActive = true;533534//////////////////////////////////////////////////////////////////////////535/// @brief Create JIT context.536/// @param simdWidth - SIMD width to be used in generated program.537HANDLE JITCALL JitCreateContext(uint32_t targetSimdWidth, const char* arch, const char* core)538{539return new JitManager(targetSimdWidth, arch, core);540}541542//////////////////////////////////////////////////////////////////////////543/// @brief Destroy JIT context.544void JITCALL JitDestroyContext(HANDLE hJitContext)545{546if (g_DllActive)547{548delete reinterpret_cast<JitManager*>(hJitContext);549}550}551}552553//////////////////////////////////////////////////////////////////////////554/// JitCache555//////////////////////////////////////////////////////////////////////////556557//////////////////////////////////////////////////////////////////////////558/// JitCacheFileHeader559//////////////////////////////////////////////////////////////////////////560struct JitCacheFileHeader561{562void Init(uint32_t llCRC,563uint32_t objCRC,564const std::string& moduleID,565const std::string& cpu,566uint32_t optLevel,567uint64_t objSize)568{569m_objSize = objSize;570m_llCRC = llCRC;571m_objCRC = objCRC;572strncpy(m_ModuleID, moduleID.c_str(), JC_STR_MAX_LEN - 1);573m_ModuleID[JC_STR_MAX_LEN - 1] = 0;574strncpy(m_Cpu, cpu.c_str(), JC_STR_MAX_LEN - 1);575m_Cpu[JC_STR_MAX_LEN - 1] = 0;576m_optLevel = optLevel;577}578579580bool581IsValid(uint32_t llCRC, const std::string& moduleID, const std::string& cpu, uint32_t optLevel)582{583if ((m_MagicNumber != JC_MAGIC_NUMBER) || (m_llCRC != llCRC) ||584(m_platformKey != JC_PLATFORM_KEY) || (m_optLevel != optLevel))585{586return false;587}588589m_ModuleID[JC_STR_MAX_LEN - 1] = 0;590if (strncmp(moduleID.c_str(), m_ModuleID, JC_STR_MAX_LEN - 1))591{592return false;593}594595m_Cpu[JC_STR_MAX_LEN - 1] = 0;596if (strncmp(cpu.c_str(), m_Cpu, JC_STR_MAX_LEN - 1))597{598return false;599}600601return true;602}603604uint64_t GetObjectSize() const { return m_objSize; }605uint64_t GetObjectCRC() const { return m_objCRC; }606607private:608static const uint64_t JC_MAGIC_NUMBER = 0xfedcba9876543210ULL + 7;609static const size_t JC_STR_MAX_LEN = 32;610static const uint32_t JC_PLATFORM_KEY = (LLVM_VERSION_MAJOR << 24) |611(LLVM_VERSION_MINOR << 16) | (LLVM_VERSION_PATCH << 8) |612((sizeof(void*) > sizeof(uint32_t)) ? 1 : 0);613614uint64_t m_MagicNumber = JC_MAGIC_NUMBER;615uint64_t m_objSize = 0;616uint32_t m_llCRC = 0;617uint32_t m_platformKey = JC_PLATFORM_KEY;618uint32_t m_objCRC = 0;619uint32_t m_optLevel = 0;620char m_ModuleID[JC_STR_MAX_LEN] = {};621char m_Cpu[JC_STR_MAX_LEN] = {};622};623624static inline uint32_t ComputeModuleCRC(const llvm::Module* M)625{626std::string bitcodeBuffer;627raw_string_ostream bitcodeStream(bitcodeBuffer);628629#if LLVM_VERSION_MAJOR >= 7630llvm::WriteBitcodeToFile(*M, bitcodeStream);631#else632llvm::WriteBitcodeToFile(M, bitcodeStream);633#endif634// M->print(bitcodeStream, nullptr, false);635636bitcodeStream.flush();637638return ComputeCRC(0, bitcodeBuffer.data(), bitcodeBuffer.size());639}640641/// constructor642JitCache::JitCache()643{644#if defined(__APPLE__) || defined(FORCE_LINUX) || defined(__linux__) || defined(__gnu_linux__)645if (strncmp(KNOB_JIT_CACHE_DIR.c_str(), "~/", 2) == 0)646{647char* homedir;648if (!(homedir = getenv("HOME")))649{650homedir = getpwuid(getuid())->pw_dir;651}652mCacheDir = homedir;653mCacheDir += (KNOB_JIT_CACHE_DIR.c_str() + 1);654}655else656#endif657{658mCacheDir = KNOB_JIT_CACHE_DIR;659}660661// Create cache dir at startup to allow jitter to write debug.ll files662// to that directory.663if (!llvm::sys::fs::exists(mCacheDir.str()) &&664llvm::sys::fs::create_directories(mCacheDir.str()))665{666SWR_INVALID("Unable to create directory: %s", mCacheDir.c_str());667}668669}670671int ExecUnhookedProcess(const std::string& CmdLine, std::string* pStdOut, std::string* pStdErr)672{673674return ExecCmd(CmdLine, nullptr, pStdOut, pStdErr);675}676677/// Calculate actual directory where module will be cached.678/// This is always a subdirectory of mCacheDir. Full absolute679/// path name will be stored in mCurrentModuleCacheDir680void JitCache::CalcModuleCacheDir()681{682mModuleCacheDir.clear();683684llvm::SmallString<MAX_PATH> moduleDir = mCacheDir;685686// Create 4 levels of directory hierarchy based on CRC, 256 entries each687uint8_t* pCRC = (uint8_t*)&mCurrentModuleCRC;688for (uint32_t i = 0; i < 4; ++i)689{690llvm::sys::path::append(moduleDir, std::to_string((int)pCRC[i]));691}692693mModuleCacheDir = moduleDir;694}695696/// notifyObjectCompiled - Provides a pointer to compiled code for Module M.697void JitCache::notifyObjectCompiled(const llvm::Module* M, llvm::MemoryBufferRef Obj)698{699const std::string& moduleID = M->getModuleIdentifier();700if (!moduleID.length())701{702return;703}704705if (!mModuleCacheDir.size())706{707SWR_INVALID("Unset module cache directory");708return;709}710711if (!llvm::sys::fs::exists(mModuleCacheDir.str()) &&712llvm::sys::fs::create_directories(mModuleCacheDir.str()))713{714SWR_INVALID("Unable to create directory: %s", mModuleCacheDir.c_str());715return;716}717718JitCacheFileHeader header;719720llvm::SmallString<MAX_PATH> filePath = mModuleCacheDir;721llvm::sys::path::append(filePath, moduleID);722723llvm::SmallString<MAX_PATH> objPath = filePath;724objPath += JIT_OBJ_EXT;725726{727std::error_code err;728llvm::raw_fd_ostream fileObj(objPath.c_str(), err, llvm::sys::fs::F_None);729fileObj << Obj.getBuffer();730fileObj.flush();731}732733734{735std::error_code err;736llvm::raw_fd_ostream fileObj(filePath.c_str(), err, llvm::sys::fs::F_None);737738uint32_t objcrc = ComputeCRC(0, Obj.getBufferStart(), Obj.getBufferSize());739740header.Init(mCurrentModuleCRC, objcrc, moduleID, mCpu, mOptLevel, Obj.getBufferSize());741742fileObj.write((const char*)&header, sizeof(header));743fileObj.flush();744}745}746747/// Returns a pointer to a newly allocated MemoryBuffer that contains the748/// object which corresponds with Module M, or 0 if an object is not749/// available.750std::unique_ptr<llvm::MemoryBuffer> JitCache::getObject(const llvm::Module* M)751{752const std::string& moduleID = M->getModuleIdentifier();753mCurrentModuleCRC = ComputeModuleCRC(M);754755if (!moduleID.length())756{757return nullptr;758}759760CalcModuleCacheDir();761762if (!llvm::sys::fs::exists(mModuleCacheDir))763{764return nullptr;765}766767llvm::SmallString<MAX_PATH> filePath = mModuleCacheDir;768llvm::sys::path::append(filePath, moduleID);769770llvm::SmallString<MAX_PATH> objFilePath = filePath;771objFilePath += JIT_OBJ_EXT;772773FILE* fpObjIn = nullptr;774FILE* fpIn = fopen(filePath.c_str(), "rb");775if (!fpIn)776{777return nullptr;778}779780std::unique_ptr<llvm::MemoryBuffer> pBuf = nullptr;781do782{783JitCacheFileHeader header;784if (!fread(&header, sizeof(header), 1, fpIn))785{786break;787}788789if (!header.IsValid(mCurrentModuleCRC, moduleID, mCpu, mOptLevel))790{791break;792}793794fpObjIn = fopen(objFilePath.c_str(), "rb");795if (!fpObjIn)796{797break;798}799800#if LLVM_VERSION_MAJOR < 6801pBuf = llvm::MemoryBuffer::getNewUninitMemBuffer(size_t(header.GetObjectSize()));802#else803pBuf = llvm::WritableMemoryBuffer::getNewUninitMemBuffer(size_t(header.GetObjectSize()));804#endif805if (!fread(const_cast<char*>(pBuf->getBufferStart()), header.GetObjectSize(), 1, fpObjIn))806{807pBuf = nullptr;808break;809}810811if (header.GetObjectCRC() != ComputeCRC(0, pBuf->getBufferStart(), pBuf->getBufferSize()))812{813SWR_TRACE("Invalid object cache file, ignoring: %s", filePath.c_str());814pBuf = nullptr;815break;816}817818} while (0);819820fclose(fpIn);821822if (fpObjIn)823{824fclose(fpObjIn);825}826827828return pBuf;829}830831void InterleaveAssemblyAnnotater::emitInstructionAnnot(const llvm::Instruction* pInst,832llvm::formatted_raw_ostream& OS)833{834auto dbgLoc = pInst->getDebugLoc();835if (dbgLoc)836{837unsigned int line = dbgLoc.getLine();838if (line != mCurrentLineNo)839{840if (line > 0 && line <= mAssembly.size())841{842// HACK: here we assume that OS is a formatted_raw_ostream(ods())843// and modify the color accordingly. We can't do the color844// modification on OS because formatted_raw_ostream strips845// the color information. The only way to fix this behavior846// is to patch LLVM.847OS << "\n; " << line << ": " << mAssembly[line - 1] << "\n";848}849mCurrentLineNo = line;850}851}852}853854855