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