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 "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
 

Macros

#define build_EvalXFunc(b, mod, funcname, v_state, op, ...)
 

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 LLVMValueRef build_EvalXFuncInt (LLVMBuilderRef b, LLVMModuleRef mod, const char *funcname, LLVMValueRef v_state, ExprEvalStep *op, int natts, LLVMValueRef *v_args)
 
static LLVMValueRef create_LifetimeEnd (LLVMModuleRef mod)
 
bool llvm_compile_expr (ExprState *state)
 

Macro Definition Documentation

◆ build_EvalXFunc

#define build_EvalXFunc (   b,
  mod,
  funcname,
  v_state,
  op,
  ... 
)
Value:
build_EvalXFuncInt(b, mod, funcname, v_state, op, \
lengthof(((LLVMValueRef[]){__VA_ARGS__})), \
((LLVMValueRef[]){__VA_ARGS__}))
#define lengthof(array)
Definition: c.h:788
#define funcname
Definition: indent_codes.h:69
int b
Definition: isn.c:70
static LLVMValueRef build_EvalXFuncInt(LLVMBuilderRef b, LLVMModuleRef mod, const char *funcname, LLVMValueRef v_state, ExprEvalStep *op, int natts, LLVMValueRef *v_args)

Definition at line 68 of file llvmjit_expr.c.

Typedef Documentation

◆ CompiledExprState

Function Documentation

◆ build_EvalXFuncInt()

static LLVMValueRef build_EvalXFuncInt ( LLVMBuilderRef  b,
LLVMModuleRef  mod,
const char *  funcname,
LLVMValueRef  v_state,
ExprEvalStep op,
int  natts,
LLVMValueRef *  v_args 
)
static

Definition at line 2730 of file llvmjit_expr.c.

2733 {
2734  LLVMValueRef v_fn = llvm_pg_func(mod, funcname);
2735  LLVMValueRef *params;
2736  int argno = 0;
2737  LLVMValueRef v_ret;
2738 
2739  /* cheap pre-check as llvm just asserts out */
2740  if (LLVMCountParams(v_fn) != (nargs + 2))
2741  elog(ERROR, "parameter mismatch: %s expects %d passed %d",
2742  funcname, LLVMCountParams(v_fn), nargs + 2);
2743 
2744  params = palloc(sizeof(LLVMValueRef) * (2 + nargs));
2745 
2746  params[argno++] = v_state;
2747  params[argno++] = l_ptr_const(op, l_ptr(StructExprEvalStep));
2748 
2749  for (int i = 0; i < nargs; i++)
2750  params[argno++] = v_args[i];
2751 
2752  v_ret = l_call(b, LLVMGetFunctionType(v_fn), v_fn, params, argno, "");
2753 
2754  pfree(params);
2755 
2756  return v_ret;
2757 }
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
int i
Definition: isn.c:73
LLVMTypeRef StructExprEvalStep
Definition: llvmjit.c:79
LLVMValueRef llvm_pg_func(LLVMModuleRef mod, const char *funcname)
Definition: llvmjit.c:496
LLVMTypeRef LLVMGetFunctionType(LLVMValueRef r)
void pfree(void *pointer)
Definition: mcxt.c:1520
void * palloc(Size size)
Definition: mcxt.c:1316

References b, elog, ERROR, funcname, i, llvm_pg_func(), LLVMGetFunctionType(), palloc(), pfree(), and StructExprEvalStep.

◆ BuildV1Call()

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

Definition at line 2679 of file llvmjit_expr.c.

