PostgreSQL Source Code  git master
llvmjit_expr.c File Reference
#include "postgres.h"
#include <llvm-c/Core.h>
#include <llvm-c/Target.h>
#include "access/htup_details.h"
#include "access/nbtree.h"
#include "access/tupconvert.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_type.h"
#include "executor/execExpr.h"
#include "executor/execdebug.h"
#include "executor/nodeAgg.h"
#include "executor/nodeSubplan.h"
#include "funcapi.h"
#include "jit/llvmjit.h"
#include "jit/llvmjit_emit.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.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/fmgrtab.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/timestamp.h"
#include "utils/typcache.h"
#include "utils/xml.h"
Include dependency graph for llvmjit_expr.c:

Go to the source code of this file.

Data Structures

struct  CompiledExprState
 

Typedefs

typedef struct CompiledExprState CompiledExprState
 

Functions

static Datum ExecRunCompiledExpr (ExprState *state, ExprContext *econtext, bool *isNull)
 
static LLVMValueRef BuildV1Call (LLVMJitContext *context, LLVMBuilderRef b, LLVMModuleRef mod, FunctionCallInfo fcinfo, LLVMValueRef *v_fcinfo_isnull)
 
static void build_EvalXFunc (LLVMBuilderRef b, LLVMModuleRef mod, const char *funcname, LLVMValueRef v_state, LLVMValueRef v_econtext, ExprEvalStep *op)
 
static LLVMValueRef create_LifetimeEnd (LLVMModuleRef mod)
 
bool llvm_compile_expr (ExprState *state)
 

Typedef Documentation

◆ CompiledExprState

Function Documentation

◆ build_EvalXFunc()

static void build_EvalXFunc ( LLVMBuilderRef  b,
LLVMModuleRef  mod,
const char *  funcname,
LLVMValueRef  v_state,
LLVMValueRef  v_econtext,
ExprEvalStep op 
)
static

Definition at line 2542 of file llvmjit_expr.c.

References lengthof, sig, StructExprContext, StructExprEvalStep, and StructExprState.

Referenced by llvm_compile_expr().

2545 {
2546  LLVMTypeRef sig;
2547  LLVMValueRef v_fn;
2548  LLVMTypeRef param_types[3];
2549  LLVMValueRef params[3];
2550 
2551  v_fn = LLVMGetNamedFunction(mod, funcname);
2552  if (!v_fn)
2553  {
2554  param_types[0] = l_ptr(StructExprState);
2555  param_types[1] = l_ptr(StructExprEvalStep);
2556  param_types[2] = l_ptr(StructExprContext);
2557 
2558  sig = LLVMFunctionType(LLVMVoidType(),
2559  param_types, lengthof(param_types),
2560  false);
2561  v_fn = LLVMAddFunction(mod, funcname, sig);
2562  }
2563 
2564  params[0] = v_state;
2565  params[1] = l_ptr_const(op, l_ptr(StructExprEvalStep));
2566  params[2] = v_econtext;
2567 
2568  LLVMBuildCall(b,
2569  v_fn,
2570  params, lengthof(params), "");
2571 }
LLVMTypeRef StructExprEvalStep
Definition: llvmjit.c:72
LLVMTypeRef StructExprState
Definition: llvmjit.c:73
#define lengthof(array)
Definition: c.h:669
LLVMTypeRef StructExprContext
Definition: llvmjit.c:71
static int sig
Definition: pg_ctl.c:84

◆ BuildV1Call()

static LLVMValueRef BuildV1Call ( LLVMJitContext *  context,
LLVMBuilderRef  b,
LLVMModuleRef  mod,
FunctionCallInfo  fcinfo,
LLVMValueRef *  v_fcinfo_isnull 
)
static

Definition at line 2496 of file llvmjit_expr.c.

References FunctionCallInfoBaseData::args, create_LifetimeEnd(), FIELDNO_FUNCTIONCALLINFODATA_ISNULL, FunctionCallInfoBaseData::isnull, lengthof, llvm_function_reference(), FunctionCallInfoBaseData::nargs, and StructFunctionCallInfoData.

Referenced by llvm_compile_expr().

2499 {
2500  LLVMValueRef v_fn;
2501  LLVMValueRef v_fcinfo_isnullp;
2502  LLVMValueRef v_retval;
2503  LLVMValueRef v_fcinfo;
2504 
2505  v_fn = llvm_function_reference(context, b, mod, fcinfo);
2506 
2507  v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
2508  v_fcinfo_isnullp = LLVMBuildStructGEP(b, v_fcinfo,
2510  "v_fcinfo_isnull");
2511  LLVMBuildStore(b, l_sbool_const(0), v_fcinfo_isnullp);
2512 
2513  v_retval = LLVMBuildCall(b, v_fn, &v_fcinfo, 1, "funccall");
2514 
2515  if (v_fcinfo_isnull)
2516  *v_fcinfo_isnull = LLVMBuildLoad(b, v_fcinfo_isnullp, "");
2517 
2518  /*
2519  * Add lifetime-end annotation, signalling that writes to memory don't
2520  * have to be retained (important for inlining potential).
2521  */
2522  {
2523  LLVMValueRef v_lifetime = create_LifetimeEnd(mod);
2524  LLVMValueRef params[2];
2525 
2526  params[0] = l_int64_const(sizeof(NullableDatum) * fcinfo->nargs);
2527  params[1] = l_ptr_const(fcinfo->args, l_ptr(LLVMInt8Type()));
2528  LLVMBuildCall(b, v_lifetime, params, lengthof(params), "");
2529 
2530  params[0] = l_int64_const(sizeof(fcinfo->isnull));
2531  params[1] = l_ptr_const(&fcinfo->isnull, l_ptr(LLVMInt8Type()));
2532  LLVMBuildCall(b, v_lifetime, params, lengthof(params), "");
2533  }
2534 
2535  return v_retval;
2536 }
#define FIELDNO_FUNCTIONCALLINFODATA_ISNULL
Definition: fmgr.h:91
LLVMTypeRef StructFunctionCallInfoData
Definition: llvmjit.c:70
static LLVMValueRef create_LifetimeEnd(LLVMModuleRef mod)
LLVMValueRef llvm_function_reference(LLVMJitContext *context, LLVMBuilderRef builder, LLVMModuleRef mod, FunctionCallInfo fcinfo)
Definition: llvmjit.c:355
#define lengthof(array)
Definition: c.h:669
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
Definition: fmgr.h:95

◆ create_LifetimeEnd()

static LLVMValueRef create_LifetimeEnd ( LLVMModuleRef  mod)
static

Definition at line 2574 of file llvmjit_expr.c.

References Assert, fn(), lengthof, and sig.

Referenced by BuildV1Call().

2575 {
2576  LLVMTypeRef sig;
2577  LLVMValueRef fn;
2578  LLVMTypeRef param_types[2];
2579 
2580  /* LLVM 5+ has a variadic pointer argument */
2581 #if LLVM_VERSION_MAJOR < 5
2582  const char *nm = "llvm.lifetime.end";
2583 #else
2584  const char *nm = "llvm.lifetime.end.p0i8";
2585 #endif
2586 
2587  fn = LLVMGetNamedFunction(mod, nm);
2588  if (fn)
2589  return fn;
2590 
2591  param_types[0] = LLVMInt64Type();
2592  param_types[1] = l_ptr(LLVMInt8Type());
2593 
2594  sig = LLVMFunctionType(LLVMVoidType(),
2595  param_types, lengthof(param_types),
2596  false);
2597  fn = LLVMAddFunction(mod, nm, sig);
2598 
2599  LLVMSetFunctionCallConv(fn, LLVMCCallConv);
2600 
2601  Assert(LLVMGetIntrinsicID(fn));
2602 
2603  return fn;
2604 }
#define lengthof(array)
Definition: c.h:669
static int sig
Definition: pg_ctl.c:84
static void * fn(void *arg)
#define Assert(condition)
Definition: c.h:739

◆ ExecRunCompiledExpr()

static Datum ExecRunCompiledExpr ( ExprState state,
ExprContext econtext,
bool isNull 
)
static

Definition at line 2476 of file llvmjit_expr.c.

References Assert, CheckExprStillValid(), CompiledExprState::context, ExprState::evalfunc, ExprState::evalfunc_private, CompiledExprState::funcname, llvm_enter_fatal_on_oom(), llvm_get_function(), and llvm_leave_fatal_on_oom().

Referenced by llvm_compile_expr().

2477 {
2478  CompiledExprState *cstate = state->evalfunc_private;
2479  ExprStateEvalFunc func;
2480 
2481  CheckExprStillValid(state, econtext);
2482 
2484  func = (ExprStateEvalFunc) llvm_get_function(cstate->context,
2485  cstate->funcname);
2487  Assert(func);
2488 
2489  /* remove indirection via this function for future calls */
2490  state->evalfunc = func;
2491 
2492  return func(state, econtext, isNull);
2493 }
Datum(* ExprStateEvalFunc)(struct ExprState *expression, struct ExprContext *econtext, bool *isNull)
Definition: execnodes.h:53
LLVMJitContext * context
Definition: llvmjit_expr.c:51
ExprStateEvalFunc evalfunc
Definition: execnodes.h:91
void * evalfunc_private
Definition: execnodes.h:97
#define Assert(condition)
Definition: c.h:739
void * llvm_get_function(LLVMJitContext *context, const char *funcname)
Definition: llvmjit.c:243
void llvm_enter_fatal_on_oom(void)
const char * funcname
Definition: llvmjit_expr.c:52
void CheckExprStillValid(ExprState *state, ExprContext *econtext)
void llvm_leave_fatal_on_oom(void)

◆ llvm_compile_expr()

bool llvm_compile_expr ( ExprState state)

Definition at line 72 of file llvmjit_expr.c.

References ExprEvalStep::agg_deserialize, ExprEvalStep::agg_init_trans, ExprEvalStep::agg_strict_input_check, ExprEvalStep::agg_strict_trans_check, ExprEvalStep::agg_trans, AggrefExprState::aggno, ExprEvalStep::aggref, generate_unaccent_rules::args, Assert, ExprEvalStep::assign_tmp, ExprEvalStep::assign_var, AttributeTemplate, ExprEvalStep::boolexpr, build_EvalXFunc(), BuildV1Call(), ExprEvalStep::casetest, ExprEvalStep::constval, CompiledExprState::context, ExprEvalStep::cparam, ExprEvalStep::d, ExprContext::ecxt_per_tuple_memory, EEOP_AGG_DESERIALIZE, EEOP_AGG_INIT_TRANS, EEOP_AGG_ORDERED_TRANS_DATUM, EEOP_AGG_ORDERED_TRANS_TUPLE, EEOP_AGG_PLAIN_TRANS, EEOP_AGG_PLAIN_TRANS_BYVAL, EEOP_AGG_STRICT_DESERIALIZE, EEOP_AGG_STRICT_INPUT_CHECK_ARGS, EEOP_AGG_STRICT_INPUT_CHECK_NULLS, EEOP_AGG_STRICT_TRANS_CHECK, EEOP_AGGREF, EEOP_ALTERNATIVE_SUBPLAN, EEOP_ARRAYCOERCE, EEOP_ARRAYEXPR, EEOP_ASSIGN_INNER_VAR, EEOP_ASSIGN_OUTER_VAR, EEOP_ASSIGN_SCAN_VAR, EEOP_ASSIGN_TMP, EEOP_ASSIGN_TMP_MAKE_RO, EEOP_BOOL_AND_STEP, EEOP_BOOL_AND_STEP_FIRST, EEOP_BOOL_AND_STEP_LAST, EEOP_BOOL_NOT_STEP, EEOP_BOOL_OR_STEP, EEOP_BOOL_OR_STEP_FIRST, EEOP_BOOL_OR_STEP_LAST, EEOP_BOOLTEST_IS_FALSE, EEOP_BOOLTEST_IS_NOT_FALSE, EEOP_BOOLTEST_IS_NOT_TRUE, EEOP_BOOLTEST_IS_TRUE, EEOP_CASE_TESTVAL, EEOP_CONST, EEOP_CONVERT_ROWTYPE, EEOP_CURRENTOFEXPR, EEOP_DISTINCT, EEOP_DOMAIN_CHECK, EEOP_DOMAIN_NOTNULL, EEOP_DOMAIN_TESTVAL, EEOP_DONE, EEOP_FIELDSELECT, EEOP_FIELDSTORE_DEFORM, EEOP_FIELDSTORE_FORM, EEOP_FUNCEXPR, EEOP_FUNCEXPR_FUSAGE, EEOP_FUNCEXPR_STRICT, EEOP_FUNCEXPR_STRICT_FUSAGE, EEOP_GROUPING_FUNC, EEOP_INNER_FETCHSOME, EEOP_INNER_SYSVAR, EEOP_INNER_VAR, EEOP_IOCOERCE, EEOP_JUMP, EEOP_JUMP_IF_NOT_NULL, EEOP_JUMP_IF_NOT_TRUE, EEOP_JUMP_IF_NULL, EEOP_LAST, EEOP_MAKE_READONLY, EEOP_MINMAX, EEOP_NEXTVALUEEXPR, EEOP_NOT_DISTINCT, EEOP_NULLIF, EEOP_NULLTEST_ISNOTNULL, EEOP_NULLTEST_ISNULL, EEOP_NULLTEST_ROWISNOTNULL, EEOP_NULLTEST_ROWISNULL, EEOP_OUTER_FETCHSOME, EEOP_OUTER_SYSVAR, EEOP_OUTER_VAR, EEOP_PARAM_CALLBACK, EEOP_PARAM_EXEC, EEOP_PARAM_EXTERN, EEOP_QUAL, EEOP_ROW, EEOP_ROWCOMPARE_FINAL, EEOP_ROWCOMPARE_STEP, EEOP_SBSREF_ASSIGN, EEOP_SBSREF_FETCH, EEOP_SBSREF_OLD, EEOP_SBSREF_SUBSCRIPT, EEOP_SCALARARRAYOP, EEOP_SCAN_FETCHSOME, EEOP_SCAN_SYSVAR, EEOP_SCAN_VAR, EEOP_SQLVALUEFUNCTION, EEOP_SUBPLAN, EEOP_WHOLEROW, EEOP_WINDOW_FUNC, EEOP_XMLEXPR, elog, ERROR, EState::es_jit, EState::es_jit_flags, ExprState::evalfunc, ExprState::evalfunc_private, ExecEvalStepOp(), ExecRunCompiledExpr(), ExprEvalStep::fetch, FIELDNO_AGGSTATE_ALL_PERGROUPS, FIELDNO_AGGSTATE_CURAGGCONTEXT, FIELDNO_AGGSTATE_CURPERTRANS, FIELDNO_AGGSTATE_CURRENT_SET, FIELDNO_AGGSTATEPERGROUPDATA_NOTRANSVALUE, FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUE, FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL, FIELDNO_EXPRCONTEXT_AGGNULLS, FIELDNO_EXPRCONTEXT_AGGVALUES, FIELDNO_EXPRCONTEXT_CASEDATUM, FIELDNO_EXPRCONTEXT_CASENULL, FIELDNO_EXPRCONTEXT_DOMAINDATUM, FIELDNO_EXPRCONTEXT_DOMAINNULL, FIELDNO_EXPRCONTEXT_INNERTUPLE, FIELDNO_EXPRCONTEXT_OUTERTUPLE, FIELDNO_EXPRCONTEXT_SCANTUPLE, FIELDNO_EXPRSTATE_RESNULL, FIELDNO_EXPRSTATE_RESULTSLOT, FIELDNO_EXPRSTATE_RESVALUE, FIELDNO_FUNCTIONCALLINFODATA_ISNULL, FIELDNO_NULLABLE_DATUM_ISNULL, FIELDNO_TUPLETABLESLOT_ISNULL, FIELDNO_TUPLETABLESLOT_NVALID, FIELDNO_TUPLETABLESLOT_VALUES, FunctionCallInfoBaseData::flinfo, FmgrInfo::fn_addr, ExprEvalStep::func, FuncExecAggInitGroup, FuncExecAggTransReparent, FuncExecEvalSubscriptingRef, FuncExecEvalSysVar, FuncMakeExpandedObjectReadOnlyInternal, CompiledExprState::funcname, FuncSlotGetsomeattrsInt, i, INSTR_TIME_ACCUM_DIFF, INSTR_TIME_SET_CURRENT, ExprEvalStep::iocoerce, ExprEvalStep::jump, lengthof, llvm_copy_attributes(), llvm_create_context(), llvm_enter_fatal_on_oom(), llvm_expand_funcname(), llvm_get_decl(), llvm_leave_fatal_on_oom(), llvm_mutable_module(), ExprEvalStep::make_readonly, palloc(), palloc0(), ExprState::parent, PGJIT_DEFORM, ExprEvalStep::qualexpr, ExprEvalStep::resnull, ExprEvalStep::resvalue, ExprEvalStep::rowcompare_final, ROWCOMPARE_GE, ROWCOMPARE_GT, ROWCOMPARE_LE, ROWCOMPARE_LT, ExprEvalStep::rowcompare_step, ExprEvalStep::sbsref_subscript, slot_compile_deform(), PlanState::state, ExprState::steps, ExprState::steps_len, StructAggState, StructAggStatePerTransData, StructExprContext, StructExprEvalStep, StructExprState, StructFunctionCallInfoData, StructMemoryContextData, StructNullableDatum, AggState::tmpcontext, AggStatePerTransData::transfn_fcinfo, TTSOpsVirtual, TypeParamBool, TypePGFunction, TypeSizeT, TypeStorageBool, value, ExprEvalStep::var, WindowFuncExprState::wfuncno, and ExprEvalStep::window_func.

