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 case Type::VectorTyID
:
317 return GetDebugVectorType(pTy
);
319 case Type::FunctionTyID
:
320 return GetDebugFunctionType(pTy
);
323 SWR_ASSERT(false, "Unimplemented llvm type");
328 // Create a DISubroutineType from an llvm FunctionType
329 DIType
* JitManager::GetDebugFunctionType(Type
* pTy
)
331 SmallVector
<Metadata
*, 8> ElemTypes
;
332 FunctionType
* pFuncTy
= cast
<FunctionType
>(pTy
);
333 DIBuilder
builder(*mpCurrentModule
);
336 ElemTypes
.push_back(GetDebugType(pFuncTy
->getReturnType()));
339 for (auto& param
: pFuncTy
->params())
341 ElemTypes
.push_back(GetDebugType(param
));
344 return builder
.createSubroutineType(builder
.getOrCreateTypeArray(ElemTypes
));
347 DIType
* JitManager::GetDebugIntegerType(Type
* pTy
)
349 DIBuilder
builder(*mpCurrentModule
);
350 IntegerType
* pIntTy
= cast
<IntegerType
>(pTy
);
351 switch (pIntTy
->getBitWidth())
354 return builder
.createBasicType("int1", 1, dwarf::DW_ATE_unsigned
);
357 return builder
.createBasicType("int8", 8, dwarf::DW_ATE_signed
);
360 return builder
.createBasicType("int16", 16, dwarf::DW_ATE_signed
);
363 return builder
.createBasicType("int", 32, dwarf::DW_ATE_signed
);
366 return builder
.createBasicType("int64", 64, dwarf::DW_ATE_signed
);
369 return builder
.createBasicType("int128", 128, dwarf::DW_ATE_signed
);
372 SWR_ASSERT(false, "Unimplemented integer bit width");
377 DIType
* JitManager::GetDebugVectorType(Type
* pTy
)
379 DIBuilder
builder(*mpCurrentModule
);
380 VectorType
* pVecTy
= cast
<VectorType
>(pTy
);
381 DataLayout DL
= DataLayout(mpCurrentModule
);
382 uint32_t size
= DL
.getTypeAllocSizeInBits(pVecTy
);
383 uint32_t alignment
= DL
.getABITypeAlignment(pVecTy
);
384 SmallVector
<Metadata
*, 1> Elems
;
385 Elems
.push_back(builder
.getOrCreateSubrange(0, pVecTy
->getVectorNumElements()));
387 return builder
.createVectorType(size
,
389 GetDebugType(pVecTy
->getVectorElementType()),
390 builder
.getOrCreateArray(Elems
));
393 //////////////////////////////////////////////////////////////////////////
394 /// @brief Dump function x86 assembly to file.
395 /// @note This should only be called after the module has been jitted to x86 and the
396 /// module will not be further accessed.
397 void JitManager::DumpAsm(Function
* pFunction
, const char* fileName
)
399 if (KNOB_DUMP_SHADER_IR
)
402 DWORD pid
= GetCurrentProcessId();
403 char procname
[MAX_PATH
];
404 GetModuleFileNameA(NULL
, procname
, MAX_PATH
);
405 const char* pBaseName
= strrchr(procname
, '\\');
406 std::stringstream outDir
;
407 outDir
<< JITTER_OUTPUT_DIR
<< pBaseName
<< "_" << pid
<< std::ends
;
408 CreateDirectoryPath(outDir
.str().c_str());
412 Module
* pModule
= pFunction
->getParent();
413 const char* funcName
= pFunction
->getName().data();
416 sprintf(fName
, "%s\\%s.%s.asm", outDir
.str().c_str(), funcName
, fileName
);
418 sprintf(fName
, "%s.%s.asm", funcName
, fileName
);
421 raw_fd_ostream
filestream(fName
, EC
, llvm::sys::fs::F_None
);
423 legacy::PassManager
* pMPasses
= new legacy::PassManager();
424 auto* pTarget
= mpExec
->getTargetMachine();
425 pTarget
->Options
.MCOptions
.AsmVerbose
= true;
426 #if LLVM_VERSION_MAJOR >= 7
427 pTarget
->addPassesToEmitFile(
428 *pMPasses
, filestream
, nullptr, TargetMachine::CGFT_AssemblyFile
);
430 pTarget
->addPassesToEmitFile(*pMPasses
, filestream
, TargetMachine::CGFT_AssemblyFile
);
432 pMPasses
->run(*pModule
);
434 pTarget
->Options
.MCOptions
.AsmVerbose
= false;
438 std::string
JitManager::GetOutputDir()
441 DWORD pid
= GetCurrentProcessId();
442 char procname
[MAX_PATH
];
443 GetModuleFileNameA(NULL
, procname
, MAX_PATH
);
444 const char* pBaseName
= strrchr(procname
, '\\');
445 std::stringstream outDir
;
446 outDir
<< JITTER_OUTPUT_DIR
<< pBaseName
<< "_" << pid
;
447 CreateDirectoryPath(outDir
.str().c_str());
453 //////////////////////////////////////////////////////////////////////////
454 /// @brief Dump function to file.
455 void JitManager::DumpToFile(Module
* M
,
456 const char* fileName
,
457 llvm::AssemblyAnnotationWriter
* annotater
)
459 if (KNOB_DUMP_SHADER_IR
)
461 std::string outDir
= GetOutputDir();
464 const char* funcName
= M
->getName().data();
467 sprintf(fName
, "%s\\%s.%s.ll", outDir
.c_str(), funcName
, fileName
);
469 sprintf(fName
, "%s.%s.ll", funcName
, fileName
);
471 raw_fd_ostream
fd(fName
, EC
, llvm::sys::fs::F_None
);
472 M
->print(fd
, annotater
);
477 //////////////////////////////////////////////////////////////////////////
478 /// @brief Dump function to file.
479 void JitManager::DumpToFile(Function
* f
, const char* fileName
)
481 if (KNOB_DUMP_SHADER_IR
)
483 std::string outDir
= GetOutputDir();
486 const char* funcName
= f
->getName().data();
489 sprintf(fName
, "%s\\%s.%s.ll", outDir
.c_str(), funcName
, fileName
);
491 sprintf(fName
, "%s.%s.ll", funcName
, fileName
);
493 raw_fd_ostream
fd(fName
, EC
, llvm::sys::fs::F_None
);
494 f
->print(fd
, nullptr);
497 sprintf(fName
, "%s\\cfg.%s.%s.dot", outDir
.c_str(), funcName
, fileName
);
499 sprintf(fName
, "cfg.%s.%s.dot", funcName
, fileName
);
503 raw_fd_ostream
fd_cfg(fName
, EC
, llvm::sys::fs::F_Text
);
504 WriteGraph(fd_cfg
, (const Function
*)f
);
511 bool g_DllActive
= true;
513 //////////////////////////////////////////////////////////////////////////
514 /// @brief Create JIT context.
515 /// @param simdWidth - SIMD width to be used in generated program.
516 HANDLE JITCALL
JitCreateContext(uint32_t targetSimdWidth
, const char* arch
, const char* core
)
518 return new JitManager(targetSimdWidth
, arch
, core
);
521 //////////////////////////////////////////////////////////////////////////
522 /// @brief Destroy JIT context.
523 void JITCALL
JitDestroyContext(HANDLE hJitContext
)
527 delete reinterpret_cast<JitManager
*>(hJitContext
);
532 //////////////////////////////////////////////////////////////////////////
534 //////////////////////////////////////////////////////////////////////////
536 //////////////////////////////////////////////////////////////////////////
537 /// JitCacheFileHeader
538 //////////////////////////////////////////////////////////////////////////
539 struct JitCacheFileHeader
541 void Init(uint32_t llCRC
,
543 const std::string
& moduleID
,
544 const std::string
& cpu
,
551 strncpy(m_ModuleID
, moduleID
.c_str(), JC_STR_MAX_LEN
- 1);
552 m_ModuleID
[JC_STR_MAX_LEN
- 1] = 0;
553 strncpy(m_Cpu
, cpu
.c_str(), JC_STR_MAX_LEN
- 1);
554 m_Cpu
[JC_STR_MAX_LEN
- 1] = 0;
555 m_optLevel
= optLevel
;
560 IsValid(uint32_t llCRC
, const std::string
& moduleID
, const std::string
& cpu
, uint32_t optLevel
)
562 if ((m_MagicNumber
!= JC_MAGIC_NUMBER
) || (m_llCRC
!= llCRC
) ||
563 (m_platformKey
!= JC_PLATFORM_KEY
) || (m_optLevel
!= optLevel
))
568 m_ModuleID
[JC_STR_MAX_LEN
- 1] = 0;
569 if (strncmp(moduleID
.c_str(), m_ModuleID
, JC_STR_MAX_LEN
- 1))
574 m_Cpu
[JC_STR_MAX_LEN
- 1] = 0;
575 if (strncmp(cpu
.c_str(), m_Cpu
, JC_STR_MAX_LEN
- 1))
583 uint64_t GetObjectSize() const { return m_objSize
; }
584 uint64_t GetObjectCRC() const { return m_objCRC
; }
587 static const uint64_t JC_MAGIC_NUMBER
= 0xfedcba9876543210ULL
+ 7;
588 static const size_t JC_STR_MAX_LEN
= 32;
589 static const uint32_t JC_PLATFORM_KEY
= (LLVM_VERSION_MAJOR
<< 24) |
590 (LLVM_VERSION_MINOR
<< 16) | (LLVM_VERSION_PATCH
<< 8) |
591 ((sizeof(void*) > sizeof(uint32_t)) ? 1 : 0);
593 uint64_t m_MagicNumber
= JC_MAGIC_NUMBER
;
594 uint64_t m_objSize
= 0;
595 uint32_t m_llCRC
= 0;
596 uint32_t m_platformKey
= JC_PLATFORM_KEY
;
597 uint32_t m_objCRC
= 0;
598 uint32_t m_optLevel
= 0;
599 char m_ModuleID
[JC_STR_MAX_LEN
] = {};
600 char m_Cpu
[JC_STR_MAX_LEN
] = {};
603 static inline uint32_t ComputeModuleCRC(const llvm::Module
* M
)
605 std::string bitcodeBuffer
;
606 raw_string_ostream
bitcodeStream(bitcodeBuffer
);
608 #if LLVM_VERSION_MAJOR >= 7
609 llvm::WriteBitcodeToFile(*M
, bitcodeStream
);
611 llvm::WriteBitcodeToFile(M
, bitcodeStream
);
613 // M->print(bitcodeStream, nullptr, false);
615 bitcodeStream
.flush();
617 return ComputeCRC(0, bitcodeBuffer
.data(), bitcodeBuffer
.size());
623 #if defined(__APPLE__) || defined(FORCE_LINUX) || defined(__linux__) || defined(__gnu_linux__)
624 if (strncmp(KNOB_JIT_CACHE_DIR
.c_str(), "~/", 2) == 0)
627 if (!(homedir
= getenv("HOME")))
629 homedir
= getpwuid(getuid())->pw_dir
;
632 mCacheDir
+= (KNOB_JIT_CACHE_DIR
.c_str() + 1);
637 mCacheDir
= KNOB_JIT_CACHE_DIR
;
640 // Create cache dir at startup to allow jitter to write debug.ll files
641 // to that directory.
642 if (!llvm::sys::fs::exists(mCacheDir
.str()) &&
643 llvm::sys::fs::create_directories(mCacheDir
.str()))
645 SWR_INVALID("Unable to create directory: %s", mCacheDir
.c_str());
650 int ExecUnhookedProcess(const std::string
& CmdLine
, std::string
* pStdOut
, std::string
* pStdErr
)
653 return ExecCmd(CmdLine
, nullptr, pStdOut
, pStdErr
);
656 /// Calculate actual directory where module will be cached.
657 /// This is always a subdirectory of mCacheDir. Full absolute
658 /// path name will be stored in mCurrentModuleCacheDir
659 void JitCache::CalcModuleCacheDir()
661 mModuleCacheDir
.clear();
663 llvm::SmallString
<MAX_PATH
> moduleDir
= mCacheDir
;
665 // Create 4 levels of directory hierarchy based on CRC, 256 entries each
666 uint8_t* pCRC
= (uint8_t*)&mCurrentModuleCRC
;
667 for (uint32_t i
= 0; i
< 4; ++i
)
669 llvm::sys::path::append(moduleDir
, std::to_string((int)pCRC
[i
]));
672 mModuleCacheDir
= moduleDir
;
675 /// notifyObjectCompiled - Provides a pointer to compiled code for Module M.
676 void JitCache::notifyObjectCompiled(const llvm::Module
* M
, llvm::MemoryBufferRef Obj
)
678 const std::string
& moduleID
= M
->getModuleIdentifier();
679 if (!moduleID
.length())
684 if (!mModuleCacheDir
.size())
686 SWR_INVALID("Unset module cache directory");
690 if (!llvm::sys::fs::exists(mModuleCacheDir
.str()) &&
691 llvm::sys::fs::create_directories(mModuleCacheDir
.str()))
693 SWR_INVALID("Unable to create directory: %s", mModuleCacheDir
.c_str());
697 JitCacheFileHeader header
;
699 llvm::SmallString
<MAX_PATH
> filePath
= mModuleCacheDir
;
700 llvm::sys::path::append(filePath
, moduleID
);
702 llvm::SmallString
<MAX_PATH
> objPath
= filePath
;
703 objPath
+= JIT_OBJ_EXT
;
707 llvm::raw_fd_ostream
fileObj(objPath
.c_str(), err
, llvm::sys::fs::F_None
);
708 fileObj
<< Obj
.getBuffer();
715 llvm::raw_fd_ostream
fileObj(filePath
.c_str(), err
, llvm::sys::fs::F_None
);
717 uint32_t objcrc
= ComputeCRC(0, Obj
.getBufferStart(), Obj
.getBufferSize());
719 header
.Init(mCurrentModuleCRC
, objcrc
, moduleID
, mCpu
, mOptLevel
, Obj
.getBufferSize());
721 fileObj
.write((const char*)&header
, sizeof(header
));
726 /// Returns a pointer to a newly allocated MemoryBuffer that contains the
727 /// object which corresponds with Module M, or 0 if an object is not
729 std::unique_ptr
<llvm::MemoryBuffer
> JitCache::getObject(const llvm::Module
* M
)
731 const std::string
& moduleID
= M
->getModuleIdentifier();
732 mCurrentModuleCRC
= ComputeModuleCRC(M
);
734 if (!moduleID
.length())
739 CalcModuleCacheDir();
741 if (!llvm::sys::fs::exists(mModuleCacheDir
))
746 llvm::SmallString
<MAX_PATH
> filePath
= mModuleCacheDir
;
747 llvm::sys::path::append(filePath
, moduleID
);
749 llvm::SmallString
<MAX_PATH
> objFilePath
= filePath
;
750 objFilePath
+= JIT_OBJ_EXT
;
752 FILE* fpObjIn
= nullptr;
753 FILE* fpIn
= fopen(filePath
.c_str(), "rb");
759 std::unique_ptr
<llvm::MemoryBuffer
> pBuf
= nullptr;
762 JitCacheFileHeader header
;
763 if (!fread(&header
, sizeof(header
), 1, fpIn
))
768 if (!header
.IsValid(mCurrentModuleCRC
, moduleID
, mCpu
, mOptLevel
))
773 fpObjIn
= fopen(objFilePath
.c_str(), "rb");
779 #if LLVM_VERSION_MAJOR < 6
780 pBuf
= llvm::MemoryBuffer::getNewUninitMemBuffer(size_t(header
.GetObjectSize()));
782 pBuf
= llvm::WritableMemoryBuffer::getNewUninitMemBuffer(size_t(header
.GetObjectSize()));
784 if (!fread(const_cast<char*>(pBuf
->getBufferStart()), header
.GetObjectSize(), 1, fpObjIn
))
790 if (header
.GetObjectCRC() != ComputeCRC(0, pBuf
->getBufferStart(), pBuf
->getBufferSize()))
792 SWR_TRACE("Invalid object cache file, ignoring: %s", filePath
.c_str());
810 void InterleaveAssemblyAnnotater::emitInstructionAnnot(const llvm::Instruction
* pInst
,
811 llvm::formatted_raw_ostream
& OS
)
813 auto dbgLoc
= pInst
->getDebugLoc();
816 unsigned int line
= dbgLoc
.getLine();
817 if (line
!= mCurrentLineNo
)
819 if (line
> 0 && line
<= mAssembly
.size())
821 // HACK: here we assume that OS is a formatted_raw_ostream(ods())
822 // and modify the color accordingly. We can't do the color
823 // modification on OS because formatted_raw_ostream strips
824 // the color information. The only way to fix this behavior
826 OS
<< "\n; " << line
<< ": " << mAssembly
[line
- 1] << "\n";
828 mCurrentLineNo
= line
;