2682 {
2683  LLVMContextRef lc;
2684  LLVMValueRef v_fn;
2685  LLVMValueRef v_fcinfo_isnullp;
2686  LLVMValueRef v_retval;
2687  LLVMValueRef v_fcinfo;
2688 
2689  lc = LLVMGetModuleContext(mod);
2690 
2691  v_fn = llvm_function_reference(context, b, mod, fcinfo);
2692 
2693  v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
2694  v_fcinfo_isnullp = l_struct_gep(b,
2696  v_fcinfo,
2698  "v_fcinfo_isnull");
2699  LLVMBuildStore(b, l_sbool_const(0), v_fcinfo_isnullp);
2700 
2701  v_retval = l_call(b, LLVMGetFunctionType(AttributeTemplate), v_fn, &v_fcinfo, 1, "funccall");
2702 
2703  if (v_fcinfo_isnull)
2704  *v_fcinfo_isnull = l_load(b, TypeStorageBool, v_fcinfo_isnullp, "");
2705 
2706  /*
2707  * Add lifetime-end annotation, signaling that writes to memory don't have
2708  * to be retained (important for inlining potential).
2709  */
2710  {
2711  LLVMValueRef v_lifetime = create_LifetimeEnd(mod);
2712  LLVMValueRef params[2];
2713 
2714  params[0] = l_int64_const(lc, sizeof(NullableDatum) * fcinfo->nargs);
2715  params[1] = l_ptr_const(fcinfo->args, l_ptr(LLVMInt8TypeInContext(lc)));
2716  l_call(b, LLVMGetFunctionType(v_lifetime), v_lifetime, params, lengthof(params), "");
2717 
2718  params[0] = l_int64_const(lc, sizeof(fcinfo->isnull));
2719  params[1] = l_ptr_const(&fcinfo->isnull, l_ptr(LLVMInt8TypeInContext(lc)));
2720  l_call(b, LLVMGetFunctionType(v_lifetime), v_lifetime, params, lengthof(params), "");
2721  }
2722 
2723  return v_retval;
2724 }
#define FIELDNO_FUNCTIONCALLINFODATA_ISNULL
Definition: fmgr.h:91
LLVMTypeRef StructFunctionCallInfoData
Definition: llvmjit.c:77
LLVMValueRef llvm_function_reference(LLVMJitContext *context, LLVMBuilderRef builder, LLVMModuleRef mod, FunctionCallInfo fcinfo)
Definition: llvmjit.c:572
LLVMTypeRef TypeStorageBool
Definition: llvmjit.c:66
LLVMValueRef AttributeTemplate
Definition: llvmjit.c:86
static LLVMValueRef create_LifetimeEnd(LLVMModuleRef mod)
tree context
Definition: radixtree.h:1829
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
Definition: fmgr.h:95

References FunctionCallInfoBaseData::args, AttributeTemplate, b, context, create_LifetimeEnd(), FIELDNO_FUNCTIONCALLINFODATA_ISNULL, FunctionCallInfoBaseData::isnull, lengthof, llvm_function_reference(), LLVMGetFunctionType(), FunctionCallInfoBaseData::nargs, StructFunctionCallInfoData, and TypeStorageBool.

◆ create_LifetimeEnd()

static LLVMValueRef create_LifetimeEnd ( LLVMModuleRef  mod)
static

Definition at line 2760 of file llvmjit_expr.c.

2761 {
2762  LLVMTypeRef sig;
2763  LLVMValueRef fn;
2764  LLVMTypeRef param_types[2];
2765  LLVMContextRef lc;
2766 
2767  /* variadic pointer argument */
2768  const char *nm = "llvm.lifetime.end.p0i8";
2769 
2770  fn = LLVMGetNamedFunction(mod, nm);
2771  if (fn)
2772  return fn;
2773 
2774  lc = LLVMGetModuleContext(mod);
2775  param_types[0] = LLVMInt64TypeInContext(lc);
2776  param_types[1] = l_ptr(LLVMInt8TypeInContext(lc));
2777 
2778  sig = LLVMFunctionType(LLVMVoidTypeInContext(lc), param_types,
2779  lengthof(param_types), false);
2780  fn = LLVMAddFunction(mod, nm, sig);
2781 
2782  LLVMSetFunctionCallConv(fn, LLVMCCallConv);
2783 
2784  Assert(LLVMGetIntrinsicID(fn));
2785 
2786  return fn;
2787 }
#define Assert(condition)
Definition: c.h:858
static int sig
Definition: pg_ctl.c:79
static void * fn(void *arg)
Definition: thread-alloc.c:119

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

Referenced by BuildV1Call().

◆ ExecRunCompiledExpr()

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

Definition at line 2659 of file llvmjit_expr.c.

2660 {
2661  CompiledExprState *cstate = state->evalfunc_private;
2662  ExprStateEvalFunc func;
2663 
2664  CheckExprStillValid(state, econtext);
2665 
2667  func = (ExprStateEvalFunc) llvm_get_function(cstate->context,
2668  cstate->funcname);
2670  Assert(func);
2671 
2672  /* remove indirection via this function for future calls */
2673  state->evalfunc = func;
2674 
2675  return func(state, econtext, isNull);
2676 }
void CheckExprStillValid(ExprState *state, ExprContext *econtext)
Datum(* ExprStateEvalFunc)(struct ExprState *expression, struct ExprContext *econtext, bool *isNull)
Definition: execnodes.h:70
void * llvm_get_function(LLVMJitContext *context, const char *funcname)
Definition: llvmjit.c:380
void llvm_enter_fatal_on_oom(void)
void llvm_leave_fatal_on_oom(void)
const char * funcname
Definition: llvmjit_expr.c:51
LLVMJitContext * context
Definition: llvmjit_expr.c:50
Definition: regguts.h:323

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

◆ llvm_compile_expr()

bool llvm_compile_expr ( ExprState state)

Definition at line 78 of file llvmjit_expr.c.

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

References Assert, b, context, EState::es_jit, EState::es_jit_flags, funcname, llvm_create_context(), llvm_enter_fatal_on_oom(), and PlanState::state.

Referenced by _PG_jit_provider_init().