Referenced by _PG_jit_provider_init().

73 {
74  PlanState *parent = state->parent;
75  int i;
76  char *funcname;
77 
78  LLVMJitContext *context = NULL;
79 
80  LLVMBuilderRef b;
81  LLVMModuleRef mod;
82  LLVMTypeRef eval_sig;
83  LLVMValueRef eval_fn;
84  LLVMBasicBlockRef entry;
85  LLVMBasicBlockRef *opblocks;
86 
87  /* state itself */
88  LLVMValueRef v_state;
89  LLVMValueRef v_econtext;
90 
91  /* returnvalue */
92  LLVMValueRef v_isnullp;
93 
94  /* tmp vars in state */
95  LLVMValueRef v_tmpvaluep;
96  LLVMValueRef v_tmpisnullp;
97 
98  /* slots */
99  LLVMValueRef v_innerslot;
100  LLVMValueRef v_outerslot;
101  LLVMValueRef v_scanslot;
102  LLVMValueRef v_resultslot;
103 
104  /* nulls/values of slots */
105  LLVMValueRef v_innervalues;
106  LLVMValueRef v_innernulls;
107  LLVMValueRef v_outervalues;
108  LLVMValueRef v_outernulls;
109  LLVMValueRef v_scanvalues;
110  LLVMValueRef v_scannulls;
111  LLVMValueRef v_resultvalues;
112  LLVMValueRef v_resultnulls;
113 
114  /* stuff in econtext */
115  LLVMValueRef v_aggvalues;
116  LLVMValueRef v_aggnulls;
117 
118  instr_time starttime;
119  instr_time endtime;
120 
122 
123  /* get or create JIT context */
124  if (parent && parent->state->es_jit)
125  {
126  context = (LLVMJitContext *) parent->state->es_jit;
127  }
128  else
129  {
130  context = llvm_create_context(parent->state->es_jit_flags);
131 
132  if (parent)
133  {
134  parent->state->es_jit = &context->base;
135  }
136 
137  }
138 
139  INSTR_TIME_SET_CURRENT(starttime);
140 
141  mod = llvm_mutable_module(context);
142 
143  b = LLVMCreateBuilder();
144 
145  funcname = llvm_expand_funcname(context, "evalexpr");
146 
147  /* Create the signature and function */
148  {
149  LLVMTypeRef param_types[3];
150 
151  param_types[0] = l_ptr(StructExprState); /* state */
152  param_types[1] = l_ptr(StructExprContext); /* econtext */
153  param_types[2] = l_ptr(TypeParamBool); /* isnull */
154 
155  eval_sig = LLVMFunctionType(TypeSizeT,
156  param_types, lengthof(param_types),
157  false);
158  }
159  eval_fn = LLVMAddFunction(mod, funcname, eval_sig);
160  LLVMSetLinkage(eval_fn, LLVMExternalLinkage);
161  LLVMSetVisibility(eval_fn, LLVMDefaultVisibility);
163 
164  entry = LLVMAppendBasicBlock(eval_fn, "entry");
165 
166  /* build state */
167  v_state = LLVMGetParam(eval_fn, 0);
168  v_econtext = LLVMGetParam(eval_fn, 1);
169  v_isnullp = LLVMGetParam(eval_fn, 2);
170 
171  LLVMPositionBuilderAtEnd(b, entry);
172 
173  v_tmpvaluep = LLVMBuildStructGEP(b, v_state,
175  "v.state.resvalue");
176  v_tmpisnullp = LLVMBuildStructGEP(b, v_state,
178  "v.state.resnull");
179 
180  /* build global slots */
181  v_scanslot = l_load_struct_gep(b, v_econtext,
183  "v_scanslot");
184  v_innerslot = l_load_struct_gep(b, v_econtext,
186  "v_innerslot");
187  v_outerslot = l_load_struct_gep(b, v_econtext,
189  "v_outerslot");
190  v_resultslot = l_load_struct_gep(b, v_state,
192  "v_resultslot");
193 
194  /* build global values/isnull pointers */
195  v_scanvalues = l_load_struct_gep(b, v_scanslot,
197  "v_scanvalues");
198  v_scannulls = l_load_struct_gep(b, v_scanslot,
200  "v_scannulls");
201  v_innervalues = l_load_struct_gep(b, v_innerslot,
203  "v_innervalues");
204  v_innernulls = l_load_struct_gep(b, v_innerslot,
206  "v_innernulls");
207  v_outervalues = l_load_struct_gep(b, v_outerslot,
209  "v_outervalues");
210  v_outernulls = l_load_struct_gep(b, v_outerslot,
212  "v_outernulls");
213  v_resultvalues = l_load_struct_gep(b, v_resultslot,
215  "v_resultvalues");
216  v_resultnulls = l_load_struct_gep(b, v_resultslot,
218  "v_resultnulls");
219 
220  /* aggvalues/aggnulls */
221  v_aggvalues = l_load_struct_gep(b, v_econtext,
223  "v.econtext.aggvalues");
224  v_aggnulls = l_load_struct_gep(b, v_econtext,
226  "v.econtext.aggnulls");
227 
228  /* allocate blocks for each op upfront, so we can do jumps easily */
229  opblocks = palloc(sizeof(LLVMBasicBlockRef) * state->steps_len);
230  for (i = 0; i < state->steps_len; i++)
231  opblocks[i] = l_bb_append_v(eval_fn, "b.op.%d.start", i);
232 
233  /* jump from entry to first block */
234  LLVMBuildBr(b, opblocks[0]);
235 
236  for (i = 0; i < state->steps_len; i++)
237  {
238  ExprEvalStep *op;
239  ExprEvalOp opcode;
240  LLVMValueRef v_resvaluep;
241  LLVMValueRef v_resnullp;
242 
243  LLVMPositionBuilderAtEnd(b, opblocks[i]);
244 
245  op = &state->steps[i];
246  opcode = ExecEvalStepOp(state, op);
247 
248  v_resvaluep = l_ptr_const(op->resvalue, l_ptr(TypeSizeT));
249  v_resnullp = l_ptr_const(op->resnull, l_ptr(TypeStorageBool));
250 
251  switch (opcode)
252  {
253  case EEOP_DONE:
254  {
255  LLVMValueRef v_tmpisnull,
256  v_tmpvalue;
257 
258  v_tmpvalue = LLVMBuildLoad(b, v_tmpvaluep, "");
259  v_tmpisnull = LLVMBuildLoad(b, v_tmpisnullp, "");
260  v_tmpisnull =
261  LLVMBuildTrunc(b, v_tmpisnull, TypeParamBool, "");
262 
263  LLVMBuildStore(b, v_tmpisnull, v_isnullp);
264 
265  LLVMBuildRet(b, v_tmpvalue);
266  break;
267  }
268 
271  case EEOP_SCAN_FETCHSOME:
272  {
273  TupleDesc desc = NULL;
274  LLVMValueRef v_slot;
275  LLVMBasicBlockRef b_fetch;
276  LLVMValueRef v_nvalid;
277  LLVMValueRef l_jit_deform = NULL;
278  const TupleTableSlotOps *tts_ops = NULL;
279 
280  b_fetch = l_bb_before_v(opblocks[i + 1],
281  "op.%d.fetch", i);
282 
283  if (op->d.fetch.known_desc)
284  desc = op->d.fetch.known_desc;
285 
286  if (op->d.fetch.fixed)
287  tts_ops = op->d.fetch.kind;
288 
289  /* step should not have been generated */
290  Assert(tts_ops != &TTSOpsVirtual);
291 
292  if (opcode == EEOP_INNER_FETCHSOME)
293  v_slot = v_innerslot;
294  else if (opcode == EEOP_OUTER_FETCHSOME)
295  v_slot = v_outerslot;
296  else
297  v_slot = v_scanslot;
298 
299  /*
300  * Check if all required attributes are available, or
301  * whether deforming is required.
302  */
303  v_nvalid =
304  l_load_struct_gep(b, v_slot,
306  "");
307  LLVMBuildCondBr(b,
308  LLVMBuildICmp(b, LLVMIntUGE, v_nvalid,
309  l_int16_const(op->d.fetch.last_var),
310  ""),
311  opblocks[i + 1], b_fetch);
312 
313  LLVMPositionBuilderAtEnd(b, b_fetch);
314 
315  /*
316  * If the tupledesc of the to-be-deformed tuple is known,
317  * and JITing of deforming is enabled, build deform
318  * function specific to tupledesc and the exact number of
319  * to-be-extracted attributes.
320  */
321  if (tts_ops && desc && (context->base.flags & PGJIT_DEFORM))
322  {
323  l_jit_deform =
324  slot_compile_deform(context, desc,
325  tts_ops,
326  op->d.fetch.last_var);
327  }
328 
329  if (l_jit_deform)
330  {
331  LLVMValueRef params[1];
332 
333  params[0] = v_slot;
334 
335  LLVMBuildCall(b, l_jit_deform,
336  params, lengthof(params), "");
337  }
338  else
339  {
340  LLVMValueRef params[2];
341 
342  params[0] = v_slot;
343  params[1] = l_int32_const(op->d.fetch.last_var);
344 
345  LLVMBuildCall(b,
347  params, lengthof(params), "");
348  }
349 
350  LLVMBuildBr(b, opblocks[i + 1]);
351  break;
352  }
353 
354  case EEOP_INNER_VAR:
355  case EEOP_OUTER_VAR:
356  case EEOP_SCAN_VAR:
357  {
358  LLVMValueRef value,
359  isnull;
360  LLVMValueRef v_attnum;
361  LLVMValueRef v_values;
362  LLVMValueRef v_nulls;
363 
364  if (opcode == EEOP_INNER_VAR)
365  {
366  v_values = v_innervalues;
367  v_nulls = v_innernulls;
368  }
369  else if (opcode == EEOP_OUTER_VAR)
370  {
371  v_values = v_outervalues;
372  v_nulls = v_outernulls;
373  }
374  else
375  {
376  v_values = v_scanvalues;
377  v_nulls = v_scannulls;
378  }
379 
380  v_attnum = l_int32_const(op->d.var.attnum);
381  value = l_load_gep1(b, v_values, v_attnum, "");
382  isnull = l_load_gep1(b, v_nulls, v_attnum, "");
383  LLVMBuildStore(b, value, v_resvaluep);
384  LLVMBuildStore(b, isnull, v_resnullp);
385 
386  LLVMBuildBr(b, opblocks[i + 1]);
387  break;
388  }
389 
390  case EEOP_INNER_SYSVAR:
391  case EEOP_OUTER_SYSVAR:
392  case EEOP_SCAN_SYSVAR:
393  {
394  LLVMValueRef v_slot;
395  LLVMValueRef v_params[4];
396 
397  if (opcode == EEOP_INNER_SYSVAR)
398  v_slot = v_innerslot;
399  else if (opcode == EEOP_OUTER_SYSVAR)
400  v_slot = v_outerslot;
401  else
402  v_slot = v_scanslot;
403 
404  v_params[0] = v_state;
405  v_params[1] = l_ptr_const(op, l_ptr(StructExprEvalStep));
406  v_params[2] = v_econtext;
407  v_params[3] = v_slot;
408 
409  LLVMBuildCall(b,
411  v_params, lengthof(v_params), "");
412 
413  LLVMBuildBr(b, opblocks[i + 1]);
414  break;
415  }
416 
417  case EEOP_WHOLEROW:
418  build_EvalXFunc(b, mod, "ExecEvalWholeRowVar",
419  v_state, v_econtext, op);
420  LLVMBuildBr(b, opblocks[i + 1]);
421  break;
422 
426  {
427  LLVMValueRef v_value,
428  v_isnull;
429  LLVMValueRef v_rvaluep,
430  v_risnullp;
431  LLVMValueRef v_attnum,
432  v_resultnum;
433  LLVMValueRef v_values;
434  LLVMValueRef v_nulls;
435 
436  if (opcode == EEOP_ASSIGN_INNER_VAR)
437  {
438  v_values = v_innervalues;
439  v_nulls = v_innernulls;
440  }
441  else if (opcode == EEOP_ASSIGN_OUTER_VAR)
442  {
443  v_values = v_outervalues;
444  v_nulls = v_outernulls;
445  }
446  else
447  {
448  v_values = v_scanvalues;
449  v_nulls = v_scannulls;
450  }
451 
452  /* load data */
453  v_attnum = l_int32_const(op->d.assign_var.attnum);
454  v_value = l_load_gep1(b, v_values, v_attnum, "");
455  v_isnull = l_load_gep1(b, v_nulls, v_attnum, "");
456 
457  /* compute addresses of targets */
458  v_resultnum = l_int32_const(op->d.assign_var.resultnum);
459  v_rvaluep = LLVMBuildGEP(b, v_resultvalues,
460  &v_resultnum, 1, "");
461  v_risnullp = LLVMBuildGEP(b, v_resultnulls,
462  &v_resultnum, 1, "");
463 
464  /* and store */
465  LLVMBuildStore(b, v_value, v_rvaluep);
466  LLVMBuildStore(b, v_isnull, v_risnullp);
467 
468  LLVMBuildBr(b, opblocks[i + 1]);
469  break;
470  }
471 
472  case EEOP_ASSIGN_TMP:
473  {
474  LLVMValueRef v_value,
475  v_isnull;
476  LLVMValueRef v_rvaluep,
477  v_risnullp;
478  LLVMValueRef v_resultnum;
479  size_t resultnum = op->d.assign_tmp.resultnum;
480 
481  /* load data */
482  v_value = LLVMBuildLoad(b, v_tmpvaluep, "");
483  v_isnull = LLVMBuildLoad(b, v_tmpisnullp, "");
484 
485  /* compute addresses of targets */
486  v_resultnum = l_int32_const(resultnum);
487  v_rvaluep =
488  LLVMBuildGEP(b, v_resultvalues, &v_resultnum, 1, "");
489  v_risnullp =
490  LLVMBuildGEP(b, v_resultnulls, &v_resultnum, 1, "");
491 
492  /* and store */
493  LLVMBuildStore(b, v_value, v_rvaluep);
494  LLVMBuildStore(b, v_isnull, v_risnullp);
495 
496  LLVMBuildBr(b, opblocks[i + 1]);
497  break;
498  }
499 
501  {
502  LLVMBasicBlockRef b_notnull;
503  LLVMValueRef v_params[1];
504  LLVMValueRef v_ret;
505  LLVMValueRef v_value,
506  v_isnull;
507  LLVMValueRef v_rvaluep,
508  v_risnullp;
509  LLVMValueRef v_resultnum;
510  size_t resultnum = op->d.assign_tmp.resultnum;
511 
512  b_notnull = l_bb_before_v(opblocks[i + 1],
513  "op.%d.assign_tmp.notnull", i);
514 
515  /* load data */
516  v_value = LLVMBuildLoad(b, v_tmpvaluep, "");
517  v_isnull = LLVMBuildLoad(b, v_tmpisnullp, "");
518 
519  /* compute addresses of targets */
520  v_resultnum = l_int32_const(resultnum);
521  v_rvaluep = LLVMBuildGEP(b, v_resultvalues,
522  &v_resultnum, 1, "");
523  v_risnullp = LLVMBuildGEP(b, v_resultnulls,
524  &v_resultnum, 1, "");
525 
526  /* store nullness */
527  LLVMBuildStore(b, v_isnull, v_risnullp);
528 
529  /* check if value is NULL */
530  LLVMBuildCondBr(b,
531  LLVMBuildICmp(b, LLVMIntEQ, v_isnull,
532  l_sbool_const(0), ""),
533  b_notnull, opblocks[i + 1]);
534 
535  /* if value is not null, convert to RO datum */
536  LLVMPositionBuilderAtEnd(b, b_notnull);
537  v_params[0] = v_value;
538  v_ret =
539  LLVMBuildCall(b,
541  v_params, lengthof(v_params), "");
542 
543  /* store value */
544  LLVMBuildStore(b, v_ret, v_rvaluep);
545 
546  LLVMBuildBr(b, opblocks[i + 1]);
547  break;
548  }
549 
550  case EEOP_CONST:
551  {
552  LLVMValueRef v_constvalue,
553  v_constnull;
554 
555  v_constvalue = l_sizet_const(op->d.constval.value);
556  v_constnull = l_sbool_const(op->d.constval.isnull);
557 
558  LLVMBuildStore(b, v_constvalue, v_resvaluep);
559  LLVMBuildStore(b, v_constnull, v_resnullp);
560 
561  LLVMBuildBr(b, opblocks[i + 1]);
562  break;
563  }
564 
566  {
567  FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
568  LLVMBasicBlockRef b_nonull;
569  int argno;
570  LLVMValueRef v_fcinfo;
571  LLVMBasicBlockRef *b_checkargnulls;
572 
573  /*
574  * Block for the actual function call, if args are
575  * non-NULL.
576  */
577  b_nonull = l_bb_before_v(opblocks[i + 1],
578  "b.%d.no-null-args", i);
579 
580  /* should make sure they're optimized beforehand */
581  if (op->d.func.nargs == 0)
582  elog(ERROR, "argumentless strict functions are pointless");
583 
584  v_fcinfo =
585  l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
586 
587  /*
588  * set resnull to true, if the function is actually
589  * called, it'll be reset
590  */
591  LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
592 
593  /* create blocks for checking args, one for each */
594  b_checkargnulls =
595  palloc(sizeof(LLVMBasicBlockRef *) * op->d.func.nargs);
596  for (argno = 0; argno < op->d.func.nargs; argno++)
597  b_checkargnulls[argno] =
598  l_bb_before_v(b_nonull, "b.%d.isnull.%d", i, argno);
599 
600  /* jump to check of first argument */
601  LLVMBuildBr(b, b_checkargnulls[0]);
602 
603  /* check each arg for NULLness */
604  for (argno = 0; argno < op->d.func.nargs; argno++)
605  {
606  LLVMValueRef v_argisnull;
607  LLVMBasicBlockRef b_argnotnull;
608 
609  LLVMPositionBuilderAtEnd(b, b_checkargnulls[argno]);
610 
611  /* compute block to jump to if argument is not null */
612  if (argno + 1 == op->d.func.nargs)
613  b_argnotnull = b_nonull;
614  else
615  b_argnotnull = b_checkargnulls[argno + 1];
616 
617  /* and finally load & check NULLness of arg */
618  v_argisnull = l_funcnull(b, v_fcinfo, argno);
619  LLVMBuildCondBr(b,
620  LLVMBuildICmp(b, LLVMIntEQ,
621  v_argisnull,
622  l_sbool_const(1),
623  ""),
624  opblocks[i + 1],
625  b_argnotnull);
626  }
627 
628  LLVMPositionBuilderAtEnd(b, b_nonull);
629  }
630  /* FALLTHROUGH */
631 
632  case EEOP_FUNCEXPR:
633  {
634  FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
635  LLVMValueRef v_fcinfo_isnull;
636  LLVMValueRef v_retval;
637 
638  v_retval = BuildV1Call(context, b, mod, fcinfo,
639  &v_fcinfo_isnull);
640  LLVMBuildStore(b, v_retval, v_resvaluep);
641  LLVMBuildStore(b, v_fcinfo_isnull, v_resnullp);
642 
643  LLVMBuildBr(b, opblocks[i + 1]);
644  break;
645  }
646 
648  build_EvalXFunc(b, mod, "ExecEvalFuncExprFusage",
649  v_state, v_econtext, op);
650  LLVMBuildBr(b, opblocks[i + 1]);
651  break;
652 
653 
655  build_EvalXFunc(b, mod, "ExecEvalFuncExprStrictFusage",
656  v_state, v_econtext, op);
657  LLVMBuildBr(b, opblocks[i + 1]);
658  break;
659 
661  {
662  LLVMValueRef v_boolanynullp;
663 
664  v_boolanynullp = l_ptr_const(op->d.boolexpr.anynull,
665  l_ptr(TypeStorageBool));
666  LLVMBuildStore(b, l_sbool_const(0), v_boolanynullp);
667 
668  }
669  /* FALLTHROUGH */
670 
671  /*
672  * Treat them the same for now, optimizer can remove
673  * redundancy. Could be worthwhile to optimize during emission
674  * though.
675  */
677  case EEOP_BOOL_AND_STEP:
678  {
679  LLVMValueRef v_boolvalue;
680  LLVMValueRef v_boolnull;
681  LLVMValueRef v_boolanynullp,
682  v_boolanynull;
683  LLVMBasicBlockRef b_boolisnull;
684  LLVMBasicBlockRef b_boolcheckfalse;
685  LLVMBasicBlockRef b_boolisfalse;
686  LLVMBasicBlockRef b_boolcont;
687  LLVMBasicBlockRef b_boolisanynull;
688 
689  b_boolisnull = l_bb_before_v(opblocks[i + 1],
690  "b.%d.boolisnull", i);
691  b_boolcheckfalse = l_bb_before_v(opblocks[i + 1],
692  "b.%d.boolcheckfalse", i);
693  b_boolisfalse = l_bb_before_v(opblocks[i + 1],
694  "b.%d.boolisfalse", i);
695  b_boolisanynull = l_bb_before_v(opblocks[i + 1],
696  "b.%d.boolisanynull", i);
697  b_boolcont = l_bb_before_v(opblocks[i + 1],
698  "b.%d.boolcont", i);
699 
700  v_boolanynullp = l_ptr_const(op->d.boolexpr.anynull,
701  l_ptr(TypeStorageBool));
702 
703  v_boolnull = LLVMBuildLoad(b, v_resnullp, "");
704  v_boolvalue = LLVMBuildLoad(b, v_resvaluep, "");
705 
706  /* set resnull to boolnull */
707  LLVMBuildStore(b, v_boolnull, v_resnullp);
708  /* set revalue to boolvalue */
709  LLVMBuildStore(b, v_boolvalue, v_resvaluep);
710 
711  /* check if current input is NULL */
712  LLVMBuildCondBr(b,
713  LLVMBuildICmp(b, LLVMIntEQ, v_boolnull,
714  l_sbool_const(1), ""),
715  b_boolisnull,
716  b_boolcheckfalse);
717 
718  /* build block that sets anynull */
719  LLVMPositionBuilderAtEnd(b, b_boolisnull);
720  /* set boolanynull to true */
721  LLVMBuildStore(b, l_sbool_const(1), v_boolanynullp);
722  /* and jump to next block */
723  LLVMBuildBr(b, b_boolcont);
724 
725  /* build block checking for false */
726  LLVMPositionBuilderAtEnd(b, b_boolcheckfalse);
727  LLVMBuildCondBr(b,
728  LLVMBuildICmp(b, LLVMIntEQ, v_boolvalue,
729  l_sizet_const(0), ""),
730  b_boolisfalse,
731  b_boolcont);
732 
733  /*
734  * Build block handling FALSE. Value is false, so short
735  * circuit.
736  */
737  LLVMPositionBuilderAtEnd(b, b_boolisfalse);
738  /* result is already set to FALSE, need not change it */
739  /* and jump to the end of the AND expression */
740  LLVMBuildBr(b, opblocks[op->d.boolexpr.jumpdone]);
741 
742  /* Build block that continues if bool is TRUE. */
743  LLVMPositionBuilderAtEnd(b, b_boolcont);
744 
745  v_boolanynull = LLVMBuildLoad(b, v_boolanynullp, "");
746 
747  /* set value to NULL if any previous values were NULL */
748  LLVMBuildCondBr(b,
749  LLVMBuildICmp(b, LLVMIntEQ, v_boolanynull,
750  l_sbool_const(0), ""),
751  opblocks[i + 1], b_boolisanynull);
752 
753  LLVMPositionBuilderAtEnd(b, b_boolisanynull);
754  /* set resnull to true */
755  LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
756  /* reset resvalue */
757  LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
758 
759  LLVMBuildBr(b, opblocks[i + 1]);
760  break;
761  }
763  {
764  LLVMValueRef v_boolanynullp;
765 
766  v_boolanynullp = l_ptr_const(op->d.boolexpr.anynull,
767  l_ptr(TypeStorageBool));
768  LLVMBuildStore(b, l_sbool_const(0), v_boolanynullp);
769  }
770  /* FALLTHROUGH */
771 
772  /*
773  * Treat them the same for now, optimizer can remove
774  * redundancy. Could be worthwhile to optimize during emission
775  * though.
776  */
778  case EEOP_BOOL_OR_STEP:
779  {
780  LLVMValueRef v_boolvalue;
781  LLVMValueRef v_boolnull;
782  LLVMValueRef v_boolanynullp,
783  v_boolanynull;
784 
785  LLVMBasicBlockRef b_boolisnull;
786  LLVMBasicBlockRef b_boolchecktrue;
787  LLVMBasicBlockRef b_boolistrue;
788  LLVMBasicBlockRef b_boolcont;
789  LLVMBasicBlockRef b_boolisanynull;
790 
791  b_boolisnull = l_bb_before_v(opblocks[i + 1],
792  "b.%d.boolisnull", i);
793  b_boolchecktrue = l_bb_before_v(opblocks[i + 1],
794  "b.%d.boolchecktrue", i);
795  b_boolistrue = l_bb_before_v(opblocks[i + 1],
796  "b.%d.boolistrue", i);
797  b_boolisanynull = l_bb_before_v(opblocks[i + 1],
798  "b.%d.boolisanynull", i);
799  b_boolcont = l_bb_before_v(opblocks[i + 1],
800  "b.%d.boolcont", i);
801 
802  v_boolanynullp = l_ptr_const(op->d.boolexpr.anynull,
803  l_ptr(TypeStorageBool));
804 
805  v_boolnull = LLVMBuildLoad(b, v_resnullp, "");
806  v_boolvalue = LLVMBuildLoad(b, v_resvaluep, "");
807 
808  /* set resnull to boolnull */
809  LLVMBuildStore(b, v_boolnull, v_resnullp);
810  /* set revalue to boolvalue */
811  LLVMBuildStore(b, v_boolvalue, v_resvaluep);
812 
813  LLVMBuildCondBr(b,
814  LLVMBuildICmp(b, LLVMIntEQ, v_boolnull,
815  l_sbool_const(1), ""),
816  b_boolisnull,
817  b_boolchecktrue);
818 
819  /* build block that sets anynull */
820  LLVMPositionBuilderAtEnd(b, b_boolisnull);
821  /* set boolanynull to true */
822  LLVMBuildStore(b, l_sbool_const(1), v_boolanynullp);
823  /* and jump to next block */
824  LLVMBuildBr(b, b_boolcont);
825 
826  /* build block checking for true */
827  LLVMPositionBuilderAtEnd(b, b_boolchecktrue);
828  LLVMBuildCondBr(b,
829  LLVMBuildICmp(b, LLVMIntEQ, v_boolvalue,
830  l_sizet_const(1), ""),
831  b_boolistrue,
832  b_boolcont);
833 
834  /*
835  * Build block handling True. Value is true, so short
836  * circuit.
837  */
838  LLVMPositionBuilderAtEnd(b, b_boolistrue);
839  /* result is already set to TRUE, need not change it */
840  /* and jump to the end of the OR expression */
841  LLVMBuildBr(b, opblocks[op->d.boolexpr.jumpdone]);
842 
843  /* build block that continues if bool is FALSE */
844  LLVMPositionBuilderAtEnd(b, b_boolcont);
845 
846  v_boolanynull = LLVMBuildLoad(b, v_boolanynullp, "");
847 
848  /* set value to NULL if any previous values were NULL */
849  LLVMBuildCondBr(b,
850  LLVMBuildICmp(b, LLVMIntEQ, v_boolanynull,
851  l_sbool_const(0), ""),
852  opblocks[i + 1], b_boolisanynull);
853 
854  LLVMPositionBuilderAtEnd(b, b_boolisanynull);
855  /* set resnull to true */
856  LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
857  /* reset resvalue */
858  LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
859 
860  LLVMBuildBr(b, opblocks[i + 1]);
861  break;
862  }
863 
864  case EEOP_BOOL_NOT_STEP:
865  {
866  LLVMValueRef v_boolvalue;
867  LLVMValueRef v_boolnull;
868  LLVMValueRef v_negbool;
869 
870  v_boolnull = LLVMBuildLoad(b, v_resnullp, "");
871  v_boolvalue = LLVMBuildLoad(b, v_resvaluep, "");
872 
873  v_negbool = LLVMBuildZExt(b,
874  LLVMBuildICmp(b, LLVMIntEQ,
875  v_boolvalue,
876  l_sizet_const(0),
877  ""),
878  TypeSizeT, "");
879  /* set resnull to boolnull */
880  LLVMBuildStore(b, v_boolnull, v_resnullp);
881  /* set revalue to !boolvalue */
882  LLVMBuildStore(b, v_negbool, v_resvaluep);
883 
884  LLVMBuildBr(b, opblocks[i + 1]);
885  break;
886  }
887 
888  case EEOP_QUAL:
889  {
890  LLVMValueRef v_resnull;
891  LLVMValueRef v_resvalue;
892  LLVMValueRef v_nullorfalse;
893  LLVMBasicBlockRef b_qualfail;
894 
895  b_qualfail = l_bb_before_v(opblocks[i + 1],
896  "op.%d.qualfail", i);
897 
898  v_resvalue = LLVMBuildLoad(b, v_resvaluep, "");
899  v_resnull = LLVMBuildLoad(b, v_resnullp, "");
900 
901  v_nullorfalse =
902  LLVMBuildOr(b,
903  LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
904  l_sbool_const(1), ""),
905  LLVMBuildICmp(b, LLVMIntEQ, v_resvalue,
906  l_sizet_const(0), ""),
907  "");
908 
909  LLVMBuildCondBr(b,
910  v_nullorfalse,
911  b_qualfail,
912  opblocks[i + 1]);
913 
914  /* build block handling NULL or false */
915  LLVMPositionBuilderAtEnd(b, b_qualfail);
916  /* set resnull to false */
917  LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
918  /* set resvalue to false */
919  LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
920  /* and jump out */
921  LLVMBuildBr(b, opblocks[op->d.qualexpr.jumpdone]);
922  break;
923  }
924 
925  case EEOP_JUMP:
926  {
927  LLVMBuildBr(b, opblocks[op->d.jump.jumpdone]);
928  break;
929  }
930 
931  case EEOP_JUMP_IF_NULL:
932  {
933  LLVMValueRef v_resnull;
934 
935  /* Transfer control if current result is null */
936 
937  v_resnull = LLVMBuildLoad(b, v_resnullp, "");
938 
939  LLVMBuildCondBr(b,
940  LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
941  l_sbool_const(1), ""),
942  opblocks[op->d.jump.jumpdone],
943  opblocks[i + 1]);
944  break;
945  }
946 
948  {
949  LLVMValueRef v_resnull;
950 
951  /* Transfer control if current result is non-null */
952 
953  v_resnull = LLVMBuildLoad(b, v_resnullp, "");
954 
955  LLVMBuildCondBr(b,
956  LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
957  l_sbool_const(0), ""),
958  opblocks[op->d.jump.jumpdone],
959  opblocks[i + 1]);
960  break;
961  }
962 
963 
965  {
966  LLVMValueRef v_resnull;
967  LLVMValueRef v_resvalue;
968  LLVMValueRef v_nullorfalse;
969 
970  /* Transfer control if current result is null or false */
971 
972  v_resvalue = LLVMBuildLoad(b, v_resvaluep, "");
973  v_resnull = LLVMBuildLoad(b, v_resnullp, "");
974 
975  v_nullorfalse =
976  LLVMBuildOr(b,
977  LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
978  l_sbool_const(1), ""),
979  LLVMBuildICmp(b, LLVMIntEQ, v_resvalue,
980  l_sizet_const(0), ""),
981  "");
982 
983  LLVMBuildCondBr(b,
984  v_nullorfalse,
985  opblocks[op->d.jump.jumpdone],
986  opblocks[i + 1]);
987  break;
988  }
989 
991  {
992  LLVMValueRef v_resnull = LLVMBuildLoad(b, v_resnullp, "");
993  LLVMValueRef v_resvalue;
994 
995  v_resvalue =
996  LLVMBuildSelect(b,
997  LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
998  l_sbool_const(1), ""),
999  l_sizet_const(1),
1000  l_sizet_const(0),
1001  "");
1002  LLVMBuildStore(b, v_resvalue, v_resvaluep);
1003  LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1004 
1005  LLVMBuildBr(b, opblocks[i + 1]);
1006  break;
1007  }
1008 
1010  {
1011  LLVMValueRef v_resnull = LLVMBuildLoad(b, v_resnullp, "");
1012  LLVMValueRef v_resvalue;
1013 
1014  v_resvalue =
1015  LLVMBuildSelect(b,
1016  LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
1017  l_sbool_const(1), ""),
1018  l_sizet_const(0),
1019  l_sizet_const(1),
1020  "");
1021  LLVMBuildStore(b, v_resvalue, v_resvaluep);
1022  LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1023 
1024  LLVMBuildBr(b, opblocks[i + 1]);
1025  break;
1026  }
1027 
1029  build_EvalXFunc(b, mod, "ExecEvalRowNull",
1030  v_state, v_econtext, op);
1031  LLVMBuildBr(b, opblocks[i + 1]);
1032  break;
1033 
1035  build_EvalXFunc(b, mod, "ExecEvalRowNotNull",
1036  v_state, v_econtext, op);
1037  LLVMBuildBr(b, opblocks[i + 1]);
1038  break;
1039 
1040  case EEOP_BOOLTEST_IS_TRUE:
1044  {
1045  LLVMBasicBlockRef b_isnull,
1046  b_notnull;
1047  LLVMValueRef v_resnull = LLVMBuildLoad(b, v_resnullp, "");
1048 
1049  b_isnull = l_bb_before_v(opblocks[i + 1],
1050  "op.%d.isnull", i);
1051  b_notnull = l_bb_before_v(opblocks[i + 1],
1052  "op.%d.isnotnull", i);
1053 
1054  /* check if value is NULL */
1055  LLVMBuildCondBr(b,
1056  LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
1057  l_sbool_const(1), ""),
1058  b_isnull, b_notnull);
1059 
1060  /* if value is NULL, return false */
1061  LLVMPositionBuilderAtEnd(b, b_isnull);
1062 
1063  /* result is not null */
1064  LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1065 
1066  if (opcode == EEOP_BOOLTEST_IS_TRUE ||
1067  opcode == EEOP_BOOLTEST_IS_FALSE)
1068  {
1069  LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
1070  }
1071  else
1072  {
1073  LLVMBuildStore(b, l_sizet_const(1), v_resvaluep);
1074  }
1075 
1076  LLVMBuildBr(b, opblocks[i + 1]);
1077 
1078  LLVMPositionBuilderAtEnd(b, b_notnull);
1079 
1080  if (opcode == EEOP_BOOLTEST_IS_TRUE ||
1081  opcode == EEOP_BOOLTEST_IS_NOT_FALSE)
1082  {
1083  /*
1084  * if value is not null NULL, return value (already
1085  * set)
1086  */
1087  }
1088  else
1089  {
1090  LLVMValueRef v_value =
1091  LLVMBuildLoad(b, v_resvaluep, "");
1092 
1093  v_value = LLVMBuildZExt(b,
1094  LLVMBuildICmp(b, LLVMIntEQ,
1095  v_value,
1096  l_sizet_const(0),
1097  ""),
1098  TypeSizeT, "");
1099  LLVMBuildStore(b, v_value, v_resvaluep);
1100  }
1101  LLVMBuildBr(b, opblocks[i + 1]);
1102  break;
1103  }
1104 
1105  case EEOP_PARAM_EXEC:
1106  build_EvalXFunc(b, mod, "ExecEvalParamExec",
1107  v_state, v_econtext, op);
1108  LLVMBuildBr(b, opblocks[i + 1]);
1109  break;
1110 
1111  case EEOP_PARAM_EXTERN:
1112  build_EvalXFunc(b, mod, "ExecEvalParamExtern",
1113  v_state, v_econtext, op);
1114  LLVMBuildBr(b, opblocks[i + 1]);
1115  break;
1116 
1117  case EEOP_PARAM_CALLBACK:
1118  {
1119  LLVMTypeRef param_types[3];
1120  LLVMValueRef v_params[3];
1121  LLVMTypeRef v_functype;
1122  LLVMValueRef v_func;
1123 
1124  param_types[0] = l_ptr(StructExprState);
1125  param_types[1] = l_ptr(TypeSizeT);
1126  param_types[2] = l_ptr(StructExprContext);
1127 
1128  v_functype = LLVMFunctionType(LLVMVoidType(),
1129  param_types,
1130  lengthof(param_types),
1131  false);
1132  v_func = l_ptr_const(op->d.cparam.paramfunc,
1133  l_ptr(v_functype));
1134 
1135  v_params[0] = v_state;
1136  v_params[1] = l_ptr_const(op, l_ptr(TypeSizeT));
1137  v_params[2] = v_econtext;
1138  LLVMBuildCall(b,
1139  v_func,
1140  v_params, lengthof(v_params), "");
1141 
1142  LLVMBuildBr(b, opblocks[i + 1]);
1143  break;
1144  }
1145 
1146  case EEOP_SBSREF_OLD:
1147  build_EvalXFunc(b, mod, "ExecEvalSubscriptingRefOld",
1148  v_state, v_econtext, op);
1149  LLVMBuildBr(b, opblocks[i + 1]);
1150  break;
1151 
1152  case EEOP_SBSREF_ASSIGN:
1153  build_EvalXFunc(b, mod, "ExecEvalSubscriptingRefAssign",
1154  v_state, v_econtext, op);
1155  LLVMBuildBr(b, opblocks[i + 1]);
1156  break;
1157 
1158  case EEOP_SBSREF_FETCH:
1159  build_EvalXFunc(b, mod, "ExecEvalSubscriptingRefFetch",
1160  v_state, v_econtext, op);
1161  LLVMBuildBr(b, opblocks[i + 1]);
1162  break;
1163 
1164  case EEOP_CASE_TESTVAL:
1165  {
1166  LLVMBasicBlockRef b_avail,
1167  b_notavail;
1168  LLVMValueRef v_casevaluep,
1169  v_casevalue;
1170  LLVMValueRef v_casenullp,
1171  v_casenull;
1172  LLVMValueRef v_casevaluenull;
1173 
1174  b_avail = l_bb_before_v(opblocks[i + 1],
1175  "op.%d.avail", i);
1176  b_notavail = l_bb_before_v(opblocks[i + 1],
1177  "op.%d.notavail", i);
1178 
1179  v_casevaluep = l_ptr_const(op->d.casetest.value,
1180  l_ptr(TypeSizeT));
1181  v_casenullp = l_ptr_const(op->d.casetest.isnull,
1182  l_ptr(TypeStorageBool));
1183 
1184  v_casevaluenull =
1185  LLVMBuildICmp(b, LLVMIntEQ,
1186  LLVMBuildPtrToInt(b, v_casevaluep,
1187  TypeSizeT, ""),
1188  l_sizet_const(0), "");
1189  LLVMBuildCondBr(b, v_casevaluenull, b_notavail, b_avail);
1190 
1191  /* if casetest != NULL */
1192  LLVMPositionBuilderAtEnd(b, b_avail);
1193  v_casevalue = LLVMBuildLoad(b, v_casevaluep, "");
1194  v_casenull = LLVMBuildLoad(b, v_casenullp, "");
1195  LLVMBuildStore(b, v_casevalue, v_resvaluep);
1196  LLVMBuildStore(b, v_casenull, v_resnullp);
1197  LLVMBuildBr(b, opblocks[i + 1]);
1198 
1199  /* if casetest == NULL */
1200  LLVMPositionBuilderAtEnd(b, b_notavail);
1201  v_casevalue =
1202  l_load_struct_gep(b, v_econtext,
1204  v_casenull =
1205  l_load_struct_gep(b, v_econtext,
1207  LLVMBuildStore(b, v_casevalue, v_resvaluep);
1208  LLVMBuildStore(b, v_casenull, v_resnullp);
1209 
1210  LLVMBuildBr(b, opblocks[i + 1]);
1211  break;
1212  }
1213 
1214  case EEOP_MAKE_READONLY:
1215  {
1216  LLVMBasicBlockRef b_notnull;
1217  LLVMValueRef v_params[1];
1218  LLVMValueRef v_ret;
1219  LLVMValueRef v_nullp;
1220  LLVMValueRef v_valuep;
1221  LLVMValueRef v_null;
1222  LLVMValueRef v_value;
1223 
1224  b_notnull = l_bb_before_v(opblocks[i + 1],
1225  "op.%d.readonly.notnull", i);
1226 
1227  v_nullp = l_ptr_const(op->d.make_readonly.isnull,
1228  l_ptr(TypeStorageBool));
1229 
1230  v_null = LLVMBuildLoad(b, v_nullp, "");
1231 
1232  /* store null isnull value in result */
1233  LLVMBuildStore(b, v_null, v_resnullp);
1234 
1235  /* check if value is NULL */
1236  LLVMBuildCondBr(b,
1237  LLVMBuildICmp(b, LLVMIntEQ, v_null,
1238  l_sbool_const(1), ""),
1239  opblocks[i + 1], b_notnull);
1240 
1241  /* if value is not null, convert to RO datum */
1242  LLVMPositionBuilderAtEnd(b, b_notnull);
1243 
1244  v_valuep = l_ptr_const(op->d.make_readonly.value,
1245  l_ptr(TypeSizeT));
1246 
1247  v_value = LLVMBuildLoad(b, v_valuep, "");
1248 
1249  v_params[0] = v_value;
1250  v_ret =
1251  LLVMBuildCall(b,
1253  v_params, lengthof(v_params), "");
1254  LLVMBuildStore(b, v_ret, v_resvaluep);
1255 
1256  LLVMBuildBr(b, opblocks[i + 1]);
1257  break;
1258  }
1259 
1260  case EEOP_IOCOERCE:
1261  {
1262  FunctionCallInfo fcinfo_out,
1263  fcinfo_in;
1264  LLVMValueRef v_fcinfo_out,
1265  v_fcinfo_in;
1266  LLVMValueRef v_fn_addr_out,
1267  v_fn_addr_in;
1268  LLVMValueRef v_fcinfo_in_isnullp;
1269  LLVMValueRef v_retval;
1270  LLVMValueRef v_resvalue;
1271  LLVMValueRef v_resnull;
1272 
1273  LLVMValueRef v_output_skip;
1274  LLVMValueRef v_output;
1275 
1276  LLVMBasicBlockRef b_skipoutput;
1277  LLVMBasicBlockRef b_calloutput;
1278  LLVMBasicBlockRef b_input;
1279  LLVMBasicBlockRef b_inputcall;
1280 
1281  fcinfo_out = op->d.iocoerce.fcinfo_data_out;
1282  fcinfo_in = op->d.iocoerce.fcinfo_data_in;
1283 
1284  b_skipoutput = l_bb_before_v(opblocks[i + 1],
1285  "op.%d.skipoutputnull", i);
1286  b_calloutput = l_bb_before_v(opblocks[i + 1],
1287  "op.%d.calloutput", i);
1288  b_input = l_bb_before_v(opblocks[i + 1],
1289  "op.%d.input", i);
1290  b_inputcall = l_bb_before_v(opblocks[i + 1],
1291  "op.%d.inputcall", i);
1292 
1293  v_fcinfo_out = l_ptr_const(fcinfo_out, l_ptr(StructFunctionCallInfoData));
1294  v_fcinfo_in = l_ptr_const(fcinfo_in, l_ptr(StructFunctionCallInfoData));
1295  v_fn_addr_out = l_ptr_const(fcinfo_out->flinfo->fn_addr, TypePGFunction);
1296  v_fn_addr_in = l_ptr_const(fcinfo_in->flinfo->fn_addr, TypePGFunction);
1297 
1298  v_fcinfo_in_isnullp =
1299  LLVMBuildStructGEP(b, v_fcinfo_in,
1301  "v_fcinfo_in_isnull");
1302 
1303  /* output functions are not called on nulls */
1304  v_resnull = LLVMBuildLoad(b, v_resnullp, "");
1305  LLVMBuildCondBr(b,
1306  LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
1307  l_sbool_const(1), ""),
1308  b_skipoutput,
1309  b_calloutput);
1310 
1311  LLVMPositionBuilderAtEnd(b, b_skipoutput);
1312  v_output_skip = l_sizet_const(0);
1313  LLVMBuildBr(b, b_input);
1314 
1315  LLVMPositionBuilderAtEnd(b, b_calloutput);
1316  v_resvalue = LLVMBuildLoad(b, v_resvaluep, "");
1317 
1318  /* set arg[0] */
1319  LLVMBuildStore(b,
1320  v_resvalue,
1321  l_funcvaluep(b, v_fcinfo_out, 0));
1322  LLVMBuildStore(b,
1323  l_sbool_const(0),
1324  l_funcnullp(b, v_fcinfo_out, 0));
1325  /* and call output function (can never return NULL) */
1326  v_output = LLVMBuildCall(b, v_fn_addr_out, &v_fcinfo_out,
1327  1, "funccall_coerce_out");
1328  LLVMBuildBr(b, b_input);
1329 
1330  /* build block handling input function call */
1331  LLVMPositionBuilderAtEnd(b, b_input);
1332 
1333  /* phi between resnull and output function call branches */
1334  {
1335  LLVMValueRef incoming_values[2];
1336  LLVMBasicBlockRef incoming_blocks[2];
1337 
1338  incoming_values[0] = v_output_skip;
1339  incoming_blocks[0] = b_skipoutput;
1340 
1341  incoming_values[1] = v_output;
1342  incoming_blocks[1] = b_calloutput;
1343 
1344  v_output = LLVMBuildPhi(b, TypeSizeT, "output");
1345  LLVMAddIncoming(v_output,
1346  incoming_values, incoming_blocks,
1347  lengthof(incoming_blocks));
1348  }
1349 
1350  /*
1351  * If input function is strict, skip if input string is
1352  * NULL.
1353  */
1354  if (op->d.iocoerce.finfo_in->fn_strict)
1355  {
1356  LLVMBuildCondBr(b,
1357  LLVMBuildICmp(b, LLVMIntEQ, v_output,
1358  l_sizet_const(0), ""),
1359  opblocks[i + 1],
1360  b_inputcall);
1361  }
1362  else
1363  {
1364  LLVMBuildBr(b, b_inputcall);
1365  }
1366 
1367  LLVMPositionBuilderAtEnd(b, b_inputcall);
1368  /* set arguments */
1369  /* arg0: output */
1370  LLVMBuildStore(b, v_output,
1371  l_funcvaluep(b, v_fcinfo_in, 0));
1372  LLVMBuildStore(b, v_resnull,
1373  l_funcnullp(b, v_fcinfo_in, 0));
1374 
1375  /* arg1: ioparam: preset in execExpr.c */
1376  /* arg2: typmod: preset in execExpr.c */
1377 
1378  /* reset fcinfo_in->isnull */
1379  LLVMBuildStore(b, l_sbool_const(0), v_fcinfo_in_isnullp);
1380  /* and call function */
1381  v_retval = LLVMBuildCall(b, v_fn_addr_in, &v_fcinfo_in, 1,
1382  "funccall_iocoerce_in");
1383 
1384  LLVMBuildStore(b, v_retval, v_resvaluep);
1385 
1386  LLVMBuildBr(b, opblocks[i + 1]);
1387  break;
1388  }
1389 
1390  case EEOP_DISTINCT:
1391  case EEOP_NOT_DISTINCT:
1392  {
1393  FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
1394 
1395  LLVMValueRef v_fcinfo;
1396  LLVMValueRef v_fcinfo_isnull;
1397 
1398  LLVMValueRef v_argnull0,
1399  v_argisnull0;
1400  LLVMValueRef v_argnull1,
1401  v_argisnull1;
1402 
1403  LLVMValueRef v_anyargisnull;
1404  LLVMValueRef v_bothargisnull;
1405 
1406  LLVMValueRef v_result;
1407 
1408  LLVMBasicBlockRef b_noargnull;
1409  LLVMBasicBlockRef b_checkbothargnull;
1410  LLVMBasicBlockRef b_bothargnull;
1411  LLVMBasicBlockRef b_anyargnull;
1412 
1413  b_noargnull = l_bb_before_v(opblocks[i + 1], "op.%d.noargnull", i);
1414  b_checkbothargnull = l_bb_before_v(opblocks[i + 1], "op.%d.checkbothargnull", i);
1415  b_bothargnull = l_bb_before_v(opblocks[i + 1], "op.%d.bothargnull", i);
1416  b_anyargnull = l_bb_before_v(opblocks[i + 1], "op.%d.anyargnull", i);
1417 
1418  v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
1419 
1420  /* load args[0|1].isnull for both arguments */
1421  v_argnull0 = l_funcnull(b, v_fcinfo, 0);
1422  v_argisnull0 = LLVMBuildICmp(b, LLVMIntEQ, v_argnull0,
1423  l_sbool_const(1), "");
1424  v_argnull1 = l_funcnull(b, v_fcinfo, 1);
1425  v_argisnull1 = LLVMBuildICmp(b, LLVMIntEQ, v_argnull1,
1426  l_sbool_const(1), "");
1427 
1428  v_anyargisnull = LLVMBuildOr(b, v_argisnull0, v_argisnull1, "");
1429  v_bothargisnull = LLVMBuildAnd(b, v_argisnull0, v_argisnull1, "");
1430 
1431  /*
1432  * Check function arguments for NULLness: If either is
1433  * NULL, we check if both args are NULL. Otherwise call
1434  * comparator.
1435  */
1436  LLVMBuildCondBr(b, v_anyargisnull, b_checkbothargnull,
1437  b_noargnull);
1438 
1439  /*
1440  * build block checking if any arg is null
1441  */
1442  LLVMPositionBuilderAtEnd(b, b_checkbothargnull);
1443  LLVMBuildCondBr(b, v_bothargisnull, b_bothargnull,
1444  b_anyargnull);
1445 
1446 
1447  /* Both NULL? Then is not distinct... */
1448  LLVMPositionBuilderAtEnd(b, b_bothargnull);
1449  LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1450  if (opcode == EEOP_NOT_DISTINCT)
1451  LLVMBuildStore(b, l_sizet_const(1), v_resvaluep);
1452  else
1453  LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
1454 
1455  LLVMBuildBr(b, opblocks[i + 1]);
1456 
1457  /* Only one is NULL? Then is distinct... */
1458  LLVMPositionBuilderAtEnd(b, b_anyargnull);
1459  LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1460  if (opcode == EEOP_NOT_DISTINCT)
1461  LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
1462  else
1463  LLVMBuildStore(b, l_sizet_const(1), v_resvaluep);
1464  LLVMBuildBr(b, opblocks[i + 1]);
1465 
1466  /* neither argument is null: compare */
1467  LLVMPositionBuilderAtEnd(b, b_noargnull);
1468 
1469  v_result = BuildV1Call(context, b, mod, fcinfo,
1470  &v_fcinfo_isnull);
1471 
1472  if (opcode == EEOP_DISTINCT)
1473  {
1474  /* Must invert result of "=" */
1475  v_result =
1476  LLVMBuildZExt(b,
1477  LLVMBuildICmp(b, LLVMIntEQ,
1478  v_result,
1479  l_sizet_const(0), ""),
1480  TypeSizeT, "");
1481  }
1482 
1483  LLVMBuildStore(b, v_fcinfo_isnull, v_resnullp);
1484  LLVMBuildStore(b, v_result, v_resvaluep);
1485 
1486  LLVMBuildBr(b, opblocks[i + 1]);
1487  break;
1488  }
1489 
1490  case EEOP_NULLIF:
1491  {
1492  FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
1493 
1494  LLVMValueRef v_fcinfo;
1495  LLVMValueRef v_fcinfo_isnull;
1496  LLVMValueRef v_argnull0;
1497  LLVMValueRef v_argnull1;
1498  LLVMValueRef v_anyargisnull;
1499  LLVMValueRef v_arg0;
1500  LLVMBasicBlockRef b_hasnull;
1501  LLVMBasicBlockRef b_nonull;
1502  LLVMBasicBlockRef b_argsequal;
1503  LLVMValueRef v_retval;
1504  LLVMValueRef v_argsequal;
1505 
1506  b_hasnull = l_bb_before_v(opblocks[i + 1],
1507  "b.%d.null-args", i);
1508  b_nonull = l_bb_before_v(opblocks[i + 1],
1509  "b.%d.no-null-args", i);
1510  b_argsequal = l_bb_before_v(opblocks[i + 1],
1511  "b.%d.argsequal", i);
1512 
1513  v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
1514 
1515  /* if either argument is NULL they can't be equal */
1516  v_argnull0 = l_funcnull(b, v_fcinfo, 0);
1517  v_argnull1 = l_funcnull(b, v_fcinfo, 1);
1518 
1519  v_anyargisnull =
1520  LLVMBuildOr(b,
1521  LLVMBuildICmp(b, LLVMIntEQ, v_argnull0,
1522  l_sbool_const(1), ""),
1523  LLVMBuildICmp(b, LLVMIntEQ, v_argnull1,
1524  l_sbool_const(1), ""),
1525  "");
1526 
1527  LLVMBuildCondBr(b, v_anyargisnull, b_hasnull, b_nonull);
1528 
1529  /* one (or both) of the arguments are null, return arg[0] */
1530  LLVMPositionBuilderAtEnd(b, b_hasnull);
1531  v_arg0 = l_funcvalue(b, v_fcinfo, 0);
1532  LLVMBuildStore(b, v_argnull0, v_resnullp);
1533  LLVMBuildStore(b, v_arg0, v_resvaluep);
1534  LLVMBuildBr(b, opblocks[i + 1]);
1535 
1536  /* build block to invoke function and check result */
1537  LLVMPositionBuilderAtEnd(b, b_nonull);
1538 
1539  v_retval = BuildV1Call(context, b, mod, fcinfo, &v_fcinfo_isnull);
1540 
1541  /*
1542  * If result not null, and arguments are equal return null
1543  * (same result as if there'd been NULLs, hence reuse
1544  * b_hasnull).
1545  */
1546  v_argsequal = LLVMBuildAnd(b,
1547  LLVMBuildICmp(b, LLVMIntEQ,
1548  v_fcinfo_isnull,
1549  l_sbool_const(0),
1550  ""),
1551  LLVMBuildICmp(b, LLVMIntEQ,
1552  v_retval,
1553  l_sizet_const(1),
1554  ""),
1555  "");
1556  LLVMBuildCondBr(b, v_argsequal, b_argsequal, b_hasnull);
1557 
1558  /* build block setting result to NULL, if args are equal */
1559  LLVMPositionBuilderAtEnd(b, b_argsequal);
1560  LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
1561  LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
1562  LLVMBuildStore(b, v_retval, v_resvaluep);
1563 
1564  LLVMBuildBr(b, opblocks[i + 1]);
1565  break;
1566  }
1567 
1568  case EEOP_SQLVALUEFUNCTION:
1569  build_EvalXFunc(b, mod, "ExecEvalSQLValueFunction",
1570  v_state, v_econtext, op);
1571  LLVMBuildBr(b, opblocks[i + 1]);
1572  break;
1573 
1574  case EEOP_CURRENTOFEXPR:
1575  build_EvalXFunc(b, mod, "ExecEvalCurrentOfExpr",
1576  v_state, v_econtext, op);
1577  LLVMBuildBr(b, opblocks[i + 1]);
1578  break;
1579 
1580  case EEOP_NEXTVALUEEXPR:
1581  build_EvalXFunc(b, mod, "ExecEvalNextValueExpr",
1582  v_state, v_econtext, op);
1583  LLVMBuildBr(b, opblocks[i + 1]);
1584  break;
1585 
1586  case EEOP_ARRAYEXPR:
1587  build_EvalXFunc(b, mod, "ExecEvalArrayExpr",
1588  v_state, v_econtext, op);
1589  LLVMBuildBr(b, opblocks[i + 1]);
1590  break;
1591 
1592  case EEOP_ARRAYCOERCE:
1593  build_EvalXFunc(b, mod, "ExecEvalArrayCoerce",
1594  v_state, v_econtext, op);
1595  LLVMBuildBr(b, opblocks[i + 1]);
1596  break;
1597 
1598  case EEOP_ROW:
1599  build_EvalXFunc(b, mod, "ExecEvalRow",
1600  v_state, v_econtext, op);
1601  LLVMBuildBr(b, opblocks[i + 1]);
1602  break;
1603 
1604  case EEOP_ROWCOMPARE_STEP:
1605  {
1606  FunctionCallInfo fcinfo = op->d.rowcompare_step.fcinfo_data;
1607  LLVMValueRef v_fcinfo_isnull;
1608  LLVMBasicBlockRef b_null;
1609  LLVMBasicBlockRef b_compare;
1610  LLVMBasicBlockRef b_compare_result;
1611 
1612  LLVMValueRef v_retval;
1613 
1614  b_null = l_bb_before_v(opblocks[i + 1],
1615  "op.%d.row-null", i);
1616  b_compare = l_bb_before_v(opblocks[i + 1],
1617  "op.%d.row-compare", i);
1618  b_compare_result =
1619  l_bb_before_v(opblocks[i + 1],
1620  "op.%d.row-compare-result",
1621  i);
1622 
1623  /*
1624  * If function is strict, and either arg is null, we're
1625  * done.
1626  */
1627  if (op->d.rowcompare_step.finfo->fn_strict)
1628  {
1629  LLVMValueRef v_fcinfo;
1630  LLVMValueRef v_argnull0;
1631  LLVMValueRef v_argnull1;
1632  LLVMValueRef v_anyargisnull;
1633 
1634  v_fcinfo = l_ptr_const(fcinfo,
1636 
1637  v_argnull0 = l_funcnull(b, v_fcinfo, 0);
1638  v_argnull1 = l_funcnull(b, v_fcinfo, 1);
1639 
1640  v_anyargisnull =
1641  LLVMBuildOr(b,
1642  LLVMBuildICmp(b,
1643  LLVMIntEQ,
1644  v_argnull0,
1645  l_sbool_const(1),
1646  ""),
1647  LLVMBuildICmp(b, LLVMIntEQ,
1648  v_argnull1,
1649  l_sbool_const(1), ""),
1650  "");
1651 
1652  LLVMBuildCondBr(b, v_anyargisnull, b_null, b_compare);
1653  }
1654  else
1655  {
1656  LLVMBuildBr(b, b_compare);
1657  }
1658 
1659  /* build block invoking comparison function */
1660  LLVMPositionBuilderAtEnd(b, b_compare);
1661 
1662  /* call function */
1663  v_retval = BuildV1Call(context, b, mod, fcinfo,
1664  &v_fcinfo_isnull);
1665  LLVMBuildStore(b, v_retval, v_resvaluep);
1666 
1667  /* if result of function is NULL, force NULL result */
1668  LLVMBuildCondBr(b,
1669  LLVMBuildICmp(b,
1670  LLVMIntEQ,
1671  v_fcinfo_isnull,
1672  l_sbool_const(0),
1673  ""),
1674  b_compare_result,
1675  b_null);
1676 
1677  /* build block analyzing the !NULL comparator result */
1678  LLVMPositionBuilderAtEnd(b, b_compare_result);
1679 
1680  /* if results equal, compare next, otherwise done */
1681  LLVMBuildCondBr(b,
1682  LLVMBuildICmp(b,
1683  LLVMIntEQ,
1684  v_retval,
1685  l_sizet_const(0), ""),
1686  opblocks[i + 1],
1687  opblocks[op->d.rowcompare_step.jumpdone]);
1688 
1689  /*
1690  * Build block handling NULL input or NULL comparator
1691  * result.
1692  */
1693  LLVMPositionBuilderAtEnd(b, b_null);
1694  LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
1695  LLVMBuildBr(b, opblocks[op->d.rowcompare_step.jumpnull]);
1696 
1697  break;
1698  }
1699 
1700  case EEOP_ROWCOMPARE_FINAL:
1701  {
1702  RowCompareType rctype = op->d.rowcompare_final.rctype;
1703 
1704  LLVMValueRef v_cmpresult;
1705  LLVMValueRef v_result;
1706  LLVMIntPredicate predicate;
1707 
1708  /*
1709  * Btree comparators return 32 bit results, need to be
1710  * careful about sign (used as a 64 bit value it's
1711  * otherwise wrong).
1712  */
1713  v_cmpresult =
1714  LLVMBuildTrunc(b,
1715  LLVMBuildLoad(b, v_resvaluep, ""),
1716  LLVMInt32Type(), "");
1717 
1718  switch (rctype)
1719  {
1720  case ROWCOMPARE_LT:
1721  predicate = LLVMIntSLT;
1722  break;
1723  case ROWCOMPARE_LE:
1724  predicate = LLVMIntSLE;
1725  break;
1726  case ROWCOMPARE_GT:
1727  predicate = LLVMIntSGT;
1728  break;
1729  case ROWCOMPARE_GE:
1730  predicate = LLVMIntSGE;
1731  break;
1732  default:
1733  /* EQ and NE cases aren't allowed here */
1734  Assert(false);
1735  predicate = 0; /* prevent compiler warning */
1736  break;
1737  }
1738 
1739  v_result = LLVMBuildICmp(b,
1740  predicate,
1741  v_cmpresult,
1742  l_int32_const(0),
1743  "");
1744  v_result = LLVMBuildZExt(b, v_result, TypeSizeT, "");
1745 
1746  LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1747  LLVMBuildStore(b, v_result, v_resvaluep);
1748 
1749  LLVMBuildBr(b, opblocks[i + 1]);
1750  break;
1751  }
1752 
1753  case EEOP_MINMAX:
1754  build_EvalXFunc(b, mod, "ExecEvalMinMax",
1755  v_state, v_econtext, op);
1756  LLVMBuildBr(b, opblocks[i + 1]);
1757  break;
1758 
1759  case EEOP_FIELDSELECT:
1760  build_EvalXFunc(b, mod, "ExecEvalFieldSelect",
1761  v_state, v_econtext, op);
1762  LLVMBuildBr(b, opblocks[i + 1]);
1763  break;
1764 
1766  build_EvalXFunc(b, mod, "ExecEvalFieldStoreDeForm",
1767  v_state, v_econtext, op);
1768  LLVMBuildBr(b, opblocks[i + 1]);
1769  break;
1770 
1771  case EEOP_FIELDSTORE_FORM:
1772  build_EvalXFunc(b, mod, "ExecEvalFieldStoreForm",
1773  v_state, v_econtext, op);
1774  LLVMBuildBr(b, opblocks[i + 1]);
1775  break;
1776 
1777  case EEOP_SBSREF_SUBSCRIPT:
1778  {
1779  LLVMValueRef v_fn;
1780  int jumpdone = op->d.sbsref_subscript.jumpdone;
1781  LLVMValueRef v_params[2];
1782  LLVMValueRef v_ret;
1783 
1785 
1786  v_params[0] = v_state;
1787  v_params[1] = l_ptr_const(op, l_ptr(StructExprEvalStep));
1788  v_ret = LLVMBuildCall(b, v_fn,
1789  v_params, lengthof(v_params), "");
1790  v_ret = LLVMBuildZExt(b, v_ret, TypeStorageBool, "");
1791 
1792  LLVMBuildCondBr(b,
1793  LLVMBuildICmp(b, LLVMIntEQ, v_ret,
1794  l_sbool_const(1), ""),
1795  opblocks[i + 1],
1796  opblocks[jumpdone]);
1797  break;
1798  }
1799 
1800  case EEOP_DOMAIN_TESTVAL:
1801  {
1802  LLVMBasicBlockRef b_avail,
1803  b_notavail;
1804  LLVMValueRef v_casevaluep,
1805  v_casevalue;
1806  LLVMValueRef v_casenullp,
1807  v_casenull;
1808  LLVMValueRef v_casevaluenull;
1809 
1810  b_avail = l_bb_before_v(opblocks[i + 1],
1811  "op.%d.avail", i);
1812  b_notavail = l_bb_before_v(opblocks[i + 1],
1813  "op.%d.notavail", i);
1814 
1815  v_casevaluep = l_ptr_const(op->d.casetest.value,
1816  l_ptr(TypeSizeT));
1817  v_casenullp = l_ptr_const(op->d.casetest.isnull,
1818  l_ptr(TypeStorageBool));
1819 
1820  v_casevaluenull =
1821  LLVMBuildICmp(b, LLVMIntEQ,
1822  LLVMBuildPtrToInt(b, v_casevaluep,
1823  TypeSizeT, ""),
1824  l_sizet_const(0), "");
1825  LLVMBuildCondBr(b,
1826  v_casevaluenull,
1827  b_notavail, b_avail);
1828 
1829  /* if casetest != NULL */
1830  LLVMPositionBuilderAtEnd(b, b_avail);
1831  v_casevalue = LLVMBuildLoad(b, v_casevaluep, "");
1832  v_casenull = LLVMBuildLoad(b, v_casenullp, "");
1833  LLVMBuildStore(b, v_casevalue, v_resvaluep);
1834  LLVMBuildStore(b, v_casenull, v_resnullp);
1835  LLVMBuildBr(b, opblocks[i + 1]);
1836 
1837  /* if casetest == NULL */
1838  LLVMPositionBuilderAtEnd(b, b_notavail);
1839  v_casevalue =
1840  l_load_struct_gep(b, v_econtext,
1842  "");
1843  v_casenull =
1844  l_load_struct_gep(b, v_econtext,
1846  "");
1847  LLVMBuildStore(b, v_casevalue, v_resvaluep);
1848  LLVMBuildStore(b, v_casenull, v_resnullp);
1849 
1850  LLVMBuildBr(b, opblocks[i + 1]);
1851  break;
1852  }
1853 
1854  case EEOP_DOMAIN_NOTNULL:
1855  build_EvalXFunc(b, mod, "ExecEvalConstraintNotNull",
1856  v_state, v_econtext, op);
1857  LLVMBuildBr(b, opblocks[i + 1]);
1858  break;
1859 
1860  case EEOP_DOMAIN_CHECK:
1861  build_EvalXFunc(b, mod, "ExecEvalConstraintCheck",
1862  v_state, v_econtext, op);
1863  LLVMBuildBr(b, opblocks[i + 1]);
1864  break;
1865 
1866  case EEOP_CONVERT_ROWTYPE:
1867  build_EvalXFunc(b, mod, "ExecEvalConvertRowtype",
1868  v_state, v_econtext, op);
1869  LLVMBuildBr(b, opblocks[i + 1]);
1870  break;
1871 
1872  case EEOP_SCALARARRAYOP:
1873  build_EvalXFunc(b, mod, "ExecEvalScalarArrayOp",
1874  v_state, v_econtext, op);
1875  LLVMBuildBr(b, opblocks[i + 1]);
1876  break;
1877 
1878  case EEOP_XMLEXPR:
1879  build_EvalXFunc(b, mod, "ExecEvalXmlExpr",
1880  v_state, v_econtext, op);
1881  LLVMBuildBr(b, opblocks[i + 1]);
1882  break;
1883 
1884  case EEOP_AGGREF:
1885  {
1886  AggrefExprState *aggref = op->d.aggref.astate;
1887  LLVMValueRef v_aggnop;
1888  LLVMValueRef v_aggno;
1889  LLVMValueRef value,
1890  isnull;
1891 
1892  /*
1893  * At this point aggref->aggno is not yet set (it's set up
1894  * in ExecInitAgg() after initializing the expression). So
1895  * load it from memory each time round.
1896  */
1897  v_aggnop = l_ptr_const(&aggref->aggno,
1898  l_ptr(LLVMInt32Type()));
1899  v_aggno = LLVMBuildLoad(b, v_aggnop, "v_aggno");
1900 
1901  /* load agg value / null */
1902  value = l_load_gep1(b, v_aggvalues, v_aggno, "aggvalue");
1903  isnull = l_load_gep1(b, v_aggnulls, v_aggno, "aggnull");
1904 
1905  /* and store result */
1906  LLVMBuildStore(b, value, v_resvaluep);
1907  LLVMBuildStore(b, isnull, v_resnullp);
1908 
1909  LLVMBuildBr(b, opblocks[i + 1]);
1910  break;
1911  }
1912 
1913  case EEOP_GROUPING_FUNC:
1914  build_EvalXFunc(b, mod, "ExecEvalGroupingFunc",
1915  v_state, v_econtext, op);
1916  LLVMBuildBr(b, opblocks[i + 1]);
1917  break;
1918 
1919  case EEOP_WINDOW_FUNC:
1920  {
1921  WindowFuncExprState *wfunc = op->d.window_func.wfstate;
1922  LLVMValueRef v_wfuncnop;
1923  LLVMValueRef v_wfuncno;
1924  LLVMValueRef value,
1925  isnull;
1926 
1927  /*
1928  * At this point aggref->wfuncno is not yet set (it's set
1929  * up in ExecInitWindowAgg() after initializing the
1930  * expression). So load it from memory each time round.
1931  */
1932  v_wfuncnop = l_ptr_const(&wfunc->wfuncno,
1933  l_ptr(LLVMInt32Type()));
1934  v_wfuncno = LLVMBuildLoad(b, v_wfuncnop, "v_wfuncno");
1935 
1936  /* load window func value / null */
1937  value = l_load_gep1(b, v_aggvalues, v_wfuncno,
1938  "windowvalue");
1939  isnull = l_load_gep1(b, v_aggnulls, v_wfuncno,
1940  "windownull");
1941 
1942  LLVMBuildStore(b, value, v_resvaluep);
1943  LLVMBuildStore(b, isnull, v_resnullp);
1944 
1945  LLVMBuildBr(b, opblocks[i + 1]);
1946  break;
1947  }
1948 
1949  case EEOP_SUBPLAN:
1950  build_EvalXFunc(b, mod, "ExecEvalSubPlan",
1951  v_state, v_econtext, op);
1952  LLVMBuildBr(b, opblocks[i + 1]);
1953  break;
1954 
1956  build_EvalXFunc(b, mod, "ExecEvalAlternativeSubPlan",
1957  v_state, v_econtext, op);
1958  LLVMBuildBr(b, opblocks[i + 1]);
1959  break;
1960 
1962  {
1963  FunctionCallInfo fcinfo = op->d.agg_deserialize.fcinfo_data;
1964  LLVMValueRef v_fcinfo;
1965  LLVMValueRef v_argnull0;
1966  LLVMBasicBlockRef b_deserialize;
1967 
1968  b_deserialize = l_bb_before_v(opblocks[i + 1],
1969  "op.%d.deserialize", i);
1970 
1971  v_fcinfo = l_ptr_const(fcinfo,
1973  v_argnull0 = l_funcnull(b, v_fcinfo, 0);
1974 
1975  LLVMBuildCondBr(b,
1976  LLVMBuildICmp(b,
1977  LLVMIntEQ,
1978  v_argnull0,
1979  l_sbool_const(1),
1980  ""),
1981  opblocks[op->d.agg_deserialize.jumpnull],
1982  b_deserialize);
1983  LLVMPositionBuilderAtEnd(b, b_deserialize);
1984  }
1985  /* FALLTHROUGH */
1986 
1987  case EEOP_AGG_DESERIALIZE:
1988  {
1989  AggState *aggstate;
1990  FunctionCallInfo fcinfo;
1991 
1992  LLVMValueRef v_retval;
1993  LLVMValueRef v_fcinfo_isnull;
1994  LLVMValueRef v_tmpcontext;
1995  LLVMValueRef v_oldcontext;
1996 
1997  aggstate = op->d.agg_deserialize.aggstate;
1998  fcinfo = op->d.agg_deserialize.fcinfo_data;
1999 
2000  v_tmpcontext =
2001  l_ptr_const(aggstate->tmpcontext->ecxt_per_tuple_memory,
2002  l_ptr(StructMemoryContextData));
2003  v_oldcontext = l_mcxt_switch(mod, b, v_tmpcontext);
2004  v_retval = BuildV1Call(context, b, mod, fcinfo,
2005  &v_fcinfo_isnull);
2006  l_mcxt_switch(mod, b, v_oldcontext);
2007 
2008  LLVMBuildStore(b, v_retval, v_resvaluep);
2009  LLVMBuildStore(b, v_fcinfo_isnull, v_resnullp);
2010 
2011  LLVMBuildBr(b, opblocks[i + 1]);
2012  break;
2013  }
2014 
2017  {
2018  int nargs = op->d.agg_strict_input_check.nargs;
2020  bool *nulls = op->d.agg_strict_input_check.nulls;
2021  int jumpnull;
2022  int argno;
2023 
2024  LLVMValueRef v_argsp;
2025  LLVMValueRef v_nullsp;
2026  LLVMBasicBlockRef *b_checknulls;
2027 
2028  Assert(nargs > 0);
2029 
2030  jumpnull = op->d.agg_strict_input_check.jumpnull;
2031  v_argsp = l_ptr_const(args, l_ptr(StructNullableDatum));
2032  v_nullsp = l_ptr_const(nulls, l_ptr(TypeStorageBool));
2033 
2034  /* create blocks for checking args */
2035  b_checknulls = palloc(sizeof(LLVMBasicBlockRef *) * nargs);
2036  for (argno = 0; argno < nargs; argno++)
2037  {
2038  b_checknulls[argno] =
2039  l_bb_before_v(opblocks[i + 1],
2040  "op.%d.check-null.%d",
2041  i, argno);
2042  }
2043 
2044  LLVMBuildBr(b, b_checknulls[0]);
2045 
2046  /* strict function, check for NULL args */
2047  for (argno = 0; argno < nargs; argno++)
2048  {
2049  LLVMValueRef v_argno = l_int32_const(argno);
2050  LLVMValueRef v_argisnull;
2051  LLVMBasicBlockRef b_argnotnull;
2052 
2053  LLVMPositionBuilderAtEnd(b, b_checknulls[argno]);
2054 
2055  if (argno + 1 == nargs)
2056  b_argnotnull = opblocks[i + 1];
2057  else
2058  b_argnotnull = b_checknulls[argno + 1];
2059 
2060  if (opcode == EEOP_AGG_STRICT_INPUT_CHECK_NULLS)
2061  v_argisnull = l_load_gep1(b, v_nullsp, v_argno, "");
2062  else
2063  {
2064  LLVMValueRef v_argn;
2065 
2066  v_argn = LLVMBuildGEP(b, v_argsp, &v_argno, 1, "");
2067  v_argisnull =
2068  l_load_struct_gep(b, v_argn,
2070  "");
2071  }
2072 
2073  LLVMBuildCondBr(b,
2074  LLVMBuildICmp(b,
2075  LLVMIntEQ,
2076  v_argisnull,
2077  l_sbool_const(1), ""),
2078  opblocks[jumpnull],
2079  b_argnotnull);
2080  }
2081 
2082  break;
2083  }
2084 
2085  case EEOP_AGG_INIT_TRANS:
2086  {
2087  AggState *aggstate;
2088  AggStatePerTrans pertrans;
2089 
2090  LLVMValueRef v_aggstatep;
2091  LLVMValueRef v_pertransp;
2092 
2093  LLVMValueRef v_allpergroupsp;
2094 
2095  LLVMValueRef v_pergroupp;
2096 
2097  LLVMValueRef v_setoff,
2098  v_transno;
2099 
2100  LLVMValueRef v_notransvalue;
2101 
2102  LLVMBasicBlockRef b_init;
2103 
2104  aggstate = op->d.agg_init_trans.aggstate;
2105  pertrans = op->d.agg_init_trans.pertrans;
2106 
2107  v_aggstatep = l_ptr_const(aggstate,
2108  l_ptr(StructAggState));
2109  v_pertransp = l_ptr_const(pertrans,
2111 
2112  /*
2113  * pergroup = &aggstate->all_pergroups
2114  * [op->d.agg_init_trans_check.setoff]
2115  * [op->d.agg_init_trans_check.transno];
2116  */
2117  v_allpergroupsp =
2118  l_load_struct_gep(b, v_aggstatep,
2120  "aggstate.all_pergroups");
2121  v_setoff = l_int32_const(op->d.agg_init_trans.setoff);
2122  v_transno = l_int32_const(op->d.agg_init_trans.transno);
2123  v_pergroupp =
2124  LLVMBuildGEP(b,
2125  l_load_gep1(b, v_allpergroupsp, v_setoff, ""),
2126  &v_transno, 1, "");
2127 
2128  v_notransvalue =
2129  l_load_struct_gep(b, v_pergroupp,
2131  "notransvalue");
2132 
2133  b_init = l_bb_before_v(opblocks[i + 1],
2134  "op.%d.inittrans", i);
2135 
2136  LLVMBuildCondBr(b,
2137  LLVMBuildICmp(b, LLVMIntEQ, v_notransvalue,
2138  l_sbool_const(1), ""),
2139  b_init,
2140  opblocks[i + 1]);
2141 
2142  LLVMPositionBuilderAtEnd(b, b_init);
2143 
2144  {
2145  LLVMValueRef params[3];
2146  LLVMValueRef v_curaggcontext;
2147  LLVMValueRef v_current_set;
2148  LLVMValueRef v_aggcontext;
2149 
2150  v_aggcontext = l_ptr_const(op->d.agg_init_trans.aggcontext,
2151  l_ptr(StructExprContext));
2152 
2153  v_current_set =
2154  LLVMBuildStructGEP(b,
2155  v_aggstatep,
2157  "aggstate.current_set");
2158  v_curaggcontext =
2159  LLVMBuildStructGEP(b,
2160  v_aggstatep,
2162  "aggstate.curaggcontext");
2163 
2164  LLVMBuildStore(b, l_int32_const(op->d.agg_init_trans.setno),
2165  v_current_set);
2166  LLVMBuildStore(b, v_aggcontext,
2167  v_curaggcontext);
2168 
2169  params[0] = v_aggstatep;
2170  params[1] = v_pertransp;
2171  params[2] = v_pergroupp;
2172 
2173  LLVMBuildCall(b,
2175  params, lengthof(params),
2176  "");
2177  }
2178  LLVMBuildBr(b, opblocks[op->d.agg_init_trans.jumpnull]);
2179 
2180  break;
2181  }
2182 
2184  {
2185  AggState *aggstate;
2186  LLVMValueRef v_setoff,
2187  v_transno;
2188 
2189  LLVMValueRef v_aggstatep;
2190  LLVMValueRef v_allpergroupsp;
2191 
2192  LLVMValueRef v_transnull;
2193  LLVMValueRef v_pergroupp;
2194 
2195  int jumpnull = op->d.agg_strict_trans_check.jumpnull;
2196 
2197  aggstate = op->d.agg_strict_trans_check.aggstate;
2198  v_aggstatep = l_ptr_const(aggstate, l_ptr(StructAggState));
2199 
2200  /*
2201  * pergroup = &aggstate->all_pergroups
2202  * [op->d.agg_strict_trans_check.setoff]
2203  * [op->d.agg_init_trans_check.transno];
2204  */
2205  v_allpergroupsp =
2206  l_load_struct_gep(b, v_aggstatep,
2208  "aggstate.all_pergroups");
2209  v_setoff =
2210  l_int32_const(op->d.agg_strict_trans_check.setoff);
2211  v_transno =
2212  l_int32_const(op->d.agg_strict_trans_check.transno);
2213  v_pergroupp =
2214  LLVMBuildGEP(b,
2215  l_load_gep1(b, v_allpergroupsp, v_setoff, ""),
2216  &v_transno, 1, "");
2217 
2218  v_transnull =
2219  l_load_struct_gep(b, v_pergroupp,
2221  "transnull");
2222 
2223  LLVMBuildCondBr(b,
2224  LLVMBuildICmp(b, LLVMIntEQ, v_transnull,
2225  l_sbool_const(1), ""),
2226  opblocks[jumpnull],
2227  opblocks[i + 1]);
2228 
2229  break;
2230  }
2231 
2233  case EEOP_AGG_PLAIN_TRANS:
2234  {
2235  AggState *aggstate;
2236  AggStatePerTrans pertrans;
2237  FunctionCallInfo fcinfo;
2238 
2239  LLVMValueRef v_aggstatep;
2240  LLVMValueRef v_fcinfo;
2241  LLVMValueRef v_fcinfo_isnull;
2242 
2243  LLVMValueRef v_transvaluep;
2244  LLVMValueRef v_transnullp;
2245 
2246  LLVMValueRef v_setoff;
2247  LLVMValueRef v_transno;
2248 
2249  LLVMValueRef v_aggcontext;
2250 
2251  LLVMValueRef v_allpergroupsp;
2252  LLVMValueRef v_current_setp;
2253  LLVMValueRef v_current_pertransp;
2254  LLVMValueRef v_curaggcontext;
2255 
2256  LLVMValueRef v_pertransp;
2257 
2258  LLVMValueRef v_pergroupp;
2259 
2260  LLVMValueRef v_retval;
2261 
2262  LLVMValueRef v_tmpcontext;
2263  LLVMValueRef v_oldcontext;
2264 
2265  aggstate = op->d.agg_trans.aggstate;
2266  pertrans = op->d.agg_trans.pertrans;
2267 
2268  fcinfo = pertrans->transfn_fcinfo;
2269 
2270  v_aggstatep = l_ptr_const(aggstate,
2271  l_ptr(StructAggState));
2272  v_pertransp = l_ptr_const(pertrans,
2274 
2275  /*
2276  * pergroup = &aggstate->all_pergroups
2277  * [op->d.agg_strict_trans_check.setoff]
2278  * [op->d.agg_init_trans_check.transno];
2279  */
2280  v_allpergroupsp =
2281  l_load_struct_gep(b, v_aggstatep,
2283  "aggstate.all_pergroups");
2284  v_setoff = l_int32_const(op->d.agg_trans.setoff);
2285  v_transno = l_int32_const(op->d.agg_trans.transno);
2286  v_pergroupp =
2287  LLVMBuildGEP(b,
2288  l_load_gep1(b, v_allpergroupsp, v_setoff, ""),
2289  &v_transno, 1, "");
2290 
2291  v_fcinfo = l_ptr_const(fcinfo,
2293  v_aggcontext = l_ptr_const(op->d.agg_trans.aggcontext,
2294  l_ptr(StructExprContext));
2295 
2296  v_current_setp =
2297  LLVMBuildStructGEP(b,
2298  v_aggstatep,
2300  "aggstate.current_set");
2301  v_curaggcontext =
2302  LLVMBuildStructGEP(b,
2303  v_aggstatep,
2305  "aggstate.curaggcontext");
2306  v_current_pertransp =
2307  LLVMBuildStructGEP(b,
2308  v_aggstatep,
2310  "aggstate.curpertrans");
2311 
2312  /* set aggstate globals */
2313  LLVMBuildStore(b, v_aggcontext, v_curaggcontext);
2314  LLVMBuildStore(b, l_int32_const(op->d.agg_trans.setno),
2315  v_current_setp);
2316  LLVMBuildStore(b, v_pertransp, v_current_pertransp);
2317 
2318  /* invoke transition function in per-tuple context */
2319  v_tmpcontext =
2320  l_ptr_const(aggstate->tmpcontext->ecxt_per_tuple_memory,
2321  l_ptr(StructMemoryContextData));
2322  v_oldcontext = l_mcxt_switch(mod, b, v_tmpcontext);
2323 
2324  /* store transvalue in fcinfo->args[0] */
2325  v_transvaluep =
2326  LLVMBuildStructGEP(b, v_pergroupp,
2328  "transvalue");
2329  v_transnullp =
2330  LLVMBuildStructGEP(b, v_pergroupp,
2332  "transnullp");
2333  LLVMBuildStore(b,
2334  LLVMBuildLoad(b, v_transvaluep,
2335  "transvalue"),
2336  l_funcvaluep(b, v_fcinfo, 0));
2337  LLVMBuildStore(b,
2338  LLVMBuildLoad(b, v_transnullp, "transnull"),
2339  l_funcnullp(b, v_fcinfo, 0));
2340 
2341  /* and invoke transition function */
2342  v_retval = BuildV1Call(context, b, mod, fcinfo,
2343  &v_fcinfo_isnull);
2344 
2345  /*
2346  * For pass-by-ref datatype, must copy the new value into
2347  * aggcontext and free the prior transValue. But if
2348  * transfn returned a pointer to its first input, we don't
2349  * need to do anything. Also, if transfn returned a
2350  * pointer to a R/W expanded object that is already a
2351  * child of the aggcontext, assume we can adopt that value
2352  * without copying it.
2353  */
2354  if (opcode == EEOP_AGG_PLAIN_TRANS)
2355  {
2356  LLVMBasicBlockRef b_call;
2357  LLVMBasicBlockRef b_nocall;
2358  LLVMValueRef v_fn;
2359  LLVMValueRef v_transvalue;
2360  LLVMValueRef v_transnull;
2361  LLVMValueRef v_newval;
2362  LLVMValueRef params[6];
2363 
2364  b_call = l_bb_before_v(opblocks[i + 1],
2365  "op.%d.transcall", i);
2366  b_nocall = l_bb_before_v(opblocks[i + 1],
2367  "op.%d.transnocall", i);
2368 
2369  v_transvalue = LLVMBuildLoad(b, v_transvaluep, "");
2370  v_transnull = LLVMBuildLoad(b, v_transnullp, "");
2371 
2372  /*
2373  * DatumGetPointer(newVal) !=
2374  * DatumGetPointer(pergroup->transValue))
2375  */
2376  LLVMBuildCondBr(b,
2377  LLVMBuildICmp(b, LLVMIntEQ,
2378  v_transvalue,
2379  v_retval, ""),
2380  b_nocall, b_call);
2381 
2382  /* returned datum not passed datum, reparent */
2383  LLVMPositionBuilderAtEnd(b, b_call);
2384 
2385  params[0] = v_aggstatep;
2386  params[1] = v_pertransp;
2387  params[2] = v_retval;
2388  params[3] = LLVMBuildTrunc(b, v_fcinfo_isnull,
2389  TypeParamBool, "");
2390  params[4] = v_transvalue;
2391  params[5] = LLVMBuildTrunc(b, v_transnull,
2392  TypeParamBool, "");
2393 
2395  v_newval =
2396  LLVMBuildCall(b, v_fn,
2397  params, lengthof(params),
2398  "");
2399 
2400  /* store trans value */
2401  LLVMBuildStore(b, v_newval, v_transvaluep);
2402  LLVMBuildStore(b, v_fcinfo_isnull, v_transnullp);
2403 
2404  l_mcxt_switch(mod, b, v_oldcontext);
2405  LLVMBuildBr(b, opblocks[i + 1]);
2406 
2407  /* returned datum passed datum, no need to reparent */
2408  LLVMPositionBuilderAtEnd(b, b_nocall);
2409  }
2410 
2411  /* store trans value */
2412  LLVMBuildStore(b, v_retval, v_transvaluep);
2413  LLVMBuildStore(b, v_fcinfo_isnull, v_transnullp);
2414 
2415  l_mcxt_switch(mod, b, v_oldcontext);
2416 
2417  LLVMBuildBr(b, opblocks[i + 1]);
2418  break;
2419  }
2420 
2422  build_EvalXFunc(b, mod, "ExecEvalAggOrderedTransDatum",
2423  v_state, v_econtext, op);
2424  LLVMBuildBr(b, opblocks[i + 1]);
2425  break;
2426 
2428  build_EvalXFunc(b, mod, "ExecEvalAggOrderedTransTuple",
2429  v_state, v_econtext, op);
2430  LLVMBuildBr(b, opblocks[i + 1]);
2431  break;
2432 
2433  case EEOP_LAST:
2434  Assert(false);
2435  break;
2436  }
2437  }
2438 
2439  LLVMDisposeBuilder(b);
2440 
2441  /*
2442  * Don't immediately emit function, instead do so the first time the
2443  * expression is actually evaluated. That allows to emit a lot of
2444  * functions together, avoiding a lot of repeated llvm and memory
2445  * remapping overhead.
2446  */
2447  {
2448 
2449  CompiledExprState *cstate = palloc0(sizeof(CompiledExprState));
2450 
2451  cstate->context = context;
2452  cstate->funcname = funcname;
2453 
2454  state->evalfunc = ExecRunCompiledExpr;
2455  state->evalfunc_private = cstate;
2456  }
2457 
2459 
2460  INSTR_TIME_SET_CURRENT(endtime);
2461  INSTR_TIME_ACCUM_DIFF(context->base.instr.generation_counter,
2462  endtime, starttime);
2463 
2464  return true;
2465 }
#define FIELDNO_FUNCTIONCALLINFODATA_ISNULL
Definition: fmgr.h:91
#define FIELDNO_EXPRCONTEXT_CASENULL
Definition: execnodes.h:249
LLVMValueRef slot_compile_deform(LLVMJitContext *context, TupleDesc desc, const TupleTableSlotOps *ops, int natts)
struct ExprEvalStep::@52::@94 agg_trans
static LLVMValueRef BuildV1Call(LLVMJitContext *context, LLVMBuilderRef b, LLVMModuleRef mod, FunctionCallInfo fcinfo, LLVMValueRef *v_fcinfo_isnull)
#define FIELDNO_EXPRSTATE_RESVALUE
Definition: execnodes.h:73
LLVMTypeRef StructFunctionCallInfoData
Definition: llvmjit.c:70
#define FIELDNO_NULLABLE_DATUM_ISNULL
Definition: postgres.h:379
struct PlanState * parent
Definition: execnodes.h:107
struct ExprEvalStep::@52::@54 var
static void build_EvalXFunc(LLVMBuilderRef b, LLVMModuleRef mod, const char *funcname, LLVMValueRef v_state, LLVMValueRef v_econtext, ExprEvalStep *op)
struct JitContext * es_jit
Definition: execnodes.h:595
Datum * resvalue
Definition: execExpr.h:250
PGFunction fn_addr
Definition: fmgr.h:58
struct ExprEvalStep::@52::@92 agg_init_trans
LLVMTypeRef StructExprEvalStep
Definition: llvmjit.c:72
struct ExprEvalStep * steps
Definition: execnodes.h:85
LLVMTypeRef TypeSizeT
Definition: llvmjit.c:48
#define FIELDNO_EXPRCONTEXT_SCANTUPLE
Definition: execnodes.h:222
LLVMTypeRef StructExprState
Definition: llvmjit.c:73
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:231
struct ExprEvalStep::@52::@85 aggref
struct timeval instr_time
Definition: instr_time.h:150
LLVMTypeRef StructNullableDatum
Definition: llvmjit.c:52
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:83
bool * resnull
Definition: execExpr.h:251
LLVMValueRef llvm_get_decl(LLVMModuleRef mod, LLVMValueRef v_src)
Definition: llvmjit.c:311
ExprEvalOp
Definition: execExpr.h:44
#define FIELDNO_AGGSTATE_CURAGGCONTEXT
Definition: execnodes.h:2045
#define FIELDNO_TUPLETABLESLOT_ISNULL
Definition: tuptable.h:127
static struct @145 value
#define INSTR_TIME_ACCUM_DIFF(x, y, z)
Definition: instr_time.h:182
LLVMJitContext * llvm_create_context(int jitFlags)
Definition: llvmjit.c:136
#define lengthof(array)
Definition: c.h:669
EState * state
Definition: execnodes.h:941
LLVMTypeRef StructAggState
Definition: llvmjit.c:74
union ExprEvalStep::@52 d
FunctionCallInfo transfn_fcinfo
Definition: nodeAgg.h:161
struct ExprEvalStep::@52::@65 cparam
struct ExprEvalStep::@52::@61 qualexpr
ExprContext * tmpcontext
Definition: execnodes.h:2044
struct ExprEvalStep::@52::@90 agg_deserialize
#define FIELDNO_AGGSTATE_ALL_PERGROUPS
Definition: execnodes.h:2075
ExprEvalOp ExecEvalStepOp(ExprState *state, ExprEvalStep *op)
#define FIELDNO_EXPRCONTEXT_OUTERTUPLE
Definition: execnodes.h:226
struct ExprEvalStep::@52::@53 fetch
#define ERROR
Definition: elog.h:43
struct ExprEvalStep::@52::@67 make_readonly
#define FIELDNO_EXPRCONTEXT_DOMAINDATUM
Definition: execnodes.h:253
LLVMValueRef FuncExecAggInitGroup
Definition: llvmjit.c:87
static Datum ExecRunCompiledExpr(ExprState *state, ExprContext *econtext, bool *isNull)
#define FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL
Definition: nodeAgg.h:245
char * llvm_expand_funcname(struct LLVMJitContext *context, const char *basename)
Definition: llvmjit.c:222
LLVMJitContext * context
Definition: llvmjit_expr.c:51
ExprStateEvalFunc evalfunc
Definition: execnodes.h:91
int es_jit_flags
Definition: execnodes.h:594
LLVMTypeRef TypeStorageBool
Definition: llvmjit.c:50
struct ExprEvalStep::@52::@66 casetest
LLVMValueRef FuncExecEvalSubscriptingRef
Definition: llvmjit.c:84
LLVMValueRef FuncMakeExpandedObjectReadOnlyInternal
Definition: llvmjit.c:83
struct ExprEvalStep::@52::@58 constval
LLVMValueRef FuncSlotGetsomeattrsInt
Definition: llvmjit.c:81
#define FIELDNO_TUPLETABLESLOT_NVALID
Definition: tuptable.h:120
LLVMTypeRef StructMemoryContextData
Definition: llvmjit.c:67
#define FIELDNO_EXPRSTATE_RESNULL
Definition: execnodes.h:71
struct ExprEvalStep::@52::@60 boolexpr
#define FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUE
Definition: nodeAgg.h:243
LLVMTypeRef StructExprContext
Definition: llvmjit.c:71
#define FIELDNO_AGGSTATE_CURRENT_SET
Definition: execnodes.h:2053
#define FIELDNO_EXPRCONTEXT_AGGNULLS
Definition: execnodes.h:243
void * evalfunc_private
Definition: execnodes.h:97
LLVMTypeRef TypePGFunction
Definition: llvmjit.c:51
struct ExprEvalStep::@52::@93 agg_strict_trans_check
#define FIELDNO_AGGSTATEPERGROUPDATA_NOTRANSVALUE
Definition: nodeAgg.h:248
#define FIELDNO_EXPRCONTEXT_INNERTUPLE
Definition: execnodes.h:224
LLVMTypeRef StructAggStatePerTransData
Definition: llvmjit.c:76
struct ExprEvalStep::@52::@87 window_func
void * palloc0(Size size)
Definition: mcxt.c:980
#define FIELDNO_EXPRCONTEXT_CASEDATUM
Definition: execnodes.h:247
FmgrInfo * flinfo
Definition: fmgr.h:87
struct ExprEvalStep::@52::@62 jump
LLVMValueRef FuncExecEvalSysVar
Definition: llvmjit.c:85
RowCompareType
Definition: primnodes.h:1042
struct ExprEvalStep::@52::@56 assign_var
LLVMModuleRef llvm_mutable_module(LLVMJitContext *context)
Definition: llvmjit.c:197
struct ExprEvalStep::@52::@59 func
struct ExprEvalStep::@52::@74 rowcompare_step
#define Assert(condition)
Definition: c.h:739
#define FIELDNO_EXPRSTATE_RESULTSLOT
Definition: execnodes.h:79
LLVMTypeRef TypeParamBool
Definition: llvmjit.c:49
struct ExprEvalStep::@52::@91 agg_strict_input_check
#define INSTR_TIME_SET_CURRENT(t)
Definition: instr_time.h:156
#define FIELDNO_EXPRCONTEXT_DOMAINNULL
Definition: execnodes.h:255
struct ExprEvalStep::@52::@79 sbsref_subscript
void * palloc(Size size)
Definition: mcxt.c:949
int steps_len
Definition: execnodes.h:104
void llvm_enter_fatal_on_oom(void)
struct ExprEvalStep::@52::@68 iocoerce
#define FIELDNO_TUPLETABLESLOT_VALUES
Definition: tuptable.h:125
#define elog(elevel,...)
Definition: elog.h:228
int i
LLVMValueRef AttributeTemplate
Definition: llvmjit.c:78
const char * funcname
Definition: llvmjit_expr.c:52
void llvm_copy_attributes(LLVMValueRef v_from, LLVMValueRef v_to)
Definition: llvmjit.c:332
#define PGJIT_DEFORM
Definition: jit.h:24
#define FIELDNO_EXPRCONTEXT_AGGVALUES
Definition: execnodes.h:241
LLVMValueRef FuncExecAggTransReparent
Definition: llvmjit.c:86
struct ExprEvalStep::@52::@75 rowcompare_final
void llvm_leave_fatal_on_oom(void)
#define FIELDNO_AGGSTATE_CURPERTRANS
Definition: execnodes.h:2048
struct ExprEvalStep::@52::@57 assign_tmp