--- /dev/null
+/*
+ *
+ */
+
+#include "postgres.h"
+
+#ifdef USE_LLVM
+
+#include "lib/llvmjit.h"
+
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <llvm-c/Core.h>
+#include <llvm-c/ExecutionEngine.h>
+#include <llvm-c/Target.h>
+#include <llvm-c/Analysis.h>
+#include <llvm-c/BitWriter.h>
+
+#include "utils/memutils.h"
+
+/* GUCs */
+bool jit_log_ir = 0;
+bool jit_dump_bitcode = 0;
+
+static bool llvm_initialized = false;
+
+/* very common public things */
+LLVMModuleRef llvm_mod;
+LLVMExecutionEngineRef llvm_engine;
+LLVMTypeRef TypeSizeT;
+LLVMTypeRef StructHeapTupleFields;
+LLVMTypeRef StructHeapTupleHeaderData;
+LLVMTypeRef StructHeapTupleData;
+LLVMTypeRef StructItemPointerData;
+LLVMTypeRef StructBlockId;
+LLVMTypeRef StructTupleTableSlot;
+
+void
+llvm_initialize(void)
+{
+ char *error = NULL;
+ struct LLVMMCJITCompilerOptions options;
+ MemoryContext oldcontext;
+
+ if (llvm_initialized)
+ return;
+
+ oldcontext = MemoryContextSwitchTo(TopMemoryContext);
+
+ LLVMLinkInMCJIT();
+ LLVMInitializeNativeTarget();
+ LLVMInitializeNativeAsmPrinter();
+ LLVMInitializeNativeAsmParser();
+
+ llvm_mod = LLVMModuleCreateWithName("top_module");
+ LLVMSetTarget(llvm_mod, "x86_64-unknown-linux-gnu");
+
+ LLVMInitializeMCJITCompilerOptions(&options, sizeof(options));
+ options.OptLevel = 3;
+ options.NoFramePointerElim = false;
+ if (LLVMCreateMCJITCompilerForModule(&llvm_engine, llvm_mod, &options, sizeof(options),
+ &error) != 0)
+ {
+ fprintf(stderr, "failed to create mcjit execution engine\n");
+ abort();
+ }
+
+ if (error)
+ {
+ fprintf(stderr, "error: %s\n", error);
+ LLVMDisposeMessage(error);
+ exit(EXIT_FAILURE);
+ }
+
+ /* so we don't constantly have to decide between 32/64 bit */
+#if SIZEOF_DATUM == 8
+ TypeSizeT = LLVMInt64Type();
+#else
+ TypeSizeT = LLVMInt32Type();
+#endif
+
+ /* FIXME: should rather load these from disk using bitcode? */
+ {
+ LLVMTypeRef members[2];
+ members[0] = LLVMInt16Type(); /* bi_hi */
+ members[1] = LLVMInt16Type(); /* bi_lo */
+ StructBlockId = LLVMStructCreateNamed(LLVMGetGlobalContext(),
+ "BlockId");
+ LLVMStructSetBody(StructBlockId, members, 2, false);
+ }
+
+ {
+ LLVMTypeRef members[2];
+ members[0] = StructBlockId; /* ip_blkid */
+ members[1] = LLVMInt16Type(); /* ip_posid */
+ StructItemPointerData = LLVMStructType(members, 2, false);
+ }
+
+ {
+ LLVMTypeRef members[3];
+ members[0] = LLVMInt32Type(); /* xmin */
+ members[1] = LLVMInt32Type(); /* xmax */
+ members[2] = LLVMInt32Type(); /* cid | xvac */
+ StructHeapTupleFields = LLVMStructType(members, 3, false);
+ }
+ {
+ LLVMTypeRef members[5];
+ members[0] = StructHeapTupleFields; /* t_heap | t_datum */
+ members[1] = StructItemPointerData; /* t_ctid */
+ members[2] = LLVMInt16Type(); /* t_infomask2 */
+ members[3] = LLVMInt16Type(); /* t_infomask1 */
+ members[4] = LLVMInt8Type(); /* t_hoff */
+ /* t_bits and other data follow */
+ StructHeapTupleHeaderData = LLVMStructType(members, 5, false);
+ }
+
+ {
+ LLVMTypeRef members[4];
+ members[0] = LLVMInt32Type(); /* t_len */
+ members[1] = StructItemPointerData; /* t_self */
+ members[2] = LLVMInt32Type(); /* t_tableOid */
+ members[3] = LLVMPointerType(StructHeapTupleHeaderData, 0); /* t_data */
+ StructHeapTupleData = LLVMStructType(members, 4, false);
+ }
+ {
+ LLVMTypeRef members[16];
+ members[ 0] = LLVMInt32Type(); /* type */
+ members[ 1] = LLVMInt8Type(); /* isempty */
+ members[ 2] = LLVMInt8Type(); /* shouldFree */
+ members[ 3] = LLVMInt8Type(); /* shouldFreeMin */
+ members[ 4] = LLVMInt8Type(); /* slow */
+ members[ 5] = LLVMPointerType(StructHeapTupleData, 0); /* tuple */
+ members[ 6] = LLVMPointerType(LLVMInt64Type(), 0); /* tupleDescriptor */
+ members[ 7] = LLVMPointerType(LLVMInt64Type(), 0); /* mcxt */
+ members[ 8] = LLVMInt32Type(); /* buffer */
+ members[ 9] = LLVMInt32Type(); /* nvalid */
+ members[10] = LLVMPointerType(TypeSizeT, 0); /* values */
+ members[11] = LLVMPointerType(LLVMInt8Type(), 0); /*nulls */
+ members[12] = LLVMPointerType(LLVMInt64Type(), 0); /* dp */
+ members[13] = LLVMPointerType(LLVMInt64Type(), 0); /* mintuple */
+ members[14] = StructHeapTupleData; /* minhdr */
+ members[15] = LLVMInt32Type(); /* off */
+ StructTupleTableSlot = LLVMStructCreateNamed(LLVMGetGlobalContext(),
+ "TupleTableSlot");
+ LLVMStructSetBody(StructTupleTableSlot, members, 16, false);
+ }
+
+ llvm_initialized = true;
+ MemoryContextSwitchTo(oldcontext);
+}
+
+
+void
+llvm_add_module(LLVMModuleRef mod, const char *name)
+{
+#ifdef USE_ASSERT_CHECKING
+ char *error = NULL;
+#endif
+
+ if (jit_log_ir)
+ {
+ LLVMDumpModule(mod);
+ }
+
+#ifdef USE_ASSERT_CHECKING
+ if (LLVMVerifyModule(mod, LLVMPrintMessageAction, &error))
+ {
+ elog(WARNING, "failed to JIT: %s", error);
+ LLVMDisposeMessage(error);
+ }
+#endif
+
+ if (jit_dump_bitcode)
+ {
+ char *filename = psprintf("%s.bc", name);
+ LLVMWriteBitcodeToFile(mod, filename);
+ pfree(filename);
+ }
+}
+
+void *
+llvm_get_function(const char *funcname)
+{
+ void *ret = (void *) LLVMGetFunctionAddress(llvm_engine, funcname);
+
+ /* to fix profiling: */
+ {
+ int fd = open("/dev/zero", O_RDWR);
+ mmap((void *)TYPEALIGN_DOWN(4096, ret), 4096, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, fd, 0);
+ close(fd);
+ }
+
+ return ret;
+}
+
+void
+llvm_dispose_module(LLVMModuleRef mod, const char *funcname)
+{
+ LLVMModuleRef outmod = NULL;
+ char *error = NULL;
+
+ LLVMRemoveModule(llvm_engine, mod, &outmod, &error);
+ LLVMDisposeModule(outmod);
+
+ if (error)
+ {
+ elog(ERROR, "failed to remove module for function %s: %s",
+ funcname, error);
+ LLVMDisposeMessage(error);
+ }
+}
+
+#endif /* USE_LLVM */