-L*) LDFLAGS="$LDFLAGS $pgac_option";;
esac
done
- for pgac_option in `$LLVM_CONFIG --libs --system-libs engine debuginfodwarf perfjitevents`; do
+ for pgac_option in `$LLVM_CONFIG --libs --system-libs engine debuginfodwarf orcjit passes perfjitevents`; do
case $pgac_option in
-l*) LLVM_LIBS="$LLVM_LIBS $pgac_option";;
esac
-L*) LDFLAGS="$LDFLAGS $pgac_option";;
esac
done
- for pgac_option in `$LLVM_CONFIG --libs --system-libs engine debuginfodwarf perfjitevents`; do
+ for pgac_option in `$LLVM_CONFIG --libs --system-libs engine debuginfodwarf orcjit passes perfjitevents`; do
case $pgac_option in
-l*) LLVM_LIBS="$LLVM_LIBS $pgac_option";;
esac
}
void
-ExecInstantiateCompiledExpr(ExprState *state)
+ExecInstantiateCompiledExpr(ExprState *state, PlanState *parent)
{
ExprEvalStep *op;
int i = 0;
builder = LLVMCreateBuilder();
/* Create the signature and function */
- mod = LLVMModuleCreateWithName(funcname);
+ mod = LLVMModuleCreateWithName("frak");
+ LLVMSetTarget(mod, "x86_64-unknown-linux-gnu");
+
+#if 0
LLVMAddModule(llvm_engine, mod);
+#endif
{
LLVMTypeRef param_types[] = {
eval_sig = LLVMFunctionType(TypeSizeT, param_types, lengthof(param_types), 0);
}
eval_fn = LLVMAddFunction(mod, funcname, eval_sig);
- LLVMSetLinkage(eval_fn, LLVMInternalLinkage);
+ LLVMSetLinkage(eval_fn, LLVMExternalLinkage);
+ LLVMSetVisibility(eval_fn, LLVMDefaultVisibility);
entry = LLVMAppendBasicBlock(eval_fn, "entry");
/* build referenced functions */
}
}
+#if 0
llvm_add_module(mod, funcname);
- state->cb = (ExecEvalExprCB) llvm_get_function(funcname);
+ state->cb = (ExprStateEvalFunc) llvm_get_function(funcname);
LLVMDisposeBuilder(builder);
llvm_dispose_module(mod, funcname);
+#else
+ {
+ int handle;
+ state->cb = (ExprStateEvalFunc) llvm_get_function2(mod, funcname, &handle);
+ if (parent && parent->state)
+ {
+ parent->state->es_handles = lappend_int(parent->state->es_handles, handle);
+ }
+ LLVMDisposeBuilder(builder);
+ }
+#endif
}
#endif
/*
* Support for building execution state.
*/
-static void ExecInstantiateExpr(ExprState *state);
-static void ExecInitExprRec(Expr *node, PlanState *parent, ExprState *state,
- Datum *resv, bool *resnull);
+static void ExecInstantiateExpr(ExprState *state, PlanState *parent);
+static void ExecInitExprRec(Expr *node, PlanState *parent,
+ ExprState *state, Datum *resv, bool *resnull);
static void ExprEvalPushStep(ExprState *es, ExprEvalStep *s);
static void ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args,
Oid funcid, Oid inputcollid, PlanState *parent,
scratch.opcode = EEO_DONE;
ExprEvalPushStep(state, &scratch);
- ExecInstantiateExpr(state);
+ ExecInstantiateExpr(state, parent);
return state;
}
scratch.opcode = EEO_DONE;
ExprEvalPushStep(state, &scratch);
- ExecInstantiateExpr(state);
+ ExecInstantiateExpr(state, parent);
return state;
}
scratch.opcode = EEO_DONE;
ExprEvalPushStep(state, &scratch);
- ExecInstantiateExpr(state);
+ ExecInstantiateExpr(state, parent);
return projInfo;
}
* Therefore this should be used instead of ExecInstantiateInterpretedExpr().
*/
static void
-ExecInstantiateExpr(ExprState *state)
+ExecInstantiateExpr(ExprState *state, PlanState *parent)
{
#ifdef USE_LLVM
- ExecInstantiateCompiledExpr(state);
+ ExecInstantiateCompiledExpr(state, parent);
if (!state->cb)
#endif
{
- ExecInstantiateInterpretedExpr(state);
+ ExecInstantiateInterpretedExpr(state, parent);
}
}
* Prepare ExprState for interpreted execution.
*/
void
-ExecInstantiateInterpretedExpr(ExprState *state)
+ExecInstantiateInterpretedExpr(ExprState *state, PlanState *parent)
{
ExecPrepareInterp();
*/
ExecResetTupleTable(estate->es_tupleTable, false);
+ ExecResetExpressions(estate->es_handles);
+
/*
* close the result relation(s) if any, but hold locks until xact commit.
*/
list_free(tupleTable);
}
+#include "lib/llvmjit.h"
+
+void
+ExecResetExpressions(List *exprTable)
+{
+ ListCell *lc;
+
+ foreach(lc, exprTable)
+ {
+ llvm_release_handle(CurrentResourceOwner, lfirst_int(lc));
+ }
+}
+
/* --------------------------------
* MakeSingleTupleTableSlot
*
#include "lib/llvmjit.h"
+#include "utils/memutils.h"
+#include "utils/resowner_private.h"
+
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <llvm-c/Target.h>
#include <llvm-c/Analysis.h>
#include <llvm-c/BitWriter.h>
+#include <llvm-c/OrcBindings.h>
+#include <llvm-c/Support.h>
+#include <llvm-c/Transforms/PassManagerBuilder.h>
-#include "utils/memutils.h"
/* GUCs */
bool jit_log_ir = 0;
LLVMTypeRef StructBlockId;
LLVMTypeRef StructTupleTableSlot;
+static char *llvm_triple = NULL;
+static LLVMTargetRef llvm_targetref;
+static LLVMTargetMachineRef llvm_targetmachine;
+static LLVMOrcJITStackRef llvm_orc;
+
static void
shutdown_perf(void)
{
LLVMInitializeNativeAsmPrinter();
LLVMInitializeNativeAsmParser();
+ llvm_triple = LLVMGetDefaultTargetTriple();
+
+ if (LLVMGetTargetFromTriple(llvm_triple, &llvm_targetref, &error) != 0)
+ {
+ fprintf(stderr, "failed to create targetref: %s\n", error);
+ abort();
+ }
+
+ llvm_targetmachine =
+ LLVMCreateTargetMachine(llvm_targetref, llvm_triple, NULL, NULL,
+ LLVMCodeGenLevelAggressive,
+ LLVMRelocDefault,
+ LLVMCodeModelJITDefault);
+
+ {
+ LLVMPassManagerRef pm = LLVMCreatePassManager();
+ LLVMPassManagerBuilderRef pmb = LLVMPassManagerBuilderCreate();
+ LLVMPassManagerBuilderSetOptLevel(pmb, 3);
+
+ LLVMPassManagerBuilderPopulateModulePassManager(pmb, pm);
+
+ LLVMAddAnalysisPasses(llvm_targetmachine, pm);
+ }
+
+ llvm_orc = LLVMOrcCreateInstance(llvm_targetmachine);
+
llvm_mod = LLVMModuleCreateWithName("top_module");
LLVMSetTarget(llvm_mod, "x86_64-unknown-linux-gnu");
}
}
+#include "executor/tuptable.h"
+static uint64_t
+resolver(const char *name, void *ctx)
+{
+ return (uint64_t) LLVMSearchForAddressOfSymbol(name);
+ if (strcmp(name, "slot_getsomeattrs") == 0)
+ return (uint64_t) slot_getsomeattrs;
+ //elog(ERROR, "resolvin %s", name);
+ return 0;
+}
+
+void *
+llvm_get_function2(LLVMModuleRef mod, const char *funcname, int *handle)
+{
+ void *addr;
+ char *mangled;
+
+ if (jit_log_ir)
+ {
+ LLVMDumpModule(mod);
+ }
+
+
+ LLVMOrcGetMangledSymbol(llvm_orc, &mangled, funcname);
+
+ *handle =
+ LLVMOrcAddEagerlyCompiledIR(llvm_orc, mod,
+ resolver, NULL);
+
+ ResourceOwnerEnlargeJIT(CurrentResourceOwner);
+ ResourceOwnerRememberJIT(CurrentResourceOwner, *handle);
+
+ addr = (void *) LLVMOrcGetSymbolAddress(llvm_orc, mangled);
+
+ if (!addr)
+ elog(ERROR, "failed to JIT: %s %s", funcname, mangled);
+
+ return addr;
+}
+
#endif /* USE_LLVM */
+
+
+#ifdef USE_LLVM
+
+extern void
+llvm_release_handle(ResourceOwner resowner, Datum handle)
+{
+ LLVMOrcRemoveModule(llvm_orc, handle);
+
+ ResourceOwnerForgetJIT(resowner, handle);
+
+}
+
+#else
+
+extern void
+llvm_release_handle(ResourceOwner resowner, Datum handle)
+{
+}
+
+#endif
#include "utils/rel.h"
#include "utils/resowner_private.h"
#include "utils/snapmgr.h"
+#include "lib/llvmjit.h"
/*
ResourceArray snapshotarr; /* snapshot references */
ResourceArray filearr; /* open temporary files */
ResourceArray dsmarr; /* dynamic shmem segments */
+ ResourceArray jitarr; /* JIT handles */
/* We can remember up to MAX_RESOWNER_LOCKS references to local locks. */
int nlocks; /* number of owned locks */
ResourceArrayInit(&(owner->snapshotarr), PointerGetDatum(NULL));
ResourceArrayInit(&(owner->filearr), FileGetDatum(-1));
ResourceArrayInit(&(owner->dsmarr), PointerGetDatum(NULL));
+ ResourceArrayInit(&(owner->jitarr), Int32GetDatum(-1));
return owner;
}
PrintDSMLeakWarning(res);
dsm_detach(res);
}
+
+ /* Ditto for dynamic shared memory segments */
+ while (ResourceArrayGetAny(&(owner->jitarr), &foundres))
+ {
+ llvm_release_handle(owner, foundres);
+ }
+
}
else if (phase == RESOURCE_RELEASE_LOCKS)
{
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);
/*
ResourceArrayFree(&(owner->snapshotarr));
ResourceArrayFree(&(owner->filearr));
ResourceArrayFree(&(owner->dsmarr));
+ ResourceArrayFree(&(owner->jitarr));
pfree(owner);
}
elog(WARNING, "dynamic shared memory leak: segment %u still referenced",
dsm_segment_handle(seg));
}
+
+void
+ResourceOwnerEnlargeJIT(ResourceOwner owner)
+{
+ ResourceArrayEnlarge(&(owner->jitarr));
+}
+
+void
+ResourceOwnerRememberJIT(ResourceOwner owner, Datum handle)
+{
+ ResourceArrayAdd(&(owner->jitarr), handle);
+}
+
+void
+ResourceOwnerForgetJIT(ResourceOwner owner, Datum handle)
+{
+ if (!ResourceArrayRemove(&(owner->jitarr), handle))
+ elog(ERROR, "jit %lu is not owned by resource owner %s",
+ handle, owner->name);
+}
bool prevnull;
} ArrayRefState;
-extern void ExecInstantiateInterpretedExpr(ExprState *state);
-extern void ExecInstantiateCompiledExpr(ExprState *state);
+extern void ExecInstantiateInterpretedExpr(ExprState *state, PlanState *parent);
+extern void ExecInstantiateCompiledExpr(ExprState *state, PlanState *parent);
extern ExprEvalOp ExecEvalStepOp(ExprState *state, ExprEvalStep *op);
extern TupleTableSlot *MakeTupleTableSlot(void);
extern TupleTableSlot *ExecAllocTableSlot(List **tupleTable);
extern void ExecResetTupleTable(List *tupleTable, bool shouldFree);
+extern void ExecResetExpressions(List *exprTable);
extern TupleTableSlot *MakeSingleTupleTableSlot(TupleDesc tupdesc);
extern void ExecDropSingleTupleTableSlot(TupleTableSlot *slot);
extern void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc);
#ifndef LLVMJIT_H
#define LLVMJIT_H
+
+#include "utils/resowner.h"
+
#ifdef USE_LLVM
#undef PM
extern void * llvm_get_function(const char *funcname);
extern void llvm_dispose_module(LLVMModuleRef mod, const char *funcname);
+extern void * llvm_get_function2(LLVMModuleRef mod, const char *funcname, int *handle);
+
+
extern void llvm_perf_support(LLVMExecutionEngineRef EE);
extern void llvm_shutdown_perf_support(LLVMExecutionEngineRef EE);
#endif /* USE_LLVM */
+
+extern void llvm_release_handle(ResourceOwner resowner, Datum handle);
+
#endif /* LLVMJIT_H */
bool *es_epqScanDone; /* true if EPQ tuple has been fetched */
/* The per-query shared memory area to use for parallel execution. */
- struct dsa_area *es_query_dsa;
+ struct dsa_area *es_query_dsa;
+
+ List *es_handles;
+
} EState;
extern void ResourceOwnerForgetDSM(ResourceOwner owner,
dsm_segment *);
+/* support for JITed functions */
+extern void ResourceOwnerEnlargeJIT(ResourceOwner owner);
+extern void ResourceOwnerRememberJIT(ResourceOwner owner,
+ Datum handle);
+extern void ResourceOwnerForgetJIT(ResourceOwner owner,
+ Datum handle);
+
#endif /* RESOWNER_PRIVATE_H */