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