1 /****************************************************************************
2 * Copyright (C) 2014-2015 Intel Corporation. All Rights Reserved.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23 * @file JitManager.cpp
25 * @brief Implementation if the Jit Manager.
29 ******************************************************************************/
30 #include "jit_pch.hpp"
32 #include "JitManager.h"
34 #include "fetch_jit.h"
36 #include "core/state.h"
38 #include "gen_state_llvm.h"
45 #define INTEL_OUTPUT_DIR "c:\\Intel"
46 #define SWR_OUTPUT_DIR INTEL_OUTPUT_DIR "\\SWR"
47 #define JITTER_OUTPUT_DIR SWR_OUTPUT_DIR "\\Jitter"
50 #if defined(__APPLE) || defined(FORCE_LINUX) || defined(__linux__) || defined(__gnu_linux__)
57 using namespace SwrJit
;
59 //////////////////////////////////////////////////////////////////////////
60 /// @brief Contructor for JitManager.
61 /// @param simdWidth - SIMD width to be used in generated program.
62 JitManager::JitManager(uint32_t simdWidth
, const char *arch
, const char* core
)
63 : mContext(), mBuilder(mContext
), mIsModuleFinalized(true), mJitNumber(0), mVWidth(simdWidth
), mArch(arch
)
65 InitializeNativeTarget();
66 InitializeNativeTargetAsmPrinter();
67 InitializeNativeTargetDisassembler();
70 tOpts
.AllowFPOpFusion
= FPOpFusion::Fast
;
71 tOpts
.NoInfsFPMath
= false;
72 tOpts
.NoNaNsFPMath
= false;
73 tOpts
.UnsafeFPMath
= false;
75 #if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR < 7
76 tOpts
.NoFramePointerElim
= true;
80 //tOpts.PrintMachineCode = true;
82 mCore
= std::string(core
);
83 std::transform(mCore
.begin(), mCore
.end(), mCore
.begin(), ::tolower
);
85 std::unique_ptr
<Module
> newModule(new Module("", mContext
));
86 mpCurrentModule
= newModule
.get();
88 StringRef hostCPUName
;
90 hostCPUName
= sys::getHostCPUName();
93 // Needed for MCJIT on windows
94 Triple
hostTriple(sys::getProcessTriple());
95 hostTriple
.setObjectFormat(Triple::COFF
);
96 mpCurrentModule
->setTargetTriple(hostTriple
.getTriple());
99 auto optLevel
= CodeGenOpt::Aggressive
;
101 mpExec
= EngineBuilder(std::move(newModule
))
102 .setTargetOptions(tOpts
)
103 .setOptLevel(optLevel
)
104 .setMCPU(hostCPUName
)
107 if (KNOB_JIT_ENABLE_CACHE
)
109 mCache
.Init(this, hostCPUName
, optLevel
);
110 mpExec
->setObjectCache(&mCache
);
113 #if LLVM_USE_INTEL_JITEVENTS
114 JITEventListener
*vTune
= JITEventListener::createIntelJITEventListener();
115 mpExec
->RegisterJITEventListener(vTune
);
118 mFP32Ty
= Type::getFloatTy(mContext
); // float type
119 mInt8Ty
= Type::getInt8Ty(mContext
);
120 mInt32Ty
= Type::getInt32Ty(mContext
); // int type
121 mInt64Ty
= Type::getInt64Ty(mContext
); // int type
123 // fetch function signature
124 #if USE_SIMD16_SHADERS
125 // typedef void(__cdecl *PFN_FETCH_FUNC)(SWR_FETCH_CONTEXT& fetchInfo, simd16vertex& out);
127 // typedef void(__cdecl *PFN_FETCH_FUNC)(SWR_FETCH_CONTEXT& fetchInfo, simdvertex& out);
129 std::vector
<Type
*> fsArgs
;
131 // llvm5 is picky and does not take a void * type
132 fsArgs
.push_back(PointerType::get(Gen_SWR_FETCH_CONTEXT(this), 0));
134 fsArgs
.push_back(PointerType::get(Gen_SWR_FETCH_CONTEXT(this), 0));
135 #if USE_SIMD16_SHADERS
136 fsArgs
.push_back(PointerType::get(Gen_simd16vertex(this), 0));
138 fsArgs
.push_back(PointerType::get(Gen_simdvertex(this), 0));
141 mFetchShaderTy
= FunctionType::get(Type::getVoidTy(mContext
), fsArgs
, false);
143 mSimtFP32Ty
= VectorType::get(mFP32Ty
, mVWidth
);
144 mSimtInt32Ty
= VectorType::get(mInt32Ty
, mVWidth
);
146 mSimdVectorTy
= ArrayType::get(mSimtFP32Ty
, 4);
147 mSimdVectorInt32Ty
= ArrayType::get(mSimtInt32Ty
, 4);
149 #if USE_SIMD16_SHADERS
150 mSimd16FP32Ty
= ArrayType::get(mSimtFP32Ty
, 2);
151 mSimd16Int32Ty
= ArrayType::get(mSimtInt32Ty
, 2);
153 mSimd16VectorFP32Ty
= ArrayType::get(mSimd16FP32Ty
, 4);
154 mSimd16VectorInt32Ty
= ArrayType::get(mSimd16Int32Ty
, 4);
158 // explicitly instantiate used symbols from potentially staticly linked libs
159 sys::DynamicLibrary::AddSymbol("exp2f", &exp2f
);
160 sys::DynamicLibrary::AddSymbol("log2f", &log2f
);
161 sys::DynamicLibrary::AddSymbol("sinf", &sinf
);
162 sys::DynamicLibrary::AddSymbol("cosf", &cosf
);
163 sys::DynamicLibrary::AddSymbol("powf", &powf
);
167 if (KNOB_DUMP_SHADER_IR
)
169 CreateDirectoryPath(INTEL_OUTPUT_DIR
);
170 CreateDirectoryPath(SWR_OUTPUT_DIR
);
171 CreateDirectoryPath(JITTER_OUTPUT_DIR
);
176 //////////////////////////////////////////////////////////////////////////
177 /// @brief Create new LLVM module.
178 void JitManager::SetupNewModule()
180 SWR_ASSERT(mIsModuleFinalized
== true && "Current module is not finalized!");
182 std::unique_ptr
<Module
> newModule(new Module("", mContext
));
183 mpCurrentModule
= newModule
.get();
185 // Needed for MCJIT on windows
186 Triple
hostTriple(sys::getProcessTriple());
187 hostTriple
.setObjectFormat(Triple::COFF
);
188 newModule
->setTargetTriple(hostTriple
.getTriple());
191 mpExec
->addModule(std::move(newModule
));
192 mIsModuleFinalized
= false;
196 DIType
* JitManager::CreateDebugStructType(StructType
* pType
, const std::string
& name
, DIFile
* pFile
, uint32_t lineNum
,
197 const std::vector
<std::pair
<std::string
, uint32_t>>& members
)
199 DIBuilder
builder(*mpCurrentModule
);
200 SmallVector
<Metadata
*, 8> ElemTypes
;
201 DataLayout DL
= DataLayout(mpCurrentModule
);
202 uint32_t size
= DL
.getTypeAllocSizeInBits(pType
);
203 uint32_t alignment
= DL
.getABITypeAlignment(pType
);
204 DINode::DIFlags flags
= DINode::DIFlags::FlagPublic
;
206 DICompositeType
* pDIStructTy
= builder
.createStructType(pFile
, name
, pFile
, lineNum
, size
, alignment
,
207 flags
, nullptr, builder
.getOrCreateArray(ElemTypes
));
209 // Register mapping now to break loops (in case struct contains itself or pointers to itself)
210 mDebugStructMap
[pType
] = pDIStructTy
;
213 for (auto& elem
: pType
->elements())
215 std::string name
= members
[idx
].first
;
216 uint32_t lineNum
= members
[idx
].second
;
217 size
= DL
.getTypeAllocSizeInBits(elem
);
218 alignment
= DL
.getABITypeAlignment(elem
);
219 uint32_t offset
= DL
.getStructLayout(pType
)->getElementOffsetInBits(idx
);
220 llvm::DIType
* pDebugTy
= GetDebugType(elem
);
221 ElemTypes
.push_back(builder
.createMemberType(pDIStructTy
, name
, pFile
, lineNum
, size
, alignment
, offset
, flags
, pDebugTy
));
226 pDIStructTy
->replaceElements(builder
.getOrCreateArray(ElemTypes
));
230 DIType
* JitManager::GetDebugArrayType(Type
* pTy
)
232 DIBuilder
builder(*mpCurrentModule
);
233 DataLayout DL
= DataLayout(mpCurrentModule
);
234 ArrayType
* pArrayTy
= cast
<ArrayType
>(pTy
);
235 uint32_t size
= DL
.getTypeAllocSizeInBits(pArrayTy
);
236 uint32_t alignment
= DL
.getABITypeAlignment(pArrayTy
);
238 SmallVector
<Metadata
*, 8> Elems
;
239 Elems
.push_back(builder
.getOrCreateSubrange(0, pArrayTy
->getNumElements()));
240 return builder
.createArrayType(size
, alignment
, GetDebugType(pArrayTy
->getElementType()), builder
.getOrCreateArray(Elems
));
243 // Create a DIType from llvm Type
244 DIType
* JitManager::GetDebugType(Type
* pTy
)
246 DIBuilder
builder(*mpCurrentModule
);
247 Type::TypeID id
= pTy
->getTypeID();
251 case Type::VoidTyID
: return builder
.createUnspecifiedType("void"); break;
252 #if LLVM_VERSION_MAJOR >= 4
253 case Type::HalfTyID
: return builder
.createBasicType("float16", 16, dwarf::DW_ATE_float
); break;
254 case Type::FloatTyID
: return builder
.createBasicType("float", 32, dwarf::DW_ATE_float
); break;
255 case Type::DoubleTyID
: return builder
.createBasicType("double", 64, dwarf::DW_ATE_float
); break;
257 case Type::HalfTyID
: return builder
.createBasicType("float16", 16, 0, dwarf::DW_ATE_float
); break;
258 case Type::FloatTyID
: return builder
.createBasicType("float", 32, 0, dwarf::DW_ATE_float
); break;
259 case Type::DoubleTyID
: return builder
.createBasicType("double", 64, 0, dwarf::DW_ATE_float
); break;
261 case Type::IntegerTyID
: return GetDebugIntegerType(pTy
); break;
262 case Type::StructTyID
: return GetDebugStructType(pTy
); break;
263 case Type::ArrayTyID
: return GetDebugArrayType(pTy
); break;
264 case Type::PointerTyID
: return builder
.createPointerType(GetDebugType(pTy
->getPointerElementType()), 64, 64); break;
265 case Type::VectorTyID
: return GetDebugVectorType(pTy
); break;
266 case Type::FunctionTyID
: return GetDebugFunctionType(pTy
); break;
267 default: SWR_ASSERT(false, "Unimplemented llvm type");
272 // Create a DISubroutineType from an llvm FunctionType
273 DIType
* JitManager::GetDebugFunctionType(Type
* pTy
)
275 SmallVector
<Metadata
*, 8> ElemTypes
;
276 FunctionType
* pFuncTy
= cast
<FunctionType
>(pTy
);
277 DIBuilder
builder(*mpCurrentModule
);
280 ElemTypes
.push_back(GetDebugType(pFuncTy
->getReturnType()));
283 for (auto& param
: pFuncTy
->params())
285 ElemTypes
.push_back(GetDebugType(param
));
288 return builder
.createSubroutineType(builder
.getOrCreateTypeArray(ElemTypes
));
291 DIType
* JitManager::GetDebugIntegerType(Type
* pTy
)
293 DIBuilder
builder(*mpCurrentModule
);
294 IntegerType
* pIntTy
= cast
<IntegerType
>(pTy
);
295 switch (pIntTy
->getBitWidth())
297 #if LLVM_VERSION_MAJOR >= 4
298 case 1: return builder
.createBasicType("int1", 1, dwarf::DW_ATE_unsigned
); break;
299 case 8: return builder
.createBasicType("int8", 8, dwarf::DW_ATE_signed
); break;
300 case 16: return builder
.createBasicType("int16", 16, dwarf::DW_ATE_signed
); break;
301 case 32: return builder
.createBasicType("int", 32, dwarf::DW_ATE_signed
); break;
302 case 64: return builder
.createBasicType("int64", 64, dwarf::DW_ATE_signed
); break;
304 case 1: return builder
.createBasicType("int1", 1, 0, dwarf::DW_ATE_unsigned
); break;
305 case 8: return builder
.createBasicType("int8", 8, 0, dwarf::DW_ATE_signed
); break;
306 case 16: return builder
.createBasicType("int16", 16, 0, dwarf::DW_ATE_signed
); break;
307 case 32: return builder
.createBasicType("int", 32, 0, dwarf::DW_ATE_signed
); break;
308 case 64: return builder
.createBasicType("int64", 64, 0, dwarf::DW_ATE_signed
); break;
310 default: SWR_ASSERT(false, "Unimplemented integer bit width");
315 DIType
* JitManager::GetDebugVectorType(Type
* pTy
)
317 DIBuilder
builder(*mpCurrentModule
);
318 VectorType
* pVecTy
= cast
<VectorType
>(pTy
);
319 DataLayout DL
= DataLayout(mpCurrentModule
);
320 uint32_t size
= DL
.getTypeAllocSizeInBits(pVecTy
);
321 uint32_t alignment
= DL
.getABITypeAlignment(pVecTy
);
322 SmallVector
<Metadata
*, 1> Elems
;
323 Elems
.push_back(builder
.getOrCreateSubrange(0, pVecTy
->getVectorNumElements()));
325 return builder
.createVectorType(size
, alignment
, GetDebugType(pVecTy
->getVectorElementType()), builder
.getOrCreateArray(Elems
));
329 //////////////////////////////////////////////////////////////////////////
330 /// @brief Dump function x86 assembly to file.
331 /// @note This should only be called after the module has been jitted to x86 and the
332 /// module will not be further accessed.
333 void JitManager::DumpAsm(Function
* pFunction
, const char* fileName
)
335 if (KNOB_DUMP_SHADER_IR
)
339 DWORD pid
= GetCurrentProcessId();
340 char procname
[MAX_PATH
];
341 GetModuleFileNameA(NULL
, procname
, MAX_PATH
);
342 const char* pBaseName
= strrchr(procname
, '\\');
343 std::stringstream outDir
;
344 outDir
<< JITTER_OUTPUT_DIR
<< pBaseName
<< "_" << pid
<< std::ends
;
345 CreateDirectoryPath(outDir
.str().c_str());
349 Module
* pModule
= pFunction
->getParent();
350 const char *funcName
= pFunction
->getName().data();
353 sprintf(fName
, "%s\\%s.%s.asm", outDir
.str().c_str(), funcName
, fileName
);
355 sprintf(fName
, "%s.%s.asm", funcName
, fileName
);
358 raw_fd_ostream
filestream(fName
, EC
, llvm::sys::fs::F_None
);
360 legacy::PassManager
* pMPasses
= new legacy::PassManager();
361 auto* pTarget
= mpExec
->getTargetMachine();
362 pTarget
->Options
.MCOptions
.AsmVerbose
= true;
363 pTarget
->addPassesToEmitFile(*pMPasses
, filestream
, TargetMachine::CGFT_AssemblyFile
);
364 pMPasses
->run(*pModule
);
366 pTarget
->Options
.MCOptions
.AsmVerbose
= false;
370 std::string
JitManager::GetOutputDir()
373 DWORD pid
= GetCurrentProcessId();
374 char procname
[MAX_PATH
];
375 GetModuleFileNameA(NULL
, procname
, MAX_PATH
);
376 const char* pBaseName
= strrchr(procname
, '\\');
377 std::stringstream outDir
;
378 outDir
<< JITTER_OUTPUT_DIR
<< pBaseName
<< "_" << pid
;
379 CreateDirectoryPath(outDir
.str().c_str());
385 //////////////////////////////////////////////////////////////////////////
386 /// @brief Dump function to file.
387 void JitManager::DumpToFile(Module
*M
, const char *fileName
)
389 if (KNOB_DUMP_SHADER_IR
)
391 std::string outDir
= GetOutputDir();
394 const char *funcName
= M
->getName().data();
397 sprintf(fName
, "%s\\%s.%s.ll", outDir
.c_str(), funcName
, fileName
);
399 sprintf(fName
, "%s.%s.ll", funcName
, fileName
);
401 raw_fd_ostream
fd(fName
, EC
, llvm::sys::fs::F_None
);
402 M
->print(fd
, nullptr);
407 //////////////////////////////////////////////////////////////////////////
408 /// @brief Dump function to file.
409 void JitManager::DumpToFile(Function
*f
, const char *fileName
)
411 if (KNOB_DUMP_SHADER_IR
)
413 std::string outDir
= GetOutputDir();
416 const char *funcName
= f
->getName().data();
419 sprintf(fName
, "%s\\%s.%s.ll", outDir
.c_str(), funcName
, fileName
);
421 sprintf(fName
, "%s.%s.ll", funcName
, fileName
);
423 raw_fd_ostream
fd(fName
, EC
, llvm::sys::fs::F_None
);
424 Module
* pModule
= f
->getParent();
425 pModule
->print(fd
, nullptr);
428 sprintf(fName
, "%s\\cfg.%s.%s.dot", outDir
.c_str(), funcName
, fileName
);
430 sprintf(fName
, "cfg.%s.%s.dot", funcName
, fileName
);
434 raw_fd_ostream
fd_cfg(fName
, EC
, llvm::sys::fs::F_Text
);
435 WriteGraph(fd_cfg
, (const Function
*)f
);
443 bool g_DllActive
= true;
445 //////////////////////////////////////////////////////////////////////////
446 /// @brief Create JIT context.
447 /// @param simdWidth - SIMD width to be used in generated program.
448 HANDLE JITCALL
JitCreateContext(uint32_t targetSimdWidth
, const char* arch
, const char* core
)
450 return new JitManager(targetSimdWidth
, arch
, core
);
453 //////////////////////////////////////////////////////////////////////////
454 /// @brief Destroy JIT context.
455 void JITCALL
JitDestroyContext(HANDLE hJitContext
)
459 delete reinterpret_cast<JitManager
*>(hJitContext
);
464 //////////////////////////////////////////////////////////////////////////
466 //////////////////////////////////////////////////////////////////////////
468 //////////////////////////////////////////////////////////////////////////
469 /// JitCacheFileHeader
470 //////////////////////////////////////////////////////////////////////////
471 struct JitCacheFileHeader
476 const std::string
& moduleID
,
477 const std::string
& cpu
,
484 strncpy(m_ModuleID
, moduleID
.c_str(), JC_STR_MAX_LEN
- 1);
485 m_ModuleID
[JC_STR_MAX_LEN
- 1] = 0;
486 strncpy(m_Cpu
, cpu
.c_str(), JC_STR_MAX_LEN
- 1);
487 m_Cpu
[JC_STR_MAX_LEN
- 1] = 0;
488 m_optLevel
= optLevel
;
491 #if defined(ENABLE_JIT_DEBUG)
495 const std::string
& moduleID
,
496 const std::string
& cpu
,
502 Init(llCRC
, objCRC
, moduleID
, cpu
, optLevel
, objSize
);
516 bool IsValid(uint32_t llCRC
, const std::string
& moduleID
, const std::string
& cpu
, uint32_t optLevel
)
518 if ((m_MagicNumber
!= JC_MAGIC_NUMBER
) ||
519 (m_llCRC
!= llCRC
) ||
520 (m_platformKey
!= JC_PLATFORM_KEY
) ||
521 (m_optLevel
!= optLevel
))
526 m_ModuleID
[JC_STR_MAX_LEN
- 1] = 0;
527 if (strncmp(moduleID
.c_str(), m_ModuleID
, JC_STR_MAX_LEN
- 1))
532 m_Cpu
[JC_STR_MAX_LEN
- 1] = 0;
533 if (strncmp(cpu
.c_str(), m_Cpu
, JC_STR_MAX_LEN
- 1))
541 uint64_t GetObjectSize() const { return m_objSize
; }
542 uint64_t GetObjectCRC() const { return m_objCRC
; }
543 #if defined(ENABLE_JIT_DEBUG)
544 uint64_t GetSharedModuleSize() const { return m_modSize
; }
545 uint64_t GetSharedModuleCRC() const { return m_modCRC
; }
549 static const uint64_t JC_MAGIC_NUMBER
= 0xfedcba9876543211ULL
+ 3;
550 static const size_t JC_STR_MAX_LEN
= 32;
551 static const uint32_t JC_PLATFORM_KEY
=
552 (LLVM_VERSION_MAJOR
<< 24) |
553 (LLVM_VERSION_MINOR
<< 16) |
554 (LLVM_VERSION_PATCH
<< 8) |
555 ((sizeof(void*) > sizeof(uint32_t)) ? 1 : 0);
557 uint64_t m_MagicNumber
= JC_MAGIC_NUMBER
;
558 uint64_t m_objSize
= 0;
559 uint32_t m_llCRC
= 0;
560 uint32_t m_platformKey
= JC_PLATFORM_KEY
;
561 uint32_t m_objCRC
= 0;
562 uint32_t m_optLevel
= 0;
563 char m_ModuleID
[JC_STR_MAX_LEN
] = {};
564 char m_Cpu
[JC_STR_MAX_LEN
] = {};
565 #if defined(ENABLE_JIT_DEBUG)
566 uint32_t m_modCRC
= 0;
567 uint64_t m_modSize
= 0;
571 static inline uint32_t ComputeModuleCRC(const llvm::Module
* M
)
573 std::string bitcodeBuffer
;
574 raw_string_ostream
bitcodeStream(bitcodeBuffer
);
576 llvm::WriteBitcodeToFile(M
, bitcodeStream
);
577 //M->print(bitcodeStream, nullptr, false);
579 bitcodeStream
.flush();
581 return ComputeCRC(0, bitcodeBuffer
.data(), bitcodeBuffer
.size());
587 #if defined(__APPLE) || defined(FORCE_LINUX) || defined(__linux__) || defined(__gnu_linux__)
588 if (strncmp(KNOB_JIT_CACHE_DIR
.c_str(), "~/", 2) == 0) {
590 if (!(homedir
= getenv("HOME"))) {
591 homedir
= getpwuid(getuid())->pw_dir
;
594 mCacheDir
+= (KNOB_JIT_CACHE_DIR
.c_str() + 1);
598 mCacheDir
= KNOB_JIT_CACHE_DIR
;
603 int ExecUnhookedProcess(const char* pCmdLine
)
605 static const char *g_pEnv
= "RASTY_DISABLE_HOOK=1\0";
607 STARTUPINFOA StartupInfo
{};
608 StartupInfo
.cb
= sizeof(STARTUPINFOA
);
609 PROCESS_INFORMATION procInfo
{};
611 BOOL ProcessValue
= CreateProcessA(
623 if (ProcessValue
&& procInfo
.hProcess
)
625 WaitForSingleObject(procInfo
.hProcess
, INFINITE
);
627 if (!GetExitCodeProcess(procInfo
.hProcess
, &exitVal
))
632 CloseHandle(procInfo
.hProcess
);
641 #if defined(_WIN64) && defined(ENABLE_JIT_DEBUG) && defined(JIT_BASE_DIR)
642 EXTERN_C IMAGE_DOS_HEADER __ImageBase
;
643 static __inline HINSTANCE
GetModuleHINSTANCE() { return (HINSTANCE
)&__ImageBase
; }
646 /// notifyObjectCompiled - Provides a pointer to compiled code for Module M.
647 void JitCache::notifyObjectCompiled(const llvm::Module
*M
, llvm::MemoryBufferRef Obj
)
649 const std::string
& moduleID
= M
->getModuleIdentifier();
650 if (!moduleID
.length())
655 if (!llvm::sys::fs::exists(mCacheDir
.str()) &&
656 llvm::sys::fs::create_directories(mCacheDir
.str()))
658 SWR_INVALID("Unable to create directory: %s", mCacheDir
.c_str());
662 JitCacheFileHeader header
;
664 llvm::SmallString
<MAX_PATH
> filePath
= mCacheDir
;
665 llvm::sys::path::append(filePath
, moduleID
);
667 llvm::SmallString
<MAX_PATH
> objPath
= filePath
;
668 objPath
+= JIT_OBJ_EXT
;
672 llvm::raw_fd_ostream
fileObj(objPath
.c_str(), err
, llvm::sys::fs::F_None
);
673 fileObj
<< Obj
.getBuffer();
680 llvm::raw_fd_ostream
fileObj(filePath
.c_str(), err
, llvm::sys::fs::F_None
);
682 uint32_t objcrc
= ComputeCRC(0, Obj
.getBufferStart(), Obj
.getBufferSize());
684 header
.Init(mCurrentModuleCRC
, objcrc
, moduleID
, mCpu
, mOptLevel
, Obj
.getBufferSize());
686 fileObj
.write((const char*)&header
, sizeof(header
));
691 /// Returns a pointer to a newly allocated MemoryBuffer that contains the
692 /// object which corresponds with Module M, or 0 if an object is not
694 std::unique_ptr
<llvm::MemoryBuffer
> JitCache::getObject(const llvm::Module
* M
)
696 const std::string
& moduleID
= M
->getModuleIdentifier();
697 mCurrentModuleCRC
= ComputeModuleCRC(M
);
699 if (!moduleID
.length())
704 if (!llvm::sys::fs::exists(mCacheDir
))
709 llvm::SmallString
<MAX_PATH
> filePath
= mCacheDir
;
710 llvm::sys::path::append(filePath
, moduleID
);
712 llvm::SmallString
<MAX_PATH
> objFilePath
= filePath
;
713 objFilePath
+= JIT_OBJ_EXT
;
715 #if defined(ENABLE_JIT_DEBUG)
716 FILE* fpModuleIn
= nullptr;
718 FILE* fpObjIn
= nullptr;
719 FILE* fpIn
= fopen(filePath
.c_str(), "rb");
725 std::unique_ptr
<llvm::MemoryBuffer
> pBuf
= nullptr;
728 JitCacheFileHeader header
;
729 if (!fread(&header
, sizeof(header
), 1, fpIn
))
734 if (!header
.IsValid(mCurrentModuleCRC
, moduleID
, mCpu
, mOptLevel
))
739 fpObjIn
= fopen(objFilePath
.c_str(), "rb");
745 #if LLVM_VERSION_MAJOR < 6
746 pBuf
= llvm::MemoryBuffer::getNewUninitMemBuffer(size_t(header
.GetObjectSize()));
748 pBuf
= llvm::WritableMemoryBuffer::getNewUninitMemBuffer(size_t(header
.GetObjectSize()));
750 if (!fread(const_cast<char*>(pBuf
->getBufferStart()), header
.GetObjectSize(), 1, fpObjIn
))
756 if (header
.GetObjectCRC() != ComputeCRC(0, pBuf
->getBufferStart(), pBuf
->getBufferSize()))
758 SWR_TRACE("Invalid object cache file, ignoring: %s", filePath
.c_str());
773 #if defined(ENABLE_JIT_DEBUG)