void initCodegen() { llvm::InitializeNativeTarget(); llvm::InitializeNativeTargetAsmPrinter(); llvm::InitializeNativeTargetAsmParser(); g.stdlib_module = loadStdlib(); llvm::EngineBuilder eb(new llvm::Module("empty_initial_module", g.context)); eb.setEngineKind(llvm::EngineKind::JIT); // specify we only want the JIT, and not the interpreter fallback eb.setUseMCJIT(true); eb.setMCJITMemoryManager(createMemoryManager()); // eb.setOptLevel(llvm::CodeGenOpt::None); // -O0 // eb.setOptLevel(llvm::CodeGenOpt::Less); // -O1 // eb.setOptLevel(llvm::CodeGenOpt::Default); // -O2, -Os // eb.setOptLevel(llvm::CodeGenOpt::Aggressive); // -O3 llvm::TargetOptions target_options; target_options.NoFramePointerElim = true; // target_options.EnableFastISel = true; eb.setTargetOptions(target_options); g.tm = eb.selectTarget(); assert(g.tm && "failed to get a target machine"); g.engine = eb.create(g.tm); assert(g.engine && "engine creation failed?"); // g.engine->setObjectCache(new MyObjectCache()); g.i1 = llvm::Type::getInt1Ty(g.context); g.i8 = llvm::Type::getInt8Ty(g.context); g.i8_ptr = g.i8->getPointerTo(); g.i32 = llvm::Type::getInt32Ty(g.context); g.i64 = llvm::Type::getInt64Ty(g.context); g.void_ = llvm::Type::getVoidTy(g.context); g.double_ = llvm::Type::getDoubleTy(g.context); std::vector<llvm::JITEventListener*> listeners = makeJITEventListeners(); for (int i = 0; i < listeners.size(); i++) { g.jit_listeners.push_back(listeners[i]); g.engine->RegisterJITEventListener(listeners[i]); } llvm::JITEventListener* stackmap_listener = makeStackMapListener(); g.jit_listeners.push_back(stackmap_listener); g.engine->RegisterJITEventListener(stackmap_listener); llvm::JITEventListener* registry_listener = makeRegistryListener(); g.jit_listeners.push_back(registry_listener); g.engine->RegisterJITEventListener(registry_listener); llvm::JITEventListener* tracebacks_listener = makeTracebacksListener(); g.jit_listeners.push_back(tracebacks_listener); g.engine->RegisterJITEventListener(tracebacks_listener); if (SHOW_DISASM) { llvm::JITEventListener* listener = new PystonJITEventListener(); g.jit_listeners.push_back(listener); g.engine->RegisterJITEventListener(listener); } initGlobalFuncs(g); setupRuntime(); signal(SIGFPE, &handle_sigfpe); // There are some parts of llvm that are only configurable through command line args, // so construct a fake argc/argv pair and pass it to the llvm command line machinery: const char* llvm_args[] = { "fake_name", "--enable-stackmap-liveness", "--enable-patchpoint-liveness", // Enabling and debugging fast-isel: //"--fast-isel", //"--fast-isel-verbose", ////"--fast-isel-abort", #ifndef NDEBUG //"--debug-only=debug-ir", //"--debug-only=regalloc", //"--debug-only=stackmaps", #endif //"--print-after-all", //"--print-machineinstrs", }; int num_llvm_args = sizeof(llvm_args) / sizeof(llvm_args[0]); llvm::cl::ParseCommandLineOptions(num_llvm_args, llvm_args, "<you should never see this>\n"); }
void initCodegen() { llvm::InitializeNativeTarget(); llvm::InitializeNativeTargetAsmPrinter(); llvm::InitializeNativeTargetAsmParser(); g.stdlib_module = loadStdlib(); #if LLVMREV < 215967 llvm::EngineBuilder eb(new llvm::Module("empty_initial_module", g.context)); #else llvm::EngineBuilder eb(std::unique_ptr<llvm::Module>(new llvm::Module("empty_initial_module", g.context))); #endif #if LLVMREV < 216982 eb.setUseMCJIT(true); #endif eb.setEngineKind(llvm::EngineKind::JIT); // specify we only want the JIT, and not the interpreter fallback #if LLVMREV < 223183 eb.setMCJITMemoryManager(createMemoryManager().release()); #else eb.setMCJITMemoryManager(createMemoryManager()); #endif // eb.setOptLevel(llvm::CodeGenOpt::None); // -O0 // eb.setOptLevel(llvm::CodeGenOpt::Less); // -O1 // eb.setOptLevel(llvm::CodeGenOpt::Default); // -O2, -Os // eb.setOptLevel(llvm::CodeGenOpt::Aggressive); // -O3 llvm::TargetOptions target_options; target_options.NoFramePointerElim = true; // target_options.EnableFastISel = true; eb.setTargetOptions(target_options); // TODO enable this? should let us get better code: // eb.setMCPU(llvm::sys::getHostCPUName()); g.tm = eb.selectTarget(); assert(g.tm && "failed to get a target machine"); g.engine = eb.create(g.tm); assert(g.engine && "engine creation failed?"); if (ENABLE_JIT_OBJECT_CACHE) { g.object_cache = new PystonObjectCache; g.engine->setObjectCache(g.object_cache); } g.i1 = llvm::Type::getInt1Ty(g.context); g.i8 = llvm::Type::getInt8Ty(g.context); g.i8_ptr = g.i8->getPointerTo(); g.i32 = llvm::Type::getInt32Ty(g.context); g.i64 = llvm::Type::getInt64Ty(g.context); g.void_ = llvm::Type::getVoidTy(g.context); g.double_ = llvm::Type::getDoubleTy(g.context); std::vector<llvm::JITEventListener*> listeners = makeJITEventListeners(); for (int i = 0; i < listeners.size(); i++) { g.jit_listeners.push_back(listeners[i]); g.engine->RegisterJITEventListener(listeners[i]); } llvm::JITEventListener* stackmap_listener = makeStackMapListener(); g.jit_listeners.push_back(stackmap_listener); g.engine->RegisterJITEventListener(stackmap_listener); #if ENABLE_INTEL_JIT_EVENTS llvm::JITEventListener* intel_listener = llvm::JITEventListener::createIntelJITEventListener(); g.jit_listeners.push_back(intel_listener); g.engine->RegisterJITEventListener(intel_listener); #endif llvm::JITEventListener* registry_listener = makeRegistryListener(); g.jit_listeners.push_back(registry_listener); g.engine->RegisterJITEventListener(registry_listener); llvm::JITEventListener* tracebacks_listener = makeTracebacksListener(); g.jit_listeners.push_back(tracebacks_listener); g.engine->RegisterJITEventListener(tracebacks_listener); if (SHOW_DISASM) { #if LLVMREV < 216983 llvm::JITEventListener* listener = new DisassemblerJITEventListener(); g.jit_listeners.push_back(listener); g.engine->RegisterJITEventListener(listener); #else fprintf(stderr, "The LLVM disassembler has been removed\n"); abort(); #endif } initGlobalFuncs(g); setupRuntime(); // signal(SIGFPE, &handle_sigfpe); // signal(SIGUSR1, &handle_sigusr1); #if ENABLE_SAMPLING_PROFILER struct itimerval prof_timer; prof_timer.it_value.tv_sec = prof_timer.it_interval.tv_sec = 0; prof_timer.it_value.tv_usec = prof_timer.it_interval.tv_usec = 1000; signal(SIGPROF, handle_sigprof); setitimer(ITIMER_PROF, &prof_timer, NULL); #endif #ifdef INVESTIGATE_STAT_TIMER struct itimerval prof_timer; prof_timer.it_value.tv_sec = prof_timer.it_interval.tv_sec = 0; prof_timer.it_value.tv_usec = prof_timer.it_interval.tv_usec = 1000; signal(SIGPROF, handle_sigprof_investigate_stattimer); setitimer(ITIMER_PROF, &prof_timer, NULL); #endif // There are some parts of llvm that are only configurable through command line args, // so construct a fake argc/argv pair and pass it to the llvm command line machinery: std::vector<const char*> llvm_args = { "fake_name" }; llvm_args.push_back("--enable-patchpoint-liveness"); if (0) { // Enabling and debugging fast-isel: // llvm_args.push_back("--fast-isel"); // llvm_args.push_back("--fast-isel-verbose"); ////llvm_args.push_back("--fast-isel-abort"); } #ifndef NDEBUG // llvm_args.push_back("--debug-only=debug-ir"); // llvm_args.push_back("--debug-only=regalloc"); // llvm_args.push_back("--debug-only=stackmaps"); #endif // llvm_args.push_back("--time-passes"); // llvm_args.push_back("--print-after-all"); // llvm_args.push_back("--print-machineinstrs"); if (USE_REGALLOC_BASIC) llvm_args.push_back("--regalloc=basic"); llvm::cl::ParseCommandLineOptions(llvm_args.size(), &llvm_args[0], "<you should never see this>\n"); }