diff --git a/src/Makefile b/src/Makefile index febbcede7d..bcdbd9588a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -31,6 +31,10 @@ SUBDIRS = \ test/isolation \ test/perl +ifeq ($(with_llvm), yes) +SUBDIRS += backend/jit/llvm +endif + # There are too many interdependencies between the subdirectories, so # don't attempt parallel make here. .NOTPARALLEL: diff --git a/src/backend/Makefile b/src/backend/Makefile index 4a28267339..6450c5a959 100644 --- a/src/backend/Makefile +++ b/src/backend/Makefile @@ -19,7 +19,8 @@ include $(top_builddir)/src/Makefile.global SUBDIRS = access bootstrap catalog parser commands executor foreign lib libpq \ main nodes optimizer port postmaster regex replication rewrite \ - statistics storage tcop tsearch utils $(top_builddir)/src/timezone + statistics storage tcop tsearch utils $(top_builddir)/src/timezone \ + jit include $(srcdir)/common.mk diff --git a/src/backend/jit/Makefile b/src/backend/jit/Makefile new file mode 100644 index 0000000000..cdb9009ec1 --- /dev/null +++ b/src/backend/jit/Makefile @@ -0,0 +1,22 @@ +#------------------------------------------------------------------------- +# +# Makefile-- +# Makefile for JIT code that's provider independent. +# +# Note that the LLVM JIT provider is recursed into by src/Makefile, +# not from here. +# +# IDENTIFICATION +# src/backend/jit/Makefile +# +#------------------------------------------------------------------------- + +subdir = src/backend/jit +top_builddir = ../../.. +include $(top_builddir)/src/Makefile.global + +override CPPFLAGS += -DDLSUFFIX=\"$(DLSUFFIX)\" + +OBJS = jit.o + +include $(top_srcdir)/src/backend/common.mk diff --git a/src/backend/jit/jit.c b/src/backend/jit/jit.c new file mode 100644 index 0000000000..6c842a0fe9 --- /dev/null +++ b/src/backend/jit/jit.c @@ -0,0 +1,156 @@ +/*------------------------------------------------------------------------- + * + * jit.c + * Provider independent JIT infrastructure. + * + * Code related to loading JIT providers, redirecting calls into JIT providers + * and error handling. No code specific to a specific JIT implementation + * should end up here. + * + * + * Copyright (c) 2016-2018, PostgreSQL Global Development Group + * + * IDENTIFICATION + * src/backend/jit/jit.c + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + + +#include +#include +#include + + +#include "fmgr.h" +#include "jit/jit.h" +#include "miscadmin.h" +#include "utils/resowner_private.h" +#include "utils/fmgrprotos.h" + + +/* GUCs */ +bool jit_enabled = true; +char *jit_provider = "llvmjit"; + +static JitProviderCallbacks provider; +static bool provider_successfully_loaded = false; +static bool provider_failed_loading = false; + + +static bool provider_init(void); +static bool file_exists(const char *name); + + +/* + * SQL level function returning whether JIT is available in the current + * backend. Will attempt to load JIT provider if necessary. + */ +Datum +pg_jit_available(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL(provider_init()); +} + + +/* + * Return whether a JIT provider has successfully been loaded, caching the + * result. + */ +static bool +provider_init(void) +{ + char path[MAXPGPATH]; + JitProviderInit init; + + /* don't even try to load if not enabled */ + if (!jit_enabled) + return false; + + /* + * Don't retry loading after failing - attempting to load JIT provider + * isn't cheap. + */ + if (provider_failed_loading) + return false; + if (provider_successfully_loaded) + return true; + + /* + * Check whether shared library exists. We do that check before actually + * attempting to load the shared library (via load_external_function()), + * because that'd error out in case the shlib isn't available. + */ + snprintf(path, MAXPGPATH, "%s/%s%s", pkglib_path, jit_provider, DLSUFFIX); + elog(DEBUG1, "probing availability of JIT provider at %s", path); + if (!file_exists(path)) + { + elog(DEBUG1, + "provider not available, disabling JIT for current session"); + provider_failed_loading = true; + return false; + } + + /* + * If loading functions fails, signal failure. We do so because + * load_external_function() might error out despite the above check if + * e.g. the library's dependencies aren't installed. We want to signal + * ERROR in that case, so the user is notified, but we don't want to + * continually retry. + */ + provider_failed_loading = true; + + /* and initialize */ + init = (JitProviderInit) + load_external_function(path, "_PG_jit_provider_init", true, NULL); + init(&provider); + + provider_successfully_loaded = true; + provider_failed_loading = false; + + elog(DEBUG1, "successfully loaded JIT provider in current session"); + + return true; +} + +/* + * Reset JIT provider's error handling. This'll be called after an error has + * been thrown and the main-loop has re-established control. + */ +void +jit_reset_after_error(void) +{ + if (provider_successfully_loaded) + provider.reset_after_error(); +} + +/* + * Release resources required by one JIT context. + */ +void +jit_release_context(JitContext *context) +{ + if (provider_successfully_loaded) + provider.release_context(context); + + ResourceOwnerForgetJIT(context->resowner, PointerGetDatum(context)); + pfree(context); +} + +static bool +file_exists(const char *name) +{ + struct stat st; + + AssertArg(name != NULL); + + if (stat(name, &st) == 0) + return S_ISDIR(st.st_mode) ? false : true; + else if (!(errno == ENOENT || errno == ENOTDIR)) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not access file \"%s\": %m", name))); + + return false; +} diff --git a/src/backend/jit/llvm/Makefile b/src/backend/jit/llvm/Makefile new file mode 100644 index 0000000000..856b94e12b --- /dev/null +++ b/src/backend/jit/llvm/Makefile @@ -0,0 +1,55 @@ +#------------------------------------------------------------------------- +# +# Makefile-- +# Makefile the LLVM JIT provider, building it into a shared library. +# +# Note that this file is recursed into from src/Makefile, not by the +# parent directory.. +# +# IDENTIFICATION +# src/backend/jit/llvm/Makefile +# +#------------------------------------------------------------------------- + +subdir = src/backend/jit/llvm +top_builddir = ../../../.. +include $(top_builddir)/src/Makefile.global + +ifneq ($(with_llvm), yes) + $(error "not building with LLVM support") +endif + +PGFILEDESC = "llvmjit - JIT using LLVM" +NAME = llvmjit + +# All files in this directy use LLVM. +CFLAGS += $(LLVM_CFLAGS) +CXXFLAGS += $(LLVM_CXXFLAGS) +override CPPFLAGS := $(LLVM_CPPFLAGS) $(CPPFLAGS) +SHLIB_LINK += $(LLVM_LIBS) +SHLIB_PREREQS += submake-generated-headers + +# Because this module includes C++ files, we need to use a C++ +# compiler for linking. Makefile.shlib uses $(COMPILER) to build +# loadable modules. +override COMPILER = $(CXX) $(CFLAGS) + +OBJS=$(WIN32RES) + +# Infrastructure +OBJS += llvmjit.o llvmjit_error.o +# Code generation +OBJS += + +all: all-shared-lib + +install: all installdirs install-lib + +installdirs: installdirs-lib + +uninstall: uninstall-lib + +include $(top_srcdir)/src/Makefile.shlib + +clean distclean maintainer-clean: clean-lib + rm -f $(OBJS) diff --git a/src/backend/jit/llvm/llvmjit.c b/src/backend/jit/llvm/llvmjit.c new file mode 100644 index 0000000000..9c57922915 --- /dev/null +++ b/src/backend/jit/llvm/llvmjit.c @@ -0,0 +1,113 @@ +/*------------------------------------------------------------------------- + * + * llvmjit.c + * Core part of the LLVM JIT provider. + * + * Copyright (c) 2016-2018, PostgreSQL Global Development Group + * + * IDENTIFICATION + * src/backend/jit/llvm/llvmjit.c + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "jit/llvmjit.h" + +#include "miscadmin.h" + +#include "utils/memutils.h" +#include "utils/resowner_private.h" +#include "storage/ipc.h" + + +#include + + +static bool llvm_session_initialized = false; + + +static void llvm_release_context(JitContext *context); +static void llvm_session_initialize(void); +static void llvm_shutdown(int code, Datum arg); + + +PG_MODULE_MAGIC; + + +/* + * Initialize LLVM JIT provider. + */ +void +_PG_jit_provider_init(JitProviderCallbacks *cb) +{ + cb->reset_after_error = llvm_reset_after_error; + cb->release_context = llvm_release_context; +} + +/* + * Create a context for JITing work. + * + * The context, including subsidiary resources, will be cleaned up either when + * the context is explicitly released, or when the lifetime of + * CurrentResourceOwner ends (usually the end of the current [sub]xact). + */ +LLVMJitContext * +llvm_create_context(int jitFlags) +{ + LLVMJitContext *context; + + llvm_assert_in_fatal_section(); + + llvm_session_initialize(); + + ResourceOwnerEnlargeJIT(CurrentResourceOwner); + + context = MemoryContextAllocZero(TopMemoryContext, + sizeof(LLVMJitContext)); + context->base.flags = jitFlags; + + /* ensure cleanup */ + context->base.resowner = CurrentResourceOwner; + ResourceOwnerRememberJIT(CurrentResourceOwner, PointerGetDatum(context)); + + return context; +} + +/* + * Release resources required by one llvm context. + */ +static void +llvm_release_context(JitContext *context) +{ +} + +/* + * Per session initialization. + */ +static void +llvm_session_initialize(void) +{ + MemoryContext oldcontext; + + if (llvm_session_initialized) + return; + + oldcontext = MemoryContextSwitchTo(TopMemoryContext); + + LLVMInitializeNativeTarget(); + LLVMInitializeNativeAsmPrinter(); + LLVMInitializeNativeAsmParser(); + + before_shmem_exit(llvm_shutdown, 0); + + llvm_session_initialized = true; + + MemoryContextSwitchTo(oldcontext); +} + +static void +llvm_shutdown(int code, Datum arg) +{ +} diff --git a/src/backend/jit/llvm/llvmjit_error.cpp b/src/backend/jit/llvm/llvmjit_error.cpp new file mode 100644 index 0000000000..edc1c479d0 --- /dev/null +++ b/src/backend/jit/llvm/llvmjit_error.cpp @@ -0,0 +1,141 @@ +/*------------------------------------------------------------------------- + * + * llvmjit_error.cpp + * LLVM error related handling that requires interfacing with C++ + * + * Unfortunately neither (re)setting the C++ new handler, nor the LLVM OOM + * handler are exposed to C. Therefore this file wraps the necesary code. + * + * Copyright (c) 2016-2018, PostgreSQL Global Development Group + * + * IDENTIFICATION + * src/backend/jit/llvm/llvmjit_error.c + * + *------------------------------------------------------------------------- + */ + +extern "C" +{ +#include "postgres.h" +} + +#include + +#include "jit/llvmjit.h" + + +static int fatal_new_handler_depth = 0; +static std::new_handler old_new_handler = NULL; + +static void fatal_system_new_handler(void); +#if LLVM_VERSION_MAJOR > 4 +static void fatal_llvm_new_handler(void *user_data, const std::string& reason, bool gen_crash_diag); +#endif +static void fatal_llvm_error_handler(void *user_data, const std::string& reason, bool gen_crash_diag); + + +/* + * Enter a section in which C++ and LLVM errors are treated as FATAL errors. + * + * This is necessary for LLVM as LLVM's error handling for such cases + * (exit()ing, throwing std::bad_alloc() if compiled with exceptions, abort()) + * isn't compatible with postgres error handling. Thus in section where LLVM + * code, not LLVM generated functions!, is executing, standard new, LLVM OOM + * and LLVM fatal errors (some OOM errors masquerade as those) are redirected + * to our own error handlers. + * + * These error handlers FATAL, because there's no reliable way from within + * LLVM to throw an error that's guaranteed not to corrupt LLVM's state. + * + * To avoid disturbing extensions using C++ and/or LLVM, these handlers are + * unset when not executing LLVM code. There is no need to call + * llvm_leave_fatal_on_oom() when ERRORing out, error recovery resets the + * handlers in that case. + */ +void +llvm_enter_fatal_on_oom(void) +{ + if (fatal_new_handler_depth == 0) + { + old_new_handler = std::set_new_handler(fatal_system_new_handler); +#if LLVM_VERSION_MAJOR > 4 + llvm::install_bad_alloc_error_handler(fatal_llvm_new_handler); +#endif + llvm::install_fatal_error_handler(fatal_llvm_error_handler); + } + fatal_new_handler_depth++; +} + +/* + * Leave fatal error section started with llvm_enter_fatal_on_oom(). + */ +void +llvm_leave_fatal_on_oom(void) +{ + fatal_new_handler_depth--; + if (fatal_new_handler_depth == 0) + { + std::set_new_handler(old_new_handler); +#if LLVM_VERSION_MAJOR > 4 + llvm::remove_bad_alloc_error_handler(); +#endif + llvm::remove_fatal_error_handler(); + } +} + +/* + * Reset fatal error handling. This should only be called in error recovery + * loops like PostgresMain()'s. + */ +void +llvm_reset_after_error(void) +{ + if (fatal_new_handler_depth != 0) + { + std::set_new_handler(old_new_handler); +#if LLVM_VERSION_MAJOR > 4 + llvm::remove_bad_alloc_error_handler(); +#endif + llvm::remove_fatal_error_handler(); + } + fatal_new_handler_depth = 0; +} + +void +llvm_assert_in_fatal_section(void) +{ + Assert(fatal_new_handler_depth > 0); +} + +static void +fatal_system_new_handler(void) +{ + ereport(FATAL, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"), + errdetail("while in LLVM"))); +} + +#if LLVM_VERSION_MAJOR > 4 +static void +fatal_llvm_new_handler(void *user_data, + const std::string& reason, + bool gen_crash_diag) +{ + ereport(FATAL, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"), + errdetail("While in LLVM: %s", reason.c_str()))); +} +#endif + +static void +fatal_llvm_error_handler(void *user_data, + const std::string& reason, + bool gen_crash_diag) +{ + ereport(FATAL, + (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("fatal llvm error: %s", + reason.c_str()))); +} diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 6dc2095b9a..f7aa4a7484 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -42,6 +42,7 @@ #include "catalog/pg_type.h" #include "commands/async.h" #include "commands/prepare.h" +#include "jit/jit.h" #include "libpq/libpq.h" #include "libpq/pqformat.h" #include "libpq/pqsignal.h" @@ -3950,6 +3951,8 @@ PostgresMain(int argc, char *argv[], /* We also want to cleanup temporary slots on error. */ ReplicationSlotCleanup(); + jit_reset_after_error(); + /* * Now return to normal top-level context and clear ErrorContext for * next time. diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 153373ead0..afb1007842 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -42,6 +42,7 @@ #include "commands/variable.h" #include "commands/trigger.h" #include "funcapi.h" +#include "jit/jit.h" #include "libpq/auth.h" #include "libpq/libpq.h" #include "libpq/pqformat.h" @@ -1714,6 +1715,16 @@ static struct config_bool ConfigureNamesBool[] = NULL, NULL, NULL }, + { + {"jit", PGC_USERSET, QUERY_TUNING_OTHER, + gettext_noop("Allow JIT compilation."), + NULL + }, + &jit_enabled, + true, + NULL, NULL, NULL + }, + /* End-of-list marker */ { {NULL, 0, 0, NULL, NULL}, NULL, false, NULL, NULL, NULL @@ -3707,6 +3718,17 @@ static struct config_string ConfigureNamesString[] = check_wal_consistency_checking, assign_wal_consistency_checking, NULL }, + { + {"jit_provider", PGC_POSTMASTER, FILE_LOCATIONS, + gettext_noop("JIT provider to use."), + NULL, + GUC_SUPERUSER_ONLY + }, + &jit_provider, + "llvmjit", + NULL, NULL, NULL + }, + /* End-of-list marker */ { {NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL, NULL diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index 048bf4cccd..91eacacdc9 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -606,6 +606,8 @@ #dynamic_library_path = '$libdir' +#jit = on # allow JIT compilation +#jit_provider = 'llvmjit' # JIT implementation to use #------------------------------------------------------------------------------ # LOCK MANAGEMENT diff --git a/src/backend/utils/resowner/resowner.c b/src/backend/utils/resowner/resowner.c index e09a4f1ddb..bce021e100 100644 --- a/src/backend/utils/resowner/resowner.c +++ b/src/backend/utils/resowner/resowner.c @@ -21,6 +21,7 @@ #include "postgres.h" #include "access/hash.h" +#include "jit/jit.h" #include "storage/predicate.h" #include "storage/proc.h" #include "utils/memutils.h" @@ -124,6 +125,7 @@ typedef struct ResourceOwnerData ResourceArray snapshotarr; /* snapshot references */ ResourceArray filearr; /* open temporary files */ ResourceArray dsmarr; /* dynamic shmem segments */ + ResourceArray jitarr; /* JIT contexts */ /* We can remember up to MAX_RESOWNER_LOCKS references to local locks. */ int nlocks; /* number of owned locks */ @@ -437,6 +439,7 @@ ResourceOwnerCreate(ResourceOwner parent, const char *name) ResourceArrayInit(&(owner->snapshotarr), PointerGetDatum(NULL)); ResourceArrayInit(&(owner->filearr), FileGetDatum(-1)); ResourceArrayInit(&(owner->dsmarr), PointerGetDatum(NULL)); + ResourceArrayInit(&(owner->jitarr), PointerGetDatum(NULL)); return owner; } @@ -538,6 +541,14 @@ ResourceOwnerReleaseInternal(ResourceOwner owner, PrintDSMLeakWarning(res); dsm_detach(res); } + + /* Ditto for JIT contexts */ + while (ResourceArrayGetAny(&(owner->jitarr), &foundres)) + { + JitContext *context = (JitContext *) PointerGetDatum(foundres); + + jit_release_context(context); + } } else if (phase == RESOURCE_RELEASE_LOCKS) { @@ -685,6 +696,7 @@ ResourceOwnerDelete(ResourceOwner owner) Assert(owner->snapshotarr.nitems == 0); Assert(owner->filearr.nitems == 0); Assert(owner->dsmarr.nitems == 0); + Assert(owner->jitarr.nitems == 0); Assert(owner->nlocks == 0 || owner->nlocks == MAX_RESOWNER_LOCKS + 1); /* @@ -711,6 +723,7 @@ ResourceOwnerDelete(ResourceOwner owner) ResourceArrayFree(&(owner->snapshotarr)); ResourceArrayFree(&(owner->filearr)); ResourceArrayFree(&(owner->dsmarr)); + ResourceArrayFree(&(owner->jitarr)); pfree(owner); } @@ -1253,3 +1266,38 @@ PrintDSMLeakWarning(dsm_segment *seg) elog(WARNING, "dynamic shared memory leak: segment %u still referenced", dsm_segment_handle(seg)); } + +/* + * Make sure there is room for at least one more entry in a ResourceOwner's + * JIT context reference array. + * + * This is separate from actually inserting an entry because if we run out of + * memory, it's critical to do so *before* acquiring the resource. + */ +void +ResourceOwnerEnlargeJIT(ResourceOwner owner) +{ + ResourceArrayEnlarge(&(owner->jitarr)); +} + +/* + * Remember that a JIT context is owned by a ResourceOwner + * + * Caller must have previously done ResourceOwnerEnlargeJIT() + */ +void +ResourceOwnerRememberJIT(ResourceOwner owner, Datum handle) +{ + ResourceArrayAdd(&(owner->jitarr), handle); +} + +/* + * Forget that a JIT context is owned by a ResourceOwner + */ +void +ResourceOwnerForgetJIT(ResourceOwner owner, Datum handle) +{ + if (!ResourceArrayRemove(&(owner->jitarr), handle)) + elog(ERROR, "JIT context %p is not owned by resource owner %s", + DatumGetPointer(handle), owner->name); +} diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 4c290abb4d..0ddf6a77c1 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 201803212 +#define CATALOG_VERSION_NO 201803213 #endif diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 871000b94b..bfc90098f8 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -3371,6 +3371,8 @@ DATA(insert OID = 3935 ( pg_sleep_for PGNSP PGUID 14 1 0 0 0 f f f t f v s 1 0 DESCR("sleep for the specified interval"); DATA(insert OID = 3936 ( pg_sleep_until PGNSP PGUID 14 1 0 0 0 f f f t f v s 1 0 2278 "1184" _null_ _null_ _null_ _null_ _null_ "select pg_catalog.pg_sleep(extract(epoch from $1) operator(pg_catalog.-) extract(epoch from pg_catalog.clock_timestamp()))" _null_ _null_ _null_ )); DESCR("sleep until the specified time"); +DATA(insert OID = 315 ( pg_jit_available PGNSP PGUID 12 1 0 0 0 f f f t f v s 0 0 16 "" _null_ _null_ _null_ _null_ _null_ pg_jit_available _null_ _null_ _null_ )); +DESCR("Is JIT compilation available in this session?"); DATA(insert OID = 2971 ( text PGNSP PGUID 12 1 0 0 0 f f f t f i s 1 0 25 "16" _null_ _null_ _null_ _null_ _null_ booltext _null_ _null_ _null_ )); DESCR("convert boolean to text"); diff --git a/src/include/jit/jit.h b/src/include/jit/jit.h new file mode 100644 index 0000000000..a2f3dd9d4f --- /dev/null +++ b/src/include/jit/jit.h @@ -0,0 +1,46 @@ +/*------------------------------------------------------------------------- + * jit.h + * Provider independent JIT infrastructure. + * + * Copyright (c) 2016-2018, PostgreSQL Global Development Group + * + * src/include/jit/jit.h + * + *------------------------------------------------------------------------- + */ +#ifndef JIT_H +#define JIT_H + +#include "utils/resowner.h" + + +typedef struct JitContext +{ + int flags; + + ResourceOwner resowner; +} JitContext; + +typedef struct JitProviderCallbacks JitProviderCallbacks; + +extern void _PG_jit_provider_init(JitProviderCallbacks *cb); +typedef void (*JitProviderInit) (JitProviderCallbacks *cb); +typedef void (*JitProviderResetAfterErrorCB) (void); +typedef void (*JitProviderReleaseContextCB) (JitContext *context); + +struct JitProviderCallbacks +{ + JitProviderResetAfterErrorCB reset_after_error; + JitProviderReleaseContextCB release_context; +}; + + +/* GUCs */ +extern bool jit_enabled; +extern char *jit_provider; + + +extern void jit_reset_after_error(void); +extern void jit_release_context(JitContext *context); + +#endif /* JIT_H */ diff --git a/src/include/jit/llvmjit.h b/src/include/jit/llvmjit.h new file mode 100644 index 0000000000..187ebe2c2a --- /dev/null +++ b/src/include/jit/llvmjit.h @@ -0,0 +1,51 @@ +/*------------------------------------------------------------------------- + * llvmjit.h + * LLVM JIT provider. + * + * Copyright (c) 2016-2018, PostgreSQL Global Development Group + * + * src/include/jit/llvmjit.h + * + *------------------------------------------------------------------------- + */ +#ifndef LLVMJIT_H +#define LLVMJIT_H + +#ifndef USE_LLVM +#error "llvmjit.h should only be included by code dealing with llvm" +#endif + +#include + + +/* + * File needs to be includable by both C and C++ code, and include other + * headers doing the same. Therefore wrap C portion in our own extern "C" if + * in C++ mode. + */ +#ifdef __cplusplus +extern "C" +{ +#endif + + +#include "jit/jit.h" + + +typedef struct LLVMJitContext +{ + JitContext base; +} LLVMJitContext; + +extern void llvm_enter_fatal_on_oom(void); +extern void llvm_leave_fatal_on_oom(void); +extern void llvm_reset_after_error(void); +extern void llvm_assert_in_fatal_section(void); + +extern LLVMJitContext *llvm_create_context(int jitFlags); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LLVMJIT_H */ diff --git a/src/include/utils/resowner_private.h b/src/include/utils/resowner_private.h index 22b377c0df..44dc99eb26 100644 --- a/src/include/utils/resowner_private.h +++ b/src/include/utils/resowner_private.h @@ -88,4 +88,11 @@ extern void ResourceOwnerRememberDSM(ResourceOwner owner, extern void ResourceOwnerForgetDSM(ResourceOwner owner, dsm_segment *); +/* support for JITContext management */ +extern void ResourceOwnerEnlargeJIT(ResourceOwner owner); +extern void ResourceOwnerRememberJIT(ResourceOwner owner, + Datum handle); +extern void ResourceOwnerForgetJIT(ResourceOwner owner, + Datum handle); + #endif /* RESOWNER_PRIVATE_H */ diff --git a/src/tools/pgindent/exclude_file_patterns b/src/tools/pgindent/exclude_file_patterns index cb2f902a90..65c42c131d 100644 --- a/src/tools/pgindent/exclude_file_patterns +++ b/src/tools/pgindent/exclude_file_patterns @@ -5,3 +5,4 @@ /ecpg/test/expected/ /snowball/libstemmer/ /pl/plperl/ppport\.h$ +/jit/llvmjit\.h$ diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index d4765ce3b0..543cb17e41 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -1055,6 +1055,8 @@ IterateForeignScan_function IterateJsonStringValuesState JEntry JHashState +JitContext +JitProviderCallbacks JOBOBJECTINFOCLASS JOBOBJECT_BASIC_LIMIT_INFORMATION JOBOBJECT_BASIC_UI_RESTRICTIONS @@ -1099,6 +1101,7 @@ LDAPMessage LDAPURLDesc LDAP_TIMEVAL LINE +LLVMJitContext LOCALLOCK LOCALLOCKOWNER LOCALLOCKTAG