1 /*-------------------------------------------------------------------------
4 * JIT compile expressions.
6 * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/jit/llvm/llvmjit_expr.c
13 *-------------------------------------------------------------------------
18 #include <llvm-c/Core.h>
19 #include <llvm-c/Target.h>
21 #include "access/htup_details.h"
22 #include "access/nbtree.h"
23 #include "access/tupconvert.h"
24 #include "catalog/objectaccess.h"
25 #include "catalog/pg_type.h"
26 #include "executor/execdebug.h"
27 #include "executor/nodeAgg.h"
28 #include "executor/nodeSubplan.h"
29 #include "executor/execExpr.h"
31 #include "jit/llvmjit.h"
32 #include "jit/llvmjit_emit.h"
33 #include "miscadmin.h"
34 #include "nodes/makefuncs.h"
35 #include "nodes/nodeFuncs.h"
36 #include "optimizer/planner.h"
37 #include "parser/parse_coerce.h"
38 #include "parser/parsetree.h"
40 #include "utils/acl.h"
41 #include "utils/builtins.h"
42 #include "utils/date.h"
43 #include "utils/fmgrtab.h"
44 #include "utils/lsyscache.h"
45 #include "utils/memutils.h"
46 #include "utils/timestamp.h"
47 #include "utils/typcache.h"
48 #include "utils/xml.h"
51 typedef struct CompiledExprState
53 LLVMJitContext *context;
58 static Datum ExecRunCompiledExpr(ExprState *state, ExprContext *econtext, bool *isNull);
60 static LLVMValueRef BuildV1Call(LLVMJitContext *context, LLVMBuilderRef b,
61 LLVMModuleRef mod, FunctionCallInfo fcinfo,
62 LLVMValueRef *v_fcinfo_isnull);
63 static void build_EvalXFunc(LLVMBuilderRef b, LLVMModuleRef mod,
65 LLVMValueRef v_state, LLVMValueRef v_econtext,
67 static LLVMValueRef create_LifetimeEnd(LLVMModuleRef mod);
71 * JIT compile expression.
74 llvm_compile_expr(ExprState *state)
76 PlanState *parent = state->parent;
80 LLVMJitContext *context = NULL;
86 LLVMBasicBlockRef entry;
87 LLVMBasicBlockRef *opblocks;
91 LLVMValueRef v_econtext;
94 LLVMValueRef v_isnullp;
96 /* tmp vars in state */
97 LLVMValueRef v_tmpvaluep;
98 LLVMValueRef v_tmpisnullp;
101 LLVMValueRef v_innerslot;
102 LLVMValueRef v_outerslot;
103 LLVMValueRef v_scanslot;
104 LLVMValueRef v_resultslot;
106 /* nulls/values of slots */
107 LLVMValueRef v_innervalues;
108 LLVMValueRef v_innernulls;
109 LLVMValueRef v_outervalues;
110 LLVMValueRef v_outernulls;
111 LLVMValueRef v_scanvalues;
112 LLVMValueRef v_scannulls;
113 LLVMValueRef v_resultvalues;
114 LLVMValueRef v_resultnulls;
116 /* stuff in econtext */
117 LLVMValueRef v_aggvalues;
118 LLVMValueRef v_aggnulls;
120 instr_time starttime;
123 llvm_enter_fatal_on_oom();
125 /* get or create JIT context */
126 if (parent && parent->state->es_jit)
128 context = (LLVMJitContext *) parent->state->es_jit;
132 context = llvm_create_context(parent->state->es_jit_flags);
136 parent->state->es_jit = &context->base;
141 INSTR_TIME_SET_CURRENT(starttime);
143 mod = llvm_mutable_module(context);
145 b = LLVMCreateBuilder();
147 funcname = llvm_expand_funcname(context, "evalexpr");
149 /* Create the signature and function */
151 LLVMTypeRef param_types[3];
153 param_types[0] = l_ptr(StructExprState); /* state */
154 param_types[1] = l_ptr(StructExprContext); /* econtext */
155 param_types[2] = l_ptr(TypeParamBool); /* isnull */
157 eval_sig = LLVMFunctionType(TypeSizeT,
158 param_types, lengthof(param_types),
161 eval_fn = LLVMAddFunction(mod, funcname, eval_sig);
162 LLVMSetLinkage(eval_fn, LLVMExternalLinkage);
163 LLVMSetVisibility(eval_fn, LLVMDefaultVisibility);
164 llvm_copy_attributes(AttributeTemplate, eval_fn);
166 entry = LLVMAppendBasicBlock(eval_fn, "entry");
169 v_state = LLVMGetParam(eval_fn, 0);
170 v_econtext = LLVMGetParam(eval_fn, 1);
171 v_isnullp = LLVMGetParam(eval_fn, 2);
173 LLVMPositionBuilderAtEnd(b, entry);
175 v_tmpvaluep = LLVMBuildStructGEP(b, v_state,
176 FIELDNO_EXPRSTATE_RESVALUE,
178 v_tmpisnullp = LLVMBuildStructGEP(b, v_state,
179 FIELDNO_EXPRSTATE_RESNULL,
182 /* build global slots */
183 v_scanslot = l_load_struct_gep(b, v_econtext,
184 FIELDNO_EXPRCONTEXT_SCANTUPLE,
186 v_innerslot = l_load_struct_gep(b, v_econtext,
187 FIELDNO_EXPRCONTEXT_INNERTUPLE,
189 v_outerslot = l_load_struct_gep(b, v_econtext,
190 FIELDNO_EXPRCONTEXT_OUTERTUPLE,
192 v_resultslot = l_load_struct_gep(b, v_state,
193 FIELDNO_EXPRSTATE_RESULTSLOT,
196 /* build global values/isnull pointers */
197 v_scanvalues = l_load_struct_gep(b, v_scanslot,
198 FIELDNO_TUPLETABLESLOT_VALUES,
200 v_scannulls = l_load_struct_gep(b, v_scanslot,
201 FIELDNO_TUPLETABLESLOT_ISNULL,
203 v_innervalues = l_load_struct_gep(b, v_innerslot,
204 FIELDNO_TUPLETABLESLOT_VALUES,
206 v_innernulls = l_load_struct_gep(b, v_innerslot,
207 FIELDNO_TUPLETABLESLOT_ISNULL,
209 v_outervalues = l_load_struct_gep(b, v_outerslot,
210 FIELDNO_TUPLETABLESLOT_VALUES,
212 v_outernulls = l_load_struct_gep(b, v_outerslot,
213 FIELDNO_TUPLETABLESLOT_ISNULL,
215 v_resultvalues = l_load_struct_gep(b, v_resultslot,
216 FIELDNO_TUPLETABLESLOT_VALUES,
218 v_resultnulls = l_load_struct_gep(b, v_resultslot,
219 FIELDNO_TUPLETABLESLOT_ISNULL,
222 /* aggvalues/aggnulls */
223 v_aggvalues = l_load_struct_gep(b, v_econtext,
224 FIELDNO_EXPRCONTEXT_AGGVALUES,
225 "v.econtext.aggvalues");
226 v_aggnulls = l_load_struct_gep(b, v_econtext,
227 FIELDNO_EXPRCONTEXT_AGGNULLS,
228 "v.econtext.aggnulls");
230 /* allocate blocks for each op upfront, so we can do jumps easily */
231 opblocks = palloc(sizeof(LLVMBasicBlockRef) * state->steps_len);
232 for (i = 0; i < state->steps_len; i++)
233 opblocks[i] = l_bb_append_v(eval_fn, "b.op.%d.start", i);
235 /* jump from entry to first block */
236 LLVMBuildBr(b, opblocks[0]);
238 for (i = 0; i < state->steps_len; i++)
242 LLVMValueRef v_resvaluep;
243 LLVMValueRef v_resnullp;
245 LLVMPositionBuilderAtEnd(b, opblocks[i]);
247 op = &state->steps[i];
248 opcode = ExecEvalStepOp(state, op);
250 v_resvaluep = l_ptr_const(op->resvalue, l_ptr(TypeSizeT));
251 v_resnullp = l_ptr_const(op->resnull, l_ptr(TypeStorageBool));
257 LLVMValueRef v_tmpisnull,
260 v_tmpvalue = LLVMBuildLoad(b, v_tmpvaluep, "");
261 v_tmpisnull = LLVMBuildLoad(b, v_tmpisnullp, "");
263 LLVMBuildTrunc(b, v_tmpisnull, TypeParamBool, "");
265 LLVMBuildStore(b, v_tmpisnull, v_isnullp);
267 LLVMBuildRet(b, v_tmpvalue);
271 case EEOP_INNER_FETCHSOME:
272 case EEOP_OUTER_FETCHSOME:
273 case EEOP_SCAN_FETCHSOME:
275 TupleDesc desc = NULL;
277 LLVMBasicBlockRef b_fetch;
278 LLVMValueRef v_nvalid;
279 LLVMValueRef l_jit_deform = NULL;
280 const TupleTableSlotOps *tts_ops = NULL;
282 b_fetch = l_bb_before_v(opblocks[i + 1],
285 if (op->d.fetch.known_desc)
286 desc = op->d.fetch.known_desc;
288 if (op->d.fetch.fixed)
289 tts_ops = op->d.fetch.kind;
291 if (opcode == EEOP_INNER_FETCHSOME)
292 v_slot = v_innerslot;
293 else if (opcode == EEOP_OUTER_FETCHSOME)
294 v_slot = v_outerslot;
299 * Check if all required attributes are available, or
300 * whether deforming is required.
302 * TODO: skip nvalid check if slot is fixed and known to
306 l_load_struct_gep(b, v_slot,
307 FIELDNO_TUPLETABLESLOT_NVALID,
310 LLVMBuildICmp(b, LLVMIntUGE, v_nvalid,
311 l_int16_const(op->d.fetch.last_var),
313 opblocks[i + 1], b_fetch);
315 LLVMPositionBuilderAtEnd(b, b_fetch);
318 * If the tupledesc of the to-be-deformed tuple is known,
319 * and JITing of deforming is enabled, build deform
320 * function specific to tupledesc and the exact number of
321 * to-be-extracted attributes.
323 if (tts_ops && desc && (context->base.flags & PGJIT_DEFORM))
326 slot_compile_deform(context, desc,
328 op->d.fetch.last_var);
333 LLVMValueRef params[1];
337 LLVMBuildCall(b, l_jit_deform,
338 params, lengthof(params), "");
342 LLVMValueRef params[2];
345 params[1] = l_int32_const(op->d.fetch.last_var);
348 llvm_get_decl(mod, FuncSlotGetsomeattrsInt),
349 params, lengthof(params), "");
352 LLVMBuildBr(b, opblocks[i + 1]);
362 LLVMValueRef v_attnum;
363 LLVMValueRef v_values;
364 LLVMValueRef v_nulls;
366 if (opcode == EEOP_INNER_VAR)
368 v_values = v_innervalues;
369 v_nulls = v_innernulls;
371 else if (opcode == EEOP_OUTER_VAR)
373 v_values = v_outervalues;
374 v_nulls = v_outernulls;
378 v_values = v_scanvalues;
379 v_nulls = v_scannulls;
382 v_attnum = l_int32_const(op->d.var.attnum);
383 value = l_load_gep1(b, v_values, v_attnum, "");
384 isnull = l_load_gep1(b, v_nulls, v_attnum, "");
385 LLVMBuildStore(b, value, v_resvaluep);
386 LLVMBuildStore(b, isnull, v_resnullp);
388 LLVMBuildBr(b, opblocks[i + 1]);
392 case EEOP_INNER_SYSVAR:
393 case EEOP_OUTER_SYSVAR:
394 case EEOP_SCAN_SYSVAR:
397 LLVMValueRef v_params[4];
399 if (opcode == EEOP_INNER_SYSVAR)
400 v_slot = v_innerslot;
401 else if (opcode == EEOP_OUTER_SYSVAR)
402 v_slot = v_outerslot;
406 v_params[0] = v_state;
407 v_params[1] = l_ptr_const(op, l_ptr(StructExprEvalStep));
408 v_params[2] = v_econtext;
409 v_params[3] = v_slot;
412 llvm_get_decl(mod, FuncExecEvalSysVar),
413 v_params, lengthof(v_params), "");
415 LLVMBuildBr(b, opblocks[i + 1]);
420 build_EvalXFunc(b, mod, "ExecEvalWholeRowVar",
421 v_state, v_econtext, op);
422 LLVMBuildBr(b, opblocks[i + 1]);
425 case EEOP_ASSIGN_INNER_VAR:
426 case EEOP_ASSIGN_OUTER_VAR:
427 case EEOP_ASSIGN_SCAN_VAR:
429 LLVMValueRef v_value,
431 LLVMValueRef v_rvaluep,
433 LLVMValueRef v_attnum,
435 LLVMValueRef v_values;
436 LLVMValueRef v_nulls;
438 if (opcode == EEOP_ASSIGN_INNER_VAR)
440 v_values = v_innervalues;
441 v_nulls = v_innernulls;
443 else if (opcode == EEOP_ASSIGN_OUTER_VAR)
445 v_values = v_outervalues;
446 v_nulls = v_outernulls;
450 v_values = v_scanvalues;
451 v_nulls = v_scannulls;
455 v_attnum = l_int32_const(op->d.assign_var.attnum);
456 v_value = l_load_gep1(b, v_values, v_attnum, "");
457 v_isnull = l_load_gep1(b, v_nulls, v_attnum, "");
459 /* compute addresses of targets */
460 v_resultnum = l_int32_const(op->d.assign_var.resultnum);
461 v_rvaluep = LLVMBuildGEP(b, v_resultvalues,
462 &v_resultnum, 1, "");
463 v_risnullp = LLVMBuildGEP(b, v_resultnulls,
464 &v_resultnum, 1, "");
467 LLVMBuildStore(b, v_value, v_rvaluep);
468 LLVMBuildStore(b, v_isnull, v_risnullp);
470 LLVMBuildBr(b, opblocks[i + 1]);
474 case EEOP_ASSIGN_TMP:
476 LLVMValueRef v_value,
478 LLVMValueRef v_rvaluep,
480 LLVMValueRef v_resultnum;
481 size_t resultnum = op->d.assign_tmp.resultnum;
484 v_value = LLVMBuildLoad(b, v_tmpvaluep, "");
485 v_isnull = LLVMBuildLoad(b, v_tmpisnullp, "");
487 /* compute addresses of targets */
488 v_resultnum = l_int32_const(resultnum);
490 LLVMBuildGEP(b, v_resultvalues, &v_resultnum, 1, "");
492 LLVMBuildGEP(b, v_resultnulls, &v_resultnum, 1, "");
495 LLVMBuildStore(b, v_value, v_rvaluep);
496 LLVMBuildStore(b, v_isnull, v_risnullp);
498 LLVMBuildBr(b, opblocks[i + 1]);
502 case EEOP_ASSIGN_TMP_MAKE_RO:
504 LLVMBasicBlockRef b_notnull;
505 LLVMValueRef v_params[1];
507 LLVMValueRef v_value,
509 LLVMValueRef v_rvaluep,
511 LLVMValueRef v_resultnum;
512 size_t resultnum = op->d.assign_tmp.resultnum;
514 b_notnull = l_bb_before_v(opblocks[i + 1],
515 "op.%d.assign_tmp.notnull", i);
518 v_value = LLVMBuildLoad(b, v_tmpvaluep, "");
519 v_isnull = LLVMBuildLoad(b, v_tmpisnullp, "");
521 /* compute addresses of targets */
522 v_resultnum = l_int32_const(resultnum);
523 v_rvaluep = LLVMBuildGEP(b, v_resultvalues,
524 &v_resultnum, 1, "");
525 v_risnullp = LLVMBuildGEP(b, v_resultnulls,
526 &v_resultnum, 1, "");
529 LLVMBuildStore(b, v_isnull, v_risnullp);
531 /* check if value is NULL */
533 LLVMBuildICmp(b, LLVMIntEQ, v_isnull,
534 l_sbool_const(0), ""),
535 b_notnull, opblocks[i + 1]);
537 /* if value is not null, convert to RO datum */
538 LLVMPositionBuilderAtEnd(b, b_notnull);
539 v_params[0] = v_value;
542 llvm_get_decl(mod, FuncMakeExpandedObjectReadOnlyInternal),
543 v_params, lengthof(v_params), "");
546 LLVMBuildStore(b, v_ret, v_rvaluep);
548 LLVMBuildBr(b, opblocks[i + 1]);
554 LLVMValueRef v_constvalue,
557 v_constvalue = l_sizet_const(op->d.constval.value);
558 v_constnull = l_sbool_const(op->d.constval.isnull);
560 LLVMBuildStore(b, v_constvalue, v_resvaluep);
561 LLVMBuildStore(b, v_constnull, v_resnullp);
563 LLVMBuildBr(b, opblocks[i + 1]);
567 case EEOP_FUNCEXPR_STRICT:
569 FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
570 LLVMBasicBlockRef b_nonull;
572 LLVMValueRef v_fcinfo;
573 LLVMBasicBlockRef *b_checkargnulls;
576 * Block for the actual function call, if args are
579 b_nonull = l_bb_before_v(opblocks[i + 1],
580 "b.%d.no-null-args", i);
582 /* should make sure they're optimized beforehand */
583 if (op->d.func.nargs == 0)
584 elog(ERROR, "argumentless strict functions are pointless");
587 l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
590 * set resnull to true, if the function is actually
591 * called, it'll be reset
593 LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
595 /* create blocks for checking args, one for each */
597 palloc(sizeof(LLVMBasicBlockRef *) * op->d.func.nargs);
598 for (argno = 0; argno < op->d.func.nargs; argno++)
599 b_checkargnulls[argno] =
600 l_bb_before_v(b_nonull, "b.%d.isnull.%d", i, argno);
602 /* jump to check of first argument */
603 LLVMBuildBr(b, b_checkargnulls[0]);
605 /* check each arg for NULLness */
606 for (argno = 0; argno < op->d.func.nargs; argno++)
608 LLVMValueRef v_argisnull;
609 LLVMBasicBlockRef b_argnotnull;
611 LLVMPositionBuilderAtEnd(b, b_checkargnulls[argno]);
613 /* compute block to jump to if argument is not null */
614 if (argno + 1 == op->d.func.nargs)
615 b_argnotnull = b_nonull;
617 b_argnotnull = b_checkargnulls[argno + 1];
619 /* and finally load & check NULLness of arg */
620 v_argisnull = l_funcnull(b, v_fcinfo, argno);
622 LLVMBuildICmp(b, LLVMIntEQ,
630 LLVMPositionBuilderAtEnd(b, b_nonull);
636 FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
637 LLVMValueRef v_fcinfo_isnull;
638 LLVMValueRef v_retval;
640 v_retval = BuildV1Call(context, b, mod, fcinfo,
642 LLVMBuildStore(b, v_retval, v_resvaluep);
643 LLVMBuildStore(b, v_fcinfo_isnull, v_resnullp);
645 LLVMBuildBr(b, opblocks[i + 1]);
649 case EEOP_FUNCEXPR_FUSAGE:
650 build_EvalXFunc(b, mod, "ExecEvalFuncExprFusage",
651 v_state, v_econtext, op);
652 LLVMBuildBr(b, opblocks[i + 1]);
656 case EEOP_FUNCEXPR_STRICT_FUSAGE:
657 build_EvalXFunc(b, mod, "ExecEvalFuncExprStrictFusage",
658 v_state, v_econtext, op);
659 LLVMBuildBr(b, opblocks[i + 1]);
662 case EEOP_BOOL_AND_STEP_FIRST:
664 LLVMValueRef v_boolanynullp;
666 v_boolanynullp = l_ptr_const(op->d.boolexpr.anynull,
667 l_ptr(TypeStorageBool));
668 LLVMBuildStore(b, l_sbool_const(0), v_boolanynullp);
674 * Treat them the same for now, optimizer can remove
675 * redundancy. Could be worthwhile to optimize during emission
678 case EEOP_BOOL_AND_STEP_LAST:
679 case EEOP_BOOL_AND_STEP:
681 LLVMValueRef v_boolvalue;
682 LLVMValueRef v_boolnull;
683 LLVMValueRef v_boolanynullp,
685 LLVMBasicBlockRef b_boolisnull;
686 LLVMBasicBlockRef b_boolcheckfalse;
687 LLVMBasicBlockRef b_boolisfalse;
688 LLVMBasicBlockRef b_boolcont;
689 LLVMBasicBlockRef b_boolisanynull;
691 b_boolisnull = l_bb_before_v(opblocks[i + 1],
692 "b.%d.boolisnull", i);
693 b_boolcheckfalse = l_bb_before_v(opblocks[i + 1],
694 "b.%d.boolcheckfalse", i);
695 b_boolisfalse = l_bb_before_v(opblocks[i + 1],
696 "b.%d.boolisfalse", i);
697 b_boolisanynull = l_bb_before_v(opblocks[i + 1],
698 "b.%d.boolisanynull", i);
699 b_boolcont = l_bb_before_v(opblocks[i + 1],
702 v_boolanynullp = l_ptr_const(op->d.boolexpr.anynull,
703 l_ptr(TypeStorageBool));
705 v_boolnull = LLVMBuildLoad(b, v_resnullp, "");
706 v_boolvalue = LLVMBuildLoad(b, v_resvaluep, "");
708 /* set resnull to boolnull */
709 LLVMBuildStore(b, v_boolnull, v_resnullp);
710 /* set revalue to boolvalue */
711 LLVMBuildStore(b, v_boolvalue, v_resvaluep);
713 /* check if current input is NULL */
715 LLVMBuildICmp(b, LLVMIntEQ, v_boolnull,
716 l_sbool_const(1), ""),
720 /* build block that sets anynull */
721 LLVMPositionBuilderAtEnd(b, b_boolisnull);
722 /* set boolanynull to true */
723 LLVMBuildStore(b, l_sbool_const(1), v_boolanynullp);
724 /* and jump to next block */
725 LLVMBuildBr(b, b_boolcont);
727 /* build block checking for false */
728 LLVMPositionBuilderAtEnd(b, b_boolcheckfalse);
730 LLVMBuildICmp(b, LLVMIntEQ, v_boolvalue,
731 l_sizet_const(0), ""),
736 * Build block handling FALSE. Value is false, so short
739 LLVMPositionBuilderAtEnd(b, b_boolisfalse);
740 /* result is already set to FALSE, need not change it */
741 /* and jump to the end of the AND expression */
742 LLVMBuildBr(b, opblocks[op->d.boolexpr.jumpdone]);
744 /* Build block that continues if bool is TRUE. */
745 LLVMPositionBuilderAtEnd(b, b_boolcont);
747 v_boolanynull = LLVMBuildLoad(b, v_boolanynullp, "");
749 /* set value to NULL if any previous values were NULL */
751 LLVMBuildICmp(b, LLVMIntEQ, v_boolanynull,
752 l_sbool_const(0), ""),
753 opblocks[i + 1], b_boolisanynull);
755 LLVMPositionBuilderAtEnd(b, b_boolisanynull);
756 /* set resnull to true */
757 LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
759 LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
761 LLVMBuildBr(b, opblocks[i + 1]);
764 case EEOP_BOOL_OR_STEP_FIRST:
766 LLVMValueRef v_boolanynullp;
768 v_boolanynullp = l_ptr_const(op->d.boolexpr.anynull,
769 l_ptr(TypeStorageBool));
770 LLVMBuildStore(b, l_sbool_const(0), v_boolanynullp);
775 * Treat them the same for now, optimizer can remove
776 * redundancy. Could be worthwhile to optimize during emission
779 case EEOP_BOOL_OR_STEP_LAST:
780 case EEOP_BOOL_OR_STEP:
782 LLVMValueRef v_boolvalue;
783 LLVMValueRef v_boolnull;
784 LLVMValueRef v_boolanynullp,
787 LLVMBasicBlockRef b_boolisnull;
788 LLVMBasicBlockRef b_boolchecktrue;
789 LLVMBasicBlockRef b_boolistrue;
790 LLVMBasicBlockRef b_boolcont;
791 LLVMBasicBlockRef b_boolisanynull;
793 b_boolisnull = l_bb_before_v(opblocks[i + 1],
794 "b.%d.boolisnull", i);
795 b_boolchecktrue = l_bb_before_v(opblocks[i + 1],
796 "b.%d.boolchecktrue", i);
797 b_boolistrue = l_bb_before_v(opblocks[i + 1],
798 "b.%d.boolistrue", i);
799 b_boolisanynull = l_bb_before_v(opblocks[i + 1],
800 "b.%d.boolisanynull", i);
801 b_boolcont = l_bb_before_v(opblocks[i + 1],
804 v_boolanynullp = l_ptr_const(op->d.boolexpr.anynull,
805 l_ptr(TypeStorageBool));
807 v_boolnull = LLVMBuildLoad(b, v_resnullp, "");
808 v_boolvalue = LLVMBuildLoad(b, v_resvaluep, "");
810 /* set resnull to boolnull */
811 LLVMBuildStore(b, v_boolnull, v_resnullp);
812 /* set revalue to boolvalue */
813 LLVMBuildStore(b, v_boolvalue, v_resvaluep);
816 LLVMBuildICmp(b, LLVMIntEQ, v_boolnull,
817 l_sbool_const(1), ""),
821 /* build block that sets anynull */
822 LLVMPositionBuilderAtEnd(b, b_boolisnull);
823 /* set boolanynull to true */
824 LLVMBuildStore(b, l_sbool_const(1), v_boolanynullp);
825 /* and jump to next block */
826 LLVMBuildBr(b, b_boolcont);
828 /* build block checking for true */
829 LLVMPositionBuilderAtEnd(b, b_boolchecktrue);
831 LLVMBuildICmp(b, LLVMIntEQ, v_boolvalue,
832 l_sizet_const(1), ""),
837 * Build block handling True. Value is true, so short
840 LLVMPositionBuilderAtEnd(b, b_boolistrue);
841 /* result is already set to TRUE, need not change it */
842 /* and jump to the end of the OR expression */
843 LLVMBuildBr(b, opblocks[op->d.boolexpr.jumpdone]);
845 /* build block that continues if bool is FALSE */
846 LLVMPositionBuilderAtEnd(b, b_boolcont);
848 v_boolanynull = LLVMBuildLoad(b, v_boolanynullp, "");
850 /* set value to NULL if any previous values were NULL */
852 LLVMBuildICmp(b, LLVMIntEQ, v_boolanynull,
853 l_sbool_const(0), ""),
854 opblocks[i + 1], b_boolisanynull);
856 LLVMPositionBuilderAtEnd(b, b_boolisanynull);
857 /* set resnull to true */
858 LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
860 LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
862 LLVMBuildBr(b, opblocks[i + 1]);
866 case EEOP_BOOL_NOT_STEP:
868 LLVMValueRef v_boolvalue;
869 LLVMValueRef v_boolnull;
870 LLVMValueRef v_negbool;
872 v_boolnull = LLVMBuildLoad(b, v_resnullp, "");
873 v_boolvalue = LLVMBuildLoad(b, v_resvaluep, "");
875 v_negbool = LLVMBuildZExt(b,
876 LLVMBuildICmp(b, LLVMIntEQ,
881 /* set resnull to boolnull */
882 LLVMBuildStore(b, v_boolnull, v_resnullp);
883 /* set revalue to !boolvalue */
884 LLVMBuildStore(b, v_negbool, v_resvaluep);
886 LLVMBuildBr(b, opblocks[i + 1]);
892 LLVMValueRef v_resnull;
893 LLVMValueRef v_resvalue;
894 LLVMValueRef v_nullorfalse;
895 LLVMBasicBlockRef b_qualfail;
897 b_qualfail = l_bb_before_v(opblocks[i + 1],
898 "op.%d.qualfail", i);
900 v_resvalue = LLVMBuildLoad(b, v_resvaluep, "");
901 v_resnull = LLVMBuildLoad(b, v_resnullp, "");
905 LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
906 l_sbool_const(1), ""),
907 LLVMBuildICmp(b, LLVMIntEQ, v_resvalue,
908 l_sizet_const(0), ""),
916 /* build block handling NULL or false */
917 LLVMPositionBuilderAtEnd(b, b_qualfail);
918 /* set resnull to false */
919 LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
920 /* set resvalue to false */
921 LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
923 LLVMBuildBr(b, opblocks[op->d.qualexpr.jumpdone]);
929 LLVMBuildBr(b, opblocks[op->d.jump.jumpdone]);
933 case EEOP_JUMP_IF_NULL:
935 LLVMValueRef v_resnull;
937 /* Transfer control if current result is null */
939 v_resnull = LLVMBuildLoad(b, v_resnullp, "");
942 LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
943 l_sbool_const(1), ""),
944 opblocks[op->d.jump.jumpdone],
949 case EEOP_JUMP_IF_NOT_NULL:
951 LLVMValueRef v_resnull;
953 /* Transfer control if current result is non-null */
955 v_resnull = LLVMBuildLoad(b, v_resnullp, "");
958 LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
959 l_sbool_const(0), ""),
960 opblocks[op->d.jump.jumpdone],
966 case EEOP_JUMP_IF_NOT_TRUE:
968 LLVMValueRef v_resnull;
969 LLVMValueRef v_resvalue;
970 LLVMValueRef v_nullorfalse;
972 /* Transfer control if current result is null or false */
974 v_resvalue = LLVMBuildLoad(b, v_resvaluep, "");
975 v_resnull = LLVMBuildLoad(b, v_resnullp, "");
979 LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
980 l_sbool_const(1), ""),
981 LLVMBuildICmp(b, LLVMIntEQ, v_resvalue,
982 l_sizet_const(0), ""),
987 opblocks[op->d.jump.jumpdone],
992 case EEOP_NULLTEST_ISNULL:
994 LLVMValueRef v_resnull = LLVMBuildLoad(b, v_resnullp, "");
995 LLVMValueRef v_resvalue;
999 LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
1000 l_sbool_const(1), ""),
1004 LLVMBuildStore(b, v_resvalue, v_resvaluep);
1005 LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1007 LLVMBuildBr(b, opblocks[i + 1]);
1011 case EEOP_NULLTEST_ISNOTNULL:
1013 LLVMValueRef v_resnull = LLVMBuildLoad(b, v_resnullp, "");
1014 LLVMValueRef v_resvalue;
1018 LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
1019 l_sbool_const(1), ""),
1023 LLVMBuildStore(b, v_resvalue, v_resvaluep);
1024 LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1026 LLVMBuildBr(b, opblocks[i + 1]);
1030 case EEOP_NULLTEST_ROWISNULL:
1031 build_EvalXFunc(b, mod, "ExecEvalRowNull",
1032 v_state, v_econtext, op);
1033 LLVMBuildBr(b, opblocks[i + 1]);
1036 case EEOP_NULLTEST_ROWISNOTNULL:
1037 build_EvalXFunc(b, mod, "ExecEvalRowNotNull",
1038 v_state, v_econtext, op);
1039 LLVMBuildBr(b, opblocks[i + 1]);
1042 case EEOP_BOOLTEST_IS_TRUE:
1043 case EEOP_BOOLTEST_IS_NOT_FALSE:
1044 case EEOP_BOOLTEST_IS_FALSE:
1045 case EEOP_BOOLTEST_IS_NOT_TRUE:
1047 LLVMBasicBlockRef b_isnull,
1049 LLVMValueRef v_resnull = LLVMBuildLoad(b, v_resnullp, "");
1051 b_isnull = l_bb_before_v(opblocks[i + 1],
1053 b_notnull = l_bb_before_v(opblocks[i + 1],
1054 "op.%d.isnotnull", i);
1056 /* check if value is NULL */
1058 LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
1059 l_sbool_const(1), ""),
1060 b_isnull, b_notnull);
1062 /* if value is NULL, return false */
1063 LLVMPositionBuilderAtEnd(b, b_isnull);
1065 /* result is not null */
1066 LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1068 if (opcode == EEOP_BOOLTEST_IS_TRUE ||
1069 opcode == EEOP_BOOLTEST_IS_FALSE)
1071 LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
1075 LLVMBuildStore(b, l_sizet_const(1), v_resvaluep);
1078 LLVMBuildBr(b, opblocks[i + 1]);
1080 LLVMPositionBuilderAtEnd(b, b_notnull);
1082 if (opcode == EEOP_BOOLTEST_IS_TRUE ||
1083 opcode == EEOP_BOOLTEST_IS_NOT_FALSE)
1086 * if value is not null NULL, return value (already
1092 LLVMValueRef v_value =
1093 LLVMBuildLoad(b, v_resvaluep, "");
1095 v_value = LLVMBuildZExt(b,
1096 LLVMBuildICmp(b, LLVMIntEQ,
1101 LLVMBuildStore(b, v_value, v_resvaluep);
1103 LLVMBuildBr(b, opblocks[i + 1]);
1107 case EEOP_PARAM_EXEC:
1108 build_EvalXFunc(b, mod, "ExecEvalParamExec",
1109 v_state, v_econtext, op);
1110 LLVMBuildBr(b, opblocks[i + 1]);
1113 case EEOP_PARAM_EXTERN:
1114 build_EvalXFunc(b, mod, "ExecEvalParamExtern",
1115 v_state, v_econtext, op);
1116 LLVMBuildBr(b, opblocks[i + 1]);
1119 case EEOP_PARAM_CALLBACK:
1121 LLVMTypeRef param_types[3];
1122 LLVMValueRef v_params[3];
1123 LLVMTypeRef v_functype;
1124 LLVMValueRef v_func;
1126 param_types[0] = l_ptr(StructExprState);
1127 param_types[1] = l_ptr(TypeSizeT);
1128 param_types[2] = l_ptr(StructExprContext);
1130 v_functype = LLVMFunctionType(LLVMVoidType(),
1132 lengthof(param_types),
1134 v_func = l_ptr_const(op->d.cparam.paramfunc,
1137 v_params[0] = v_state;
1138 v_params[1] = l_ptr_const(op, l_ptr(TypeSizeT));
1139 v_params[2] = v_econtext;
1142 v_params, lengthof(v_params), "");
1144 LLVMBuildBr(b, opblocks[i + 1]);
1148 case EEOP_ARRAYREF_OLD:
1149 build_EvalXFunc(b, mod, "ExecEvalArrayRefOld",
1150 v_state, v_econtext, op);
1151 LLVMBuildBr(b, opblocks[i + 1]);
1154 case EEOP_ARRAYREF_ASSIGN:
1155 build_EvalXFunc(b, mod, "ExecEvalArrayRefAssign",
1156 v_state, v_econtext, op);
1157 LLVMBuildBr(b, opblocks[i + 1]);
1160 case EEOP_ARRAYREF_FETCH:
1161 build_EvalXFunc(b, mod, "ExecEvalArrayRefFetch",
1162 v_state, v_econtext, op);
1163 LLVMBuildBr(b, opblocks[i + 1]);
1166 case EEOP_CASE_TESTVAL:
1168 LLVMBasicBlockRef b_avail,
1170 LLVMValueRef v_casevaluep,
1172 LLVMValueRef v_casenullp,
1174 LLVMValueRef v_casevaluenull;
1176 b_avail = l_bb_before_v(opblocks[i + 1],
1178 b_notavail = l_bb_before_v(opblocks[i + 1],
1179 "op.%d.notavail", i);
1181 v_casevaluep = l_ptr_const(op->d.casetest.value,
1183 v_casenullp = l_ptr_const(op->d.casetest.isnull,
1184 l_ptr(TypeStorageBool));
1187 LLVMBuildICmp(b, LLVMIntEQ,
1188 LLVMBuildPtrToInt(b, v_casevaluep,
1190 l_sizet_const(0), "");
1191 LLVMBuildCondBr(b, v_casevaluenull, b_notavail, b_avail);
1193 /* if casetest != NULL */
1194 LLVMPositionBuilderAtEnd(b, b_avail);
1195 v_casevalue = LLVMBuildLoad(b, v_casevaluep, "");
1196 v_casenull = LLVMBuildLoad(b, v_casenullp, "");
1197 LLVMBuildStore(b, v_casevalue, v_resvaluep);
1198 LLVMBuildStore(b, v_casenull, v_resnullp);
1199 LLVMBuildBr(b, opblocks[i + 1]);
1201 /* if casetest == NULL */
1202 LLVMPositionBuilderAtEnd(b, b_notavail);
1204 l_load_struct_gep(b, v_econtext,
1205 FIELDNO_EXPRCONTEXT_CASEDATUM, "");
1207 l_load_struct_gep(b, v_econtext,
1208 FIELDNO_EXPRCONTEXT_CASENULL, "");
1209 LLVMBuildStore(b, v_casevalue, v_resvaluep);
1210 LLVMBuildStore(b, v_casenull, v_resnullp);
1212 LLVMBuildBr(b, opblocks[i + 1]);
1216 case EEOP_MAKE_READONLY:
1218 LLVMBasicBlockRef b_notnull;
1219 LLVMValueRef v_params[1];
1221 LLVMValueRef v_nullp;
1222 LLVMValueRef v_valuep;
1223 LLVMValueRef v_null;
1224 LLVMValueRef v_value;
1226 b_notnull = l_bb_before_v(opblocks[i + 1],
1227 "op.%d.readonly.notnull", i);
1229 v_nullp = l_ptr_const(op->d.make_readonly.isnull,
1230 l_ptr(TypeStorageBool));
1232 v_null = LLVMBuildLoad(b, v_nullp, "");
1234 /* store null isnull value in result */
1235 LLVMBuildStore(b, v_null, v_resnullp);
1237 /* check if value is NULL */
1239 LLVMBuildICmp(b, LLVMIntEQ, v_null,
1240 l_sbool_const(1), ""),
1241 opblocks[i + 1], b_notnull);
1243 /* if value is not null, convert to RO datum */
1244 LLVMPositionBuilderAtEnd(b, b_notnull);
1246 v_valuep = l_ptr_const(op->d.make_readonly.value,
1249 v_value = LLVMBuildLoad(b, v_valuep, "");
1251 v_params[0] = v_value;
1254 llvm_get_decl(mod, FuncMakeExpandedObjectReadOnlyInternal),
1255 v_params, lengthof(v_params), "");
1256 LLVMBuildStore(b, v_ret, v_resvaluep);
1258 LLVMBuildBr(b, opblocks[i + 1]);
1264 FunctionCallInfo fcinfo_out,
1266 LLVMValueRef v_fcinfo_out,
1268 LLVMValueRef v_fn_addr_out,
1270 LLVMValueRef v_fcinfo_in_isnullp;
1271 LLVMValueRef v_retval;
1272 LLVMValueRef v_resvalue;
1273 LLVMValueRef v_resnull;
1275 LLVMValueRef v_output_skip;
1276 LLVMValueRef v_output;
1278 LLVMBasicBlockRef b_skipoutput;
1279 LLVMBasicBlockRef b_calloutput;
1280 LLVMBasicBlockRef b_input;
1281 LLVMBasicBlockRef b_inputcall;
1283 fcinfo_out = op->d.iocoerce.fcinfo_data_out;
1284 fcinfo_in = op->d.iocoerce.fcinfo_data_in;
1286 b_skipoutput = l_bb_before_v(opblocks[i + 1],
1287 "op.%d.skipoutputnull", i);
1288 b_calloutput = l_bb_before_v(opblocks[i + 1],
1289 "op.%d.calloutput", i);
1290 b_input = l_bb_before_v(opblocks[i + 1],
1292 b_inputcall = l_bb_before_v(opblocks[i + 1],
1293 "op.%d.inputcall", i);
1295 v_fcinfo_out = l_ptr_const(fcinfo_out, l_ptr(StructFunctionCallInfoData));
1296 v_fcinfo_in = l_ptr_const(fcinfo_in, l_ptr(StructFunctionCallInfoData));
1297 v_fn_addr_out = l_ptr_const(fcinfo_out->flinfo->fn_addr, TypePGFunction);
1298 v_fn_addr_in = l_ptr_const(fcinfo_in->flinfo->fn_addr, TypePGFunction);
1300 v_fcinfo_in_isnullp =
1301 LLVMBuildStructGEP(b, v_fcinfo_in,
1302 FIELDNO_FUNCTIONCALLINFODATA_ISNULL,
1303 "v_fcinfo_in_isnull");
1305 /* output functions are not called on nulls */
1306 v_resnull = LLVMBuildLoad(b, v_resnullp, "");
1308 LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
1309 l_sbool_const(1), ""),
1313 LLVMPositionBuilderAtEnd(b, b_skipoutput);
1314 v_output_skip = l_sizet_const(0);
1315 LLVMBuildBr(b, b_input);
1317 LLVMPositionBuilderAtEnd(b, b_calloutput);
1318 v_resvalue = LLVMBuildLoad(b, v_resvaluep, "");
1323 l_funcvaluep(b, v_fcinfo_out, 0));
1326 l_funcnullp(b, v_fcinfo_out, 0));
1327 /* and call output function (can never return NULL) */
1328 v_output = LLVMBuildCall(b, v_fn_addr_out, &v_fcinfo_out,
1329 1, "funccall_coerce_out");
1330 LLVMBuildBr(b, b_input);
1332 /* build block handling input function call */
1333 LLVMPositionBuilderAtEnd(b, b_input);
1335 /* phi between resnull and output function call branches */
1337 LLVMValueRef incoming_values[2];
1338 LLVMBasicBlockRef incoming_blocks[2];
1340 incoming_values[0] = v_output_skip;
1341 incoming_blocks[0] = b_skipoutput;
1343 incoming_values[1] = v_output;
1344 incoming_blocks[1] = b_calloutput;
1346 v_output = LLVMBuildPhi(b, TypeSizeT, "output");
1347 LLVMAddIncoming(v_output,
1348 incoming_values, incoming_blocks,
1349 lengthof(incoming_blocks));
1353 * If input function is strict, skip if input string is
1356 if (op->d.iocoerce.finfo_in->fn_strict)
1359 LLVMBuildICmp(b, LLVMIntEQ, v_output,
1360 l_sizet_const(0), ""),
1366 LLVMBuildBr(b, b_inputcall);
1369 LLVMPositionBuilderAtEnd(b, b_inputcall);
1372 LLVMBuildStore(b, v_output,
1373 l_funcvaluep(b, v_fcinfo_in, 0));
1374 LLVMBuildStore(b, v_resnull,
1375 l_funcnullp(b, v_fcinfo_in, 0));
1377 /* arg1: ioparam: preset in execExpr.c */
1378 /* arg2: typmod: preset in execExpr.c */
1380 /* reset fcinfo_in->isnull */
1381 LLVMBuildStore(b, l_sbool_const(0), v_fcinfo_in_isnullp);
1382 /* and call function */
1383 v_retval = LLVMBuildCall(b, v_fn_addr_in, &v_fcinfo_in, 1,
1384 "funccall_iocoerce_in");
1386 LLVMBuildStore(b, v_retval, v_resvaluep);
1388 LLVMBuildBr(b, opblocks[i + 1]);
1393 case EEOP_NOT_DISTINCT:
1395 FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
1397 LLVMValueRef v_fcinfo;
1398 LLVMValueRef v_fcinfo_isnull;
1400 LLVMValueRef v_argnull0,
1402 LLVMValueRef v_argnull1,
1405 LLVMValueRef v_anyargisnull;
1406 LLVMValueRef v_bothargisnull;
1408 LLVMValueRef v_result;
1410 LLVMBasicBlockRef b_noargnull;
1411 LLVMBasicBlockRef b_checkbothargnull;
1412 LLVMBasicBlockRef b_bothargnull;
1413 LLVMBasicBlockRef b_anyargnull;
1415 b_noargnull = l_bb_before_v(opblocks[i + 1], "op.%d.noargnull", i);
1416 b_checkbothargnull = l_bb_before_v(opblocks[i + 1], "op.%d.checkbothargnull", i);
1417 b_bothargnull = l_bb_before_v(opblocks[i + 1], "op.%d.bothargnull", i);
1418 b_anyargnull = l_bb_before_v(opblocks[i + 1], "op.%d.anyargnull", i);
1420 v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
1422 /* load args[0|1].isnull for both arguments */
1423 v_argnull0 = l_funcnull(b, v_fcinfo, 0);
1424 v_argisnull0 = LLVMBuildICmp(b, LLVMIntEQ, v_argnull0,
1425 l_sbool_const(1), "");
1426 v_argnull1 = l_funcnull(b, v_fcinfo, 1);
1427 v_argisnull1 = LLVMBuildICmp(b, LLVMIntEQ, v_argnull1,
1428 l_sbool_const(1), "");
1430 v_anyargisnull = LLVMBuildOr(b, v_argisnull0, v_argisnull1, "");
1431 v_bothargisnull = LLVMBuildAnd(b, v_argisnull0, v_argisnull1, "");
1434 * Check function arguments for NULLness: If either is
1435 * NULL, we check if both args are NULL. Otherwise call
1438 LLVMBuildCondBr(b, v_anyargisnull, b_checkbothargnull,
1442 * build block checking if any arg is null
1444 LLVMPositionBuilderAtEnd(b, b_checkbothargnull);
1445 LLVMBuildCondBr(b, v_bothargisnull, b_bothargnull,
1449 /* Both NULL? Then is not distinct... */
1450 LLVMPositionBuilderAtEnd(b, b_bothargnull);
1451 LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1452 if (opcode == EEOP_NOT_DISTINCT)
1453 LLVMBuildStore(b, l_sizet_const(1), v_resvaluep);
1455 LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
1457 LLVMBuildBr(b, opblocks[i + 1]);
1459 /* Only one is NULL? Then is distinct... */
1460 LLVMPositionBuilderAtEnd(b, b_anyargnull);
1461 LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1462 if (opcode == EEOP_NOT_DISTINCT)
1463 LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
1465 LLVMBuildStore(b, l_sizet_const(1), v_resvaluep);
1466 LLVMBuildBr(b, opblocks[i + 1]);
1468 /* neither argument is null: compare */
1469 LLVMPositionBuilderAtEnd(b, b_noargnull);
1471 v_result = BuildV1Call(context, b, mod, fcinfo,
1474 if (opcode == EEOP_DISTINCT)
1476 /* Must invert result of "=" */
1479 LLVMBuildICmp(b, LLVMIntEQ,
1481 l_sizet_const(0), ""),
1485 LLVMBuildStore(b, v_fcinfo_isnull, v_resnullp);
1486 LLVMBuildStore(b, v_result, v_resvaluep);
1488 LLVMBuildBr(b, opblocks[i + 1]);
1494 FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
1496 LLVMValueRef v_fcinfo;
1497 LLVMValueRef v_fcinfo_isnull;
1498 LLVMValueRef v_argnull0;
1499 LLVMValueRef v_argnull1;
1500 LLVMValueRef v_anyargisnull;
1501 LLVMValueRef v_arg0;
1502 LLVMBasicBlockRef b_hasnull;
1503 LLVMBasicBlockRef b_nonull;
1504 LLVMBasicBlockRef b_argsequal;
1505 LLVMValueRef v_retval;
1506 LLVMValueRef v_argsequal;
1508 b_hasnull = l_bb_before_v(opblocks[i + 1],
1509 "b.%d.null-args", i);
1510 b_nonull = l_bb_before_v(opblocks[i + 1],
1511 "b.%d.no-null-args", i);
1512 b_argsequal = l_bb_before_v(opblocks[i + 1],
1513 "b.%d.argsequal", i);
1515 v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
1517 /* if either argument is NULL they can't be equal */
1518 v_argnull0 = l_funcnull(b, v_fcinfo, 0);
1519 v_argnull1 = l_funcnull(b, v_fcinfo, 1);
1523 LLVMBuildICmp(b, LLVMIntEQ, v_argnull0,
1524 l_sbool_const(1), ""),
1525 LLVMBuildICmp(b, LLVMIntEQ, v_argnull1,
1526 l_sbool_const(1), ""),
1529 LLVMBuildCondBr(b, v_anyargisnull, b_hasnull, b_nonull);
1531 /* one (or both) of the arguments are null, return arg[0] */
1532 LLVMPositionBuilderAtEnd(b, b_hasnull);
1533 v_arg0 = l_funcvalue(b, v_fcinfo, 0);
1534 LLVMBuildStore(b, v_argnull0, v_resnullp);
1535 LLVMBuildStore(b, v_arg0, v_resvaluep);
1536 LLVMBuildBr(b, opblocks[i + 1]);
1538 /* build block to invoke function and check result */
1539 LLVMPositionBuilderAtEnd(b, b_nonull);
1541 v_retval = BuildV1Call(context, b, mod, fcinfo, &v_fcinfo_isnull);
1544 * If result not null, and arguments are equal return null
1545 * (same result as if there'd been NULLs, hence reuse
1548 v_argsequal = LLVMBuildAnd(b,
1549 LLVMBuildICmp(b, LLVMIntEQ,
1553 LLVMBuildICmp(b, LLVMIntEQ,
1558 LLVMBuildCondBr(b, v_argsequal, b_argsequal, b_hasnull);
1560 /* build block setting result to NULL, if args are equal */
1561 LLVMPositionBuilderAtEnd(b, b_argsequal);
1562 LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
1563 LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
1564 LLVMBuildStore(b, v_retval, v_resvaluep);
1566 LLVMBuildBr(b, opblocks[i + 1]);
1570 case EEOP_SQLVALUEFUNCTION:
1571 build_EvalXFunc(b, mod, "ExecEvalSQLValueFunction",
1572 v_state, v_econtext, op);
1573 LLVMBuildBr(b, opblocks[i + 1]);
1576 case EEOP_CURRENTOFEXPR:
1577 build_EvalXFunc(b, mod, "ExecEvalCurrentOfExpr",
1578 v_state, v_econtext, op);
1579 LLVMBuildBr(b, opblocks[i + 1]);
1582 case EEOP_NEXTVALUEEXPR:
1583 build_EvalXFunc(b, mod, "ExecEvalNextValueExpr",
1584 v_state, v_econtext, op);
1585 LLVMBuildBr(b, opblocks[i + 1]);
1588 case EEOP_ARRAYEXPR:
1589 build_EvalXFunc(b, mod, "ExecEvalArrayExpr",
1590 v_state, v_econtext, op);
1591 LLVMBuildBr(b, opblocks[i + 1]);
1594 case EEOP_ARRAYCOERCE:
1595 build_EvalXFunc(b, mod, "ExecEvalArrayCoerce",
1596 v_state, v_econtext, op);
1597 LLVMBuildBr(b, opblocks[i + 1]);
1601 build_EvalXFunc(b, mod, "ExecEvalRow",
1602 v_state, v_econtext, op);
1603 LLVMBuildBr(b, opblocks[i + 1]);
1606 case EEOP_ROWCOMPARE_STEP:
1608 FunctionCallInfo fcinfo = op->d.rowcompare_step.fcinfo_data;
1609 LLVMValueRef v_fcinfo_isnull;
1610 LLVMBasicBlockRef b_null;
1611 LLVMBasicBlockRef b_compare;
1612 LLVMBasicBlockRef b_compare_result;
1614 LLVMValueRef v_retval;
1616 b_null = l_bb_before_v(opblocks[i + 1],
1617 "op.%d.row-null", i);
1618 b_compare = l_bb_before_v(opblocks[i + 1],
1619 "op.%d.row-compare", i);
1621 l_bb_before_v(opblocks[i + 1],
1622 "op.%d.row-compare-result",
1626 * If function is strict, and either arg is null, we're
1629 if (op->d.rowcompare_step.finfo->fn_strict)
1631 LLVMValueRef v_fcinfo;
1632 LLVMValueRef v_argnull0;
1633 LLVMValueRef v_argnull1;
1634 LLVMValueRef v_anyargisnull;
1636 v_fcinfo = l_ptr_const(fcinfo,
1637 l_ptr(StructFunctionCallInfoData));
1639 v_argnull0 = l_funcnull(b, v_fcinfo, 0);
1640 v_argnull1 = l_funcnull(b, v_fcinfo, 1);
1649 LLVMBuildICmp(b, LLVMIntEQ,
1651 l_sbool_const(1), ""),
1654 LLVMBuildCondBr(b, v_anyargisnull, b_null, b_compare);
1658 LLVMBuildBr(b, b_compare);
1661 /* build block invoking comparison function */
1662 LLVMPositionBuilderAtEnd(b, b_compare);
1665 v_retval = BuildV1Call(context, b, mod, fcinfo,
1667 LLVMBuildStore(b, v_retval, v_resvaluep);
1669 /* if result of function is NULL, force NULL result */
1679 /* build block analyzing the !NULL comparator result */
1680 LLVMPositionBuilderAtEnd(b, b_compare_result);
1682 /* if results equal, compare next, otherwise done */
1687 l_sizet_const(0), ""),
1689 opblocks[op->d.rowcompare_step.jumpdone]);
1692 * Build block handling NULL input or NULL comparator
1695 LLVMPositionBuilderAtEnd(b, b_null);
1696 LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
1697 LLVMBuildBr(b, opblocks[op->d.rowcompare_step.jumpnull]);
1702 case EEOP_ROWCOMPARE_FINAL:
1704 RowCompareType rctype = op->d.rowcompare_final.rctype;
1706 LLVMValueRef v_cmpresult;
1707 LLVMValueRef v_result;
1708 LLVMIntPredicate predicate;
1711 * Btree comparators return 32 bit results, need to be
1712 * careful about sign (used as a 64 bit value it's
1717 LLVMBuildLoad(b, v_resvaluep, ""),
1718 LLVMInt32Type(), "");
1723 predicate = LLVMIntSLT;
1726 predicate = LLVMIntSLE;
1729 predicate = LLVMIntSGT;
1732 predicate = LLVMIntSGE;
1735 /* EQ and NE cases aren't allowed here */
1737 predicate = 0; /* prevent compiler warning */
1741 v_result = LLVMBuildICmp(b,
1746 v_result = LLVMBuildZExt(b, v_result, TypeSizeT, "");
1748 LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1749 LLVMBuildStore(b, v_result, v_resvaluep);
1751 LLVMBuildBr(b, opblocks[i + 1]);
1756 build_EvalXFunc(b, mod, "ExecEvalMinMax",
1757 v_state, v_econtext, op);
1758 LLVMBuildBr(b, opblocks[i + 1]);
1761 case EEOP_FIELDSELECT:
1762 build_EvalXFunc(b, mod, "ExecEvalFieldSelect",
1763 v_state, v_econtext, op);
1764 LLVMBuildBr(b, opblocks[i + 1]);
1767 case EEOP_FIELDSTORE_DEFORM:
1768 build_EvalXFunc(b, mod, "ExecEvalFieldStoreDeForm",
1769 v_state, v_econtext, op);
1770 LLVMBuildBr(b, opblocks[i + 1]);
1773 case EEOP_FIELDSTORE_FORM:
1774 build_EvalXFunc(b, mod, "ExecEvalFieldStoreForm",
1775 v_state, v_econtext, op);
1776 LLVMBuildBr(b, opblocks[i + 1]);
1779 case EEOP_ARRAYREF_SUBSCRIPT:
1782 int jumpdone = op->d.arrayref_subscript.jumpdone;
1783 LLVMValueRef v_params[2];
1786 v_fn = llvm_get_decl(mod, FuncExecEvalArrayRefSubscript);
1788 v_params[0] = v_state;
1789 v_params[1] = l_ptr_const(op, l_ptr(StructExprEvalStep));
1790 v_ret = LLVMBuildCall(b, v_fn,
1791 v_params, lengthof(v_params), "");
1792 v_ret = LLVMBuildZExt(b, v_ret, TypeStorageBool, "");
1795 LLVMBuildICmp(b, LLVMIntEQ, v_ret,
1796 l_sbool_const(1), ""),
1798 opblocks[jumpdone]);
1802 case EEOP_DOMAIN_TESTVAL:
1804 LLVMBasicBlockRef b_avail,
1806 LLVMValueRef v_casevaluep,
1808 LLVMValueRef v_casenullp,
1810 LLVMValueRef v_casevaluenull;
1812 b_avail = l_bb_before_v(opblocks[i + 1],
1814 b_notavail = l_bb_before_v(opblocks[i + 1],
1815 "op.%d.notavail", i);
1817 v_casevaluep = l_ptr_const(op->d.casetest.value,
1819 v_casenullp = l_ptr_const(op->d.casetest.isnull,
1820 l_ptr(TypeStorageBool));
1823 LLVMBuildICmp(b, LLVMIntEQ,
1824 LLVMBuildPtrToInt(b, v_casevaluep,
1826 l_sizet_const(0), "");
1829 b_notavail, b_avail);
1831 /* if casetest != NULL */
1832 LLVMPositionBuilderAtEnd(b, b_avail);
1833 v_casevalue = LLVMBuildLoad(b, v_casevaluep, "");
1834 v_casenull = LLVMBuildLoad(b, v_casenullp, "");
1835 LLVMBuildStore(b, v_casevalue, v_resvaluep);
1836 LLVMBuildStore(b, v_casenull, v_resnullp);
1837 LLVMBuildBr(b, opblocks[i + 1]);
1839 /* if casetest == NULL */
1840 LLVMPositionBuilderAtEnd(b, b_notavail);
1842 l_load_struct_gep(b, v_econtext,
1843 FIELDNO_EXPRCONTEXT_DOMAINDATUM,
1846 l_load_struct_gep(b, v_econtext,
1847 FIELDNO_EXPRCONTEXT_DOMAINNULL,
1849 LLVMBuildStore(b, v_casevalue, v_resvaluep);
1850 LLVMBuildStore(b, v_casenull, v_resnullp);
1852 LLVMBuildBr(b, opblocks[i + 1]);
1856 case EEOP_DOMAIN_NOTNULL:
1857 build_EvalXFunc(b, mod, "ExecEvalConstraintNotNull",
1858 v_state, v_econtext, op);
1859 LLVMBuildBr(b, opblocks[i + 1]);
1862 case EEOP_DOMAIN_CHECK:
1863 build_EvalXFunc(b, mod, "ExecEvalConstraintCheck",
1864 v_state, v_econtext, op);
1865 LLVMBuildBr(b, opblocks[i + 1]);
1868 case EEOP_CONVERT_ROWTYPE:
1869 build_EvalXFunc(b, mod, "ExecEvalConvertRowtype",
1870 v_state, v_econtext, op);
1871 LLVMBuildBr(b, opblocks[i + 1]);
1874 case EEOP_SCALARARRAYOP:
1875 build_EvalXFunc(b, mod, "ExecEvalScalarArrayOp",
1876 v_state, v_econtext, op);
1877 LLVMBuildBr(b, opblocks[i + 1]);
1881 build_EvalXFunc(b, mod, "ExecEvalXmlExpr",
1882 v_state, v_econtext, op);
1883 LLVMBuildBr(b, opblocks[i + 1]);
1888 AggrefExprState *aggref = op->d.aggref.astate;
1889 LLVMValueRef v_aggnop;
1890 LLVMValueRef v_aggno;
1895 * At this point aggref->aggno is not yet set (it's set up
1896 * in ExecInitAgg() after initializing the expression). So
1897 * load it from memory each time round.
1899 v_aggnop = l_ptr_const(&aggref->aggno,
1900 l_ptr(LLVMInt32Type()));
1901 v_aggno = LLVMBuildLoad(b, v_aggnop, "v_aggno");
1903 /* load agg value / null */
1904 value = l_load_gep1(b, v_aggvalues, v_aggno, "aggvalue");
1905 isnull = l_load_gep1(b, v_aggnulls, v_aggno, "aggnull");
1907 /* and store result */
1908 LLVMBuildStore(b, value, v_resvaluep);
1909 LLVMBuildStore(b, isnull, v_resnullp);
1911 LLVMBuildBr(b, opblocks[i + 1]);
1915 case EEOP_GROUPING_FUNC:
1916 build_EvalXFunc(b, mod, "ExecEvalGroupingFunc",
1917 v_state, v_econtext, op);
1918 LLVMBuildBr(b, opblocks[i + 1]);
1921 case EEOP_WINDOW_FUNC:
1923 WindowFuncExprState *wfunc = op->d.window_func.wfstate;
1924 LLVMValueRef v_wfuncnop;
1925 LLVMValueRef v_wfuncno;
1930 * At this point aggref->wfuncno is not yet set (it's set
1931 * up in ExecInitWindowAgg() after initializing the
1932 * expression). So load it from memory each time round.
1934 v_wfuncnop = l_ptr_const(&wfunc->wfuncno,
1935 l_ptr(LLVMInt32Type()));
1936 v_wfuncno = LLVMBuildLoad(b, v_wfuncnop, "v_wfuncno");
1938 /* load window func value / null */
1939 value = l_load_gep1(b, v_aggvalues, v_wfuncno,
1941 isnull = l_load_gep1(b, v_aggnulls, v_wfuncno,
1944 LLVMBuildStore(b, value, v_resvaluep);
1945 LLVMBuildStore(b, isnull, v_resnullp);
1947 LLVMBuildBr(b, opblocks[i + 1]);
1952 build_EvalXFunc(b, mod, "ExecEvalSubPlan",
1953 v_state, v_econtext, op);
1954 LLVMBuildBr(b, opblocks[i + 1]);
1957 case EEOP_ALTERNATIVE_SUBPLAN:
1958 build_EvalXFunc(b, mod, "ExecEvalAlternativeSubPlan",
1959 v_state, v_econtext, op);
1960 LLVMBuildBr(b, opblocks[i + 1]);
1963 case EEOP_AGG_STRICT_DESERIALIZE:
1965 FunctionCallInfo fcinfo = op->d.agg_deserialize.fcinfo_data;
1966 LLVMValueRef v_fcinfo;
1967 LLVMValueRef v_argnull0;
1968 LLVMBasicBlockRef b_deserialize;
1970 b_deserialize = l_bb_before_v(opblocks[i + 1],
1971 "op.%d.deserialize", i);
1973 v_fcinfo = l_ptr_const(fcinfo,
1974 l_ptr(StructFunctionCallInfoData));
1975 v_argnull0 = l_funcnull(b, v_fcinfo, 0);
1983 opblocks[op->d.agg_deserialize.jumpnull],
1985 LLVMPositionBuilderAtEnd(b, b_deserialize);
1989 case EEOP_AGG_DESERIALIZE:
1992 FunctionCallInfo fcinfo;
1994 LLVMValueRef v_retval;
1995 LLVMValueRef v_fcinfo_isnull;
1996 LLVMValueRef v_tmpcontext;
1997 LLVMValueRef v_oldcontext;
1999 aggstate = op->d.agg_deserialize.aggstate;
2000 fcinfo = op->d.agg_deserialize.fcinfo_data;
2003 l_ptr_const(aggstate->tmpcontext->ecxt_per_tuple_memory,
2004 l_ptr(StructMemoryContextData));
2005 v_oldcontext = l_mcxt_switch(mod, b, v_tmpcontext);
2006 v_retval = BuildV1Call(context, b, mod, fcinfo,
2008 l_mcxt_switch(mod, b, v_oldcontext);
2010 LLVMBuildStore(b, v_retval, v_resvaluep);
2011 LLVMBuildStore(b, v_fcinfo_isnull, v_resnullp);
2013 LLVMBuildBr(b, opblocks[i + 1]);
2017 case EEOP_AGG_STRICT_INPUT_CHECK_NULLS:
2018 case EEOP_AGG_STRICT_INPUT_CHECK_ARGS:
2020 int nargs = op->d.agg_strict_input_check.nargs;
2021 NullableDatum *args = op->d.agg_strict_input_check.args;
2022 bool *nulls = op->d.agg_strict_input_check.nulls;
2026 LLVMValueRef v_argsp;
2027 LLVMValueRef v_nullsp;
2028 LLVMBasicBlockRef *b_checknulls;
2032 jumpnull = op->d.agg_strict_input_check.jumpnull;
2033 v_argsp = l_ptr_const(args, l_ptr(StructNullableDatum));
2034 v_nullsp = l_ptr_const(nulls, l_ptr(TypeStorageBool));
2036 /* create blocks for checking args */
2037 b_checknulls = palloc(sizeof(LLVMBasicBlockRef *) * nargs);
2038 for (argno = 0; argno < nargs; argno++)
2040 b_checknulls[argno] =
2041 l_bb_before_v(opblocks[i + 1],
2042 "op.%d.check-null.%d",
2046 LLVMBuildBr(b, b_checknulls[0]);
2048 /* strict function, check for NULL args */
2049 for (argno = 0; argno < nargs; argno++)
2051 LLVMValueRef v_argno = l_int32_const(argno);
2052 LLVMValueRef v_argisnull;
2053 LLVMBasicBlockRef b_argnotnull;
2055 LLVMPositionBuilderAtEnd(b, b_checknulls[argno]);
2057 if (argno + 1 == nargs)
2058 b_argnotnull = opblocks[i + 1];
2060 b_argnotnull = b_checknulls[argno + 1];
2062 if (opcode == EEOP_AGG_STRICT_INPUT_CHECK_NULLS)
2063 v_argisnull = l_load_gep1(b, v_nullsp, v_argno, "");
2066 LLVMValueRef v_argn;
2068 v_argn = LLVMBuildGEP(b, v_argsp, &v_argno, 1, "");
2070 l_load_struct_gep(b, v_argn,
2071 FIELDNO_NULLABLE_DATUM_ISNULL,
2079 l_sbool_const(1), ""),
2087 case EEOP_AGG_INIT_TRANS:
2090 AggStatePerTrans pertrans;
2092 LLVMValueRef v_aggstatep;
2093 LLVMValueRef v_pertransp;
2095 LLVMValueRef v_allpergroupsp;
2097 LLVMValueRef v_pergroupp;
2099 LLVMValueRef v_setoff,
2102 LLVMValueRef v_notransvalue;
2104 LLVMBasicBlockRef b_init;
2106 aggstate = op->d.agg_init_trans.aggstate;
2107 pertrans = op->d.agg_init_trans.pertrans;
2109 v_aggstatep = l_ptr_const(aggstate,
2110 l_ptr(StructAggState));
2111 v_pertransp = l_ptr_const(pertrans,
2112 l_ptr(StructAggStatePerTransData));
2115 * pergroup = &aggstate->all_pergroups
2116 * [op->d.agg_init_trans_check.setoff]
2117 * [op->d.agg_init_trans_check.transno];
2120 l_load_struct_gep(b, v_aggstatep,
2121 FIELDNO_AGGSTATE_ALL_PERGROUPS,
2122 "aggstate.all_pergroups");
2123 v_setoff = l_int32_const(op->d.agg_init_trans.setoff);
2124 v_transno = l_int32_const(op->d.agg_init_trans.transno);
2127 l_load_gep1(b, v_allpergroupsp, v_setoff, ""),
2131 l_load_struct_gep(b, v_pergroupp,
2132 FIELDNO_AGGSTATEPERGROUPDATA_NOTRANSVALUE,
2135 b_init = l_bb_before_v(opblocks[i + 1],
2136 "op.%d.inittrans", i);
2139 LLVMBuildICmp(b, LLVMIntEQ, v_notransvalue,
2140 l_sbool_const(1), ""),
2144 LLVMPositionBuilderAtEnd(b, b_init);
2147 LLVMValueRef params[3];
2148 LLVMValueRef v_curaggcontext;
2149 LLVMValueRef v_current_set;
2150 LLVMValueRef v_aggcontext;
2152 v_aggcontext = l_ptr_const(op->d.agg_init_trans.aggcontext,
2153 l_ptr(StructExprContext));
2156 LLVMBuildStructGEP(b,
2158 FIELDNO_AGGSTATE_CURRENT_SET,
2159 "aggstate.current_set");
2161 LLVMBuildStructGEP(b,
2163 FIELDNO_AGGSTATE_CURAGGCONTEXT,
2164 "aggstate.curaggcontext");
2166 LLVMBuildStore(b, l_int32_const(op->d.agg_init_trans.setno),
2168 LLVMBuildStore(b, v_aggcontext,
2171 params[0] = v_aggstatep;
2172 params[1] = v_pertransp;
2173 params[2] = v_pergroupp;
2176 llvm_get_decl(mod, FuncExecAggInitGroup),
2177 params, lengthof(params),
2180 LLVMBuildBr(b, opblocks[op->d.agg_init_trans.jumpnull]);
2185 case EEOP_AGG_STRICT_TRANS_CHECK:
2188 LLVMValueRef v_setoff,
2191 LLVMValueRef v_aggstatep;
2192 LLVMValueRef v_allpergroupsp;
2194 LLVMValueRef v_transnull;
2195 LLVMValueRef v_pergroupp;
2197 int jumpnull = op->d.agg_strict_trans_check.jumpnull;
2199 aggstate = op->d.agg_strict_trans_check.aggstate;
2200 v_aggstatep = l_ptr_const(aggstate, l_ptr(StructAggState));
2203 * pergroup = &aggstate->all_pergroups
2204 * [op->d.agg_strict_trans_check.setoff]
2205 * [op->d.agg_init_trans_check.transno];
2208 l_load_struct_gep(b, v_aggstatep,
2209 FIELDNO_AGGSTATE_ALL_PERGROUPS,
2210 "aggstate.all_pergroups");
2212 l_int32_const(op->d.agg_strict_trans_check.setoff);
2214 l_int32_const(op->d.agg_strict_trans_check.transno);
2217 l_load_gep1(b, v_allpergroupsp, v_setoff, ""),
2221 l_load_struct_gep(b, v_pergroupp,
2222 FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL,
2226 LLVMBuildICmp(b, LLVMIntEQ, v_transnull,
2227 l_sbool_const(1), ""),
2234 case EEOP_AGG_PLAIN_TRANS_BYVAL:
2235 case EEOP_AGG_PLAIN_TRANS:
2238 AggStatePerTrans pertrans;
2239 FunctionCallInfo fcinfo;
2241 LLVMValueRef v_aggstatep;
2242 LLVMValueRef v_fcinfo;
2243 LLVMValueRef v_fcinfo_isnull;
2245 LLVMValueRef v_transvaluep;
2246 LLVMValueRef v_transnullp;
2248 LLVMValueRef v_setoff;
2249 LLVMValueRef v_transno;
2251 LLVMValueRef v_aggcontext;
2253 LLVMValueRef v_allpergroupsp;
2254 LLVMValueRef v_current_setp;
2255 LLVMValueRef v_current_pertransp;
2256 LLVMValueRef v_curaggcontext;
2258 LLVMValueRef v_pertransp;
2260 LLVMValueRef v_pergroupp;
2262 LLVMValueRef v_retval;
2264 LLVMValueRef v_tmpcontext;
2265 LLVMValueRef v_oldcontext;
2267 aggstate = op->d.agg_trans.aggstate;
2268 pertrans = op->d.agg_trans.pertrans;
2270 fcinfo = pertrans->transfn_fcinfo;
2272 v_aggstatep = l_ptr_const(aggstate,
2273 l_ptr(StructAggState));
2274 v_pertransp = l_ptr_const(pertrans,
2275 l_ptr(StructAggStatePerTransData));
2278 * pergroup = &aggstate->all_pergroups
2279 * [op->d.agg_strict_trans_check.setoff]
2280 * [op->d.agg_init_trans_check.transno];
2283 l_load_struct_gep(b, v_aggstatep,
2284 FIELDNO_AGGSTATE_ALL_PERGROUPS,
2285 "aggstate.all_pergroups");
2286 v_setoff = l_int32_const(op->d.agg_trans.setoff);
2287 v_transno = l_int32_const(op->d.agg_trans.transno);
2290 l_load_gep1(b, v_allpergroupsp, v_setoff, ""),
2293 v_fcinfo = l_ptr_const(fcinfo,
2294 l_ptr(StructFunctionCallInfoData));
2295 v_aggcontext = l_ptr_const(op->d.agg_trans.aggcontext,
2296 l_ptr(StructExprContext));
2299 LLVMBuildStructGEP(b,
2301 FIELDNO_AGGSTATE_CURRENT_SET,
2302 "aggstate.current_set");
2304 LLVMBuildStructGEP(b,
2306 FIELDNO_AGGSTATE_CURAGGCONTEXT,
2307 "aggstate.curaggcontext");
2308 v_current_pertransp =
2309 LLVMBuildStructGEP(b,
2311 FIELDNO_AGGSTATE_CURPERTRANS,
2312 "aggstate.curpertrans");
2314 /* set aggstate globals */
2315 LLVMBuildStore(b, v_aggcontext, v_curaggcontext);
2316 LLVMBuildStore(b, l_int32_const(op->d.agg_trans.setno),
2318 LLVMBuildStore(b, v_pertransp, v_current_pertransp);
2320 /* invoke transition function in per-tuple context */
2322 l_ptr_const(aggstate->tmpcontext->ecxt_per_tuple_memory,
2323 l_ptr(StructMemoryContextData));
2324 v_oldcontext = l_mcxt_switch(mod, b, v_tmpcontext);
2326 /* store transvalue in fcinfo->args[0] */
2328 LLVMBuildStructGEP(b, v_pergroupp,
2329 FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUE,
2332 LLVMBuildStructGEP(b, v_pergroupp,
2333 FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL,
2336 LLVMBuildLoad(b, v_transvaluep,
2338 l_funcvaluep(b, v_fcinfo, 0));
2340 LLVMBuildLoad(b, v_transnullp, "transnull"),
2341 l_funcnullp(b, v_fcinfo, 0));
2343 /* and invoke transition function */
2344 v_retval = BuildV1Call(context, b, mod, fcinfo,
2348 * For pass-by-ref datatype, must copy the new value into
2349 * aggcontext and free the prior transValue. But if
2350 * transfn returned a pointer to its first input, we don't
2351 * need to do anything. Also, if transfn returned a
2352 * pointer to a R/W expanded object that is already a
2353 * child of the aggcontext, assume we can adopt that value
2354 * without copying it.
2356 if (opcode == EEOP_AGG_PLAIN_TRANS)
2358 LLVMBasicBlockRef b_call;
2359 LLVMBasicBlockRef b_nocall;
2361 LLVMValueRef v_transvalue;
2362 LLVMValueRef v_transnull;
2363 LLVMValueRef v_newval;
2364 LLVMValueRef params[6];
2366 b_call = l_bb_before_v(opblocks[i + 1],
2367 "op.%d.transcall", i);
2368 b_nocall = l_bb_before_v(opblocks[i + 1],
2369 "op.%d.transnocall", i);
2371 v_transvalue = LLVMBuildLoad(b, v_transvaluep, "");
2372 v_transnull = LLVMBuildLoad(b, v_transnullp, "");
2375 * DatumGetPointer(newVal) !=
2376 * DatumGetPointer(pergroup->transValue))
2379 LLVMBuildICmp(b, LLVMIntEQ,
2384 /* returned datum not passed datum, reparent */
2385 LLVMPositionBuilderAtEnd(b, b_call);
2387 params[0] = v_aggstatep;
2388 params[1] = v_pertransp;
2389 params[2] = v_retval;
2390 params[3] = LLVMBuildTrunc(b, v_fcinfo_isnull,
2392 params[4] = v_transvalue;
2393 params[5] = LLVMBuildTrunc(b, v_transnull,
2396 v_fn = llvm_get_decl(mod, FuncExecAggTransReparent);
2398 LLVMBuildCall(b, v_fn,
2399 params, lengthof(params),
2402 /* store trans value */
2403 LLVMBuildStore(b, v_newval, v_transvaluep);
2404 LLVMBuildStore(b, v_fcinfo_isnull, v_transnullp);
2406 l_mcxt_switch(mod, b, v_oldcontext);
2407 LLVMBuildBr(b, opblocks[i + 1]);
2409 /* returned datum passed datum, no need to reparent */
2410 LLVMPositionBuilderAtEnd(b, b_nocall);
2413 /* store trans value */
2414 LLVMBuildStore(b, v_retval, v_transvaluep);
2415 LLVMBuildStore(b, v_fcinfo_isnull, v_transnullp);
2417 l_mcxt_switch(mod, b, v_oldcontext);
2419 LLVMBuildBr(b, opblocks[i + 1]);
2423 case EEOP_AGG_ORDERED_TRANS_DATUM:
2424 build_EvalXFunc(b, mod, "ExecEvalAggOrderedTransDatum",
2425 v_state, v_econtext, op);
2426 LLVMBuildBr(b, opblocks[i + 1]);
2429 case EEOP_AGG_ORDERED_TRANS_TUPLE:
2430 build_EvalXFunc(b, mod, "ExecEvalAggOrderedTransTuple",
2431 v_state, v_econtext, op);
2432 LLVMBuildBr(b, opblocks[i + 1]);
2441 LLVMDisposeBuilder(b);
2444 * Don't immediately emit function, instead do so the first time the
2445 * expression is actually evaluated. That allows to emit a lot of
2446 * functions together, avoiding a lot of repeated llvm and memory
2447 * remapping overhead.
2451 CompiledExprState *cstate = palloc0(sizeof(CompiledExprState));
2453 cstate->context = context;
2454 cstate->funcname = funcname;
2456 state->evalfunc = ExecRunCompiledExpr;
2457 state->evalfunc_private = cstate;
2460 llvm_leave_fatal_on_oom();
2462 INSTR_TIME_SET_CURRENT(endtime);
2463 INSTR_TIME_ACCUM_DIFF(context->base.instr.generation_counter,
2464 endtime, starttime);
2470 * Run compiled expression.
2472 * This will only be called the first time a JITed expression is called. We
2473 * first make sure the expression is still up2date, and then get a pointer to
2474 * the emitted function. The latter can be the first thing that triggers
2475 * optimizing and emitting all the generated functions.
2478 ExecRunCompiledExpr(ExprState *state, ExprContext *econtext, bool *isNull)
2480 CompiledExprState *cstate = state->evalfunc_private;
2481 ExprStateEvalFunc func;
2483 CheckExprStillValid(state, econtext);
2485 llvm_enter_fatal_on_oom();
2486 func = (ExprStateEvalFunc) llvm_get_function(cstate->context,
2488 llvm_leave_fatal_on_oom();
2491 /* remove indirection via this function for future calls */
2492 state->evalfunc = func;
2494 return func(state, econtext, isNull);
2498 BuildV1Call(LLVMJitContext *context, LLVMBuilderRef b,
2499 LLVMModuleRef mod, FunctionCallInfo fcinfo,
2500 LLVMValueRef *v_fcinfo_isnull)
2503 LLVMValueRef v_fcinfo_isnullp;
2504 LLVMValueRef v_retval;
2505 LLVMValueRef v_fcinfo;
2507 v_fn = llvm_function_reference(context, b, mod, fcinfo);
2509 v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
2510 v_fcinfo_isnullp = LLVMBuildStructGEP(b, v_fcinfo,
2511 FIELDNO_FUNCTIONCALLINFODATA_ISNULL,
2513 LLVMBuildStore(b, l_sbool_const(0), v_fcinfo_isnullp);
2515 v_retval = LLVMBuildCall(b, v_fn, &v_fcinfo, 1, "funccall");
2517 if (v_fcinfo_isnull)
2518 *v_fcinfo_isnull = LLVMBuildLoad(b, v_fcinfo_isnullp, "");
2521 * Add lifetime-end annotation, signalling that writes to memory don't
2522 * have to be retained (important for inlining potential).
2525 LLVMValueRef v_lifetime = create_LifetimeEnd(mod);
2526 LLVMValueRef params[2];
2528 params[0] = l_int64_const(sizeof(NullableDatum) * fcinfo->nargs);
2529 params[1] = l_ptr_const(fcinfo->args, l_ptr(LLVMInt8Type()));
2530 LLVMBuildCall(b, v_lifetime, params, lengthof(params), "");
2532 params[0] = l_int64_const(sizeof(fcinfo->isnull));
2533 params[1] = l_ptr_const(&fcinfo->isnull, l_ptr(LLVMInt8Type()));
2534 LLVMBuildCall(b, v_lifetime, params, lengthof(params), "");
2541 * Implement an expression step by calling the function funcname.
2544 build_EvalXFunc(LLVMBuilderRef b, LLVMModuleRef mod, const char *funcname,
2545 LLVMValueRef v_state, LLVMValueRef v_econtext,
2550 LLVMTypeRef param_types[3];
2551 LLVMValueRef params[3];
2553 v_fn = LLVMGetNamedFunction(mod, funcname);
2556 param_types[0] = l_ptr(StructExprState);
2557 param_types[1] = l_ptr(StructExprEvalStep);
2558 param_types[2] = l_ptr(StructExprContext);
2560 sig = LLVMFunctionType(LLVMVoidType(),
2561 param_types, lengthof(param_types),
2563 v_fn = LLVMAddFunction(mod, funcname, sig);
2566 params[0] = v_state;
2567 params[1] = l_ptr_const(op, l_ptr(StructExprEvalStep));
2568 params[2] = v_econtext;
2572 params, lengthof(params), "");
2576 create_LifetimeEnd(LLVMModuleRef mod)
2580 LLVMTypeRef param_types[2];
2582 /* LLVM 5+ has a variadic pointer argument */
2583 #if LLVM_VERSION_MAJOR < 5
2584 const char *nm = "llvm.lifetime.end";
2586 const char *nm = "llvm.lifetime.end.p0i8";
2589 fn = LLVMGetNamedFunction(mod, nm);
2593 param_types[0] = LLVMInt64Type();
2594 param_types[1] = l_ptr(LLVMInt8Type());
2596 sig = LLVMFunctionType(LLVMVoidType(),
2597 param_types, lengthof(param_types),
2599 fn = LLVMAddFunction(mod, nm, sig);
2601 LLVMSetFunctionCallConv(fn, LLVMCCallConv);
2603 Assert(LLVMGetIntrinsicID(fn));