7f9c9dd9d7babded5af9aa106633158a9100babf
[mesa.git] / src / gallium / drivers / swr / rasterizer / jitter / JitManager.cpp
1 /****************************************************************************
2 * Copyright (C) 2014-2015 Intel Corporation. All Rights Reserved.
3 *
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:
10 *
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
13 * Software.
14 *
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
21 * IN THE SOFTWARE.
22 *
23 * @file JitManager.cpp
24 *
25 * @brief Implementation if the Jit Manager.
26 *
27 * Notes:
28 *
29 ******************************************************************************/
30 #include "jit_pch.hpp"
31
32 #include "JitManager.h"
33 #include "jit_api.h"
34 #include "fetch_jit.h"
35
36 #include "core/state.h"
37
38 #include "gen_state_llvm.h"
39
40 #include <sstream>
41 #if defined(_WIN32)
42 #include <psapi.h>
43 #include <cstring>
44
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"
48 #endif // _WIN32
49
50 #if defined(__APPLE__) || defined(FORCE_LINUX) || defined(__linux__) || defined(__gnu_linux__)
51 #include <pwd.h>
52 #include <sys/stat.h>
53 #endif
54
55
56 using namespace llvm;
57 using namespace SwrJit;
58
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)
64 {
65 InitializeNativeTarget();
66 InitializeNativeTargetAsmPrinter();
67 InitializeNativeTargetDisassembler();
68
69
70 TargetOptions tOpts;
71 tOpts.AllowFPOpFusion = FPOpFusion::Fast;
72 tOpts.NoInfsFPMath = false;
73 tOpts.NoNaNsFPMath = false;
74 tOpts.UnsafeFPMath = false;
75
76 //tOpts.PrintMachineCode = true;
77
78 std::unique_ptr<Module> newModule(new Module("", mContext));
79 mpCurrentModule = newModule.get();
80
81 StringRef hostCPUName;
82
83 hostCPUName = sys::getHostCPUName();
84
85 #if defined(_WIN32)
86 // Needed for MCJIT on windows
87 Triple hostTriple(sys::getProcessTriple());
88 hostTriple.setObjectFormat(Triple::COFF);
89 mpCurrentModule->setTargetTriple(hostTriple.getTriple());
90 #endif // _WIN32
91
92 auto optLevel = CodeGenOpt::Aggressive;
93
94 if (KNOB_JIT_OPTIMIZATION_LEVEL >= CodeGenOpt::None &&
95 KNOB_JIT_OPTIMIZATION_LEVEL <= CodeGenOpt::Aggressive)
96 {
97 optLevel = CodeGenOpt::Level(KNOB_JIT_OPTIMIZATION_LEVEL);
98 }
99
100 mpExec = EngineBuilder(std::move(newModule))
101 .setTargetOptions(tOpts)
102 .setOptLevel(optLevel)
103 .setMCPU(hostCPUName)
104 .create();
105
106 if (KNOB_JIT_ENABLE_CACHE)
107 {
108 mCache.Init(this, hostCPUName, optLevel);
109 mpExec->setObjectCache(&mCache);
110 }
111
112 #if LLVM_USE_INTEL_JITEVENTS
113 JITEventListener *vTune = JITEventListener::createIntelJITEventListener();
114 mpExec->RegisterJITEventListener(vTune);
115 #endif
116
117 // fetch function signature
118 #if USE_SIMD16_SHADERS
119 // typedef void(__cdecl *PFN_FETCH_FUNC)(SWR_FETCH_CONTEXT& fetchInfo, simd16vertex& out);
120 #else
121 // typedef void(__cdecl *PFN_FETCH_FUNC)(SWR_FETCH_CONTEXT& fetchInfo, simdvertex& out);
122 #endif
123 std::vector<Type*> fsArgs;
124
125 // llvm5 is picky and does not take a void * type
126 fsArgs.push_back(PointerType::get(Gen_SWR_FETCH_CONTEXT(this), 0));
127
128 fsArgs.push_back(PointerType::get(Gen_SWR_FETCH_CONTEXT(this), 0));
129 #if USE_SIMD16_SHADERS
130 fsArgs.push_back(PointerType::get(Gen_simd16vertex(this), 0));
131 #else
132 fsArgs.push_back(PointerType::get(Gen_simdvertex(this), 0));
133 #endif
134
135 mFetchShaderTy = FunctionType::get(Type::getVoidTy(mContext), fsArgs, false);
136
137 #if defined(_WIN32)
138 // explicitly instantiate used symbols from potentially staticly linked libs
139 sys::DynamicLibrary::AddSymbol("exp2f", &exp2f);
140 sys::DynamicLibrary::AddSymbol("log2f", &log2f);
141 sys::DynamicLibrary::AddSymbol("sinf", &sinf);
142 sys::DynamicLibrary::AddSymbol("cosf", &cosf);
143 sys::DynamicLibrary::AddSymbol("powf", &powf);
144 #endif
145
146 #if defined(_WIN32)
147 if (KNOB_DUMP_SHADER_IR)
148 {
149 CreateDirectoryPath(INTEL_OUTPUT_DIR);
150 CreateDirectoryPath(SWR_OUTPUT_DIR);
151 CreateDirectoryPath(JITTER_OUTPUT_DIR);
152 }
153 #endif
154 }
155
156 //////////////////////////////////////////////////////////////////////////
157 /// @brief Create new LLVM module.
158 void JitManager::SetupNewModule()
159 {
160 SWR_ASSERT(mIsModuleFinalized == true && "Current module is not finalized!");
161
162 std::unique_ptr<Module> newModule(new Module("", mContext));
163 mpCurrentModule = newModule.get();
164 #if defined(_WIN32)
165 // Needed for MCJIT on windows
166 Triple hostTriple(sys::getProcessTriple());
167 hostTriple.setObjectFormat(Triple::COFF);
168 newModule->setTargetTriple(hostTriple.getTriple());
169 #endif // _WIN32
170
171 mpExec->addModule(std::move(newModule));
172 mIsModuleFinalized = false;
173 }
174
175
176 DIType* JitManager::CreateDebugStructType(StructType* pType, const std::string& name, DIFile* pFile, uint32_t lineNum,
177 const std::vector<std::pair<std::string, uint32_t>>& members)
178 {
179 DIBuilder builder(*mpCurrentModule);
180 SmallVector<Metadata*, 8> ElemTypes;
181 DataLayout DL = DataLayout(mpCurrentModule);
182 uint32_t size = DL.getTypeAllocSizeInBits(pType);
183 uint32_t alignment = DL.getABITypeAlignment(pType);
184 DINode::DIFlags flags = DINode::DIFlags::FlagPublic;
185
186 DICompositeType* pDIStructTy = builder.createStructType(pFile, name, pFile, lineNum, size, alignment,
187 flags, nullptr, builder.getOrCreateArray(ElemTypes));
188
189 // Register mapping now to break loops (in case struct contains itself or pointers to itself)
190 mDebugStructMap[pType] = pDIStructTy;
191
192 uint32_t idx = 0;
193 for (auto& elem : pType->elements())
194 {
195 std::string name = members[idx].first;
196 uint32_t lineNum = members[idx].second;
197 size = DL.getTypeAllocSizeInBits(elem);
198 alignment = DL.getABITypeAlignment(elem);
199 uint32_t offset = DL.getStructLayout(pType)->getElementOffsetInBits(idx);
200 llvm::DIType* pDebugTy = GetDebugType(elem);
201 ElemTypes.push_back(builder.createMemberType(pDIStructTy, name, pFile, lineNum, size, alignment, offset, flags, pDebugTy));
202
203 idx++;
204 }
205
206 pDIStructTy->replaceElements(builder.getOrCreateArray(ElemTypes));
207 return pDIStructTy;
208 }
209
210 DIType* JitManager::GetDebugArrayType(Type* pTy)
211 {
212 DIBuilder builder(*mpCurrentModule);
213 DataLayout DL = DataLayout(mpCurrentModule);
214 ArrayType* pArrayTy = cast<ArrayType>(pTy);
215 uint32_t size = DL.getTypeAllocSizeInBits(pArrayTy);
216 uint32_t alignment = DL.getABITypeAlignment(pArrayTy);
217
218 SmallVector<Metadata*, 8> Elems;
219 Elems.push_back(builder.getOrCreateSubrange(0, pArrayTy->getNumElements()));
220 return builder.createArrayType(size, alignment, GetDebugType(pArrayTy->getElementType()), builder.getOrCreateArray(Elems));
221 }
222
223 // Create a DIType from llvm Type
224 DIType* JitManager::GetDebugType(Type* pTy)
225 {
226 DIBuilder builder(*mpCurrentModule);
227 Type::TypeID id = pTy->getTypeID();
228
229 switch (id)
230 {
231 case Type::VoidTyID: return builder.createUnspecifiedType("void"); break;
232 case Type::HalfTyID: return builder.createBasicType("float16", 16, dwarf::DW_ATE_float); break;
233 case Type::FloatTyID: return builder.createBasicType("float", 32, dwarf::DW_ATE_float); break;
234 case Type::DoubleTyID: return builder.createBasicType("double", 64, dwarf::DW_ATE_float); break;
235 case Type::IntegerTyID: return GetDebugIntegerType(pTy); break;
236 case Type::StructTyID: return GetDebugStructType(pTy); break;
237 case Type::ArrayTyID: return GetDebugArrayType(pTy); break;
238 case Type::PointerTyID: return builder.createPointerType(GetDebugType(pTy->getPointerElementType()), 64, 64); break;
239 case Type::VectorTyID: return GetDebugVectorType(pTy); break;
240 case Type::FunctionTyID: return GetDebugFunctionType(pTy); break;
241 default: SWR_ASSERT(false, "Unimplemented llvm type");
242 }
243 return nullptr;
244 }
245
246 // Create a DISubroutineType from an llvm FunctionType
247 DIType* JitManager::GetDebugFunctionType(Type* pTy)
248 {
249 SmallVector<Metadata*, 8> ElemTypes;
250 FunctionType* pFuncTy = cast<FunctionType>(pTy);
251 DIBuilder builder(*mpCurrentModule);
252
253 // Add result type
254 ElemTypes.push_back(GetDebugType(pFuncTy->getReturnType()));
255
256 // Add arguments
257 for (auto& param : pFuncTy->params())
258 {
259 ElemTypes.push_back(GetDebugType(param));
260 }
261
262 return builder.createSubroutineType(builder.getOrCreateTypeArray(ElemTypes));
263 }
264
265 DIType* JitManager::GetDebugIntegerType(Type* pTy)
266 {
267 DIBuilder builder(*mpCurrentModule);
268 IntegerType* pIntTy = cast<IntegerType>(pTy);
269 switch (pIntTy->getBitWidth())
270 {
271 case 1: return builder.createBasicType("int1", 1, dwarf::DW_ATE_unsigned); break;
272 case 8: return builder.createBasicType("int8", 8, dwarf::DW_ATE_signed); break;
273 case 16: return builder.createBasicType("int16", 16, dwarf::DW_ATE_signed); break;
274 case 32: return builder.createBasicType("int", 32, dwarf::DW_ATE_signed); break;
275 case 64: return builder.createBasicType("int64", 64, dwarf::DW_ATE_signed); break;
276 case 128: return builder.createBasicType("int128", 128, dwarf::DW_ATE_signed); break;
277 default: SWR_ASSERT(false, "Unimplemented integer bit width");
278 }
279 return nullptr;
280 }
281
282 DIType* JitManager::GetDebugVectorType(Type* pTy)
283 {
284 DIBuilder builder(*mpCurrentModule);
285 VectorType* pVecTy = cast<VectorType>(pTy);
286 DataLayout DL = DataLayout(mpCurrentModule);
287 uint32_t size = DL.getTypeAllocSizeInBits(pVecTy);
288 uint32_t alignment = DL.getABITypeAlignment(pVecTy);
289 SmallVector<Metadata*, 1> Elems;
290 Elems.push_back(builder.getOrCreateSubrange(0, pVecTy->getVectorNumElements()));
291
292 return builder.createVectorType(size, alignment, GetDebugType(pVecTy->getVectorElementType()), builder.getOrCreateArray(Elems));
293
294 }
295
296 //////////////////////////////////////////////////////////////////////////
297 /// @brief Dump function x86 assembly to file.
298 /// @note This should only be called after the module has been jitted to x86 and the
299 /// module will not be further accessed.
300 void JitManager::DumpAsm(Function* pFunction, const char* fileName)
301 {
302 if (KNOB_DUMP_SHADER_IR)
303 {
304
305 #if defined(_WIN32)
306 DWORD pid = GetCurrentProcessId();
307 char procname[MAX_PATH];
308 GetModuleFileNameA(NULL, procname, MAX_PATH);
309 const char* pBaseName = strrchr(procname, '\\');
310 std::stringstream outDir;
311 outDir << JITTER_OUTPUT_DIR << pBaseName << "_" << pid << std::ends;
312 CreateDirectoryPath(outDir.str().c_str());
313 #endif
314
315 std::error_code EC;
316 Module* pModule = pFunction->getParent();
317 const char *funcName = pFunction->getName().data();
318 char fName[256];
319 #if defined(_WIN32)
320 sprintf(fName, "%s\\%s.%s.asm", outDir.str().c_str(), funcName, fileName);
321 #else
322 sprintf(fName, "%s.%s.asm", funcName, fileName);
323 #endif
324
325 raw_fd_ostream filestream(fName, EC, llvm::sys::fs::F_None);
326
327 legacy::PassManager* pMPasses = new legacy::PassManager();
328 auto* pTarget = mpExec->getTargetMachine();
329 pTarget->Options.MCOptions.AsmVerbose = true;
330 pTarget->addPassesToEmitFile(*pMPasses, filestream, TargetMachine::CGFT_AssemblyFile);
331 pMPasses->run(*pModule);
332 delete pMPasses;
333 pTarget->Options.MCOptions.AsmVerbose = false;
334 }
335 }
336
337 std::string JitManager::GetOutputDir()
338 {
339 #if defined(_WIN32)
340 DWORD pid = GetCurrentProcessId();
341 char procname[MAX_PATH];
342 GetModuleFileNameA(NULL, procname, MAX_PATH);
343 const char* pBaseName = strrchr(procname, '\\');
344 std::stringstream outDir;
345 outDir << JITTER_OUTPUT_DIR << pBaseName << "_" << pid;
346 CreateDirectoryPath(outDir.str().c_str());
347 return outDir.str();
348 #endif
349 return "";
350 }
351
352 //////////////////////////////////////////////////////////////////////////
353 /// @brief Dump function to file.
354 void JitManager::DumpToFile(Module *M, const char *fileName)
355 {
356 if (KNOB_DUMP_SHADER_IR)
357 {
358 std::string outDir = GetOutputDir();
359
360 std::error_code EC;
361 const char *funcName = M->getName().data();
362 char fName[256];
363 #if defined(_WIN32)
364 sprintf(fName, "%s\\%s.%s.ll", outDir.c_str(), funcName, fileName);
365 #else
366 sprintf(fName, "%s.%s.ll", funcName, fileName);
367 #endif
368 raw_fd_ostream fd(fName, EC, llvm::sys::fs::F_None);
369 M->print(fd, nullptr);
370 fd.flush();
371 }
372 }
373
374 //////////////////////////////////////////////////////////////////////////
375 /// @brief Dump function to file.
376 void JitManager::DumpToFile(Function *f, const char *fileName)
377 {
378 if (KNOB_DUMP_SHADER_IR)
379 {
380 std::string outDir = GetOutputDir();
381
382 std::error_code EC;
383 const char *funcName = f->getName().data();
384 char fName[256];
385 #if defined(_WIN32)
386 sprintf(fName, "%s\\%s.%s.ll", outDir.c_str(), funcName, fileName);
387 #else
388 sprintf(fName, "%s.%s.ll", funcName, fileName);
389 #endif
390 raw_fd_ostream fd(fName, EC, llvm::sys::fs::F_None);
391 f->print(fd, nullptr);
392
393 #if defined(_WIN32)
394 sprintf(fName, "%s\\cfg.%s.%s.dot", outDir.c_str(), funcName, fileName);
395 #else
396 sprintf(fName, "cfg.%s.%s.dot", funcName, fileName);
397 #endif
398 fd.flush();
399
400 raw_fd_ostream fd_cfg(fName, EC, llvm::sys::fs::F_Text);
401 WriteGraph(fd_cfg, (const Function*)f);
402
403 fd_cfg.flush();
404 }
405 }
406
407 extern "C"
408 {
409 bool g_DllActive = true;
410
411 //////////////////////////////////////////////////////////////////////////
412 /// @brief Create JIT context.
413 /// @param simdWidth - SIMD width to be used in generated program.
414 HANDLE JITCALL JitCreateContext(uint32_t targetSimdWidth, const char* arch, const char* core)
415 {
416 return new JitManager(targetSimdWidth, arch, core);
417 }
418
419 //////////////////////////////////////////////////////////////////////////
420 /// @brief Destroy JIT context.
421 void JITCALL JitDestroyContext(HANDLE hJitContext)
422 {
423 if (g_DllActive)
424 {
425 delete reinterpret_cast<JitManager*>(hJitContext);
426 }
427 }
428 }
429
430 //////////////////////////////////////////////////////////////////////////
431 /// JitCache
432 //////////////////////////////////////////////////////////////////////////
433
434 //////////////////////////////////////////////////////////////////////////
435 /// JitCacheFileHeader
436 //////////////////////////////////////////////////////////////////////////
437 struct JitCacheFileHeader
438 {
439 void Init(
440 uint32_t llCRC,
441 uint32_t objCRC,
442 const std::string& moduleID,
443 const std::string& cpu,
444 uint32_t optLevel,
445 uint64_t objSize)
446 {
447 m_objSize = objSize;
448 m_llCRC = llCRC;
449 m_objCRC = objCRC;
450 strncpy(m_ModuleID, moduleID.c_str(), JC_STR_MAX_LEN - 1);
451 m_ModuleID[JC_STR_MAX_LEN - 1] = 0;
452 strncpy(m_Cpu, cpu.c_str(), JC_STR_MAX_LEN - 1);
453 m_Cpu[JC_STR_MAX_LEN - 1] = 0;
454 m_optLevel = optLevel;
455 }
456
457
458 bool IsValid(uint32_t llCRC, const std::string& moduleID, const std::string& cpu, uint32_t optLevel)
459 {
460 if ((m_MagicNumber != JC_MAGIC_NUMBER) ||
461 (m_llCRC != llCRC) ||
462 (m_platformKey != JC_PLATFORM_KEY) ||
463 (m_optLevel != optLevel))
464 {
465 return false;
466 }
467
468 m_ModuleID[JC_STR_MAX_LEN - 1] = 0;
469 if (strncmp(moduleID.c_str(), m_ModuleID, JC_STR_MAX_LEN - 1))
470 {
471 return false;
472 }
473
474 m_Cpu[JC_STR_MAX_LEN - 1] = 0;
475 if (strncmp(cpu.c_str(), m_Cpu, JC_STR_MAX_LEN - 1))
476 {
477 return false;
478 }
479
480 return true;
481 }
482
483 uint64_t GetObjectSize() const { return m_objSize; }
484 uint64_t GetObjectCRC() const { return m_objCRC; }
485
486 private:
487 static const uint64_t JC_MAGIC_NUMBER = 0xfedcba9876543211ULL + 3;
488 static const size_t JC_STR_MAX_LEN = 32;
489 static const uint32_t JC_PLATFORM_KEY =
490 (LLVM_VERSION_MAJOR << 24) |
491 (LLVM_VERSION_MINOR << 16) |
492 (LLVM_VERSION_PATCH << 8) |
493 ((sizeof(void*) > sizeof(uint32_t)) ? 1 : 0);
494
495 uint64_t m_MagicNumber = JC_MAGIC_NUMBER;
496 uint64_t m_objSize = 0;
497 uint32_t m_llCRC = 0;
498 uint32_t m_platformKey = JC_PLATFORM_KEY;
499 uint32_t m_objCRC = 0;
500 uint32_t m_optLevel = 0;
501 char m_ModuleID[JC_STR_MAX_LEN] = {};
502 char m_Cpu[JC_STR_MAX_LEN] = {};
503 };
504
505 static inline uint32_t ComputeModuleCRC(const llvm::Module* M)
506 {
507 std::string bitcodeBuffer;
508 raw_string_ostream bitcodeStream(bitcodeBuffer);
509
510 llvm::WriteBitcodeToFile(M, bitcodeStream);
511 //M->print(bitcodeStream, nullptr, false);
512
513 bitcodeStream.flush();
514
515 return ComputeCRC(0, bitcodeBuffer.data(), bitcodeBuffer.size());
516 }
517
518 /// constructor
519 JitCache::JitCache()
520 {
521 #if defined(__APPLE__) || defined(FORCE_LINUX) || defined(__linux__) || defined(__gnu_linux__)
522 if (strncmp(KNOB_JIT_CACHE_DIR.c_str(), "~/", 2) == 0) {
523 char *homedir;
524 if (!(homedir = getenv("HOME"))) {
525 homedir = getpwuid(getuid())->pw_dir;
526 }
527 mCacheDir = homedir;
528 mCacheDir += (KNOB_JIT_CACHE_DIR.c_str() + 1);
529 } else
530 #endif
531 {
532 mCacheDir = KNOB_JIT_CACHE_DIR;
533 }
534 }
535
536 int ExecUnhookedProcess(const std::string& CmdLine, std::string* pStdOut, std::string* pStdErr)
537 {
538 static const char *g_pEnv = "RASTY_DISABLE_HOOK=1\0";
539
540 return ExecCmd(CmdLine, g_pEnv, pStdOut, pStdErr);
541 }
542
543
544 /// notifyObjectCompiled - Provides a pointer to compiled code for Module M.
545 void JitCache::notifyObjectCompiled(const llvm::Module *M, llvm::MemoryBufferRef Obj)
546 {
547 const std::string& moduleID = M->getModuleIdentifier();
548 if (!moduleID.length())
549 {
550 return;
551 }
552
553 if (!llvm::sys::fs::exists(mCacheDir.str()) &&
554 llvm::sys::fs::create_directories(mCacheDir.str()))
555 {
556 SWR_INVALID("Unable to create directory: %s", mCacheDir.c_str());
557 return;
558 }
559
560 JitCacheFileHeader header;
561
562 llvm::SmallString<MAX_PATH> filePath = mCacheDir;
563 llvm::sys::path::append(filePath, moduleID);
564
565 llvm::SmallString<MAX_PATH> objPath = filePath;
566 objPath += JIT_OBJ_EXT;
567
568 {
569 std::error_code err;
570 llvm::raw_fd_ostream fileObj(objPath.c_str(), err, llvm::sys::fs::F_None);
571 fileObj << Obj.getBuffer();
572 fileObj.flush();
573 }
574
575
576 {
577 std::error_code err;
578 llvm::raw_fd_ostream fileObj(filePath.c_str(), err, llvm::sys::fs::F_None);
579
580 uint32_t objcrc = ComputeCRC(0, Obj.getBufferStart(), Obj.getBufferSize());
581
582 header.Init(mCurrentModuleCRC, objcrc, moduleID, mCpu, mOptLevel, Obj.getBufferSize());
583
584 fileObj.write((const char*)&header, sizeof(header));
585 fileObj.flush();
586 }
587 }
588
589 /// Returns a pointer to a newly allocated MemoryBuffer that contains the
590 /// object which corresponds with Module M, or 0 if an object is not
591 /// available.
592 std::unique_ptr<llvm::MemoryBuffer> JitCache::getObject(const llvm::Module* M)
593 {
594 const std::string& moduleID = M->getModuleIdentifier();
595 mCurrentModuleCRC = ComputeModuleCRC(M);
596
597 if (!moduleID.length())
598 {
599 return nullptr;
600 }
601
602 if (!llvm::sys::fs::exists(mCacheDir))
603 {
604 return nullptr;
605 }
606
607 llvm::SmallString<MAX_PATH> filePath = mCacheDir;
608 llvm::sys::path::append(filePath, moduleID);
609
610 llvm::SmallString<MAX_PATH> objFilePath = filePath;
611 objFilePath += JIT_OBJ_EXT;
612
613 FILE* fpObjIn = nullptr;
614 FILE* fpIn = fopen(filePath.c_str(), "rb");
615 if (!fpIn)
616 {
617 return nullptr;
618 }
619
620 std::unique_ptr<llvm::MemoryBuffer> pBuf = nullptr;
621 do
622 {
623 JitCacheFileHeader header;
624 if (!fread(&header, sizeof(header), 1, fpIn))
625 {
626 break;
627 }
628
629 if (!header.IsValid(mCurrentModuleCRC, moduleID, mCpu, mOptLevel))
630 {
631 break;
632 }
633
634 fpObjIn = fopen(objFilePath.c_str(), "rb");
635 if (!fpObjIn)
636 {
637 break;
638 }
639
640 #if LLVM_VERSION_MAJOR < 6
641 pBuf = llvm::MemoryBuffer::getNewUninitMemBuffer(size_t(header.GetObjectSize()));
642 #else
643 pBuf = llvm::WritableMemoryBuffer::getNewUninitMemBuffer(size_t(header.GetObjectSize()));
644 #endif
645 if (!fread(const_cast<char*>(pBuf->getBufferStart()), header.GetObjectSize(), 1, fpObjIn))
646 {
647 pBuf = nullptr;
648 break;
649 }
650
651 if (header.GetObjectCRC() != ComputeCRC(0, pBuf->getBufferStart(), pBuf->getBufferSize()))
652 {
653 SWR_TRACE("Invalid object cache file, ignoring: %s", filePath.c_str());
654 pBuf = nullptr;
655 break;
656 }
657
658 }
659 while (0);
660
661 fclose(fpIn);
662
663 if (fpObjIn)
664 {
665 fclose(fpObjIn);
666 }
667
668
669 return pBuf;
670 }