LLVMExecutionEngineRef mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb) { std::string Error; force_pass_linking (); LLVMInitializeX86Target (); LLVMInitializeX86TargetInfo (); llvm::cl::ParseEnvironmentOptions("mono", "MONO_LLVM", "", false); mono_mm = new MonoJITMemoryManager (); mono_mm->alloc_cb = alloc_cb; #if LLVM_MAJOR_VERSION == 2 && LLVM_MINOR_VERSION < 8 DwarfExceptionHandling = true; #else JITExceptionHandling = true; #endif // PrettyStackTrace installs signal handlers which trip up libgc DisablePrettyStackTrace = true; ExecutionEngine *EE = ExecutionEngine::createJIT (unwrap (MP), &Error, mono_mm, CodeGenOpt::Default); if (!EE) { errs () << "Unable to create LLVM ExecutionEngine: " << Error << "\n"; g_assert_not_reached (); } EE->InstallExceptionTableRegister (exception_cb); EE->RegisterJITEventListener (new MonoJITEventListener (emitted_cb)); fpm = new FunctionPassManager (unwrap (MP)); fpm->add(new TargetData(*EE->getTargetData())); /* Add a default set of passes */ //createStandardFunctionPasses (fpm, 2); fpm->add(createInstructionCombiningPass()); fpm->add(createReassociatePass()); fpm->add(createGVNPass()); fpm->add(createCFGSimplificationPass()); /* The one used by opt is: * -simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -basiccg -domtree -domfrontier -scalarrepl -simplify-libcalls -instcombine -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loopsimplify -domfrontier -loopsimplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loopsimplify -lcssa -iv-users -indvars -loop-deletion -loopsimplify -lcssa -loop-unroll -instcombine -memdep -gvn -memdep -memcpyopt -sccp -instcombine -domtree -memdep -dse -adce -gvn -simplifycfg -preverify -domtree -verify */ /* Add passes specified by the env variable */ /* Only the passes in force_pass_linking () can be used */ for (unsigned i = 0; i < PassList.size(); ++i) { const PassInfo *PassInf = PassList[i]; Pass *P = 0; if (PassInf->getNormalCtor()) P = PassInf->getNormalCtor()(); fpm->add (P); } return wrap(EE); }
LLVMExecutionEngineRef mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb) { std::string Error; LLVMInitializeX86Target (); LLVMInitializeX86TargetInfo (); llvm::cl::ParseEnvironmentOptions("mono", "MONO_LLVM", "", false); mono_mm = new MonoJITMemoryManager (); mono_mm->alloc_cb = alloc_cb; mono_mm->emitted_cb = emitted_cb; DwarfExceptionHandling = true; // PrettyStackTrace installs signal handlers which trip up libgc DisablePrettyStackTrace = true; ExecutionEngine *EE = ExecutionEngine::createJIT (unwrap (MP), &Error, mono_mm, CodeGenOpt::Default); if (!EE) { errs () << "Unable to create LLVM ExecutionEngine: " << Error << "\n"; g_assert_not_reached (); } EE->InstallExceptionTableRegister (exception_cb); EE->RegisterJITEventListener (new MonoJITEventListener ()); fpm = new FunctionPassManager (unwrap (MP)); fpm->add(new TargetData(*EE->getTargetData())); /* Add a random set of passes */ /* Make this run-time configurable */ fpm->add(createInstructionCombiningPass()); fpm->add(createReassociatePass()); fpm->add(createGVNPass()); fpm->add(createCFGSimplificationPass()); /* Add passes specified by the env variable */ /* FIXME: This can only add passes which are linked in, thus are already used */ for (unsigned i = 0; i < PassList.size(); ++i) { const PassInfo *PassInf = PassList[i]; Pass *P = 0; if (PassInf->getNormalCtor()) P = PassInf->getNormalCtor()(); if (dynamic_cast<MachineFunctionPass*>(P) != 0) { errs () << PassInf->getPassName () << " is a machine function pass.\n"; } else { fpm->add (P); } } return wrap(EE); }
int main() { Module* module = new Module("interactive"); ExecutionEngine* engine = ExecutionEngine::create(module); CEnv cenv(module, engine->getTargetData()); repl(cenv, engine); std::cout << "Generated code:" << endl; module->dump(); return 0; }
main_func_type jit_engine::compile(const ast::Program &prog) { llvm::LLVMContext &c=llvm::getGlobalContext(); llvm::Module *m=new llvm::Module("brainfuck", c); brainfuck::codegen(*m, prog); //m->dump(); std::string ErrStr; ExecutionEngine *TheExecutionEngine = EngineBuilder(m).setErrorStr(&ErrStr).create(); if (!TheExecutionEngine) { fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); exit(1); } Function *f_main=m->getFunction("main"); // Optimize, target dependant if(optimization_level_>0) { FunctionPassManager OurFPM(m); // Set up the optimizer pipeline. Start with registering info about how the // target lays out data structures. OurFPM.add(new TargetData(*TheExecutionEngine->getTargetData())); // Provide basic AliasAnalysis support for GVN. OurFPM.add(createBasicAliasAnalysisPass()); // Do simple "peephole" optimizations and bit-twiddling optzns. OurFPM.add(createInstructionCombiningPass()); // Reassociate expressions. OurFPM.add(createReassociatePass()); // Eliminate Common SubExpressions. OurFPM.add(createGVNPass()); // Simplify the control flow graph (deleting unreachable blocks, etc). OurFPM.add(createCFGSimplificationPass()); //OurFPM.add(createLoopSimplifyPass()); //OurFPM.add(createBlockPlacementPass()); //OurFPM.add(createConstantPropagationPass()); OurFPM.doInitialization(); OurFPM.run(*f_main); } //m->dump(); void *rp=TheExecutionEngine->getPointerToFunction(f_main); main_func_type fp=reinterpret_cast<main_func_type>(rp); return fp; }
LLVMExecutionEngineRef mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb, DlSymCb *dlsym_cb) { std::string Error; force_pass_linking (); #ifdef TARGET_ARM LLVMInitializeARMTarget (); LLVMInitializeARMTargetInfo (); LLVMInitializeARMTargetMC (); #else LLVMInitializeX86Target (); LLVMInitializeX86TargetInfo (); LLVMInitializeX86TargetMC (); #endif mono_mm = new MonoJITMemoryManager (); mono_mm->alloc_cb = alloc_cb; mono_mm->dlsym_cb = dlsym_cb; //JITExceptionHandling = true; // PrettyStackTrace installs signal handlers which trip up libgc DisablePrettyStackTrace = true; /* * The Default code model doesn't seem to work on amd64, * test_0_fields_with_big_offsets (among others) crashes, because LLVM tries to call * memset using a normal pcrel code which is in 32bit memory, while memset isn't. */ TargetOptions opts; opts.JITExceptionHandling = 1; EngineBuilder b (unwrap (MP)); #ifdef TARGET_AMD64 ExecutionEngine *EE = b.setJITMemoryManager (mono_mm).setTargetOptions (opts).setCodeModel (CodeModel::Large).setAllocateGVsWithCode (true).create (); #else ExecutionEngine *EE = b.setJITMemoryManager (mono_mm).setTargetOptions (opts).setAllocateGVsWithCode (true).create (); #endif g_assert (EE); #if 0 ExecutionEngine *EE = ExecutionEngine::createJIT (unwrap (MP), &Error, mono_mm, CodeGenOpt::Default, true, Reloc::Default, CodeModel::Large); if (!EE) { errs () << "Unable to create LLVM ExecutionEngine: " << Error << "\n"; g_assert_not_reached (); } #endif EE->InstallExceptionTableRegister (exception_cb); mono_event_listener = new MonoJITEventListener (emitted_cb); EE->RegisterJITEventListener (mono_event_listener); fpm = new FunctionPassManager (unwrap (MP)); fpm->add(new TargetData(*EE->getTargetData())); PassRegistry &Registry = *PassRegistry::getPassRegistry(); initializeCore(Registry); initializeScalarOpts(Registry); //initializeIPO(Registry); initializeAnalysis(Registry); initializeIPA(Registry); initializeTransformUtils(Registry); initializeInstCombine(Registry); //initializeInstrumentation(Registry); initializeTarget(Registry); llvm::cl::ParseEnvironmentOptions("mono", "MONO_LLVM", "", false); if (PassList.size() > 0) { /* Use the passes specified by the env variable */ /* Only the passes in force_pass_linking () can be used */ for (unsigned i = 0; i < PassList.size(); ++i) { const PassInfo *PassInf = PassList[i]; Pass *P = 0; if (PassInf->getNormalCtor()) P = PassInf->getNormalCtor()(); fpm->add (P); } } else { /* Use the same passes used by 'opt' by default, without the ipo passes */ const char *opts = "-simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -basiccg -domtree -domfrontier -scalarrepl -simplify-libcalls -instcombine -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loop-simplify -domfrontier -loop-simplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loop-simplify -lcssa -iv-users -indvars -loop-deletion -loop-simplify -lcssa -loop-unroll -instcombine -memdep -gvn -memdep -memcpyopt -sccp -instcombine -domtree -memdep -dse -adce -gvn -simplifycfg -preverify -domtree -verify"; char **args; int i; args = g_strsplit (opts, " ", 1000); for (i = 0; args [i]; i++) ; llvm::cl::ParseCommandLineOptions (i, args, "", false); g_strfreev (args); for (unsigned i = 0; i < PassList.size(); ++i) { const PassInfo *PassInf = PassList[i]; Pass *P = 0; if (PassInf->getNormalCtor()) P = PassInf->getNormalCtor()(); fpm->add (P); } /* fpm->add(createInstructionCombiningPass()); fpm->add(createReassociatePass()); fpm->add(createGVNPass()); fpm->add(createCFGSimplificationPass()); */ } return wrap(EE); }
LLVMExecutionEngineRef mono_llvm_create_ee (LLVMModuleProviderRef MP, AllocCodeMemoryCb *alloc_cb, FunctionEmittedCb *emitted_cb, ExceptionTableCb *exception_cb) { std::string Error; force_pass_linking (); LLVMInitializeX86Target (); LLVMInitializeX86TargetInfo (); mono_mm = new MonoJITMemoryManager (); mono_mm->alloc_cb = alloc_cb; #if LLVM_MAJOR_VERSION == 2 && LLVM_MINOR_VERSION < 8 DwarfExceptionHandling = true; #else JITExceptionHandling = true; #endif // PrettyStackTrace installs signal handlers which trip up libgc DisablePrettyStackTrace = true; ExecutionEngine *EE = ExecutionEngine::createJIT (unwrap (MP), &Error, mono_mm, CodeGenOpt::Default); if (!EE) { errs () << "Unable to create LLVM ExecutionEngine: " << Error << "\n"; g_assert_not_reached (); } EE->InstallExceptionTableRegister (exception_cb); mono_event_listener = new MonoJITEventListener (emitted_cb); EE->RegisterJITEventListener (mono_event_listener); fpm = new FunctionPassManager (unwrap (MP)); fpm->add(new TargetData(*EE->getTargetData())); #if LLVM_CHECK_VERSION(2, 9) PassRegistry &Registry = *PassRegistry::getPassRegistry(); initializeCore(Registry); initializeScalarOpts(Registry); //initializeIPO(Registry); initializeAnalysis(Registry); initializeIPA(Registry); initializeTransformUtils(Registry); initializeInstCombine(Registry); //initializeInstrumentation(Registry); initializeTarget(Registry); #endif llvm::cl::ParseEnvironmentOptions("mono", "MONO_LLVM", "", false); if (PassList.size() > 0) { /* Use the passes specified by the env variable */ /* Only the passes in force_pass_linking () can be used */ for (unsigned i = 0; i < PassList.size(); ++i) { const PassInfo *PassInf = PassList[i]; Pass *P = 0; if (PassInf->getNormalCtor()) P = PassInf->getNormalCtor()(); fpm->add (P); } } else { /* Use the same passes used by 'opt' by default, without the ipo passes */ const char *opts = "-simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -basiccg -domtree -domfrontier -scalarrepl -simplify-libcalls -instcombine -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loopsimplify -domfrontier -loopsimplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loopsimplify -lcssa -iv-users -indvars -loop-deletion -loopsimplify -lcssa -loop-unroll -instcombine -memdep -gvn -memdep -memcpyopt -sccp -instcombine -domtree -memdep -dse -adce -gvn -simplifycfg -preverify -domtree -verify"; char **args; int i; args = g_strsplit (opts, " ", 1000); for (i = 0; args [i]; i++) ; llvm::cl::ParseCommandLineOptions (i, args, "", false); g_strfreev (args); for (unsigned i = 0; i < PassList.size(); ++i) { const PassInfo *PassInf = PassList[i]; Pass *P = 0; if (PassInf->getNormalCtor()) P = PassInf->getNormalCtor()(); fpm->add (P); } /* fpm->add(createInstructionCombiningPass()); fpm->add(createReassociatePass()); fpm->add(createGVNPass()); fpm->add(createCFGSimplificationPass()); */ } return wrap(EE); }
int main(int argc, char* argv[]) { if(argc < 2) { cerr << "Usage: " << argv[0] << " bf_file" << endl; return -1; } ifstream sourceFile(argv[1]); string line, source; while(getline(sourceFile, line)) source += line; // Setup a module and engine for JIT-ing std::string error; InitializeNativeTarget(); Module* module = new Module("bfcode", getGlobalContext()); InitializeNativeTarget(); LLVMLinkInJIT(); ExecutionEngine *engine = EngineBuilder(module) .setErrorStr(&error) .setOptLevel(CodeGenOpt::Aggressive) .create(); if(!engine) { cout << "No engine created: " << error << endl; return -1; } module->setDataLayout(engine->getTargetData()->getStringRepresentation()); // Compile the BF to IR cout << "Parsing… " << flush; Function* func = makeFunc(module, source.c_str()); cout << "done" << endl; { ofstream dst("out.ll"); raw_os_ostream rawdst(dst); rawdst << *module; } // Run optimization passes cout << "Optimizing… " << flush; PassManagerBuilder PMBuilder; FunctionPassManager pm(module); PMBuilder.populateFunctionPassManager(pm); pm.add(new TargetData(*(engine->getTargetData()))); pm.add(createVerifierPass()); // Eliminate simple loops such as [>>++<<-] pm.add(createInstructionCombiningPass()); // Cleanup for scalarrepl. pm.add(createLICMPass()); // Hoist loop invariants pm.add(createPromoteMemoryToRegisterPass()); pm.add(createIndVarSimplifyPass()); // Canonicalize indvars pm.add(createLoopDeletionPass()); // Delete dead loops pm.add(createConstantPropagationPass()); // Propagate constants pm.add(new CondProp); // Propagate conditionals // Simplify code for(int repeat=0; repeat < 3; repeat++) { pm.add(createPromoteMemoryToRegisterPass()); pm.add(createGVNPass()); // Remove redundancies pm.add(createSCCPPass()); // Constant prop with SCCP pm.add(createLoopDeletionPass()); pm.add(createLoopUnrollPass()); pm.add(createCFGSimplificationPass()); // Merge & remove BBs pm.add(createInstructionCombiningPass()); pm.add(createConstantPropagationPass()); // Propagate constants pm.add(createAggressiveDCEPass()); // Delete dead instructions pm.add(createCFGSimplificationPass()); // Merge & remove BBs pm.add(createDeadStoreEliminationPass()); // Delete dead stores pm.add(createMemCpyOptPass()); // Combine multiple stores into memset's //pm.add(new PutCharAggregatePass); } pm.add(createPromoteMemoryToRegisterPass()); // Process foreach (Function& f, *module) if (!f.isDeclaration) pm.run(f); PassManager pmm; PMBuilder.populateModulePassManager(pmm); pmm.add(createConstantMergePass()); pmm.add(createGlobalOptimizerPass()); pmm.add(createGlobalDCEPass()); pmm.add(createIPConstantPropagationPass()); pmm.run(*module); foreach (Function& f, *module) if (!f.isDeclaration) pm.run(f); pmm.run(*module); cout << "done" << endl; { ofstream dst("optout.ll"); raw_os_ostream rawdst(dst); rawdst << *module; } // Compile … cout << "Compiling…" << flush; int (*bf)() = (int (*)())engine->getPointerToFunction(func); cout << " done" << endl; // … and run! return bf(); }
bool CompiledCondition::compile(){ InitializeNativeTarget(); // Assume we're on main thread... LLVMContext &context = getGlobalContext(); // Initialize module Module* module = new Module("Compiled function", context); // Create exection engine ExecutionEngine* engine = EngineBuilder(module).create(); /********** Generate code **********/ //Get a type for representing an integer pointer //Maybe this should be unsigned integer pointer type... PointerType* integerPointerType = PointerType::get(IntegerType::get(module->getContext(), 32), 0); //Create function type, for our function, int*, int* -> bool vector<const Type*> paramType; paramType.push_back(integerPointerType); paramType.push_back(integerPointerType); FunctionType* functionType = FunctionType::get(IntegerType::get(module->getContext(), 8), paramType, false); //Declare new function Function* function = Function::Create(functionType, GlobalValue::ExternalLinkage, "evaluate", module); //Use C calling convention function->setCallingConv(CallingConv::C); //TODO: Read documentation and reconsider this //Get arguments from function Function::arg_iterator args = function->arg_begin(); Value* marking = args++; Value* valuation = args++; marking->setName("marking"); valuation->setName("valuation"); //Create function block BasicBlock* functionBlock = BasicBlock::Create(module->getContext(), "functionBlock", function, 0); //Generate code CodeGenerationContext codeGenContext(marking, valuation, functionBlock, context); Value* result = _cond->codegen(codeGenContext); //Zero extend the result, e.g. make it a 8 bit bool CastInst* retval = new ZExtInst(result, IntegerType::get(module->getContext(), 8), "retval", functionBlock); //Create a return instruction ReturnInst::Create(module->getContext(), retval, functionBlock); /********** Optimize and Compile **********/ // Create function pass manager, to optimize query FunctionPassManager optimizer(module); optimizer.add(new TargetData(*engine->getTargetData())); optimizer.add(createBasicAliasAnalysisPass()); optimizer.add(createInstructionCombiningPass()); optimizer.add(createReassociatePass()); optimizer.add(createGVNPass()); optimizer.add(createCFGSimplificationPass()); optimizer.doInitialization(); // Verify function, errors written to stderr if(verifyFunction(*function)) return false; // Optimize function optimizer.run(*function); // Compile the function _nativeFunction = (bool(*)(const MarkVal*, const VarVal*))engine->getPointerToFunction(function); return _nativeFunction != NULL; }