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:742
#define funcname
Definition: indent_codes.h:69
int b
Definition: isn.c:69
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 2961 of file llvmjit_expr.c.

2964 {
2965  LLVMValueRef v_fn = llvm_pg_func(mod, funcname);
2966  LLVMValueRef *params;
2967  int argno = 0;
2968  LLVMValueRef v_ret;
2969 
2970  /* cheap pre-check as llvm just asserts out */
2971  if (LLVMCountParams(v_fn) != (nargs + 2))
2972  elog(ERROR, "parameter mismatch: %s expects %d passed %d",
2973  funcname, LLVMCountParams(v_fn), nargs + 2);
2974 
2975  params = palloc(sizeof(LLVMValueRef) * (2 + nargs));
2976 
2977  params[argno++] = v_state;
2978  params[argno++] = l_ptr_const(op, l_ptr(StructExprEvalStep));
2979 
2980  for (int i = 0; i < nargs; i++)
2981  params[argno++] = v_args[i];
2982 
2983  v_ret = l_call(b, LLVMGetFunctionType(v_fn), v_fn, params, argno, "");
2984 
2985  pfree(params);
2986 
2987  return v_ret;
2988 }
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
int i
Definition: isn.c:72
LLVMTypeRef StructExprEvalStep
Definition: llvmjit.c:71
LLVMValueRef llvm_pg_func(LLVMModuleRef mod, const char *funcname)
Definition: llvmjit.c:461
LLVMTypeRef LLVMGetFunctionType(LLVMValueRef r)
void pfree(void *pointer)
Definition: mcxt.c:1521
void * palloc(Size size)
Definition: mcxt.c:1317

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 2910 of file llvmjit_expr.c.

2913 {
2914  LLVMContextRef lc;
2915  LLVMValueRef v_fn;
2916  LLVMValueRef v_fcinfo_isnullp;
2917  LLVMValueRef v_retval;
2918  LLVMValueRef v_fcinfo;
2919 
2920  lc = LLVMGetModuleContext(mod);
2921 
2922  v_fn = llvm_function_reference(context, b, mod, fcinfo);
2923 
2924  v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
2925  v_fcinfo_isnullp = l_struct_gep(b,
2927  v_fcinfo,
2929  "v_fcinfo_isnull");
2930  LLVMBuildStore(b, l_sbool_const(0), v_fcinfo_isnullp);
2931 
2932  v_retval = l_call(b, LLVMGetFunctionType(AttributeTemplate), v_fn, &v_fcinfo, 1, "funccall");
2933 
2934  if (v_fcinfo_isnull)
2935  *v_fcinfo_isnull = l_load(b, TypeStorageBool, v_fcinfo_isnullp, "");
2936 
2937  /*
2938  * Add lifetime-end annotation, signaling that writes to memory don't have
2939  * to be retained (important for inlining potential).
2940  */
2941  {
2942  LLVMValueRef v_lifetime = create_LifetimeEnd(mod);
2943  LLVMValueRef params[2];
2944 
2945  params[0] = l_int64_const(lc, sizeof(NullableDatum) * fcinfo->nargs);
2946  params[1] = l_ptr_const(fcinfo->args, l_ptr(LLVMInt8TypeInContext(lc)));
2947  l_call(b, LLVMGetFunctionType(v_lifetime), v_lifetime, params, lengthof(params), "");
2948 
2949  params[0] = l_int64_const(lc, sizeof(fcinfo->isnull));
2950  params[1] = l_ptr_const(&fcinfo->isnull, l_ptr(LLVMInt8TypeInContext(lc)));
2951  l_call(b, LLVMGetFunctionType(v_lifetime), v_lifetime, params, lengthof(params), "");
2952  }
2953 
2954  return v_retval;
2955 }
#define FIELDNO_FUNCTIONCALLINFODATA_ISNULL
Definition: fmgr.h:91
LLVMTypeRef StructFunctionCallInfoData
Definition: llvmjit.c:69
LLVMValueRef llvm_function_reference(LLVMJitContext *context, LLVMBuilderRef builder, LLVMModuleRef mod, FunctionCallInfo fcinfo)
Definition: llvmjit.c:537
LLVMTypeRef TypeStorageBool
Definition: llvmjit.c:58
LLVMValueRef AttributeTemplate
Definition: llvmjit.c:78
static LLVMValueRef create_LifetimeEnd(LLVMModuleRef mod)
tree context
Definition: radixtree.h:1837
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 2991 of file llvmjit_expr.c.

2992 {
2993  LLVMTypeRef sig;
2994  LLVMValueRef fn;
2995  LLVMTypeRef param_types[2];
2996  LLVMContextRef lc;
2997 
2998  /* variadic pointer argument */
2999  const char *nm = "llvm.lifetime.end.p0";
3000 
3001  fn = LLVMGetNamedFunction(mod, nm);
3002  if (fn)
3003  return fn;
3004 
3005  lc = LLVMGetModuleContext(mod);
3006  param_types[0] = LLVMInt64TypeInContext(lc);
3007  param_types[1] = l_ptr(LLVMInt8TypeInContext(lc));
3008 
3009  sig = LLVMFunctionType(LLVMVoidTypeInContext(lc), param_types,
3010  lengthof(param_types), false);
3011  fn = LLVMAddFunction(mod, nm, sig);
3012 
3013  LLVMSetFunctionCallConv(fn, LLVMCCallConv);
3014 
3015  Assert(LLVMGetIntrinsicID(fn));
3016 
3017  return fn;
3018 }
#define Assert(condition)
Definition: c.h:812
static int sig
Definition: pg_ctl.c:80
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 2890 of file llvmjit_expr.c.

