void Cache::preload(llvm::ExecutionEngine& _ee, std::unordered_map<std::string, uint64_t>& _funcCache) { Guard g{x_cacheMutex}; // Disable listener auto listener = g_listener; g_listener = nullptr; auto cachePath = getVersionedCacheDir(); std::error_code err; for (auto it = llvm::sys::fs::directory_iterator{cachePath, err}; it != decltype(it){}; it.increment(err)) { auto name = it->path().substr(cachePath.size() + 1); if (auto module = getObject(name)) { DLOG(cache) << "Preload: " << name << "\n"; _ee.addModule(std::move(module)); auto addr = _ee.getFunctionAddress(name); assert(addr); _funcCache[std::move(name)] = addr; } } g_listener = listener; }
void JITtedFunctionCollector::UnregisterFunctionMapping(llvm::ExecutionEngine &engine) { std::vector<llvm::Function *>::reverse_iterator it; for (it=m_vec_functions.rbegin(); it < m_vec_functions.rend(); it++) { llvm::Function *ff = (llvm::Function *)*it; //BB std::cerr << "JITtedFunctionCollector::UnregisterFunctionMapping: updateGlobalMapping(" //BB << ff->getName().data() << ", 0); Global @" << engine.getPointerToGlobalIfAvailable(ff) << std::endl; engine.freeMachineCodeForFunction(ff); engine.updateGlobalMapping(ff, 0); //BB std::cerr << "Global after delete @" << engine.getPointerToGlobalIfAvailable(ff) << std::endl; } m_vec_functions.clear(); }
bool ExternalDispatcherImpl::runProtectedCall(Function *f, uint64_t *args) { struct sigaction segvAction, segvActionOld; bool res; if (!f) return false; std::vector<GenericValue> gvArgs; gTheArgsP = args; segvAction.sa_handler = 0; memset(&segvAction.sa_mask, 0, sizeof(segvAction.sa_mask)); segvAction.sa_flags = SA_SIGINFO; segvAction.sa_sigaction = ::sigsegv_handler; sigaction(SIGSEGV, &segvAction, &segvActionOld); if (setjmp(escapeCallJmpBuf)) { res = false; } else { errno = lastErrno; executionEngine->runFunction(f, gvArgs); // Explicitly acquire errno information lastErrno = errno; res = true; } sigaction(SIGSEGV, &segvActionOld, 0); return res; }
void IRExecutionUnit::ReportAllocations (llvm::ExecutionEngine &engine) { for (AllocationRecord &record : m_records) { if (record.m_process_address == LLDB_INVALID_ADDRESS) continue; if (record.m_section_id == eSectionIDInvalid) continue; engine.mapSectionAddress((void*)record.m_host_address, record.m_process_address); } // Trigger re-application of relocations. engine.finalizeObject(); }
void RecordingMemoryManager::ReportAllocations (llvm::ExecutionEngine &engine) { for (AllocationList::iterator ai = m_allocations.begin(), ae = m_allocations.end(); ai != ae; ++ai) { if (!ai->m_allocated) continue; engine.mapSectionAddress((void*)ai->m_local_start, ai->m_remote_start); } }
bool ExternalDispatcherImpl::executeCall(Function *f, Instruction *i, uint64_t *args) { dispatchers_ty::iterator it = dispatchers.find(i); if (it != dispatchers.end()) { // Code already JIT'ed for this return runProtectedCall(it->second, args); } // Code for this not JIT'ed. Do this now. Function *dispatcher; #ifdef WINDOWS std::map<std::string, void *>::iterator it2 = preboundFunctions.find(f->getName()); if (it2 != preboundFunctions.end()) { // only bind once if (it2->second) { executionEngine->addGlobalMapping(f, it2->second); it2->second = 0; } } #endif Module *dispatchModule = NULL; #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) // The MCJIT generates whole modules at a time so for every call that we // haven't made before we need to create a new Module. dispatchModule = new Module(getFreshModuleID(), ctx); #else dispatchModule = this->singleDispatchModule; #endif dispatcher = createDispatcher(f, i, dispatchModule); dispatchers.insert(std::make_pair(i, dispatcher)); // Force the JIT execution engine to go ahead and build the function. This // ensures that any errors or assertions in the compilation process will // trigger crashes instead of being caught as aborts in the external // function. #if LLVM_VERSION_CODE >= LLVM_VERSION(3, 6) if (dispatcher) { // The dispatchModule is now ready so tell MCJIT to generate the code for // it. auto dispatchModuleUniq = std::unique_ptr<Module>(dispatchModule); executionEngine->addModule( std::move(dispatchModuleUniq)); // MCJIT takes ownership // Force code generation uint64_t fnAddr = executionEngine->getFunctionAddress(dispatcher->getName()); executionEngine->finalizeObject(); assert(fnAddr && "failed to get function address"); (void)fnAddr; } else { // MCJIT didn't take ownership of the module so delete it. delete dispatchModule; } #else if (dispatcher) { // Old JIT works on a function at a time so compile the function. executionEngine->recompileAndRelinkFunction(dispatcher); } #endif return runProtectedCall(dispatcher, args); }
void Simulator::Simulate() { llvm::SMDiagnostic error; //std::unique_ptr<llvm::Module> M = llvm::ParseIRFile("Behavior.bc", error, context); //MyModule = M.get(); MyModule = llvm::ParseIRFile("Behavior.bc", error, context); string err_str; /* OwningPtr<MemoryBuffer> result; MemoryBuffer *mb; llvm::error_code ec = MemoryBuffer::getFile("Behavior.bc", result); mb = result.take(); err_str = ec.message(); if (!mb) { error() <<"Cannot open \"" <<bitcode_file() <<"\": " <<err_str <<endl; exit(1); } MyModule = llvm::ParseBitcodeFile(mb,context,&err_str); if (!MyModule) { error() <<"Failed to load module from bitcode file: " <<err_str <<endl; exit(1); } delete mb; */ /* for (llvm::Module::iterator f = MyModule->begin(), ef = MyModule->end(); f!=ef; ++f) { f->addFnAttr(Attributes::AlwaysInline); } */ for (int32_t i = 0; i < (int32_t)OPCODE::INVALID; i++) { OPCODE op = (OPCODE) i; llvm::Function *func = MyModule->getFunction(GetFuncName(op)); func->addFnAttr(llvm::Attribute::AlwaysInline); OpFunctionMap[op] = func; } test_type = MyModule->getFunction("test")->getFunctionType(); std::string ErrStr; passManager = new llvm::PassManager(); passManager->add(llvm::createAlwaysInlinerPass()); fPassManager = new llvm::FunctionPassManager(MyModule); //fPassManager->add(new DataLayout(*EE->getDataLayout())); //fPassManager->add(new DataLayout(*EE->getDataLayout())); fPassManager->add(llvm::createGVNPass()); fPassManager->add(llvm::createInstructionCombiningPass()); fPassManager->add(llvm::createCFGSimplificationPass()); fPassManager->add(llvm::createDeadStoreEliminationPass()); /* llvm::EngineBuilder builder(MyModule); builder.setErrorStr(&ErrStr); builder.setEngineKind(llvm::EngineKind::JIT); builder.setOptLevel(llvm::CodeGenOpt::Default); // None/Less/Default/Aggressive //llvm::TargetOptions options; //options.JITExceptionHandling = 1; //builder.setTargetOptions(options); EE = builder.create(); */ //StringRef MCPU = llvm::sys::getHostCPUName() EE = llvm::EngineBuilder(MyModule).create(); /* EE = llvm::EngineBuilder(std::move(M)) .setErrorStr(&ErrStr) .setMCJITMemoryManager(llvm::make_unique<llvm::SectionMemoryManager>()) .create(); */ /* EE = llvm::EngineBuilder(M) .setErrorStr(&ErrStr) .setMCJITMemoryManager(llvm::SectionMemoryManager()) .create(); EE = llvm::EngineBuilder(std::move(M)).setErrorStr(&ErrStr).create(); */ if (!EE) { fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); exit(1); } EE->DisableLazyCompilation(true); /* //atexit(llvm_shutdown); // Call llvm_shutdown() on exit. //llvm::EngineBuilder builder(MyModule); llvm::EngineBuilder builder(std::move(M)); //llvm::EngineBuilder builder(MyModule); builder.setErrorStr(&err_str); builder.setEngineKind(llvm::EngineKind::JIT); builder.setOptLevel(llvm::CodeGenOpt::Default); // None/Less/Default/Aggressive //TargetOptions options; //options.JITExceptionHandling = 1; //builder.setTargetOptions(options); EE = builder.create(); if (!EE) { std::cout <<"failed to create execution engine: " <<err_str <<"\n"; exit(1); } */ /* //MyModule->dump(); EE = llvm::EngineBuilder(std::move(M)).create(); */ //string ErrStr; //EE = llvm::EngineBuilder(std::move(M)).setErrorStr(&ErrStr).setMCPU("i386").create(); //context = llvm::getGlobalContext(); int32_t index = 0; Blocks = new HostBlock[1000]; int32_t block_index = 0; while(index < total_inst) { Blocks[block_index].pc = index; ostringstream f_name; f_name << "func"; f_name << block_index; //string f_name = string("func");// + string(index); /* llvm::Function *func = llvm::cast<llvm::Function>(MyModule->getOrInsertFunction(f_name.str(), llvm::Type::getVoidTy(context), (llvm::Type *)0)); */ // Make the function type: double(double,double) etc. //std::vector<Type*> Doubles(Args.size(), // Type::getDoubleTy(getGlobalContext())); llvm::FunctionType *FT = llvm::FunctionType::get(llvm::Type::getVoidTy(context), false); llvm::Function *func = llvm::Function::Create(FT, llvm::Function::ExternalLinkage, f_name.str(), MyModule); //Function *F = Function::Create(FT, Function::ExternalLinkage, FnName, M); // Add a basic block to the function. As before, it automatically inserts // because of the last argument. llvm::BasicBlock *BB = llvm::BasicBlock::Create(context, "EntryBlock", func); // Create a basic block builder with default parameters. The builder will // automatically append instructions to the basic block `BB'. IRB.SetInsertPoint(BB); llvm::Function *sim_func; CInst *inst; int b_size = 0; do { inst = &instructions[index]; llvm::Value *dst = IRB.getInt32(inst->dst_reg); llvm::Value *src0 = IRB.getInt32(inst->src0_reg); llvm::Value *src1 = IRB.getInt32(inst->src1_reg); sim_func = OpFunctionMap[inst->opcode]; llvm::Value *oprnds[] = {dst, src0, src1}; llvm::ArrayRef <llvm::Value *> ref(oprnds, 3); IRB.CreateCall(sim_func, ref); index++; b_size++; //cout << "Index " << index << endl; //} while(b_size < 10 || inst->opcode != OPCODE::JMP); } while(b_size < 10 && index < total_inst); IRB.CreateRetVoid(); passManager->run(*MyModule); fPassManager->run(*func); EE->finalizeObject(); //std::vector<llvm::GenericValue> noargs; //std::cout << "calling " << f_name.str() << endl; //EE->runFunction(func, noargs); //Blocks[block_index].func_ptr = reinterpret_cast<HostFunction>(EE->getPointerToFunction(func)); Blocks[block_index].func_ptr = (void *)(EE->getPointerToFunction(func)); //Blocks[block_index].func_ptr = reinterpret_cast<decltype(HostFunction())>(EE->getPointerToNamedFunction(f_name.str())); //(Blocks[block_index].func_ptr)(); block_index++; //cout << "BlockIndex " << block_index << endl; } total_blocks = block_index; MyModule->dump(); /* cout << "calling add32" << endl; void (*add32)(int32_t, int32_t, int32_t) = reinterpret_cast<void (*)(int32_t, int32_t, int32_t)>(EE->getFunctionAddress("add32")); add32(0, 2, 3); */ /* void (*func0)() = reinterpret_cast<void (*)()>(EE->getFunctionAddress("func1")); func0(); */ /* struct timeval tp; gettimeofday(&tp, NULL); long int start = tp.tv_sec * 1000 + tp.tv_usec / 1000; for (int32_t i = 0; i < 100; i++) { for (int32_t j = 0 ; j < total_blocks; j++) { ((HostFunction)(Blocks[j].func_ptr))(); } } gettimeofday(&tp, NULL); long int end = tp.tv_sec * 1000 + tp.tv_usec / 1000; cout << "Time = " << end - start << endl; */ }