1 /****************************************************************************
2 * Copyright (C) 2014-2018 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
),
66 mpCurrentModule
= nullptr;
69 InitializeNativeTarget();
70 InitializeNativeTargetAsmPrinter();
71 InitializeNativeTargetDisassembler();
74 // force JIT to use the same CPU arch as the rest of swr
77 #if USE_SIMD16_SHADERS
80 mHostCpuName
= StringRef("knl");
84 mHostCpuName
= StringRef("skylake-avx512");
88 mHostCpuName
= StringRef("core-avx2");
95 else if (mArch
.AVX2())
97 mHostCpuName
= StringRef("core-avx2");
103 else if (mArch
.AVX())
107 mHostCpuName
= StringRef("core-avx-i");
111 mHostCpuName
= StringRef("corei7-avx");
120 SWR_INVALID("Jitting requires at least AVX ISA support");
124 mOptLevel
= CodeGenOpt::Aggressive
;
126 if (KNOB_JIT_OPTIMIZATION_LEVEL
>= CodeGenOpt::None
&&
127 KNOB_JIT_OPTIMIZATION_LEVEL
<= CodeGenOpt::Aggressive
)
129 mOptLevel
= CodeGenOpt::Level(KNOB_JIT_OPTIMIZATION_LEVEL
);
132 if (KNOB_JIT_ENABLE_CACHE
)
134 mCache
.Init(this, mHostCpuName
, mOptLevel
);
138 mIsModuleFinalized
= true;
140 // fetch function signature
141 #if USE_SIMD16_SHADERS
142 // typedef void(__cdecl *PFN_FETCH_FUNC)(SWR_FETCH_CONTEXT& fetchInfo, simd16vertex& out);
144 // typedef void(__cdecl *PFN_FETCH_FUNC)(SWR_FETCH_CONTEXT& fetchInfo, simdvertex& out);
146 std::vector
<Type
*> fsArgs
;
148 // llvm5 is picky and does not take a void * type
149 fsArgs
.push_back(PointerType::get(Gen_SWR_FETCH_CONTEXT(this), 0));
151 fsArgs
.push_back(Type::getInt8PtrTy(mContext
));
153 fsArgs
.push_back(PointerType::get(Gen_SWR_FETCH_CONTEXT(this), 0));
154 #if USE_SIMD16_SHADERS
155 fsArgs
.push_back(PointerType::get(Gen_simd16vertex(this), 0));
157 fsArgs
.push_back(PointerType::get(Gen_simdvertex(this), 0));
160 mFetchShaderTy
= FunctionType::get(Type::getVoidTy(mContext
), fsArgs
, false);
163 // explicitly instantiate used symbols from potentially staticly linked libs
164 sys::DynamicLibrary::AddSymbol("exp2f", &exp2f
);
165 sys::DynamicLibrary::AddSymbol("log2f", &log2f
);
166 sys::DynamicLibrary::AddSymbol("sinf", &sinf
);
167 sys::DynamicLibrary::AddSymbol("cosf", &cosf
);
168 sys::DynamicLibrary::AddSymbol("powf", &powf
);
172 if (KNOB_DUMP_SHADER_IR
)
174 CreateDirectoryPath(INTEL_OUTPUT_DIR
);
175 CreateDirectoryPath(SWR_OUTPUT_DIR
);
176 CreateDirectoryPath(JITTER_OUTPUT_DIR
);
181 void JitManager::CreateExecEngine(std::unique_ptr
<Module
> pModule
)
184 tOpts
.AllowFPOpFusion
= FPOpFusion::Fast
;
185 tOpts
.NoInfsFPMath
= false;
186 tOpts
.NoNaNsFPMath
= false;
187 tOpts
.UnsafeFPMath
= false;
189 // tOpts.PrintMachineCode = true;
191 mpExec
= EngineBuilder(std::move(pModule
))
192 .setTargetOptions(tOpts
)
193 .setOptLevel(mOptLevel
)
194 .setMCPU(mHostCpuName
)
197 if (KNOB_JIT_ENABLE_CACHE
)
199 mpExec
->setObjectCache(&mCache
);
202 #if LLVM_USE_INTEL_JITEVENTS
203 JITEventListener
* vTune
= JITEventListener::createIntelJITEventListener();
204 mpExec
->RegisterJITEventListener(vTune
);
207 mvExecEngines
.push_back(mpExec
);
210 //////////////////////////////////////////////////////////////////////////
211 /// @brief Create new LLVM module.
212 void JitManager::SetupNewModule()
214 SWR_ASSERT(mIsModuleFinalized
== true && "Current module is not finalized!");
216 std::unique_ptr
<Module
> newModule(new Module("", mContext
));
217 mpCurrentModule
= newModule
.get();
218 mpCurrentModule
->setTargetTriple(sys::getProcessTriple());
219 CreateExecEngine(std::move(newModule
));
220 mIsModuleFinalized
= false;
225 JitManager::CreateDebugStructType(StructType
* pType
,
226 const std::string
& name
,
229 const std::vector
<std::pair
<std::string
, uint32_t>>& members
)
231 DIBuilder
builder(*mpCurrentModule
);
232 SmallVector
<Metadata
*, 8> ElemTypes
;
233 DataLayout DL
= DataLayout(mpCurrentModule
);
234 uint32_t size
= DL
.getTypeAllocSizeInBits(pType
);
235 uint32_t alignment
= DL
.getABITypeAlignment(pType
);
236 DINode::DIFlags flags
= DINode::DIFlags::FlagPublic
;
238 DICompositeType
* pDIStructTy
= builder
.createStructType(pFile
,
246 builder
.getOrCreateArray(ElemTypes
));
248 // Register mapping now to break loops (in case struct contains itself or pointers to itself)
249 mDebugStructMap
[pType
] = pDIStructTy
;
252 for (auto& elem
: pType
->elements())
254 std::string name
= members
[idx
].first
;
255 uint32_t lineNum
= members
[idx
].second
;
256 size
= DL
.getTypeAllocSizeInBits(elem
);
257 alignment
= DL
.getABITypeAlignment(elem
);
258 uint32_t offset
= DL
.getStructLayout(pType
)->getElementOffsetInBits(idx
);
259 llvm::DIType
* pDebugTy
= GetDebugType(elem
);
260 ElemTypes
.push_back(builder
.createMemberType(
261 pDIStructTy
, name
, pFile
, lineNum
, size
, alignment
, offset
, flags
, pDebugTy
));
266 pDIStructTy
->replaceElements(builder
.getOrCreateArray(ElemTypes
));
270 DIType
* JitManager::GetDebugArrayType(Type
* pTy
)
272 DIBuilder
builder(*mpCurrentModule
);
273 DataLayout DL
= DataLayout(mpCurrentModule
);
274 ArrayType
* pArrayTy
= cast
<ArrayType
>(pTy
);
275 uint32_t size
= DL
.getTypeAllocSizeInBits(pArrayTy
);
276 uint32_t alignment
= DL
.getABITypeAlignment(pArrayTy
);
278 SmallVector
<Metadata
*, 8> Elems
;
279 Elems
.push_back(builder
.getOrCreateSubrange(0, pArrayTy
->getNumElements()));
280 return builder
.createArrayType(
281 size
, alignment
, GetDebugType(pArrayTy
->getElementType()), builder
.getOrCreateArray(Elems
));
284 // Create a DIType from llvm Type
285 DIType
* JitManager::GetDebugType(Type
* pTy
)
287 DIBuilder
builder(*mpCurrentModule
);
288 Type::TypeID id
= pTy
->getTypeID();
293 return builder
.createUnspecifiedType("void");
296 return builder
.createBasicType("float16", 16, dwarf::DW_ATE_float
);
298 case Type::FloatTyID
:
299 return builder
.createBasicType("float", 32, dwarf::DW_ATE_float
);
301 case Type::DoubleTyID
:
302 return builder
.createBasicType("double", 64, dwarf::DW_ATE_float
);
304 case Type::IntegerTyID
:
305 return GetDebugIntegerType(pTy
);
307 case Type::StructTyID
:
308 return GetDebugStructType(pTy
);
310 case Type::ArrayTyID
:
311 return GetDebugArrayType(pTy
);
313 case Type::PointerTyID
:
314 return builder
.createPointerType(GetDebugType(pTy
->getPointerElementType()), 64, 64);
316 #if LLVM_VERSION_MAJOR >= 11
317 case Type::FixedVectorTyID
:
319 case Type::VectorTyID
:
321 return GetDebugVectorType(pTy
);
323 case Type::FunctionTyID
:
324 return GetDebugFunctionType(pTy
);
327 SWR_ASSERT(false, "Unimplemented llvm type");
332 // Create a DISubroutineType from an llvm FunctionType
333 DIType
* JitManager::GetDebugFunctionType(Type
* pTy
)
335 SmallVector
<Metadata
*, 8> ElemTypes
;
336 FunctionType
* pFuncTy
= cast
<FunctionType
>(pTy
);
337 DIBuilder
builder(*mpCurrentModule
);
340 ElemTypes
.push_back(GetDebugType(pFuncTy
->getReturnType()));
343 for (auto& param
: pFuncTy
->params())
345 ElemTypes
.push_back(GetDebugType(param
));
348 return builder
.createSubroutineType(builder
.getOrCreateTypeArray(ElemTypes
));
351 DIType
* JitManager::GetDebugIntegerType(Type
* pTy
)
353 DIBuilder
builder(*mpCurrentModule
);
354 IntegerType
* pIntTy
= cast
<IntegerType
>(pTy
);
355 switch (pIntTy
->getBitWidth())
358 return builder
.createBasicType("int1", 1, dwarf::DW_ATE_unsigned
);
361 return builder
.createBasicType("int8", 8, dwarf::DW_ATE_signed
);
364 return builder
.createBasicType("int16", 16, dwarf::DW_ATE_signed
);
367 return builder
.createBasicType("int", 32, dwarf::DW_ATE_signed
);
370 return builder
.createBasicType("int64", 64, dwarf::DW_ATE_signed
);
373 return builder
.createBasicType("int128", 128, dwarf::DW_ATE_signed
);
376 SWR_ASSERT(false, "Unimplemented integer bit width");
381 DIType
* JitManager::GetDebugVectorType(Type
* pTy
)
383 DIBuilder
builder(*mpCurrentModule
);
384 VectorType
* pVecTy
= cast
<VectorType
>(pTy
);
385 DataLayout DL
= DataLayout(mpCurrentModule
);
386 uint32_t size
= DL
.getTypeAllocSizeInBits(pVecTy
);
387 uint32_t alignment
= DL
.getABITypeAlignment(pVecTy
);
388 SmallVector
<Metadata
*, 1> Elems
;
390 #if LLVM_VERSION_MAJOR >= 11
391 Elems
.push_back(builder
.getOrCreateSubrange(0, pVecTy
->getNumElements()));
393 Elems
.push_back(builder
.getOrCreateSubrange(0, pVecTy
->getVectorNumElements()));
396 return builder
.createVectorType(size
,
398 #if LLVM_VERSION_MAJOR >= 11
399 GetDebugType(pVecTy
->getElementType()),
401 GetDebugType(pVecTy
->getVectorElementType()),
403 builder
.getOrCreateArray(Elems
));
406 //////////////////////////////////////////////////////////////////////////
407 /// @brief Dump function x86 assembly to file.
408 /// @note This should only be called after the module has been jitted to x86 and the
409 /// module will not be further accessed.
410 void JitManager::DumpAsm(Function
* pFunction
, const char* fileName
)
412 if (KNOB_DUMP_SHADER_IR
)
415 DWORD pid
= GetCurrentProcessId();
416 char procname
[MAX_PATH
];
417 GetModuleFileNameA(NULL
, procname
, MAX_PATH
);
418 const char* pBaseName
= strrchr(procname
, '\\');
419 std::stringstream outDir
;
420 outDir
<< JITTER_OUTPUT_DIR
<< pBaseName
<< "_" << pid
<< std::ends
;
421 CreateDirectoryPath(outDir
.str().c_str());
425 Module
* pModule
= pFunction
->getParent();
426 const char* funcName
= pFunction
->getName().data();
429 sprintf(fName
, "%s\\%s.%s.asm", outDir
.str().c_str(), funcName
, fileName
);
431 sprintf(fName
, "%s.%s.asm", funcName
, fileName
);
434 raw_fd_ostream
filestream(fName
, EC
, llvm::sys::fs::F_None
);
436 legacy::PassManager
* pMPasses
= new legacy::PassManager();
437 auto* pTarget
= mpExec
->getTargetMachine();
438 pTarget
->Options
.MCOptions
.AsmVerbose
= true;
439 #if LLVM_VERSION_MAJOR >= 10
440 pTarget
->addPassesToEmitFile(
441 *pMPasses
, filestream
, nullptr, CGFT_AssemblyFile
);
442 #elif LLVM_VERSION_MAJOR >= 7
443 pTarget
->addPassesToEmitFile(
444 *pMPasses
, filestream
, nullptr, TargetMachine::CGFT_AssemblyFile
);
446 pTarget
->addPassesToEmitFile(*pMPasses
, filestream
, TargetMachine::CGFT_AssemblyFile
);
448 pMPasses
->run(*pModule
);
450 pTarget
->Options
.MCOptions
.AsmVerbose
= false;
454 std::string
JitManager::GetOutputDir()
457 DWORD pid
= GetCurrentProcessId();
458 char procname
[MAX_PATH
];
459 GetModuleFileNameA(NULL
, procname
, MAX_PATH
);
460 const char* pBaseName
= strrchr(procname
, '\\');
461 std::stringstream outDir
;
462 outDir
<< JITTER_OUTPUT_DIR
<< pBaseName
<< "_" << pid
;
463 CreateDirectoryPath(outDir
.str().c_str());
469 //////////////////////////////////////////////////////////////////////////
470 /// @brief Dump function to file.
471 void JitManager::DumpToFile(Module
* M
,
472 const char* fileName
,
473 llvm::AssemblyAnnotationWriter
* annotater
)
475 if (KNOB_DUMP_SHADER_IR
)
477 std::string outDir
= GetOutputDir();
480 const char* funcName
= M
->getName().data();
483 sprintf(fName
, "%s\\%s.%s.ll", outDir
.c_str(), funcName
, fileName
);
485 sprintf(fName
, "%s.%s.ll", funcName
, fileName
);
487 raw_fd_ostream
fd(fName
, EC
, llvm::sys::fs::F_None
);
488 M
->print(fd
, annotater
);
493 //////////////////////////////////////////////////////////////////////////
494 /// @brief Dump function to file.
495 void JitManager::DumpToFile(Function
* f
, const char* fileName
)
497 if (KNOB_DUMP_SHADER_IR
)
499 std::string outDir
= GetOutputDir();
502 const char* funcName
= f
->getName().data();
505 sprintf(fName
, "%s\\%s.%s.ll", outDir
.c_str(), funcName
, fileName
);
507 sprintf(fName
, "%s.%s.ll", funcName
, fileName
);
509 raw_fd_ostream
fd(fName
, EC
, llvm::sys::fs::F_None
);
510 f
->print(fd
, nullptr);
513 sprintf(fName
, "%s\\cfg.%s.%s.dot", outDir
.c_str(), funcName
, fileName
);
515 sprintf(fName
, "cfg.%s.%s.dot", funcName
, fileName
);
519 raw_fd_ostream
fd_cfg(fName
, EC
, llvm::sys::fs::F_Text
);
520 WriteGraph(fd_cfg
, (const Function
*)f
);
527 bool g_DllActive
= true;
529 //////////////////////////////////////////////////////////////////////////
530 /// @brief Create JIT context.
531 /// @param simdWidth - SIMD width to be used in generated program.
532 HANDLE JITCALL
JitCreateContext(uint32_t targetSimdWidth
, const char* arch
, const char* core
)
534 return new JitManager(targetSimdWidth
, arch
, core
);
537 //////////////////////////////////////////////////////////////////////////
538 /// @brief Destroy JIT context.
539 void JITCALL
JitDestroyContext(HANDLE hJitContext
)
543 delete reinterpret_cast<JitManager
*>(hJitContext
);
548 //////////////////////////////////////////////////////////////////////////
550 //////////////////////////////////////////////////////////////////////////
552 //////////////////////////////////////////////////////////////////////////
553 /// JitCacheFileHeader
554 //////////////////////////////////////////////////////////////////////////
555 struct JitCacheFileHeader
557 void Init(uint32_t llCRC
,
559 const std::string
& moduleID
,
560 const std::string
& cpu
,
567 strncpy(m_ModuleID
, moduleID
.c_str(), JC_STR_MAX_LEN
- 1);
568 m_ModuleID
[JC_STR_MAX_LEN
- 1] = 0;
569 strncpy(m_Cpu
, cpu
.c_str(), JC_STR_MAX_LEN
- 1);
570 m_Cpu
[JC_STR_MAX_LEN
- 1] = 0;
571 m_optLevel
= optLevel
;
576 IsValid(uint32_t llCRC
, const std::string
& moduleID
, const std::string
& cpu
, uint32_t optLevel
)
578 if ((m_MagicNumber
!= JC_MAGIC_NUMBER
) || (m_llCRC
!= llCRC
) ||
579 (m_platformKey
!= JC_PLATFORM_KEY
) || (m_optLevel
!= optLevel
))
584 m_ModuleID
[JC_STR_MAX_LEN
- 1] = 0;
585 if (strncmp(moduleID
.c_str(), m_ModuleID
, JC_STR_MAX_LEN
- 1))
590 m_Cpu
[JC_STR_MAX_LEN
- 1] = 0;
591 if (strncmp(cpu
.c_str(), m_Cpu
, JC_STR_MAX_LEN
- 1))
599 uint64_t GetObjectSize() const { return m_objSize
; }
600 uint64_t GetObjectCRC() const { return m_objCRC
; }
603 static const uint64_t JC_MAGIC_NUMBER
= 0xfedcba9876543210ULL
+ 7;
604 static const size_t JC_STR_MAX_LEN
= 32;
605 static const uint32_t JC_PLATFORM_KEY
= (LLVM_VERSION_MAJOR
<< 24) |
606 (LLVM_VERSION_MINOR
<< 16) | (LLVM_VERSION_PATCH
<< 8) |
607 ((sizeof(void*) > sizeof(uint32_t)) ? 1 : 0);
609 uint64_t m_MagicNumber
= JC_MAGIC_NUMBER
;
610 uint64_t m_objSize
= 0;
611 uint32_t m_llCRC
= 0;
612 uint32_t m_platformKey
= JC_PLATFORM_KEY
;
613 uint32_t m_objCRC
= 0;
614 uint32_t m_optLevel
= 0;
615 char m_ModuleID
[JC_STR_MAX_LEN
] = {};
616 char m_Cpu
[JC_STR_MAX_LEN
] = {};
619 static inline uint32_t ComputeModuleCRC(const llvm::Module
* M
)
621 std::string bitcodeBuffer
;
622 raw_string_ostream
bitcodeStream(bitcodeBuffer
);
624 #if LLVM_VERSION_MAJOR >= 7
625 llvm::WriteBitcodeToFile(*M
, bitcodeStream
);
627 llvm::WriteBitcodeToFile(M
, bitcodeStream
);
629 // M->print(bitcodeStream, nullptr, false);
631 bitcodeStream
.flush();
633 return ComputeCRC(0, bitcodeBuffer
.data(), bitcodeBuffer
.size());
639 #if defined(__APPLE__) || defined(FORCE_LINUX) || defined(__linux__) || defined(__gnu_linux__)
640 if (strncmp(KNOB_JIT_CACHE_DIR
.c_str(), "~/", 2) == 0)
643 if (!(homedir
= getenv("HOME")))
645 homedir
= getpwuid(getuid())->pw_dir
;
648 mCacheDir
+= (KNOB_JIT_CACHE_DIR
.c_str() + 1);
653 mCacheDir
= KNOB_JIT_CACHE_DIR
;
656 // Create cache dir at startup to allow jitter to write debug.ll files
657 // to that directory.
658 if (!llvm::sys::fs::exists(mCacheDir
.str()) &&
659 llvm::sys::fs::create_directories(mCacheDir
.str()))
661 SWR_INVALID("Unable to create directory: %s", mCacheDir
.c_str());
666 int ExecUnhookedProcess(const std::string
& CmdLine
, std::string
* pStdOut
, std::string
* pStdErr
)
669 return ExecCmd(CmdLine
, nullptr, pStdOut
, pStdErr
);
672 /// Calculate actual directory where module will be cached.
673 /// This is always a subdirectory of mCacheDir. Full absolute
674 /// path name will be stored in mCurrentModuleCacheDir
675 void JitCache::CalcModuleCacheDir()
677 mModuleCacheDir
.clear();
679 llvm::SmallString
<MAX_PATH
> moduleDir
= mCacheDir
;
681 // Create 4 levels of directory hierarchy based on CRC, 256 entries each
682 uint8_t* pCRC
= (uint8_t*)&mCurrentModuleCRC
;
683 for (uint32_t i
= 0; i
< 4; ++i
)
685 llvm::sys::path::append(moduleDir
, std::to_string((int)pCRC
[i
]));
688 mModuleCacheDir
= moduleDir
;
691 /// notifyObjectCompiled - Provides a pointer to compiled code for Module M.
692 void JitCache::notifyObjectCompiled(const llvm::Module
* M
, llvm::MemoryBufferRef Obj
)
694 const std::string
& moduleID
= M
->getModuleIdentifier();
695 if (!moduleID
.length())
700 if (!mModuleCacheDir
.size())
702 SWR_INVALID("Unset module cache directory");
706 if (!llvm::sys::fs::exists(mModuleCacheDir
.str()) &&
707 llvm::sys::fs::create_directories(mModuleCacheDir
.str()))
709 SWR_INVALID("Unable to create directory: %s", mModuleCacheDir
.c_str());
713 JitCacheFileHeader header
;
715 llvm::SmallString
<MAX_PATH
> filePath
= mModuleCacheDir
;
716 llvm::sys::path::append(filePath
, moduleID
);
718 llvm::SmallString
<MAX_PATH
> objPath
= filePath
;
719 objPath
+= JIT_OBJ_EXT
;
723 llvm::raw_fd_ostream
fileObj(objPath
.c_str(), err
, llvm::sys::fs::F_None
);
724 fileObj
<< Obj
.getBuffer();
731 llvm::raw_fd_ostream
fileObj(filePath
.c_str(), err
, llvm::sys::fs::F_None
);
733 uint32_t objcrc
= ComputeCRC(0, Obj
.getBufferStart(), Obj
.getBufferSize());
735 header
.Init(mCurrentModuleCRC
, objcrc
, moduleID
, mCpu
, mOptLevel
, Obj
.getBufferSize());
737 fileObj
.write((const char*)&header
, sizeof(header
));
742 /// Returns a pointer to a newly allocated MemoryBuffer that contains the
743 /// object which corresponds with Module M, or 0 if an object is not
745 std::unique_ptr
<llvm::MemoryBuffer
> JitCache::getObject(const llvm::Module
* M
)
747 const std::string
& moduleID
= M
->getModuleIdentifier();
748 mCurrentModuleCRC
= ComputeModuleCRC(M
);
750 if (!moduleID
.length())
755 CalcModuleCacheDir();
757 if (!llvm::sys::fs::exists(mModuleCacheDir
))
762 llvm::SmallString
<MAX_PATH
> filePath
= mModuleCacheDir
;
763 llvm::sys::path::append(filePath
, moduleID
);
765 llvm::SmallString
<MAX_PATH
> objFilePath
= filePath
;
766 objFilePath
+= JIT_OBJ_EXT
;
768 FILE* fpObjIn
= nullptr;
769 FILE* fpIn
= fopen(filePath
.c_str(), "rb");
775 std::unique_ptr
<llvm::MemoryBuffer
> pBuf
= nullptr;
778 JitCacheFileHeader header
;
779 if (!fread(&header
, sizeof(header
), 1, fpIn
))
784 if (!header
.IsValid(mCurrentModuleCRC
, moduleID
, mCpu
, mOptLevel
))
789 fpObjIn
= fopen(objFilePath
.c_str(), "rb");
795 #if LLVM_VERSION_MAJOR < 6
796 pBuf
= llvm::MemoryBuffer::getNewUninitMemBuffer(size_t(header
.GetObjectSize()));
798 pBuf
= llvm::WritableMemoryBuffer::getNewUninitMemBuffer(size_t(header
.GetObjectSize()));
800 if (!fread(const_cast<char*>(pBuf
->getBufferStart()), header
.GetObjectSize(), 1, fpObjIn
))
806 if (header
.GetObjectCRC() != ComputeCRC(0, pBuf
->getBufferStart(), pBuf
->getBufferSize()))
808 SWR_TRACE("Invalid object cache file, ignoring: %s", filePath
.c_str());
826 void InterleaveAssemblyAnnotater::emitInstructionAnnot(const llvm::Instruction
* pInst
,
827 llvm::formatted_raw_ostream
& OS
)
829 auto dbgLoc
= pInst
->getDebugLoc();
832 unsigned int line
= dbgLoc
.getLine();
833 if (line
!= mCurrentLineNo
)
835 if (line
> 0 && line
<= mAssembly
.size())
837 // HACK: here we assume that OS is a formatted_raw_ostream(ods())
838 // and modify the color accordingly. We can't do the color
839 // modification on OS because formatted_raw_ostream strips
840 // the color information. The only way to fix this behavior
842 OS
<< "\n; " << line
<< ": " << mAssembly
[line
- 1] << "\n";
844 mCurrentLineNo
= line
;