+ if (g_DllActive)
+ {
+ delete reinterpret_cast<JitManager*>(hJitContext);
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+/// JitCache
+//////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////
+/// JitCacheFileHeader
+//////////////////////////////////////////////////////////////////////////
+struct JitCacheFileHeader
+{
+ void Init(
+ uint32_t llCRC,
+ uint32_t objCRC,
+ const std::string& moduleID,
+ const std::string& cpu,
+ uint32_t optLevel,
+ uint64_t objSize)
+ {
+ m_objSize = objSize;
+ m_llCRC = llCRC;
+ m_objCRC = objCRC;
+ strncpy(m_ModuleID, moduleID.c_str(), JC_STR_MAX_LEN - 1);
+ m_ModuleID[JC_STR_MAX_LEN - 1] = 0;
+ strncpy(m_Cpu, cpu.c_str(), JC_STR_MAX_LEN - 1);
+ m_Cpu[JC_STR_MAX_LEN - 1] = 0;
+ m_optLevel = optLevel;
+ }
+
+
+ bool IsValid(uint32_t llCRC, const std::string& moduleID, const std::string& cpu, uint32_t optLevel)
+ {
+ if ((m_MagicNumber != JC_MAGIC_NUMBER) ||
+ (m_llCRC != llCRC) ||
+ (m_platformKey != JC_PLATFORM_KEY) ||
+ (m_optLevel != optLevel))
+ {
+ return false;
+ }
+
+ m_ModuleID[JC_STR_MAX_LEN - 1] = 0;
+ if (strncmp(moduleID.c_str(), m_ModuleID, JC_STR_MAX_LEN - 1))
+ {
+ return false;
+ }
+
+ m_Cpu[JC_STR_MAX_LEN - 1] = 0;
+ if (strncmp(cpu.c_str(), m_Cpu, JC_STR_MAX_LEN - 1))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ uint64_t GetObjectSize() const { return m_objSize; }
+ uint64_t GetObjectCRC() const { return m_objCRC; }
+
+private:
+ static const uint64_t JC_MAGIC_NUMBER = 0xfedcba9876543211ULL + 3;
+ static const size_t JC_STR_MAX_LEN = 32;
+ static const uint32_t JC_PLATFORM_KEY =
+ (LLVM_VERSION_MAJOR << 24) |
+ (LLVM_VERSION_MINOR << 16) |
+ (LLVM_VERSION_PATCH << 8) |
+ ((sizeof(void*) > sizeof(uint32_t)) ? 1 : 0);
+
+ uint64_t m_MagicNumber = JC_MAGIC_NUMBER;
+ uint64_t m_objSize = 0;
+ uint32_t m_llCRC = 0;
+ uint32_t m_platformKey = JC_PLATFORM_KEY;
+ uint32_t m_objCRC = 0;
+ uint32_t m_optLevel = 0;
+ char m_ModuleID[JC_STR_MAX_LEN] = {};
+ char m_Cpu[JC_STR_MAX_LEN] = {};
+};
+
+static inline uint32_t ComputeModuleCRC(const llvm::Module* M)
+{
+ std::string bitcodeBuffer;
+ raw_string_ostream bitcodeStream(bitcodeBuffer);
+
+ llvm::WriteBitcodeToFile(M, bitcodeStream);
+ //M->print(bitcodeStream, nullptr, false);
+
+ bitcodeStream.flush();
+
+ return ComputeCRC(0, bitcodeBuffer.data(), bitcodeBuffer.size());
+}
+
+/// constructor
+JitCache::JitCache()
+{
+#if defined(__APPLE__) || defined(FORCE_LINUX) || defined(__linux__) || defined(__gnu_linux__)
+ if (strncmp(KNOB_JIT_CACHE_DIR.c_str(), "~/", 2) == 0) {
+ char *homedir;
+ if (!(homedir = getenv("HOME"))) {
+ homedir = getpwuid(getuid())->pw_dir;
+ }
+ mCacheDir = homedir;
+ mCacheDir += (KNOB_JIT_CACHE_DIR.c_str() + 1);
+ } else
+#endif
+ {
+ mCacheDir = KNOB_JIT_CACHE_DIR;
+ }
+}
+
+int ExecUnhookedProcess(const std::string& CmdLine, std::string* pStdOut, std::string* pStdErr)
+{
+ static const char *g_pEnv = "RASTY_DISABLE_HOOK=1\0";
+
+ return ExecCmd(CmdLine, g_pEnv, pStdOut, pStdErr);
+}
+
+
+/// notifyObjectCompiled - Provides a pointer to compiled code for Module M.
+void JitCache::notifyObjectCompiled(const llvm::Module *M, llvm::MemoryBufferRef Obj)
+{
+ const std::string& moduleID = M->getModuleIdentifier();
+ if (!moduleID.length())
+ {
+ return;
+ }
+
+ if (!llvm::sys::fs::exists(mCacheDir.str()) &&
+ llvm::sys::fs::create_directories(mCacheDir.str()))
+ {
+ SWR_INVALID("Unable to create directory: %s", mCacheDir.c_str());
+ return;
+ }
+
+ JitCacheFileHeader header;
+
+ llvm::SmallString<MAX_PATH> filePath = mCacheDir;
+ llvm::sys::path::append(filePath, moduleID);
+
+ llvm::SmallString<MAX_PATH> objPath = filePath;
+ objPath += JIT_OBJ_EXT;
+
+ {
+ std::error_code err;
+ llvm::raw_fd_ostream fileObj(objPath.c_str(), err, llvm::sys::fs::F_None);
+ fileObj << Obj.getBuffer();
+ fileObj.flush();
+ }
+
+
+ {
+ std::error_code err;
+ llvm::raw_fd_ostream fileObj(filePath.c_str(), err, llvm::sys::fs::F_None);
+
+ uint32_t objcrc = ComputeCRC(0, Obj.getBufferStart(), Obj.getBufferSize());
+
+ header.Init(mCurrentModuleCRC, objcrc, moduleID, mCpu, mOptLevel, Obj.getBufferSize());
+
+ fileObj.write((const char*)&header, sizeof(header));
+ fileObj.flush();