--- /dev/null
+/*-------------------------------------------------------------------------
+ *
+ * execCompileExpr.c
+ * LLVM compilation based expression evaluation.
+ *
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/executor/execCompileExpr.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#ifdef USE_LLVM
+
+#include "access/htup_details.h"
+#include "access/nbtree.h"
+#include "access/tupconvert.h"
+#include "catalog/objectaccess.h"
+#include "catalog/pg_type.h"
+#include "executor/execdebug.h"
+#include "executor/nodeSubplan.h"
+#include "executor/execExpr.h"
+#include "funcapi.h"
+#include "lib/llvmjit.h"
+#include "miscadmin.h"
+#include "nodes/makefuncs.h"
+#include "nodes/nodeFuncs.h"
+#include "optimizer/planner.h"
+#include "parser/parse_coerce.h"
+#include "parser/parsetree.h"
+#include "pgstat.h"
+#include "utils/acl.h"
+#include "utils/builtins.h"
+#include "utils/date.h"
+#include "utils/lsyscache.h"
+#include "utils/memutils.h"
+#include "utils/timestamp.h"
+#include "utils/typcache.h"
+#include "utils/xml.h"
+
+bool jit_expressions = false;
+
+static LLVMTypeRef StructExprState;
+static LLVMTypeRef StructExprContext;
+static LLVMTypeRef TypePGFunction;
+
+static void
+create_types(void)
+{
+ if (!StructExprState)
+ {
+ {
+ LLVMTypeRef members[12];
+
+ members[ 0] = LLVMInt32Type(); /* tag */
+ members[ 1] = LLVMInt8Type(); /* resnull */
+ members[ 2] = TypeSizeT; /* resvalue */
+ members[ 3] = LLVMPointerType(TypeSizeT, 0); /* steps */
+ members[ 4] = LLVMPointerType(StructTupleTableSlot, 0); /* resultslot */
+ members[ 5] = LLVMPointerType(TypeSizeT, 0); /* cb */
+ members[ 5] = LLVMPointerType(TypeSizeT, 0); /* expr */
+ members[ 6] = TypeSizeT; /* steps_alloc */
+ members[ 7] = TypeSizeT; /* steps_len */
+ members[ 8] = LLVMPointerType(TypeSizeT, 0); /* innermost caseval */
+ members[ 9] = LLVMPointerType(LLVMInt8Type(), 0); /* innermost casenull */
+ members[10] = LLVMPointerType(TypeSizeT, 0); /* innermost domainval */
+ members[11] = LLVMPointerType(LLVMInt8Type(), 0); /* innermost domainnull */
+
+ StructExprState = LLVMStructCreateNamed(LLVMGetGlobalContext(),
+ "struct.ExprState");
+ LLVMStructSetBody(StructExprState, members, lengthof(members), false);
+ }
+
+ {
+ LLVMTypeRef members[16];
+
+ members[ 0] = LLVMInt32Type(); /* tag */
+ members[ 1] = LLVMPointerType(StructTupleTableSlot, 0); /* scantuple */
+ members[ 2] = LLVMPointerType(StructTupleTableSlot, 0); /* innertuple */
+ members[ 3] = LLVMPointerType(StructTupleTableSlot, 0); /* outertuple */
+
+ members[ 4] = LLVMPointerType(TypeSizeT, 0); /* per_query_memory */
+ members[ 5] = LLVMPointerType(TypeSizeT, 0); /* per_tuple_memory */
+
+ members[ 6] = LLVMPointerType(TypeSizeT, 0); /* param_exec */
+ members[ 7] = LLVMPointerType(TypeSizeT, 0); /* param_list_info */
+
+ members[ 8] = LLVMPointerType(TypeSizeT, 0); /* aggvalues */
+ members[ 9] = LLVMPointerType(LLVMInt8Type(), 0); /* aggnulls */
+
+ members[10] = TypeSizeT; /* casvalue */
+ members[11] = LLVMInt8Type(); /* casenull */
+
+ members[12] = TypeSizeT; /* domainvalue */
+ members[13] = LLVMInt8Type(); /* domainnull */
+
+ members[14] = LLVMPointerType(TypeSizeT, 0); /* estate */
+ members[15] = LLVMPointerType(TypeSizeT, 0); /* callbacks */
+
+ StructExprContext = LLVMStructCreateNamed(LLVMGetGlobalContext(),
+ "struct.ExprContext");
+ LLVMStructSetBody(StructExprContext, members, lengthof(members), false);
+ }
+
+ {
+ LLVMTypeRef params[1];
+ params[0] = LLVMPointerType(TypeSizeT, 0); /* FIXME: define fmgrinfo properly */
+ TypePGFunction = LLVMFunctionType(TypeSizeT, params, lengthof(params), 0);
+ }
+ }
+}
+
+static LLVMValueRef
+create_slot_getsomeattrs(LLVMModuleRef mod)
+{
+ LLVMTypeRef sig;
+ LLVMValueRef fn;
+ LLVMTypeRef param_types[2];
+
+ param_types[0] = LLVMPointerType(StructTupleTableSlot, 0);
+ param_types[1] = LLVMInt32Type();
+
+ sig = LLVMFunctionType(LLVMInt64Type(), param_types, lengthof(param_types), 0);
+ fn = LLVMAddFunction(mod, "slot_getsomeattrs", sig);
+
+ return fn;
+}
+
+
+static LLVMValueRef
+create_heap_getsysattr(LLVMModuleRef mod)
+{
+ LLVMTypeRef sig;
+ LLVMValueRef fn;
+ LLVMTypeRef param_types[4];
+
+ param_types[0] = LLVMPointerType(StructHeapTupleData, 0);
+ param_types[1] = LLVMInt32Type();
+ param_types[2] = LLVMPointerType(TypeSizeT, 0);
+ param_types[3] = LLVMPointerType(LLVMInt8Type(), 0);
+
+ sig = LLVMFunctionType(LLVMInt64Type(), param_types, lengthof(param_types), 0);
+ fn = LLVMAddFunction(mod, "heap_getsysattr", sig);
+
+ return fn;
+}
+
+static LLVMValueRef
+create_EvalXFunc(LLVMModuleRef mod, const char *funcname)
+{
+ LLVMTypeRef sig;
+ LLVMValueRef fn;
+ LLVMTypeRef param_types[3];
+
+ param_types[0] = LLVMPointerType(StructExprState, 0);
+ param_types[1] = LLVMPointerType(TypeSizeT, 0);
+ param_types[2] = LLVMPointerType(StructExprContext, 0);
+
+ sig = LLVMFunctionType(LLVMVoidType(), param_types, lengthof(param_types), 0);
+ fn = LLVMAddFunction(mod, funcname, sig);
+
+ return fn;
+}
+
+static LLVMValueRef
+create_EvalArrayRefCheckSubscript(LLVMModuleRef mod)
+{
+ LLVMTypeRef sig;
+ LLVMValueRef fn;
+ LLVMTypeRef param_types[3];
+
+ param_types[0] = LLVMPointerType(StructExprState, 0);
+ param_types[1] = LLVMPointerType(TypeSizeT, 0);
+ param_types[2] = LLVMPointerType(StructExprContext, 0);
+
+ sig = LLVMFunctionType(LLVMInt8Type(), param_types, lengthof(param_types), 0);
+ fn = LLVMAddFunction(mod, "ExecEvalArrayRefCheckSubscript", sig);
+
+ return fn;
+}
+
+void
+ExecInstantiateCompiledExpr(ExprState *state)
+{
+ ExprEvalStep *op;
+ int i = 0;
+ static int exprcounter = 0;
+ char *funcname;
+
+ LLVMBuilderRef builder;
+ LLVMModuleRef mod;
+ LLVMTypeRef eval_sig;
+ LLVMValueRef eval_fn;
+ LLVMBasicBlockRef entry;
+ LLVMBasicBlockRef *opblocks;
+
+ /* referenced functions */
+ LLVMValueRef l_slot_getsomeattrs;
+ LLVMValueRef l_heap_getsysattr = NULL;
+
+ LLVMValueRef l_EvalWholeRowVar = NULL;
+ LLVMValueRef l_EvalParamExec = NULL;
+ LLVMValueRef l_EvalParamExtern = NULL;
+ LLVMValueRef l_EvalRowNull = NULL;
+ LLVMValueRef l_EvalRowNotNull = NULL;
+ LLVMValueRef l_EvalSQLValueFunction = NULL;
+ LLVMValueRef l_EvalCurrentOfExpr = NULL;
+ LLVMValueRef l_EvalArrayExpr = NULL;
+ LLVMValueRef l_EvalArrayCoerce = NULL;
+ LLVMValueRef l_EvalRow = NULL;
+ LLVMValueRef l_EvalMinMax = NULL;
+ LLVMValueRef l_EvalFieldSelect = NULL;
+ LLVMValueRef l_EvalFieldStoreDeForm = NULL;
+ LLVMValueRef l_EvalFieldStoreForm = NULL;
+ LLVMValueRef l_EvalArrayRefCheckSubscript = NULL;
+ LLVMValueRef l_EvalArrayRefFetch = NULL;
+ LLVMValueRef l_EvalArrayRefAssign = NULL;
+ LLVMValueRef l_EvalArrayRefOld = NULL;
+ LLVMValueRef l_EvalConvertRowtype = NULL;
+ LLVMValueRef l_EvalScalarArrayOp = NULL;
+ LLVMValueRef l_EvalConstraintNotNull = NULL;
+ LLVMValueRef l_EvalConstraintCheck = NULL;
+ LLVMValueRef l_EvalXmlExpr = NULL;
+ LLVMValueRef l_EvalGroupingFunc = NULL;
+ LLVMValueRef l_EvalSubPlan = NULL;
+ LLVMValueRef l_EvalAlternativeSubPlan = NULL;
+
+ /* state itself */
+ LLVMValueRef v_state;
+ LLVMValueRef v_econtext;
+
+ /* returnvalue */
+ LLVMValueRef v_isnullp;
+
+ /* tmp vars in state */
+ LLVMValueRef v_tmpvaluep;
+ LLVMValueRef v_tmpisnullp;
+
+ /* slots */
+ LLVMValueRef v_innerslot;
+ LLVMValueRef v_outerslot;
+ LLVMValueRef v_scanslot;
+ LLVMValueRef v_resultslot;
+
+ /* nulls/values of slots */
+ LLVMValueRef v_innervalues;
+ LLVMValueRef v_innernulls;
+ LLVMValueRef v_outervalues;
+ LLVMValueRef v_outernulls;
+ LLVMValueRef v_scanvalues;
+ LLVMValueRef v_scannulls;
+ LLVMValueRef v_resultvalues;
+ LLVMValueRef v_resultnulls;
+
+ /* stuff in econtext */
+ LLVMValueRef v_aggvalues;
+ LLVMValueRef v_aggnulls;
+
+ /* only do JITing if enabled */
+ if (!jit_expressions)
+ return;
+
+ llvm_initialize();
+ create_types();
+
+ /* setup state */
+ op = state->steps;
+
+ funcname = psprintf("evalexpr%d", exprcounter);
+ exprcounter++;
+
+ builder = LLVMCreateBuilder();
+
+ /* Create the signature and function */
+ mod = LLVMModuleCreateWithName(funcname);
+ LLVMAddModule(llvm_engine, mod);
+
+ {
+ LLVMTypeRef param_types[] = {
+ LLVMPointerType(StructExprState, 0), /* state */
+ LLVMPointerType(StructExprContext, 0), /* econtext */
+ LLVMPointerType(LLVMInt8Type(), 0)}; /* isnull */
+ eval_sig = LLVMFunctionType(TypeSizeT, param_types, lengthof(param_types), 0);
+ }
+ eval_fn = LLVMAddFunction(mod, funcname, eval_sig);
+ LLVMSetLinkage(eval_fn, LLVMInternalLinkage);
+ entry = LLVMAppendBasicBlock(eval_fn, "entry");
+
+ /* build referenced functions */
+ l_slot_getsomeattrs = create_slot_getsomeattrs(mod);
+
+ /* build state */
+ v_state = LLVMGetParam(eval_fn, 0);
+ v_econtext = LLVMGetParam(eval_fn, 1);
+ v_isnullp = LLVMGetParam(eval_fn, 2);
+
+ LLVMPositionBuilderAtEnd(builder, entry);
+
+ v_tmpvaluep = LLVMBuildStructGEP(builder, v_state, 2, "v.state.resvalue");
+ v_tmpisnullp = LLVMBuildStructGEP(builder, v_state, 1, "v.state.resnull");
+
+ /* build global slots */
+ v_resultslot = LLVMBuildLoad(builder, LLVMBuildStructGEP(builder, v_state, 4, ""), "v_resultslot");
+ v_scanslot = LLVMBuildLoad(builder, LLVMBuildStructGEP(builder, v_econtext, 1, ""), "v_scanslot");
+ v_innerslot = LLVMBuildLoad(builder, LLVMBuildStructGEP(builder, v_econtext, 2, ""), "v_innerslot");
+ v_outerslot = LLVMBuildLoad(builder, LLVMBuildStructGEP(builder, v_econtext, 3, ""), "v_outerslot");
+
+ /* build global values/isnull pointers */
+ v_scanvalues = LLVMBuildLoad(builder, LLVMBuildStructGEP(builder, v_scanslot, 10, ""), "v_scanvalues");
+ v_scannulls = LLVMBuildLoad(builder, LLVMBuildStructGEP(builder, v_scanslot, 11, ""), "v_scannulls");
+ v_innervalues = LLVMBuildLoad(builder, LLVMBuildStructGEP(builder, v_innerslot, 10, ""), "v_innervalues");
+ v_innernulls = LLVMBuildLoad(builder, LLVMBuildStructGEP(builder, v_innerslot, 11, ""), "v_innernulls");
+ v_outervalues = LLVMBuildLoad(builder, LLVMBuildStructGEP(builder, v_outerslot, 10, ""), "v_outervalues");
+ v_outernulls = LLVMBuildLoad(builder, LLVMBuildStructGEP(builder, v_outerslot, 11, ""), "v_outernulls");
+ v_resultvalues = LLVMBuildLoad(builder, LLVMBuildStructGEP(builder, v_resultslot, 10, ""), "v_resultvalues");
+ v_resultnulls = LLVMBuildLoad(builder, LLVMBuildStructGEP(builder, v_resultslot, 11, ""), "v_resultnulls");
+
+ /* aggvalues/aggnulls */
+ v_aggvalues = LLVMBuildLoad(builder, LLVMBuildStructGEP(builder, v_econtext, 8, ""), "v.econtext.aggvalues");
+ v_aggnulls = LLVMBuildLoad(builder, LLVMBuildStructGEP(builder, v_econtext, 9, ""), "v.econtext.aggnulls");
+
+ /* allocate blocks for each op upfront, so we can do jumps easily */
+ opblocks = palloc(sizeof(LLVMBasicBlockRef) * state->steps_len);
+ for (i = 0; i < state->steps_len;i++)
+ {
+ char *blockname = psprintf("block.op.%d.start", i);
+ opblocks[i] = LLVMAppendBasicBlock(eval_fn, blockname);
+ pfree(blockname);
+ }
+
+ /* jump from entry to first block */
+ LLVMBuildBr(builder, opblocks[0]);
+
+ for (i = 0; i < state->steps_len;i++)
+ {
+ LLVMValueRef v_resvaluep; /* FIXME */
+ LLVMValueRef v_resnullp;
+
+ LLVMPositionBuilderAtEnd(builder, opblocks[i]);
+
+ op = &state->steps[i];
+
+ v_resvaluep = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (intptr_t) op->resvalue, false),
+ LLVMPointerType(TypeSizeT, 0),
+ "v_resvaluep");
+ v_resnullp = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (intptr_t) op->resnull, false),
+ LLVMPointerType(LLVMInt8Type(), 0),
+ "v_resnullp");
+
+ switch ((ExprEvalOp) op->opcode)
+ {
+ case EEO_DONE:
+ {
+ LLVMValueRef v_tmpisnull, v_tmpvalue;
+
+ v_tmpvalue = LLVMBuildLoad(builder, v_tmpvaluep, "");
+ v_tmpisnull = LLVMBuildLoad(builder, v_tmpisnullp, "");
+
+ LLVMBuildStore(builder, v_tmpisnull, v_isnullp);
+ LLVMBuildRet(builder, v_tmpvalue);
+ break;
+ }
+ case EEO_INNER_FETCHSOME:
+ case EEO_OUTER_FETCHSOME:
+ case EEO_SCAN_FETCHSOME:
+ {
+ LLVMValueRef params[2];
+ if (op->opcode == EEO_INNER_FETCHSOME)
+ params[0] = v_innerslot;
+ else if (op->opcode == EEO_OUTER_FETCHSOME)
+ params[0] = v_outerslot;
+ else
+ params[0] = v_scanslot;
+
+ params[1] = LLVMConstInt(LLVMInt32Type(), op->d.fetch.last_var, false);
+ LLVMBuildCall(builder, l_slot_getsomeattrs, params, 2, "");
+
+ LLVMBuildBr(builder, opblocks[i + 1]);
+ break;
+ }
+
+ case EEO_INNER_VAR:
+ {
+ LLVMValueRef value, isnull;
+ LLVMValueRef v_attnum;
+
+ v_attnum = LLVMConstInt(LLVMInt32Type(), op->d.var.attnum, false);
+ value = LLVMBuildLoad(builder, LLVMBuildGEP(builder, v_innervalues, &v_attnum, 1, ""), "");
+ isnull = LLVMBuildLoad(builder, LLVMBuildGEP(builder, v_innernulls, &v_attnum, 1, ""), "");
+ LLVMBuildStore(builder, value, v_resvaluep);
+ LLVMBuildStore(builder, isnull, v_resnullp);
+
+ LLVMBuildBr(builder, opblocks[i + 1]);
+ break;
+ }
+ case EEO_OUTER_VAR:
+ {
+ LLVMValueRef value, isnull;
+ LLVMValueRef v_attnum;
+
+ v_attnum = LLVMConstInt(LLVMInt32Type(), op->d.var.attnum, false);
+ value = LLVMBuildLoad(builder, LLVMBuildGEP(builder, v_outervalues, &v_attnum, 1, ""), "");
+ isnull = LLVMBuildLoad(builder, LLVMBuildGEP(builder, v_outernulls, &v_attnum, 1, ""), "");
+ LLVMBuildStore(builder, value, v_resvaluep);
+ LLVMBuildStore(builder, isnull, v_resnullp);
+
+ LLVMBuildBr(builder, opblocks[i + 1]);
+ break;
+ }
+
+ case EEO_SCAN_VAR:
+ {
+ LLVMValueRef value, isnull;
+ LLVMValueRef v_attnum;
+
+ v_attnum = LLVMConstInt(LLVMInt32Type(), op->d.var.attnum, false);
+ value = LLVMBuildLoad(builder, LLVMBuildGEP(builder, v_scanvalues, &v_attnum, 1, ""), "");
+ isnull = LLVMBuildLoad(builder, LLVMBuildGEP(builder, v_scannulls, &v_attnum, 1, ""), "");
+ LLVMBuildStore(builder, value, v_resvaluep);
+ LLVMBuildStore(builder, isnull, v_resnullp);
+
+ LLVMBuildBr(builder, opblocks[i + 1]);
+ break;
+ }
+
+ case EEO_ASSIGN_INNER_VAR:
+ {
+ LLVMValueRef v_value, v_isnull;
+ LLVMValueRef v_rvaluep, v_risnullp;
+ LLVMValueRef v_attnum, v_resultnum;
+
+ v_attnum = LLVMConstInt(LLVMInt32Type(), op->d.assign_var.attnum, false);
+ v_resultnum = LLVMConstInt(LLVMInt32Type(), op->d.assign_var.resultnum, false);
+ v_rvaluep = LLVMBuildGEP(builder, v_resultvalues, &v_resultnum, 1, "");
+ v_risnullp = LLVMBuildGEP(builder, v_resultnulls, &v_resultnum, 1, "");
+
+ v_value = LLVMBuildLoad(builder, LLVMBuildGEP(builder, v_innervalues, &v_attnum, 1, ""), "");
+ v_isnull = LLVMBuildLoad(builder, LLVMBuildGEP(builder, v_innernulls, &v_attnum, 1, ""), "");
+
+ LLVMBuildStore(builder, v_value, v_rvaluep);
+ LLVMBuildStore(builder, v_isnull, v_risnullp);
+
+ LLVMBuildBr(builder, opblocks[i + 1]);
+ break;
+
+ }
+
+ case EEO_ASSIGN_OUTER_VAR:
+ {
+ LLVMValueRef v_value, v_isnull;
+ LLVMValueRef v_rvaluep, v_risnullp;
+ LLVMValueRef v_attnum, v_resultnum;
+
+ v_attnum = LLVMConstInt(LLVMInt32Type(), op->d.assign_var.attnum, false);
+ v_resultnum = LLVMConstInt(LLVMInt32Type(), op->d.assign_var.resultnum, false);
+ v_rvaluep = LLVMBuildGEP(builder, v_resultvalues, &v_resultnum, 1, "");
+ v_risnullp = LLVMBuildGEP(builder, v_resultnulls, &v_resultnum, 1, "");
+
+ v_value = LLVMBuildLoad(builder, LLVMBuildGEP(builder, v_outervalues, &v_attnum, 1, ""), "");
+ v_isnull = LLVMBuildLoad(builder, LLVMBuildGEP(builder, v_outernulls, &v_attnum, 1, ""), "");
+
+ LLVMBuildStore(builder, v_value, v_rvaluep);
+ LLVMBuildStore(builder, v_isnull, v_risnullp);
+
+ LLVMBuildBr(builder, opblocks[i + 1]);
+ break;
+ }
+
+ case EEO_ASSIGN_SCAN_VAR:
+ {
+ LLVMValueRef v_value, v_isnull;
+ LLVMValueRef v_rvaluep, v_risnullp;
+ LLVMValueRef v_attnum, v_resultnum;
+
+ v_attnum = LLVMConstInt(LLVMInt32Type(), op->d.assign_var.attnum, false);
+ v_resultnum = LLVMConstInt(LLVMInt32Type(), op->d.assign_var.resultnum, false);
+ v_rvaluep = LLVMBuildGEP(builder, v_resultvalues, &v_resultnum, 1, "");
+ v_risnullp = LLVMBuildGEP(builder, v_resultnulls, &v_resultnum, 1, "");
+
+ v_value = LLVMBuildLoad(builder, LLVMBuildGEP(builder, v_scanvalues, &v_attnum, 1, ""), "");
+ v_isnull = LLVMBuildLoad(builder, LLVMBuildGEP(builder, v_scannulls, &v_attnum, 1, ""), "");
+
+ LLVMBuildStore(builder, v_value, v_rvaluep);
+ LLVMBuildStore(builder, v_isnull, v_risnullp);
+
+ LLVMBuildBr(builder, opblocks[i + 1]);
+ break;
+ }
+
+ case EEO_ASSIGN_TMP:
+ case EEO_ASSIGN_TMP_UNEXPAND: /* FIXME: not correct */
+ {
+ LLVMValueRef v_value, v_isnull;
+ LLVMValueRef v_rvaluep, v_risnullp;
+ LLVMValueRef v_resultnum;
+ size_t resultnum = op->d.assign_tmp.resultnum;
+
+ v_resultnum = LLVMConstInt(LLVMInt32Type(), resultnum, false);
+ v_value = LLVMBuildLoad(builder, v_tmpvaluep, "");
+ v_isnull = LLVMBuildLoad(builder, v_tmpisnullp, "");
+ v_rvaluep = LLVMBuildGEP(builder, v_resultvalues, &v_resultnum, 1, "");
+ v_risnullp = LLVMBuildGEP(builder, v_resultnulls, &v_resultnum, 1, "");
+
+ LLVMBuildStore(builder, v_value, v_rvaluep);
+ LLVMBuildStore(builder, v_isnull, v_risnullp);
+
+ LLVMBuildBr(builder, opblocks[i + 1]);
+ break;
+ }
+
+ case EEO_INNER_SYSVAR:
+ {
+ int attnum = op->d.var.attnum;
+ LLVMValueRef v_attnum;
+ LLVMValueRef v_tuple;
+ LLVMValueRef v_tupleDescriptor;
+ LLVMValueRef v_params[4];
+ LLVMValueRef v_syscol;
+
+ Assert(op->d.var.attnum < 0);
+
+ if (!l_heap_getsysattr)
+ l_heap_getsysattr = create_heap_getsysattr(mod);
+
+ v_tuple = LLVMBuildLoad(
+ builder,
+ LLVMBuildStructGEP(builder, v_innerslot, 5, "v.innertuple"),
+ "");
+ v_tupleDescriptor = LLVMBuildLoad(
+ builder,
+ LLVMBuildStructGEP(builder, v_innerslot, 6, "v.innertupledesc"),
+ "");
+
+ v_attnum = LLVMConstInt(LLVMInt32Type(), attnum, 0);
+
+ v_params[0] = v_tuple;
+ v_params[1] = v_attnum;
+ v_params[2] = v_tupleDescriptor;
+ v_params[3] = v_resnullp;
+ v_syscol = LLVMBuildCall(builder, l_heap_getsysattr, v_params, lengthof(v_params), "");
+ LLVMBuildStore(builder, v_syscol, v_resvaluep);
+
+ LLVMBuildBr(builder, opblocks[i + 1]);
+
+ break;
+ }
+
+ case EEO_OUTER_SYSVAR:
+ {
+ int attnum = op->d.var.attnum;
+ LLVMValueRef v_attnum;
+ LLVMValueRef v_tuple;
+ LLVMValueRef v_tupleDescriptor;
+ LLVMValueRef v_params[4];
+ LLVMValueRef v_syscol;
+
+ Assert(op->d.var.attnum < 0);
+
+ if (!l_heap_getsysattr)
+ l_heap_getsysattr = create_heap_getsysattr(mod);
+
+ v_tuple = LLVMBuildLoad(
+ builder,
+ LLVMBuildStructGEP(builder, v_outerslot, 5, "v.outertuple"),
+ "");
+ v_tupleDescriptor = LLVMBuildLoad(
+ builder,
+ LLVMBuildStructGEP(builder, v_outerslot, 6, "v.outertupledesc"),
+ "");
+
+ v_attnum = LLVMConstInt(LLVMInt32Type(), attnum, 0);
+
+ v_params[0] = v_tuple;
+ v_params[1] = v_attnum;
+ v_params[2] = v_tupleDescriptor;
+ v_params[3] = v_resnullp;
+ v_syscol = LLVMBuildCall(builder, l_heap_getsysattr, v_params, lengthof(v_params), "");
+ LLVMBuildStore(builder, v_syscol, v_resvaluep);
+
+ LLVMBuildBr(builder, opblocks[i + 1]);
+ }
+
+ case EEO_SCAN_SYSVAR:
+ {
+ int attnum = op->d.var.attnum;
+ LLVMValueRef v_attnum;
+ LLVMValueRef v_tuple;
+ LLVMValueRef v_tupleDescriptor;
+ LLVMValueRef v_params[4];
+ LLVMValueRef v_syscol;
+
+ Assert(op->d.var.attnum < 0);
+
+ if (!l_heap_getsysattr)
+ l_heap_getsysattr = create_heap_getsysattr(mod);
+
+ v_tuple = LLVMBuildLoad(
+ builder,
+ LLVMBuildStructGEP(builder, v_scanslot, 5, "v.scantuple"),
+ "");
+ v_tupleDescriptor = LLVMBuildLoad(
+ builder,
+ LLVMBuildStructGEP(builder, v_scanslot, 6, "v.scantupledesc"),
+ "");
+
+ v_attnum = LLVMConstInt(LLVMInt32Type(), attnum, 0);
+
+ v_params[0] = v_tuple;
+ v_params[1] = v_attnum;
+ v_params[2] = v_tupleDescriptor;
+ v_params[3] = v_resnullp;
+ v_syscol = LLVMBuildCall(builder, l_heap_getsysattr, v_params, lengthof(v_params), "");
+ LLVMBuildStore(builder, v_syscol, v_resvaluep);
+
+ LLVMBuildBr(builder, opblocks[i + 1]);
+
+ break;
+ }
+
+ case EEO_CONST:
+ {
+ LLVMValueRef v_constvalue, v_constnull;
+
+ v_constvalue = LLVMConstInt(TypeSizeT, op->d.constval.value, false);
+ v_constnull = LLVMConstInt(LLVMInt8Type(), op->d.constval.isnull, false);
+
+ LLVMBuildStore(builder, v_constvalue, v_resvaluep);
+ LLVMBuildStore(builder, v_constnull, v_resnullp);
+
+ LLVMBuildBr(builder, opblocks[i + 1]);
+ break;
+ }
+
+ case EEO_FUNCEXPR_STRICT:
+ {
+ FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
+ LLVMBasicBlockRef b_nonull = LLVMInsertBasicBlock(opblocks[i], "no-null-args");
+ int argno;
+ LLVMValueRef v_argnullp;
+ LLVMBasicBlockRef *b_checkargnulls;
+
+ /* should make sure they're optimized beforehand */
+ if (op->d.func.nargs == 0)
+ elog(ERROR, "argumentless strict functions are pointless");
+
+ v_argnullp = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (uintptr_t) fcinfo->argnull, false),
+ LLVMPointerType(LLVMInt8Type(), 0),
+ "v_argnullp");
+
+ /* set resnull to true, if the function is actually called, it'll be reset */
+ LLVMBuildStore(builder, LLVMConstInt(LLVMInt8Type(), 1, false), v_resnullp);
+
+ /* create blocks for checking args */
+ b_checkargnulls = palloc(sizeof(LLVMBasicBlockRef *) * op->d.func.nargs);
+ for (argno = 0; argno < op->d.func.nargs;argno++)
+ {
+ b_checkargnulls[argno] = LLVMInsertBasicBlock(opblocks[i], "check-null-arg");
+ }
+
+ LLVMBuildBr(builder, b_checkargnulls[0]);
+
+ /* strict function, check for NULL args */
+ for (argno = 0; argno < op->d.func.nargs;argno++)
+ {
+ LLVMValueRef v_argno = LLVMConstInt(LLVMInt32Type(), argno, false);
+ LLVMValueRef v_argisnull;
+ LLVMBasicBlockRef b_argnotnull;
+
+ LLVMPositionBuilderAtEnd(builder, b_checkargnulls[argno]);
+
+ if (argno + 1 == op->d.func.nargs)
+ b_argnotnull = b_nonull;
+ else
+ b_argnotnull = b_checkargnulls[argno + 1];
+
+ v_argisnull = LLVMBuildLoad(builder, LLVMBuildGEP(builder, v_argnullp, &v_argno, 1, ""), "");
+
+ LLVMBuildCondBr(
+ builder,
+ LLVMBuildICmp(builder, LLVMIntEQ, v_argisnull,
+ LLVMConstInt(LLVMInt8Type(), 1, false), ""),
+ opblocks[i + 1],
+ b_argnotnull);
+ }
+
+ LLVMPositionBuilderAtEnd(builder, b_nonull);
+ }
+ /* explicit fallthrough */
+ case EEO_FUNCEXPR:
+ {
+ FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
+ LLVMValueRef v_fcinfo;
+ LLVMValueRef v_fn_addr;
+ LLVMValueRef v_fcinfo_isnullp;
+ LLVMValueRef v_fcinfo_isnull;
+ LLVMValueRef v_retval;
+
+ v_fcinfo = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (intptr_t) fcinfo, false),
+ LLVMPointerType(TypeSizeT, 0),
+ "v_fcinfo");
+
+ v_fn_addr = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (intptr_t) op->d.func.fn_addr, false),
+ LLVMPointerType(TypePGFunction, 0),
+ "v_fn_addr");
+
+ v_fcinfo_isnullp = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (intptr_t) &fcinfo->isnull, false),
+ LLVMPointerType(LLVMInt8Type(), 0),
+ "v_fcinfo_isnull");
+
+ LLVMBuildStore(builder, LLVMConstInt(LLVMInt8Type(), 0, false),
+ v_fcinfo_isnullp);
+ v_retval = LLVMBuildCall(builder, v_fn_addr, &v_fcinfo, 1, "funccall");
+
+ LLVMBuildStore(builder, v_retval, v_resvaluep);
+ v_fcinfo_isnull = LLVMBuildLoad(builder, v_fcinfo_isnullp, "");
+ LLVMBuildStore(builder, v_fcinfo_isnull, v_resnullp);
+
+ LLVMBuildBr(builder, opblocks[i + 1]);
+ break;
+ }
+
+ case EEO_AGGREF:
+ {
+ AggrefExprState *aggref = op->d.aggref.astate;
+ LLVMValueRef v_aggnop;
+ LLVMValueRef v_aggno;
+ LLVMValueRef value, isnull;
+
+ /*
+ * At this point aggref->aggno has necessarily been set
+ * yet. So load it from memory each time round. Yes,
+ * that's really ugly. XXX
+ */
+ v_aggnop = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(LLVMInt64Type(), (intptr_t) &aggref->aggno, false),
+ LLVMPointerType(LLVMInt32Type(), 0),
+ "aggnop");
+ v_aggno = LLVMBuildLoad(builder, v_aggnop, "");
+ value = LLVMBuildLoad(builder, LLVMBuildGEP(builder, v_aggvalues, &v_aggno, 1, ""), "aggvalue");
+ isnull = LLVMBuildLoad(builder, LLVMBuildGEP(builder, v_aggnulls, &v_aggno, 1, ""), "aggnull");
+
+ LLVMBuildStore(builder, value, v_resvaluep);
+ LLVMBuildStore(builder, isnull, v_resnullp);
+
+ LLVMBuildBr(builder, opblocks[i + 1]);
+ break;
+ }
+ case EEO_WINDOW_FUNC:
+ {
+ WindowFuncExprState *wfunc = op->d.window_func.wfstate;
+ LLVMValueRef v_aggnop;// = LLVMConstInt(LLVMInt32Type(), wfunc->wfuncno, false);
+ LLVMValueRef v_aggno;
+ LLVMValueRef value, isnull;
+
+ /*
+ * At this point wfuncref->wfuncno has necessarily been set
+ * yet. So load it from memory each time round. Yes,
+ * that's really ugly. XXX
+ */
+ v_aggnop = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(LLVMInt64Type(), (intptr_t) &wfunc->wfuncno, false),
+ LLVMPointerType(LLVMInt32Type(), 0),
+ "aggnop");
+
+ v_aggno = LLVMBuildLoad(builder, v_aggnop, "");
+ value = LLVMBuildLoad(builder, LLVMBuildGEP(builder, v_aggvalues, &v_aggno, 1, ""), "windowvalue");
+ isnull = LLVMBuildLoad(builder, LLVMBuildGEP(builder, v_aggnulls, &v_aggno, 1, ""), "windownull");
+
+ LLVMBuildStore(builder, value, v_resvaluep);
+ LLVMBuildStore(builder, isnull, v_resnullp);
+
+ LLVMBuildBr(builder, opblocks[i + 1]);
+ break;
+ }
+
+ case EEO_BOOL_AND_STEP_FIRST:
+ {
+ LLVMValueRef v_boolanynullp;
+
+ v_boolanynullp = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(LLVMInt64Type(), (intptr_t) op->d.boolexpr.anynull, false),
+ LLVMPointerType(LLVMInt8Type(), 0),
+ "boolanynull");
+ LLVMBuildStore(builder, LLVMConstInt(LLVMInt8Type(), 0, false), v_boolanynullp);
+
+ /* intentionally fall through */
+ }
+ case EEO_BOOL_AND_STEP:
+ {
+ LLVMValueRef v_boolvaluep, v_boolvalue;
+ LLVMValueRef v_boolnullp, v_boolnull;
+ LLVMValueRef v_boolanynullp, v_boolanynull;
+ LLVMBasicBlockRef boolisnullblock;
+ LLVMBasicBlockRef boolcheckfalseblock;
+ LLVMBasicBlockRef boolisfalseblock;
+ LLVMBasicBlockRef boolcontblock;
+ LLVMBasicBlockRef boolisanynullblock;
+ char *blockname;
+
+ blockname = psprintf("block.op.%d.boolisnull", i);
+ boolisnullblock = LLVMAppendBasicBlock(eval_fn, blockname);
+ pfree(blockname);
+
+ blockname = psprintf("block.op.%d.boolcheckfalse", i);
+ boolcheckfalseblock = LLVMAppendBasicBlock(eval_fn, blockname);
+ pfree(blockname);
+
+ blockname = psprintf("block.op.%d.boolisfalse", i);
+ boolisfalseblock = LLVMAppendBasicBlock(eval_fn, blockname);
+ pfree(blockname);
+
+ blockname = psprintf("block.op.%d.boolisanynullblock", i);
+ boolisanynullblock = LLVMAppendBasicBlock(eval_fn, blockname);
+ pfree(blockname);
+
+ blockname = psprintf("block.op.%d.boolcontblock", i);
+ boolcontblock = LLVMAppendBasicBlock(eval_fn, blockname);
+ pfree(blockname);
+
+ v_boolvaluep = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(LLVMInt64Type(), (intptr_t) op->d.boolexpr.value, false),
+ LLVMPointerType(TypeSizeT, 0),
+ "boolvaluep");
+
+ v_boolnullp = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(LLVMInt64Type(), (intptr_t) op->d.boolexpr.isnull, false),
+ LLVMPointerType(LLVMInt8Type(), 0),
+ "boolnullp");
+
+ v_boolanynullp = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(LLVMInt64Type(), (intptr_t) op->d.boolexpr.anynull, false),
+ LLVMPointerType(LLVMInt8Type(), 0),
+ "anynull");
+
+ v_boolnull = LLVMBuildLoad(builder, v_boolnullp, "");
+ v_boolvalue = LLVMBuildLoad(builder, v_boolvaluep, "");
+
+ /* set resnull to boolnull */
+ LLVMBuildStore(builder, v_boolnull, v_resnullp);
+ /* set revalue to boolvalue */
+ LLVMBuildStore(builder, v_boolvalue, v_resvaluep);
+
+ LLVMBuildCondBr(
+ builder,
+ LLVMBuildICmp(builder, LLVMIntEQ, v_boolnull,
+ LLVMConstInt(LLVMInt8Type(), 1, false), ""),
+ boolisnullblock,
+ boolcheckfalseblock);
+
+ /* build block that checks that sets anynull */
+ LLVMPositionBuilderAtEnd(builder, boolisnullblock);
+ /* set boolanynull to true */
+ LLVMBuildStore(builder, LLVMConstInt(LLVMInt8Type(), 1, false), v_boolanynullp);
+ /* set resnull to true */
+ LLVMBuildStore(builder, LLVMConstInt(LLVMInt8Type(), 1, false), v_resnullp);
+ /* reset resvalue (cleanliness) */
+ LLVMBuildStore(builder, LLVMConstInt(TypeSizeT, 0, false), v_resvaluep);
+ /* and jump to next block */
+ LLVMBuildBr(builder, boolcontblock);
+
+ /* build block checking for false, which can jumps out at false */
+ LLVMPositionBuilderAtEnd(builder, boolcheckfalseblock);
+ LLVMBuildCondBr(
+ builder,
+ LLVMBuildICmp(builder, LLVMIntEQ, v_boolvalue,
+ LLVMConstInt(LLVMInt64Type(), 0, false), ""),
+ boolisfalseblock,
+ boolcontblock);
+
+ /* Build block handling FALSE. Value is false, so short circuit. */
+ LLVMPositionBuilderAtEnd(builder, boolisfalseblock);
+ /* set resnull to false */
+ LLVMBuildStore(builder, LLVMConstInt(LLVMInt8Type(), 0, false), v_resnullp);
+ /* reset resvalue to false */
+ LLVMBuildStore(builder, LLVMConstInt(TypeSizeT, 0, false), v_resvaluep);
+ /* and jump to the end of the AND expression */
+ LLVMBuildBr(builder, opblocks[op->d.boolexpr.jumpdone]);
+
+ /* build block that continues if bool is TRUE */
+ LLVMPositionBuilderAtEnd(builder, boolcontblock);
+
+ v_boolanynull = LLVMBuildLoad(builder, v_boolanynullp, "");
+
+ /* set value to NULL if any previous values were NULL */
+ LLVMBuildCondBr(
+ builder,
+ LLVMBuildICmp(builder, LLVMIntEQ, v_boolanynull,
+ LLVMConstInt(LLVMInt8Type(), 0, false), ""),
+ opblocks[i + 1], boolisanynullblock);
+
+ LLVMPositionBuilderAtEnd(builder, boolisanynullblock);
+ /* set resnull to true */
+ LLVMBuildStore(builder, LLVMConstInt(LLVMInt8Type(), 1, true), v_resnullp);
+ /* reset resvalue */
+ LLVMBuildStore(builder, LLVMConstInt(TypeSizeT, 0, false), v_resvaluep);
+
+ LLVMBuildBr(builder, opblocks[i + 1]);
+ break;
+ }
+ case EEO_BOOL_OR_STEP_FIRST:
+ {
+ LLVMValueRef v_boolanynullp;
+
+ v_boolanynullp = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(LLVMInt64Type(), (intptr_t) op->d.boolexpr.anynull, false),
+ LLVMPointerType(LLVMInt8Type(), 0),
+ "boolanynull");
+ LLVMBuildStore(builder, LLVMConstInt(LLVMInt8Type(), 0, false), v_boolanynullp);
+
+ /* intentionally fall through */
+ }
+ case EEO_BOOL_OR_STEP:
+ {
+ LLVMValueRef v_boolvaluep, v_boolvalue;
+ LLVMValueRef v_boolnullp, v_boolnull;
+ LLVMValueRef v_boolanynullp, v_boolanynull;
+ LLVMBasicBlockRef boolisnullblock;
+ LLVMBasicBlockRef boolchecktrueblock;
+ LLVMBasicBlockRef boolistrueblock;
+ LLVMBasicBlockRef boolcontblock;
+ LLVMBasicBlockRef boolisanynullblock;
+ char *blockname;
+
+ blockname = psprintf("block.op.%d.boolisnull", i);
+ boolisnullblock = LLVMAppendBasicBlock(eval_fn, blockname);
+ pfree(blockname);
+
+ blockname = psprintf("block.op.%d.boolchecktrue", i);
+ boolchecktrueblock = LLVMAppendBasicBlock(eval_fn, blockname);
+ pfree(blockname);
+
+ blockname = psprintf("block.op.%d.boolistrue", i);
+ boolistrueblock = LLVMAppendBasicBlock(eval_fn, blockname);
+ pfree(blockname);
+
+ blockname = psprintf("block.op.%d.boolisanynullblock", i);
+ boolisanynullblock = LLVMAppendBasicBlock(eval_fn, blockname);
+ pfree(blockname);
+
+ blockname = psprintf("block.op.%d.boolcontblock", i);
+ boolcontblock = LLVMAppendBasicBlock(eval_fn, blockname);
+ pfree(blockname);
+
+ v_boolvaluep = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(LLVMInt64Type(), (intptr_t) op->d.boolexpr.value, false),
+ LLVMPointerType(TypeSizeT, 0),
+ "boolvaluep");
+
+ v_boolnullp = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(LLVMInt64Type(), (intptr_t) op->d.boolexpr.isnull, false),
+ LLVMPointerType(LLVMInt8Type(), 0),
+ "boolnullp");
+
+ v_boolanynullp = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(LLVMInt64Type(), (intptr_t) op->d.boolexpr.anynull, false),
+ LLVMPointerType(LLVMInt8Type(), 0),
+ "anynull");
+
+ v_boolnull = LLVMBuildLoad(builder, v_boolnullp, "");
+ v_boolvalue = LLVMBuildLoad(builder, v_boolvaluep, "");
+
+ /* set resnull to boolnull */
+ LLVMBuildStore(builder, v_boolnull, v_resnullp);
+ /* set revalue to boolvalue */
+ LLVMBuildStore(builder, v_boolvalue, v_resvaluep);
+
+ LLVMBuildCondBr(
+ builder,
+ LLVMBuildICmp(builder, LLVMIntEQ, v_boolnull,
+ LLVMConstInt(LLVMInt8Type(), 1, false), ""),
+ boolisnullblock,
+ boolchecktrueblock);
+
+ /* build block that checks that sets anynull */
+ LLVMPositionBuilderAtEnd(builder, boolisnullblock);
+ /* set boolanynull to true */
+ LLVMBuildStore(builder, LLVMConstInt(LLVMInt8Type(), 1, false), v_boolanynullp);
+ /* set resnull to true */
+ LLVMBuildStore(builder, LLVMConstInt(LLVMInt8Type(), 1, false), v_resnullp);
+ /* reset resvalue (cleanliness) */
+ LLVMBuildStore(builder, LLVMConstInt(TypeSizeT, 0, false), v_resvaluep);
+ /* and jump to next block */
+ LLVMBuildBr(builder, boolcontblock);
+
+ /* build block checking for false, which can jumps out at false */
+ LLVMPositionBuilderAtEnd(builder, boolchecktrueblock);
+ LLVMBuildCondBr(
+ builder,
+ LLVMBuildICmp(builder, LLVMIntEQ, v_boolvalue,
+ LLVMConstInt(LLVMInt64Type(), 1, false), ""),
+ boolistrueblock,
+ boolcontblock);
+
+ /* Build block handling TRUE. Value is true, so short circuit. */
+ LLVMPositionBuilderAtEnd(builder, boolistrueblock);
+ /* set resnull to false */
+ LLVMBuildStore(builder, LLVMConstInt(LLVMInt8Type(), 0, false), v_resnullp);
+ /* reset resvalue to true */
+ LLVMBuildStore(builder, LLVMConstInt(TypeSizeT, 1, false), v_resvaluep);
+ /* and jump to the end of the OR expression */
+ LLVMBuildBr(builder, opblocks[op->d.boolexpr.jumpdone]);
+
+ /* build block that continues if bool is FALSE */
+ LLVMPositionBuilderAtEnd(builder, boolcontblock);
+
+ v_boolanynull = LLVMBuildLoad(builder, v_boolanynullp, "");
+
+ /* set value to NULL if any previous values were NULL */
+ LLVMBuildCondBr(
+ builder,
+ LLVMBuildICmp(builder, LLVMIntEQ, v_boolanynull,
+ LLVMConstInt(LLVMInt8Type(), 0, false), ""),
+ opblocks[i + 1], boolisanynullblock);
+
+ LLVMPositionBuilderAtEnd(builder, boolisanynullblock);
+ /* set resnull to true */
+ LLVMBuildStore(builder, LLVMConstInt(LLVMInt8Type(), 1, true), v_resnullp);
+ /* reset resvalue */
+ LLVMBuildStore(builder, LLVMConstInt(TypeSizeT, 0, false), v_resvaluep);
+
+ LLVMBuildBr(builder, opblocks[i + 1]);
+ break;
+ }
+
+ case EEO_BOOL_NOT_STEP:
+ {
+ LLVMValueRef v_boolvaluep, v_boolvalue;
+ LLVMValueRef v_boolnullp, v_boolnull;
+ LLVMValueRef v_negbool;
+
+ v_boolvaluep = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(LLVMInt64Type(), (intptr_t) op->d.boolexpr.value, false),
+ LLVMPointerType(TypeSizeT, 0),
+ "boolvaluep");
+
+ v_boolnullp = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(LLVMInt64Type(), (intptr_t) op->d.boolexpr.isnull, false),
+ LLVMPointerType(LLVMInt8Type(), 0),
+ "boolnullp");
+
+ v_boolnull = LLVMBuildLoad(builder, v_boolnullp, "");
+ v_boolvalue = LLVMBuildLoad(builder, v_boolvaluep, "");
+
+ v_negbool = LLVMBuildZExt(
+ builder,
+ LLVMBuildICmp(builder, LLVMIntEQ, v_boolvalue,
+ LLVMConstInt(TypeSizeT, 0, false), ""),
+ TypeSizeT, "");
+ /* set resnull to boolnull */
+ LLVMBuildStore(builder, v_boolnull, v_resnullp);
+ /* set revalue to !boolvalue */
+ LLVMBuildStore(builder, v_negbool, v_resvaluep);
+
+ LLVMBuildBr(builder, opblocks[i + 1]);
+ break;
+ }
+
+ case EEO_QUAL:
+ {
+ LLVMValueRef v_resnull;
+ LLVMValueRef v_resvalue;
+ LLVMValueRef v_nullorfalse;
+ LLVMBasicBlockRef qualfailblock;
+ char *blockname;
+
+ blockname = psprintf("block.op.%d.qualfail", i);
+ qualfailblock = LLVMAppendBasicBlock(eval_fn, blockname);
+ pfree(blockname);
+
+ v_resvalue = LLVMBuildLoad(builder, v_resvaluep, "");
+ v_resnull = LLVMBuildLoad(builder, v_resnullp, "");
+
+ v_nullorfalse = LLVMBuildOr(
+ builder,
+ LLVMBuildICmp(
+ builder, LLVMIntEQ, v_resnull,
+ LLVMConstInt(LLVMInt8Type(), 1, false), ""),
+ LLVMBuildICmp(
+ builder, LLVMIntEQ, v_resvalue,
+ LLVMConstInt(TypeSizeT, 0, false), ""),
+ "");
+
+ LLVMBuildCondBr(
+ builder,
+ v_nullorfalse,
+ qualfailblock,
+ opblocks[i + 1]);
+
+ /* build block handling NULL or false */
+ LLVMPositionBuilderAtEnd(builder, qualfailblock);
+ /* set resnull to false */
+ LLVMBuildStore(builder, LLVMConstInt(LLVMInt8Type(), 0, false), v_resnullp);
+ /* set resvalue to false */
+ LLVMBuildStore(builder, LLVMConstInt(TypeSizeT, 0, false), v_resvaluep);
+ /* and jump out */
+ LLVMBuildBr(builder, opblocks[op->d.qualexpr.jumpdone]);
+
+ break;
+ }
+
+ case EEO_CASE_WHEN_STEP:
+ {
+ LLVMBasicBlockRef b_isnotnullblock;
+ LLVMValueRef v_whenisnullp, v_whenvaluep;
+ LLVMValueRef v_whenisnull, v_whenvalue;
+ char *blockname;
+
+ blockname = psprintf("block.op.%d.when_step_notnull", i);
+ b_isnotnullblock = LLVMInsertBasicBlock(opblocks[i + 1], blockname);
+ pfree(blockname);
+
+ v_whenisnullp = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (uintptr_t) op->d.casewhen.isnull, false),
+ LLVMPointerType(LLVMInt8Type(), 0),
+ "");
+
+ v_whenisnull = LLVMBuildLoad(builder, v_whenisnullp, "");
+
+ /* if value is NULL, jump to false branch */
+ LLVMBuildCondBr(
+ builder,
+ LLVMBuildICmp(builder, LLVMIntEQ, v_whenisnull,
+ LLVMConstInt(LLVMInt8Type(), 1, false), ""),
+ opblocks[op->d.casewhen.jumpfalse],
+ b_isnotnullblock);
+
+ LLVMPositionBuilderAtEnd(builder, b_isnotnullblock);
+
+ v_whenvaluep = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (uintptr_t) op->d.casewhen.value, false),
+ LLVMPointerType(TypeSizeT, 0),
+ "");
+ v_whenvalue = LLVMBuildLoad(builder, v_whenvaluep, "");
+
+ /* if value is true, jump to true branch, otherwise false */
+ LLVMBuildCondBr(
+ builder,
+ LLVMBuildICmp(builder, LLVMIntEQ, v_whenvalue,
+ LLVMConstInt(TypeSizeT, 1, false), ""),
+ opblocks[i + 1],
+ opblocks[op->d.casewhen.jumpfalse]);
+
+ break;
+ }
+
+ case EEO_PARAM_EXEC:
+ case EEO_PARAM_EXTERN:
+ case EEO_SQLVALUEFUNCTION:
+ case EEO_CURRENTOFEXPR:
+ case EEO_ARRAYEXPR:
+ case EEO_ARRAYCOERCE:
+ case EEO_ROW:
+ case EEO_MINMAX:
+ case EEO_FIELDSELECT:
+ case EEO_FIELDSTORE_DEFORM:
+ case EEO_FIELDSTORE_FORM:
+ case EEO_ARRAYREF_ASSIGN:
+ case EEO_ARRAYREF_FETCH:
+ case EEO_ARRAYREF_OLD:
+ case EEO_CONVERT_ROWTYPE:
+ case EEO_SCALARARRAYOP:
+ case EEO_DOMAIN_NOTNULL:
+ case EEO_DOMAIN_CHECK:
+ case EEO_XMLEXPR:
+ case EEO_GROUPING_FUNC:
+ case EEO_SUBPLAN:
+ case EEO_ALTERNATIVE_SUBPLAN:
+ case EEO_NULLTEST_ROWISNULL:
+ case EEO_NULLTEST_ROWISNOTNULL:
+ case EEO_WHOLEROW:
+ {
+ LLVMValueRef v_params[3];
+ const char *funcname;
+ LLVMValueRef *funcptr;
+
+ if (op->opcode == EEO_PARAM_EXEC)
+ {
+ funcname = "ExecEvalParamExec";
+ funcptr = &l_EvalParamExec;
+ }
+ else if (op->opcode == EEO_PARAM_EXTERN)
+ {
+ funcname = "ExecEvalParamExtern";
+ funcptr = &l_EvalParamExtern;
+ }
+ else if (op->opcode == EEO_SQLVALUEFUNCTION)
+ {
+ funcname = "ExecEvalSQLValueFunction";
+ funcptr = &l_EvalSQLValueFunction;
+ }
+ else if (op->opcode == EEO_CURRENTOFEXPR)
+ {
+ funcname = "ExecEvalCurrentOfExpr";
+ funcptr = &l_EvalCurrentOfExpr;
+ }
+ else if (op->opcode == EEO_ARRAYEXPR)
+ {
+ funcname = "ExecEvalArrayExpr";
+ funcptr = &l_EvalArrayExpr;
+ }
+ else if (op->opcode == EEO_ARRAYCOERCE)
+ {
+ funcname = "ExecEvalArrayCoerce";
+ funcptr = &l_EvalArrayCoerce;
+ }
+ else if (op->opcode == EEO_ROW)
+ {
+ funcname = "ExecEvalRow";
+ funcptr = &l_EvalRow;
+ }
+ else if (op->opcode == EEO_MINMAX)
+ {
+ funcname = "ExecEvalMinMax";
+ funcptr = &l_EvalMinMax;
+ }
+ else if (op->opcode == EEO_FIELDSELECT)
+ {
+ funcname = "ExecEvalFieldSelect";
+ funcptr = &l_EvalFieldSelect;
+ }
+ else if (op->opcode == EEO_FIELDSTORE_DEFORM)
+ {
+ funcname = "ExecEvalFieldStoreDeForm";
+ funcptr = &l_EvalFieldStoreDeForm;
+ }
+ else if (op->opcode == EEO_FIELDSTORE_FORM)
+ {
+ funcname = "ExecEvalFieldStoreForm";
+ funcptr = &l_EvalFieldStoreForm;
+ }
+ else if (op->opcode == EEO_ARRAYREF_FETCH)
+ {
+ funcname = "ExecEvalArrayRefFetch";
+ funcptr = &l_EvalArrayRefFetch;
+ }
+ else if (op->opcode == EEO_ARRAYREF_ASSIGN)
+ {
+ funcname = "ExecEvalArrayRefAssign";
+ funcptr = &l_EvalArrayRefAssign;
+ }
+ else if (op->opcode == EEO_ARRAYREF_OLD)
+ {
+ funcname = "ExecEvalArrayRefOld";
+ funcptr = &l_EvalArrayRefOld;
+ }
+ else if (op->opcode == EEO_NULLTEST_ROWISNULL)
+ {
+ funcname = "ExecEvalRowNull";
+ funcptr = &l_EvalRowNull;
+ }
+ else if (op->opcode == EEO_NULLTEST_ROWISNOTNULL)
+ {
+ funcname = "ExecEvalRowNotNull";
+ funcptr = &l_EvalRowNotNull;
+ }
+ else if (op->opcode == EEO_CONVERT_ROWTYPE)
+ {
+ funcname = "ExecEvalConvertRowtype";
+ funcptr = &l_EvalConvertRowtype;
+ }
+ else if (op->opcode == EEO_SCALARARRAYOP)
+ {
+ funcname = "ExecEvalScalarArrayOp";
+ funcptr = &l_EvalScalarArrayOp;
+ }
+ else if (op->opcode == EEO_DOMAIN_NOTNULL)
+ {
+ funcname = "ExecEvalConstraintNotNull";
+ funcptr = &l_EvalConstraintNotNull;
+ }
+ else if (op->opcode == EEO_DOMAIN_CHECK)
+ {
+ funcname = "ExecEvalConstraintCheck";
+ funcptr = &l_EvalConstraintCheck;
+ }
+ else if (op->opcode == EEO_XMLEXPR)
+ {
+ funcname = "ExecEvalXmlExpr";
+ funcptr = &l_EvalXmlExpr;
+ }
+ else if (op->opcode == EEO_GROUPING_FUNC)
+ {
+ funcname = "ExecEvalGroupingFunc";
+ funcptr = &l_EvalGroupingFunc;
+ }
+ else if (op->opcode == EEO_SUBPLAN)
+ {
+ funcname = "ExecEvalSubPlan";
+ funcptr = &l_EvalSubPlan;
+ }
+ else if (op->opcode == EEO_ALTERNATIVE_SUBPLAN)
+ {
+ funcname = "ExecEvalAlternativeSubPlan";
+ funcptr = &l_EvalAlternativeSubPlan;
+ }
+ else if (op->opcode == EEO_WHOLEROW)
+ {
+ funcname = "ExecEvalWholeRowVar";
+ funcptr = &l_EvalWholeRowVar;
+ }
+ else
+ {
+ Assert(false);
+ funcptr = NULL; /* prevent compiler warning */
+ funcname = NULL; /* prevent compiler warning */
+ }
+
+ if (!*funcptr)
+ *funcptr = create_EvalXFunc(mod, funcname);
+
+ v_params[0] = v_state;
+ v_params[1] = LLVMBuildIntToPtr(builder,
+ LLVMConstInt(TypeSizeT, (uintptr_t) op, false),
+ LLVMPointerType(TypeSizeT, 0),
+ "");
+ v_params[2] = v_econtext;
+ LLVMBuildCall(builder, *funcptr, v_params, lengthof(v_params), "");
+ LLVMBuildBr(builder, opblocks[i + 1]);
+ break;
+ }
+
+ case EEO_ARRAYREF_CHECKSUBSCRIPT:
+ {
+ LLVMValueRef v_params[3];
+ LLVMValueRef v_ret;
+
+ if (!l_EvalArrayRefCheckSubscript)
+ l_EvalArrayRefCheckSubscript = create_EvalArrayRefCheckSubscript(mod);
+
+ v_params[0] = v_state;
+ v_params[1] = LLVMBuildIntToPtr(builder,
+ LLVMConstInt(TypeSizeT, (uintptr_t) op, false),
+ LLVMPointerType(TypeSizeT, 0),
+ "");
+ v_params[2] = v_econtext;
+ v_ret = LLVMBuildCall(builder, l_EvalArrayRefCheckSubscript, v_params, lengthof(v_params), "");
+
+ LLVMBuildCondBr(builder,
+ LLVMBuildICmp(builder, LLVMIntEQ, v_ret,
+ LLVMConstInt(LLVMInt8Type(), 1, false), ""),
+ opblocks[i + 1],
+ opblocks[op->d.arrayref_checksubscript.jumpdone]);
+ break;
+ }
+
+ case EEO_CASE_THEN_STEP:
+ {
+ LLVMBuildBr(builder, opblocks[op->d.casethen.jumpdone]);
+ break;
+ }
+
+ case EEO_CASE_TESTVAL_UNEXPAND:
+ case EEO_CASE_TESTVAL:
+ {
+ LLVMBasicBlockRef b_avail, b_notavail;
+ LLVMValueRef v_casevaluep, v_casevalue;
+ LLVMValueRef v_casenullp, v_casenull;
+
+ b_avail = LLVMInsertBasicBlock(opblocks[i + 1], "");
+ b_notavail = LLVMInsertBasicBlock(opblocks[i + 1], "");
+
+ v_casevaluep = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (uintptr_t) op->d.casetest.value, false),
+ LLVMPointerType(TypeSizeT, 0),
+ "");
+ v_casenullp = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (uintptr_t) op->d.casetest.isnull, false),
+ LLVMPointerType(LLVMInt8Type(), 0),
+ "");
+
+ LLVMBuildCondBr(
+ builder,
+ LLVMBuildICmp(builder, LLVMIntEQ,
+ LLVMBuildPtrToInt(builder, v_casevaluep, TypeSizeT, ""),
+ LLVMConstInt(TypeSizeT, 0, false), ""),
+ b_notavail, b_avail);
+
+ /* if casetest != NULL */
+ LLVMPositionBuilderAtEnd(builder, b_avail);
+ v_casevalue = LLVMBuildLoad(builder, v_casevaluep, "");
+ v_casenull = LLVMBuildLoad(builder, v_casenullp, "");
+ LLVMBuildStore(builder, v_casevalue, v_resvaluep);
+ LLVMBuildStore(builder, v_casenull, v_resnullp);
+ LLVMBuildBr(builder, opblocks[i + 1]);
+
+ /* if casetest == NULL */
+ LLVMPositionBuilderAtEnd(builder, b_notavail);
+ v_casevalue = LLVMBuildLoad(
+ builder,
+ LLVMBuildStructGEP(builder, v_econtext, 10, ""), "");
+ v_casenull = LLVMBuildLoad(
+ builder,
+ LLVMBuildStructGEP(builder, v_econtext, 11, ""), "");
+ LLVMBuildStore(builder, v_casevalue, v_resvaluep);
+ LLVMBuildStore(builder, v_casenull, v_resnullp);
+ LLVMBuildBr(builder, opblocks[i + 1]);
+
+ break;
+ }
+
+ case EEO_DOMAIN_TESTVAL_UNEXPAND: /* FIXME: not correct */
+ case EEO_DOMAIN_TESTVAL:
+ {
+ LLVMBasicBlockRef b_avail, b_notavail;
+ LLVMValueRef v_casevaluep, v_casevalue;
+ LLVMValueRef v_casenullp, v_casenull;
+
+ b_avail = LLVMInsertBasicBlock(opblocks[i + 1], "");
+ b_notavail = LLVMInsertBasicBlock(opblocks[i + 1], "");
+
+ v_casevaluep = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (uintptr_t) op->d.casetest.value, false),
+ LLVMPointerType(TypeSizeT, 0),
+ "");
+ v_casenullp = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (uintptr_t) op->d.casetest.isnull, false),
+ LLVMPointerType(LLVMInt8Type(), 0),
+ "");
+
+ LLVMBuildCondBr(
+ builder,
+ LLVMBuildICmp(builder, LLVMIntEQ,
+ LLVMBuildPtrToInt(builder, v_casevaluep, TypeSizeT, ""),
+ LLVMConstInt(TypeSizeT, 0, false), ""),
+ b_notavail, b_avail);
+
+ /* if casetest != NULL */
+ LLVMPositionBuilderAtEnd(builder, b_avail);
+ v_casevalue = LLVMBuildLoad(builder, v_casevaluep, "");
+ v_casenull = LLVMBuildLoad(builder, v_casenullp, "");
+ LLVMBuildStore(builder, v_casevalue, v_resvaluep);
+ LLVMBuildStore(builder, v_casenull, v_resnullp);
+ LLVMBuildBr(builder, opblocks[i + 1]);
+
+ /* if casetest == NULL */
+ LLVMPositionBuilderAtEnd(builder, b_notavail);
+ v_casevalue = LLVMBuildLoad(
+ builder,
+ LLVMBuildStructGEP(builder, v_econtext, 12, ""), "");
+ v_casenull = LLVMBuildLoad(
+ builder,
+ LLVMBuildStructGEP(builder, v_econtext, 13, ""), "");
+ LLVMBuildStore(builder, v_casevalue, v_resvaluep);
+ LLVMBuildStore(builder, v_casenull, v_resnullp);
+ LLVMBuildBr(builder, opblocks[i + 1]);
+
+ break;
+ }
+
+ case EEO_BOOLTEST_IS_UNKNOWN:
+ case EEO_NULLTEST_ISNULL:
+ {
+ LLVMValueRef v_resnull = LLVMBuildLoad(builder, v_resnullp, "");
+ LLVMValueRef v_resvalue;
+
+ v_resvalue = LLVMBuildSelect(
+ builder,
+ LLVMBuildICmp(builder, LLVMIntEQ, v_resnull,
+ LLVMConstInt(LLVMInt8Type(), 1, false), ""),
+ LLVMConstInt(TypeSizeT, 1, false),
+ LLVMConstInt(TypeSizeT, 0, false),
+ "");
+ LLVMBuildStore(
+ builder,
+ v_resvalue,
+ v_resvaluep);
+ LLVMBuildStore(
+ builder,
+ LLVMConstInt(LLVMInt8Type(), 0, false),
+ v_resnullp);
+ LLVMBuildBr(builder, opblocks[i + 1]);
+
+ break;
+ }
+
+ case EEO_BOOLTEST_IS_NOT_UNKNOWN:
+ case EEO_NULLTEST_ISNOTNULL:
+ {
+ LLVMValueRef v_resnull = LLVMBuildLoad(builder, v_resnullp, "");
+ LLVMValueRef v_resvalue;
+
+ v_resvalue = LLVMBuildSelect(
+ builder,
+ LLVMBuildICmp(builder, LLVMIntEQ, v_resnull,
+ LLVMConstInt(LLVMInt8Type(), 1, false), ""),
+ LLVMConstInt(TypeSizeT, 0, false),
+ LLVMConstInt(TypeSizeT, 1, false),
+ "");
+ LLVMBuildStore(
+ builder,
+ v_resvalue,
+ v_resvaluep);
+ LLVMBuildStore(
+ builder,
+ LLVMConstInt(LLVMInt8Type(), 0, false),
+ v_resnullp);
+ LLVMBuildBr(builder, opblocks[i + 1]);
+
+ break;
+ }
+
+ case EEO_BOOLTEST_IS_TRUE:
+ case EEO_BOOLTEST_IS_NOT_FALSE:
+ case EEO_BOOLTEST_IS_FALSE:
+ case EEO_BOOLTEST_IS_NOT_TRUE:
+ {
+ LLVMBasicBlockRef b_isnull, b_notnull;
+ LLVMValueRef v_resnull = LLVMBuildLoad(builder, v_resnullp, "");
+
+ b_isnull = LLVMInsertBasicBlock(opblocks[i + 1], "");
+ b_notnull = LLVMInsertBasicBlock(opblocks[i + 1], "");
+
+ /* result's always not null */
+ LLVMBuildStore(
+ builder,
+ LLVMConstInt(LLVMInt8Type(), 0, false),
+ v_resnullp);
+
+ /* check if value is NULL */
+ LLVMBuildCondBr(
+ builder,
+ LLVMBuildICmp(builder, LLVMIntEQ, v_resnull,
+ LLVMConstInt(LLVMInt8Type(), 1, false), ""),
+ b_isnull, b_notnull);
+
+ /* if value is NULL, return false */
+ LLVMPositionBuilderAtEnd(builder, b_isnull);
+ LLVMBuildStore(
+ builder,
+ LLVMConstInt(TypeSizeT, 0, false),
+ v_resvaluep);
+ LLVMBuildBr(builder, opblocks[i + 1]);
+
+ LLVMPositionBuilderAtEnd(builder, b_notnull);
+
+ if (op->opcode == EEO_BOOLTEST_IS_TRUE ||
+ op->opcode == EEO_BOOLTEST_IS_NOT_FALSE)
+ {
+ /* if value is not null NULL, return value (already set) */
+ }
+ else
+ {
+ LLVMValueRef v_value = LLVMBuildLoad(
+ builder, v_resvaluep, "");
+
+ v_value = LLVMBuildZExt(
+ builder,
+ LLVMBuildICmp(builder, LLVMIntEQ, v_value,
+ LLVMConstInt(TypeSizeT, 0, false), ""),
+ TypeSizeT, "");
+ LLVMBuildStore(
+ builder,
+ v_value,
+ v_resvaluep);
+ }
+ LLVMBuildBr(builder, opblocks[i + 1]);
+ break;
+ }
+
+ case EEO_COALESCE:
+ {
+ LLVMValueRef v_resnull = LLVMBuildLoad(builder, v_resnullp, "");
+
+ LLVMBuildCondBr(
+ builder,
+ LLVMBuildICmp(builder, LLVMIntEQ, v_resnull,
+ LLVMConstInt(LLVMInt8Type(), 1, false), ""),
+ opblocks[i + 1],
+ opblocks[op->d.coalesce.jumpdone]);
+
+ break;
+ }
+
+ case EEO_NULLIF:
+ {
+ FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
+ LLVMValueRef v_fcinfo;
+ LLVMValueRef v_fn_addr;
+ LLVMValueRef v_fcinfo_isnullp;
+ LLVMValueRef v_fcinfo_isnull;
+
+ LLVMValueRef v_argnullp;
+ LLVMValueRef v_argnull0;
+ LLVMValueRef v_argnull1;
+ LLVMValueRef v_anyargisnull;
+ LLVMValueRef v_argp;
+ LLVMValueRef v_arg0;
+ LLVMValueRef v_argno;
+ LLVMBasicBlockRef b_hasnull =
+ LLVMInsertBasicBlock(opblocks[i + 1], "null-args");
+ LLVMBasicBlockRef b_nonull =
+ LLVMInsertBasicBlock(opblocks[i + 1], "no-null-args");
+ LLVMBasicBlockRef b_argsequal =
+ LLVMInsertBasicBlock(opblocks[i + 1], "argsequal");
+ LLVMValueRef v_retval;
+ LLVMValueRef v_argsequal;
+
+
+ v_fcinfo = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (intptr_t) fcinfo, false),
+ LLVMPointerType(TypeSizeT, 0),
+ "v_fcinfo");
+
+ v_fn_addr = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (intptr_t) op->d.func.fn_addr, false),
+ LLVMPointerType(TypePGFunction, 0),
+ "v_fn_addr");
+
+ v_fcinfo_isnullp = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (intptr_t) &fcinfo->isnull, false),
+ LLVMPointerType(LLVMInt8Type(), 0),
+ "v_fcinfo_isnull");
+
+ v_argnullp = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (uintptr_t) fcinfo->argnull, false),
+ LLVMPointerType(LLVMInt8Type(), 0),
+ "v_argnullp");
+
+ v_argp = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (uintptr_t) fcinfo->arg, false),
+ LLVMPointerType(TypeSizeT, 0),
+ "v_arg");
+
+ /* if either argument is NULL they can't be equal */
+ v_argno = LLVMConstInt(LLVMInt32Type(), 0, false);
+ v_argnull0 = LLVMBuildLoad(
+ builder,
+ LLVMBuildGEP(builder, v_argnullp, &v_argno, 1, "")
+ , "");
+ v_argno = LLVMConstInt(LLVMInt32Type(), 1, false);
+ v_argnull1 = LLVMBuildLoad(
+ builder,
+ LLVMBuildGEP(builder, v_argnullp, &v_argno, 1, "")
+ , "");
+
+ v_anyargisnull = LLVMBuildOr(
+ builder,
+ LLVMBuildICmp(
+ builder, LLVMIntEQ, v_argnull0,
+ LLVMConstInt(LLVMInt8Type(), 1, false), ""),
+ LLVMBuildICmp(
+ builder, LLVMIntEQ, v_argnull1,
+ LLVMConstInt(LLVMInt8Type(), 1, false), ""),
+ "");
+
+ LLVMBuildCondBr(
+ builder,
+ v_anyargisnull,
+ b_hasnull,
+ b_nonull);
+
+ /* one (or both) of the arguments are null, return arg[0] */
+ LLVMPositionBuilderAtEnd(builder, b_hasnull);
+ v_argno = LLVMConstInt(LLVMInt32Type(), 0, false);
+ v_arg0 = LLVMBuildLoad(
+ builder,
+ LLVMBuildGEP(builder, v_argp, &v_argno, 1, "")
+ , "");
+ LLVMBuildStore(
+ builder,
+ v_argnull0,
+ v_resnullp);
+ LLVMBuildStore(
+ builder,
+ v_arg0,
+ v_resvaluep);
+ LLVMBuildBr(builder, opblocks[i + 1]);
+
+ /* build block to invoke function and check result */
+ LLVMPositionBuilderAtEnd(builder, b_nonull);
+
+ /* reset fcinfo->isnull */
+ LLVMBuildStore(
+ builder, LLVMConstInt(LLVMInt8Type(), 0, false),
+ v_fcinfo_isnullp);
+
+ /* call function */
+ v_retval = LLVMBuildCall(
+ builder, v_fn_addr, &v_fcinfo, 1, "funccall_nullif");
+
+ v_fcinfo_isnull = LLVMBuildLoad(
+ builder, v_fcinfo_isnullp, "");
+
+ /* if result not null, and arguments are equal return null, */
+ v_argsequal = LLVMBuildAnd(
+ builder,
+ LLVMBuildICmp(
+ builder, LLVMIntEQ, v_fcinfo_isnull,
+ LLVMConstInt(LLVMInt8Type(), 0, false), ""),
+ LLVMBuildICmp(
+ builder, LLVMIntEQ, v_retval,
+ LLVMConstInt(TypeSizeT, 1, false), ""),
+ "");
+ LLVMBuildCondBr(
+ builder,
+ v_argsequal,
+ b_argsequal,
+ b_hasnull);
+
+ /* build block setting result to NULL, if args are equal */
+ LLVMPositionBuilderAtEnd(builder, b_argsequal);
+ LLVMBuildStore(
+ builder,
+ LLVMConstInt(LLVMInt8Type(), 1, false),
+ v_resnullp);
+ LLVMBuildStore(
+ builder,
+ LLVMConstInt(TypeSizeT, 0, false),
+ v_resvaluep);
+ LLVMBuildStore(builder, v_retval, v_resvaluep);
+ LLVMBuildBr(builder, opblocks[i + 1]);
+
+ break;
+ }
+
+ case EEO_IOCOERCE:
+ {
+ FunctionCallInfo fcinfo_out, fcinfo_in;
+ LLVMValueRef v_fcinfo_out, v_fcinfo_in;
+ LLVMValueRef v_fn_addr_out, v_fn_addr_in;
+ LLVMValueRef v_fcinfo_in_isnullp;
+ LLVMValueRef v_in_argp, v_out_argp;
+ LLVMValueRef v_in_argnullp, v_out_argnullp;
+ LLVMValueRef v_retval;
+ LLVMValueRef v_resvalue;
+ LLVMValueRef v_resnull;
+
+ LLVMValueRef v_output_skip;
+ LLVMValueRef v_output;
+
+ LLVMValueRef v_argno;
+
+ LLVMBasicBlockRef b_skipoutput =
+ LLVMInsertBasicBlock(opblocks[i + 1], "skipoutputnull");
+ LLVMBasicBlockRef b_calloutput =
+ LLVMInsertBasicBlock(opblocks[i + 1], "calloutput");
+ LLVMBasicBlockRef b_input =
+ LLVMInsertBasicBlock(opblocks[i + 1], "input");
+ LLVMBasicBlockRef b_inputcall =
+ LLVMInsertBasicBlock(opblocks[i + 1], "inputcall");
+
+ fcinfo_out = op->d.iocoerce.fcinfo_data_out;
+ fcinfo_in = op->d.iocoerce.fcinfo_data_in;
+
+ v_fcinfo_out = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (intptr_t) fcinfo_out, false),
+ LLVMPointerType(TypeSizeT, 0),
+ "v_fcinfo");
+
+ v_fcinfo_in = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (intptr_t) fcinfo_in, false),
+ LLVMPointerType(TypeSizeT, 0),
+ "v_fcinfo");
+
+ v_fn_addr_out = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (intptr_t) fcinfo_out->flinfo->fn_addr, false),
+ LLVMPointerType(TypePGFunction, 0),
+ "v_fn_addr");
+
+ v_fn_addr_in = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (intptr_t) fcinfo_in->flinfo->fn_addr, false),
+ LLVMPointerType(TypePGFunction, 0),
+ "v_fn_addr");
+
+ v_fcinfo_in_isnullp = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (intptr_t) &fcinfo_in->isnull, false),
+ LLVMPointerType(LLVMInt8Type(), 0),
+ "v_fcinfo_isnull");
+
+ v_out_argnullp = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (uintptr_t) fcinfo_out->argnull, false),
+ LLVMPointerType(LLVMInt8Type(), 0),
+ "v_out_argnullp");
+
+ v_in_argnullp = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (uintptr_t) fcinfo_in->argnull, false),
+ LLVMPointerType(LLVMInt8Type(), 0),
+ "v_in_argnullp");
+
+ v_out_argp = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (uintptr_t) fcinfo_out->arg, false),
+ LLVMPointerType(TypeSizeT, 0),
+ "v_out_arg");
+
+ v_in_argp = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (uintptr_t) fcinfo_in->arg, false),
+ LLVMPointerType(TypeSizeT, 0),
+ "v_in_arg");
+
+ /*
+ * If input is NULL, don't call output functions, as
+ * they're not called on NULL.
+ */
+ v_resnull = LLVMBuildLoad(builder, v_resnullp, "");
+ LLVMBuildCondBr(
+ builder,
+ LLVMBuildICmp(
+ builder, LLVMIntEQ, v_resnull,
+ LLVMConstInt(LLVMInt8Type(), 1, false), ""),
+ b_skipoutput,
+ b_calloutput);
+
+ LLVMPositionBuilderAtEnd(builder, b_skipoutput);
+ v_output_skip = LLVMConstInt(TypeSizeT, 0, false);
+ LLVMBuildBr(builder, b_input);
+
+ LLVMPositionBuilderAtEnd(builder, b_calloutput);
+ v_resvalue = LLVMBuildLoad(builder, v_resvaluep, "");
+ /* set arg[0] */
+ v_argno = LLVMConstInt(LLVMInt32Type(), 0, false);
+ LLVMBuildStore(
+ builder,
+ v_resvalue,
+ LLVMBuildGEP(builder, v_out_argp, &v_argno, 1, ""));
+ LLVMBuildStore(
+ builder,
+ LLVMConstInt(LLVMInt8Type(), 0, false),
+ LLVMBuildGEP(builder, v_out_argnullp, &v_argno, 1, ""));
+ /* and call output function (can never return NULL) */
+ v_output = LLVMBuildCall(
+ builder, v_fn_addr_out, &v_fcinfo_out, 1, "funccall_coerce_out");
+ LLVMBuildBr(builder, b_input);
+
+ /* build block handling input function call */
+ LLVMPositionBuilderAtEnd(builder, b_input);
+ {
+ LLVMValueRef incoming_values[] =
+ {v_output_skip, v_output};
+ LLVMBasicBlockRef incoming_blocks[] =
+ {b_skipoutput, b_calloutput};
+ v_output = LLVMBuildPhi(builder, TypeSizeT, "output");
+ LLVMAddIncoming(v_output,
+ incoming_values, incoming_blocks,
+ lengthof(incoming_blocks));
+
+ }
+
+ /* if input function is strict, skip if input string is NULL */
+ if (op->d.iocoerce.finfo_in->fn_strict)
+ {
+ LLVMBuildCondBr(
+ builder,
+ LLVMBuildICmp(
+ builder, LLVMIntEQ, v_output,
+ LLVMConstInt(TypeSizeT, 0, false), ""),
+ opblocks[i + 1],
+ b_inputcall);
+ }
+ else
+ {
+ LLVMBuildBr(builder, b_inputcall);
+ }
+
+ LLVMPositionBuilderAtEnd(builder, b_inputcall);
+ /* set arguments */
+ /* arg0: output */
+ v_argno = LLVMConstInt(LLVMInt32Type(), 0, false);
+ LLVMBuildStore(
+ builder,
+ v_output,
+ LLVMBuildGEP(builder, v_in_argp, &v_argno, 1, ""));
+ LLVMBuildStore(
+ builder,
+ v_resnull,
+ LLVMBuildGEP(builder, v_in_argnullp, &v_argno, 1, ""));
+ /* arg1: ioparam */
+ v_argno = LLVMConstInt(LLVMInt32Type(), 1, false);
+ LLVMBuildStore(
+ builder,
+ LLVMConstInt(TypeSizeT, op->d.iocoerce.intypioparam, false),
+ LLVMBuildGEP(builder, v_in_argp, &v_argno, 1, ""));
+ LLVMBuildStore(
+ builder,
+ LLVMConstInt(LLVMInt8Type(), 0, false),
+ LLVMBuildGEP(builder, v_in_argnullp, &v_argno, 1, ""));
+ /* arg2: typmod */
+ v_argno = LLVMConstInt(LLVMInt32Type(), 2, false);
+ LLVMBuildStore(
+ builder,
+ LLVMConstInt(TypeSizeT, -1, false),
+ LLVMBuildGEP(builder, v_in_argp, &v_argno, 1, ""));
+ LLVMBuildStore(
+ builder,
+ LLVMConstInt(LLVMInt8Type(), 0, false),
+ LLVMBuildGEP(builder, v_in_argnullp, &v_argno, 1, ""));
+ /* reset fcinfo_in->isnull */
+ LLVMBuildStore(
+ builder, LLVMConstInt(LLVMInt8Type(), 0, false),
+ v_fcinfo_in_isnullp);
+ /* and call function */
+ v_retval = LLVMBuildCall(
+ builder, v_fn_addr_in, &v_fcinfo_in, 1,
+ "funccall_iocoerce_in");
+ LLVMBuildStore(builder, v_retval, v_resvaluep);
+ LLVMBuildBr(builder, opblocks[i + 1]);
+
+ break;
+ }
+
+ case EEO_DISTINCT:
+ {
+ FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
+
+ LLVMValueRef v_fcinfo;
+ LLVMValueRef v_fn_addr;
+ LLVMValueRef v_fcinfo_isnullp;
+ LLVMValueRef v_fcinfo_isnull;
+
+ LLVMValueRef v_argnullp;
+ LLVMValueRef v_argnull0, v_argisnull0;
+ LLVMValueRef v_argnull1, v_argisnull1;
+
+ LLVMValueRef v_anyargisnull;
+ LLVMValueRef v_bothargisnull;
+
+ LLVMValueRef v_argno;
+ LLVMValueRef v_result;
+
+ LLVMBasicBlockRef b_noargnull =
+ LLVMInsertBasicBlock(opblocks[i + 1], "nonull");
+ LLVMBasicBlockRef b_checkbothargnull =
+ LLVMInsertBasicBlock(opblocks[i + 1], "checkbothargnull");
+ LLVMBasicBlockRef b_bothargnull =
+ LLVMInsertBasicBlock(opblocks[i + 1], "bothargnull");
+ LLVMBasicBlockRef b_anyargnull =
+ LLVMInsertBasicBlock(opblocks[i + 1], "anyargnull");
+
+
+ v_fcinfo = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (intptr_t) fcinfo, false),
+ LLVMPointerType(TypeSizeT, 0),
+ "v_fcinfo");
+
+ v_fn_addr = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (intptr_t) op->d.func.fn_addr, false),
+ LLVMPointerType(TypePGFunction, 0),
+ "v_fn_addr");
+
+ v_fcinfo_isnullp = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (intptr_t) &fcinfo->isnull, false),
+ LLVMPointerType(LLVMInt8Type(), 0),
+ "v_fcinfo_isnull");
+
+ v_argnullp = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (uintptr_t) fcinfo->argnull, false),
+ LLVMPointerType(LLVMInt8Type(), 0),
+ "v_argnullp");
+
+ /* load argnull[0|1] for both arguments */
+ v_argno = LLVMConstInt(LLVMInt32Type(), 0, false);
+ v_argnull0 = LLVMBuildLoad(
+ builder,
+ LLVMBuildGEP(builder, v_argnullp, &v_argno, 1, "")
+ , "");
+ v_argisnull0 = LLVMBuildICmp(
+ builder, LLVMIntEQ, v_argnull0,
+ LLVMConstInt(LLVMInt8Type(), 1, false), "");
+
+ v_argno = LLVMConstInt(LLVMInt32Type(), 1, false);
+ v_argnull1 = LLVMBuildLoad(
+ builder,
+ LLVMBuildGEP(builder, v_argnullp, &v_argno, 1, "")
+ , "");
+ v_argisnull1 = LLVMBuildICmp(
+ builder, LLVMIntEQ, v_argnull1,
+ LLVMConstInt(LLVMInt8Type(), 1, false), "");
+
+ v_anyargisnull = LLVMBuildOr(
+ builder, v_argisnull0, v_argisnull1, "");
+ v_bothargisnull = LLVMBuildAnd(
+ builder, v_argisnull0, v_argisnull1, "");
+
+ /*
+ * Check function arguments for NULLness: If either is
+ * NULL, we check if both args are NULL. Otherwise call
+ * comparator.
+ */
+ LLVMBuildCondBr(
+ builder,
+ v_anyargisnull,
+ b_checkbothargnull,
+ b_noargnull);
+
+ /*
+ * build block checking if any arg is null
+ */
+ LLVMPositionBuilderAtEnd(builder, b_checkbothargnull);
+ LLVMBuildCondBr(
+ builder,
+ v_bothargisnull,
+ b_bothargnull,
+ b_anyargnull);
+
+
+ /* Both NULL? Then is not distinct... */
+ LLVMPositionBuilderAtEnd(builder, b_bothargnull);
+ LLVMBuildStore(
+ builder,
+ LLVMConstInt(LLVMInt8Type(), 0, false),
+ v_resnullp);
+ LLVMBuildStore(
+ builder,
+ LLVMConstInt(TypeSizeT, 0, false),
+ v_resvaluep);
+ LLVMBuildBr(builder, opblocks[i + 1]);
+
+ /* Only one is NULL? Then is distinct... */
+ LLVMPositionBuilderAtEnd(builder, b_anyargnull);
+ LLVMBuildStore(
+ builder,
+ LLVMConstInt(LLVMInt8Type(), 0, false),
+ v_resnullp);
+ LLVMBuildStore(
+ builder,
+ LLVMConstInt(TypeSizeT, 1, false),
+ v_resvaluep);
+ LLVMBuildBr(builder, opblocks[i + 1]);
+
+ /* neither argument is null: compare */
+ LLVMPositionBuilderAtEnd(builder, b_noargnull);
+
+ /* reset fcinfo->isnull */
+ LLVMBuildStore(
+ builder, LLVMConstInt(LLVMInt8Type(), 0, false),
+ v_fcinfo_isnullp);
+
+ v_result = LLVMBuildCall(
+ builder, v_fn_addr, &v_fcinfo, 1, "funccall_distinct");
+
+ /* Must invert result of "=" */
+ v_result = LLVMBuildZExt(
+ builder,
+ LLVMBuildICmp(builder, LLVMIntEQ, v_result,
+ LLVMConstInt(TypeSizeT, 0, false), ""),
+ TypeSizeT, "");
+ v_fcinfo_isnull = LLVMBuildLoad(
+ builder, v_fcinfo_isnullp, "");
+
+ LLVMBuildStore(
+ builder,
+ v_fcinfo_isnull,
+ v_resnullp);
+ LLVMBuildStore(
+ builder,
+ v_result,
+ v_resvaluep);
+ LLVMBuildBr(builder, opblocks[i + 1]);
+
+ break;
+ }
+
+ case EEO_ARRAYREF_CHECKINPUT:
+ {
+ LLVMValueRef v_resnull;
+
+ v_resnull = LLVMBuildLoad(builder, v_resnullp, "");
+
+ /*
+ * If refexpr yields NULL, and it's a fetch, then result
+ * is NULL.
+ */
+ LLVMBuildCondBr(
+ builder,
+ LLVMBuildICmp(
+ builder, LLVMIntEQ, v_resnull,
+ LLVMConstInt(LLVMInt8Type(), 0, false), ""),
+ opblocks[i + 1],
+ opblocks[op->d.arrayref.jumpdone]);
+ break;
+ }
+
+ case EEO_ROWCOMPARE_STEP:
+ {
+ FunctionCallInfo fcinfo = op->d.rowcompare_step.fcinfo_data;
+ LLVMValueRef v_fcinfo;
+ LLVMValueRef v_fn_addr;
+ LLVMValueRef v_fcinfo_isnullp;
+ LLVMValueRef v_fcinfo_isnull;
+
+ LLVMBasicBlockRef b_null =
+ LLVMInsertBasicBlock(opblocks[i + 1], "row-null");
+ LLVMBasicBlockRef b_compare =
+ LLVMInsertBasicBlock(opblocks[i + 1], "row-compare");
+ LLVMBasicBlockRef b_compare_result =
+ LLVMInsertBasicBlock(opblocks[i + 1], "row-compare-result");
+
+ LLVMValueRef v_retval;
+
+ v_fcinfo = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (intptr_t) fcinfo, false),
+ LLVMPointerType(TypeSizeT, 0),
+ "v_fcinfo");
+
+ v_fn_addr = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (intptr_t) op->d.rowcompare_step.fn_addr, false),
+ LLVMPointerType(TypePGFunction, 0),
+ "v_fn_addr");
+
+ v_fcinfo_isnullp = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (intptr_t) &fcinfo->isnull, false),
+ LLVMPointerType(LLVMInt8Type(), 0),
+ "v_fcinfo_isnull");
+
+ /* if function is strict, and either arg is null, we're done */
+ if (op->d.rowcompare_step.finfo->fn_strict)
+ {
+ LLVMValueRef v_argnullp;
+ LLVMValueRef v_argnull0;
+ LLVMValueRef v_argnull1;
+ LLVMValueRef v_argno;
+ LLVMValueRef v_anyargisnull;
+
+ v_argnullp = LLVMBuildIntToPtr(
+ builder,
+ LLVMConstInt(TypeSizeT, (uintptr_t) fcinfo->argnull, false),
+ LLVMPointerType(LLVMInt8Type(), 0),
+ "v_argnullp");
+
+ v_argno = LLVMConstInt(LLVMInt32Type(), 0, false);
+ v_argnull0 = LLVMBuildLoad(
+ builder,
+ LLVMBuildGEP(builder, v_argnullp, &v_argno, 1, "")
+ , "");
+ v_argno = LLVMConstInt(LLVMInt32Type(), 1, false);
+ v_argnull1 = LLVMBuildLoad(
+ builder,
+ LLVMBuildGEP(builder, v_argnullp, &v_argno, 1, "")
+ , "");
+
+ v_anyargisnull = LLVMBuildOr(
+ builder,
+ LLVMBuildICmp(
+ builder, LLVMIntEQ, v_argnull0,
+ LLVMConstInt(LLVMInt8Type(), 1, false), ""),
+ LLVMBuildICmp(
+ builder, LLVMIntEQ, v_argnull1,
+ LLVMConstInt(LLVMInt8Type(), 1, false), ""),
+ "");
+
+ LLVMBuildCondBr(
+ builder,
+ v_anyargisnull,
+ b_null,
+ b_compare);
+ }
+ else
+ {
+ LLVMBuildBr(builder, b_compare);
+ }
+
+ /* build block invoking comparison function */
+ LLVMPositionBuilderAtEnd(builder, b_compare);
+
+ /* reset fcinfo->isnull */
+ LLVMBuildStore(
+ builder, LLVMConstInt(LLVMInt8Type(), 0, false),
+ v_fcinfo_isnullp);
+
+ /* call function */
+ v_retval = LLVMBuildCall(
+ builder, v_fn_addr, &v_fcinfo, 1, "funccall_rowcompare");
+ LLVMBuildStore(builder, v_retval, v_resvaluep);
+
+ v_fcinfo_isnull = LLVMBuildLoad(
+ builder, v_fcinfo_isnullp, "");
+
+ /* if result of function is NULL, force NULL result */
+ LLVMBuildCondBr(
+ builder,
+ LLVMBuildICmp(
+ builder, LLVMIntEQ, v_fcinfo_isnull,
+ LLVMConstInt(LLVMInt8Type(), 0, false), ""),
+ b_compare_result,
+ b_null);
+
+ /* build block analying the !NULL comparator result */
+ LLVMPositionBuilderAtEnd(builder, b_compare_result);
+
+ /* if results equal, compare next, otherwise done */
+ LLVMBuildCondBr(
+ builder,
+ LLVMBuildICmp(
+ builder, LLVMIntEQ, v_retval,
+ LLVMConstInt(TypeSizeT, 0, false), ""),
+ opblocks[i + 1],
+ opblocks[op->d.rowcompare_step.jumpdone]);
+
+ /* build block handling NULL input or NULL comparator result */
+ LLVMPositionBuilderAtEnd(builder, b_null);
+ LLVMBuildStore(
+ builder,
+ LLVMConstInt(LLVMInt8Type(), 1, false),
+ v_resnullp);
+ LLVMBuildBr(
+ builder,
+ opblocks[op->d.rowcompare_step.jumpnull]);
+
+ break;
+ }
+
+ case EEO_ROWCOMPARE_FINAL:
+ {
+ RowCompareType rctype = op->d.rowcompare_final.rctype;
+
+ LLVMValueRef v_cmpresult;
+ LLVMValueRef v_result;
+ LLVMIntPredicate predicate;
+
+ /*
+ * Btree comparators return 32 bit results, need to be
+ * careful about sign (used as a 64 bit value it's
+ * otherwise wrong).
+ */
+ v_cmpresult = LLVMBuildTrunc(
+ builder,
+ LLVMBuildLoad(builder, v_resvaluep, ""),
+ LLVMInt32Type(), "");
+
+ switch (rctype)
+ {
+ /* EQ and NE cases aren't allowed here */
+ case ROWCOMPARE_LT:
+ predicate = LLVMIntSLT;
+ break;
+ case ROWCOMPARE_LE:
+ predicate = LLVMIntSLE;
+ break;
+ case ROWCOMPARE_GT:
+ predicate = LLVMIntSGT;
+ break;
+ case ROWCOMPARE_GE:
+ predicate = LLVMIntSGE;
+ break;
+ default:
+ Assert(false);
+ predicate = 0; /* prevent compiler warning */
+ break;
+ }
+
+ v_result = LLVMBuildZExt(
+ builder,
+ LLVMBuildICmp(
+ builder,
+ predicate,
+ v_cmpresult,
+ LLVMConstInt(LLVMInt32Type(), 0, false), ""),
+ TypeSizeT, "");
+
+ LLVMBuildStore(
+ builder,
+ LLVMConstInt(LLVMInt8Type(), 0, false),
+ v_resnullp);
+ LLVMBuildStore(
+ builder,
+ v_result,
+ v_resvaluep);
+
+ LLVMBuildBr(builder, opblocks[i + 1]);
+
+ break;
+ }
+
+ case EEO_FUNCEXPR_FUSAGE:
+ case EEO_FUNCEXPR_STRICT_FUSAGE:
+
+ elog(ERROR, "unimplemented in jit: %zu", op->opcode);
+
+ case EEO_LAST:
+ Assert(false);
+ break;
+ }
+ }
+
+ llvm_add_module(mod, funcname);
+
+ state->cb = (ExecEvalExprCB) llvm_get_function(funcname);
+
+ LLVMDisposeBuilder(builder);
+ llvm_dispose_module(mod, funcname);
+}
+
+#endif