1 /*-------------------------------------------------------------------------
4 * JIT compile expressions.
6 * Portions Copyright (c) 1996-2017, 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;
280 b_fetch = l_bb_before_v(opblocks[i + 1],
283 if (op->d.fetch.known_desc)
284 desc = op->d.fetch.known_desc;
286 if (opcode == EEOP_INNER_FETCHSOME)
288 PlanState *is = innerPlanState(parent);
290 v_slot = v_innerslot;
294 is->ps_ResultTupleSlot &&
295 is->ps_ResultTupleSlot->tts_fixedTupleDescriptor)
296 desc = is->ps_ResultTupleSlot->tts_tupleDescriptor;
298 else if (opcode == EEOP_OUTER_FETCHSOME)
300 PlanState *os = outerPlanState(parent);
302 v_slot = v_outerslot;
306 os->ps_ResultTupleSlot &&
307 os->ps_ResultTupleSlot->tts_fixedTupleDescriptor)
308 desc = os->ps_ResultTupleSlot->tts_tupleDescriptor;
314 desc = parent->scandesc;
318 * Check if all required attributes are available, or
319 * whether deforming is required.
322 l_load_struct_gep(b, v_slot,
323 FIELDNO_TUPLETABLESLOT_NVALID,
326 LLVMBuildICmp(b, LLVMIntUGE, v_nvalid,
327 l_int32_const(op->d.fetch.last_var),
329 opblocks[i + 1], b_fetch);
331 LLVMPositionBuilderAtEnd(b, b_fetch);
334 * If the tupledesc of the to-be-deformed tuple is known,
335 * and JITing of deforming is enabled, build deform
336 * function specific to tupledesc and the exact number of
337 * to-be-extracted attributes.
339 if (desc && (context->base.flags & PGJIT_DEFORM))
341 LLVMValueRef params[1];
342 LLVMValueRef l_jit_deform;
345 slot_compile_deform(context, desc,
346 op->d.fetch.last_var);
349 LLVMBuildCall(b, l_jit_deform,
350 params, lengthof(params), "");
355 LLVMValueRef params[2];
358 params[1] = l_int32_const(op->d.fetch.last_var);
361 llvm_get_decl(mod, FuncSlotGetsomeattrs),
362 params, lengthof(params), "");
365 LLVMBuildBr(b, opblocks[i + 1]);
375 LLVMValueRef v_attnum;
376 LLVMValueRef v_values;
377 LLVMValueRef v_nulls;
379 if (opcode == EEOP_INNER_VAR)
381 v_values = v_innervalues;
382 v_nulls = v_innernulls;
384 else if (opcode == EEOP_OUTER_VAR)
386 v_values = v_outervalues;
387 v_nulls = v_outernulls;
391 v_values = v_scanvalues;
392 v_nulls = v_scannulls;
395 v_attnum = l_int32_const(op->d.var.attnum);
396 value = l_load_gep1(b, v_values, v_attnum, "");
397 isnull = l_load_gep1(b, v_nulls, v_attnum, "");
398 LLVMBuildStore(b, value, v_resvaluep);
399 LLVMBuildStore(b, isnull, v_resnullp);
401 LLVMBuildBr(b, opblocks[i + 1]);
405 case EEOP_INNER_SYSVAR:
406 case EEOP_OUTER_SYSVAR:
407 case EEOP_SCAN_SYSVAR:
409 int attnum = op->d.var.attnum;
410 LLVMValueRef v_attnum;
411 LLVMValueRef v_tuple;
412 LLVMValueRef v_tupleDescriptor;
413 LLVMValueRef v_params[4];
414 LLVMValueRef v_syscol;
417 if (opcode == EEOP_INNER_SYSVAR)
418 v_slot = v_innerslot;
419 else if (opcode == EEOP_OUTER_SYSVAR)
420 v_slot = v_outerslot;
424 Assert(op->d.var.attnum < 0);
426 v_tuple = l_load_struct_gep(b, v_slot,
427 FIELDNO_TUPLETABLESLOT_TUPLE,
431 * Could optimize this a bit for fixed descriptors, but
432 * this shouldn't be that critical a path.
435 l_load_struct_gep(b, v_slot,
436 FIELDNO_TUPLETABLESLOT_TUPLEDESCRIPTOR,
438 v_attnum = l_int32_const(attnum);
440 v_params[0] = v_tuple;
441 v_params[1] = v_attnum;
442 v_params[2] = v_tupleDescriptor;
443 v_params[3] = v_resnullp;
444 v_syscol = LLVMBuildCall(b,
445 llvm_get_decl(mod, FuncHeapGetsysattr),
446 v_params, lengthof(v_params),
448 LLVMBuildStore(b, v_syscol, v_resvaluep);
450 LLVMBuildBr(b, opblocks[i + 1]);
455 build_EvalXFunc(b, mod, "ExecEvalWholeRowVar",
456 v_state, v_econtext, op);
457 LLVMBuildBr(b, opblocks[i + 1]);
460 case EEOP_ASSIGN_INNER_VAR:
461 case EEOP_ASSIGN_OUTER_VAR:
462 case EEOP_ASSIGN_SCAN_VAR:
464 LLVMValueRef v_value,
466 LLVMValueRef v_rvaluep,
468 LLVMValueRef v_attnum,
470 LLVMValueRef v_values;
471 LLVMValueRef v_nulls;
473 if (opcode == EEOP_ASSIGN_INNER_VAR)
475 v_values = v_innervalues;
476 v_nulls = v_innernulls;
478 else if (opcode == EEOP_ASSIGN_OUTER_VAR)
480 v_values = v_outervalues;
481 v_nulls = v_outernulls;
485 v_values = v_scanvalues;
486 v_nulls = v_scannulls;
490 v_attnum = l_int32_const(op->d.assign_var.attnum);
491 v_value = l_load_gep1(b, v_values, v_attnum, "");
492 v_isnull = l_load_gep1(b, v_nulls, v_attnum, "");
494 /* compute addresses of targets */
495 v_resultnum = l_int32_const(op->d.assign_var.resultnum);
496 v_rvaluep = LLVMBuildGEP(b, v_resultvalues,
497 &v_resultnum, 1, "");
498 v_risnullp = LLVMBuildGEP(b, v_resultnulls,
499 &v_resultnum, 1, "");
502 LLVMBuildStore(b, v_value, v_rvaluep);
503 LLVMBuildStore(b, v_isnull, v_risnullp);
505 LLVMBuildBr(b, opblocks[i + 1]);
509 case EEOP_ASSIGN_TMP:
511 LLVMValueRef v_value,
513 LLVMValueRef v_rvaluep,
515 LLVMValueRef v_resultnum;
516 size_t resultnum = op->d.assign_tmp.resultnum;
519 v_value = LLVMBuildLoad(b, v_tmpvaluep, "");
520 v_isnull = LLVMBuildLoad(b, v_tmpisnullp, "");
522 /* compute addresses of targets */
523 v_resultnum = l_int32_const(resultnum);
525 LLVMBuildGEP(b, v_resultvalues, &v_resultnum, 1, "");
527 LLVMBuildGEP(b, v_resultnulls, &v_resultnum, 1, "");
530 LLVMBuildStore(b, v_value, v_rvaluep);
531 LLVMBuildStore(b, v_isnull, v_risnullp);
533 LLVMBuildBr(b, opblocks[i + 1]);
537 case EEOP_ASSIGN_TMP_MAKE_RO:
539 LLVMBasicBlockRef b_notnull;
540 LLVMValueRef v_params[1];
542 LLVMValueRef v_value,
544 LLVMValueRef v_rvaluep,
546 LLVMValueRef v_resultnum;
547 size_t resultnum = op->d.assign_tmp.resultnum;
549 b_notnull = l_bb_before_v(opblocks[i + 1],
550 "op.%d.assign_tmp.notnull", i);
553 v_value = LLVMBuildLoad(b, v_tmpvaluep, "");
554 v_isnull = LLVMBuildLoad(b, v_tmpisnullp, "");
556 /* compute addresses of targets */
557 v_resultnum = l_int32_const(resultnum);
558 v_rvaluep = LLVMBuildGEP(b, v_resultvalues,
559 &v_resultnum, 1, "");
560 v_risnullp = LLVMBuildGEP(b, v_resultnulls,
561 &v_resultnum, 1, "");
564 LLVMBuildStore(b, v_isnull, v_risnullp);
566 /* check if value is NULL */
568 LLVMBuildICmp(b, LLVMIntEQ, v_isnull,
569 l_sbool_const(0), ""),
570 b_notnull, opblocks[i + 1]);
572 /* if value is not null, convert to RO datum */
573 LLVMPositionBuilderAtEnd(b, b_notnull);
574 v_params[0] = v_value;
577 llvm_get_decl(mod, FuncMakeExpandedObjectReadOnlyInternal),
578 v_params, lengthof(v_params), "");
581 LLVMBuildStore(b, v_ret, v_rvaluep);
583 LLVMBuildBr(b, opblocks[i + 1]);
589 LLVMValueRef v_constvalue,
592 v_constvalue = l_sizet_const(op->d.constval.value);
593 v_constnull = l_sbool_const(op->d.constval.isnull);
595 LLVMBuildStore(b, v_constvalue, v_resvaluep);
596 LLVMBuildStore(b, v_constnull, v_resnullp);
598 LLVMBuildBr(b, opblocks[i + 1]);
602 case EEOP_FUNCEXPR_STRICT:
604 FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
605 LLVMBasicBlockRef b_nonull;
607 LLVMValueRef v_fcinfo;
608 LLVMValueRef v_argnullp;
609 LLVMBasicBlockRef *b_checkargnulls;
612 * Block for the actual function call, if args are
615 b_nonull = l_bb_before_v(opblocks[i + 1],
616 "b.%d.no-null-args", i);
618 /* should make sure they're optimized beforehand */
619 if (op->d.func.nargs == 0)
620 elog(ERROR, "argumentless strict functions are pointless");
623 l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
626 LLVMBuildStructGEP(b,
628 FIELDNO_FUNCTIONCALLINFODATA_ARGNULL,
632 * set resnull to true, if the function is actually
633 * called, it'll be reset
635 LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
637 /* create blocks for checking args, one for each */
639 palloc(sizeof(LLVMBasicBlockRef *) * op->d.func.nargs);
640 for (argno = 0; argno < op->d.func.nargs; argno++)
641 b_checkargnulls[argno] =
642 l_bb_before_v(b_nonull, "b.%d.isnull.%d", i, argno);
644 /* jump to check of first argument */
645 LLVMBuildBr(b, b_checkargnulls[0]);
647 /* check each arg for NULLness */
648 for (argno = 0; argno < op->d.func.nargs; argno++)
650 LLVMValueRef v_argisnull;
651 LLVMBasicBlockRef b_argnotnull;
653 LLVMPositionBuilderAtEnd(b, b_checkargnulls[argno]);
655 /* compute block to jump to if argument is not null */
656 if (argno + 1 == op->d.func.nargs)
657 b_argnotnull = b_nonull;
659 b_argnotnull = b_checkargnulls[argno + 1];
661 /* and finally load & check NULLness of arg */
662 v_argisnull = l_load_struct_gep(b, v_argnullp,
665 LLVMBuildICmp(b, LLVMIntEQ,
673 LLVMPositionBuilderAtEnd(b, b_nonull);
679 FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
680 LLVMValueRef v_fcinfo_isnull;
681 LLVMValueRef v_retval;
683 v_retval = BuildV1Call(context, b, mod, fcinfo,
685 LLVMBuildStore(b, v_retval, v_resvaluep);
686 LLVMBuildStore(b, v_fcinfo_isnull, v_resnullp);
688 LLVMBuildBr(b, opblocks[i + 1]);
692 case EEOP_FUNCEXPR_FUSAGE:
693 build_EvalXFunc(b, mod, "ExecEvalFuncExprFusage",
694 v_state, v_econtext, op);
695 LLVMBuildBr(b, opblocks[i + 1]);
699 case EEOP_FUNCEXPR_STRICT_FUSAGE:
700 build_EvalXFunc(b, mod, "ExecEvalFuncExprStrictFusage",
701 v_state, v_econtext, op);
702 LLVMBuildBr(b, opblocks[i + 1]);
705 case EEOP_BOOL_AND_STEP_FIRST:
707 LLVMValueRef v_boolanynullp;
709 v_boolanynullp = l_ptr_const(op->d.boolexpr.anynull,
710 l_ptr(TypeStorageBool));
711 LLVMBuildStore(b, l_sbool_const(0), v_boolanynullp);
717 * Treat them the same for now, optimizer can remove
718 * redundancy. Could be worthwhile to optimize during emission
721 case EEOP_BOOL_AND_STEP_LAST:
722 case EEOP_BOOL_AND_STEP:
724 LLVMValueRef v_boolvalue;
725 LLVMValueRef v_boolnull;
726 LLVMValueRef v_boolanynullp,
728 LLVMBasicBlockRef b_boolisnull;
729 LLVMBasicBlockRef b_boolcheckfalse;
730 LLVMBasicBlockRef b_boolisfalse;
731 LLVMBasicBlockRef b_boolcont;
732 LLVMBasicBlockRef b_boolisanynull;
734 b_boolisnull = l_bb_before_v(opblocks[i + 1],
735 "b.%d.boolisnull", i);
736 b_boolcheckfalse = l_bb_before_v(opblocks[i + 1],
737 "b.%d.boolcheckfalse", i);
738 b_boolisfalse = l_bb_before_v(opblocks[i + 1],
739 "b.%d.boolisfalse", i);
740 b_boolisanynull = l_bb_before_v(opblocks[i + 1],
741 "b.%d.boolisanynull", i);
742 b_boolcont = l_bb_before_v(opblocks[i + 1],
745 v_boolanynullp = l_ptr_const(op->d.boolexpr.anynull,
746 l_ptr(TypeStorageBool));
748 v_boolnull = LLVMBuildLoad(b, v_resnullp, "");
749 v_boolvalue = LLVMBuildLoad(b, v_resvaluep, "");
751 /* set resnull to boolnull */
752 LLVMBuildStore(b, v_boolnull, v_resnullp);
753 /* set revalue to boolvalue */
754 LLVMBuildStore(b, v_boolvalue, v_resvaluep);
756 /* check if current input is NULL */
758 LLVMBuildICmp(b, LLVMIntEQ, v_boolnull,
759 l_sbool_const(1), ""),
763 /* build block that sets anynull */
764 LLVMPositionBuilderAtEnd(b, b_boolisnull);
765 /* set boolanynull to true */
766 LLVMBuildStore(b, l_sbool_const(1), v_boolanynullp);
767 /* and jump to next block */
768 LLVMBuildBr(b, b_boolcont);
770 /* build block checking for false */
771 LLVMPositionBuilderAtEnd(b, b_boolcheckfalse);
773 LLVMBuildICmp(b, LLVMIntEQ, v_boolvalue,
774 l_sizet_const(0), ""),
779 * Build block handling FALSE. Value is false, so short
782 LLVMPositionBuilderAtEnd(b, b_boolisfalse);
783 /* result is already set to FALSE, need not change it */
784 /* and jump to the end of the AND expression */
785 LLVMBuildBr(b, opblocks[op->d.boolexpr.jumpdone]);
787 /* Build block that continues if bool is TRUE. */
788 LLVMPositionBuilderAtEnd(b, b_boolcont);
790 v_boolanynull = LLVMBuildLoad(b, v_boolanynullp, "");
792 /* set value to NULL if any previous values were NULL */
794 LLVMBuildICmp(b, LLVMIntEQ, v_boolanynull,
795 l_sbool_const(0), ""),
796 opblocks[i + 1], b_boolisanynull);
798 LLVMPositionBuilderAtEnd(b, b_boolisanynull);
799 /* set resnull to true */
800 LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
802 LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
804 LLVMBuildBr(b, opblocks[i + 1]);
807 case EEOP_BOOL_OR_STEP_FIRST:
809 LLVMValueRef v_boolanynullp;
811 v_boolanynullp = l_ptr_const(op->d.boolexpr.anynull,
812 l_ptr(TypeStorageBool));
813 LLVMBuildStore(b, l_sbool_const(0), v_boolanynullp);
818 * Treat them the same for now, optimizer can remove
819 * redundancy. Could be worthwhile to optimize during emission
822 case EEOP_BOOL_OR_STEP_LAST:
823 case EEOP_BOOL_OR_STEP:
825 LLVMValueRef v_boolvalue;
826 LLVMValueRef v_boolnull;
827 LLVMValueRef v_boolanynullp,
830 LLVMBasicBlockRef b_boolisnull;
831 LLVMBasicBlockRef b_boolchecktrue;
832 LLVMBasicBlockRef b_boolistrue;
833 LLVMBasicBlockRef b_boolcont;
834 LLVMBasicBlockRef b_boolisanynull;
836 b_boolisnull = l_bb_before_v(opblocks[i + 1],
837 "b.%d.boolisnull", i);
838 b_boolchecktrue = l_bb_before_v(opblocks[i + 1],
839 "b.%d.boolchecktrue", i);
840 b_boolistrue = l_bb_before_v(opblocks[i + 1],
841 "b.%d.boolistrue", i);
842 b_boolisanynull = l_bb_before_v(opblocks[i + 1],
843 "b.%d.boolisanynull", i);
844 b_boolcont = l_bb_before_v(opblocks[i + 1],
847 v_boolanynullp = l_ptr_const(op->d.boolexpr.anynull,
848 l_ptr(TypeStorageBool));
850 v_boolnull = LLVMBuildLoad(b, v_resnullp, "");
851 v_boolvalue = LLVMBuildLoad(b, v_resvaluep, "");
853 /* set resnull to boolnull */
854 LLVMBuildStore(b, v_boolnull, v_resnullp);
855 /* set revalue to boolvalue */
856 LLVMBuildStore(b, v_boolvalue, v_resvaluep);
859 LLVMBuildICmp(b, LLVMIntEQ, v_boolnull,
860 l_sbool_const(1), ""),
864 /* build block that sets anynull */
865 LLVMPositionBuilderAtEnd(b, b_boolisnull);
866 /* set boolanynull to true */
867 LLVMBuildStore(b, l_sbool_const(1), v_boolanynullp);
868 /* and jump to next block */
869 LLVMBuildBr(b, b_boolcont);
871 /* build block checking for true */
872 LLVMPositionBuilderAtEnd(b, b_boolchecktrue);
874 LLVMBuildICmp(b, LLVMIntEQ, v_boolvalue,
875 l_sizet_const(1), ""),
880 * Build block handling True. Value is true, so short
883 LLVMPositionBuilderAtEnd(b, b_boolistrue);
884 /* result is already set to TRUE, need not change it */
885 /* and jump to the end of the OR expression */
886 LLVMBuildBr(b, opblocks[op->d.boolexpr.jumpdone]);
888 /* build block that continues if bool is FALSE */
889 LLVMPositionBuilderAtEnd(b, b_boolcont);
891 v_boolanynull = LLVMBuildLoad(b, v_boolanynullp, "");
893 /* set value to NULL if any previous values were NULL */
895 LLVMBuildICmp(b, LLVMIntEQ, v_boolanynull,
896 l_sbool_const(0), ""),
897 opblocks[i + 1], b_boolisanynull);
899 LLVMPositionBuilderAtEnd(b, b_boolisanynull);
900 /* set resnull to true */
901 LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
903 LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
905 LLVMBuildBr(b, opblocks[i + 1]);
909 case EEOP_BOOL_NOT_STEP:
911 LLVMValueRef v_boolvalue;
912 LLVMValueRef v_boolnull;
913 LLVMValueRef v_negbool;
915 v_boolnull = LLVMBuildLoad(b, v_resnullp, "");
916 v_boolvalue = LLVMBuildLoad(b, v_resvaluep, "");
918 v_negbool = LLVMBuildZExt(b,
919 LLVMBuildICmp(b, LLVMIntEQ,
924 /* set resnull to boolnull */
925 LLVMBuildStore(b, v_boolnull, v_resnullp);
926 /* set revalue to !boolvalue */
927 LLVMBuildStore(b, v_negbool, v_resvaluep);
929 LLVMBuildBr(b, opblocks[i + 1]);
935 LLVMValueRef v_resnull;
936 LLVMValueRef v_resvalue;
937 LLVMValueRef v_nullorfalse;
938 LLVMBasicBlockRef b_qualfail;
940 b_qualfail = l_bb_before_v(opblocks[i + 1],
941 "op.%d.qualfail", i);
943 v_resvalue = LLVMBuildLoad(b, v_resvaluep, "");
944 v_resnull = LLVMBuildLoad(b, v_resnullp, "");
948 LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
949 l_sbool_const(1), ""),
950 LLVMBuildICmp(b, LLVMIntEQ, v_resvalue,
951 l_sizet_const(0), ""),
959 /* build block handling NULL or false */
960 LLVMPositionBuilderAtEnd(b, b_qualfail);
961 /* set resnull to false */
962 LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
963 /* set resvalue to false */
964 LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
966 LLVMBuildBr(b, opblocks[op->d.qualexpr.jumpdone]);
972 LLVMBuildBr(b, opblocks[op->d.jump.jumpdone]);
976 case EEOP_JUMP_IF_NULL:
978 LLVMValueRef v_resnull;
980 /* Transfer control if current result is null */
982 v_resnull = LLVMBuildLoad(b, v_resnullp, "");
985 LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
986 l_sbool_const(1), ""),
987 opblocks[op->d.jump.jumpdone],
992 case EEOP_JUMP_IF_NOT_NULL:
994 LLVMValueRef v_resnull;
996 /* Transfer control if current result is non-null */
998 v_resnull = LLVMBuildLoad(b, v_resnullp, "");
1001 LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
1002 l_sbool_const(0), ""),
1003 opblocks[op->d.jump.jumpdone],
1009 case EEOP_JUMP_IF_NOT_TRUE:
1011 LLVMValueRef v_resnull;
1012 LLVMValueRef v_resvalue;
1013 LLVMValueRef v_nullorfalse;
1015 /* Transfer control if current result is null or false */
1017 v_resvalue = LLVMBuildLoad(b, v_resvaluep, "");
1018 v_resnull = LLVMBuildLoad(b, v_resnullp, "");
1022 LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
1023 l_sbool_const(1), ""),
1024 LLVMBuildICmp(b, LLVMIntEQ, v_resvalue,
1025 l_sizet_const(0), ""),
1030 opblocks[op->d.jump.jumpdone],
1035 case EEOP_NULLTEST_ISNULL:
1037 LLVMValueRef v_resnull = LLVMBuildLoad(b, v_resnullp, "");
1038 LLVMValueRef v_resvalue;
1042 LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
1043 l_sbool_const(1), ""),
1047 LLVMBuildStore(b, v_resvalue, v_resvaluep);
1048 LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1050 LLVMBuildBr(b, opblocks[i + 1]);
1054 case EEOP_NULLTEST_ISNOTNULL:
1056 LLVMValueRef v_resnull = LLVMBuildLoad(b, v_resnullp, "");
1057 LLVMValueRef v_resvalue;
1061 LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
1062 l_sbool_const(1), ""),
1066 LLVMBuildStore(b, v_resvalue, v_resvaluep);
1067 LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1069 LLVMBuildBr(b, opblocks[i + 1]);
1073 case EEOP_NULLTEST_ROWISNULL:
1074 build_EvalXFunc(b, mod, "ExecEvalRowNull",
1075 v_state, v_econtext, op);
1076 LLVMBuildBr(b, opblocks[i + 1]);
1079 case EEOP_NULLTEST_ROWISNOTNULL:
1080 build_EvalXFunc(b, mod, "ExecEvalRowNotNull",
1081 v_state, v_econtext, op);
1082 LLVMBuildBr(b, opblocks[i + 1]);
1085 case EEOP_BOOLTEST_IS_TRUE:
1086 case EEOP_BOOLTEST_IS_NOT_FALSE:
1087 case EEOP_BOOLTEST_IS_FALSE:
1088 case EEOP_BOOLTEST_IS_NOT_TRUE:
1090 LLVMBasicBlockRef b_isnull,
1092 LLVMValueRef v_resnull = LLVMBuildLoad(b, v_resnullp, "");
1094 b_isnull = l_bb_before_v(opblocks[i + 1],
1096 b_notnull = l_bb_before_v(opblocks[i + 1],
1097 "op.%d.isnotnull", i);
1099 /* check if value is NULL */
1101 LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
1102 l_sbool_const(1), ""),
1103 b_isnull, b_notnull);
1105 /* if value is NULL, return false */
1106 LLVMPositionBuilderAtEnd(b, b_isnull);
1108 /* result is not null */
1109 LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1111 if (opcode == EEOP_BOOLTEST_IS_TRUE ||
1112 opcode == EEOP_BOOLTEST_IS_FALSE)
1114 LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
1118 LLVMBuildStore(b, l_sizet_const(1), v_resvaluep);
1121 LLVMBuildBr(b, opblocks[i + 1]);
1123 LLVMPositionBuilderAtEnd(b, b_notnull);
1125 if (opcode == EEOP_BOOLTEST_IS_TRUE ||
1126 opcode == EEOP_BOOLTEST_IS_NOT_FALSE)
1129 * if value is not null NULL, return value (already
1135 LLVMValueRef v_value =
1136 LLVMBuildLoad(b, v_resvaluep, "");
1138 v_value = LLVMBuildZExt(b,
1139 LLVMBuildICmp(b, LLVMIntEQ,
1144 LLVMBuildStore(b, v_value, v_resvaluep);
1146 LLVMBuildBr(b, opblocks[i + 1]);
1150 case EEOP_PARAM_EXEC:
1151 build_EvalXFunc(b, mod, "ExecEvalParamExec",
1152 v_state, v_econtext, op);
1153 LLVMBuildBr(b, opblocks[i + 1]);
1156 case EEOP_PARAM_EXTERN:
1157 build_EvalXFunc(b, mod, "ExecEvalParamExtern",
1158 v_state, v_econtext, op);
1159 LLVMBuildBr(b, opblocks[i + 1]);
1162 case EEOP_PARAM_CALLBACK:
1164 LLVMTypeRef param_types[3];
1165 LLVMValueRef v_params[3];
1166 LLVMTypeRef v_functype;
1167 LLVMValueRef v_func;
1169 param_types[0] = l_ptr(StructExprState);
1170 param_types[1] = l_ptr(TypeSizeT);
1171 param_types[2] = l_ptr(StructExprContext);
1173 v_functype = LLVMFunctionType(LLVMVoidType(),
1175 lengthof(param_types),
1177 v_func = l_ptr_const(op->d.cparam.paramfunc,
1180 v_params[0] = v_state;
1181 v_params[1] = l_ptr_const(op, l_ptr(TypeSizeT));
1182 v_params[2] = v_econtext;
1185 v_params, lengthof(v_params), "");
1187 LLVMBuildBr(b, opblocks[i + 1]);
1191 case EEOP_ARRAYREF_OLD:
1192 build_EvalXFunc(b, mod, "ExecEvalArrayRefOld",
1193 v_state, v_econtext, op);
1194 LLVMBuildBr(b, opblocks[i + 1]);
1197 case EEOP_ARRAYREF_ASSIGN:
1198 build_EvalXFunc(b, mod, "ExecEvalArrayRefAssign",
1199 v_state, v_econtext, op);
1200 LLVMBuildBr(b, opblocks[i + 1]);
1203 case EEOP_ARRAYREF_FETCH:
1204 build_EvalXFunc(b, mod, "ExecEvalArrayRefFetch",
1205 v_state, v_econtext, op);
1206 LLVMBuildBr(b, opblocks[i + 1]);
1209 case EEOP_CASE_TESTVAL:
1211 LLVMBasicBlockRef b_avail,
1213 LLVMValueRef v_casevaluep,
1215 LLVMValueRef v_casenullp,
1217 LLVMValueRef v_casevaluenull;
1219 b_avail = l_bb_before_v(opblocks[i + 1],
1221 b_notavail = l_bb_before_v(opblocks[i + 1],
1222 "op.%d.notavail", i);
1224 v_casevaluep = l_ptr_const(op->d.casetest.value,
1226 v_casenullp = l_ptr_const(op->d.casetest.isnull,
1227 l_ptr(TypeStorageBool));
1230 LLVMBuildICmp(b, LLVMIntEQ,
1231 LLVMBuildPtrToInt(b, v_casevaluep,
1233 l_sizet_const(0), "");
1234 LLVMBuildCondBr(b, v_casevaluenull, b_notavail, b_avail);
1236 /* if casetest != NULL */
1237 LLVMPositionBuilderAtEnd(b, b_avail);
1238 v_casevalue = LLVMBuildLoad(b, v_casevaluep, "");
1239 v_casenull = LLVMBuildLoad(b, v_casenullp, "");
1240 LLVMBuildStore(b, v_casevalue, v_resvaluep);
1241 LLVMBuildStore(b, v_casenull, v_resnullp);
1242 LLVMBuildBr(b, opblocks[i + 1]);
1244 /* if casetest == NULL */
1245 LLVMPositionBuilderAtEnd(b, b_notavail);
1247 l_load_struct_gep(b, v_econtext,
1248 FIELDNO_EXPRCONTEXT_CASEDATUM, "");
1250 l_load_struct_gep(b, v_econtext,
1251 FIELDNO_EXPRCONTEXT_CASENULL, "");
1252 LLVMBuildStore(b, v_casevalue, v_resvaluep);
1253 LLVMBuildStore(b, v_casenull, v_resnullp);
1255 LLVMBuildBr(b, opblocks[i + 1]);
1259 case EEOP_MAKE_READONLY:
1261 LLVMBasicBlockRef b_notnull;
1262 LLVMValueRef v_params[1];
1264 LLVMValueRef v_nullp;
1265 LLVMValueRef v_valuep;
1266 LLVMValueRef v_null;
1267 LLVMValueRef v_value;
1269 b_notnull = l_bb_before_v(opblocks[i + 1],
1270 "op.%d.readonly.notnull", i);
1272 v_nullp = l_ptr_const(op->d.make_readonly.isnull,
1273 l_ptr(TypeStorageBool));
1275 v_null = LLVMBuildLoad(b, v_nullp, "");
1277 /* store null isnull value in result */
1278 LLVMBuildStore(b, v_null, v_resnullp);
1280 /* check if value is NULL */
1282 LLVMBuildICmp(b, LLVMIntEQ, v_null,
1283 l_sbool_const(1), ""),
1284 opblocks[i + 1], b_notnull);
1286 /* if value is not null, convert to RO datum */
1287 LLVMPositionBuilderAtEnd(b, b_notnull);
1289 v_valuep = l_ptr_const(op->d.make_readonly.value,
1292 v_value = LLVMBuildLoad(b, v_valuep, "");
1294 v_params[0] = v_value;
1297 llvm_get_decl(mod, FuncMakeExpandedObjectReadOnlyInternal),
1298 v_params, lengthof(v_params), "");
1299 LLVMBuildStore(b, v_ret, v_resvaluep);
1301 LLVMBuildBr(b, opblocks[i + 1]);
1307 FunctionCallInfo fcinfo_out,
1309 LLVMValueRef v_fcinfo_out,
1311 LLVMValueRef v_fn_addr_out,
1313 LLVMValueRef v_fcinfo_in_isnullp;
1314 LLVMValueRef v_in_argp,
1316 LLVMValueRef v_in_argnullp,
1318 LLVMValueRef v_retval;
1319 LLVMValueRef v_resvalue;
1320 LLVMValueRef v_resnull;
1322 LLVMValueRef v_output_skip;
1323 LLVMValueRef v_output;
1325 LLVMBasicBlockRef b_skipoutput;
1326 LLVMBasicBlockRef b_calloutput;
1327 LLVMBasicBlockRef b_input;
1328 LLVMBasicBlockRef b_inputcall;
1330 fcinfo_out = op->d.iocoerce.fcinfo_data_out;
1331 fcinfo_in = op->d.iocoerce.fcinfo_data_in;
1333 b_skipoutput = l_bb_before_v(opblocks[i + 1],
1334 "op.%d.skipoutputnull", i);
1335 b_calloutput = l_bb_before_v(opblocks[i + 1],
1336 "op.%d.calloutput", i);
1337 b_input = l_bb_before_v(opblocks[i + 1],
1339 b_inputcall = l_bb_before_v(opblocks[i + 1],
1340 "op.%d.inputcall", i);
1342 v_fcinfo_out = l_ptr_const(fcinfo_out, l_ptr(StructFunctionCallInfoData));
1343 v_fcinfo_in = l_ptr_const(fcinfo_in, l_ptr(StructFunctionCallInfoData));
1344 v_fn_addr_out = l_ptr_const(fcinfo_out->flinfo->fn_addr, TypePGFunction);
1345 v_fn_addr_in = l_ptr_const(fcinfo_in->flinfo->fn_addr, TypePGFunction);
1347 v_fcinfo_in_isnullp =
1348 LLVMBuildStructGEP(b, v_fcinfo_in,
1349 FIELDNO_FUNCTIONCALLINFODATA_ISNULL,
1350 "v_fcinfo_in_isnull");
1352 LLVMBuildStructGEP(b, v_fcinfo_out,
1353 FIELDNO_FUNCTIONCALLINFODATA_ARGNULL,
1354 "v_fcinfo_out_argnullp");
1356 LLVMBuildStructGEP(b, v_fcinfo_in,
1357 FIELDNO_FUNCTIONCALLINFODATA_ARGNULL,
1358 "v_fcinfo_in_argnullp");
1360 LLVMBuildStructGEP(b, v_fcinfo_out,
1361 FIELDNO_FUNCTIONCALLINFODATA_ARG,
1362 "v_fcinfo_out_argp");
1364 LLVMBuildStructGEP(b, v_fcinfo_in,
1365 FIELDNO_FUNCTIONCALLINFODATA_ARG,
1366 "v_fcinfo_in_argp");
1368 /* output functions are not called on nulls */
1369 v_resnull = LLVMBuildLoad(b, v_resnullp, "");
1371 LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
1372 l_sbool_const(1), ""),
1376 LLVMPositionBuilderAtEnd(b, b_skipoutput);
1377 v_output_skip = l_sizet_const(0);
1378 LLVMBuildBr(b, b_input);
1380 LLVMPositionBuilderAtEnd(b, b_calloutput);
1381 v_resvalue = LLVMBuildLoad(b, v_resvaluep, "");
1386 LLVMBuildStructGEP(b, v_out_argp, 0, ""));
1389 LLVMBuildStructGEP(b, v_out_argnullp,
1391 /* and call output function (can never return NULL) */
1392 v_output = LLVMBuildCall(b, v_fn_addr_out, &v_fcinfo_out,
1393 1, "funccall_coerce_out");
1394 LLVMBuildBr(b, b_input);
1396 /* build block handling input function call */
1397 LLVMPositionBuilderAtEnd(b, b_input);
1399 /* phi between resnull and output function call branches */
1401 LLVMValueRef incoming_values[2];
1402 LLVMBasicBlockRef incoming_blocks[2];
1404 incoming_values[0] = v_output_skip;
1405 incoming_blocks[0] = b_skipoutput;
1407 incoming_values[1] = v_output;
1408 incoming_blocks[1] = b_calloutput;
1410 v_output = LLVMBuildPhi(b, TypeSizeT, "output");
1411 LLVMAddIncoming(v_output,
1412 incoming_values, incoming_blocks,
1413 lengthof(incoming_blocks));
1417 * If input function is strict, skip if input string is
1420 if (op->d.iocoerce.finfo_in->fn_strict)
1423 LLVMBuildICmp(b, LLVMIntEQ, v_output,
1424 l_sizet_const(0), ""),
1430 LLVMBuildBr(b, b_inputcall);
1433 LLVMPositionBuilderAtEnd(b, b_inputcall);
1436 LLVMBuildStore(b, v_output,
1437 LLVMBuildStructGEP(b, v_in_argp, 0, ""));
1438 LLVMBuildStore(b, v_resnull,
1439 LLVMBuildStructGEP(b, v_in_argnullp, 0, ""));
1441 /* arg1: ioparam: preset in execExpr.c */
1442 /* arg2: typmod: preset in execExpr.c */
1444 /* reset fcinfo_in->isnull */
1445 LLVMBuildStore(b, l_sbool_const(0), v_fcinfo_in_isnullp);
1446 /* and call function */
1447 v_retval = LLVMBuildCall(b, v_fn_addr_in, &v_fcinfo_in, 1,
1448 "funccall_iocoerce_in");
1450 LLVMBuildStore(b, v_retval, v_resvaluep);
1452 LLVMBuildBr(b, opblocks[i + 1]);
1457 case EEOP_NOT_DISTINCT:
1459 FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
1461 LLVMValueRef v_fcinfo;
1462 LLVMValueRef v_fcinfo_isnull;
1464 LLVMValueRef v_argnullp;
1465 LLVMValueRef v_argnull0,
1467 LLVMValueRef v_argnull1,
1470 LLVMValueRef v_anyargisnull;
1471 LLVMValueRef v_bothargisnull;
1473 LLVMValueRef v_result;
1475 LLVMBasicBlockRef b_noargnull;
1476 LLVMBasicBlockRef b_checkbothargnull;
1477 LLVMBasicBlockRef b_bothargnull;
1478 LLVMBasicBlockRef b_anyargnull;
1480 b_noargnull = l_bb_before_v(opblocks[i + 1], "op.%d.noargnull", i);
1481 b_checkbothargnull = l_bb_before_v(opblocks[i + 1], "op.%d.checkbothargnull", i);
1482 b_bothargnull = l_bb_before_v(opblocks[i + 1], "op.%d.bothargnull", i);
1483 b_anyargnull = l_bb_before_v(opblocks[i + 1], "op.%d.anyargnull", i);
1485 v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
1488 LLVMBuildStructGEP(b,
1490 FIELDNO_FUNCTIONCALLINFODATA_ARGNULL,
1493 /* load argnull[0|1] for both arguments */
1494 v_argnull0 = l_load_struct_gep(b, v_argnullp, 0, "");
1495 v_argisnull0 = LLVMBuildICmp(b, LLVMIntEQ, v_argnull0,
1496 l_sbool_const(1), "");
1498 v_argnull1 = l_load_struct_gep(b, v_argnullp, 1, "");
1499 v_argisnull1 = LLVMBuildICmp(b, LLVMIntEQ, v_argnull1,
1500 l_sbool_const(1), "");
1502 v_anyargisnull = LLVMBuildOr(b, v_argisnull0, v_argisnull1, "");
1503 v_bothargisnull = LLVMBuildAnd(b, v_argisnull0, v_argisnull1, "");
1506 * Check function arguments for NULLness: If either is
1507 * NULL, we check if both args are NULL. Otherwise call
1510 LLVMBuildCondBr(b, v_anyargisnull, b_checkbothargnull,
1514 * build block checking if any arg is null
1516 LLVMPositionBuilderAtEnd(b, b_checkbothargnull);
1517 LLVMBuildCondBr(b, v_bothargisnull, b_bothargnull,
1521 /* Both NULL? Then is not distinct... */
1522 LLVMPositionBuilderAtEnd(b, b_bothargnull);
1523 LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1524 if (opcode == EEOP_NOT_DISTINCT)
1525 LLVMBuildStore(b, l_sizet_const(1), v_resvaluep);
1527 LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
1529 LLVMBuildBr(b, opblocks[i + 1]);
1531 /* Only one is NULL? Then is distinct... */
1532 LLVMPositionBuilderAtEnd(b, b_anyargnull);
1533 LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1534 if (opcode == EEOP_NOT_DISTINCT)
1535 LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
1537 LLVMBuildStore(b, l_sizet_const(1), v_resvaluep);
1538 LLVMBuildBr(b, opblocks[i + 1]);
1540 /* neither argument is null: compare */
1541 LLVMPositionBuilderAtEnd(b, b_noargnull);
1543 v_result = BuildV1Call(context, b, mod, fcinfo,
1546 if (opcode == EEOP_DISTINCT)
1548 /* Must invert result of "=" */
1551 LLVMBuildICmp(b, LLVMIntEQ,
1553 l_sizet_const(0), ""),
1557 LLVMBuildStore(b, v_fcinfo_isnull, v_resnullp);
1558 LLVMBuildStore(b, v_result, v_resvaluep);
1560 LLVMBuildBr(b, opblocks[i + 1]);
1566 FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
1568 LLVMValueRef v_fcinfo;
1569 LLVMValueRef v_fcinfo_isnull;
1570 LLVMValueRef v_argnullp;
1571 LLVMValueRef v_argnull0;
1572 LLVMValueRef v_argnull1;
1573 LLVMValueRef v_anyargisnull;
1574 LLVMValueRef v_argp;
1575 LLVMValueRef v_arg0;
1576 LLVMBasicBlockRef b_hasnull;
1577 LLVMBasicBlockRef b_nonull;
1578 LLVMBasicBlockRef b_argsequal;
1579 LLVMValueRef v_retval;
1580 LLVMValueRef v_argsequal;
1582 b_hasnull = l_bb_before_v(opblocks[i + 1],
1583 "b.%d.null-args", i);
1584 b_nonull = l_bb_before_v(opblocks[i + 1],
1585 "b.%d.no-null-args", i);
1586 b_argsequal = l_bb_before_v(opblocks[i + 1],
1587 "b.%d.argsequal", i);
1589 v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
1592 LLVMBuildStructGEP(b,
1594 FIELDNO_FUNCTIONCALLINFODATA_ARGNULL,
1598 LLVMBuildStructGEP(b,
1600 FIELDNO_FUNCTIONCALLINFODATA_ARG,
1603 /* if either argument is NULL they can't be equal */
1604 v_argnull0 = l_load_struct_gep(b, v_argnullp, 0, "");
1605 v_argnull1 = l_load_struct_gep(b, v_argnullp, 1, "");
1609 LLVMBuildICmp(b, LLVMIntEQ, v_argnull0,
1610 l_sbool_const(1), ""),
1611 LLVMBuildICmp(b, LLVMIntEQ, v_argnull1,
1612 l_sbool_const(1), ""),
1615 LLVMBuildCondBr(b, v_anyargisnull, b_hasnull, b_nonull);
1617 /* one (or both) of the arguments are null, return arg[0] */
1618 LLVMPositionBuilderAtEnd(b, b_hasnull);
1619 v_arg0 = l_load_struct_gep(b, v_argp, 0, "");
1620 LLVMBuildStore(b, v_argnull0, v_resnullp);
1621 LLVMBuildStore(b, v_arg0, v_resvaluep);
1622 LLVMBuildBr(b, opblocks[i + 1]);
1624 /* build block to invoke function and check result */
1625 LLVMPositionBuilderAtEnd(b, b_nonull);
1627 v_retval = BuildV1Call(context, b, mod, fcinfo, &v_fcinfo_isnull);
1630 * If result not null, and arguments are equal return null
1631 * (same result as if there'd been NULLs, hence reuse
1634 v_argsequal = LLVMBuildAnd(b,
1635 LLVMBuildICmp(b, LLVMIntEQ,
1639 LLVMBuildICmp(b, LLVMIntEQ,
1644 LLVMBuildCondBr(b, v_argsequal, b_argsequal, b_hasnull);
1646 /* build block setting result to NULL, if args are equal */
1647 LLVMPositionBuilderAtEnd(b, b_argsequal);
1648 LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
1649 LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
1650 LLVMBuildStore(b, v_retval, v_resvaluep);
1652 LLVMBuildBr(b, opblocks[i + 1]);
1656 case EEOP_SQLVALUEFUNCTION:
1657 build_EvalXFunc(b, mod, "ExecEvalSQLValueFunction",
1658 v_state, v_econtext, op);
1659 LLVMBuildBr(b, opblocks[i + 1]);
1662 case EEOP_CURRENTOFEXPR:
1663 build_EvalXFunc(b, mod, "ExecEvalCurrentOfExpr",
1664 v_state, v_econtext, op);
1665 LLVMBuildBr(b, opblocks[i + 1]);
1668 case EEOP_NEXTVALUEEXPR:
1669 build_EvalXFunc(b, mod, "ExecEvalNextValueExpr",
1670 v_state, v_econtext, op);
1671 LLVMBuildBr(b, opblocks[i + 1]);
1674 case EEOP_ARRAYEXPR:
1675 build_EvalXFunc(b, mod, "ExecEvalArrayExpr",
1676 v_state, v_econtext, op);
1677 LLVMBuildBr(b, opblocks[i + 1]);
1680 case EEOP_ARRAYCOERCE:
1681 build_EvalXFunc(b, mod, "ExecEvalArrayCoerce",
1682 v_state, v_econtext, op);
1683 LLVMBuildBr(b, opblocks[i + 1]);
1687 build_EvalXFunc(b, mod, "ExecEvalRow",
1688 v_state, v_econtext, op);
1689 LLVMBuildBr(b, opblocks[i + 1]);
1692 case EEOP_ROWCOMPARE_STEP:
1694 FunctionCallInfo fcinfo = op->d.rowcompare_step.fcinfo_data;
1695 LLVMValueRef v_fcinfo_isnull;
1696 LLVMBasicBlockRef b_null;
1697 LLVMBasicBlockRef b_compare;
1698 LLVMBasicBlockRef b_compare_result;
1700 LLVMValueRef v_retval;
1702 b_null = l_bb_before_v(opblocks[i + 1],
1703 "op.%d.row-null", i);
1704 b_compare = l_bb_before_v(opblocks[i + 1],
1705 "op.%d.row-compare", i);
1707 l_bb_before_v(opblocks[i + 1],
1708 "op.%d.row-compare-result",
1712 * If function is strict, and either arg is null, we're
1715 if (op->d.rowcompare_step.finfo->fn_strict)
1717 LLVMValueRef v_fcinfo;
1718 LLVMValueRef v_argnullp;
1719 LLVMValueRef v_argnull0;
1720 LLVMValueRef v_argnull1;
1721 LLVMValueRef v_anyargisnull;
1723 v_fcinfo = l_ptr_const(fcinfo,
1724 l_ptr(StructFunctionCallInfoData));
1727 LLVMBuildStructGEP(b, v_fcinfo,
1728 FIELDNO_FUNCTIONCALLINFODATA_ARGNULL,
1731 v_argnull0 = l_load_struct_gep(b, v_argnullp, 0, "");
1732 v_argnull1 = l_load_struct_gep(b, v_argnullp, 1, "");
1741 LLVMBuildICmp(b, LLVMIntEQ,
1743 l_sbool_const(1), ""),
1746 LLVMBuildCondBr(b, v_anyargisnull, b_null, b_compare);
1750 LLVMBuildBr(b, b_compare);
1753 /* build block invoking comparison function */
1754 LLVMPositionBuilderAtEnd(b, b_compare);
1757 v_retval = BuildV1Call(context, b, mod, fcinfo,
1759 LLVMBuildStore(b, v_retval, v_resvaluep);
1761 /* if result of function is NULL, force NULL result */
1771 /* build block analyzing the !NULL comparator result */
1772 LLVMPositionBuilderAtEnd(b, b_compare_result);
1774 /* if results equal, compare next, otherwise done */
1779 l_sizet_const(0), ""),
1781 opblocks[op->d.rowcompare_step.jumpdone]);
1784 * Build block handling NULL input or NULL comparator
1787 LLVMPositionBuilderAtEnd(b, b_null);
1788 LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
1789 LLVMBuildBr(b, opblocks[op->d.rowcompare_step.jumpnull]);
1794 case EEOP_ROWCOMPARE_FINAL:
1796 RowCompareType rctype = op->d.rowcompare_final.rctype;
1798 LLVMValueRef v_cmpresult;
1799 LLVMValueRef v_result;
1800 LLVMIntPredicate predicate;
1803 * Btree comparators return 32 bit results, need to be
1804 * careful about sign (used as a 64 bit value it's
1809 LLVMBuildLoad(b, v_resvaluep, ""),
1810 LLVMInt32Type(), "");
1815 predicate = LLVMIntSLT;
1818 predicate = LLVMIntSLE;
1821 predicate = LLVMIntSGT;
1824 predicate = LLVMIntSGE;
1827 /* EQ and NE cases aren't allowed here */
1829 predicate = 0; /* prevent compiler warning */
1833 v_result = LLVMBuildICmp(b,
1838 v_result = LLVMBuildZExt(b, v_result, TypeSizeT, "");
1840 LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1841 LLVMBuildStore(b, v_result, v_resvaluep);
1843 LLVMBuildBr(b, opblocks[i + 1]);
1848 build_EvalXFunc(b, mod, "ExecEvalMinMax",
1849 v_state, v_econtext, op);
1850 LLVMBuildBr(b, opblocks[i + 1]);
1853 case EEOP_FIELDSELECT:
1854 build_EvalXFunc(b, mod, "ExecEvalFieldSelect",
1855 v_state, v_econtext, op);
1856 LLVMBuildBr(b, opblocks[i + 1]);
1859 case EEOP_FIELDSTORE_DEFORM:
1860 build_EvalXFunc(b, mod, "ExecEvalFieldStoreDeForm",
1861 v_state, v_econtext, op);
1862 LLVMBuildBr(b, opblocks[i + 1]);
1865 case EEOP_FIELDSTORE_FORM:
1866 build_EvalXFunc(b, mod, "ExecEvalFieldStoreForm",
1867 v_state, v_econtext, op);
1868 LLVMBuildBr(b, opblocks[i + 1]);
1871 case EEOP_ARRAYREF_SUBSCRIPT:
1874 int jumpdone = op->d.arrayref_subscript.jumpdone;
1875 LLVMValueRef v_params[2];
1878 v_fn = llvm_get_decl(mod, FuncExecEvalArrayRefSubscript);
1880 v_params[0] = v_state;
1881 v_params[1] = l_ptr_const(op, l_ptr(StructExprEvalStep));
1882 v_ret = LLVMBuildCall(b, v_fn,
1883 v_params, lengthof(v_params), "");
1884 v_ret = LLVMBuildZExt(b, v_ret, TypeStorageBool, "");
1887 LLVMBuildICmp(b, LLVMIntEQ, v_ret,
1888 l_sbool_const(1), ""),
1890 opblocks[jumpdone]);
1894 case EEOP_DOMAIN_TESTVAL:
1896 LLVMBasicBlockRef b_avail,
1898 LLVMValueRef v_casevaluep,
1900 LLVMValueRef v_casenullp,
1902 LLVMValueRef v_casevaluenull;
1904 b_avail = l_bb_before_v(opblocks[i + 1],
1906 b_notavail = l_bb_before_v(opblocks[i + 1],
1907 "op.%d.notavail", i);
1909 v_casevaluep = l_ptr_const(op->d.casetest.value,
1911 v_casenullp = l_ptr_const(op->d.casetest.isnull,
1912 l_ptr(TypeStorageBool));
1915 LLVMBuildICmp(b, LLVMIntEQ,
1916 LLVMBuildPtrToInt(b, v_casevaluep,
1918 l_sizet_const(0), "");
1921 b_notavail, b_avail);
1923 /* if casetest != NULL */
1924 LLVMPositionBuilderAtEnd(b, b_avail);
1925 v_casevalue = LLVMBuildLoad(b, v_casevaluep, "");
1926 v_casenull = LLVMBuildLoad(b, v_casenullp, "");
1927 LLVMBuildStore(b, v_casevalue, v_resvaluep);
1928 LLVMBuildStore(b, v_casenull, v_resnullp);
1929 LLVMBuildBr(b, opblocks[i + 1]);
1931 /* if casetest == NULL */
1932 LLVMPositionBuilderAtEnd(b, b_notavail);
1934 l_load_struct_gep(b, v_econtext,
1935 FIELDNO_EXPRCONTEXT_DOMAINDATUM,
1938 l_load_struct_gep(b, v_econtext,
1939 FIELDNO_EXPRCONTEXT_DOMAINNULL,
1941 LLVMBuildStore(b, v_casevalue, v_resvaluep);
1942 LLVMBuildStore(b, v_casenull, v_resnullp);
1944 LLVMBuildBr(b, opblocks[i + 1]);
1948 case EEOP_DOMAIN_NOTNULL:
1949 build_EvalXFunc(b, mod, "ExecEvalConstraintNotNull",
1950 v_state, v_econtext, op);
1951 LLVMBuildBr(b, opblocks[i + 1]);
1954 case EEOP_DOMAIN_CHECK:
1955 build_EvalXFunc(b, mod, "ExecEvalConstraintCheck",
1956 v_state, v_econtext, op);
1957 LLVMBuildBr(b, opblocks[i + 1]);
1960 case EEOP_CONVERT_ROWTYPE:
1961 build_EvalXFunc(b, mod, "ExecEvalConvertRowtype",
1962 v_state, v_econtext, op);
1963 LLVMBuildBr(b, opblocks[i + 1]);
1966 case EEOP_SCALARARRAYOP:
1967 build_EvalXFunc(b, mod, "ExecEvalScalarArrayOp",
1968 v_state, v_econtext, op);
1969 LLVMBuildBr(b, opblocks[i + 1]);
1973 build_EvalXFunc(b, mod, "ExecEvalXmlExpr",
1974 v_state, v_econtext, op);
1975 LLVMBuildBr(b, opblocks[i + 1]);
1980 AggrefExprState *aggref = op->d.aggref.astate;
1981 LLVMValueRef v_aggnop;
1982 LLVMValueRef v_aggno;
1987 * At this point aggref->aggno is not yet set (it's set up
1988 * in ExecInitAgg() after initializing the expression). So
1989 * load it from memory each time round.
1991 v_aggnop = l_ptr_const(&aggref->aggno,
1992 l_ptr(LLVMInt32Type()));
1993 v_aggno = LLVMBuildLoad(b, v_aggnop, "v_aggno");
1995 /* load agg value / null */
1996 value = l_load_gep1(b, v_aggvalues, v_aggno, "aggvalue");
1997 isnull = l_load_gep1(b, v_aggnulls, v_aggno, "aggnull");
1999 /* and store result */
2000 LLVMBuildStore(b, value, v_resvaluep);
2001 LLVMBuildStore(b, isnull, v_resnullp);
2003 LLVMBuildBr(b, opblocks[i + 1]);
2007 case EEOP_GROUPING_FUNC:
2008 build_EvalXFunc(b, mod, "ExecEvalGroupingFunc",
2009 v_state, v_econtext, op);
2010 LLVMBuildBr(b, opblocks[i + 1]);
2013 case EEOP_WINDOW_FUNC:
2015 WindowFuncExprState *wfunc = op->d.window_func.wfstate;
2016 LLVMValueRef v_wfuncnop;
2017 LLVMValueRef v_wfuncno;
2022 * At this point aggref->wfuncno is not yet set (it's set
2023 * up in ExecInitWindowAgg() after initializing the
2024 * expression). So load it from memory each time round.
2026 v_wfuncnop = l_ptr_const(&wfunc->wfuncno,
2027 l_ptr(LLVMInt32Type()));
2028 v_wfuncno = LLVMBuildLoad(b, v_wfuncnop, "v_wfuncno");
2030 /* load window func value / null */
2031 value = l_load_gep1(b, v_aggvalues, v_wfuncno,
2033 isnull = l_load_gep1(b, v_aggnulls, v_wfuncno,
2036 LLVMBuildStore(b, value, v_resvaluep);
2037 LLVMBuildStore(b, isnull, v_resnullp);
2039 LLVMBuildBr(b, opblocks[i + 1]);
2044 build_EvalXFunc(b, mod, "ExecEvalSubPlan",
2045 v_state, v_econtext, op);
2046 LLVMBuildBr(b, opblocks[i + 1]);
2049 case EEOP_ALTERNATIVE_SUBPLAN:
2050 build_EvalXFunc(b, mod, "ExecEvalAlternativeSubPlan",
2051 v_state, v_econtext, op);
2052 LLVMBuildBr(b, opblocks[i + 1]);
2055 case EEOP_AGG_STRICT_DESERIALIZE:
2057 FunctionCallInfo fcinfo = op->d.agg_deserialize.fcinfo_data;
2058 LLVMValueRef v_fcinfo;
2059 LLVMValueRef v_argnullp;
2060 LLVMValueRef v_argnull0;
2061 LLVMBasicBlockRef b_deserialize;
2063 b_deserialize = l_bb_before_v(opblocks[i + 1],
2064 "op.%d.deserialize", i);
2066 v_fcinfo = l_ptr_const(fcinfo,
2067 l_ptr(StructFunctionCallInfoData));
2070 LLVMBuildStructGEP(b,
2072 FIELDNO_FUNCTIONCALLINFODATA_ARGNULL,
2075 l_load_struct_gep(b, v_argnullp, 0, "v_argnull0");
2083 opblocks[op->d.agg_deserialize.jumpnull],
2085 LLVMPositionBuilderAtEnd(b, b_deserialize);
2089 case EEOP_AGG_DESERIALIZE:
2092 FunctionCallInfo fcinfo;
2094 LLVMValueRef v_retval;
2095 LLVMValueRef v_fcinfo_isnull;
2096 LLVMValueRef v_tmpcontext;
2097 LLVMValueRef v_oldcontext;
2099 aggstate = op->d.agg_deserialize.aggstate;
2100 fcinfo = op->d.agg_deserialize.fcinfo_data;
2103 l_ptr_const(aggstate->tmpcontext->ecxt_per_tuple_memory,
2104 l_ptr(StructMemoryContextData));
2105 v_oldcontext = l_mcxt_switch(mod, b, v_tmpcontext);
2106 v_retval = BuildV1Call(context, b, mod, fcinfo,
2108 l_mcxt_switch(mod, b, v_oldcontext);
2110 LLVMBuildStore(b, v_retval, v_resvaluep);
2111 LLVMBuildStore(b, v_fcinfo_isnull, v_resnullp);
2113 LLVMBuildBr(b, opblocks[i + 1]);
2117 case EEOP_AGG_STRICT_INPUT_CHECK:
2119 int nargs = op->d.agg_strict_input_check.nargs;
2120 bool *nulls = op->d.agg_strict_input_check.nulls;
2124 LLVMValueRef v_nullp;
2125 LLVMBasicBlockRef *b_checknulls;
2127 jumpnull = op->d.agg_strict_input_check.jumpnull;
2128 v_nullp = l_ptr_const(nulls, l_ptr(TypeStorageBool));
2130 /* create blocks for checking args */
2131 b_checknulls = palloc(sizeof(LLVMBasicBlockRef *) * nargs);
2132 for (argno = 0; argno < nargs; argno++)
2134 b_checknulls[argno] =
2135 l_bb_before_v(opblocks[i + 1],
2136 "op.%d.check-null.%d",
2140 LLVMBuildBr(b, b_checknulls[0]);
2142 /* strict function, check for NULL args */
2143 for (argno = 0; argno < nargs; argno++)
2145 LLVMValueRef v_argno = l_int32_const(argno);
2146 LLVMValueRef v_argisnull;
2147 LLVMBasicBlockRef b_argnotnull;
2149 LLVMPositionBuilderAtEnd(b, b_checknulls[argno]);
2151 if (argno + 1 == nargs)
2152 b_argnotnull = opblocks[i + 1];
2154 b_argnotnull = b_checknulls[argno + 1];
2156 v_argisnull = l_load_gep1(b, v_nullp, v_argno, "");
2162 l_sbool_const(1), ""),
2170 case EEOP_AGG_INIT_TRANS:
2173 AggStatePerTrans pertrans;
2175 LLVMValueRef v_aggstatep;
2176 LLVMValueRef v_pertransp;
2178 LLVMValueRef v_allpergroupsp;
2180 LLVMValueRef v_pergroupp;
2182 LLVMValueRef v_setoff,
2185 LLVMValueRef v_notransvalue;
2187 LLVMBasicBlockRef b_init;
2189 aggstate = op->d.agg_init_trans.aggstate;
2190 pertrans = op->d.agg_init_trans.pertrans;
2192 v_aggstatep = l_ptr_const(aggstate,
2193 l_ptr(StructAggState));
2194 v_pertransp = l_ptr_const(pertrans,
2195 l_ptr(StructAggStatePerTransData));
2198 * pergroup = &aggstate->all_pergroups
2199 * [op->d.agg_init_trans_check.setoff]
2200 * [op->d.agg_init_trans_check.transno];
2203 l_load_struct_gep(b, v_aggstatep,
2204 FIELDNO_AGGSTATE_ALL_PERGROUPS,
2205 "aggstate.all_pergroups");
2206 v_setoff = l_int32_const(op->d.agg_init_trans.setoff);
2207 v_transno = l_int32_const(op->d.agg_init_trans.transno);
2210 l_load_gep1(b, v_allpergroupsp, v_setoff, ""),
2214 l_load_struct_gep(b, v_pergroupp,
2215 FIELDNO_AGGSTATEPERGROUPDATA_NOTRANSVALUE,
2218 b_init = l_bb_before_v(opblocks[i + 1],
2219 "op.%d.inittrans", i);
2222 LLVMBuildICmp(b, LLVMIntEQ, v_notransvalue,
2223 l_sbool_const(1), ""),
2227 LLVMPositionBuilderAtEnd(b, b_init);
2230 LLVMValueRef params[3];
2232 params[0] = v_aggstatep;
2233 params[1] = v_pertransp;
2234 params[2] = v_pergroupp;
2237 llvm_get_decl(mod, FuncExecAggInitGroup),
2238 params, lengthof(params),
2241 LLVMBuildBr(b, opblocks[op->d.agg_init_trans.jumpnull]);
2246 case EEOP_AGG_STRICT_TRANS_CHECK:
2249 LLVMValueRef v_setoff,
2252 LLVMValueRef v_aggstatep;
2253 LLVMValueRef v_allpergroupsp;
2255 LLVMValueRef v_transnull;
2256 LLVMValueRef v_pergroupp;
2258 int jumpnull = op->d.agg_strict_trans_check.jumpnull;
2260 aggstate = op->d.agg_strict_trans_check.aggstate;
2261 v_aggstatep = l_ptr_const(aggstate, l_ptr(StructAggState));
2264 * pergroup = &aggstate->all_pergroups
2265 * [op->d.agg_strict_trans_check.setoff]
2266 * [op->d.agg_init_trans_check.transno];
2269 l_load_struct_gep(b, v_aggstatep,
2270 FIELDNO_AGGSTATE_ALL_PERGROUPS,
2271 "aggstate.all_pergroups");
2273 l_int32_const(op->d.agg_strict_trans_check.setoff);
2275 l_int32_const(op->d.agg_strict_trans_check.transno);
2278 l_load_gep1(b, v_allpergroupsp, v_setoff, ""),
2282 l_load_struct_gep(b, v_pergroupp,
2283 FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL,
2287 LLVMBuildICmp(b, LLVMIntEQ, v_transnull,
2288 l_sbool_const(1), ""),
2295 case EEOP_AGG_PLAIN_TRANS_BYVAL:
2296 case EEOP_AGG_PLAIN_TRANS:
2299 AggStatePerTrans pertrans;
2300 FunctionCallInfo fcinfo;
2302 LLVMValueRef v_aggstatep;
2303 LLVMValueRef v_fcinfo;
2304 LLVMValueRef v_fcinfo_isnull;
2305 LLVMValueRef v_argp,
2308 LLVMValueRef v_transvaluep;
2309 LLVMValueRef v_transnullp;
2311 LLVMValueRef v_setoff;
2312 LLVMValueRef v_transno;
2314 LLVMValueRef v_aggcontext;
2316 LLVMValueRef v_allpergroupsp;
2317 LLVMValueRef v_current_setp;
2318 LLVMValueRef v_current_pertransp;
2319 LLVMValueRef v_curaggcontext;
2321 LLVMValueRef v_pertransp;
2323 LLVMValueRef v_pergroupp;
2325 LLVMValueRef v_retval;
2327 LLVMValueRef v_tmpcontext;
2328 LLVMValueRef v_oldcontext;
2330 aggstate = op->d.agg_trans.aggstate;
2331 pertrans = op->d.agg_trans.pertrans;
2333 fcinfo = &pertrans->transfn_fcinfo;
2335 v_aggstatep = l_ptr_const(aggstate,
2336 l_ptr(StructAggState));
2337 v_pertransp = l_ptr_const(pertrans,
2338 l_ptr(StructAggStatePerTransData));
2341 * pergroup = &aggstate->all_pergroups
2342 * [op->d.agg_strict_trans_check.setoff]
2343 * [op->d.agg_init_trans_check.transno];
2346 l_load_struct_gep(b, v_aggstatep,
2347 FIELDNO_AGGSTATE_ALL_PERGROUPS,
2348 "aggstate.all_pergroups");
2349 v_setoff = l_int32_const(op->d.agg_trans.setoff);
2350 v_transno = l_int32_const(op->d.agg_trans.transno);
2353 l_load_gep1(b, v_allpergroupsp, v_setoff, ""),
2356 v_fcinfo = l_ptr_const(fcinfo,
2357 l_ptr(StructFunctionCallInfoData));
2360 LLVMBuildStructGEP(b,
2362 FIELDNO_FUNCTIONCALLINFODATA_ARGNULL,
2365 LLVMBuildStructGEP(b,
2367 FIELDNO_FUNCTIONCALLINFODATA_ARG,
2370 v_aggcontext = l_ptr_const(op->d.agg_trans.aggcontext,
2371 l_ptr(StructExprContext));
2374 LLVMBuildStructGEP(b,
2376 FIELDNO_AGGSTATE_CURRENT_SET,
2377 "aggstate.current_set");
2379 LLVMBuildStructGEP(b,
2381 FIELDNO_AGGSTATE_CURAGGCONTEXT,
2382 "aggstate.curaggcontext");
2383 v_current_pertransp =
2384 LLVMBuildStructGEP(b,
2386 FIELDNO_AGGSTATE_CURPERTRANS,
2387 "aggstate.curpertrans");
2389 /* set aggstate globals */
2390 LLVMBuildStore(b, v_aggcontext, v_curaggcontext);
2391 LLVMBuildStore(b, l_int32_const(op->d.agg_trans.setno),
2393 LLVMBuildStore(b, v_pertransp, v_current_pertransp);
2395 /* invoke transition function in per-tuple context */
2397 l_ptr_const(aggstate->tmpcontext->ecxt_per_tuple_memory,
2398 l_ptr(StructMemoryContextData));
2399 v_oldcontext = l_mcxt_switch(mod, b, v_tmpcontext);
2401 /* store transvalue in fcinfo->arg/argnull[0] */
2403 LLVMBuildStructGEP(b, v_pergroupp,
2404 FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUE,
2407 LLVMBuildStructGEP(b, v_pergroupp,
2408 FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL,
2411 LLVMBuildLoad(b, v_transvaluep,
2413 LLVMBuildStructGEP(b, v_argp, 0, ""));
2415 LLVMBuildLoad(b, v_transnullp, "transnull"),
2416 LLVMBuildStructGEP(b, v_argnullp, 0, ""));
2418 /* and invoke transition function */
2419 v_retval = BuildV1Call(context, b, mod, fcinfo,
2423 * For pass-by-ref datatype, must copy the new value into
2424 * aggcontext and free the prior transValue. But if
2425 * transfn returned a pointer to its first input, we don't
2426 * need to do anything. Also, if transfn returned a
2427 * pointer to a R/W expanded object that is already a
2428 * child of the aggcontext, assume we can adopt that value
2429 * without copying it.
2431 if (opcode == EEOP_AGG_PLAIN_TRANS)
2433 LLVMBasicBlockRef b_call;
2434 LLVMBasicBlockRef b_nocall;
2436 LLVMValueRef v_transvalue;
2437 LLVMValueRef v_transnull;
2438 LLVMValueRef v_newval;
2439 LLVMValueRef params[6];
2441 b_call = l_bb_before_v(opblocks[i + 1],
2442 "op.%d.transcall", i);
2443 b_nocall = l_bb_before_v(opblocks[i + 1],
2444 "op.%d.transnocall", i);
2446 v_transvalue = LLVMBuildLoad(b, v_transvaluep, "");
2447 v_transnull = LLVMBuildLoad(b, v_transnullp, "");
2450 * DatumGetPointer(newVal) !=
2451 * DatumGetPointer(pergroup->transValue))
2454 LLVMBuildICmp(b, LLVMIntEQ,
2459 /* returned datum not passed datum, reparent */
2460 LLVMPositionBuilderAtEnd(b, b_call);
2462 params[0] = v_aggstatep;
2463 params[1] = v_pertransp;
2464 params[2] = v_retval;
2465 params[3] = LLVMBuildTrunc(b, v_fcinfo_isnull,
2467 params[4] = v_transvalue;
2468 params[5] = LLVMBuildTrunc(b, v_transnull,
2471 v_fn = llvm_get_decl(mod, FuncExecAggTransReparent);
2473 LLVMBuildCall(b, v_fn,
2474 params, lengthof(params),
2477 /* store trans value */
2478 LLVMBuildStore(b, v_newval, v_transvaluep);
2479 LLVMBuildStore(b, v_fcinfo_isnull, v_transnullp);
2480 LLVMBuildBr(b, opblocks[i + 1]);
2482 /* returned datum passed datum, no need to reparent */
2483 LLVMPositionBuilderAtEnd(b, b_nocall);
2486 /* store trans value */
2487 LLVMBuildStore(b, v_retval, v_transvaluep);
2488 LLVMBuildStore(b, v_fcinfo_isnull, v_transnullp);
2490 l_mcxt_switch(mod, b, v_oldcontext);
2492 LLVMBuildBr(b, opblocks[i + 1]);
2496 case EEOP_AGG_ORDERED_TRANS_DATUM:
2497 build_EvalXFunc(b, mod, "ExecEvalAggOrderedTransDatum",
2498 v_state, v_econtext, op);
2499 LLVMBuildBr(b, opblocks[i + 1]);
2502 case EEOP_AGG_ORDERED_TRANS_TUPLE:
2503 build_EvalXFunc(b, mod, "ExecEvalAggOrderedTransTuple",
2504 v_state, v_econtext, op);
2505 LLVMBuildBr(b, opblocks[i + 1]);
2514 LLVMDisposeBuilder(b);
2517 * Don't immediately emit function, instead do so the first time the
2518 * expression is actually evaluated. That allows to emit a lot of
2519 * functions together, avoiding a lot of repeated llvm and memory
2520 * remapping overhead.
2524 CompiledExprState *cstate = palloc0(sizeof(CompiledExprState));
2526 cstate->context = context;
2527 cstate->funcname = funcname;
2529 state->evalfunc = ExecRunCompiledExpr;
2530 state->evalfunc_private = cstate;
2533 llvm_leave_fatal_on_oom();
2535 INSTR_TIME_SET_CURRENT(endtime);
2536 INSTR_TIME_ACCUM_DIFF(context->base.generation_counter,
2537 endtime, starttime);
2543 * Run compiled expression.
2545 * This will only be called the first time a JITed expression is called. We
2546 * first make sure the expression is still up2date, and then get a pointer to
2547 * the emitted function. The latter can be the first thing that triggers
2548 * optimizing and emitting all the generated functions.
2551 ExecRunCompiledExpr(ExprState *state, ExprContext *econtext, bool *isNull)
2553 CompiledExprState *cstate = state->evalfunc_private;
2554 ExprStateEvalFunc func;
2556 CheckExprStillValid(state, econtext);
2558 llvm_enter_fatal_on_oom();
2559 func = (ExprStateEvalFunc) llvm_get_function(cstate->context,
2561 llvm_leave_fatal_on_oom();
2564 /* remove indirection via this function for future calls */
2565 state->evalfunc = func;
2567 return func(state, econtext, isNull);
2571 BuildV1Call(LLVMJitContext *context, LLVMBuilderRef b,
2572 LLVMModuleRef mod, FunctionCallInfo fcinfo,
2573 LLVMValueRef *v_fcinfo_isnull)
2576 LLVMValueRef v_fcinfo_isnullp;
2577 LLVMValueRef v_retval;
2578 LLVMValueRef v_fcinfo;
2580 v_fn = llvm_function_reference(context, b, mod, fcinfo);
2582 v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
2583 v_fcinfo_isnullp = LLVMBuildStructGEP(b, v_fcinfo,
2584 FIELDNO_FUNCTIONCALLINFODATA_ISNULL,
2586 LLVMBuildStore(b, l_sbool_const(0), v_fcinfo_isnullp);
2588 v_retval = LLVMBuildCall(b, v_fn, &v_fcinfo, 1, "funccall");
2590 if (v_fcinfo_isnull)
2591 *v_fcinfo_isnull = LLVMBuildLoad(b, v_fcinfo_isnullp, "");
2594 * Add lifetime-end annotation, signalling that writes to memory don't
2595 * have to be retained (important for inlining potential).
2598 LLVMValueRef v_lifetime = create_LifetimeEnd(mod);
2599 LLVMValueRef params[2];
2601 params[0] = l_int64_const(sizeof(fcinfo->arg));
2602 params[1] = l_ptr_const(fcinfo->arg, l_ptr(LLVMInt8Type()));
2603 LLVMBuildCall(b, v_lifetime, params, lengthof(params), "");
2605 params[0] = l_int64_const(sizeof(fcinfo->argnull));
2606 params[1] = l_ptr_const(fcinfo->argnull, l_ptr(LLVMInt8Type()));
2607 LLVMBuildCall(b, v_lifetime, params, lengthof(params), "");
2609 params[0] = l_int64_const(sizeof(fcinfo->isnull));
2610 params[1] = l_ptr_const(&fcinfo->isnull, l_ptr(LLVMInt8Type()));
2611 LLVMBuildCall(b, v_lifetime, params, lengthof(params), "");
2618 * Implement an expression step by calling the function funcname.
2621 build_EvalXFunc(LLVMBuilderRef b, LLVMModuleRef mod, const char *funcname,
2622 LLVMValueRef v_state, LLVMValueRef v_econtext,
2627 LLVMTypeRef param_types[3];
2628 LLVMValueRef params[3];
2630 v_fn = LLVMGetNamedFunction(mod, funcname);
2633 param_types[0] = l_ptr(StructExprState);
2634 param_types[1] = l_ptr(StructExprEvalStep);
2635 param_types[2] = l_ptr(StructExprContext);
2637 sig = LLVMFunctionType(LLVMVoidType(),
2638 param_types, lengthof(param_types),
2640 v_fn = LLVMAddFunction(mod, funcname, sig);
2643 params[0] = v_state;
2644 params[1] = l_ptr_const(op, l_ptr(StructExprEvalStep));
2645 params[2] = v_econtext;
2649 params, lengthof(params), "");
2653 create_LifetimeEnd(LLVMModuleRef mod)
2657 LLVMTypeRef param_types[2];
2659 /* LLVM 5+ has a variadic pointer argument */
2660 #if LLVM_VERSION_MAJOR < 5
2661 const char *nm = "llvm.lifetime.end";
2663 const char *nm = "llvm.lifetime.end.p0i8";
2666 fn = LLVMGetNamedFunction(mod, nm);
2670 param_types[0] = LLVMInt64Type();
2671 param_types[1] = l_ptr(LLVMInt8Type());
2673 sig = LLVMFunctionType(LLVMVoidType(),
2674 param_types, lengthof(param_types),
2676 fn = LLVMAddFunction(mod, nm, sig);
2678 LLVMSetFunctionCallConv(fn, LLVMCCallConv);
2680 Assert(LLVMGetIntrinsicID(fn));