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:777
#define funcname
Definition: indent_codes.h:69
int b
Definition: isn.c:70
static LLVMValueRef build_EvalXFuncInt(LLVMBuilderRef b, LLVMModuleRef mod, const char *funcname, LLVMValueRef v_state, ExprEvalStep *op, int natts, LLVMValueRef *v_args)

Definition at line 68 of file llvmjit_expr.c.

Typedef Documentation

◆ CompiledExprState

Function Documentation

◆ build_EvalXFuncInt()

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

Definition at line 2529 of file llvmjit_expr.c.

2532 {
2533  LLVMValueRef v_fn = llvm_pg_func(mod, funcname);
2534  LLVMValueRef *params;
2535  int argno = 0;
2536  LLVMValueRef v_ret;
2537 
2538  /* cheap pre-check as llvm just asserts out */
2539  if (LLVMCountParams(v_fn) != (nargs + 2))
2540  elog(ERROR, "parameter mismatch: %s expects %d passed %d",
2541  funcname, LLVMCountParams(v_fn), nargs + 2);
2542 
2543  params = palloc(sizeof(LLVMValueRef) * (2 + nargs));
2544 
2545  params[argno++] = v_state;
2546  params[argno++] = l_ptr_const(op, l_ptr(StructExprEvalStep));
2547 
2548  for (int i = 0; i < nargs; i++)
2549  params[argno++] = v_args[i];
2550 
2551  v_ret = LLVMBuildCall(b, v_fn, params, argno, "");
2552 
2553  pfree(params);
2554 
2555  return v_ret;
2556 }
#define ERROR
Definition: elog.h:39
int i
Definition: isn.c:73
LLVMTypeRef StructExprEvalStep
Definition: llvmjit.c:74
LLVMValueRef llvm_pg_func(LLVMModuleRef mod, const char *funcname)
Definition: llvmjit.c:488
void pfree(void *pointer)
Definition: mcxt.c:1456
void * palloc(Size size)
Definition: mcxt.c:1226

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

◆ BuildV1Call()

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

Definition at line 2480 of file llvmjit_expr.c.

2483 {
2484  LLVMContextRef lc;
2485  LLVMValueRef v_fn;
2486  LLVMValueRef v_fcinfo_isnullp;
2487  LLVMValueRef v_retval;
2488  LLVMValueRef v_fcinfo;
2489 
2490  lc = LLVMGetModuleContext(mod);
2491 
2492  v_fn = llvm_function_reference(context, b, mod, fcinfo);
2493 
2494  v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
2495  v_fcinfo_isnullp = LLVMBuildStructGEP(b, v_fcinfo,
2497  "v_fcinfo_isnull");
2498  LLVMBuildStore(b, l_sbool_const(0), v_fcinfo_isnullp);
2499 
2500  v_retval = LLVMBuildCall(b, v_fn, &v_fcinfo, 1, "funccall");
2501 
2502  if (v_fcinfo_isnull)
2503  *v_fcinfo_isnull = LLVMBuildLoad(b, v_fcinfo_isnullp, "");
2504 
2505  /*
2506  * Add lifetime-end annotation, signaling that writes to memory don't have
2507  * to be retained (important for inlining potential).
2508  */
2509  {
2510  LLVMValueRef v_lifetime = create_LifetimeEnd(mod);
2511  LLVMValueRef params[2];
2512 
2513  params[0] = l_int64_const(lc, sizeof(NullableDatum) * fcinfo->nargs);
2514  params[1] = l_ptr_const(fcinfo->args, l_ptr(LLVMInt8TypeInContext(lc)));
2515  LLVMBuildCall(b, v_lifetime, params, lengthof(params), "");
2516 
2517  params[0] = l_int64_const(lc, sizeof(fcinfo->isnull));
2518  params[1] = l_ptr_const(&fcinfo->isnull, l_ptr(LLVMInt8TypeInContext(lc)));
2519  LLVMBuildCall(b, v_lifetime, params, lengthof(params), "");
2520  }
2521 
2522  return v_retval;
2523 }
#define FIELDNO_FUNCTIONCALLINFODATA_ISNULL
Definition: fmgr.h:91
LLVMTypeRef StructFunctionCallInfoData
Definition: llvmjit.c:72
LLVMValueRef llvm_function_reference(LLVMJitContext *context, LLVMBuilderRef builder, LLVMModuleRef mod, FunctionCallInfo fcinfo)
Definition: llvmjit.c:565
static LLVMValueRef create_LifetimeEnd(LLVMModuleRef mod)
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
Definition: fmgr.h:95

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

◆ create_LifetimeEnd()

static LLVMValueRef create_LifetimeEnd ( LLVMModuleRef  mod)
static

Definition at line 2559 of file llvmjit_expr.c.

2560 {
2561  LLVMTypeRef sig;
2562  LLVMValueRef fn;
2563  LLVMTypeRef param_types[2];
2564  LLVMContextRef lc;
2565 
2566  /* LLVM 5+ has a variadic pointer argument */
2567 #if LLVM_VERSION_MAJOR < 5
2568  const char *nm = "llvm.lifetime.end";
2569 #else
2570  const char *nm = "llvm.lifetime.end.p0i8";
2571 #endif
2572 
2573  fn = LLVMGetNamedFunction(mod, nm);
2574  if (fn)
2575  return fn;
2576 
2577  lc = LLVMGetModuleContext(mod);
2578  param_types[0] = LLVMInt64TypeInContext(lc);
2579  param_types[1] = l_ptr(LLVMInt8TypeInContext(lc));
2580 
2581  sig = LLVMFunctionType(LLVMVoidTypeInContext(lc), param_types,
2582  lengthof(param_types), false);
2583  fn = LLVMAddFunction(mod, nm, sig);
2584 
2585  LLVMSetFunctionCallConv(fn, LLVMCCallConv);
2586 
2587  Assert(LLVMGetIntrinsicID(fn));
2588 
2589  return fn;
2590 }
Assert(fmt[strlen(fmt) - 1] !='\n')
static int sig
Definition: pg_ctl.c:79
static void * fn(void *arg)
Definition: thread-alloc.c:119

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

Referenced by BuildV1Call().

◆ ExecRunCompiledExpr()

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

Definition at line 2460 of file llvmjit_expr.c.

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