[PATCH] Enable using llvm jitlink as an alternative llvm jit linker of old Rtdyld. - Mailing list pgsql-hackers
From | Alex Fan |
---|---|
Subject | [PATCH] Enable using llvm jitlink as an alternative llvm jit linker of old Rtdyld. |
Date | |
Msg-id | 20220829074622.2474104-1-alex.fan.q@gmail.com Whole thread Raw |
Responses |
Re: [PATCH] Enable using llvm jitlink as an alternative llvm jit linker of old Rtdyld.
|
List | pgsql-hackers |
This brings the bonus of support jitting on riscv64 (included in this patch) and other platforms Rtdyld doesn't support, e.g. windows COFF. Currently, llvm doesn't expose jitlink (ObjectLinkingLayer) via C API, so a wrapper is added. This also adds minor llvm 15 compat fix that is needed --- config/llvm.m4 | 1 + src/backend/jit/llvm/llvmjit.c | 67 +++++++++++++++++++++++++-- src/backend/jit/llvm/llvmjit_wrap.cpp | 35 ++++++++++++++ src/include/jit/llvmjit.h | 9 ++++ 4 files changed, 108 insertions(+), 4 deletions(-) diff --git a/config/llvm.m4 b/config/llvm.m4 index 3a75cd8b4d..a31b8b304a 100644 --- a/config/llvm.m4 +++ b/config/llvm.m4 @@ -75,6 +75,7 @@ AC_DEFUN([PGAC_LLVM_SUPPORT], engine) pgac_components="$pgac_components $pgac_component";; debuginfodwarf) pgac_components="$pgac_components $pgac_component";; orcjit) pgac_components="$pgac_components $pgac_component";; + jitlink) pgac_components="$pgac_components $pgac_component";; passes) pgac_components="$pgac_components $pgac_component";; native) pgac_components="$pgac_components $pgac_component";; perfjitevents) pgac_components="$pgac_components $pgac_component";; diff --git a/src/backend/jit/llvm/llvmjit.c b/src/backend/jit/llvm/llvmjit.c index 6c72d43beb..d8b840da8c 100644 --- a/src/backend/jit/llvm/llvmjit.c +++ b/src/backend/jit/llvm/llvmjit.c @@ -229,6 +229,11 @@ llvm_release_context(JitContext *context) LLVMModuleRef llvm_mutable_module(LLVMJitContext *context) { +#ifdef __riscv + const char* abiname; + const char* target_abi = "target-abi"; + LLVMMetadataRef abi_metadata; +#endif llvm_assert_in_fatal_section(); /* @@ -241,6 +246,40 @@ llvm_mutable_module(LLVMJitContext *context) context->module = LLVMModuleCreateWithName("pg"); LLVMSetTarget(context->module, llvm_triple); LLVMSetDataLayout(context->module, llvm_layout); +#ifdef __riscv +#if __riscv_xlen == 64 +#ifdef __riscv_float_abi_double + abiname = "lp64d"; +#elif defined(__riscv_float_abi_single) + abiname = "lp64f"; +#else + abiname = "lp64"; +#endif +#elif __riscv_xlen == 32 +#ifdef __riscv_float_abi_double + abiname = "ilp32d"; +#elif defined(__riscv_float_abi_single) + abiname = "ilp32f"; +#else + abiname = "ilp32"; +#endif +#else + elog(ERROR, "unsupported riscv xlen %d", __riscv_xlen); +#endif + /* + * set this manually to avoid llvm defaulting to soft float and + * resulting in linker error: `can't link double-float modules + * with soft-float modules` + * we could set this for TargetMachine via MCOptions, but there + * is no C API for it + * ref: https://github.com/llvm/llvm-project/blob/afa520ab34803c82587ea6759bfd352579f741b4/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp#L90 + */ + abi_metadata = LLVMMDStringInContext2( + LLVMGetModuleContext(context->module), + abiname, strlen(abiname)); + LLVMAddModuleFlag(context->module, LLVMModuleFlagBehaviorOverride, + target_abi, strlen(target_abi), abi_metadata); +#endif } return context->module; @@ -786,6 +825,8 @@ llvm_session_initialize(void) char *error = NULL; char *cpu = NULL; char *features = NULL; + LLVMRelocMode reloc=LLVMRelocDefault; + LLVMCodeModel codemodel=LLVMCodeModelJITDefault; LLVMTargetMachineRef opt0_tm; LLVMTargetMachineRef opt3_tm; @@ -820,16 +861,21 @@ llvm_session_initialize(void) elog(DEBUG2, "LLVMJIT detected CPU \"%s\", with features \"%s\"", cpu, features); +#ifdef __riscv + reloc=LLVMRelocPIC; + codemodel=LLVMCodeModelMedium; +#endif + opt0_tm = LLVMCreateTargetMachine(llvm_targetref, llvm_triple, cpu, features, LLVMCodeGenLevelNone, - LLVMRelocDefault, - LLVMCodeModelJITDefault); + reloc, + codemodel); opt3_tm = LLVMCreateTargetMachine(llvm_targetref, llvm_triple, cpu, features, LLVMCodeGenLevelAggressive, - LLVMRelocDefault, - LLVMCodeModelJITDefault); + reloc, + codemodel); LLVMDisposeMessage(cpu); cpu = NULL; @@ -1112,7 +1158,11 @@ llvm_resolve_symbols(LLVMOrcDefinitionGeneratorRef GeneratorObj, void *Ctx, LLVMOrcJITDylibRef JD, LLVMOrcJITDylibLookupFlags JDLookupFlags, LLVMOrcCLookupSet LookupSet, size_t LookupSetSize) { +#if LLVM_VERSION_MAJOR > 14 + LLVMOrcCSymbolMapPairs symbols = palloc0(sizeof(LLVMOrcCSymbolMapPair) * LookupSetSize); +#else LLVMOrcCSymbolMapPairs symbols = palloc0(sizeof(LLVMJITCSymbolMapPair) * LookupSetSize); +#endif LLVMErrorRef error; LLVMOrcMaterializationUnitRef mu; @@ -1160,6 +1210,10 @@ llvm_log_jit_error(void *ctx, LLVMErrorRef error) static LLVMOrcObjectLayerRef llvm_create_object_layer(void *Ctx, LLVMOrcExecutionSessionRef ES, const char *Triple) { +#if defined(USE_JITLINK) + LLVMOrcObjectLayerRef objlayer = + LLVMOrcCreateJitlinkObjectLinkingLayer(ES); +#else LLVMOrcObjectLayerRef objlayer = LLVMOrcCreateRTDyldObjectLinkingLayerWithSectionMemoryManager(ES); @@ -1179,6 +1233,7 @@ llvm_create_object_layer(void *Ctx, LLVMOrcExecutionSessionRef ES, const char *T LLVMOrcRTDyldObjectLinkingLayerRegisterJITEventListener(objlayer, l); } +#endif #endif return objlayer; @@ -1230,7 +1285,11 @@ llvm_create_jit_instance(LLVMTargetMachineRef tm) * Symbol resolution support for "special" functions, e.g. a call into an * SQL callable function. */ +#if LLVM_VERSION_MAJOR > 14 + ref_gen = LLVMOrcCreateCustomCAPIDefinitionGenerator(llvm_resolve_symbols, NULL, NULL); +#else ref_gen = LLVMOrcCreateCustomCAPIDefinitionGenerator(llvm_resolve_symbols, NULL); +#endif LLVMOrcJITDylibAddGenerator(LLVMOrcLLJITGetMainJITDylib(lljit), ref_gen); return lljit; diff --git a/src/backend/jit/llvm/llvmjit_wrap.cpp b/src/backend/jit/llvm/llvmjit_wrap.cpp index 8f11cc02b2..29f21f1715 100644 --- a/src/backend/jit/llvm/llvmjit_wrap.cpp +++ b/src/backend/jit/llvm/llvmjit_wrap.cpp @@ -27,6 +27,10 @@ extern "C" #include <llvm/Support/Host.h> #include "jit/llvmjit.h" +#ifdef USE_JITLINK +#include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h" +#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" +#endif /* @@ -48,6 +52,19 @@ char *LLVMGetHostCPUFeatures(void) { for (auto &F : HostFeatures) Features.AddFeature(F.first(), F.second); +#if defined(__riscv) + /* getHostCPUName returns "generic-rv[32|64]", which lacks all features */ + Features.AddFeature("m", true); + Features.AddFeature("a", true); + Features.AddFeature("c", true); +# if defined(__riscv_float_abi_single) + Features.AddFeature("f", true); +# endif +# if defined(__riscv_float_abi_double) + Features.AddFeature("d", true); +# endif +#endif + return strdup(Features.getString().c_str()); } #endif @@ -76,3 +93,21 @@ LLVMGetAttributeCountAtIndexPG(LLVMValueRef F, uint32 Idx) */ return LLVMGetAttributeCountAtIndex(F, Idx); } + +#ifdef USE_JITLINK +/* + * There is no public C API to create ObjectLinkingLayer for JITLINK, create our own + */ +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(llvm::orc::ExecutionSession, LLVMOrcExecutionSessionRef) +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(llvm::orc::ObjectLayer, LLVMOrcObjectLayerRef) + +LLVMOrcObjectLayerRef +LLVMOrcCreateJitlinkObjectLinkingLayer(LLVMOrcExecutionSessionRef ES) +{ + assert(ES && "ES must not be null"); + auto ObjLinkingLayer = new llvm::orc::ObjectLinkingLayer(*unwrap(ES)); + ObjLinkingLayer->addPlugin(std::make_unique<llvm::orc::EHFrameRegistrationPlugin>( + *unwrap(ES), std::make_unique<llvm::jitlink::InProcessEHFrameRegistrar>())); + return wrap(ObjLinkingLayer); +} +#endif diff --git a/src/include/jit/llvmjit.h b/src/include/jit/llvmjit.h index 4541f9a2c4..85a0cfe5e0 100644 --- a/src/include/jit/llvmjit.h +++ b/src/include/jit/llvmjit.h @@ -19,6 +19,11 @@ #include <llvm-c/Types.h> +#if defined(__riscv) && LLVM_VERSION_MAJOR >= 15 +#include <llvm-c/Orc.h> +#define USE_JITLINK +/* else use legacy RTDyld */ +#endif /* * File needs to be includable by both C and C++ code, and include other @@ -134,6 +139,10 @@ extern char *LLVMGetHostCPUFeatures(void); extern unsigned LLVMGetAttributeCountAtIndexPG(LLVMValueRef F, uint32 Idx); +#ifdef USE_JITLINK +extern LLVMOrcObjectLayerRef LLVMOrcCreateJitlinkObjectLinkingLayer(LLVMOrcExecutionSessionRef ES); +#endif + #ifdef __cplusplus } /* extern "C" */ #endif -- 2.37.2
pgsql-hackers by date: