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