2891 {
2892  CompiledExprState *cstate = state->evalfunc_private;
2893  ExprStateEvalFunc func;
2894 
2895  CheckExprStillValid(state, econtext);
2896 
2898  func = (ExprStateEvalFunc) llvm_get_function(cstate->context,
2899  cstate->funcname);
2901  Assert(func);
2902 
2903  /* remove indirection via this function for future calls */
2904  state->evalfunc = func;
2905 
2906  return func(state, econtext, isNull);
2907 }
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:359
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  /* check if current input is NULL */
724  LLVMBuildCondBr(b,
725  LLVMBuildICmp(b, LLVMIntEQ, v_boolnull,
726  l_sbool_const(1), ""),
727  b_boolisnull,
728  b_boolcheckfalse);
729 
730  /* build block that sets anynull */
731  LLVMPositionBuilderAtEnd(b, b_boolisnull);
732  /* set boolanynull to true */
733  LLVMBuildStore(b, l_sbool_const(1), v_boolanynullp);
734  /* and jump to next block */
735  LLVMBuildBr(b, b_boolcont);
736 
737  /* build block checking for false */
738  LLVMPositionBuilderAtEnd(b, b_boolcheckfalse);
739  LLVMBuildCondBr(b,
740  LLVMBuildICmp(b, LLVMIntEQ, v_boolvalue,
741  l_sizet_const(0), ""),
742  b_boolisfalse,
743  b_boolcont);
744 
745  /*
746  * Build block handling FALSE. Value is false, so short
747  * circuit.
748  */
749  LLVMPositionBuilderAtEnd(b, b_boolisfalse);
750  /* result is already set to FALSE, need not change it */
751  /* and jump to the end of the AND expression */
752  LLVMBuildBr(b, opblocks[op->d.boolexpr.jumpdone]);
753 
754  /* Build block that continues if bool is TRUE. */
755  LLVMPositionBuilderAtEnd(b, b_boolcont);
756 
757  v_boolanynull = l_load(b, TypeStorageBool, v_boolanynullp, "");
758 
759  /* set value to NULL if any previous values were NULL */
760  LLVMBuildCondBr(b,
761  LLVMBuildICmp(b, LLVMIntEQ, v_boolanynull,
762  l_sbool_const(0), ""),
763  opblocks[opno + 1], b_boolisanynull);
764 
765  LLVMPositionBuilderAtEnd(b, b_boolisanynull);
766  /* set resnull to true */
767  LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
768  /* reset resvalue */
769  LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
770 
771  LLVMBuildBr(b, opblocks[opno + 1]);
772  break;
773  }
774 
775  /*
776  * Treat them the same for now, optimizer can remove
777  * redundancy. Could be worthwhile to optimize during emission
778  * though.
779  */
781  case EEOP_BOOL_OR_STEP:
783  {
784  LLVMValueRef v_boolvalue;
785  LLVMValueRef v_boolnull;
786  LLVMValueRef v_boolanynullp,
787  v_boolanynull;
788 
789  LLVMBasicBlockRef b_boolisnull;
790  LLVMBasicBlockRef b_boolchecktrue;
791  LLVMBasicBlockRef b_boolistrue;
792  LLVMBasicBlockRef b_boolcont;
793  LLVMBasicBlockRef b_boolisanynull;
794 
795  b_boolisnull = l_bb_before_v(opblocks[opno + 1],
796  "b.%d.boolisnull", opno);
797  b_boolchecktrue = l_bb_before_v(opblocks[opno + 1],
798  "b.%d.boolchecktrue", opno);
799  b_boolistrue = l_bb_before_v(opblocks[opno + 1],
800  "b.%d.boolistrue", opno);
801  b_boolisanynull = l_bb_before_v(opblocks[opno + 1],
802  "b.%d.boolisanynull", opno);
803  b_boolcont = l_bb_before_v(opblocks[opno + 1],
804  "b.%d.boolcont", opno);
805 
806  v_boolanynullp = l_ptr_const(op->d.boolexpr.anynull,
807  l_ptr(TypeStorageBool));
808 
809  if (opcode == EEOP_BOOL_OR_STEP_FIRST)
810  LLVMBuildStore(b, l_sbool_const(0), v_boolanynullp);
811  v_boolnull = l_load(b, TypeStorageBool, v_resnullp, "");
812  v_boolvalue = l_load(b, TypeSizeT, v_resvaluep, "");
813 
814  LLVMBuildCondBr(b,
815  LLVMBuildICmp(b, LLVMIntEQ, v_boolnull,
816  l_sbool_const(1), ""),
817  b_boolisnull,
818  b_boolchecktrue);
819 
820  /* build block that sets anynull */
821  LLVMPositionBuilderAtEnd(b, b_boolisnull);
822  /* set boolanynull to true */
823  LLVMBuildStore(b, l_sbool_const(1), v_boolanynullp);
824  /* and jump to next block */
825  LLVMBuildBr(b, b_boolcont);
826 
827  /* build block checking for true */
828  LLVMPositionBuilderAtEnd(b, b_boolchecktrue);
829  LLVMBuildCondBr(b,
830  LLVMBuildICmp(b, LLVMIntEQ, v_boolvalue,
831  l_sizet_const(1), ""),
832  b_boolistrue,
833  b_boolcont);
834 
835  /*
836  * Build block handling True. Value is true, so short
837  * circuit.
838  */
839  LLVMPositionBuilderAtEnd(b, b_boolistrue);
840  /* result is already set to TRUE, need not change it */
841  /* and jump to the end of the OR expression */
842  LLVMBuildBr(b, opblocks[op->d.boolexpr.jumpdone]);
843 
844  /* build block that continues if bool is FALSE */
845  LLVMPositionBuilderAtEnd(b, b_boolcont);
846 
847  v_boolanynull = l_load(b, TypeStorageBool, v_boolanynullp, "");
848 
849  /* set value to NULL if any previous values were NULL */
850  LLVMBuildCondBr(b,
851  LLVMBuildICmp(b, LLVMIntEQ, v_boolanynull,
852  l_sbool_const(0), ""),
853  opblocks[opno + 1], b_boolisanynull);
854 
855  LLVMPositionBuilderAtEnd(b, b_boolisanynull);
856  /* set resnull to true */
857  LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
858  /* reset resvalue */
859  LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
860 
861  LLVMBuildBr(b, opblocks[opno + 1]);
862  break;
863  }
864 
865  case EEOP_BOOL_NOT_STEP:
866  {
867  LLVMValueRef v_boolvalue;
868  LLVMValueRef v_negbool;
869 
870  /* compute !boolvalue */
871  v_boolvalue = l_load(b, TypeSizeT, v_resvaluep, "");
872  v_negbool = LLVMBuildZExt(b,
873  LLVMBuildICmp(b, LLVMIntEQ,
874  v_boolvalue,
875  l_sizet_const(0),
876  ""),
877  TypeSizeT, "");
878 
879  /*
880  * Store it back in resvalue. We can ignore resnull here;
881  * if it was true, it stays true, and the value we store
882  * in resvalue doesn't matter.
883  */
884  LLVMBuildStore(b, v_negbool, v_resvaluep);
885 
886  LLVMBuildBr(b, opblocks[opno + 1]);
887  break;
888  }
889 
890  case EEOP_QUAL:
891  {
892  LLVMValueRef v_resnull;
893  LLVMValueRef v_resvalue;
894  LLVMValueRef v_nullorfalse;
895  LLVMBasicBlockRef b_qualfail;
896 
897  b_qualfail = l_bb_before_v(opblocks[opno + 1],
898  "op.%d.qualfail", opno);
899 
900  v_resvalue = l_load(b, TypeSizeT, v_resvaluep, "");
901  v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
902 
903  v_nullorfalse =
904  LLVMBuildOr(b,
905  LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
906  l_sbool_const(1), ""),
907  LLVMBuildICmp(b, LLVMIntEQ, v_resvalue,
908  l_sizet_const(0), ""),
909  "");
910 
911  LLVMBuildCondBr(b,
912  v_nullorfalse,
913  b_qualfail,
914  opblocks[opno + 1]);
915 
916  /* build block handling NULL or false */
917  LLVMPositionBuilderAtEnd(b, b_qualfail);
918  /* set resnull to false */
919  LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
920  /* set resvalue to false */
921  LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
922  /* and jump out */
923  LLVMBuildBr(b, opblocks[op->d.qualexpr.jumpdone]);
924  break;
925  }
926 
927  case EEOP_JUMP:
928  {
929  LLVMBuildBr(b, opblocks[op->d.jump.jumpdone]);
930  break;
931  }
932 
933  case EEOP_JUMP_IF_NULL:
934  {
935  LLVMValueRef v_resnull;
936 
937  /* Transfer control if current result is null */
938 
939  v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
940 
941  LLVMBuildCondBr(b,
942  LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
943  l_sbool_const(1), ""),
944  opblocks[op->d.jump.jumpdone],
945  opblocks[opno + 1]);
946  break;
947  }
948 
950  {
951  LLVMValueRef v_resnull;
952 
953  /* Transfer control if current result is non-null */
954 
955  v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
956 
957  LLVMBuildCondBr(b,
958  LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
959  l_sbool_const(0), ""),
960  opblocks[op->d.jump.jumpdone],
961  opblocks[opno + 1]);
962  break;
963  }
964 
965 
967  {
968  LLVMValueRef v_resnull;
969  LLVMValueRef v_resvalue;
970  LLVMValueRef v_nullorfalse;
971 
972  /* Transfer control if current result is null or false */
973 
974  v_resvalue = l_load(b, TypeSizeT, v_resvaluep, "");
975  v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
976 
977  v_nullorfalse =
978  LLVMBuildOr(b,
979  LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
980  l_sbool_const(1), ""),
981  LLVMBuildICmp(b, LLVMIntEQ, v_resvalue,
982  l_sizet_const(0), ""),
983  "");
984 
985  LLVMBuildCondBr(b,
986  v_nullorfalse,
987  opblocks[op->d.jump.jumpdone],
988  opblocks[opno + 1]);
989  break;
990  }
991 
993  {
994  LLVMValueRef v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
995  LLVMValueRef v_resvalue;
996 
997  v_resvalue =
998  LLVMBuildSelect(b,
999  LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
1000  l_sbool_const(1), ""),
1001  l_sizet_const(1),
1002  l_sizet_const(0),
1003  "");
1004  LLVMBuildStore(b, v_resvalue, v_resvaluep);
1005  LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1006 
1007  LLVMBuildBr(b, opblocks[opno + 1]);
1008  break;
1009  }
1010 
1012  {
1013  LLVMValueRef v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
1014  LLVMValueRef v_resvalue;
1015 
1016  v_resvalue =
1017  LLVMBuildSelect(b,
1018  LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
1019  l_sbool_const(1), ""),
1020  l_sizet_const(0),
1021  l_sizet_const(1),
1022  "");
1023  LLVMBuildStore(b, v_resvalue, v_resvaluep);
1024  LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1025 
1026  LLVMBuildBr(b, opblocks[opno + 1]);
1027  break;
1028  }
1029 
1031  build_EvalXFunc(b, mod, "ExecEvalRowNull",
1032  v_state, op, v_econtext);
1033  LLVMBuildBr(b, opblocks[opno + 1]);
1034  break;
1035 
1037  build_EvalXFunc(b, mod, "ExecEvalRowNotNull",
1038  v_state, op, v_econtext);
1039  LLVMBuildBr(b, opblocks[opno + 1]);
1040  break;
1041 
1042  case EEOP_BOOLTEST_IS_TRUE:
1046  {
1047  LLVMBasicBlockRef b_isnull,
1048  b_notnull;
1049  LLVMValueRef v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
1050 
1051  b_isnull = l_bb_before_v(opblocks[opno + 1],
1052  "op.%d.isnull", opno);
1053  b_notnull = l_bb_before_v(opblocks[opno + 1],
1054  "op.%d.isnotnull", opno);
1055 
1056  /* check if value is NULL */
1057  LLVMBuildCondBr(b,
1058  LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
1059  l_sbool_const(1), ""),
1060  b_isnull, b_notnull);
1061 
1062  /* if value is NULL, return false */
1063  LLVMPositionBuilderAtEnd(b, b_isnull);
1064 
1065  /* result is not null */
1066  LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1067 
1068  if (opcode == EEOP_BOOLTEST_IS_TRUE ||
1069  opcode == EEOP_BOOLTEST_IS_FALSE)
1070  {
1071  LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
1072  }
1073  else
1074  {
1075  LLVMBuildStore(b, l_sizet_const(1), v_resvaluep);
1076  }
1077 
1078  LLVMBuildBr(b, opblocks[opno + 1]);
1079 
1080  LLVMPositionBuilderAtEnd(b, b_notnull);
1081 
1082  if (opcode == EEOP_BOOLTEST_IS_TRUE ||
1083  opcode == EEOP_BOOLTEST_IS_NOT_FALSE)
1084  {
1085  /*
1086  * if value is not null NULL, return value (already
1087  * set)
1088  */
1089  }
1090  else
1091  {
1092  LLVMValueRef v_value =
1093  l_load(b, TypeSizeT, v_resvaluep, "");
1094 
1095  v_value = LLVMBuildZExt(b,
1096  LLVMBuildICmp(b, LLVMIntEQ,
1097  v_value,
1098  l_sizet_const(0),
1099  ""),
1100  TypeSizeT, "");
1101  LLVMBuildStore(b, v_value, v_resvaluep);
1102  }
1103  LLVMBuildBr(b, opblocks[opno + 1]);
1104  break;
1105  }
1106 
1107  case EEOP_PARAM_EXEC:
1108  build_EvalXFunc(b, mod, "ExecEvalParamExec",
1109  v_state, op, v_econtext);
1110  LLVMBuildBr(b, opblocks[opno + 1]);
1111  break;
1112 
1113  case EEOP_PARAM_EXTERN:
1114  build_EvalXFunc(b, mod, "ExecEvalParamExtern",
1115  v_state, op, v_econtext);
1116  LLVMBuildBr(b, opblocks[opno + 1]);
1117  break;
1118 
1119  case EEOP_PARAM_CALLBACK:
1120  {
1121  LLVMValueRef v_func;
1122  LLVMValueRef v_params[3];
1123 
1124  v_func = l_ptr_const(op->d.cparam.paramfunc,
1125  llvm_pg_var_type("TypeExecEvalSubroutine"));
1126 
1127  v_params[0] = v_state;
1128  v_params[1] = l_ptr_const(op, l_ptr(StructExprEvalStep));
1129  v_params[2] = v_econtext;
1130  l_call(b,
1132  v_func,
1133  v_params, lengthof(v_params), "");
1134 
1135  LLVMBuildBr(b, opblocks[opno + 1]);
1136  break;
1137  }
1138 
1139  case EEOP_PARAM_SET:
1140  build_EvalXFunc(b, mod, "ExecEvalParamSet",
1141  v_state, op, v_econtext);
1142  LLVMBuildBr(b, opblocks[opno + 1]);
1143  break;
1144 
1146  {
1147  int jumpdone = op->d.sbsref_subscript.jumpdone;
1148  LLVMValueRef v_func;
1149  LLVMValueRef v_params[3];
1150  LLVMValueRef v_ret;
1151 
1152  v_func = l_ptr_const(op->d.sbsref_subscript.subscriptfunc,
1153  llvm_pg_var_type("TypeExecEvalBoolSubroutine"));
1154 
1155  v_params[0] = v_state;
1156  v_params[1] = l_ptr_const(op, l_ptr(StructExprEvalStep));
1157  v_params[2] = v_econtext;
1158  v_ret = l_call(b,
1160  v_func,
1161  v_params, lengthof(v_params), "");
1162  v_ret = LLVMBuildZExt(b, v_ret, TypeStorageBool, "");
1163 
1164  LLVMBuildCondBr(b,
1165  LLVMBuildICmp(b, LLVMIntEQ, v_ret,
1166  l_sbool_const(1), ""),
1167  opblocks[opno + 1],
1168  opblocks[jumpdone]);
1169  break;
1170  }
1171 
1172  case EEOP_SBSREF_OLD:
1173  case EEOP_SBSREF_ASSIGN:
1174  case EEOP_SBSREF_FETCH:
1175  {
1176  LLVMValueRef v_func;
1177  LLVMValueRef v_params[3];
1178 
1179  v_func = l_ptr_const(op->d.sbsref.subscriptfunc,
1180  llvm_pg_var_type("TypeExecEvalSubroutine"));
1181 
1182  v_params[0] = v_state;
1183  v_params[1] = l_ptr_const(op, l_ptr(StructExprEvalStep));
1184  v_params[2] = v_econtext;
1185  l_call(b,
1187  v_func,
1188  v_params, lengthof(v_params), "");
1189 
1190  LLVMBuildBr(b, opblocks[opno + 1]);
1191  break;
1192  }
1193 
1194  case EEOP_CASE_TESTVAL:
1195  {
1196  LLVMBasicBlockRef b_avail,
1197  b_notavail;
1198  LLVMValueRef v_casevaluep,
1199  v_casevalue;
1200  LLVMValueRef v_casenullp,
1201  v_casenull;
1202  LLVMValueRef v_casevaluenull;
1203 
1204  b_avail = l_bb_before_v(opblocks[opno + 1],
1205  "op.%d.avail", opno);
1206  b_notavail = l_bb_before_v(opblocks[opno + 1],
1207  "op.%d.notavail", opno);
1208 
1209  v_casevaluep = l_ptr_const(op->d.casetest.value,
1210  l_ptr(TypeSizeT));
1211  v_casenullp = l_ptr_const(op->d.casetest.isnull,
1212  l_ptr(TypeStorageBool));
1213 
1214  v_casevaluenull =
1215  LLVMBuildICmp(b, LLVMIntEQ,
1216  LLVMBuildPtrToInt(b, v_casevaluep,
1217  TypeSizeT, ""),
1218  l_sizet_const(0), "");
1219  LLVMBuildCondBr(b, v_casevaluenull, b_notavail, b_avail);
1220 
1221  /* if casetest != NULL */
1222  LLVMPositionBuilderAtEnd(b, b_avail);
1223  v_casevalue = l_load(b, TypeSizeT, v_casevaluep, "");
1224  v_casenull = l_load(b, TypeStorageBool, v_casenullp, "");
1225  LLVMBuildStore(b, v_casevalue, v_resvaluep);
1226  LLVMBuildStore(b, v_casenull, v_resnullp);
1227  LLVMBuildBr(b, opblocks[opno + 1]);
1228 
1229  /* if casetest == NULL */
1230  LLVMPositionBuilderAtEnd(b, b_notavail);
1231  v_casevalue =
1232  l_load_struct_gep(b,
1234  v_econtext,
1236  v_casenull =
1237  l_load_struct_gep(b,
1239  v_econtext,
1241  LLVMBuildStore(b, v_casevalue, v_resvaluep);
1242  LLVMBuildStore(b, v_casenull, v_resnullp);
1243 
1244  LLVMBuildBr(b, opblocks[opno + 1]);
1245  break;
1246  }
1247 
1248  case EEOP_MAKE_READONLY:
1249  {
1250  LLVMBasicBlockRef b_notnull;
1251  LLVMValueRef v_params[1];
1252  LLVMValueRef v_ret;
1253  LLVMValueRef v_nullp;
1254  LLVMValueRef v_valuep;
1255  LLVMValueRef v_null;
1256  LLVMValueRef v_value;
1257 
1258  b_notnull = l_bb_before_v(opblocks[opno + 1],
1259  "op.%d.readonly.notnull", opno);
1260 
1261  v_nullp = l_ptr_const(op->d.make_readonly.isnull,
1262  l_ptr(TypeStorageBool));
1263 
1264  v_null = l_load(b, TypeStorageBool, v_nullp, "");
1265 
1266  /* store null isnull value in result */
1267  LLVMBuildStore(b, v_null, v_resnullp);
1268 
1269  /* check if value is NULL */
1270  LLVMBuildCondBr(b,
1271  LLVMBuildICmp(b, LLVMIntEQ, v_null,
1272  l_sbool_const(1), ""),
1273  opblocks[opno + 1], b_notnull);
1274 
1275  /* if value is not null, convert to RO datum */
1276  LLVMPositionBuilderAtEnd(b, b_notnull);
1277 
1278  v_valuep = l_ptr_const(op->d.make_readonly.value,
1279  l_ptr(TypeSizeT));
1280 
1281  v_value = l_load(b, TypeSizeT, v_valuep, "");
1282 
1283  v_params[0] = v_value;
1284  v_ret =
1285  l_call(b,
1286  llvm_pg_var_func_type("MakeExpandedObjectReadOnlyInternal"),
1287  llvm_pg_func(mod, "MakeExpandedObjectReadOnlyInternal"),
1288  v_params, lengthof(v_params), "");
1289  LLVMBuildStore(b, v_ret, v_resvaluep);
1290 
1291  LLVMBuildBr(b, opblocks[opno + 1]);
1292  break;
1293  }
1294 
1295  case EEOP_IOCOERCE:
1296  {
1297  FunctionCallInfo fcinfo_out,
1298  fcinfo_in;
1299  LLVMValueRef v_fn_out,
1300  v_fn_in;
1301  LLVMValueRef v_fcinfo_out,
1302  v_fcinfo_in;
1303  LLVMValueRef v_fcinfo_in_isnullp;
1304  LLVMValueRef v_retval;
1305  LLVMValueRef v_resvalue;
1306  LLVMValueRef v_resnull;
1307 
1308  LLVMValueRef v_output_skip;
1309  LLVMValueRef v_output;
1310 
1311  LLVMBasicBlockRef b_skipoutput;
1312  LLVMBasicBlockRef b_calloutput;
1313  LLVMBasicBlockRef b_input;
1314  LLVMBasicBlockRef b_inputcall;
1315 
1316  fcinfo_out = op->d.iocoerce.fcinfo_data_out;
1317  fcinfo_in = op->d.iocoerce.fcinfo_data_in;
1318 
1319  b_skipoutput = l_bb_before_v(opblocks[opno + 1],
1320  "op.%d.skipoutputnull", opno);
1321  b_calloutput = l_bb_before_v(opblocks[opno + 1],
1322  "op.%d.calloutput", opno);
1323  b_input = l_bb_before_v(opblocks[opno + 1],
1324  "op.%d.input", opno);
1325  b_inputcall = l_bb_before_v(opblocks[opno + 1],
1326  "op.%d.inputcall", opno);
1327 
1328  v_fn_out = llvm_function_reference(context, b, mod, fcinfo_out);
1329  v_fn_in = llvm_function_reference(context, b, mod, fcinfo_in);
1330  v_fcinfo_out = l_ptr_const(fcinfo_out, l_ptr(StructFunctionCallInfoData));
1331  v_fcinfo_in = l_ptr_const(fcinfo_in, l_ptr(StructFunctionCallInfoData));
1332 
1333  v_fcinfo_in_isnullp =
1334  l_struct_gep(b,
1336  v_fcinfo_in,
1338  "v_fcinfo_in_isnull");
1339 
1340  /* output functions are not called on nulls */
1341  v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
1342  LLVMBuildCondBr(b,
1343  LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
1344  l_sbool_const(1), ""),
1345  b_skipoutput,
1346  b_calloutput);
1347 
1348  LLVMPositionBuilderAtEnd(b, b_skipoutput);
1349  v_output_skip = l_sizet_const(0);
1350  LLVMBuildBr(b, b_input);
1351 
1352  LLVMPositionBuilderAtEnd(b, b_calloutput);
1353  v_resvalue = l_load(b, TypeSizeT, v_resvaluep, "");
1354 
1355  /* set arg[0] */
1356  LLVMBuildStore(b,
1357  v_resvalue,
1358  l_funcvaluep(b, v_fcinfo_out, 0));
1359  LLVMBuildStore(b,
1360  l_sbool_const(0),
1361  l_funcnullp(b, v_fcinfo_out, 0));
1362  /* and call output function (can never return NULL) */
1363  v_output = l_call(b,
1364  LLVMGetFunctionType(v_fn_out),
1365  v_fn_out, &v_fcinfo_out,
1366  1, "funccall_coerce_out");
1367  LLVMBuildBr(b, b_input);
1368 
1369  /* build block handling input function call */
1370  LLVMPositionBuilderAtEnd(b, b_input);
1371 
1372  /* phi between resnull and output function call branches */
1373  {
1374  LLVMValueRef incoming_values[2];
1375  LLVMBasicBlockRef incoming_blocks[2];
1376 
1377  incoming_values[0] = v_output_skip;
1378  incoming_blocks[0] = b_skipoutput;
1379 
1380  incoming_values[1] = v_output;
1381  incoming_blocks[1] = b_calloutput;
1382 
1383  v_output = LLVMBuildPhi(b, TypeSizeT, "output");
1384  LLVMAddIncoming(v_output,
1385  incoming_values, incoming_blocks,
1386  lengthof(incoming_blocks));
1387  }
1388 
1389  /*
1390  * If input function is strict, skip if input string is
1391  * NULL.
1392  */
1393  if (op->d.iocoerce.finfo_in->fn_strict)
1394  {
1395  LLVMBuildCondBr(b,
1396  LLVMBuildICmp(b, LLVMIntEQ, v_output,
1397  l_sizet_const(0), ""),
1398  opblocks[opno + 1],
1399  b_inputcall);
1400  }
1401  else
1402  {
1403  LLVMBuildBr(b, b_inputcall);
1404  }
1405 
1406  LLVMPositionBuilderAtEnd(b, b_inputcall);
1407  /* set arguments */
1408  /* arg0: output */
1409  LLVMBuildStore(b, v_output,
1410  l_funcvaluep(b, v_fcinfo_in, 0));
1411  LLVMBuildStore(b, v_resnull,
1412  l_funcnullp(b, v_fcinfo_in, 0));
1413 
1414  /* arg1: ioparam: preset in execExpr.c */
1415  /* arg2: typmod: preset in execExpr.c */
1416 
1417  /* reset fcinfo_in->isnull */
1418  LLVMBuildStore(b, l_sbool_const(0), v_fcinfo_in_isnullp);
1419  /* and call function */
1420  v_retval = l_call(b,
1421  LLVMGetFunctionType(v_fn_in),
1422  v_fn_in, &v_fcinfo_in, 1,
1423  "funccall_iocoerce_in");
1424 
1425  LLVMBuildStore(b, v_retval, v_resvaluep);
1426 
1427  LLVMBuildBr(b, opblocks[opno + 1]);
1428  break;
1429  }
1430 
1431  case EEOP_IOCOERCE_SAFE:
1432  build_EvalXFunc(b, mod, "ExecEvalCoerceViaIOSafe",
1433  v_state, op);
1434  LLVMBuildBr(b, opblocks[opno + 1]);
1435  break;
1436 
1437  case EEOP_DISTINCT:
1438  case EEOP_NOT_DISTINCT:
1439  {
1440  FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
1441 
1442  LLVMValueRef v_fcinfo;
1443  LLVMValueRef v_fcinfo_isnull;
1444 
1445  LLVMValueRef v_argnull0,
1446  v_argisnull0;
1447  LLVMValueRef v_argnull1,
1448  v_argisnull1;
1449 
1450  LLVMValueRef v_anyargisnull;
1451  LLVMValueRef v_bothargisnull;
1452 
1453  LLVMValueRef v_result;
1454 
1455  LLVMBasicBlockRef b_noargnull;
1456  LLVMBasicBlockRef b_checkbothargnull;
1457  LLVMBasicBlockRef b_bothargnull;
1458  LLVMBasicBlockRef b_anyargnull;
1459 
1460  b_noargnull = l_bb_before_v(opblocks[opno + 1], "op.%d.noargnull", opno);
1461  b_checkbothargnull = l_bb_before_v(opblocks[opno + 1], "op.%d.checkbothargnull", opno);
1462  b_bothargnull = l_bb_before_v(opblocks[opno + 1], "op.%d.bothargnull", opno);
1463  b_anyargnull = l_bb_before_v(opblocks[opno + 1], "op.%d.anyargnull", opno);
1464 
1465  v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
1466 
1467  /* load args[0|1].isnull for both arguments */
1468  v_argnull0 = l_funcnull(b, v_fcinfo, 0);
1469  v_argisnull0 = LLVMBuildICmp(b, LLVMIntEQ, v_argnull0,
1470  l_sbool_const(1), "");
1471  v_argnull1 = l_funcnull(b, v_fcinfo, 1);
1472  v_argisnull1 = LLVMBuildICmp(b, LLVMIntEQ, v_argnull1,
1473  l_sbool_const(1), "");
1474 
1475  v_anyargisnull = LLVMBuildOr(b, v_argisnull0, v_argisnull1, "");
1476  v_bothargisnull = LLVMBuildAnd(b, v_argisnull0, v_argisnull1, "");
1477 
1478  /*
1479  * Check function arguments for NULLness: If either is
1480  * NULL, we check if both args are NULL. Otherwise call
1481  * comparator.
1482  */
1483  LLVMBuildCondBr(b, v_anyargisnull, b_checkbothargnull,
1484  b_noargnull);
1485 
1486  /*
1487  * build block checking if any arg is null
1488  */
1489  LLVMPositionBuilderAtEnd(b, b_checkbothargnull);
1490  LLVMBuildCondBr(b, v_bothargisnull, b_bothargnull,
1491  b_anyargnull);
1492 
1493 
1494  /* Both NULL? Then is not distinct... */
1495  LLVMPositionBuilderAtEnd(b, b_bothargnull);
1496  LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1497  if (opcode == EEOP_NOT_DISTINCT)
1498  LLVMBuildStore(b, l_sizet_const(1), v_resvaluep);
1499  else
1500  LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
1501 
1502  LLVMBuildBr(b, opblocks[opno + 1]);
1503 
1504  /* Only one is NULL? Then is distinct... */
1505  LLVMPositionBuilderAtEnd(b, b_anyargnull);
1506  LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1507  if (opcode == EEOP_NOT_DISTINCT)
1508  LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
1509  else
1510  LLVMBuildStore(b, l_sizet_const(1), v_resvaluep);
1511  LLVMBuildBr(b, opblocks[opno + 1]);
1512 
1513  /* neither argument is null: compare */
1514  LLVMPositionBuilderAtEnd(b, b_noargnull);
1515 
1516  v_result = BuildV1Call(context, b, mod, fcinfo,
1517  &v_fcinfo_isnull);
1518 
1519  if (opcode == EEOP_DISTINCT)
1520  {
1521  /* Must invert result of "=" */
1522  v_result =
1523  LLVMBuildZExt(b,
1524  LLVMBuildICmp(b, LLVMIntEQ,
1525  v_result,
1526  l_sizet_const(0), ""),
1527  TypeSizeT, "");
1528  }
1529 
1530  LLVMBuildStore(b, v_fcinfo_isnull, v_resnullp);
1531  LLVMBuildStore(b, v_result, v_resvaluep);
1532 
1533  LLVMBuildBr(b, opblocks[opno + 1]);
1534  break;
1535  }
1536 
1537  case EEOP_NULLIF:
1538  {
1539  FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
1540 
1541  LLVMValueRef v_fcinfo;
1542  LLVMValueRef v_fcinfo_isnull;
1543  LLVMValueRef v_argnull0;
1544  LLVMValueRef v_argnull1;
1545  LLVMValueRef v_anyargisnull;
1546  LLVMValueRef v_arg0;
1547  LLVMBasicBlockRef b_hasnull;
1548  LLVMBasicBlockRef b_nonull;
1549  LLVMBasicBlockRef b_argsequal;
1550  LLVMValueRef v_retval;
1551  LLVMValueRef v_argsequal;
1552 
1553  b_hasnull = l_bb_before_v(opblocks[opno + 1],
1554  "b.%d.null-args", opno);
1555  b_nonull = l_bb_before_v(opblocks[opno + 1],
1556  "b.%d.no-null-args", opno);
1557  b_argsequal = l_bb_before_v(opblocks[opno + 1],
1558  "b.%d.argsequal", opno);
1559 
1560  v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
1561 
1562  /* save original arg[0] */
1563  v_arg0 = l_funcvalue(b, v_fcinfo, 0);
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  LLVMBuildStore(b, v_argnull0, v_resnullp);
1582  LLVMBuildStore(b, v_arg0, v_resvaluep);
1583  LLVMBuildBr(b, opblocks[opno + 1]);
1584 
1585  /* build block to invoke function and check result */
1586  LLVMPositionBuilderAtEnd(b, b_nonull);
1587 
1588  /*
1589  * If first argument is of varlena type, it might be an
1590  * expanded datum. We need to ensure that the value
1591  * passed to the comparison function is a read-only
1592  * pointer. However, if we end by returning the first
1593  * argument, that will be the original read-write pointer
1594  * if it was read-write.
1595  */
1596  if (op->d.func.make_ro)
1597  {
1598  LLVMValueRef v_params[1];
1599  LLVMValueRef v_arg0_ro;
1600 
1601  v_params[0] = v_arg0;
1602  v_arg0_ro =
1603  l_call(b,
1604  llvm_pg_var_func_type("MakeExpandedObjectReadOnlyInternal"),
1605  llvm_pg_func(mod, "MakeExpandedObjectReadOnlyInternal"),
1606  v_params, lengthof(v_params), "");
1607  LLVMBuildStore(b, v_arg0_ro,
1608  l_funcvaluep(b, v_fcinfo, 0));
1609  }
1610 
1611  v_retval = BuildV1Call(context, b, mod, fcinfo, &v_fcinfo_isnull);
1612 
1613  /*
1614  * If result not null and arguments are equal return null,
1615  * else return arg[0] (same result as if there'd been
1616  * NULLs, hence reuse b_hasnull).
1617  */
1618  v_argsequal = LLVMBuildAnd(b,
1619  LLVMBuildICmp(b, LLVMIntEQ,
1620  v_fcinfo_isnull,
1621  l_sbool_const(0),
1622  ""),
1623  LLVMBuildICmp(b, LLVMIntEQ,
1624  v_retval,
1625  l_sizet_const(1),
1626  ""),
1627  "");
1628  LLVMBuildCondBr(b, v_argsequal, b_argsequal, b_hasnull);
1629 
1630  /* build block setting result to NULL, if args are equal */
1631  LLVMPositionBuilderAtEnd(b, b_argsequal);
1632  LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
1633  LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
1634 
1635  LLVMBuildBr(b, opblocks[opno + 1]);
1636  break;
1637  }
1638 
1639  case EEOP_SQLVALUEFUNCTION:
1640  build_EvalXFunc(b, mod, "ExecEvalSQLValueFunction",
1641  v_state, op);
1642  LLVMBuildBr(b, opblocks[opno + 1]);
1643  break;
1644 
1645  case EEOP_CURRENTOFEXPR:
1646  build_EvalXFunc(b, mod, "ExecEvalCurrentOfExpr",
1647  v_state, op);
1648  LLVMBuildBr(b, opblocks[opno + 1]);
1649  break;
1650 
1651  case EEOP_NEXTVALUEEXPR:
1652  build_EvalXFunc(b, mod, "ExecEvalNextValueExpr",
1653  v_state, op);
1654  LLVMBuildBr(b, opblocks[opno + 1]);
1655  break;
1656 
1657  case EEOP_ARRAYEXPR:
1658  build_EvalXFunc(b, mod, "ExecEvalArrayExpr",
1659  v_state, op);
1660  LLVMBuildBr(b, opblocks[opno + 1]);
1661  break;
1662 
1663  case EEOP_ARRAYCOERCE:
1664  build_EvalXFunc(b, mod, "ExecEvalArrayCoerce",
1665  v_state, op, v_econtext);
1666  LLVMBuildBr(b, opblocks[opno + 1]);
1667  break;
1668 
1669  case EEOP_ROW:
1670  build_EvalXFunc(b, mod, "ExecEvalRow",
1671  v_state, op);
1672  LLVMBuildBr(b, opblocks[opno + 1]);
1673  break;
1674 
1675  case EEOP_ROWCOMPARE_STEP:
1676  {
1677  FunctionCallInfo fcinfo = op->d.rowcompare_step.fcinfo_data;
1678  LLVMValueRef v_fcinfo_isnull;
1679  LLVMBasicBlockRef b_null;
1680  LLVMBasicBlockRef b_compare;
1681  LLVMBasicBlockRef b_compare_result;
1682 
1683  LLVMValueRef v_retval;
1684 
1685  b_null = l_bb_before_v(opblocks[opno + 1],
1686  "op.%d.row-null", opno);
1687  b_compare = l_bb_before_v(opblocks[opno + 1],
1688  "op.%d.row-compare", opno);
1689  b_compare_result =
1690  l_bb_before_v(opblocks[opno + 1],
1691  "op.%d.row-compare-result",
1692  opno);
1693 
1694  /*
1695  * If function is strict, and either arg is null, we're
1696  * done.
1697  */
1698  if (op->d.rowcompare_step.finfo->fn_strict)
1699  {
1700  LLVMValueRef v_fcinfo;
1701  LLVMValueRef v_argnull0;
1702  LLVMValueRef v_argnull1;
1703  LLVMValueRef v_anyargisnull;
1704 
1705  v_fcinfo = l_ptr_const(fcinfo,
1707 
1708  v_argnull0 = l_funcnull(b, v_fcinfo, 0);
1709  v_argnull1 = l_funcnull(b, v_fcinfo, 1);
1710 
1711  v_anyargisnull =
1712  LLVMBuildOr(b,
1713  LLVMBuildICmp(b,
1714  LLVMIntEQ,
1715  v_argnull0,
1716  l_sbool_const(1),
1717  ""),
1718  LLVMBuildICmp(b, LLVMIntEQ,
1719  v_argnull1,
1720  l_sbool_const(1), ""),
1721  "");
1722 
1723  LLVMBuildCondBr(b, v_anyargisnull, b_null, b_compare);
1724  }
1725  else
1726  {
1727  LLVMBuildBr(b, b_compare);
1728  }
1729 
1730  /* build block invoking comparison function */
1731  LLVMPositionBuilderAtEnd(b, b_compare);
1732 
1733  /* call function */
1734  v_retval = BuildV1Call(context, b, mod, fcinfo,
1735  &v_fcinfo_isnull);
1736  LLVMBuildStore(b, v_retval, v_resvaluep);
1737 
1738  /* if result of function is NULL, force NULL result */
1739  LLVMBuildCondBr(b,
1740  LLVMBuildICmp(b,
1741  LLVMIntEQ,
1742  v_fcinfo_isnull,
1743  l_sbool_const(0),
1744  ""),
1745  b_compare_result,
1746  b_null);
1747 
1748  /* build block analyzing the !NULL comparator result */
1749  LLVMPositionBuilderAtEnd(b, b_compare_result);
1750 
1751  /* if results equal, compare next, otherwise done */
1752  LLVMBuildCondBr(b,
1753  LLVMBuildICmp(b,
1754  LLVMIntEQ,
1755  v_retval,
1756  l_sizet_const(0), ""),
1757  opblocks[opno + 1],
1758  opblocks[op->d.rowcompare_step.jumpdone]);
1759 
1760  /*
1761  * Build block handling NULL input or NULL comparator
1762  * result.
1763  */
1764  LLVMPositionBuilderAtEnd(b, b_null);
1765  LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
1766  LLVMBuildBr(b, opblocks[op->d.rowcompare_step.jumpnull]);
1767 
1768  break;
1769  }
1770 
1771  case EEOP_ROWCOMPARE_FINAL:
1772  {
1773  RowCompareType rctype = op->d.rowcompare_final.rctype;
1774 
1775  LLVMValueRef v_cmpresult;
1776  LLVMValueRef v_result;
1777  LLVMIntPredicate predicate;
1778 
1779  /*
1780  * Btree comparators return 32 bit results, need to be
1781  * careful about sign (used as a 64 bit value it's
1782  * otherwise wrong).
1783  */
1784  v_cmpresult =
1785  LLVMBuildTrunc(b,
1786  l_load(b, TypeSizeT, v_resvaluep, ""),
1787  LLVMInt32TypeInContext(lc), "");
1788 
1789  switch (rctype)
1790  {
1791  case ROWCOMPARE_LT:
1792  predicate = LLVMIntSLT;
1793  break;
1794  case ROWCOMPARE_LE:
1795  predicate = LLVMIntSLE;
1796  break;
1797  case ROWCOMPARE_GT:
1798  predicate = LLVMIntSGT;
1799  break;
1800  case ROWCOMPARE_GE:
1801  predicate = LLVMIntSGE;
1802  break;
1803  default:
1804  /* EQ and NE cases aren't allowed here */
1805  Assert(false);
1806  predicate = 0; /* prevent compiler warning */
1807  break;
1808  }
1809 
1810  v_result = LLVMBuildICmp(b,
1811  predicate,
1812  v_cmpresult,
1813  l_int32_const(lc, 0),
1814  "");
1815  v_result = LLVMBuildZExt(b, v_result, TypeSizeT, "");
1816 
1817  LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1818  LLVMBuildStore(b, v_result, v_resvaluep);
1819 
1820  LLVMBuildBr(b, opblocks[opno + 1]);
1821  break;
1822  }
1823 
1824  case EEOP_MINMAX:
1825  build_EvalXFunc(b, mod, "ExecEvalMinMax",
1826  v_state, op);
1827  LLVMBuildBr(b, opblocks[opno + 1]);
1828  break;
1829 
1830  case EEOP_FIELDSELECT:
1831  build_EvalXFunc(b, mod, "ExecEvalFieldSelect",
1832  v_state, op, v_econtext);
1833  LLVMBuildBr(b, opblocks[opno + 1]);
1834  break;
1835 
1837  build_EvalXFunc(b, mod, "ExecEvalFieldStoreDeForm",
1838  v_state, op, v_econtext);
1839  LLVMBuildBr(b, opblocks[opno + 1]);
1840  break;
1841 
1842  case EEOP_FIELDSTORE_FORM:
1843  build_EvalXFunc(b, mod, "ExecEvalFieldStoreForm",
1844  v_state, op, v_econtext);
1845  LLVMBuildBr(b, opblocks[opno + 1]);
1846  break;
1847 
1848  case EEOP_DOMAIN_TESTVAL:
1849  {
1850  LLVMBasicBlockRef b_avail,
1851  b_notavail;
1852  LLVMValueRef v_casevaluep,
1853  v_casevalue;
1854  LLVMValueRef v_casenullp,
1855  v_casenull;
1856  LLVMValueRef v_casevaluenull;
1857 
1858  b_avail = l_bb_before_v(opblocks[opno + 1],
1859  "op.%d.avail", opno);
1860  b_notavail = l_bb_before_v(opblocks[opno + 1],
1861  "op.%d.notavail", opno);
1862 
1863  v_casevaluep = l_ptr_const(op->d.casetest.value,
1864  l_ptr(TypeSizeT));
1865  v_casenullp = l_ptr_const(op->d.casetest.isnull,
1866  l_ptr(TypeStorageBool));
1867 
1868  v_casevaluenull =
1869  LLVMBuildICmp(b, LLVMIntEQ,
1870  LLVMBuildPtrToInt(b, v_casevaluep,
1871  TypeSizeT, ""),
1872  l_sizet_const(0), "");
1873  LLVMBuildCondBr(b,
1874  v_casevaluenull,
1875  b_notavail, b_avail);
1876 
1877  /* if casetest != NULL */
1878  LLVMPositionBuilderAtEnd(b, b_avail);
1879  v_casevalue = l_load(b, TypeSizeT, v_casevaluep, "");
1880  v_casenull = l_load(b, TypeStorageBool, v_casenullp, "");
1881  LLVMBuildStore(b, v_casevalue, v_resvaluep);
1882  LLVMBuildStore(b, v_casenull, v_resnullp);
1883  LLVMBuildBr(b, opblocks[opno + 1]);
1884 
1885  /* if casetest == NULL */
1886  LLVMPositionBuilderAtEnd(b, b_notavail);
1887  v_casevalue =
1888  l_load_struct_gep(b,
1890  v_econtext,
1892  "");
1893  v_casenull =
1894  l_load_struct_gep(b,
1896  v_econtext,
1898  "");
1899  LLVMBuildStore(b, v_casevalue, v_resvaluep);
1900  LLVMBuildStore(b, v_casenull, v_resnullp);
1901 
1902  LLVMBuildBr(b, opblocks[opno + 1]);
1903  break;
1904  }
1905 
1906  case EEOP_DOMAIN_NOTNULL:
1907  build_EvalXFunc(b, mod, "ExecEvalConstraintNotNull",
1908  v_state, op);
1909  LLVMBuildBr(b, opblocks[opno + 1]);
1910  break;
1911 
1912  case EEOP_DOMAIN_CHECK:
1913  build_EvalXFunc(b, mod, "ExecEvalConstraintCheck",
1914  v_state, op);
1915  LLVMBuildBr(b, opblocks[opno + 1]);
1916  break;
1917 
1919  {
1920  LLVMValueRef v_initvalue;
1921 
1922  v_initvalue = l_sizet_const(op->d.hashdatum_initvalue.init_value);
1923 
1924  LLVMBuildStore(b, v_initvalue, v_resvaluep);
1925  LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1926  LLVMBuildBr(b, opblocks[opno + 1]);
1927  break;
1928  }
1929 
1930  case EEOP_HASHDATUM_FIRST:
1932  case EEOP_HASHDATUM_NEXT32:
1934  {
1935  FunctionCallInfo fcinfo = op->d.hashdatum.fcinfo_data;
1936  LLVMValueRef v_fcinfo;
1937  LLVMValueRef v_fcinfo_isnull;
1938  LLVMValueRef v_retval;
1939  LLVMBasicBlockRef b_checkargnull;
1940  LLVMBasicBlockRef b_ifnotnull;
1941  LLVMBasicBlockRef b_ifnullblock;
1942  LLVMValueRef v_argisnull;
1943  LLVMValueRef v_prevhash = NULL;
1944 
1945  /*
1946  * When performing the next hash and not in strict mode we
1947  * perform a rotation of the previously stored hash value
1948  * before doing the NULL check. We want to do this even
1949  * when we receive a NULL Datum to hash. In strict mode,
1950  * we do this after the NULL check so as not to waste the
1951  * effort of rotating the bits when we're going to throw
1952  * away the hash value and return NULL.
1953  */
1954  if (opcode == EEOP_HASHDATUM_NEXT32)
1955  {
1956  LLVMValueRef v_tmp1;
1957  LLVMValueRef v_tmp2;
1958  LLVMValueRef tmp;
1959 
1960  tmp = l_ptr_const(&op->d.hashdatum.iresult->value,
1961  l_ptr(TypeSizeT));
1962 
1963  /*
1964  * Fetch the previously hashed value from where the
1965  * previous hash operation stored it.
1966  */
1967  v_prevhash = l_load(b, TypeSizeT, tmp, "prevhash");
1968 
1969  /*
1970  * Rotate bits left by 1 bit. Be careful not to
1971  * overflow uint32 when working with size_t.
1972  */
1973  v_tmp1 = LLVMBuildShl(b, v_prevhash, l_sizet_const(1),
1974  "");
1975  v_tmp1 = LLVMBuildAnd(b, v_tmp1,
1976  l_sizet_const(0xffffffff), "");
1977  v_tmp2 = LLVMBuildLShr(b, v_prevhash,
1978  l_sizet_const(31), "");
1979  v_prevhash = LLVMBuildOr(b, v_tmp1, v_tmp2,
1980  "rotatedhash");
1981  }
1982 
1983  /*
1984  * Block for the actual function call, if args are
1985  * non-NULL.
1986  */
1987  b_ifnotnull = l_bb_before_v(opblocks[opno + 1],
1988  "b.%d.ifnotnull",
1989  opno);
1990 
1991  /* we expect the hash function to have 1 argument */
1992  if (fcinfo->nargs != 1)
1993  elog(ERROR, "incorrect number of function arguments");
1994 
1995  v_fcinfo = l_ptr_const(fcinfo,
1997 
1998  b_checkargnull = l_bb_before_v(b_ifnotnull,
1999  "b.%d.isnull.0", opno);
2000 
2001  LLVMBuildBr(b, b_checkargnull);
2002 
2003  /*
2004  * Determine what to do if we find the argument to be
2005  * NULL.
2006  */
2007  if (opcode == EEOP_HASHDATUM_FIRST_STRICT ||
2008  opcode == EEOP_HASHDATUM_NEXT32_STRICT)
2009  {
2010  b_ifnullblock = l_bb_before_v(b_ifnotnull,
2011  "b.%d.strictnull",
2012  opno);
2013 
2014  LLVMPositionBuilderAtEnd(b, b_ifnullblock);
2015 
2016  /*
2017  * In strict node, NULL inputs result in NULL. Save
2018  * the NULL result and goto jumpdone.
2019  */
2020  LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
2021  LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
2022  LLVMBuildBr(b, opblocks[op->d.hashdatum.jumpdone]);
2023  }
2024  else
2025  {
2026  b_ifnullblock = l_bb_before_v(b_ifnotnull,
2027  "b.%d.null",
2028  opno);
2029 
2030  LLVMPositionBuilderAtEnd(b, b_ifnullblock);
2031 
2032 
2033  LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
2034 
2035  if (opcode == EEOP_HASHDATUM_NEXT32)
2036  {
2037  Assert(v_prevhash != NULL);
2038 
2039  /*
2040  * Save the rotated hash value and skip to the
2041  * next op.
2042  */
2043  LLVMBuildStore(b, v_prevhash, v_resvaluep);
2044  }
2045  else
2046  {
2047  Assert(opcode == EEOP_HASHDATUM_FIRST);
2048 
2049  /*
2050  * Store a zero Datum when the Datum to hash is
2051  * NULL
2052  */
2053  LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
2054  }
2055 
2056  LLVMBuildBr(b, opblocks[opno + 1]);
2057  }
2058 
2059  LLVMPositionBuilderAtEnd(b, b_checkargnull);
2060 
2061  /* emit code to check if the input parameter is NULL */
2062  v_argisnull = l_funcnull(b, v_fcinfo, 0);
2063  LLVMBuildCondBr(b,
2064  LLVMBuildICmp(b,
2065  LLVMIntEQ,
2066  v_argisnull,
2067  l_sbool_const(1),
2068  ""),
2069  b_ifnullblock,
2070  b_ifnotnull);
2071 
2072  LLVMPositionBuilderAtEnd(b, b_ifnotnull);
2073 
2074  /*
2075  * Rotate the previously stored hash value when performing
2076  * NEXT32 in strict mode. In non-strict mode we already
2077  * did this before checking for NULLs.
2078  */
2079  if (opcode == EEOP_HASHDATUM_NEXT32_STRICT)
2080  {
2081  LLVMValueRef v_tmp1;
2082  LLVMValueRef v_tmp2;
2083  LLVMValueRef tmp;
2084 
2085  tmp = l_ptr_const(&op->d.hashdatum.iresult->value,
2086  l_ptr(TypeSizeT));
2087 
2088  /*
2089  * Fetch the previously hashed value from where the
2090  * previous hash operation stored it.
2091  */
2092  v_prevhash = l_load(b, TypeSizeT, tmp, "prevhash");
2093 
2094  /*
2095  * Rotate bits left by 1 bit. Be careful not to
2096  * overflow uint32 when working with size_t.
2097  */
2098  v_tmp1 = LLVMBuildShl(b, v_prevhash, l_sizet_const(1),
2099  "");
2100  v_tmp1 = LLVMBuildAnd(b, v_tmp1,
2101  l_sizet_const(0xffffffff), "");
2102  v_tmp2 = LLVMBuildLShr(b, v_prevhash,
2103  l_sizet_const(31), "");
2104  v_prevhash = LLVMBuildOr(b, v_tmp1, v_tmp2,
2105  "rotatedhash");
2106  }
2107 
2108  /* call the hash function */
2109  v_retval = BuildV1Call(context, b, mod, fcinfo,
2110  &v_fcinfo_isnull);
2111 
2112  /*
2113  * For NEXT32 ops, XOR (^) the returned hash value with
2114  * the existing hash value.
2115  */
2116  if (opcode == EEOP_HASHDATUM_NEXT32 ||
2117  opcode == EEOP_HASHDATUM_NEXT32_STRICT)
2118  v_retval = LLVMBuildXor(b, v_prevhash, v_retval,
2119  "xorhash");
2120 
2121  LLVMBuildStore(b, v_retval, v_resvaluep);
2122  LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
2123 
2124  LLVMBuildBr(b, opblocks[opno + 1]);
2125  break;
2126  }
2127 
2128  case EEOP_CONVERT_ROWTYPE:
2129  build_EvalXFunc(b, mod, "ExecEvalConvertRowtype",
2130  v_state, op, v_econtext);
2131  LLVMBuildBr(b, opblocks[opno + 1]);
2132  break;
2133 
2134  case EEOP_SCALARARRAYOP:
2135  build_EvalXFunc(b, mod, "ExecEvalScalarArrayOp",
2136  v_state, op);
2137  LLVMBuildBr(b, opblocks[opno + 1]);
2138  break;
2139 
2141  build_EvalXFunc(b, mod, "ExecEvalHashedScalarArrayOp",
2142  v_state, op, v_econtext);
2143  LLVMBuildBr(b, opblocks[opno + 1]);
2144  break;
2145 
2146  case EEOP_XMLEXPR:
2147  build_EvalXFunc(b, mod, "ExecEvalXmlExpr",
2148  v_state, op);
2149  LLVMBuildBr(b, opblocks[opno + 1]);
2150  break;
2151 
2152  case EEOP_JSON_CONSTRUCTOR:
2153  build_EvalXFunc(b, mod, "ExecEvalJsonConstructor",
2154  v_state, op, v_econtext);
2155  LLVMBuildBr(b, opblocks[opno + 1]);
2156  break;
2157 
2158  case EEOP_IS_JSON:
2159  build_EvalXFunc(b, mod, "ExecEvalJsonIsPredicate",
2160  v_state, op);
2161  LLVMBuildBr(b, opblocks[opno + 1]);
2162  break;
2163 
2164  case EEOP_JSONEXPR_PATH:
2165  {
2166  JsonExprState *jsestate = op->d.jsonexpr.jsestate;
2167  LLVMValueRef v_ret;
2168 
2169  /*
2170  * Call ExecEvalJsonExprPath(). It returns the address of
2171  * the step to perform next.
2172  */
2173  v_ret = build_EvalXFunc(b, mod, "ExecEvalJsonExprPath",
2174  v_state, op, v_econtext);
2175 
2176  /*
2177  * Build a switch to map the return value (v_ret above),
2178  * which is a runtime value of the step address to perform
2179  * next, to either jump_empty, jump_error,
2180  * jump_eval_coercion, or jump_end.
2181  */
2182  if (jsestate->jump_empty >= 0 ||
2183  jsestate->jump_error >= 0 ||
2184  jsestate->jump_eval_coercion >= 0)
2185  {
2186  LLVMValueRef v_jump_empty;
2187  LLVMValueRef v_jump_error;
2188  LLVMValueRef v_jump_coercion;
2189  LLVMValueRef v_switch;
2190  LLVMBasicBlockRef b_done,
2191  b_empty,
2192  b_error,
2193  b_coercion;
2194 
2195  b_empty =
2196  l_bb_before_v(opblocks[opno + 1],
2197  "op.%d.jsonexpr_empty", opno);
2198  b_error =
2199  l_bb_before_v(opblocks[opno + 1],
2200  "op.%d.jsonexpr_error", opno);
2201  b_coercion =
2202  l_bb_before_v(opblocks[opno + 1],
2203  "op.%d.jsonexpr_coercion", opno);
2204  b_done =
2205  l_bb_before_v(opblocks[opno + 1],
2206  "op.%d.jsonexpr_done", opno);
2207 
2208  v_switch = LLVMBuildSwitch(b,
2209  v_ret,
2210  b_done,
2211  3);
2212  /* Returned jsestate->jump_empty? */
2213  if (jsestate->jump_empty >= 0)
2214  {
2215  v_jump_empty = l_int32_const(lc, jsestate->jump_empty);
2216  LLVMAddCase(v_switch, v_jump_empty, b_empty);
2217  }
2218  /* ON EMPTY code */
2219  LLVMPositionBuilderAtEnd(b, b_empty);
2220  if (jsestate->jump_empty >= 0)
2221  LLVMBuildBr(b, opblocks[jsestate->jump_empty]);
2222  else
2223  LLVMBuildUnreachable(b);
2224 
2225  /* Returned jsestate->jump_error? */
2226  if (jsestate->jump_error >= 0)
2227  {
2228  v_jump_error = l_int32_const(lc, jsestate->jump_error);
2229  LLVMAddCase(v_switch, v_jump_error, b_error);
2230  }
2231  /* ON ERROR code */
2232  LLVMPositionBuilderAtEnd(b, b_error);
2233  if (jsestate->jump_error >= 0)
2234  LLVMBuildBr(b, opblocks[jsestate->jump_error]);
2235  else
2236  LLVMBuildUnreachable(b);
2237 
2238  /* Returned jsestate->jump_eval_coercion? */
2239  if (jsestate->jump_eval_coercion >= 0)
2240  {
2241  v_jump_coercion = l_int32_const(lc, jsestate->jump_eval_coercion);
2242  LLVMAddCase(v_switch, v_jump_coercion, b_coercion);
2243  }
2244  /* jump_eval_coercion code */
2245  LLVMPositionBuilderAtEnd(b, b_coercion);
2246  if (jsestate->jump_eval_coercion >= 0)
2247  LLVMBuildBr(b, opblocks[jsestate->jump_eval_coercion]);
2248  else
2249  LLVMBuildUnreachable(b);
2250 
2251  LLVMPositionBuilderAtEnd(b, b_done);
2252  }
2253 
2254  LLVMBuildBr(b, opblocks[jsestate->jump_end]);
2255  break;
2256  }
2257 
2259  build_EvalXFunc(b, mod, "ExecEvalJsonCoercion",
2260  v_state, op, v_econtext);
2261 
2262  LLVMBuildBr(b, opblocks[opno + 1]);
2263  break;
2264 
2266  build_EvalXFunc(b, mod, "ExecEvalJsonCoercionFinish",
2267  v_state, op);
2268 
2269  LLVMBuildBr(b, opblocks[opno + 1]);
2270  break;
2271 
2272  case EEOP_AGGREF:
2273  {
2274  LLVMValueRef v_aggno;
2275  LLVMValueRef value,
2276  isnull;
2277 
2278  v_aggno = l_int32_const(lc, op->d.aggref.aggno);
2279 
2280  /* load agg value / null */
2281  value = l_load_gep1(b, TypeSizeT, v_aggvalues, v_aggno, "aggvalue");
2282  isnull = l_load_gep1(b, TypeStorageBool, v_aggnulls, v_aggno, "aggnull");
2283 
2284  /* and store result */
2285  LLVMBuildStore(b, value, v_resvaluep);
2286  LLVMBuildStore(b, isnull, v_resnullp);
2287 
2288  LLVMBuildBr(b, opblocks[opno + 1]);
2289  break;
2290  }
2291 
2292  case EEOP_GROUPING_FUNC:
2293  build_EvalXFunc(b, mod, "ExecEvalGroupingFunc",
2294  v_state, op);
2295  LLVMBuildBr(b, opblocks[opno + 1]);
2296  break;
2297 
2298  case EEOP_WINDOW_FUNC:
2299  {
2300  WindowFuncExprState *wfunc = op->d.window_func.wfstate;
2301  LLVMValueRef v_wfuncnop;
2302  LLVMValueRef v_wfuncno;
2303  LLVMValueRef value,
2304  isnull;
2305 
2306  /*
2307  * At this point aggref->wfuncno is not yet set (it's set
2308  * up in ExecInitWindowAgg() after initializing the
2309  * expression). So load it from memory each time round.
2310  */
2311  v_wfuncnop = l_ptr_const(&wfunc->wfuncno,
2312  l_ptr(LLVMInt32TypeInContext(lc)));
2313  v_wfuncno = l_load(b, LLVMInt32TypeInContext(lc), v_wfuncnop, "v_wfuncno");
2314 
2315  /* load window func value / null */
2316  value = l_load_gep1(b, TypeSizeT, v_aggvalues, v_wfuncno,
2317  "windowvalue");
2318  isnull = l_load_gep1(b, TypeStorageBool, v_aggnulls, v_wfuncno,
2319  "windownull");
2320 
2321  LLVMBuildStore(b, value, v_resvaluep);
2322  LLVMBuildStore(b, isnull, v_resnullp);
2323 
2324  LLVMBuildBr(b, opblocks[opno + 1]);
2325  break;
2326  }
2327 
2329  build_EvalXFunc(b, mod, "ExecEvalMergeSupportFunc",
2330  v_state, op, v_econtext);
2331  LLVMBuildBr(b, opblocks[opno + 1]);
2332  break;
2333 
2334  case EEOP_SUBPLAN:
2335  build_EvalXFunc(b, mod, "ExecEvalSubPlan",
2336  v_state, op, v_econtext);
2337  LLVMBuildBr(b, opblocks[opno + 1]);
2338  break;
2339 
2341  case EEOP_AGG_DESERIALIZE:
2342  {
2343  AggState *aggstate;
2344  FunctionCallInfo fcinfo = op->d.agg_deserialize.fcinfo_data;
2345 
2346  LLVMValueRef v_retval;
2347  LLVMValueRef v_fcinfo_isnull;
2348  LLVMValueRef v_tmpcontext;
2349  LLVMValueRef v_oldcontext;
2350 
2351  if (opcode == EEOP_AGG_STRICT_DESERIALIZE)
2352  {
2353  LLVMValueRef v_fcinfo;
2354  LLVMValueRef v_argnull0;
2355  LLVMBasicBlockRef b_deserialize;
2356 
2357  b_deserialize = l_bb_before_v(opblocks[opno + 1],
2358  "op.%d.deserialize", opno);
2359 
2360  v_fcinfo = l_ptr_const(fcinfo,
2362  v_argnull0 = l_funcnull(b, v_fcinfo, 0);
2363 
2364  LLVMBuildCondBr(b,
2365  LLVMBuildICmp(b,
2366  LLVMIntEQ,
2367  v_argnull0,
2368  l_sbool_const(1),
2369  ""),
2370  opblocks[op->d.agg_deserialize.jumpnull],
2371  b_deserialize);
2372  LLVMPositionBuilderAtEnd(b, b_deserialize);
2373  }
2374 
2375  aggstate = castNode(AggState, state->parent);
2376  fcinfo = op->d.agg_deserialize.fcinfo_data;
2377 
2378  v_tmpcontext =
2379  l_ptr_const(aggstate->tmpcontext->ecxt_per_tuple_memory,
2380  l_ptr(StructMemoryContextData));
2381  v_oldcontext = l_mcxt_switch(mod, b, v_tmpcontext);
2382  v_retval = BuildV1Call(context, b, mod, fcinfo,
2383  &v_fcinfo_isnull);
2384  l_mcxt_switch(mod, b, v_oldcontext);
2385 
2386  LLVMBuildStore(b, v_retval, v_resvaluep);
2387  LLVMBuildStore(b, v_fcinfo_isnull, v_resnullp);
2388 
2389  LLVMBuildBr(b, opblocks[opno + 1]);
2390  break;
2391  }
2392 
2395  {
2396  int nargs = op->d.agg_strict_input_check.nargs;
2398  bool *nulls = op->d.agg_strict_input_check.nulls;
2399  int jumpnull;
2400 
2401  LLVMValueRef v_argsp;
2402  LLVMValueRef v_nullsp;
2403  LLVMBasicBlockRef *b_checknulls;
2404 
2405  Assert(nargs > 0);
2406 
2407  jumpnull = op->d.agg_strict_input_check.jumpnull;
2408  v_argsp = l_ptr_const(args, l_ptr(StructNullableDatum));
2409  v_nullsp = l_ptr_const(nulls, l_ptr(TypeStorageBool));
2410 
2411  /* create blocks for checking args */
2412  b_checknulls = palloc(sizeof(LLVMBasicBlockRef *) * nargs);
2413  for (int argno = 0; argno < nargs; argno++)
2414  {
2415  b_checknulls[argno] =
2416  l_bb_before_v(opblocks[opno + 1],
2417  "op.%d.check-null.%d",
2418  opno, argno);
2419  }
2420 
2421  LLVMBuildBr(b, b_checknulls[0]);
2422 
2423  /* strict function, check for NULL args */
2424  for (int argno = 0; argno < nargs; argno++)
2425  {
2426  LLVMValueRef v_argno = l_int32_const(lc, argno);
2427  LLVMValueRef v_argisnull;
2428  LLVMBasicBlockRef b_argnotnull;
2429 
2430  LLVMPositionBuilderAtEnd(b, b_checknulls[argno]);
2431 
2432  if (argno + 1 == nargs)
2433  b_argnotnull = opblocks[opno + 1];
2434  else
2435  b_argnotnull = b_checknulls[argno + 1];
2436 
2437  if (opcode == EEOP_AGG_STRICT_INPUT_CHECK_NULLS)
2438  v_argisnull = l_load_gep1(b, TypeStorageBool, v_nullsp, v_argno, "");
2439  else
2440  {
2441  LLVMValueRef v_argn;
2442 
2443  v_argn = l_gep(b, StructNullableDatum, v_argsp, &v_argno, 1, "");
2444  v_argisnull =
2445  l_load_struct_gep(b, StructNullableDatum, v_argn,
2447  "");
2448  }
2449 
2450  LLVMBuildCondBr(b,
2451  LLVMBuildICmp(b,
2452  LLVMIntEQ,
2453  v_argisnull,
2454  l_sbool_const(1), ""),
2455  opblocks[jumpnull],
2456  b_argnotnull);
2457  }
2458 
2459  break;
2460  }
2461 
2463  {
2464  int jumpnull;
2465  LLVMValueRef v_aggstatep;
2466  LLVMValueRef v_allpergroupsp;
2467  LLVMValueRef v_pergroup_allaggs;
2468  LLVMValueRef v_setoff;
2469 
2470  jumpnull = op->d.agg_plain_pergroup_nullcheck.jumpnull;
2471 
2472  /*
2473  * pergroup_allaggs = aggstate->all_pergroups
2474  * [op->d.agg_plain_pergroup_nullcheck.setoff];
2475  */
2476  v_aggstatep = LLVMBuildBitCast(b, v_parent,
2477  l_ptr(StructAggState), "");
2478 
2479  v_allpergroupsp = l_load_struct_gep(b,
2481  v_aggstatep,
2483  "aggstate.all_pergroups");
2484 
2485  v_setoff = l_int32_const(lc, op->d.agg_plain_pergroup_nullcheck.setoff);
2486 
2487  v_pergroup_allaggs = l_load_gep1(b, l_ptr(StructAggStatePerGroupData),
2488  v_allpergroupsp, v_setoff, "");
2489 
2490  LLVMBuildCondBr(b,
2491  LLVMBuildICmp(b, LLVMIntEQ,
2492  LLVMBuildPtrToInt(b, v_pergroup_allaggs, TypeSizeT, ""),
2493  l_sizet_const(0), ""),
2494  opblocks[jumpnull],
2495  opblocks[opno + 1]);
2496  break;
2497  }
2498 
2505  {
2506  AggState *aggstate;
2507  AggStatePerTrans pertrans;
2508  FunctionCallInfo fcinfo;
2509 
2510  LLVMValueRef v_aggstatep;
2511  LLVMValueRef v_fcinfo;
2512  LLVMValueRef v_fcinfo_isnull;
2513 
2514  LLVMValueRef v_transvaluep;
2515  LLVMValueRef v_transnullp;
2516 
2517  LLVMValueRef v_setoff;
2518  LLVMValueRef v_transno;
2519 
2520  LLVMValueRef v_aggcontext;
2521 
2522  LLVMValueRef v_allpergroupsp;
2523  LLVMValueRef v_current_setp;
2524  LLVMValueRef v_current_pertransp;
2525  LLVMValueRef v_curaggcontext;
2526 
2527  LLVMValueRef v_pertransp;
2528 
2529  LLVMValueRef v_pergroupp;
2530 
2531  LLVMValueRef v_retval;
2532 
2533  LLVMValueRef v_tmpcontext;
2534  LLVMValueRef v_oldcontext;
2535 
2536  aggstate = castNode(AggState, state->parent);
2537  pertrans = op->d.agg_trans.pertrans;
2538 
2539  fcinfo = pertrans->transfn_fcinfo;
2540 
2541  v_aggstatep =
2542  LLVMBuildBitCast(b, v_parent, l_ptr(StructAggState), "");
2543  v_pertransp = l_ptr_const(pertrans,
2545 
2546  /*
2547  * pergroup = &aggstate->all_pergroups
2548  * [op->d.agg_trans.setoff] [op->d.agg_trans.transno];
2549  */
2550  v_allpergroupsp =
2551  l_load_struct_gep(b,
2553  v_aggstatep,
2555  "aggstate.all_pergroups");
2556  v_setoff = l_int32_const(lc, op->d.agg_trans.setoff);
2557  v_transno = l_int32_const(lc, op->d.agg_trans.transno);
2558  v_pergroupp =
2559  l_gep(b,
2561  l_load_gep1(b, l_ptr(StructAggStatePerGroupData),
2562  v_allpergroupsp, v_setoff, ""),
2563  &v_transno, 1, "");
2564 
2565 
2568  {
2569  LLVMValueRef v_notransvalue;
2570  LLVMBasicBlockRef b_init;
2571  LLVMBasicBlockRef b_no_init;
2572 
2573  v_notransvalue =
2574  l_load_struct_gep(b,
2576  v_pergroupp,
2578  "notransvalue");
2579 
2580  b_init = l_bb_before_v(opblocks[opno + 1],
2581  "op.%d.inittrans", opno);
2582  b_no_init = l_bb_before_v(opblocks[opno + 1],
2583  "op.%d.no_inittrans", opno);
2584 
2585  LLVMBuildCondBr(b,
2586  LLVMBuildICmp(b, LLVMIntEQ, v_notransvalue,
2587  l_sbool_const(1), ""),
2588  b_init,
2589  b_no_init);
2590 
2591  /* block to init the transition value if necessary */
2592  {
2593  LLVMValueRef params[4];
2594 
2595  LLVMPositionBuilderAtEnd(b, b_init);
2596 
2597  v_aggcontext = l_ptr_const(op->d.agg_trans.aggcontext,
2598  l_ptr(StructExprContext));
2599 
2600  params[0] = v_aggstatep;
2601  params[1] = v_pertransp;
2602  params[2] = v_pergroupp;
2603  params[3] = v_aggcontext;
2604 
2605  l_call(b,
2606  llvm_pg_var_func_type("ExecAggInitGroup"),
2607  llvm_pg_func(mod, "ExecAggInitGroup"),
2608  params, lengthof(params),
2609  "");
2610 
2611  LLVMBuildBr(b, opblocks[opno + 1]);
2612  }
2613 
2614  LLVMPositionBuilderAtEnd(b, b_no_init);
2615  }
2616 
2621  {
2622  LLVMValueRef v_transnull;
2623  LLVMBasicBlockRef b_strictpass;
2624 
2625  b_strictpass = l_bb_before_v(opblocks[opno + 1],
2626  "op.%d.strictpass", opno);
2627  v_transnull =
2628  l_load_struct_gep(b,
2630  v_pergroupp,
2632  "transnull");
2633 
2634  LLVMBuildCondBr(b,
2635  LLVMBuildICmp(b, LLVMIntEQ, v_transnull,
2636  l_sbool_const(1), ""),
2637  opblocks[opno + 1],
2638  b_strictpass);
2639 
2640  LLVMPositionBuilderAtEnd(b, b_strictpass);
2641  }
2642 
2643 
2644  v_fcinfo = l_ptr_const(fcinfo,
2646  v_aggcontext = l_ptr_const(op->d.agg_trans.aggcontext,
2647  l_ptr(StructExprContext));
2648 
2649  v_current_setp =
2650  l_struct_gep(b,
2652  v_aggstatep,
2654  "aggstate.current_set");
2655  v_curaggcontext =
2656  l_struct_gep(b,
2658  v_aggstatep,
2660  "aggstate.curaggcontext");
2661  v_current_pertransp =
2662  l_struct_gep(b,
2664  v_aggstatep,
2666  "aggstate.curpertrans");
2667 
2668  /* set aggstate globals */
2669  LLVMBuildStore(b, v_aggcontext, v_curaggcontext);
2670  LLVMBuildStore(b, l_int32_const(lc, op->d.agg_trans.setno),
2671  v_current_setp);
2672  LLVMBuildStore(b, v_pertransp, v_current_pertransp);
2673 
2674  /* invoke transition function in per-tuple context */
2675  v_tmpcontext =
2676  l_ptr_const(aggstate->tmpcontext->ecxt_per_tuple_memory,
2677  l_ptr(StructMemoryContextData));
2678  v_oldcontext = l_mcxt_switch(mod, b, v_tmpcontext);
2679 
2680  /* store transvalue in fcinfo->args[0] */
2681  v_transvaluep =
2682  l_struct_gep(b,
2684  v_pergroupp,
2686  "transvalue");
2687  v_transnullp =
2688  l_struct_gep(b,
2690  v_pergroupp,
2692  "transnullp");
2693  LLVMBuildStore(b,
2694  l_load(b,
2695  TypeSizeT,
2696  v_transvaluep,
2697  "transvalue"),
2698  l_funcvaluep(b, v_fcinfo, 0));
2699  LLVMBuildStore(b,
2700  l_load(b, TypeStorageBool, v_transnullp, "transnull"),
2701  l_funcnullp(b, v_fcinfo, 0));
2702 
2703  /* and invoke transition function */
2704  v_retval = BuildV1Call(context, b, mod, fcinfo,
2705  &v_fcinfo_isnull);
2706 
2707  /*
2708  * For pass-by-ref datatype, must copy the new value into
2709  * aggcontext and free the prior transValue. But if
2710  * transfn returned a pointer to its first input, we don't
2711  * need to do anything. Also, if transfn returned a
2712  * pointer to a R/W expanded object that is already a
2713  * child of the aggcontext, assume we can adopt that value
2714  * without copying it.
2715  */
2718  opcode == EEOP_AGG_PLAIN_TRANS_BYREF)
2719  {
2720  LLVMBasicBlockRef b_call;
2721  LLVMBasicBlockRef b_nocall;
2722  LLVMValueRef v_fn;
2723  LLVMValueRef v_transvalue;
2724  LLVMValueRef v_transnull;
2725  LLVMValueRef v_newval;
2726  LLVMValueRef params[6];
2727 
2728  b_call = l_bb_before_v(opblocks[opno + 1],
2729  "op.%d.transcall", opno);
2730  b_nocall = l_bb_before_v(opblocks[opno + 1],
2731  "op.%d.transnocall", opno);
2732 
2733  v_transvalue = l_load(b, TypeSizeT, v_transvaluep, "");
2734  v_transnull = l_load(b, TypeStorageBool, v_transnullp, "");
2735 
2736  /*
2737  * DatumGetPointer(newVal) !=
2738  * DatumGetPointer(pergroup->transValue))
2739  */
2740  LLVMBuildCondBr(b,
2741  LLVMBuildICmp(b, LLVMIntEQ,
2742  v_transvalue,
2743  v_retval, ""),
2744  b_nocall, b_call);
2745 
2746  /* returned datum not passed datum, reparent */
2747  LLVMPositionBuilderAtEnd(b, b_call);
2748 
2749  params[0] = v_aggstatep;
2750  params[1] = v_pertransp;
2751  params[2] = v_retval;
2752  params[3] = LLVMBuildTrunc(b, v_fcinfo_isnull,
2753  TypeParamBool, "");
2754  params[4] = v_transvalue;
2755  params[5] = LLVMBuildTrunc(b, v_transnull,
2756  TypeParamBool, "");
2757 
2758  v_fn = llvm_pg_func(mod, "ExecAggCopyTransValue");
2759  v_newval =
2760  l_call(b,
2761  LLVMGetFunctionType(v_fn),
2762  v_fn,
2763  params, lengthof(params),
2764  "");
2765 
2766  /* store trans value */
2767  LLVMBuildStore(b, v_newval, v_transvaluep);
2768  LLVMBuildStore(b, v_fcinfo_isnull, v_transnullp);
2769 
2770  l_mcxt_switch(mod, b, v_oldcontext);
2771  LLVMBuildBr(b, opblocks[opno + 1]);
2772 
2773  /* returned datum passed datum, no need to reparent */
2774  LLVMPositionBuilderAtEnd(b, b_nocall);
2775  }
2776 
2777  /* store trans value */
2778  LLVMBuildStore(b, v_retval, v_transvaluep);
2779  LLVMBuildStore(b, v_fcinfo_isnull, v_transnullp);
2780 
2781  l_mcxt_switch(mod, b, v_oldcontext);
2782 
2783  LLVMBuildBr(b, opblocks[opno + 1]);
2784  break;
2785  }
2786 
2788  {
2789  AggState *aggstate = castNode(AggState, state->parent);
2790  AggStatePerTrans pertrans = op->d.agg_presorted_distinctcheck.pertrans;
2791  int jumpdistinct = op->d.agg_presorted_distinctcheck.jumpdistinct;
2792 
2793  LLVMValueRef v_fn = llvm_pg_func(mod, "ExecEvalPreOrderedDistinctSingle");
2794  LLVMValueRef v_args[2];
2795  LLVMValueRef v_ret;
2796 
2797  v_args[0] = l_ptr_const(aggstate, l_ptr(StructAggState));
2798  v_args[1] = l_ptr_const(pertrans, l_ptr(StructAggStatePerTransData));
2799 
2800  v_ret = l_call(b, LLVMGetFunctionType(v_fn), v_fn, v_args, 2, "");
2801  v_ret = LLVMBuildZExt(b, v_ret, TypeStorageBool, "");
2802 
2803  LLVMBuildCondBr(b,
2804  LLVMBuildICmp(b, LLVMIntEQ, v_ret,
2805  l_sbool_const(1), ""),
2806  opblocks[opno + 1],
2807  opblocks[jumpdistinct]);
2808  break;
2809  }
2810 
2812  {
2813  AggState *aggstate = castNode(AggState, state->parent);
2814  AggStatePerTrans pertrans = op->d.agg_presorted_distinctcheck.pertrans;
2815  int jumpdistinct = op->d.agg_presorted_distinctcheck.jumpdistinct;
2816 
2817  LLVMValueRef v_fn = llvm_pg_func(mod, "ExecEvalPreOrderedDistinctMulti");
2818  LLVMValueRef v_args[2];
2819  LLVMValueRef v_ret;
2820 
2821  v_args[0] = l_ptr_const(aggstate, l_ptr(StructAggState));
2822  v_args[1] = l_ptr_const(pertrans, l_ptr(StructAggStatePerTransData));
2823 
2824  v_ret = l_call(b, LLVMGetFunctionType(v_fn), v_fn, v_args, 2, "");
2825  v_ret = LLVMBuildZExt(b, v_ret, TypeStorageBool, "");
2826 
2827  LLVMBuildCondBr(b,
2828  LLVMBuildICmp(b, LLVMIntEQ, v_ret,
2829  l_sbool_const(1), ""),
2830  opblocks[opno + 1],
2831  opblocks[jumpdistinct]);
2832  break;
2833  }
2834 
2836  build_EvalXFunc(b, mod, "ExecEvalAggOrderedTransDatum",
2837  v_state, op, v_econtext);
2838  LLVMBuildBr(b, opblocks[opno + 1]);
2839  break;
2840 
2842  build_EvalXFunc(b, mod, "ExecEvalAggOrderedTransTuple",
2843  v_state, op, v_econtext);
2844  LLVMBuildBr(b, opblocks[opno + 1]);
2845  break;
2846 
2847  case EEOP_LAST:
2848  Assert(false);
2849  break;
2850  }
2851  }
2852 
2853  LLVMDisposeBuilder(b);
2854 
2855  /*
2856  * Don't immediately emit function, instead do so the first time the
2857  * expression is actually evaluated. That allows to emit a lot of
2858  * functions together, avoiding a lot of repeated llvm and memory
2859  * remapping overhead.
2860  */
2861  {
2862 
2863  CompiledExprState *cstate = palloc0(sizeof(CompiledExprState));
2864 
2865  cstate->context = context;
2866  cstate->funcname = funcname;
2867 
2868  state->evalfunc = ExecRunCompiledExpr;
2869  state->evalfunc_private = cstate;
2870  }
2871 
2873 
2874  INSTR_TIME_SET_CURRENT(endtime);
2875  INSTR_TIME_ACCUM_DIFF(context->base.instr.generation_counter,
2876  endtime, starttime);
2877 
2878  return true;
2879 }
ExprEvalOp ExecEvalStepOp(ExprState *state, ExprEvalStep *op)
ExprEvalOp
Definition: execExpr.h:67
@ EEOP_ASSIGN_TMP
Definition: execExpr.h:99
@ EEOP_SUBPLAN
Definition: execExpr.h:259
@ EEOP_CONVERT_ROWTYPE
Definition: execExpr.h:246
@ EEOP_FUNCEXPR_STRICT_FUSAGE
Definition: execExpr.h:114
@ EEOP_ARRAYEXPR
Definition: execExpr.h:181
@ EEOP_JSONEXPR_PATH
Definition: execExpr.h:252
@ EEOP_NOT_DISTINCT
Definition: execExpr.h:176
@ EEOP_DOMAIN_TESTVAL
Definition: execExpr.h:230
@ EEOP_PARAM_EXTERN
Definition: execExpr.h:161
@ EEOP_HASHDATUM_NEXT32_STRICT
Definition: execExpr.h:243
@ EEOP_IOCOERCE_SAFE
Definition: execExpr.h:174
@ EEOP_BOOL_AND_STEP
Definition: execExpr.h:123
@ EEOP_WHOLEROW
Definition: execExpr.h:87
@ EEOP_JSONEXPR_COERCION_FINISH
Definition: execExpr.h:254
@ EEOP_HASHDATUM_FIRST_STRICT
Definition: execExpr.h:241
@ EEOP_AGGREF
Definition: execExpr.h:255
@ EEOP_INNER_VAR
Definition: execExpr.h:77
@ EEOP_AGG_PLAIN_PERGROUP_NULLCHECK
Definition: execExpr.h:266
@ EEOP_HASHDATUM_NEXT32
Definition: execExpr.h:242
@ EEOP_ROWCOMPARE_FINAL
Definition: execExpr.h:192
@ EEOP_AGG_STRICT_DESERIALIZE
Definition: execExpr.h:262
@ EEOP_IOCOERCE
Definition: execExpr.h:173
@ EEOP_GROUPING_FUNC
Definition: execExpr.h:256
@ EEOP_DOMAIN_CHECK
Definition: execExpr.h:236
@ EEOP_BOOLTEST_IS_NOT_FALSE
Definition: execExpr.h:157
@ EEOP_PARAM_SET
Definition: execExpr.h:164
@ EEOP_NEXTVALUEEXPR
Definition: execExpr.h:180
@ EEOP_DONE
Definition: execExpr.h:69
@ EEOP_AGG_PLAIN_TRANS_BYREF
Definition: execExpr.h:272
@ EEOP_QUAL
Definition: execExpr.h:135
@ EEOP_AGG_PRESORTED_DISTINCT_MULTI
Definition: execExpr.h:274
@ EEOP_AGG_PLAIN_TRANS_BYVAL
Definition: execExpr.h:269
@ 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:247
@ EEOP_DOMAIN_NOTNULL
Definition: execExpr.h:233
@ EEOP_WINDOW_FUNC
Definition: execExpr.h:257
@ 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:183
@ EEOP_MAKE_READONLY
Definition: execExpr.h:170
@ EEOP_FIELDSTORE_FORM
Definition: execExpr.h:211
@ EEOP_SBSREF_SUBSCRIPTS
Definition: execExpr.h:214
@ EEOP_SBSREF_FETCH
Definition: execExpr.h:227
@ EEOP_FUNCEXPR_STRICT
Definition: execExpr.h:112
@ EEOP_NULLIF
Definition: execExpr.h:177
@ EEOP_CURRENTOFEXPR
Definition: execExpr.h:179
@ 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:253
@ EEOP_BOOL_OR_STEP_FIRST
Definition: execExpr.h:127
@ EEOP_XMLEXPR
Definition: execExpr.h:249
@ EEOP_AGG_STRICT_INPUT_CHECK_NULLS
Definition: execExpr.h:265
@ EEOP_SBSREF_ASSIGN
Definition: execExpr.h:224
@ 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:264
@ 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:189
@ EEOP_MERGE_SUPPORT_FUNC
Definition: execExpr.h:258
@ EEOP_AGG_DESERIALIZE
Definition: execExpr.h:263
@ EEOP_LAST
Definition: execExpr.h:279
@ EEOP_HASHDATUM_FIRST
Definition: execExpr.h:240
@ EEOP_DISTINCT
Definition: execExpr.h:175
@ EEOP_JUMP_IF_NOT_TRUE
Definition: execExpr.h:143
@ EEOP_FUNCEXPR_FUSAGE
Definition: execExpr.h:113
@ EEOP_AGG_PRESORTED_DISTINCT_SINGLE
Definition: execExpr.h:273
@ 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:275
@ EEOP_SBSREF_OLD
Definition: execExpr.h:221
@ EEOP_SQLVALUEFUNCTION
Definition: execExpr.h:178
@ EEOP_HASHDATUM_SET_INITVAL
Definition: execExpr.h:239
@ EEOP_JUMP_IF_NOT_NULL
Definition: execExpr.h:142
@ EEOP_AGG_PLAIN_TRANS_STRICT_BYREF
Definition: execExpr.h:271
@ EEOP_FIELDSTORE_DEFORM
Definition: execExpr.h:204
@ 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:267
@ EEOP_PARAM_EXEC
Definition: execExpr.h:160
@ EEOP_JSON_CONSTRUCTOR
Definition: execExpr.h:250
@ EEOP_AGG_PLAIN_TRANS_STRICT_BYVAL
Definition: execExpr.h:268
@ EEOP_NULLTEST_ISNULL
Definition: execExpr.h:146
@ EEOP_MINMAX
Definition: execExpr.h:195
@ EEOP_JUMP_IF_NULL
Definition: execExpr.h:141
@ EEOP_ARRAYCOERCE
Definition: execExpr.h:182
@ EEOP_FIELDSELECT
Definition: execExpr.h:198
@ EEOP_CASE_TESTVAL
Definition: execExpr.h:167
@ EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF
Definition: execExpr.h:270
@ EEOP_HASHED_SCALARARRAYOP
Definition: execExpr.h:248
@ EEOP_OUTER_VAR
Definition: execExpr.h:78
@ EEOP_AGG_ORDERED_TRANS_TUPLE
Definition: execExpr.h:276
@ EEOP_SCAN_FETCHSOME
Definition: execExpr.h:74
@ EEOP_IS_JSON
Definition: execExpr.h:251
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:84
#define FIELDNO_EXPRSTATE_RESULTSLOT
Definition: execnodes.h:96
#define FIELDNO_EXPRCONTEXT_CASENULL
Definition: execnodes.h:284
#define FIELDNO_EXPRCONTEXT_INNERTUPLE
Definition: execnodes.h:259
#define FIELDNO_EXPRCONTEXT_DOMAINNULL
Definition: execnodes.h:290
#define FIELDNO_EXPRCONTEXT_DOMAINDATUM
Definition: execnodes.h:288
#define FIELDNO_EXPRCONTEXT_CASEDATUM
Definition: execnodes.h:282
#define FIELDNO_AGGSTATE_CURPERTRANS
Definition: execnodes.h:2514
#define FIELDNO_EXPRSTATE_RESNULL
Definition: execnodes.h:88
#define FIELDNO_EXPRCONTEXT_AGGNULLS
Definition: execnodes.h:278
#define FIELDNO_EXPRSTATE_RESVALUE
Definition: execnodes.h:90
#define FIELDNO_AGGSTATE_CURRENT_SET
Definition: execnodes.h:2519
#define FIELDNO_EXPRCONTEXT_AGGVALUES
Definition: execnodes.h:276
#define FIELDNO_EXPRCONTEXT_OUTERTUPLE
Definition: execnodes.h:261
#define FIELDNO_AGGSTATE_ALL_PERGROUPS
Definition: execnodes.h:2565
#define FIELDNO_EXPRSTATE_PARENT
Definition: execnodes.h:124
#define FIELDNO_EXPRCONTEXT_SCANTUPLE
Definition: execnodes.h:257
#define FIELDNO_AGGSTATE_CURAGGCONTEXT
Definition: execnodes.h:2511
static struct @160 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:72
LLVMTypeRef TypeParamBool
Definition: llvmjit.c:57
LLVMTypeRef StructMemoryContextData
Definition: llvmjit.c:68
LLVMTypeRef StructAggStatePerGroupData
Definition: llvmjit.c:74
LLVMTypeRef llvm_pg_var_type(const char *varname)
Definition: llvmjit.c:419
LLVMTypeRef TypeSizeT
Definition: llvmjit.c:56
char * llvm_expand_funcname(struct LLVMJitContext *context, const char *basename)
Definition: llvmjit.c:338
LLVMTypeRef llvm_pg_var_func_type(const char *varname)
Definition: llvmjit.c:439
LLVMTypeRef StructTupleTableSlot
Definition: llvmjit.c:64
LLVMJitContext * llvm_create_context(int jitFlags)
Definition: llvmjit.c:220
LLVMModuleRef llvm_mutable_module(LLVMJitContext *context)
Definition: llvmjit.c:313
LLVMTypeRef StructAggState
Definition: llvmjit.c:73
LLVMTypeRef StructExprContext
Definition: llvmjit.c:70
LLVMTypeRef StructNullableDatum
Definition: llvmjit.c:60
LLVMValueRef ExecEvalSubroutineTemplate
Definition: llvmjit.c:79
LLVMValueRef ExecEvalBoolSubroutineTemplate
Definition: llvmjit.c:80
LLVMTypeRef StructAggStatePerTransData
Definition: llvmjit.c:75
void llvm_copy_attributes(LLVMValueRef v_from, LLVMValueRef v_to)
Definition: llvmjit.c:513
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:1347
#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:1453
@ ROWCOMPARE_GT
Definition: primnodes.h:1459
@ ROWCOMPARE_LT
Definition: primnodes.h:1455
@ ROWCOMPARE_LE
Definition: primnodes.h:1456
@ ROWCOMPARE_GE
Definition: primnodes.h:1458
FunctionCallInfo transfn_fcinfo
Definition: nodeAgg.h:170
ExprContext * tmpcontext
Definition: execnodes.h:2510
struct JitContext * es_jit
Definition: execnodes.h:729
int es_jit_flags
Definition: execnodes.h:728
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:266
struct ExprEvalStep::@55::@65 jump
struct ExprEvalStep::@55::@78 rowcompare_final
struct ExprEvalStep::@55::@86 hashdatum
struct ExprEvalStep::@55::@60 assign_tmp
struct ExprEvalStep::@55::@100 agg_trans
struct ExprEvalStep::@55::@57 var
struct ExprEvalStep::@55::@63 boolexpr
struct ExprEvalStep::@55::@98 agg_plain_pergroup_nullcheck
struct ExprEvalStep::@55::@92 aggref
struct ExprEvalStep::@55::@64 qualexpr
struct ExprEvalStep::@55::@82 sbsref_subscript
struct ExprEvalStep::@55::@62 func
struct ExprEvalStep::@55::@94 window_func
Datum * resvalue
Definition: execExpr.h:293
struct ExprEvalStep::@55::@77 rowcompare_step
struct ExprEvalStep::@55::@102 jsonexpr
struct ExprEvalStep::@55::@70 make_readonly
union ExprEvalStep::@55 d
struct ExprEvalStep::@55::@71 iocoerce
struct ExprEvalStep::@55::@68 cparam
bool * resnull
Definition: execExpr.h:294
struct ExprEvalStep::@55::@69 casetest
struct ExprEvalStep::@55::@83 sbsref
struct ExprEvalStep::@55::@97 agg_strict_input_check
struct ExprEvalStep::@55::@61 constval
struct ExprEvalStep::@55::@56 fetch
struct ExprEvalStep::@55::@85 hashdatum_initvalue
struct ExprEvalStep::@55::@59 assign_var
struct ExprEvalStep::@55::@99 agg_presorted_distinctcheck
struct ExprEvalStep::@55::@96 agg_deserialize
int jump_eval_coercion
Definition: execnodes.h:1069
EState * state
Definition: execnodes.h:1129
#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().