1/****************************************************************************
2 * Copyright (C) 2014-2018 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
56using namespace llvm;
57using namespace SwrJit;
58
59//////////////////////////////////////////////////////////////////////////
60/// @brief Contructor for JitManager.
61/// @param simdWidth - SIMD width to be used in generated program.
62JitManager::JitManager(uint32_t simdWidth, const char* arch, const char* core) :
63    mContext(), mBuilder(mContext), mIsModuleFinalized(true), mJitNumber(0), mVWidth(simdWidth),
64    mArch(arch)
65{
66    mpCurrentModule = nullptr;
67    mpExec = nullptr;
68
69    InitializeNativeTarget();
70    InitializeNativeTargetAsmPrinter();
71    InitializeNativeTargetDisassembler();
72
73
74    // force JIT to use the same CPU arch as the rest of swr
75    if (mArch.AVX512F())
76    {
77#if USE_SIMD16_SHADERS
78        if (mArch.AVX512ER())
79        {
80            mHostCpuName = StringRef("knl");
81        }
82        else
83        {
84            mHostCpuName = StringRef("skylake-avx512");
85        }
86        mUsingAVX512 = true;
87#else
88        mHostCpuName = StringRef("core-avx2");
89#endif
90        if (mVWidth == 0)
91        {
92            mVWidth = 8;
93        }
94    }
95    else if (mArch.AVX2())
96    {
97        mHostCpuName = StringRef("core-avx2");
98        if (mVWidth == 0)
99        {
100            mVWidth = 8;
101        }
102    }
103    else if (mArch.AVX())
104    {
105        if (mArch.F16C())
106        {
107            mHostCpuName = StringRef("core-avx-i");
108        }
109        else
110        {
111            mHostCpuName = StringRef("corei7-avx");
112        }
113        if (mVWidth == 0)
114        {
115            mVWidth = 8;
116        }
117    }
118    else
119    {
120        SWR_INVALID("Jitting requires at least AVX ISA support");
121    }
122
123
124    mOptLevel = CodeGenOpt::Aggressive;
125
126    if (KNOB_JIT_OPTIMIZATION_LEVEL >= CodeGenOpt::None &&
127        KNOB_JIT_OPTIMIZATION_LEVEL <= CodeGenOpt::Aggressive)
128    {
129        mOptLevel = CodeGenOpt::Level(KNOB_JIT_OPTIMIZATION_LEVEL);
130    }
131
132    if (KNOB_JIT_ENABLE_CACHE)
133    {
134        mCache.Init(this, mHostCpuName, mOptLevel);
135    }
136
137    SetupNewModule();
138    mIsModuleFinalized = true;
139
140    // fetch function signature
141#if USE_SIMD16_SHADERS
142    // typedef void(__cdecl *PFN_FETCH_FUNC)(SWR_FETCH_CONTEXT& fetchInfo, simd16vertex& out);
143#else
144    // typedef void(__cdecl *PFN_FETCH_FUNC)(SWR_FETCH_CONTEXT& fetchInfo, simdvertex& out);
145#endif
146    std::vector<Type*> fsArgs;
147
148    // llvm5 is picky and does not take a void * type
149    fsArgs.push_back(PointerType::get(Gen_SWR_FETCH_CONTEXT(this), 0));
150
151    fsArgs.push_back(Type::getInt8PtrTy(mContext));
152
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));
156#else
157    fsArgs.push_back(PointerType::get(Gen_simdvertex(this), 0));
158#endif
159
160    mFetchShaderTy = FunctionType::get(Type::getVoidTy(mContext), fsArgs, false);
161
162#if defined(_WIN32)
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);
169#endif
170
171#if defined(_WIN32)
172    if (KNOB_DUMP_SHADER_IR)
173    {
174        CreateDirectoryPath(INTEL_OUTPUT_DIR);
175        CreateDirectoryPath(SWR_OUTPUT_DIR);
176        CreateDirectoryPath(JITTER_OUTPUT_DIR);
177    }
178#endif
179}
180
181void JitManager::CreateExecEngine(std::unique_ptr<Module> pModule)
182{
183    TargetOptions tOpts;
184    tOpts.AllowFPOpFusion = FPOpFusion::Fast;
185    tOpts.NoInfsFPMath    = false;
186    tOpts.NoNaNsFPMath    = false;
187    tOpts.UnsafeFPMath = false;
188
189    // tOpts.PrintMachineCode    = true;
190
191    mpExec = EngineBuilder(std::move(pModule))
192                 .setTargetOptions(tOpts)
193                 .setOptLevel(mOptLevel)
194                 .setMCPU(mHostCpuName)
195                 .create();
196
197    if (KNOB_JIT_ENABLE_CACHE)
198    {
199        mpExec->setObjectCache(&mCache);
200    }
201
202#if LLVM_USE_INTEL_JITEVENTS
203    JITEventListener* vTune = JITEventListener::createIntelJITEventListener();
204    mpExec->RegisterJITEventListener(vTune);
205#endif
206
207    mvExecEngines.push_back(mpExec);
208}
209
210//////////////////////////////////////////////////////////////////////////
211/// @brief Create new LLVM module.
212void JitManager::SetupNewModule()
213{
214    SWR_ASSERT(mIsModuleFinalized == true && "Current module is not finalized!");
215
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;
221}
222
223
224DIType*
225JitManager::CreateDebugStructType(StructType*                                          pType,
226                                  const std::string&                                   name,
227                                  DIFile*                                              pFile,
228                                  uint32_t                                             lineNum,
229                                  const std::vector<std::pair<std::string, uint32_t>>& members)
230{
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;
237
238    DICompositeType* pDIStructTy = builder.createStructType(pFile,
239                                                            name,
240                                                            pFile,
241                                                            lineNum,
242                                                            size,
243                                                            alignment,
244                                                            flags,
245                                                            nullptr,
246                                                            builder.getOrCreateArray(ElemTypes));
247
248    // Register mapping now to break loops (in case struct contains itself or pointers to itself)
249    mDebugStructMap[pType] = pDIStructTy;
250
251    uint32_t idx = 0;
252    for (auto& elem : pType->elements())
253    {
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));
262
263        idx++;
264    }
265
266    pDIStructTy->replaceElements(builder.getOrCreateArray(ElemTypes));
267    return pDIStructTy;
268}
269
270DIType* JitManager::GetDebugArrayType(Type* pTy)
271{
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);
277
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));
282}
283
284// Create a DIType from llvm Type
285DIType* JitManager::GetDebugType(Type* pTy)
286{
287    DIBuilder    builder(*mpCurrentModule);
288    Type::TypeID id = pTy->getTypeID();
289
290    switch (id)
291    {
292    case Type::VoidTyID:
293        return builder.createUnspecifiedType("void");
294        break;
295    case Type::HalfTyID:
296        return builder.createBasicType("float16", 16, dwarf::DW_ATE_float);
297        break;
298    case Type::FloatTyID:
299        return builder.createBasicType("float", 32, dwarf::DW_ATE_float);
300        break;
301    case Type::DoubleTyID:
302        return builder.createBasicType("double", 64, dwarf::DW_ATE_float);
303        break;
304    case Type::IntegerTyID:
305        return GetDebugIntegerType(pTy);
306        break;
307    case Type::StructTyID:
308        return GetDebugStructType(pTy);
309        break;
310    case Type::ArrayTyID:
311        return GetDebugArrayType(pTy);
312        break;
313    case Type::PointerTyID:
314        return builder.createPointerType(GetDebugType(pTy->getPointerElementType()), 64, 64);
315        break;
316    case Type::VectorTyID:
317        return GetDebugVectorType(pTy);
318        break;
319    case Type::FunctionTyID:
320        return GetDebugFunctionType(pTy);
321        break;
322    default:
323        SWR_ASSERT(false, "Unimplemented llvm type");
324    }
325    return nullptr;
326}
327
328// Create a DISubroutineType from an llvm FunctionType
329DIType* JitManager::GetDebugFunctionType(Type* pTy)
330{
331    SmallVector<Metadata*, 8> ElemTypes;
332    FunctionType*             pFuncTy = cast<FunctionType>(pTy);
333    DIBuilder                 builder(*mpCurrentModule);
334
335    // Add result type
336    ElemTypes.push_back(GetDebugType(pFuncTy->getReturnType()));
337
338    // Add arguments
339    for (auto& param : pFuncTy->params())
340    {
341        ElemTypes.push_back(GetDebugType(param));
342    }
343
344    return builder.createSubroutineType(builder.getOrCreateTypeArray(ElemTypes));
345}
346
347DIType* JitManager::GetDebugIntegerType(Type* pTy)
348{
349    DIBuilder    builder(*mpCurrentModule);
350    IntegerType* pIntTy = cast<IntegerType>(pTy);
351    switch (pIntTy->getBitWidth())
352    {
353    case 1:
354        return builder.createBasicType("int1", 1, dwarf::DW_ATE_unsigned);
355        break;
356    case 8:
357        return builder.createBasicType("int8", 8, dwarf::DW_ATE_signed);
358        break;
359    case 16:
360        return builder.createBasicType("int16", 16, dwarf::DW_ATE_signed);
361        break;
362    case 32:
363        return builder.createBasicType("int", 32, dwarf::DW_ATE_signed);
364        break;
365    case 64:
366        return builder.createBasicType("int64", 64, dwarf::DW_ATE_signed);
367        break;
368    case 128:
369        return builder.createBasicType("int128", 128, dwarf::DW_ATE_signed);
370        break;
371    default:
372        SWR_ASSERT(false, "Unimplemented integer bit width");
373    }
374    return nullptr;
375}
376
377DIType* JitManager::GetDebugVectorType(Type* pTy)
378{
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()));
386
387    return builder.createVectorType(size,
388                                    alignment,
389                                    GetDebugType(pVecTy->getVectorElementType()),
390                                    builder.getOrCreateArray(Elems));
391}
392
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.
397void JitManager::DumpAsm(Function* pFunction, const char* fileName)
398{
399    if (KNOB_DUMP_SHADER_IR)
400    {
401#if defined(_WIN32)
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());
409#endif
410
411        std::error_code EC;
412        Module*         pModule  = pFunction->getParent();
413        const char*     funcName = pFunction->getName().data();
414        char            fName[256];
415#if defined(_WIN32)
416        sprintf(fName, "%s\\%s.%s.asm", outDir.str().c_str(), funcName, fileName);
417#else
418        sprintf(fName, "%s.%s.asm", funcName, fileName);
419#endif
420
421        raw_fd_ostream filestream(fName, EC, llvm::sys::fs::F_None);
422
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);
429#else
430        pTarget->addPassesToEmitFile(*pMPasses, filestream, TargetMachine::CGFT_AssemblyFile);
431#endif
432        pMPasses->run(*pModule);
433        delete pMPasses;
434        pTarget->Options.MCOptions.AsmVerbose = false;
435    }
436}
437
438std::string JitManager::GetOutputDir()
439{
440#if defined(_WIN32)
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());
448    return outDir.str();
449#endif
450    return "";
451}
452
453//////////////////////////////////////////////////////////////////////////
454/// @brief Dump function to file.
455void JitManager::DumpToFile(Module* M, const char* fileName, llvm::AssemblyAnnotationWriter* annotater)
456{
457    if (KNOB_DUMP_SHADER_IR)
458    {
459        std::string outDir = GetOutputDir();
460
461        std::error_code EC;
462        const char*     funcName = M->getName().data();
463        char            fName[256];
464#if defined(_WIN32)
465        sprintf(fName, "%s\\%s.%s.ll", outDir.c_str(), funcName, fileName);
466#else
467        sprintf(fName, "%s.%s.ll", funcName, fileName);
468#endif
469        raw_fd_ostream fd(fName, EC, llvm::sys::fs::F_None);
470        M->print(fd, annotater);
471        fd.flush();
472    }
473}
474
475//////////////////////////////////////////////////////////////////////////
476/// @brief Dump function to file.
477void JitManager::DumpToFile(Function* f, const char* fileName)
478{
479    if (KNOB_DUMP_SHADER_IR)
480    {
481        std::string outDir = GetOutputDir();
482
483        std::error_code EC;
484        const char*     funcName = f->getName().data();
485        char            fName[256];
486#if defined(_WIN32)
487        sprintf(fName, "%s\\%s.%s.ll", outDir.c_str(), funcName, fileName);
488#else
489        sprintf(fName, "%s.%s.ll", funcName, fileName);
490#endif
491        raw_fd_ostream fd(fName, EC, llvm::sys::fs::F_None);
492        f->print(fd, nullptr);
493
494#if defined(_WIN32)
495        sprintf(fName, "%s\\cfg.%s.%s.dot", outDir.c_str(), funcName, fileName);
496#else
497        sprintf(fName, "cfg.%s.%s.dot", funcName, fileName);
498#endif
499        fd.flush();
500
501        raw_fd_ostream fd_cfg(fName, EC, llvm::sys::fs::F_Text);
502        WriteGraph(fd_cfg, (const Function*)f);
503
504        fd_cfg.flush();
505    }
506}
507
508extern "C" {
509bool g_DllActive = true;
510
511//////////////////////////////////////////////////////////////////////////
512/// @brief Create JIT context.
513/// @param simdWidth - SIMD width to be used in generated program.
514HANDLE JITCALL JitCreateContext(uint32_t targetSimdWidth, const char* arch, const char* core)
515{
516    return new JitManager(targetSimdWidth, arch, core);
517}
518
519//////////////////////////////////////////////////////////////////////////
520/// @brief Destroy JIT context.
521void JITCALL JitDestroyContext(HANDLE hJitContext)
522{
523    if (g_DllActive)
524    {
525        delete reinterpret_cast<JitManager*>(hJitContext);
526    }
527}
528}
529
530//////////////////////////////////////////////////////////////////////////
531/// JitCache
532//////////////////////////////////////////////////////////////////////////
533
534//////////////////////////////////////////////////////////////////////////
535/// JitCacheFileHeader
536//////////////////////////////////////////////////////////////////////////
537struct JitCacheFileHeader
538{
539    void Init(uint32_t           llCRC,
540              uint32_t           objCRC,
541              const std::string& moduleID,
542              const std::string& cpu,
543              uint32_t           optLevel,
544              uint64_t           objSize)
545    {
546        m_objSize = objSize;
547        m_llCRC   = llCRC;
548        m_objCRC  = objCRC;
549        strncpy(m_ModuleID, moduleID.c_str(), JC_STR_MAX_LEN - 1);
550        m_ModuleID[JC_STR_MAX_LEN - 1] = 0;
551        strncpy(m_Cpu, cpu.c_str(), JC_STR_MAX_LEN - 1);
552        m_Cpu[JC_STR_MAX_LEN - 1] = 0;
553        m_optLevel                = optLevel;
554    }
555
556
557    bool
558    IsValid(uint32_t llCRC, const std::string& moduleID, const std::string& cpu, uint32_t optLevel)
559    {
560        if ((m_MagicNumber != JC_MAGIC_NUMBER) || (m_llCRC != llCRC) ||
561            (m_platformKey != JC_PLATFORM_KEY) || (m_optLevel != optLevel))
562        {
563            return false;
564        }
565
566        m_ModuleID[JC_STR_MAX_LEN - 1] = 0;
567        if (strncmp(moduleID.c_str(), m_ModuleID, JC_STR_MAX_LEN - 1))
568        {
569            return false;
570        }
571
572        m_Cpu[JC_STR_MAX_LEN - 1] = 0;
573        if (strncmp(cpu.c_str(), m_Cpu, JC_STR_MAX_LEN - 1))
574        {
575            return false;
576        }
577
578        return true;
579    }
580
581    uint64_t GetObjectSize() const { return m_objSize; }
582    uint64_t GetObjectCRC() const { return m_objCRC; }
583
584private:
585    static const uint64_t JC_MAGIC_NUMBER = 0xfedcba9876543210ULL + 6;
586    static const size_t   JC_STR_MAX_LEN  = 32;
587    static const uint32_t JC_PLATFORM_KEY = (LLVM_VERSION_MAJOR << 24) |
588                                            (LLVM_VERSION_MINOR << 16) | (LLVM_VERSION_PATCH << 8) |
589                                            ((sizeof(void*) > sizeof(uint32_t)) ? 1 : 0);
590
591    uint64_t m_MagicNumber              = JC_MAGIC_NUMBER;
592    uint64_t m_objSize                  = 0;
593    uint32_t m_llCRC                    = 0;
594    uint32_t m_platformKey              = JC_PLATFORM_KEY;
595    uint32_t m_objCRC                   = 0;
596    uint32_t m_optLevel                 = 0;
597    char     m_ModuleID[JC_STR_MAX_LEN] = {};
598    char     m_Cpu[JC_STR_MAX_LEN]      = {};
599};
600
601static inline uint32_t ComputeModuleCRC(const llvm::Module* M)
602{
603    std::string        bitcodeBuffer;
604    raw_string_ostream bitcodeStream(bitcodeBuffer);
605
606#if LLVM_VERSION_MAJOR >= 7
607    llvm::WriteBitcodeToFile(*M, bitcodeStream);
608#else
609    llvm::WriteBitcodeToFile(M, bitcodeStream);
610#endif
611    // M->print(bitcodeStream, nullptr, false);
612
613    bitcodeStream.flush();
614
615    return ComputeCRC(0, bitcodeBuffer.data(), bitcodeBuffer.size());
616}
617
618/// constructor
619JitCache::JitCache()
620{
621#if defined(__APPLE__) || defined(FORCE_LINUX) || defined(__linux__) || defined(__gnu_linux__)
622    if (strncmp(KNOB_JIT_CACHE_DIR.c_str(), "~/", 2) == 0)
623    {
624        char* homedir;
625        if (!(homedir = getenv("HOME")))
626        {
627            homedir = getpwuid(getuid())->pw_dir;
628        }
629        mCacheDir = homedir;
630        mCacheDir += (KNOB_JIT_CACHE_DIR.c_str() + 1);
631    }
632    else
633#endif
634    {
635        mCacheDir = KNOB_JIT_CACHE_DIR;
636    }
637
638    // Create cache dir at startup to allow jitter to write debug.ll files
639    // to that directory.
640    if (!llvm::sys::fs::exists(mCacheDir.str()) &&
641        llvm::sys::fs::create_directories(mCacheDir.str()))
642    {
643        SWR_INVALID("Unable to create directory: %s", mCacheDir.c_str());
644    }
645
646}
647
648int ExecUnhookedProcess(const std::string& CmdLine, std::string* pStdOut, std::string* pStdErr)
649{
650    return ExecCmd(CmdLine, "", pStdOut, pStdErr);
651}
652
653/// Calculate actual directory where module will be cached.
654/// This is always a subdirectory of mCacheDir.  Full absolute
655/// path name will be stored in mCurrentModuleCacheDir
656void JitCache::CalcModuleCacheDir()
657{
658    mModuleCacheDir.clear();
659
660    llvm::SmallString<MAX_PATH> moduleDir = mCacheDir;
661
662    // Create 4 levels of directory hierarchy based on CRC, 256 entries each
663    uint8_t* pCRC = (uint8_t*)&mCurrentModuleCRC;
664    for (uint32_t i = 0; i < 4; ++i)
665    {
666        llvm::sys::path::append(moduleDir, std::to_string((int)pCRC[i]));
667    }
668
669    mModuleCacheDir = moduleDir;
670}
671
672
673/// notifyObjectCompiled - Provides a pointer to compiled code for Module M.
674void JitCache::notifyObjectCompiled(const llvm::Module* M, llvm::MemoryBufferRef Obj)
675{
676    const std::string& moduleID = M->getModuleIdentifier();
677    if (!moduleID.length())
678    {
679        return;
680    }
681
682    if (!mModuleCacheDir.size())
683    {
684        SWR_INVALID("Unset module cache directory");
685        return;
686    }
687
688    if (!llvm::sys::fs::exists(mModuleCacheDir.str()) &&
689        llvm::sys::fs::create_directories(mModuleCacheDir.str()))
690    {
691        SWR_INVALID("Unable to create directory: %s", mModuleCacheDir.c_str());
692        return;
693    }
694
695    JitCacheFileHeader header;
696
697    llvm::SmallString<MAX_PATH> filePath = mModuleCacheDir;
698    llvm::sys::path::append(filePath, moduleID);
699
700    llvm::SmallString<MAX_PATH> objPath = filePath;
701    objPath += JIT_OBJ_EXT;
702
703    {
704        std::error_code      err;
705        llvm::raw_fd_ostream fileObj(objPath.c_str(), err, llvm::sys::fs::F_None);
706        fileObj << Obj.getBuffer();
707        fileObj.flush();
708    }
709
710
711    {
712        std::error_code      err;
713        llvm::raw_fd_ostream fileObj(filePath.c_str(), err, llvm::sys::fs::F_None);
714
715        uint32_t objcrc = ComputeCRC(0, Obj.getBufferStart(), Obj.getBufferSize());
716
717        header.Init(mCurrentModuleCRC, objcrc, moduleID, mCpu, mOptLevel, Obj.getBufferSize());
718
719        fileObj.write((const char*)&header, sizeof(header));
720        fileObj.flush();
721    }
722}
723
724/// Returns a pointer to a newly allocated MemoryBuffer that contains the
725/// object which corresponds with Module M, or 0 if an object is not
726/// available.
727std::unique_ptr<llvm::MemoryBuffer> JitCache::getObject(const llvm::Module* M)
728{
729    const std::string& moduleID = M->getModuleIdentifier();
730    mCurrentModuleCRC           = ComputeModuleCRC(M);
731
732    if (!moduleID.length())
733    {
734        return nullptr;
735    }
736
737    CalcModuleCacheDir();
738
739    if (!llvm::sys::fs::exists(mModuleCacheDir))
740    {
741        return nullptr;
742    }
743
744    llvm::SmallString<MAX_PATH> filePath = mModuleCacheDir;
745    llvm::sys::path::append(filePath, moduleID);
746
747    llvm::SmallString<MAX_PATH> objFilePath = filePath;
748    objFilePath += JIT_OBJ_EXT;
749
750    FILE* fpObjIn = nullptr;
751    FILE* fpIn    = fopen(filePath.c_str(), "rb");
752    if (!fpIn)
753    {
754        return nullptr;
755    }
756
757    std::unique_ptr<llvm::MemoryBuffer> pBuf = nullptr;
758    do
759    {
760        JitCacheFileHeader header;
761        if (!fread(&header, sizeof(header), 1, fpIn))
762        {
763            break;
764        }
765
766        if (!header.IsValid(mCurrentModuleCRC, moduleID, mCpu, mOptLevel))
767        {
768            break;
769        }
770
771        fpObjIn = fopen(objFilePath.c_str(), "rb");
772        if (!fpObjIn)
773        {
774            break;
775        }
776
777#if LLVM_VERSION_MAJOR < 6
778        pBuf = llvm::MemoryBuffer::getNewUninitMemBuffer(size_t(header.GetObjectSize()));
779#else
780        pBuf = llvm::WritableMemoryBuffer::getNewUninitMemBuffer(size_t(header.GetObjectSize()));
781#endif
782        if (!fread(const_cast<char*>(pBuf->getBufferStart()), header.GetObjectSize(), 1, fpObjIn))
783        {
784            pBuf = nullptr;
785            break;
786        }
787
788        if (header.GetObjectCRC() != ComputeCRC(0, pBuf->getBufferStart(), pBuf->getBufferSize()))
789        {
790            SWR_TRACE("Invalid object cache file, ignoring: %s", filePath.c_str());
791            pBuf = nullptr;
792            break;
793        }
794
795    } while (0);
796
797    fclose(fpIn);
798
799    if (fpObjIn)
800    {
801        fclose(fpObjIn);
802    }
803
804
805    return pBuf;
806}
807
808void InterleaveAssemblyAnnotater::emitInstructionAnnot(const llvm::Instruction *pInst, llvm::formatted_raw_ostream &OS)
809{
810    auto dbgLoc = pInst->getDebugLoc();
811    if(dbgLoc)
812    {
813        unsigned int line = dbgLoc.getLine();
814        if(line != mCurrentLineNo)
815        {
816            if(line > 0 && line <= mAssembly.size())
817            {
818                // HACK: here we assume that OS is a formatted_raw_ostream(ods())
819                // and modify the color accordingly. We can't do the color
820                // modification on OS because formatted_raw_ostream strips
821                // the color information. The only way to fix this behavior
822                // is to patch LLVM.
823                OS << "\n; " << line << ": " << mAssembly[line-1] << "\n";
824            }
825            mCurrentLineNo = line;
826        }
827    }
828}
829
830