/* unit -> bool */ CAMLprim value llvm_ee_initialize(value Unit) { LLVMLinkInMCJIT(); return Val_bool(!LLVMInitializeNativeTarget() && !LLVMInitializeNativeAsmParser() && !LLVMInitializeNativeAsmPrinter()); }
bool codegen_llvm_init() { LLVMLinkInMCJIT(); LLVMInitializeNativeTarget(); LLVMInitializeAllTargets(); LLVMInitializeAllTargetMCs(); LLVMInitializeAllTargetInfos(); LLVMInitializeAllAsmPrinters(); LLVMInitializeAllAsmParsers(); LLVMEnablePrettyStackTrace(); LLVMInstallFatalErrorHandler(fatal_error); LLVMPassRegistryRef passreg = LLVMGetGlobalPassRegistry(); LLVMInitializeCore(passreg); LLVMInitializeTransformUtils(passreg); LLVMInitializeScalarOpts(passreg); LLVMInitializeObjCARCOpts(passreg); LLVMInitializeVectorization(passreg); LLVMInitializeInstCombine(passreg); LLVMInitializeIPO(passreg); LLVMInitializeInstrumentation(passreg); LLVMInitializeAnalysis(passreg); LLVMInitializeIPA(passreg); LLVMInitializeCodeGen(passreg); LLVMInitializeTarget(passreg); return true; }
int main(int argc, char const *argv[]) { LLVMModuleRef mod = LLVMModuleCreateWithName("my_module"); LLVMTypeRef param_types[] = { LLVMInt32Type(), LLVMInt32Type() }; LLVMTypeRef ret_type = LLVMFunctionType(LLVMInt32Type(), param_types, 2, 0); LLVMValueRef sum = LLVMAddFunction(mod, "sum", ret_type); LLVMBasicBlockRef entry = LLVMAppendBasicBlock(sum, "entry"); LLVMBuilderRef builder = LLVMCreateBuilder(); LLVMPositionBuilderAtEnd(builder, entry); LLVMValueRef tmp = LLVMBuildAdd(builder, LLVMGetParam(sum, 0), LLVMGetParam(sum, 1), "tmp"); LLVMBuildRet(builder, tmp); char *error = NULL; LLVMVerifyModule(mod, LLVMAbortProcessAction, &error); LLVMDisposeMessage(error); LLVMExecutionEngineRef engine; error = NULL; LLVMLinkInMCJIT(); LLVMInitializeNativeAsmPrinter(); LLVMInitializeNativeTarget(); if (LLVMCreateExecutionEngineForModule(&engine, mod, &error) != 0) { fprintf(stderr, "failed to create execution engine\n"); abort(); } if (error) { fprintf(stderr, "error: %s\n", error); LLVMDisposeMessage(error); exit(EXIT_FAILURE); } if (argc < 3) { fprintf(stderr, "usage: %s x y\n", argv[0]); exit(EXIT_FAILURE); } long long x = strtoll(argv[1], NULL, 10); long long y = strtoll(argv[2], NULL, 10); LLVMGenericValueRef args[] = { LLVMCreateGenericValueOfInt(LLVMInt32Type(), x, 0), LLVMCreateGenericValueOfInt(LLVMInt32Type(), y, 0) }; LLVMGenericValueRef res = LLVMRunFunction(engine, sum, 2, args); printf("%d\n", (int)LLVMGenericValueToInt(res, 0)); // Write out bitcode to file if (LLVMWriteBitcodeToFile(mod, "sum.bc") != 0) { fprintf(stderr, "error writing bitcode to file, skipping\n"); } LLVMDisposeBuilder(builder); LLVMDisposeExecutionEngine(engine); }
void lp_build_init(void) { if (gallivm_initialized) return; #ifdef DEBUG gallivm_debug = debug_get_option_gallivm_debug(); #endif lp_set_target_options(); #if USE_MCJIT LLVMLinkInMCJIT(); #else LLVMLinkInJIT(); #endif util_cpu_detect(); /* AMD Bulldozer AVX's throughput is the same as SSE2; and because using * 8-wide vector needs more floating ops than 4-wide (due to padding), it is * actually more efficient to use 4-wide vectors on this processor. * * See also: * - http://www.anandtech.com/show/4955/the-bulldozer-review-amd-fx8150-tested/2 */ if (HAVE_AVX && util_cpu_caps.has_avx && util_cpu_caps.has_intel) { lp_native_vector_width = 256; } else { /* Leave it at 128, even when no SIMD extensions are available. * Really needs to be a multiple of 128 so can fit 4 floats. */ lp_native_vector_width = 128; } lp_native_vector_width = debug_get_num_option("LP_NATIVE_VECTOR_WIDTH", lp_native_vector_width); gallivm_initialized = TRUE; #if 0 /* For simulating less capable machines */ util_cpu_caps.has_sse3 = 0; util_cpu_caps.has_ssse3 = 0; util_cpu_caps.has_sse4_1 = 0; #endif }
extern "C" JSC::LLVMAPI* initializeAndGetJSCLLVMAPI(void (*callback)(const char*, ...)) { g_llvmTrapCallback = callback; LLVMInstallFatalErrorHandler(llvmCrash); if (!LLVMStartMultithreaded()) callback("Could not start LLVM multithreading"); LLVMLinkInMCJIT(); // You think you want to call LLVMInitializeNativeTarget()? Think again. This presumes that // LLVM was ./configured correctly, which won't be the case in cross-compilation situations. #if CPU(X86_64) LLVMInitializeX86TargetInfo(); LLVMInitializeX86Target(); LLVMInitializeX86TargetMC(); LLVMInitializeX86AsmPrinter(); LLVMInitializeX86Disassembler(); #elif CPU(ARM64) LLVMInitializeARM64TargetInfo(); LLVMInitializeARM64Target(); LLVMInitializeARM64TargetMC(); LLVMInitializeARM64AsmPrinter(); LLVMInitializeARM64Disassembler(); #else UNREACHABLE_FOR_PLATFORM(); #endif const char* args[] = { "llvmForJSC.dylib", "-enable-stackmap-liveness=true", "-enable-patchpoint-liveness=true" }; llvm::cl::ParseCommandLineOptions(sizeof(args) / sizeof(const char*), args); JSC::LLVMAPI* result = new JSC::LLVMAPI; #define LLVM_API_FUNCTION_ASSIGNMENT(returnType, name, signature) \ result->name = LLVM##name; FOR_EACH_LLVM_API_FUNCTION(LLVM_API_FUNCTION_ASSIGNMENT); #undef LLVM_API_FUNCTION_ASSIGNMENT return result; }
void lp_build_init(void) { if (gallivm_initialized) return; #ifdef DEBUG gallivm_debug = debug_get_option_gallivm_debug(); #endif lp_set_target_options(); #if USE_MCJIT LLVMLinkInMCJIT(); #else LLVMLinkInJIT(); #endif util_cpu_detect(); if (HAVE_AVX && util_cpu_caps.has_avx) { lp_native_vector_width = 256; } else { /* Leave it at 128, even when no SIMD extensions are available. * Really needs to be a multiple of 128 so can fit 4 floats. */ lp_native_vector_width = 128; } lp_native_vector_width = debug_get_num_option("LP_NATIVE_VECTOR_WIDTH", lp_native_vector_width); gallivm_initialized = TRUE; #if 0 /* For simulating less capable machines */ util_cpu_caps.has_sse3 = 0; util_cpu_caps.has_ssse3 = 0; util_cpu_caps.has_sse4_1 = 0; #endif }
extern "C" JSC::LLVMAPI* initializeAndGetJSCLLVMAPI(void (*callback)(const char*, ...)) { g_llvmTrapCallback = callback; LLVMInstallFatalErrorHandler(llvmCrash); if (!LLVMStartMultithreaded()) callback("Could not start LLVM multithreading"); LLVMLinkInMCJIT(); LLVMInitializeNativeTarget(); LLVMInitializeX86AsmPrinter(); LLVMInitializeX86Disassembler(); JSC::LLVMAPI* result = new JSC::LLVMAPI; #define LLVM_API_FUNCTION_ASSIGNMENT(returnType, name, signature) \ result->name = LLVM##name; FOR_EACH_LLVM_API_FUNCTION(LLVM_API_FUNCTION_ASSIGNMENT); #undef LLVM_API_FUNCTION_ASSIGNMENT return result; }
void init_core(void) { LLVMLinkInMCJIT(); LLVMInitializeNativeTarget(); LLVMInitializeNativeAsmPrinter(); LLVMInitializeNativeAsmParser(); llvm_module_tag = scm_make_smob_type("llvm_module", sizeof(struct llvm_module_t)); scm_set_smob_free(llvm_module_tag, free_llvm_module); llvm_function_tag = scm_make_smob_type("llvm_function", sizeof(struct llvm_function_t)); scm_set_smob_free(llvm_function_tag, free_llvm_function); llvm_value_tag = scm_make_smob_type("llvm_value", sizeof(struct llvm_value_t)); llvm_basic_block_tag = scm_make_smob_type("llvm_basic_block", sizeof(struct llvm_basic_block_t)); scm_c_define("llvm-bool" , scm_from_int(SCM_FOREIGN_TYPE_LAST + 1)); scm_c_define("llvm-void" , scm_from_int(SCM_FOREIGN_TYPE_VOID )); scm_c_define("llvm-float" , scm_from_int(SCM_FOREIGN_TYPE_FLOAT )); scm_c_define("llvm-double", scm_from_int(SCM_FOREIGN_TYPE_DOUBLE )); scm_c_define("llvm-uint8" , scm_from_int(SCM_FOREIGN_TYPE_UINT8 )); scm_c_define("llvm-int8" , scm_from_int(SCM_FOREIGN_TYPE_INT8 )); scm_c_define("llvm-uint16", scm_from_int(SCM_FOREIGN_TYPE_UINT16 )); scm_c_define("llvm-int16" , scm_from_int(SCM_FOREIGN_TYPE_INT16 )); scm_c_define("llvm-uint32", scm_from_int(SCM_FOREIGN_TYPE_UINT32 )); scm_c_define("llvm-int32" , scm_from_int(SCM_FOREIGN_TYPE_INT32 )); scm_c_define("llvm-uint64", scm_from_int(SCM_FOREIGN_TYPE_UINT64 )); scm_c_define("llvm-int64" , scm_from_int(SCM_FOREIGN_TYPE_INT64 )); scm_c_define("llvm-int-slt" , scm_from_int(LLVMIntSLT)); scm_c_define("llvm-int-ult" , scm_from_int(LLVMIntULT)); scm_c_define("llvm-int-sle" , scm_from_int(LLVMIntSLE)); scm_c_define("llvm-int-ule" , scm_from_int(LLVMIntULE)); scm_c_define("llvm-int-ugt" , scm_from_int(LLVMIntUGT)); scm_c_define("llvm-int-sgt" , scm_from_int(LLVMIntSGT)); scm_c_define("llvm-int-uge" , scm_from_int(LLVMIntUGE)); scm_c_define("llvm-int-sge" , scm_from_int(LLVMIntSGE)); scm_c_define("llvm-int-eq" , scm_from_int(LLVMIntEQ )); scm_c_define("llvm-int-ne" , scm_from_int(LLVMIntNE )); scm_c_define("llvm-real-lt" , scm_from_int(LLVMRealOLT)); scm_c_define("llvm-real-le" , scm_from_int(LLVMRealOLE)); scm_c_define("llvm-real-gt" , scm_from_int(LLVMRealOGT)); scm_c_define("llvm-real-ge" , scm_from_int(LLVMRealOGE)); scm_c_define("llvm-real-eq" , scm_from_int(LLVMRealOEQ)); scm_c_define("llvm-real-ne" , scm_from_int(LLVMRealONE)); scm_c_define_gsubr("make-llvm-module-base" , 0, 0, 0, SCM_FUNC(make_llvm_module_base )); scm_c_define_gsubr("llvm-module-destroy" , 1, 0, 0, SCM_FUNC(llvm_module_destroy )); scm_c_define_gsubr("llvm-dump-module" , 1, 0, 0, SCM_FUNC(llvm_dump_module )); scm_c_define_gsubr("make-llvm-function" , 4, 0, 0, SCM_FUNC(make_llvm_function )); scm_c_define_gsubr("llvm-function-destroy" , 1, 0, 0, SCM_FUNC(llvm_function_destroy )); scm_c_define_gsubr("llvm-function-return" , 2, 0, 0, SCM_FUNC(llvm_function_return )); scm_c_define_gsubr("llvm-function-return-void" , 1, 0, 0, SCM_FUNC(llvm_function_return_void )); scm_c_define_gsubr("llvm-compile-module" , 1, 0, 0, SCM_FUNC(llvm_compile_module )); scm_c_define_gsubr("llvm-get-function-address" , 2, 0, 0, SCM_FUNC(llvm_get_function_address )); scm_c_define_gsubr("llvm-verify-module" , 1, 0, 0, SCM_FUNC(llvm_verify_module )); scm_c_define_gsubr("make-llvm-basic-block" , 2, 0, 0, SCM_FUNC(make_llvm_basic_block )); scm_c_define_gsubr("llvm-position-builder-at-end", 2, 0, 0, SCM_FUNC(llvm_position_builder_at_end)); scm_c_define_gsubr("llvm-build-branch" , 2, 0, 0, SCM_FUNC(llvm_build_branch )); scm_c_define_gsubr("llvm-build-cond-branch" , 4, 0, 0, SCM_FUNC(llvm_build_cond_branch )); scm_c_define_gsubr("llvm-build-select" , 4, 0, 0, SCM_FUNC(llvm_build_select )); scm_c_define_gsubr("make-llvm-constant" , 2, 0, 0, SCM_FUNC(make_llvm_constant )); scm_c_define_gsubr("llvm-get-type" , 1, 0, 0, SCM_FUNC(llvm_get_type )); scm_c_define_gsubr("llvm-build-load" , 3, 0, 0, SCM_FUNC(llvm_build_load )); scm_c_define_gsubr("llvm-build-store" , 4, 0, 0, SCM_FUNC(llvm_build_store )); scm_c_define_gsubr("llvm-get-param" , 2, 0, 0, SCM_FUNC(llvm_get_param )); scm_c_define_gsubr("llvm-build-neg" , 2, 0, 0, SCM_FUNC(llvm_build_neg )); scm_c_define_gsubr("llvm-build-fneg" , 2, 0, 0, SCM_FUNC(llvm_build_fneg )); scm_c_define_gsubr("llvm-build-not" , 2, 0, 0, SCM_FUNC(llvm_build_not )); scm_c_define_gsubr("llvm-build-add" , 3, 0, 0, SCM_FUNC(llvm_build_add )); scm_c_define_gsubr("llvm-build-fadd" , 3, 0, 0, SCM_FUNC(llvm_build_fadd )); scm_c_define_gsubr("llvm-build-sub" , 3, 0, 0, SCM_FUNC(llvm_build_sub )); scm_c_define_gsubr("llvm-build-fsub" , 3, 0, 0, SCM_FUNC(llvm_build_fsub )); scm_c_define_gsubr("llvm-build-mul" , 3, 0, 0, SCM_FUNC(llvm_build_mul )); scm_c_define_gsubr("llvm-build-fmul" , 3, 0, 0, SCM_FUNC(llvm_build_fmul )); scm_c_define_gsubr("llvm-build-udiv" , 3, 0, 0, SCM_FUNC(llvm_build_udiv )); scm_c_define_gsubr("llvm-build-sdiv" , 3, 0, 0, SCM_FUNC(llvm_build_sdiv )); scm_c_define_gsubr("llvm-build-fdiv" , 3, 0, 0, SCM_FUNC(llvm_build_fdiv )); scm_c_define_gsubr("llvm-build-shl" , 3, 0, 0, SCM_FUNC(llvm_build_shl )); scm_c_define_gsubr("llvm-build-lshr" , 3, 0, 0, SCM_FUNC(llvm_build_lshr )); scm_c_define_gsubr("llvm-build-ashr" , 3, 0, 0, SCM_FUNC(llvm_build_ashr )); scm_c_define_gsubr("llvm-build-urem" , 3, 0, 0, SCM_FUNC(llvm_build_urem )); scm_c_define_gsubr("llvm-build-srem" , 3, 0, 0, SCM_FUNC(llvm_build_srem )); scm_c_define_gsubr("llvm-build-frem" , 3, 0, 0, SCM_FUNC(llvm_build_frem )); scm_c_define_gsubr("llvm-build-and" , 3, 0, 0, SCM_FUNC(llvm_build_and )); scm_c_define_gsubr("llvm-build-or" , 3, 0, 0, SCM_FUNC(llvm_build_or )); scm_c_define_gsubr("llvm-build-xor" , 3, 0, 0, SCM_FUNC(llvm_build_xor )); scm_c_define_gsubr("llvm-build-trunc" , 3, 0, 0, SCM_FUNC(llvm_build_trunc )); scm_c_define_gsubr("llvm-build-sext" , 3, 0, 0, SCM_FUNC(llvm_build_sext )); scm_c_define_gsubr("llvm-build-zext" , 3, 0, 0, SCM_FUNC(llvm_build_zext )); scm_c_define_gsubr("llvm-build-fp-cast" , 3, 0, 0, SCM_FUNC(llvm_build_fp_cast )); scm_c_define_gsubr("llvm-build-fp-to-si" , 3, 0, 0, SCM_FUNC(llvm_build_fp_to_si )); scm_c_define_gsubr("llvm-build-fp-to-ui" , 3, 0, 0, SCM_FUNC(llvm_build_fp_to_ui )); scm_c_define_gsubr("llvm-build-si-to-fp" , 3, 0, 0, SCM_FUNC(llvm_build_si_to_fp )); scm_c_define_gsubr("llvm-build-ui-to-fp" , 3, 0, 0, SCM_FUNC(llvm_build_ui_to_fp )); scm_c_define_gsubr("llvm-build-call" , 6, 0, 0, SCM_FUNC(llvm_build_call )); scm_c_define_gsubr("llvm-build-integer-cmp" , 4, 0, 0, SCM_FUNC(llvm_build_integer_cmp )); scm_c_define_gsubr("llvm-build-float-cmp" , 4, 0, 0, SCM_FUNC(llvm_build_float_cmp )); scm_c_define_gsubr("llvm-build-alloca" , 2, 0, 0, SCM_FUNC(llvm_build_alloca )); scm_c_define_gsubr("llvm-build-phi" , 2, 0, 0, SCM_FUNC(llvm_build_phi )); scm_c_define_gsubr("llvm-add-incoming" , 3, 0, 0, SCM_FUNC(llvm_add_incoming )); }
jit_compiler::jit_compiler(std::unique_ptr<llvm::Module>&& _module, std::unordered_map<std::string, std::uintptr_t>&& table) { verify(HERE), s_memory; std::string result; const auto module_ptr = _module.get(); // Initialization llvm::InitializeNativeTarget(); llvm::InitializeNativeTargetAsmPrinter(); LLVMLinkInMCJIT(); const auto _cpu = llvm::sys::getHostCPUName(); m_engine.reset(llvm::EngineBuilder(std::move(_module)) .setErrorStr(&result) .setMCJITMemoryManager(std::make_unique<MemoryManager>(std::move(table))) .setOptLevel(llvm::CodeGenOpt::Aggressive) .setCodeModel((u64)s_memory <= 0x60000000 ? llvm::CodeModel::Small : llvm::CodeModel::Large) // TODO .setMCPU(_cpu == "skylake" ? "haswell" : _cpu) .create()); if (!m_engine) { fmt::throw_exception("LLVM: Failed to create ExecutionEngine: %s", result); } m_engine->setProcessAllSections(true); // ??? m_engine->RegisterJITEventListener(&s_listener); m_engine->finalizeObject(); for (auto& func : module_ptr->functions()) { if (!func.empty()) { const std::string& name = func.getName(); // Register compiled function m_map[name] = m_engine->getFunctionAddress(name); } // Delete IR to lower memory consumption func.deleteBody(); } #ifdef _WIN32 // Register .xdata UNWIND_INFO (.pdata section is empty for some reason) std::set<u64> func_set; for (const auto& pair : m_map) { func_set.emplace(pair.second); } const u64 base = (u64)s_memory; const u8* bits = s_unwind_info; s_unwind.clear(); s_unwind.reserve(m_map.size()); for (const u64 addr : func_set) { // Find next function address const auto _next = func_set.upper_bound(addr); const u64 next = _next != func_set.end() ? *_next : (u64)s_code_addr + s_code_size; // Generate RUNTIME_FUNCTION record RUNTIME_FUNCTION uw; uw.BeginAddress = static_cast<u32>(addr - base); uw.EndAddress = static_cast<u32>(next - base); uw.UnwindData = static_cast<u32>((u64)bits - base); s_unwind.emplace_back(uw); // Parse .xdata UNWIND_INFO record const u8 flags = *bits++; // Version and flags const u8 prolog = *bits++; // Size of prolog const u8 count = *bits++; // Count of unwind codes const u8 frame = *bits++; // Frame Reg + Off bits += ::align(std::max<u8>(1, count), 2) * sizeof(u16); // UNWIND_CODE array if (flags != 1) { // Can't happen for trivial code LOG_ERROR(GENERAL, "LLVM: unsupported UNWIND_INFO version/flags (0x%02x)", flags); break; } LOG_TRACE(GENERAL, "LLVM: .xdata at 0x%llx: function 0x%x..0x%x: p0x%02x, c0x%02x, f0x%02x", uw.UnwindData + base, uw.BeginAddress + base, uw.EndAddress + base, prolog, count, frame); } if (s_unwind_info + s_unwind_size != bits) { LOG_ERROR(GENERAL, "LLVM: .xdata analysis failed! (%p != %p)", s_unwind_info + s_unwind_size, bits); } else if (!RtlAddFunctionTable(s_unwind.data(), (DWORD)s_unwind.size(), base)) { LOG_ERROR(GENERAL, "RtlAddFunctionTable(%p) failed! Error %u", s_unwind_info, GetLastError()); } else { LOG_SUCCESS(GENERAL, "LLVM: UNWIND_INFO registered (%p, size=0x%llx)", s_unwind_info, s_unwind_size); } #endif }
int main(int c, char **v) { LLVMContextRef *contexts; LLVMModuleRef *modules; char *error; const char *mode = "opt"; const char **filenames; unsigned numFiles; unsigned i; bool moreOptions; static int verboseFlag = 0; static int timingFlag = 0; static int disassembleFlag = 0; bool manyContexts = true; double beforeAll; if (c == 1) usage(); moreOptions = true; while (moreOptions) { static struct option longOptions[] = { {"verbose", no_argument, &verboseFlag, 1}, {"timing", no_argument, &timingFlag, 1}, {"disassemble", no_argument, &disassembleFlag, 1}, {"mode", required_argument, 0, 0}, {"contexts", required_argument, 0, 0}, {"help", no_argument, 0, 0} }; int optionIndex; int optionValue; optionValue = getopt_long(c, v, "", longOptions, &optionIndex); switch (optionValue) { case -1: moreOptions = false; break; case 0: { const char* thisOption = longOptions[optionIndex].name; if (!strcmp(thisOption, "help")) usage(); if (!strcmp(thisOption, "contexts")) { if (!strcasecmp(optarg, "one")) manyContexts = false; else if (!strcasecmp(optarg, "many")) manyContexts = true; else { fprintf(stderr, "Invalid argument for --contexts.\n"); exit(1); } break; } if (!strcmp(thisOption, "mode")) { mode = strdup(optarg); break; } break; } case '?': exit(0); break; default: printf("optionValue = %d\n", optionValue); abort(); break; } } LLVMLinkInMCJIT(); LLVMInitializeNativeTarget(); LLVMInitializeX86AsmPrinter(); LLVMInitializeX86Disassembler(); filenames = (const char **)(v + optind); numFiles = c - optind; contexts = malloc(sizeof(LLVMContextRef) * numFiles); modules = malloc(sizeof(LLVMModuleRef) * numFiles); if (manyContexts) { for (i = 0; i < numFiles; ++i) contexts[i] = LLVMContextCreate(); } else { LLVMContextRef context = LLVMContextCreate(); for (i = 0; i < numFiles; ++i) contexts[i] = context; } for (i = 0; i < numFiles; ++i) { LLVMMemoryBufferRef buffer; const char* filename = filenames[i]; if (LLVMCreateMemoryBufferWithContentsOfFile(filename, &buffer, &error)) { fprintf(stderr, "Error reading file %s: %s\n", filename, error); exit(1); } if (LLVMParseBitcodeInContext(contexts[i], buffer, modules + i, &error)) { fprintf(stderr, "Error parsing file %s: %s\n", filename, error); exit(1); } LLVMDisposeMemoryBuffer(buffer); if (verboseFlag) { printf("Module #%u (%s) after parsing:\n", i, filename); LLVMDumpModule(modules[i]); } } if (verboseFlag) printf("Generating code for modules...\n"); if (timingFlag) beforeAll = currentTime(); for (i = 0; i < numFiles; ++i) { LLVMModuleRef module; LLVMExecutionEngineRef engine; struct LLVMMCJITCompilerOptions options; LLVMValueRef value; LLVMPassManagerRef functionPasses = 0; LLVMPassManagerRef modulePasses = 0; double before; if (timingFlag) before = currentTime(); module = modules[i]; LLVMInitializeMCJITCompilerOptions(&options, sizeof(options)); options.OptLevel = 2; options.EnableFastISel = 0; options.MCJMM = LLVMCreateSimpleMCJITMemoryManager( 0, mmAllocateCodeSection, mmAllocateDataSection, mmApplyPermissions, mmDestroy); if (LLVMCreateMCJITCompilerForModule(&engine, module, &options, sizeof(options), &error)) { fprintf(stderr, "Error building MCJIT: %s\n", error); exit(1); } if (!strcasecmp(mode, "simple")) { modulePasses = LLVMCreatePassManager(); LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), modulePasses); LLVMAddConstantPropagationPass(modulePasses); LLVMAddInstructionCombiningPass(modulePasses); LLVMAddPromoteMemoryToRegisterPass(modulePasses); LLVMAddBasicAliasAnalysisPass(modulePasses); LLVMAddTypeBasedAliasAnalysisPass(modulePasses); LLVMAddGVNPass(modulePasses); LLVMAddCFGSimplificationPass(modulePasses); LLVMRunPassManager(modulePasses, module); } else if (!strcasecmp(mode, "opt")) { LLVMPassManagerBuilderRef passBuilder; passBuilder = LLVMPassManagerBuilderCreate(); LLVMPassManagerBuilderSetOptLevel(passBuilder, 2); LLVMPassManagerBuilderSetSizeLevel(passBuilder, 0); functionPasses = LLVMCreateFunctionPassManagerForModule(module); modulePasses = LLVMCreatePassManager(); LLVMAddTargetData(LLVMGetExecutionEngineTargetData(engine), modulePasses); LLVMPassManagerBuilderPopulateFunctionPassManager(passBuilder, functionPasses); LLVMPassManagerBuilderPopulateModulePassManager(passBuilder, modulePasses); LLVMPassManagerBuilderDispose(passBuilder); LLVMInitializeFunctionPassManager(functionPasses); for (value = LLVMGetFirstFunction(module); value; value = LLVMGetNextFunction(value)) LLVMRunFunctionPassManager(functionPasses, value); LLVMFinalizeFunctionPassManager(functionPasses); LLVMRunPassManager(modulePasses, module); } else { fprintf(stderr, "Bad optimization mode: %s.\n", mode); fprintf(stderr, "Valid modes are: \"simple\" or \"opt\".\n"); exit(1); } if (verboseFlag) { printf("Module #%d (%s) after optimization:\n", i, filenames[i]); LLVMDumpModule(module); } for (value = LLVMGetFirstFunction(module); value; value = LLVMGetNextFunction(value)) { if (LLVMIsDeclaration(value)) continue; LLVMGetPointerToGlobal(engine, value); } if (functionPasses) LLVMDisposePassManager(functionPasses); if (modulePasses) LLVMDisposePassManager(modulePasses); LLVMDisposeExecutionEngine(engine); if (timingFlag) { double after = currentTime(); printf("Module #%d (%s) took %lf ms.\n", i, filenames[i], (after - before) * 1000); } } if (timingFlag) { double after = currentTime(); printf("Compilation took a total of %lf ms.\n", (after - beforeAll) * 1000); } if (disassembleFlag) { LLVMDisasmContextRef disassembler; struct MemorySection *section; disassembler = LLVMCreateDisasm("x86_64-apple-darwin", 0, 0, 0, symbolLookupCallback); if (!disassembler) { fprintf(stderr, "Error building disassembler.\n"); exit(1); } for (section = sectionHead; section; section = section->next) { printf("Disassembly for section %p:\n", section); char pcString[20]; char instructionString[1000]; uint8_t *pc; uint8_t *end; pc = section->start; end = pc + section->size; while (pc < end) { snprintf( pcString, sizeof(pcString), "0x%lx", (unsigned long)(uintptr_t)pc); size_t instructionSize = LLVMDisasmInstruction( disassembler, pc, end - pc, (uintptr_t)pc, instructionString, sizeof(instructionString)); if (!instructionSize) snprintf(instructionString, sizeof(instructionString), ".byte 0x%02x", *pc++); else pc += instructionSize; printf(" %16s: %s\n", pcString, instructionString); } } } return 0; }