int run(unique_ptr<Module> module, Chars_const fnName, const vector<string> args) { check(module, "no module"); Function* entryFn = module->getFunction(fnName); check(entryFn, "Source file does not contain a function of the given name"); // Use an EngineBuilder to configure and construct an MCJIT ExecutionEngine. #if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR <= 5 EngineBuilder builder(module.release()); builder.setUseMCJIT(true); #else const EngineBuilder builder(move(module)); const SectionMemoryManager mm; builder.setMCJITMemoryManager(&mm); #endif string errorStr; builder.setErrorStr(&errorStr); builder.setEngineKind(EngineKind::JIT); builder.setOptLevel(CodeGenOpt::None); ExecutionEngine* engine = builder.create(); // Call 'finalizeObject' to notify the JIT that we're ready to execute the jitted code, // then run the static constructors. engine->finalizeObject(); engine->runStaticConstructorsDestructors(false); // Pass the args to the jitted function, and capture the result. const int result = engine->runFunctionAsMain(entryFn, args, nullptr); engine->runStaticConstructorsDestructors(true); // Run the static destructors. return result; }
casefoldFunctionType caseFoldCodeGen(void) { Module * M = new Module("casefold", getGlobalContext()); IDISA::IDISA_Builder * idb = GetIDISA_Builder(M); kernel::PipelineBuilder pipelineBuilder(M, idb); Encoding encoding(Encoding::Type::UTF_8, 8); pablo::PabloFunction * function = casefold2pablo(encoding); pipelineBuilder.CreateKernels(function); pipelineBuilder.ExecuteKernels(); //std::cerr << "ExecuteKernels(); done\n"; llvm::Function * main_IR = M->getFunction("Main"); ExecutionEngine * mEngine = JIT_to_ExecutionEngine(M); mEngine->finalizeObject(); //std::cerr << "finalizeObject(); done\n"; delete idb; return reinterpret_cast<casefoldFunctionType>(mEngine->getPointerToFunction(main_IR)); }
void * compile(llvm::Module * m) { ExecutionEngine * engine = EngineBuilder(std::unique_ptr<Module>(m)) .create(); engine->finalizeObject(); return engine->getPointerToFunction( m->getFunction("aFun")); }
ExecutionEngine *MCJITHelper::compileModule(Module *M) { if (M == OpenModule) closeCurrentModule(); std::string ErrStr; ExecutionEngine *NewEngine = EngineBuilder(M) .setErrorStr(&ErrStr) .setMCJITMemoryManager(new HelpingMemoryManager(this)) .create(); if (!NewEngine) { fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); exit(1); } // Create a function pass manager for this engine FunctionPassManager *FPM = new FunctionPassManager(M); // Set up the optimizer pipeline. Start with registering info about how the // target lays out data structures. FPM->add(new DataLayout(*NewEngine->getDataLayout())); // Provide basic AliasAnalysis support for GVN. FPM->add(createBasicAliasAnalysisPass()); // Promote allocas to registers. FPM->add(createPromoteMemoryToRegisterPass()); // Do simple "peephole" optimizations and bit-twiddling optzns. FPM->add(createInstructionCombiningPass()); // Reassociate expressions. FPM->add(createReassociatePass()); // Eliminate Common SubExpressions. FPM->add(createGVNPass()); // Simplify the control flow graph (deleting unreachable blocks, etc). FPM->add(createCFGSimplificationPass()); FPM->doInitialization(); // For each function in the module Module::iterator it; Module::iterator end = M->end(); for (it = M->begin(); it != end; ++it) { // Run the FPM on this function FPM->run(*it); } // We don't need this anymore delete FPM; // Store this engine EngineMap[M] = NewEngine; NewEngine->finalizeObject(); return NewEngine; }
void initEE(std::unique_ptr<Module> Owner) { string ErrStr; if (EE == NULL) { RTDyldMM = new SectionMemoryManager(); EE = EngineBuilder(std::move(Owner)) .setEngineKind(EngineKind::JIT) .setErrorStr(&ErrStr) .setVerifyModules(true) .setMCJITMemoryManager(std::unique_ptr<RTDyldMemoryManager>(RTDyldMM)) .setOptLevel(CodeGenOpt::Default) .create(); } else EE->addModule(std::move(Owner)); if (ErrStr.length() != 0) cerr << "Create Engine Error" << endl << ErrStr << endl; EE->finalizeObject(); }
ExecutionEngine* codegen::compile() { if(compiled) { cerr << "Module has already been compiled, cannot compile again!" << "\nExiting..." << endl; exit(-1); } builder->CreateRet(ConstantInt::get(int32Type, 0)); // This is for debugging if(llvmoutput) module->dump(); string error; ExecutionEngine *executionEngine = EngineBuilder(module). setErrorStr(&error). setUseMCJIT(true). create(); executionEngine->finalizeObject(); compiled = true; return executionEngine; }
void JITCompiledModule::compile_module(CodeGen *cg, llvm::Module *m, const string &function_name) { // Make the execution engine debug(2) << "Creating new execution engine\n"; string error_string; TargetOptions options; options.LessPreciseFPMADOption = true; options.NoFramePointerElim = false; options.AllowFPOpFusion = FPOpFusion::Fast; options.UnsafeFPMath = true; options.NoInfsFPMath = true; options.NoNaNsFPMath = true; options.HonorSignDependentRoundingFPMathOption = false; options.UseSoftFloat = false; options.FloatABIType = cg->use_soft_float_abi() ? FloatABI::Soft : FloatABI::Hard; options.NoZerosInBSS = false; options.GuaranteedTailCallOpt = false; options.DisableTailCalls = false; options.StackAlignmentOverride = 0; options.TrapFuncName = ""; options.PositionIndependentExecutable = true; options.UseInitArray = false; EngineBuilder engine_builder(m); engine_builder.setTargetOptions(options); engine_builder.setErrorStr(&error_string); engine_builder.setEngineKind(EngineKind::JIT); #ifdef USE_MCJIT engine_builder.setUseMCJIT(true); JITMemoryManager *memory_manager = JITMemoryManager::CreateDefaultMemManager(); engine_builder.setJITMemoryManager(memory_manager); #else engine_builder.setUseMCJIT(false); #endif engine_builder.setOptLevel(CodeGenOpt::Aggressive); engine_builder.setMCPU(cg->mcpu()); engine_builder.setMAttrs(vec<string>(cg->mattrs())); ExecutionEngine *ee = engine_builder.create(); if (!ee) std::cerr << error_string << "\n"; internal_assert(ee) << "Couldn't create execution engine\n"; #ifdef __arm__ start = end = NULL; #endif // Do any target-specific initialization cg->jit_init(ee, m); // Retrieve function pointers from the compiled module (which also // triggers compilation) debug(1) << "JIT compiling...\n"; hook_up_function_pointer(ee, m, function_name, true, &function); void *function_address = reinterpret_bits<void *>(function); debug(1) << "JIT compiled function pointer " << function_address << "\n"; hook_up_function_pointer(ee, m, function_name + "_jit_wrapper", true, &wrapped_function); hook_up_function_pointer(ee, m, "halide_copy_to_host", false, ©_to_host); hook_up_function_pointer(ee, m, "halide_copy_to_dev", false, ©_to_dev); hook_up_function_pointer(ee, m, "halide_dev_free", false, &free_dev_buffer); hook_up_function_pointer(ee, m, "halide_set_error_handler", true, &set_error_handler); hook_up_function_pointer(ee, m, "halide_set_custom_allocator", true, &set_custom_allocator); hook_up_function_pointer(ee, m, "halide_set_custom_do_par_for", true, &set_custom_do_par_for); hook_up_function_pointer(ee, m, "halide_set_custom_do_task", true, &set_custom_do_task); hook_up_function_pointer(ee, m, "halide_set_custom_trace", true, &set_custom_trace); hook_up_function_pointer(ee, m, "halide_shutdown_thread_pool", true, &shutdown_thread_pool); debug(2) << "Finalizing object\n"; ee->finalizeObject(); // Stash the various objects that need to stay alive behind a reference-counted pointer. module = new JITModuleHolder(ee, m, shutdown_thread_pool); // Do any target-specific post-compilation module meddling cg->jit_finalize(ee, m, &module.ptr->cleanup_routines); #ifdef __arm__ // Flush each function from the dcache so that it gets pulled into // the icache correctly. // finalizeMemory should have done the trick, but as of Aug 28 // 2013, it doesn't work unless we also manually flush the // cache. Otherwise the icache's view of the code is missing the // relocations, which gets really confusing to debug, because // gdb's view of the code uses the dcache, so the disassembly // isn't right. debug(2) << "Flushing cache from " << (void *)start << " to " << (void *)end << "\n"; __builtin___clear_cache(start, end); #endif // TODO: I don't think this is necessary, we shouldn't have any static constructors // ee->runStaticConstructorsDestructors(false); }
extern "C" void LLVMExecutionEngineFinalizeObject(LLVMExecutionEngineRef eeref) { ExecutionEngine *ee = unwrap(eeref); ee->finalizeObject(); }
ExecutionEngine *MCJITHelper::compileModule(Module *M) { assert(EngineMap.find(M) == EngineMap.end()); if (M == CurrentModule) closeCurrentModule(); std::string ErrStr; ExecutionEngine *EE = EngineBuilder(M) .setErrorStr(&ErrStr) .setMCJITMemoryManager(new HelpingMemoryManager(this)) .create(); if (!EE) { fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); exit(1); } if (UseObjectCache) EE->setObjectCache(&OurObjectCache); // Get the ModuleID so we can identify IR input files const std::string ModuleID = M->getModuleIdentifier(); // If we've flagged this as an IR file, it doesn't need function passes run. if (0 != ModuleID.compare(0, 3, "IR:")) { FunctionPassManager *FPM = 0; // Create a FPM for this module FPM = new FunctionPassManager(M); // Set up the optimizer pipeline. Start with registering info about how the // target lays out data structures. FPM->add(new DataLayout(*EE->getDataLayout())); // Provide basic AliasAnalysis support for GVN. FPM->add(createBasicAliasAnalysisPass()); // Promote allocas to registers. FPM->add(createPromoteMemoryToRegisterPass()); // Do simple "peephole" optimizations and bit-twiddling optzns. FPM->add(createInstructionCombiningPass()); // Reassociate expressions. FPM->add(createReassociatePass()); // Eliminate Common SubExpressions. FPM->add(createGVNPass()); // Simplify the control flow graph (deleting unreachable blocks, etc). FPM->add(createCFGSimplificationPass()); FPM->doInitialization(); // For each function in the module Module::iterator it; Module::iterator end = M->end(); for (it = M->begin(); it != end; ++it) { // Run the FPM on this function FPM->run(*it); } delete FPM; } EE->finalizeObject(); // Store this engine EngineMap[M] = EE; return EE; }
int main() { ygt_print("Hello!\n"); InitializeNativeTarget(); InitializeNativeTargetAsmPrinter(); InitializeNativeTargetAsmParser(); InitializeNativeTargetDisassembler(); ygt_print("Creating LLVM context and module...\n"); LLVMContext ctx; auto m = make_unique<Module>("the_module", ctx); ygt_print("Creating StackMapHelper...\n"); StackMapHelper smhelper; ygt_print("Declaring yg_stack_swap as an LLVM-level function...\n"); declare_ss(ctx, *m); ygt_print("Constructing bar, the ss leaf...\n"); Function *bar; smid_t bar_smid; tie(bar, bar_smid) = make_ss_leaf("barss", &main_stack, &coro_stack, smhelper, ctx, *m); verifyFunction(*bar); ygt_print("Constructing foo, the caller...\n"); Function *foo; smid_t foo_smid; tie(foo, foo_smid) = make_caller("foo", bar, smhelper, ctx, *m); verifyFunction(*foo); m->dump(); Function *ss_func = m->getFunction("yg_stack_swap"); ygt_print("Creating execution engine...\n"); ExecutionEngine *ee = EngineBuilder(move(m)).setEngineKind(EngineKind::JIT).create(); ygt_print("Execution engine created.\n"); StackMapSectionRecorder smsr; ygt_print("Registering JIT event listener...\n"); ee->RegisterJITEventListener(&smsr); EHFrameSectionRegisterer reg; ygt_print("Registering EHFrame registerer...\n"); ee->RegisterJITEventListener(®); ygt_print("Adding global mapping yg_stack_swap...\n"); ee->addGlobalMapping(ss_func, reinterpret_cast<void*>(yg_stack_swap)); ygt_print("JIT compiling...\n"); ee->finalizeObject(); ygt_print("Adding stack map sections...\n"); smhelper.add_stackmap_sections(smsr, *ee); ygt_print("Registering EH frames...\n"); reg.registerEHFrameSections(); uintptr_t yg_stack_swap_addr = ee->getFunctionAddress("yg_stack_swap"); ygt_print("yg_stack_swap_addr=%" PRIxPTR ", yg_stack_swap=%p\n", yg_stack_swap_addr, yg_stack_swap); assert(yg_stack_swap_addr == reinterpret_cast<uintptr_t>(yg_stack_swap)); ygt_print("Getting foo...\n"); void (*the_real_foo)(int32_t, int64_t, float, double) = (void(*)(int32_t, int64_t, float, double)) ee->getFunctionAddress("foo"); ygt_print("the_real_foo == %p\n", the_real_foo); ygt_print("Prepare corotine for introspection...\n"); coro_stack = YGStack::alloc(8*1024*1024); coro_stack.init(reinterpret_cast<uintptr_t>(coro)); MyCtx my_ctx = { foo_smid, bar_smid, &smhelper }; ygt_print("Swap-stack to prepare the coroutine...\n"); yg_stack_swap(&main_stack, &coro_stack, reinterpret_cast<uintptr_t>(&my_ctx)); ygt_print("Back from coro.\n"); ygt_print("Calling the_real_foo...\n"); the_real_foo(100, 200, 300.0f, 400.0); ygt_print("Returned from foo.\n"); return 0; }
void *MCJITHelper::getPointerToFunction(Function* F) { // See if an existing instance of MCJIT has this function. EngineVector::iterator begin = Engines.begin(); EngineVector::iterator end = Engines.end(); EngineVector::iterator it; for (it = begin; it != end; ++it) { void *P = (*it)->getPointerToFunction(F); if (P) return P; } // If we didn't find the function, see if we can generate it. if (OpenModule) { std::string ErrStr; ExecutionEngine *NewEngine = EngineBuilder(OpenModule) .setErrorStr(&ErrStr) .setMCJITMemoryManager(new HelpingMemoryManager(this)) .create(); if (!NewEngine) { fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); exit(1); } // Create a function pass manager for this engine FunctionPassManager *FPM = new FunctionPassManager(OpenModule); // Set up the optimizer pipeline. Start with registering info about how the // target lays out data structures. FPM->add(new DataLayout(*NewEngine->getDataLayout())); // Provide basic AliasAnalysis support for GVN. FPM->add(createBasicAliasAnalysisPass()); // Promote allocas to registers. FPM->add(createPromoteMemoryToRegisterPass()); // Do simple "peephole" optimizations and bit-twiddling optzns. FPM->add(createInstructionCombiningPass()); // Reassociate expressions. FPM->add(createReassociatePass()); // Eliminate Common SubExpressions. FPM->add(createGVNPass()); // Simplify the control flow graph (deleting unreachable blocks, etc). FPM->add(createCFGSimplificationPass()); FPM->doInitialization(); // For each function in the module Module::iterator it; Module::iterator end = OpenModule->end(); for (it = OpenModule->begin(); it != end; ++it) { // Run the FPM on this function FPM->run(*it); } // We don't need this anymore delete FPM; OpenModule = NULL; Engines.push_back(NewEngine); NewEngine->finalizeObject(); return NewEngine->getPointerToFunction(F); } return NULL; }