From a3d374eb57d57e9ae1ae6e9e16613490c63100c6 Mon Sep 17 00:00:00 2001 From: Wenyong Huang Date: Thu, 24 Sep 2020 11:21:20 +0800 Subject: [PATCH] Fix jit target arch not set issue and custom name section typo issue (#400) And set target machine's cpu to host cpu when creating JIT execution engine. Signed-off-by: Wenyong Huang wenyong.huang@intel.com --- core/iwasm/compilation/aot_llvm.c | 23 +++- core/iwasm/compilation/aot_llvm_extra.cpp | 147 ++++++++++++++++++++++ core/iwasm/compilation/iwasm_compl.cmake | 4 +- core/iwasm/interpreter/wasm_loader.c | 2 +- 4 files changed, 172 insertions(+), 4 deletions(-) create mode 100644 core/iwasm/compilation/aot_llvm_extra.cpp diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index cb024e5f9..6dea84524 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -997,6 +997,13 @@ get_target_arch_from_triple(const char *triple, char *arch_buf, uint32 buf_size) bh_assert(*triple == '-' || *triple == '\0'); } +LLVMBool +WAMRCreateMCJITCompilerForModule(LLVMExecutionEngineRef *OutJIT, + LLVMModuleRef M, + struct LLVMMCJITCompilerOptions *Options, + size_t SizeOfOptions, + char **OutError); + void LLVMAddPromoteMemoryToRegisterPass(LLVMPassManagerRef PM); AOTCompContext * @@ -1007,7 +1014,8 @@ aot_create_comp_context(AOTCompData *comp_data, /*LLVMTypeRef elem_types[8];*/ struct LLVMMCJITCompilerOptions jit_options; LLVMTargetRef target; - char *triple = NULL, *triple_norm, *arch, *abi, *cpu, *features, buf[128]; + char *triple = NULL, *triple_jit = NULL, *triple_norm, *arch, *abi; + char *cpu = NULL, *features, buf[128]; char *triple_norm_new = NULL, *cpu_new = NULL; char *err = NULL, *fp_round= "round.tonearest", *fp_exce = "fpexcept.strict"; char triple_buf[32] = {0}; @@ -1060,7 +1068,7 @@ aot_create_comp_context(AOTCompData *comp_data, jit_options.OptLevel = LLVMCodeGenLevelAggressive; jit_options.EnableFastISel = true; /*jit_options.CodeModel = LLVMCodeModelSmall;*/ - if (LLVMCreateMCJITCompilerForModule + if (WAMRCreateMCJITCompilerForModule (&comp_ctx->exec_engine, comp_ctx->module, &jit_options, sizeof(jit_options), &err) != 0) { if (err) { @@ -1078,6 +1086,17 @@ aot_create_comp_context(AOTCompData *comp_data, #else comp_ctx->enable_bound_check = false; #endif + + if (!(triple_jit = + LLVMGetTargetMachineTriple(comp_ctx->target_machine))) { + aot_set_last_error("can not get triple from the target machine"); + goto fail; + } + + /* Save target arch */ + get_target_arch_from_triple(triple_jit, comp_ctx->target_arch, + sizeof(comp_ctx->target_arch)); + LLVMDisposeMessage(triple_jit); } else { /* Create LLVM target machine */ diff --git a/core/iwasm/compilation/aot_llvm_extra.cpp b/core/iwasm/compilation/aot_llvm_extra.cpp new file mode 100644 index 000000000..895f29049 --- /dev/null +++ b/core/iwasm/compilation/aot_llvm_extra.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace llvm; + +extern "C" LLVMBool +WAMRCreateMCJITCompilerForModule(LLVMExecutionEngineRef *OutJIT, + LLVMModuleRef M, + LLVMMCJITCompilerOptions *PassedOptions, + size_t SizeOfPassedOptions, + char **OutError); + +extern "C" bool +aot_check_simd_compatibility(const char *arch_c_str, const char *cpu_c_str); + +LLVMBool +WAMRCreateMCJITCompilerForModule(LLVMExecutionEngineRef *OutJIT, + LLVMModuleRef M, + LLVMMCJITCompilerOptions *PassedOptions, + size_t SizeOfPassedOptions, + char **OutError) +{ + LLVMMCJITCompilerOptions options; + // If the user passed a larger sized options struct, then they were compiled + // against a newer LLVM. Tell them that something is wrong. + if (SizeOfPassedOptions > sizeof(options)) { + *OutError = strdup( + "Refusing to use options struct that is larger than my own; assuming " + "LLVM library mismatch."); + return 1; + } + + // Defend against the user having an old version of the API by ensuring that + // any fields they didn't see are cleared. We must defend against fields being + // set to the bitwise equivalent of zero, and assume that this means "do the + // default" as if that option hadn't been available. + LLVMInitializeMCJITCompilerOptions(&options, sizeof(options)); + memcpy(&options, PassedOptions, SizeOfPassedOptions); + + TargetOptions targetOptions; + targetOptions.EnableFastISel = options.EnableFastISel; + std::unique_ptr Mod(unwrap(M)); + + if (Mod) { + // Set function attribute "frame-pointer" based on + // NoFramePointerElim. + for (auto &F : *Mod) { + auto Attrs = F.getAttributes(); + StringRef Value = options.NoFramePointerElim ? "all" : "none"; + Attrs = Attrs.addAttribute(F.getContext(), AttributeList::FunctionIndex, + "frame-pointer", Value); + F.setAttributes(Attrs); + } + } + + std::string Error; + bool JIT; + char *host_cpu = LLVMGetHostCPUName(); + + if (!host_cpu) { + *OutError = NULL; + return false; + } + + std::string mcpu(host_cpu); + LLVMDisposeMessage(host_cpu); + + EngineBuilder builder(std::move(Mod)); + builder.setEngineKind(EngineKind::JIT) + .setErrorStr(&Error) + .setMCPU(mcpu) + .setOptLevel((CodeGenOpt::Level)options.OptLevel) + .setTargetOptions(targetOptions); + if (Optional CM = unwrap(options.CodeModel, JIT)) + builder.setCodeModel(*CM); + if (options.MCJMM) + builder.setMCJITMemoryManager( + std::unique_ptr(unwrap(options.MCJMM))); + if (ExecutionEngine *JIT = builder.create()) { + *OutJIT = wrap(JIT); + return 0; + } + *OutError = strdup(Error.c_str()); + return 1; +} + +bool +aot_check_simd_compatibility(const char *arch_c_str, const char *cpu_c_str) +{ +#if WASM_ENABLE_SIMD != 0 + if (!arch_c_str || !cpu_c_str) { + return false; + } + + llvm::SmallVector targetAttributes; + llvm::Triple targetTriple(arch_c_str, "", ""); + llvm::TargetMachine *targetMachine = llvm::EngineBuilder().selectTarget( + targetTriple, "", std::string(cpu_c_str), targetAttributes); + if (targetMachine == nullptr) { + return false; + } + + const llvm::Triple::ArchType targetArch = + targetMachine->getTargetTriple().getArch(); + const llvm::MCSubtargetInfo *subTargetInfo = + targetMachine->getMCSubtargetInfo(); + if (subTargetInfo == nullptr) { + return false; + } + + if (targetArch == llvm::Triple::x86_64) { + return subTargetInfo->checkFeatures("+sse4.1"); + } + else if (targetArch == llvm::Triple::aarch64) { + return subTargetInfo->checkFeatures("+neon"); + } + else { + return false; + } +#else + (void)arch_c_str; + (void)cpu_c_str; + return true; +#endif /* WASM_ENABLE_SIMD */ +} + diff --git a/core/iwasm/compilation/iwasm_compl.cmake b/core/iwasm/compilation/iwasm_compl.cmake index 36efd335e..09b3b9ecc 100644 --- a/core/iwasm/compilation/iwasm_compl.cmake +++ b/core/iwasm/compilation/iwasm_compl.cmake @@ -2,7 +2,9 @@ set (IWASM_COMPL_DIR ${CMAKE_CURRENT_LIST_DIR}) include_directories(${IWASM_COMPL_DIR}) -file (GLOB_RECURSE source_all ${IWASM_COMPL_DIR}/*.c) +file (GLOB_RECURSE source_all + ${IWASM_COMPL_DIR}/*.c + ${IWASM_COMPL_DIR}/*.cpp) set (IWASM_COMPL_SOURCE ${source_all}) diff --git a/core/iwasm/interpreter/wasm_loader.c b/core/iwasm/interpreter/wasm_loader.c index e99f04e8a..ac8d15500 100644 --- a/core/iwasm/interpreter/wasm_loader.c +++ b/core/iwasm/interpreter/wasm_loader.c @@ -2394,7 +2394,7 @@ fail: #if WASM_ENABLE_CUSTOM_NAME_SECTION != 0 static bool -handle_name_section(const uint8 *buf, const uint8 *buf_end,Ø +handle_name_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module, char *error_buf, uint32 error_buf_size) {