1 /*-------------------------------------------------------------------------
4 * JIT compile expressions.
6 * Portions Copyright (c) 1996-2025, 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 "catalog/objectaccess.h"
24 #include "catalog/pg_type.h"
25 #include "executor/execExpr.h"
26 #include "executor/execdebug.h"
27 #include "executor/nodeAgg.h"
28 #include "executor/nodeSubplan.h"
30 #include "jit/llvmjit.h"
31 #include "jit/llvmjit_emit.h"
32 #include "miscadmin.h"
33 #include "nodes/makefuncs.h"
34 #include "nodes/nodeFuncs.h"
35 #include "parser/parse_coerce.h"
36 #include "parser/parsetree.h"
38 #include "utils/acl.h"
39 #include "utils/builtins.h"
40 #include "utils/date.h"
41 #include "utils/fmgrtab.h"
42 #include "utils/lsyscache.h"
43 #include "utils/memutils.h"
44 #include "utils/timestamp.h"
45 #include "utils/typcache.h"
46 #include "utils/xml.h"
48 typedef struct CompiledExprState
50 LLVMJitContext
*context
;
55 static Datum
ExecRunCompiledExpr(ExprState
*state
, ExprContext
*econtext
, bool *isNull
);
57 static LLVMValueRef
BuildV1Call(LLVMJitContext
*context
, LLVMBuilderRef b
,
58 LLVMModuleRef mod
, FunctionCallInfo fcinfo
,
59 LLVMValueRef
*v_fcinfo_isnull
);
60 static LLVMValueRef
build_EvalXFuncInt(LLVMBuilderRef b
, LLVMModuleRef mod
,
64 int natts
, LLVMValueRef
*v_args
);
65 static LLVMValueRef
create_LifetimeEnd(LLVMModuleRef mod
);
67 /* macro making it easier to call ExecEval* functions */
68 #define build_EvalXFunc(b, mod, funcname, v_state, op, ...) \
69 build_EvalXFuncInt(b, mod, funcname, v_state, op, \
70 lengthof(((LLVMValueRef[]){__VA_ARGS__})), \
71 ((LLVMValueRef[]){__VA_ARGS__}))
75 * JIT compile expression.
78 llvm_compile_expr(ExprState
*state
)
80 PlanState
*parent
= state
->parent
;
83 LLVMJitContext
*context
= NULL
;
89 LLVMBasicBlockRef entry
;
90 LLVMBasicBlockRef
*opblocks
;
94 LLVMValueRef v_econtext
;
95 LLVMValueRef v_parent
;
98 LLVMValueRef v_isnullp
;
100 /* tmp vars in state */
101 LLVMValueRef v_tmpvaluep
;
102 LLVMValueRef v_tmpisnullp
;
105 LLVMValueRef v_innerslot
;
106 LLVMValueRef v_outerslot
;
107 LLVMValueRef v_scanslot
;
108 LLVMValueRef v_resultslot
;
110 /* nulls/values of slots */
111 LLVMValueRef v_innervalues
;
112 LLVMValueRef v_innernulls
;
113 LLVMValueRef v_outervalues
;
114 LLVMValueRef v_outernulls
;
115 LLVMValueRef v_scanvalues
;
116 LLVMValueRef v_scannulls
;
117 LLVMValueRef v_resultvalues
;
118 LLVMValueRef v_resultnulls
;
120 /* stuff in econtext */
121 LLVMValueRef v_aggvalues
;
122 LLVMValueRef v_aggnulls
;
124 instr_time starttime
;
125 instr_time deform_starttime
;
127 instr_time deform_endtime
;
129 llvm_enter_fatal_on_oom();
132 * Right now we don't support compiling expressions without a parent, as
133 * we need access to the EState.
137 /* get or create JIT context */
138 if (parent
->state
->es_jit
)
139 context
= (LLVMJitContext
*) parent
->state
->es_jit
;
142 context
= llvm_create_context(parent
->state
->es_jit_flags
);
143 parent
->state
->es_jit
= &context
->base
;
146 INSTR_TIME_SET_CURRENT(starttime
);
148 mod
= llvm_mutable_module(context
);
149 lc
= LLVMGetModuleContext(mod
);
151 b
= LLVMCreateBuilderInContext(lc
);
153 funcname
= llvm_expand_funcname(context
, "evalexpr");
155 /* create function */
156 eval_fn
= LLVMAddFunction(mod
, funcname
,
157 llvm_pg_var_func_type("ExecInterpExprStillValid"));
158 LLVMSetLinkage(eval_fn
, LLVMExternalLinkage
);
159 LLVMSetVisibility(eval_fn
, LLVMDefaultVisibility
);
160 llvm_copy_attributes(AttributeTemplate
, eval_fn
);
162 entry
= LLVMAppendBasicBlockInContext(lc
, eval_fn
, "entry");
165 v_state
= LLVMGetParam(eval_fn
, 0);
166 v_econtext
= LLVMGetParam(eval_fn
, 1);
167 v_isnullp
= LLVMGetParam(eval_fn
, 2);
169 LLVMPositionBuilderAtEnd(b
, entry
);
171 v_tmpvaluep
= l_struct_gep(b
,
174 FIELDNO_EXPRSTATE_RESVALUE
,
176 v_tmpisnullp
= l_struct_gep(b
,
179 FIELDNO_EXPRSTATE_RESNULL
,
181 v_parent
= l_load_struct_gep(b
,
184 FIELDNO_EXPRSTATE_PARENT
,
187 /* build global slots */
188 v_scanslot
= l_load_struct_gep(b
,
191 FIELDNO_EXPRCONTEXT_SCANTUPLE
,
193 v_innerslot
= l_load_struct_gep(b
,
196 FIELDNO_EXPRCONTEXT_INNERTUPLE
,
198 v_outerslot
= l_load_struct_gep(b
,
201 FIELDNO_EXPRCONTEXT_OUTERTUPLE
,
203 v_resultslot
= l_load_struct_gep(b
,
206 FIELDNO_EXPRSTATE_RESULTSLOT
,
209 /* build global values/isnull pointers */
210 v_scanvalues
= l_load_struct_gep(b
,
211 StructTupleTableSlot
,
213 FIELDNO_TUPLETABLESLOT_VALUES
,
215 v_scannulls
= l_load_struct_gep(b
,
216 StructTupleTableSlot
,
218 FIELDNO_TUPLETABLESLOT_ISNULL
,
220 v_innervalues
= l_load_struct_gep(b
,
221 StructTupleTableSlot
,
223 FIELDNO_TUPLETABLESLOT_VALUES
,
225 v_innernulls
= l_load_struct_gep(b
,
226 StructTupleTableSlot
,
228 FIELDNO_TUPLETABLESLOT_ISNULL
,
230 v_outervalues
= l_load_struct_gep(b
,
231 StructTupleTableSlot
,
233 FIELDNO_TUPLETABLESLOT_VALUES
,
235 v_outernulls
= l_load_struct_gep(b
,
236 StructTupleTableSlot
,
238 FIELDNO_TUPLETABLESLOT_ISNULL
,
240 v_resultvalues
= l_load_struct_gep(b
,
241 StructTupleTableSlot
,
243 FIELDNO_TUPLETABLESLOT_VALUES
,
245 v_resultnulls
= l_load_struct_gep(b
,
246 StructTupleTableSlot
,
248 FIELDNO_TUPLETABLESLOT_ISNULL
,
251 /* aggvalues/aggnulls */
252 v_aggvalues
= l_load_struct_gep(b
,
255 FIELDNO_EXPRCONTEXT_AGGVALUES
,
256 "v.econtext.aggvalues");
257 v_aggnulls
= l_load_struct_gep(b
,
260 FIELDNO_EXPRCONTEXT_AGGNULLS
,
261 "v.econtext.aggnulls");
263 /* allocate blocks for each op upfront, so we can do jumps easily */
264 opblocks
= palloc(sizeof(LLVMBasicBlockRef
) * state
->steps_len
);
265 for (int opno
= 0; opno
< state
->steps_len
; opno
++)
266 opblocks
[opno
] = l_bb_append_v(eval_fn
, "b.op.%d.start", opno
);
268 /* jump from entry to first block */
269 LLVMBuildBr(b
, opblocks
[0]);
271 for (int opno
= 0; opno
< state
->steps_len
; opno
++)
275 LLVMValueRef v_resvaluep
;
276 LLVMValueRef v_resnullp
;
278 LLVMPositionBuilderAtEnd(b
, opblocks
[opno
]);
280 op
= &state
->steps
[opno
];
281 opcode
= ExecEvalStepOp(state
, op
);
283 v_resvaluep
= l_ptr_const(op
->resvalue
, l_ptr(TypeSizeT
));
284 v_resnullp
= l_ptr_const(op
->resnull
, l_ptr(TypeStorageBool
));
290 LLVMValueRef v_tmpisnull
;
291 LLVMValueRef v_tmpvalue
;
293 v_tmpvalue
= l_load(b
, TypeSizeT
, v_tmpvaluep
, "");
294 v_tmpisnull
= l_load(b
, TypeStorageBool
, v_tmpisnullp
, "");
296 LLVMBuildStore(b
, v_tmpisnull
, v_isnullp
);
298 LLVMBuildRet(b
, v_tmpvalue
);
302 case EEOP_INNER_FETCHSOME
:
303 case EEOP_OUTER_FETCHSOME
:
304 case EEOP_SCAN_FETCHSOME
:
306 TupleDesc desc
= NULL
;
308 LLVMBasicBlockRef b_fetch
;
309 LLVMValueRef v_nvalid
;
310 LLVMValueRef l_jit_deform
= NULL
;
311 const TupleTableSlotOps
*tts_ops
= NULL
;
313 b_fetch
= l_bb_before_v(opblocks
[opno
+ 1],
314 "op.%d.fetch", opno
);
316 if (op
->d
.fetch
.known_desc
)
317 desc
= op
->d
.fetch
.known_desc
;
319 if (op
->d
.fetch
.fixed
)
320 tts_ops
= op
->d
.fetch
.kind
;
322 /* step should not have been generated */
323 Assert(tts_ops
!= &TTSOpsVirtual
);
325 if (opcode
== EEOP_INNER_FETCHSOME
)
326 v_slot
= v_innerslot
;
327 else if (opcode
== EEOP_OUTER_FETCHSOME
)
328 v_slot
= v_outerslot
;
333 * Check if all required attributes are available, or
334 * whether deforming is required.
338 StructTupleTableSlot
,
340 FIELDNO_TUPLETABLESLOT_NVALID
,
343 LLVMBuildICmp(b
, LLVMIntUGE
, v_nvalid
,
344 l_int16_const(lc
, op
->d
.fetch
.last_var
),
346 opblocks
[opno
+ 1], b_fetch
);
348 LLVMPositionBuilderAtEnd(b
, b_fetch
);
351 * If the tupledesc of the to-be-deformed tuple is known,
352 * and JITing of deforming is enabled, build deform
353 * function specific to tupledesc and the exact number of
354 * to-be-extracted attributes.
356 if (tts_ops
&& desc
&& (context
->base
.flags
& PGJIT_DEFORM
))
358 INSTR_TIME_SET_CURRENT(deform_starttime
);
360 slot_compile_deform(context
, desc
,
362 op
->d
.fetch
.last_var
);
363 INSTR_TIME_SET_CURRENT(deform_endtime
);
364 INSTR_TIME_ACCUM_DIFF(context
->base
.instr
.deform_counter
,
365 deform_endtime
, deform_starttime
);
370 LLVMValueRef params
[1];
375 LLVMGetFunctionType(l_jit_deform
),
377 params
, lengthof(params
), "");
381 LLVMValueRef params
[2];
384 params
[1] = l_int32_const(lc
, op
->d
.fetch
.last_var
);
387 llvm_pg_var_func_type("slot_getsomeattrs_int"),
388 llvm_pg_func(mod
, "slot_getsomeattrs_int"),
389 params
, lengthof(params
), "");
392 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
402 LLVMValueRef v_attnum
;
403 LLVMValueRef v_values
;
404 LLVMValueRef v_nulls
;
406 if (opcode
== EEOP_INNER_VAR
)
408 v_values
= v_innervalues
;
409 v_nulls
= v_innernulls
;
411 else if (opcode
== EEOP_OUTER_VAR
)
413 v_values
= v_outervalues
;
414 v_nulls
= v_outernulls
;
418 v_values
= v_scanvalues
;
419 v_nulls
= v_scannulls
;
422 v_attnum
= l_int32_const(lc
, op
->d
.var
.attnum
);
423 value
= l_load_gep1(b
, TypeSizeT
, v_values
, v_attnum
, "");
424 isnull
= l_load_gep1(b
, TypeStorageBool
, v_nulls
, v_attnum
, "");
425 LLVMBuildStore(b
, value
, v_resvaluep
);
426 LLVMBuildStore(b
, isnull
, v_resnullp
);
428 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
432 case EEOP_INNER_SYSVAR
:
433 case EEOP_OUTER_SYSVAR
:
434 case EEOP_SCAN_SYSVAR
:
438 if (opcode
== EEOP_INNER_SYSVAR
)
439 v_slot
= v_innerslot
;
440 else if (opcode
== EEOP_OUTER_SYSVAR
)
441 v_slot
= v_outerslot
;
445 build_EvalXFunc(b
, mod
, "ExecEvalSysVar",
446 v_state
, op
, v_econtext
, v_slot
);
448 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
453 build_EvalXFunc(b
, mod
, "ExecEvalWholeRowVar",
454 v_state
, op
, v_econtext
);
455 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
458 case EEOP_ASSIGN_INNER_VAR
:
459 case EEOP_ASSIGN_OUTER_VAR
:
460 case EEOP_ASSIGN_SCAN_VAR
:
462 LLVMValueRef v_value
;
463 LLVMValueRef v_isnull
;
464 LLVMValueRef v_rvaluep
;
465 LLVMValueRef v_risnullp
;
466 LLVMValueRef v_attnum
;
467 LLVMValueRef v_resultnum
;
468 LLVMValueRef v_values
;
469 LLVMValueRef v_nulls
;
471 if (opcode
== EEOP_ASSIGN_INNER_VAR
)
473 v_values
= v_innervalues
;
474 v_nulls
= v_innernulls
;
476 else if (opcode
== EEOP_ASSIGN_OUTER_VAR
)
478 v_values
= v_outervalues
;
479 v_nulls
= v_outernulls
;
483 v_values
= v_scanvalues
;
484 v_nulls
= v_scannulls
;
488 v_attnum
= l_int32_const(lc
, op
->d
.assign_var
.attnum
);
489 v_value
= l_load_gep1(b
, TypeSizeT
, v_values
, v_attnum
, "");
490 v_isnull
= l_load_gep1(b
, TypeStorageBool
, v_nulls
, v_attnum
, "");
492 /* compute addresses of targets */
493 v_resultnum
= l_int32_const(lc
, op
->d
.assign_var
.resultnum
);
497 &v_resultnum
, 1, "");
498 v_risnullp
= l_gep(b
,
501 &v_resultnum
, 1, "");
504 LLVMBuildStore(b
, v_value
, v_rvaluep
);
505 LLVMBuildStore(b
, v_isnull
, v_risnullp
);
507 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
511 case EEOP_ASSIGN_TMP
:
512 case EEOP_ASSIGN_TMP_MAKE_RO
:
514 LLVMValueRef v_value
,
516 LLVMValueRef v_rvaluep
,
518 LLVMValueRef v_resultnum
;
519 size_t resultnum
= op
->d
.assign_tmp
.resultnum
;
522 v_value
= l_load(b
, TypeSizeT
, v_tmpvaluep
, "");
523 v_isnull
= l_load(b
, TypeStorageBool
, v_tmpisnullp
, "");
525 /* compute addresses of targets */
526 v_resultnum
= l_int32_const(lc
, resultnum
);
528 l_gep(b
, TypeSizeT
, v_resultvalues
, &v_resultnum
, 1, "");
530 l_gep(b
, TypeStorageBool
, v_resultnulls
, &v_resultnum
, 1, "");
533 LLVMBuildStore(b
, v_isnull
, v_risnullp
);
535 /* make value readonly if necessary */
536 if (opcode
== EEOP_ASSIGN_TMP_MAKE_RO
)
538 LLVMBasicBlockRef b_notnull
;
539 LLVMValueRef v_params
[1];
541 b_notnull
= l_bb_before_v(opblocks
[opno
+ 1],
542 "op.%d.assign_tmp.notnull", opno
);
544 /* check if value is NULL */
546 LLVMBuildICmp(b
, LLVMIntEQ
, v_isnull
,
547 l_sbool_const(0), ""),
548 b_notnull
, opblocks
[opno
+ 1]);
550 /* if value is not null, convert to RO datum */
551 LLVMPositionBuilderAtEnd(b
, b_notnull
);
552 v_params
[0] = v_value
;
555 llvm_pg_var_func_type("MakeExpandedObjectReadOnlyInternal"),
556 llvm_pg_func(mod
, "MakeExpandedObjectReadOnlyInternal"),
557 v_params
, lengthof(v_params
), "");
560 * Falling out of the if () with builder in b_notnull,
561 * which is fine - the null is already stored above.
565 /* and finally store result */
566 LLVMBuildStore(b
, v_value
, v_rvaluep
);
568 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
574 LLVMValueRef v_constvalue
,
577 v_constvalue
= l_sizet_const(op
->d
.constval
.value
);
578 v_constnull
= l_sbool_const(op
->d
.constval
.isnull
);
580 LLVMBuildStore(b
, v_constvalue
, v_resvaluep
);
581 LLVMBuildStore(b
, v_constnull
, v_resnullp
);
583 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
588 case EEOP_FUNCEXPR_STRICT
:
590 FunctionCallInfo fcinfo
= op
->d
.func
.fcinfo_data
;
591 LLVMValueRef v_fcinfo_isnull
;
592 LLVMValueRef v_retval
;
594 if (opcode
== EEOP_FUNCEXPR_STRICT
)
596 LLVMBasicBlockRef b_nonull
;
597 LLVMBasicBlockRef
*b_checkargnulls
;
598 LLVMValueRef v_fcinfo
;
601 * Block for the actual function call, if args are
604 b_nonull
= l_bb_before_v(opblocks
[opno
+ 1],
605 "b.%d.no-null-args", opno
);
607 /* should make sure they're optimized beforehand */
608 if (op
->d
.func
.nargs
== 0)
609 elog(ERROR
, "argumentless strict functions are pointless");
612 l_ptr_const(fcinfo
, l_ptr(StructFunctionCallInfoData
));
615 * set resnull to true, if the function is actually
616 * called, it'll be reset
618 LLVMBuildStore(b
, l_sbool_const(1), v_resnullp
);
620 /* create blocks for checking args, one for each */
622 palloc(sizeof(LLVMBasicBlockRef
*) * op
->d
.func
.nargs
);
623 for (int argno
= 0; argno
< op
->d
.func
.nargs
; argno
++)
624 b_checkargnulls
[argno
] =
625 l_bb_before_v(b_nonull
, "b.%d.isnull.%d", opno
,
628 /* jump to check of first argument */
629 LLVMBuildBr(b
, b_checkargnulls
[0]);
631 /* check each arg for NULLness */
632 for (int argno
= 0; argno
< op
->d
.func
.nargs
; argno
++)
634 LLVMValueRef v_argisnull
;
635 LLVMBasicBlockRef b_argnotnull
;
637 LLVMPositionBuilderAtEnd(b
, b_checkargnulls
[argno
]);
640 * Compute block to jump to if argument is not
643 if (argno
+ 1 == op
->d
.func
.nargs
)
644 b_argnotnull
= b_nonull
;
646 b_argnotnull
= b_checkargnulls
[argno
+ 1];
648 /* and finally load & check NULLness of arg */
649 v_argisnull
= l_funcnull(b
, v_fcinfo
, argno
);
651 LLVMBuildICmp(b
, LLVMIntEQ
,
659 LLVMPositionBuilderAtEnd(b
, b_nonull
);
662 v_retval
= BuildV1Call(context
, b
, mod
, fcinfo
,
664 LLVMBuildStore(b
, v_retval
, v_resvaluep
);
665 LLVMBuildStore(b
, v_fcinfo_isnull
, v_resnullp
);
667 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
671 case EEOP_FUNCEXPR_FUSAGE
:
672 build_EvalXFunc(b
, mod
, "ExecEvalFuncExprFusage",
673 v_state
, op
, v_econtext
);
674 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
678 case EEOP_FUNCEXPR_STRICT_FUSAGE
:
679 build_EvalXFunc(b
, mod
, "ExecEvalFuncExprStrictFusage",
680 v_state
, op
, v_econtext
);
681 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
685 * Treat them the same for now, optimizer can remove
686 * redundancy. Could be worthwhile to optimize during emission
689 case EEOP_BOOL_AND_STEP_FIRST
:
690 case EEOP_BOOL_AND_STEP
:
691 case EEOP_BOOL_AND_STEP_LAST
:
693 LLVMValueRef v_boolvalue
;
694 LLVMValueRef v_boolnull
;
695 LLVMValueRef v_boolanynullp
,
697 LLVMBasicBlockRef b_boolisnull
;
698 LLVMBasicBlockRef b_boolcheckfalse
;
699 LLVMBasicBlockRef b_boolisfalse
;
700 LLVMBasicBlockRef b_boolcont
;
701 LLVMBasicBlockRef b_boolisanynull
;
703 b_boolisnull
= l_bb_before_v(opblocks
[opno
+ 1],
704 "b.%d.boolisnull", opno
);
705 b_boolcheckfalse
= l_bb_before_v(opblocks
[opno
+ 1],
706 "b.%d.boolcheckfalse", opno
);
707 b_boolisfalse
= l_bb_before_v(opblocks
[opno
+ 1],
708 "b.%d.boolisfalse", opno
);
709 b_boolisanynull
= l_bb_before_v(opblocks
[opno
+ 1],
710 "b.%d.boolisanynull", opno
);
711 b_boolcont
= l_bb_before_v(opblocks
[opno
+ 1],
712 "b.%d.boolcont", opno
);
714 v_boolanynullp
= l_ptr_const(op
->d
.boolexpr
.anynull
,
715 l_ptr(TypeStorageBool
));
717 if (opcode
== EEOP_BOOL_AND_STEP_FIRST
)
718 LLVMBuildStore(b
, l_sbool_const(0), v_boolanynullp
);
720 v_boolnull
= l_load(b
, TypeStorageBool
, v_resnullp
, "");
721 v_boolvalue
= l_load(b
, TypeSizeT
, v_resvaluep
, "");
723 /* check if current input is NULL */
725 LLVMBuildICmp(b
, LLVMIntEQ
, v_boolnull
,
726 l_sbool_const(1), ""),
730 /* build block that sets anynull */
731 LLVMPositionBuilderAtEnd(b
, b_boolisnull
);
732 /* set boolanynull to true */
733 LLVMBuildStore(b
, l_sbool_const(1), v_boolanynullp
);
734 /* and jump to next block */
735 LLVMBuildBr(b
, b_boolcont
);
737 /* build block checking for false */
738 LLVMPositionBuilderAtEnd(b
, b_boolcheckfalse
);
740 LLVMBuildICmp(b
, LLVMIntEQ
, v_boolvalue
,
741 l_sizet_const(0), ""),
746 * Build block handling FALSE. Value is false, so short
749 LLVMPositionBuilderAtEnd(b
, b_boolisfalse
);
750 /* result is already set to FALSE, need not change it */
751 /* and jump to the end of the AND expression */
752 LLVMBuildBr(b
, opblocks
[op
->d
.boolexpr
.jumpdone
]);
754 /* Build block that continues if bool is TRUE. */
755 LLVMPositionBuilderAtEnd(b
, b_boolcont
);
757 v_boolanynull
= l_load(b
, TypeStorageBool
, v_boolanynullp
, "");
759 /* set value to NULL if any previous values were NULL */
761 LLVMBuildICmp(b
, LLVMIntEQ
, v_boolanynull
,
762 l_sbool_const(0), ""),
763 opblocks
[opno
+ 1], b_boolisanynull
);
765 LLVMPositionBuilderAtEnd(b
, b_boolisanynull
);
766 /* set resnull to true */
767 LLVMBuildStore(b
, l_sbool_const(1), v_resnullp
);
769 LLVMBuildStore(b
, l_sizet_const(0), v_resvaluep
);
771 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
776 * Treat them the same for now, optimizer can remove
777 * redundancy. Could be worthwhile to optimize during emission
780 case EEOP_BOOL_OR_STEP_FIRST
:
781 case EEOP_BOOL_OR_STEP
:
782 case EEOP_BOOL_OR_STEP_LAST
:
784 LLVMValueRef v_boolvalue
;
785 LLVMValueRef v_boolnull
;
786 LLVMValueRef v_boolanynullp
,
789 LLVMBasicBlockRef b_boolisnull
;
790 LLVMBasicBlockRef b_boolchecktrue
;
791 LLVMBasicBlockRef b_boolistrue
;
792 LLVMBasicBlockRef b_boolcont
;
793 LLVMBasicBlockRef b_boolisanynull
;
795 b_boolisnull
= l_bb_before_v(opblocks
[opno
+ 1],
796 "b.%d.boolisnull", opno
);
797 b_boolchecktrue
= l_bb_before_v(opblocks
[opno
+ 1],
798 "b.%d.boolchecktrue", opno
);
799 b_boolistrue
= l_bb_before_v(opblocks
[opno
+ 1],
800 "b.%d.boolistrue", opno
);
801 b_boolisanynull
= l_bb_before_v(opblocks
[opno
+ 1],
802 "b.%d.boolisanynull", opno
);
803 b_boolcont
= l_bb_before_v(opblocks
[opno
+ 1],
804 "b.%d.boolcont", opno
);
806 v_boolanynullp
= l_ptr_const(op
->d
.boolexpr
.anynull
,
807 l_ptr(TypeStorageBool
));
809 if (opcode
== EEOP_BOOL_OR_STEP_FIRST
)
810 LLVMBuildStore(b
, l_sbool_const(0), v_boolanynullp
);
811 v_boolnull
= l_load(b
, TypeStorageBool
, v_resnullp
, "");
812 v_boolvalue
= l_load(b
, TypeSizeT
, v_resvaluep
, "");
815 LLVMBuildICmp(b
, LLVMIntEQ
, v_boolnull
,
816 l_sbool_const(1), ""),
820 /* build block that sets anynull */
821 LLVMPositionBuilderAtEnd(b
, b_boolisnull
);
822 /* set boolanynull to true */
823 LLVMBuildStore(b
, l_sbool_const(1), v_boolanynullp
);
824 /* and jump to next block */
825 LLVMBuildBr(b
, b_boolcont
);
827 /* build block checking for true */
828 LLVMPositionBuilderAtEnd(b
, b_boolchecktrue
);
830 LLVMBuildICmp(b
, LLVMIntEQ
, v_boolvalue
,
831 l_sizet_const(1), ""),
836 * Build block handling True. Value is true, so short
839 LLVMPositionBuilderAtEnd(b
, b_boolistrue
);
840 /* result is already set to TRUE, need not change it */
841 /* and jump to the end of the OR expression */
842 LLVMBuildBr(b
, opblocks
[op
->d
.boolexpr
.jumpdone
]);
844 /* build block that continues if bool is FALSE */
845 LLVMPositionBuilderAtEnd(b
, b_boolcont
);
847 v_boolanynull
= l_load(b
, TypeStorageBool
, v_boolanynullp
, "");
849 /* set value to NULL if any previous values were NULL */
851 LLVMBuildICmp(b
, LLVMIntEQ
, v_boolanynull
,
852 l_sbool_const(0), ""),
853 opblocks
[opno
+ 1], b_boolisanynull
);
855 LLVMPositionBuilderAtEnd(b
, b_boolisanynull
);
856 /* set resnull to true */
857 LLVMBuildStore(b
, l_sbool_const(1), v_resnullp
);
859 LLVMBuildStore(b
, l_sizet_const(0), v_resvaluep
);
861 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
865 case EEOP_BOOL_NOT_STEP
:
867 LLVMValueRef v_boolvalue
;
868 LLVMValueRef v_negbool
;
870 /* compute !boolvalue */
871 v_boolvalue
= l_load(b
, TypeSizeT
, v_resvaluep
, "");
872 v_negbool
= LLVMBuildZExt(b
,
873 LLVMBuildICmp(b
, LLVMIntEQ
,
880 * Store it back in resvalue. We can ignore resnull here;
881 * if it was true, it stays true, and the value we store
882 * in resvalue doesn't matter.
884 LLVMBuildStore(b
, v_negbool
, v_resvaluep
);
886 LLVMBuildBr(b
, opblocks
[opno
+ 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
[opno
+ 1],
898 "op.%d.qualfail", opno
);
900 v_resvalue
= l_load(b
, TypeSizeT
, v_resvaluep
, "");
901 v_resnull
= l_load(b
, TypeStorageBool
, 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
= l_load(b
, TypeStorageBool
, 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
= l_load(b
, TypeStorageBool
, 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
= l_load(b
, TypeSizeT
, v_resvaluep
, "");
975 v_resnull
= l_load(b
, TypeStorageBool
, 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
= l_load(b
, TypeStorageBool
, 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
[opno
+ 1]);
1011 case EEOP_NULLTEST_ISNOTNULL
:
1013 LLVMValueRef v_resnull
= l_load(b
, TypeStorageBool
, 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
[opno
+ 1]);
1030 case EEOP_NULLTEST_ROWISNULL
:
1031 build_EvalXFunc(b
, mod
, "ExecEvalRowNull",
1032 v_state
, op
, v_econtext
);
1033 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1036 case EEOP_NULLTEST_ROWISNOTNULL
:
1037 build_EvalXFunc(b
, mod
, "ExecEvalRowNotNull",
1038 v_state
, op
, v_econtext
);
1039 LLVMBuildBr(b
, opblocks
[opno
+ 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
= l_load(b
, TypeStorageBool
, v_resnullp
, "");
1051 b_isnull
= l_bb_before_v(opblocks
[opno
+ 1],
1052 "op.%d.isnull", opno
);
1053 b_notnull
= l_bb_before_v(opblocks
[opno
+ 1],
1054 "op.%d.isnotnull", opno
);
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
[opno
+ 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 l_load(b
, TypeSizeT
, v_resvaluep
, "");
1095 v_value
= LLVMBuildZExt(b
,
1096 LLVMBuildICmp(b
, LLVMIntEQ
,
1101 LLVMBuildStore(b
, v_value
, v_resvaluep
);
1103 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1107 case EEOP_PARAM_EXEC
:
1108 build_EvalXFunc(b
, mod
, "ExecEvalParamExec",
1109 v_state
, op
, v_econtext
);
1110 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1113 case EEOP_PARAM_EXTERN
:
1114 build_EvalXFunc(b
, mod
, "ExecEvalParamExtern",
1115 v_state
, op
, v_econtext
);
1116 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1119 case EEOP_PARAM_CALLBACK
:
1121 LLVMValueRef v_func
;
1122 LLVMValueRef v_params
[3];
1124 v_func
= l_ptr_const(op
->d
.cparam
.paramfunc
,
1125 llvm_pg_var_type("TypeExecEvalSubroutine"));
1127 v_params
[0] = v_state
;
1128 v_params
[1] = l_ptr_const(op
, l_ptr(StructExprEvalStep
));
1129 v_params
[2] = v_econtext
;
1131 LLVMGetFunctionType(ExecEvalSubroutineTemplate
),
1133 v_params
, lengthof(v_params
), "");
1135 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1139 case EEOP_PARAM_SET
:
1140 build_EvalXFunc(b
, mod
, "ExecEvalParamSet",
1141 v_state
, op
, v_econtext
);
1142 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1145 case EEOP_SBSREF_SUBSCRIPTS
:
1147 int jumpdone
= op
->d
.sbsref_subscript
.jumpdone
;
1148 LLVMValueRef v_func
;
1149 LLVMValueRef v_params
[3];
1152 v_func
= l_ptr_const(op
->d
.sbsref_subscript
.subscriptfunc
,
1153 llvm_pg_var_type("TypeExecEvalBoolSubroutine"));
1155 v_params
[0] = v_state
;
1156 v_params
[1] = l_ptr_const(op
, l_ptr(StructExprEvalStep
));
1157 v_params
[2] = v_econtext
;
1159 LLVMGetFunctionType(ExecEvalBoolSubroutineTemplate
),
1161 v_params
, lengthof(v_params
), "");
1162 v_ret
= LLVMBuildZExt(b
, v_ret
, TypeStorageBool
, "");
1165 LLVMBuildICmp(b
, LLVMIntEQ
, v_ret
,
1166 l_sbool_const(1), ""),
1168 opblocks
[jumpdone
]);
1172 case EEOP_SBSREF_OLD
:
1173 case EEOP_SBSREF_ASSIGN
:
1174 case EEOP_SBSREF_FETCH
:
1176 LLVMValueRef v_func
;
1177 LLVMValueRef v_params
[3];
1179 v_func
= l_ptr_const(op
->d
.sbsref
.subscriptfunc
,
1180 llvm_pg_var_type("TypeExecEvalSubroutine"));
1182 v_params
[0] = v_state
;
1183 v_params
[1] = l_ptr_const(op
, l_ptr(StructExprEvalStep
));
1184 v_params
[2] = v_econtext
;
1186 LLVMGetFunctionType(ExecEvalSubroutineTemplate
),
1188 v_params
, lengthof(v_params
), "");
1190 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1194 case EEOP_CASE_TESTVAL
:
1196 LLVMBasicBlockRef b_avail
,
1198 LLVMValueRef v_casevaluep
,
1200 LLVMValueRef v_casenullp
,
1202 LLVMValueRef v_casevaluenull
;
1204 b_avail
= l_bb_before_v(opblocks
[opno
+ 1],
1205 "op.%d.avail", opno
);
1206 b_notavail
= l_bb_before_v(opblocks
[opno
+ 1],
1207 "op.%d.notavail", opno
);
1209 v_casevaluep
= l_ptr_const(op
->d
.casetest
.value
,
1211 v_casenullp
= l_ptr_const(op
->d
.casetest
.isnull
,
1212 l_ptr(TypeStorageBool
));
1215 LLVMBuildICmp(b
, LLVMIntEQ
,
1216 LLVMBuildPtrToInt(b
, v_casevaluep
,
1218 l_sizet_const(0), "");
1219 LLVMBuildCondBr(b
, v_casevaluenull
, b_notavail
, b_avail
);
1221 /* if casetest != NULL */
1222 LLVMPositionBuilderAtEnd(b
, b_avail
);
1223 v_casevalue
= l_load(b
, TypeSizeT
, v_casevaluep
, "");
1224 v_casenull
= l_load(b
, TypeStorageBool
, v_casenullp
, "");
1225 LLVMBuildStore(b
, v_casevalue
, v_resvaluep
);
1226 LLVMBuildStore(b
, v_casenull
, v_resnullp
);
1227 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1229 /* if casetest == NULL */
1230 LLVMPositionBuilderAtEnd(b
, b_notavail
);
1232 l_load_struct_gep(b
,
1235 FIELDNO_EXPRCONTEXT_CASEDATUM
, "");
1237 l_load_struct_gep(b
,
1240 FIELDNO_EXPRCONTEXT_CASENULL
, "");
1241 LLVMBuildStore(b
, v_casevalue
, v_resvaluep
);
1242 LLVMBuildStore(b
, v_casenull
, v_resnullp
);
1244 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1248 case EEOP_MAKE_READONLY
:
1250 LLVMBasicBlockRef b_notnull
;
1251 LLVMValueRef v_params
[1];
1253 LLVMValueRef v_nullp
;
1254 LLVMValueRef v_valuep
;
1255 LLVMValueRef v_null
;
1256 LLVMValueRef v_value
;
1258 b_notnull
= l_bb_before_v(opblocks
[opno
+ 1],
1259 "op.%d.readonly.notnull", opno
);
1261 v_nullp
= l_ptr_const(op
->d
.make_readonly
.isnull
,
1262 l_ptr(TypeStorageBool
));
1264 v_null
= l_load(b
, TypeStorageBool
, v_nullp
, "");
1266 /* store null isnull value in result */
1267 LLVMBuildStore(b
, v_null
, v_resnullp
);
1269 /* check if value is NULL */
1271 LLVMBuildICmp(b
, LLVMIntEQ
, v_null
,
1272 l_sbool_const(1), ""),
1273 opblocks
[opno
+ 1], b_notnull
);
1275 /* if value is not null, convert to RO datum */
1276 LLVMPositionBuilderAtEnd(b
, b_notnull
);
1278 v_valuep
= l_ptr_const(op
->d
.make_readonly
.value
,
1281 v_value
= l_load(b
, TypeSizeT
, v_valuep
, "");
1283 v_params
[0] = v_value
;
1286 llvm_pg_var_func_type("MakeExpandedObjectReadOnlyInternal"),
1287 llvm_pg_func(mod
, "MakeExpandedObjectReadOnlyInternal"),
1288 v_params
, lengthof(v_params
), "");
1289 LLVMBuildStore(b
, v_ret
, v_resvaluep
);
1291 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1297 FunctionCallInfo fcinfo_out
,
1299 LLVMValueRef v_fn_out
,
1301 LLVMValueRef v_fcinfo_out
,
1303 LLVMValueRef v_fcinfo_in_isnullp
;
1304 LLVMValueRef v_retval
;
1305 LLVMValueRef v_resvalue
;
1306 LLVMValueRef v_resnull
;
1308 LLVMValueRef v_output_skip
;
1309 LLVMValueRef v_output
;
1311 LLVMBasicBlockRef b_skipoutput
;
1312 LLVMBasicBlockRef b_calloutput
;
1313 LLVMBasicBlockRef b_input
;
1314 LLVMBasicBlockRef b_inputcall
;
1316 fcinfo_out
= op
->d
.iocoerce
.fcinfo_data_out
;
1317 fcinfo_in
= op
->d
.iocoerce
.fcinfo_data_in
;
1319 b_skipoutput
= l_bb_before_v(opblocks
[opno
+ 1],
1320 "op.%d.skipoutputnull", opno
);
1321 b_calloutput
= l_bb_before_v(opblocks
[opno
+ 1],
1322 "op.%d.calloutput", opno
);
1323 b_input
= l_bb_before_v(opblocks
[opno
+ 1],
1324 "op.%d.input", opno
);
1325 b_inputcall
= l_bb_before_v(opblocks
[opno
+ 1],
1326 "op.%d.inputcall", opno
);
1328 v_fn_out
= llvm_function_reference(context
, b
, mod
, fcinfo_out
);
1329 v_fn_in
= llvm_function_reference(context
, b
, mod
, fcinfo_in
);
1330 v_fcinfo_out
= l_ptr_const(fcinfo_out
, l_ptr(StructFunctionCallInfoData
));
1331 v_fcinfo_in
= l_ptr_const(fcinfo_in
, l_ptr(StructFunctionCallInfoData
));
1333 v_fcinfo_in_isnullp
=
1335 StructFunctionCallInfoData
,
1337 FIELDNO_FUNCTIONCALLINFODATA_ISNULL
,
1338 "v_fcinfo_in_isnull");
1340 /* output functions are not called on nulls */
1341 v_resnull
= l_load(b
, TypeStorageBool
, v_resnullp
, "");
1343 LLVMBuildICmp(b
, LLVMIntEQ
, v_resnull
,
1344 l_sbool_const(1), ""),
1348 LLVMPositionBuilderAtEnd(b
, b_skipoutput
);
1349 v_output_skip
= l_sizet_const(0);
1350 LLVMBuildBr(b
, b_input
);
1352 LLVMPositionBuilderAtEnd(b
, b_calloutput
);
1353 v_resvalue
= l_load(b
, TypeSizeT
, v_resvaluep
, "");
1358 l_funcvaluep(b
, v_fcinfo_out
, 0));
1361 l_funcnullp(b
, v_fcinfo_out
, 0));
1362 /* and call output function (can never return NULL) */
1363 v_output
= l_call(b
,
1364 LLVMGetFunctionType(v_fn_out
),
1365 v_fn_out
, &v_fcinfo_out
,
1366 1, "funccall_coerce_out");
1367 LLVMBuildBr(b
, b_input
);
1369 /* build block handling input function call */
1370 LLVMPositionBuilderAtEnd(b
, b_input
);
1372 /* phi between resnull and output function call branches */
1374 LLVMValueRef incoming_values
[2];
1375 LLVMBasicBlockRef incoming_blocks
[2];
1377 incoming_values
[0] = v_output_skip
;
1378 incoming_blocks
[0] = b_skipoutput
;
1380 incoming_values
[1] = v_output
;
1381 incoming_blocks
[1] = b_calloutput
;
1383 v_output
= LLVMBuildPhi(b
, TypeSizeT
, "output");
1384 LLVMAddIncoming(v_output
,
1385 incoming_values
, incoming_blocks
,
1386 lengthof(incoming_blocks
));
1390 * If input function is strict, skip if input string is
1393 if (op
->d
.iocoerce
.finfo_in
->fn_strict
)
1396 LLVMBuildICmp(b
, LLVMIntEQ
, v_output
,
1397 l_sizet_const(0), ""),
1403 LLVMBuildBr(b
, b_inputcall
);
1406 LLVMPositionBuilderAtEnd(b
, b_inputcall
);
1409 LLVMBuildStore(b
, v_output
,
1410 l_funcvaluep(b
, v_fcinfo_in
, 0));
1411 LLVMBuildStore(b
, v_resnull
,
1412 l_funcnullp(b
, v_fcinfo_in
, 0));
1414 /* arg1: ioparam: preset in execExpr.c */
1415 /* arg2: typmod: preset in execExpr.c */
1417 /* reset fcinfo_in->isnull */
1418 LLVMBuildStore(b
, l_sbool_const(0), v_fcinfo_in_isnullp
);
1419 /* and call function */
1420 v_retval
= l_call(b
,
1421 LLVMGetFunctionType(v_fn_in
),
1422 v_fn_in
, &v_fcinfo_in
, 1,
1423 "funccall_iocoerce_in");
1425 LLVMBuildStore(b
, v_retval
, v_resvaluep
);
1427 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1431 case EEOP_IOCOERCE_SAFE
:
1432 build_EvalXFunc(b
, mod
, "ExecEvalCoerceViaIOSafe",
1434 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1438 case EEOP_NOT_DISTINCT
:
1440 FunctionCallInfo fcinfo
= op
->d
.func
.fcinfo_data
;
1442 LLVMValueRef v_fcinfo
;
1443 LLVMValueRef v_fcinfo_isnull
;
1445 LLVMValueRef v_argnull0
,
1447 LLVMValueRef v_argnull1
,
1450 LLVMValueRef v_anyargisnull
;
1451 LLVMValueRef v_bothargisnull
;
1453 LLVMValueRef v_result
;
1455 LLVMBasicBlockRef b_noargnull
;
1456 LLVMBasicBlockRef b_checkbothargnull
;
1457 LLVMBasicBlockRef b_bothargnull
;
1458 LLVMBasicBlockRef b_anyargnull
;
1460 b_noargnull
= l_bb_before_v(opblocks
[opno
+ 1], "op.%d.noargnull", opno
);
1461 b_checkbothargnull
= l_bb_before_v(opblocks
[opno
+ 1], "op.%d.checkbothargnull", opno
);
1462 b_bothargnull
= l_bb_before_v(opblocks
[opno
+ 1], "op.%d.bothargnull", opno
);
1463 b_anyargnull
= l_bb_before_v(opblocks
[opno
+ 1], "op.%d.anyargnull", opno
);
1465 v_fcinfo
= l_ptr_const(fcinfo
, l_ptr(StructFunctionCallInfoData
));
1467 /* load args[0|1].isnull for both arguments */
1468 v_argnull0
= l_funcnull(b
, v_fcinfo
, 0);
1469 v_argisnull0
= LLVMBuildICmp(b
, LLVMIntEQ
, v_argnull0
,
1470 l_sbool_const(1), "");
1471 v_argnull1
= l_funcnull(b
, v_fcinfo
, 1);
1472 v_argisnull1
= LLVMBuildICmp(b
, LLVMIntEQ
, v_argnull1
,
1473 l_sbool_const(1), "");
1475 v_anyargisnull
= LLVMBuildOr(b
, v_argisnull0
, v_argisnull1
, "");
1476 v_bothargisnull
= LLVMBuildAnd(b
, v_argisnull0
, v_argisnull1
, "");
1479 * Check function arguments for NULLness: If either is
1480 * NULL, we check if both args are NULL. Otherwise call
1483 LLVMBuildCondBr(b
, v_anyargisnull
, b_checkbothargnull
,
1487 * build block checking if any arg is null
1489 LLVMPositionBuilderAtEnd(b
, b_checkbothargnull
);
1490 LLVMBuildCondBr(b
, v_bothargisnull
, b_bothargnull
,
1494 /* Both NULL? Then is not distinct... */
1495 LLVMPositionBuilderAtEnd(b
, b_bothargnull
);
1496 LLVMBuildStore(b
, l_sbool_const(0), v_resnullp
);
1497 if (opcode
== EEOP_NOT_DISTINCT
)
1498 LLVMBuildStore(b
, l_sizet_const(1), v_resvaluep
);
1500 LLVMBuildStore(b
, l_sizet_const(0), v_resvaluep
);
1502 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1504 /* Only one is NULL? Then is distinct... */
1505 LLVMPositionBuilderAtEnd(b
, b_anyargnull
);
1506 LLVMBuildStore(b
, l_sbool_const(0), v_resnullp
);
1507 if (opcode
== EEOP_NOT_DISTINCT
)
1508 LLVMBuildStore(b
, l_sizet_const(0), v_resvaluep
);
1510 LLVMBuildStore(b
, l_sizet_const(1), v_resvaluep
);
1511 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1513 /* neither argument is null: compare */
1514 LLVMPositionBuilderAtEnd(b
, b_noargnull
);
1516 v_result
= BuildV1Call(context
, b
, mod
, fcinfo
,
1519 if (opcode
== EEOP_DISTINCT
)
1521 /* Must invert result of "=" */
1524 LLVMBuildICmp(b
, LLVMIntEQ
,
1526 l_sizet_const(0), ""),
1530 LLVMBuildStore(b
, v_fcinfo_isnull
, v_resnullp
);
1531 LLVMBuildStore(b
, v_result
, v_resvaluep
);
1533 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1539 FunctionCallInfo fcinfo
= op
->d
.func
.fcinfo_data
;
1541 LLVMValueRef v_fcinfo
;
1542 LLVMValueRef v_fcinfo_isnull
;
1543 LLVMValueRef v_argnull0
;
1544 LLVMValueRef v_argnull1
;
1545 LLVMValueRef v_anyargisnull
;
1546 LLVMValueRef v_arg0
;
1547 LLVMBasicBlockRef b_hasnull
;
1548 LLVMBasicBlockRef b_nonull
;
1549 LLVMBasicBlockRef b_argsequal
;
1550 LLVMValueRef v_retval
;
1551 LLVMValueRef v_argsequal
;
1553 b_hasnull
= l_bb_before_v(opblocks
[opno
+ 1],
1554 "b.%d.null-args", opno
);
1555 b_nonull
= l_bb_before_v(opblocks
[opno
+ 1],
1556 "b.%d.no-null-args", opno
);
1557 b_argsequal
= l_bb_before_v(opblocks
[opno
+ 1],
1558 "b.%d.argsequal", opno
);
1560 v_fcinfo
= l_ptr_const(fcinfo
, l_ptr(StructFunctionCallInfoData
));
1562 /* save original arg[0] */
1563 v_arg0
= l_funcvalue(b
, v_fcinfo
, 0);
1565 /* if either argument is NULL they can't be equal */
1566 v_argnull0
= l_funcnull(b
, v_fcinfo
, 0);
1567 v_argnull1
= l_funcnull(b
, v_fcinfo
, 1);
1571 LLVMBuildICmp(b
, LLVMIntEQ
, v_argnull0
,
1572 l_sbool_const(1), ""),
1573 LLVMBuildICmp(b
, LLVMIntEQ
, v_argnull1
,
1574 l_sbool_const(1), ""),
1577 LLVMBuildCondBr(b
, v_anyargisnull
, b_hasnull
, b_nonull
);
1579 /* one (or both) of the arguments are null, return arg[0] */
1580 LLVMPositionBuilderAtEnd(b
, b_hasnull
);
1581 LLVMBuildStore(b
, v_argnull0
, v_resnullp
);
1582 LLVMBuildStore(b
, v_arg0
, v_resvaluep
);
1583 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1585 /* build block to invoke function and check result */
1586 LLVMPositionBuilderAtEnd(b
, b_nonull
);
1589 * If first argument is of varlena type, it might be an
1590 * expanded datum. We need to ensure that the value
1591 * passed to the comparison function is a read-only
1592 * pointer. However, if we end by returning the first
1593 * argument, that will be the original read-write pointer
1594 * if it was read-write.
1596 if (op
->d
.func
.make_ro
)
1598 LLVMValueRef v_params
[1];
1599 LLVMValueRef v_arg0_ro
;
1601 v_params
[0] = v_arg0
;
1604 llvm_pg_var_func_type("MakeExpandedObjectReadOnlyInternal"),
1605 llvm_pg_func(mod
, "MakeExpandedObjectReadOnlyInternal"),
1606 v_params
, lengthof(v_params
), "");
1607 LLVMBuildStore(b
, v_arg0_ro
,
1608 l_funcvaluep(b
, v_fcinfo
, 0));
1611 v_retval
= BuildV1Call(context
, b
, mod
, fcinfo
, &v_fcinfo_isnull
);
1614 * If result not null and arguments are equal return null,
1615 * else return arg[0] (same result as if there'd been
1616 * NULLs, hence reuse b_hasnull).
1618 v_argsequal
= LLVMBuildAnd(b
,
1619 LLVMBuildICmp(b
, LLVMIntEQ
,
1623 LLVMBuildICmp(b
, LLVMIntEQ
,
1628 LLVMBuildCondBr(b
, v_argsequal
, b_argsequal
, b_hasnull
);
1630 /* build block setting result to NULL, if args are equal */
1631 LLVMPositionBuilderAtEnd(b
, b_argsequal
);
1632 LLVMBuildStore(b
, l_sbool_const(1), v_resnullp
);
1633 LLVMBuildStore(b
, l_sizet_const(0), v_resvaluep
);
1635 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1639 case EEOP_SQLVALUEFUNCTION
:
1640 build_EvalXFunc(b
, mod
, "ExecEvalSQLValueFunction",
1642 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1645 case EEOP_CURRENTOFEXPR
:
1646 build_EvalXFunc(b
, mod
, "ExecEvalCurrentOfExpr",
1648 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1651 case EEOP_NEXTVALUEEXPR
:
1652 build_EvalXFunc(b
, mod
, "ExecEvalNextValueExpr",
1654 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1657 case EEOP_ARRAYEXPR
:
1658 build_EvalXFunc(b
, mod
, "ExecEvalArrayExpr",
1660 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1663 case EEOP_ARRAYCOERCE
:
1664 build_EvalXFunc(b
, mod
, "ExecEvalArrayCoerce",
1665 v_state
, op
, v_econtext
);
1666 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1670 build_EvalXFunc(b
, mod
, "ExecEvalRow",
1672 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1675 case EEOP_ROWCOMPARE_STEP
:
1677 FunctionCallInfo fcinfo
= op
->d
.rowcompare_step
.fcinfo_data
;
1678 LLVMValueRef v_fcinfo_isnull
;
1679 LLVMBasicBlockRef b_null
;
1680 LLVMBasicBlockRef b_compare
;
1681 LLVMBasicBlockRef b_compare_result
;
1683 LLVMValueRef v_retval
;
1685 b_null
= l_bb_before_v(opblocks
[opno
+ 1],
1686 "op.%d.row-null", opno
);
1687 b_compare
= l_bb_before_v(opblocks
[opno
+ 1],
1688 "op.%d.row-compare", opno
);
1690 l_bb_before_v(opblocks
[opno
+ 1],
1691 "op.%d.row-compare-result",
1695 * If function is strict, and either arg is null, we're
1698 if (op
->d
.rowcompare_step
.finfo
->fn_strict
)
1700 LLVMValueRef v_fcinfo
;
1701 LLVMValueRef v_argnull0
;
1702 LLVMValueRef v_argnull1
;
1703 LLVMValueRef v_anyargisnull
;
1705 v_fcinfo
= l_ptr_const(fcinfo
,
1706 l_ptr(StructFunctionCallInfoData
));
1708 v_argnull0
= l_funcnull(b
, v_fcinfo
, 0);
1709 v_argnull1
= l_funcnull(b
, v_fcinfo
, 1);
1718 LLVMBuildICmp(b
, LLVMIntEQ
,
1720 l_sbool_const(1), ""),
1723 LLVMBuildCondBr(b
, v_anyargisnull
, b_null
, b_compare
);
1727 LLVMBuildBr(b
, b_compare
);
1730 /* build block invoking comparison function */
1731 LLVMPositionBuilderAtEnd(b
, b_compare
);
1734 v_retval
= BuildV1Call(context
, b
, mod
, fcinfo
,
1736 LLVMBuildStore(b
, v_retval
, v_resvaluep
);
1738 /* if result of function is NULL, force NULL result */
1748 /* build block analyzing the !NULL comparator result */
1749 LLVMPositionBuilderAtEnd(b
, b_compare_result
);
1751 /* if results equal, compare next, otherwise done */
1756 l_sizet_const(0), ""),
1758 opblocks
[op
->d
.rowcompare_step
.jumpdone
]);
1761 * Build block handling NULL input or NULL comparator
1764 LLVMPositionBuilderAtEnd(b
, b_null
);
1765 LLVMBuildStore(b
, l_sbool_const(1), v_resnullp
);
1766 LLVMBuildBr(b
, opblocks
[op
->d
.rowcompare_step
.jumpnull
]);
1771 case EEOP_ROWCOMPARE_FINAL
:
1773 RowCompareType rctype
= op
->d
.rowcompare_final
.rctype
;
1775 LLVMValueRef v_cmpresult
;
1776 LLVMValueRef v_result
;
1777 LLVMIntPredicate predicate
;
1780 * Btree comparators return 32 bit results, need to be
1781 * careful about sign (used as a 64 bit value it's
1786 l_load(b
, TypeSizeT
, v_resvaluep
, ""),
1787 LLVMInt32TypeInContext(lc
), "");
1792 predicate
= LLVMIntSLT
;
1795 predicate
= LLVMIntSLE
;
1798 predicate
= LLVMIntSGT
;
1801 predicate
= LLVMIntSGE
;
1804 /* EQ and NE cases aren't allowed here */
1806 predicate
= 0; /* prevent compiler warning */
1810 v_result
= LLVMBuildICmp(b
,
1813 l_int32_const(lc
, 0),
1815 v_result
= LLVMBuildZExt(b
, v_result
, TypeSizeT
, "");
1817 LLVMBuildStore(b
, l_sbool_const(0), v_resnullp
);
1818 LLVMBuildStore(b
, v_result
, v_resvaluep
);
1820 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1825 build_EvalXFunc(b
, mod
, "ExecEvalMinMax",
1827 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1830 case EEOP_FIELDSELECT
:
1831 build_EvalXFunc(b
, mod
, "ExecEvalFieldSelect",
1832 v_state
, op
, v_econtext
);
1833 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1836 case EEOP_FIELDSTORE_DEFORM
:
1837 build_EvalXFunc(b
, mod
, "ExecEvalFieldStoreDeForm",
1838 v_state
, op
, v_econtext
);
1839 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1842 case EEOP_FIELDSTORE_FORM
:
1843 build_EvalXFunc(b
, mod
, "ExecEvalFieldStoreForm",
1844 v_state
, op
, v_econtext
);
1845 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1848 case EEOP_DOMAIN_TESTVAL
:
1850 LLVMBasicBlockRef b_avail
,
1852 LLVMValueRef v_casevaluep
,
1854 LLVMValueRef v_casenullp
,
1856 LLVMValueRef v_casevaluenull
;
1858 b_avail
= l_bb_before_v(opblocks
[opno
+ 1],
1859 "op.%d.avail", opno
);
1860 b_notavail
= l_bb_before_v(opblocks
[opno
+ 1],
1861 "op.%d.notavail", opno
);
1863 v_casevaluep
= l_ptr_const(op
->d
.casetest
.value
,
1865 v_casenullp
= l_ptr_const(op
->d
.casetest
.isnull
,
1866 l_ptr(TypeStorageBool
));
1869 LLVMBuildICmp(b
, LLVMIntEQ
,
1870 LLVMBuildPtrToInt(b
, v_casevaluep
,
1872 l_sizet_const(0), "");
1875 b_notavail
, b_avail
);
1877 /* if casetest != NULL */
1878 LLVMPositionBuilderAtEnd(b
, b_avail
);
1879 v_casevalue
= l_load(b
, TypeSizeT
, v_casevaluep
, "");
1880 v_casenull
= l_load(b
, TypeStorageBool
, v_casenullp
, "");
1881 LLVMBuildStore(b
, v_casevalue
, v_resvaluep
);
1882 LLVMBuildStore(b
, v_casenull
, v_resnullp
);
1883 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1885 /* if casetest == NULL */
1886 LLVMPositionBuilderAtEnd(b
, b_notavail
);
1888 l_load_struct_gep(b
,
1891 FIELDNO_EXPRCONTEXT_DOMAINDATUM
,
1894 l_load_struct_gep(b
,
1897 FIELDNO_EXPRCONTEXT_DOMAINNULL
,
1899 LLVMBuildStore(b
, v_casevalue
, v_resvaluep
);
1900 LLVMBuildStore(b
, v_casenull
, v_resnullp
);
1902 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1906 case EEOP_DOMAIN_NOTNULL
:
1907 build_EvalXFunc(b
, mod
, "ExecEvalConstraintNotNull",
1909 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1912 case EEOP_DOMAIN_CHECK
:
1913 build_EvalXFunc(b
, mod
, "ExecEvalConstraintCheck",
1915 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1918 case EEOP_HASHDATUM_SET_INITVAL
:
1920 LLVMValueRef v_initvalue
;
1922 v_initvalue
= l_sizet_const(op
->d
.hashdatum_initvalue
.init_value
);
1924 LLVMBuildStore(b
, v_initvalue
, v_resvaluep
);
1925 LLVMBuildStore(b
, l_sbool_const(0), v_resnullp
);
1926 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
1930 case EEOP_HASHDATUM_FIRST
:
1931 case EEOP_HASHDATUM_FIRST_STRICT
:
1932 case EEOP_HASHDATUM_NEXT32
:
1933 case EEOP_HASHDATUM_NEXT32_STRICT
:
1935 FunctionCallInfo fcinfo
= op
->d
.hashdatum
.fcinfo_data
;
1936 LLVMValueRef v_fcinfo
;
1937 LLVMValueRef v_fcinfo_isnull
;
1938 LLVMValueRef v_retval
;
1939 LLVMBasicBlockRef b_checkargnull
;
1940 LLVMBasicBlockRef b_ifnotnull
;
1941 LLVMBasicBlockRef b_ifnullblock
;
1942 LLVMValueRef v_argisnull
;
1943 LLVMValueRef v_prevhash
= NULL
;
1946 * When performing the next hash and not in strict mode we
1947 * perform a rotation of the previously stored hash value
1948 * before doing the NULL check. We want to do this even
1949 * when we receive a NULL Datum to hash. In strict mode,
1950 * we do this after the NULL check so as not to waste the
1951 * effort of rotating the bits when we're going to throw
1952 * away the hash value and return NULL.
1954 if (opcode
== EEOP_HASHDATUM_NEXT32
)
1956 LLVMValueRef v_tmp1
;
1957 LLVMValueRef v_tmp2
;
1960 tmp
= l_ptr_const(&op
->d
.hashdatum
.iresult
->value
,
1964 * Fetch the previously hashed value from where the
1965 * previous hash operation stored it.
1967 v_prevhash
= l_load(b
, TypeSizeT
, tmp
, "prevhash");
1970 * Rotate bits left by 1 bit. Be careful not to
1971 * overflow uint32 when working with size_t.
1973 v_tmp1
= LLVMBuildShl(b
, v_prevhash
, l_sizet_const(1),
1975 v_tmp1
= LLVMBuildAnd(b
, v_tmp1
,
1976 l_sizet_const(0xffffffff), "");
1977 v_tmp2
= LLVMBuildLShr(b
, v_prevhash
,
1978 l_sizet_const(31), "");
1979 v_prevhash
= LLVMBuildOr(b
, v_tmp1
, v_tmp2
,
1984 * Block for the actual function call, if args are
1987 b_ifnotnull
= l_bb_before_v(opblocks
[opno
+ 1],
1991 /* we expect the hash function to have 1 argument */
1992 if (fcinfo
->nargs
!= 1)
1993 elog(ERROR
, "incorrect number of function arguments");
1995 v_fcinfo
= l_ptr_const(fcinfo
,
1996 l_ptr(StructFunctionCallInfoData
));
1998 b_checkargnull
= l_bb_before_v(b_ifnotnull
,
1999 "b.%d.isnull.0", opno
);
2001 LLVMBuildBr(b
, b_checkargnull
);
2004 * Determine what to do if we find the argument to be
2007 if (opcode
== EEOP_HASHDATUM_FIRST_STRICT
||
2008 opcode
== EEOP_HASHDATUM_NEXT32_STRICT
)
2010 b_ifnullblock
= l_bb_before_v(b_ifnotnull
,
2014 LLVMPositionBuilderAtEnd(b
, b_ifnullblock
);
2017 * In strict node, NULL inputs result in NULL. Save
2018 * the NULL result and goto jumpdone.
2020 LLVMBuildStore(b
, l_sbool_const(1), v_resnullp
);
2021 LLVMBuildStore(b
, l_sizet_const(0), v_resvaluep
);
2022 LLVMBuildBr(b
, opblocks
[op
->d
.hashdatum
.jumpdone
]);
2026 b_ifnullblock
= l_bb_before_v(b_ifnotnull
,
2030 LLVMPositionBuilderAtEnd(b
, b_ifnullblock
);
2033 LLVMBuildStore(b
, l_sbool_const(0), v_resnullp
);
2035 if (opcode
== EEOP_HASHDATUM_NEXT32
)
2037 Assert(v_prevhash
!= NULL
);
2040 * Save the rotated hash value and skip to the
2043 LLVMBuildStore(b
, v_prevhash
, v_resvaluep
);
2047 Assert(opcode
== EEOP_HASHDATUM_FIRST
);
2050 * Store a zero Datum when the Datum to hash is
2053 LLVMBuildStore(b
, l_sizet_const(0), v_resvaluep
);
2056 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
2059 LLVMPositionBuilderAtEnd(b
, b_checkargnull
);
2061 /* emit code to check if the input parameter is NULL */
2062 v_argisnull
= l_funcnull(b
, v_fcinfo
, 0);
2072 LLVMPositionBuilderAtEnd(b
, b_ifnotnull
);
2075 * Rotate the previously stored hash value when performing
2076 * NEXT32 in strict mode. In non-strict mode we already
2077 * did this before checking for NULLs.
2079 if (opcode
== EEOP_HASHDATUM_NEXT32_STRICT
)
2081 LLVMValueRef v_tmp1
;
2082 LLVMValueRef v_tmp2
;
2085 tmp
= l_ptr_const(&op
->d
.hashdatum
.iresult
->value
,
2089 * Fetch the previously hashed value from where the
2090 * previous hash operation stored it.
2092 v_prevhash
= l_load(b
, TypeSizeT
, tmp
, "prevhash");
2095 * Rotate bits left by 1 bit. Be careful not to
2096 * overflow uint32 when working with size_t.
2098 v_tmp1
= LLVMBuildShl(b
, v_prevhash
, l_sizet_const(1),
2100 v_tmp1
= LLVMBuildAnd(b
, v_tmp1
,
2101 l_sizet_const(0xffffffff), "");
2102 v_tmp2
= LLVMBuildLShr(b
, v_prevhash
,
2103 l_sizet_const(31), "");
2104 v_prevhash
= LLVMBuildOr(b
, v_tmp1
, v_tmp2
,
2108 /* call the hash function */
2109 v_retval
= BuildV1Call(context
, b
, mod
, fcinfo
,
2113 * For NEXT32 ops, XOR (^) the returned hash value with
2114 * the existing hash value.
2116 if (opcode
== EEOP_HASHDATUM_NEXT32
||
2117 opcode
== EEOP_HASHDATUM_NEXT32_STRICT
)
2118 v_retval
= LLVMBuildXor(b
, v_prevhash
, v_retval
,
2121 LLVMBuildStore(b
, v_retval
, v_resvaluep
);
2122 LLVMBuildStore(b
, l_sbool_const(0), v_resnullp
);
2124 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
2128 case EEOP_CONVERT_ROWTYPE
:
2129 build_EvalXFunc(b
, mod
, "ExecEvalConvertRowtype",
2130 v_state
, op
, v_econtext
);
2131 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
2134 case EEOP_SCALARARRAYOP
:
2135 build_EvalXFunc(b
, mod
, "ExecEvalScalarArrayOp",
2137 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
2140 case EEOP_HASHED_SCALARARRAYOP
:
2141 build_EvalXFunc(b
, mod
, "ExecEvalHashedScalarArrayOp",
2142 v_state
, op
, v_econtext
);
2143 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
2147 build_EvalXFunc(b
, mod
, "ExecEvalXmlExpr",
2149 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
2152 case EEOP_JSON_CONSTRUCTOR
:
2153 build_EvalXFunc(b
, mod
, "ExecEvalJsonConstructor",
2154 v_state
, op
, v_econtext
);
2155 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
2159 build_EvalXFunc(b
, mod
, "ExecEvalJsonIsPredicate",
2161 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
2164 case EEOP_JSONEXPR_PATH
:
2166 JsonExprState
*jsestate
= op
->d
.jsonexpr
.jsestate
;
2170 * Call ExecEvalJsonExprPath(). It returns the address of
2171 * the step to perform next.
2173 v_ret
= build_EvalXFunc(b
, mod
, "ExecEvalJsonExprPath",
2174 v_state
, op
, v_econtext
);
2177 * Build a switch to map the return value (v_ret above),
2178 * which is a runtime value of the step address to perform
2179 * next, to either jump_empty, jump_error,
2180 * jump_eval_coercion, or jump_end.
2182 if (jsestate
->jump_empty
>= 0 ||
2183 jsestate
->jump_error
>= 0 ||
2184 jsestate
->jump_eval_coercion
>= 0)
2186 LLVMValueRef v_jump_empty
;
2187 LLVMValueRef v_jump_error
;
2188 LLVMValueRef v_jump_coercion
;
2189 LLVMValueRef v_switch
;
2190 LLVMBasicBlockRef b_done
,
2196 l_bb_before_v(opblocks
[opno
+ 1],
2197 "op.%d.jsonexpr_empty", opno
);
2199 l_bb_before_v(opblocks
[opno
+ 1],
2200 "op.%d.jsonexpr_error", opno
);
2202 l_bb_before_v(opblocks
[opno
+ 1],
2203 "op.%d.jsonexpr_coercion", opno
);
2205 l_bb_before_v(opblocks
[opno
+ 1],
2206 "op.%d.jsonexpr_done", opno
);
2208 v_switch
= LLVMBuildSwitch(b
,
2212 /* Returned jsestate->jump_empty? */
2213 if (jsestate
->jump_empty
>= 0)
2215 v_jump_empty
= l_int32_const(lc
, jsestate
->jump_empty
);
2216 LLVMAddCase(v_switch
, v_jump_empty
, b_empty
);
2219 LLVMPositionBuilderAtEnd(b
, b_empty
);
2220 if (jsestate
->jump_empty
>= 0)
2221 LLVMBuildBr(b
, opblocks
[jsestate
->jump_empty
]);
2223 LLVMBuildUnreachable(b
);
2225 /* Returned jsestate->jump_error? */
2226 if (jsestate
->jump_error
>= 0)
2228 v_jump_error
= l_int32_const(lc
, jsestate
->jump_error
);
2229 LLVMAddCase(v_switch
, v_jump_error
, b_error
);
2232 LLVMPositionBuilderAtEnd(b
, b_error
);
2233 if (jsestate
->jump_error
>= 0)
2234 LLVMBuildBr(b
, opblocks
[jsestate
->jump_error
]);
2236 LLVMBuildUnreachable(b
);
2238 /* Returned jsestate->jump_eval_coercion? */
2239 if (jsestate
->jump_eval_coercion
>= 0)
2241 v_jump_coercion
= l_int32_const(lc
, jsestate
->jump_eval_coercion
);
2242 LLVMAddCase(v_switch
, v_jump_coercion
, b_coercion
);
2244 /* jump_eval_coercion code */
2245 LLVMPositionBuilderAtEnd(b
, b_coercion
);
2246 if (jsestate
->jump_eval_coercion
>= 0)
2247 LLVMBuildBr(b
, opblocks
[jsestate
->jump_eval_coercion
]);
2249 LLVMBuildUnreachable(b
);
2251 LLVMPositionBuilderAtEnd(b
, b_done
);
2254 LLVMBuildBr(b
, opblocks
[jsestate
->jump_end
]);
2258 case EEOP_JSONEXPR_COERCION
:
2259 build_EvalXFunc(b
, mod
, "ExecEvalJsonCoercion",
2260 v_state
, op
, v_econtext
);
2262 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
2265 case EEOP_JSONEXPR_COERCION_FINISH
:
2266 build_EvalXFunc(b
, mod
, "ExecEvalJsonCoercionFinish",
2269 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
2274 LLVMValueRef v_aggno
;
2278 v_aggno
= l_int32_const(lc
, op
->d
.aggref
.aggno
);
2280 /* load agg value / null */
2281 value
= l_load_gep1(b
, TypeSizeT
, v_aggvalues
, v_aggno
, "aggvalue");
2282 isnull
= l_load_gep1(b
, TypeStorageBool
, v_aggnulls
, v_aggno
, "aggnull");
2284 /* and store result */
2285 LLVMBuildStore(b
, value
, v_resvaluep
);
2286 LLVMBuildStore(b
, isnull
, v_resnullp
);
2288 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
2292 case EEOP_GROUPING_FUNC
:
2293 build_EvalXFunc(b
, mod
, "ExecEvalGroupingFunc",
2295 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
2298 case EEOP_WINDOW_FUNC
:
2300 WindowFuncExprState
*wfunc
= op
->d
.window_func
.wfstate
;
2301 LLVMValueRef v_wfuncnop
;
2302 LLVMValueRef v_wfuncno
;
2307 * At this point aggref->wfuncno is not yet set (it's set
2308 * up in ExecInitWindowAgg() after initializing the
2309 * expression). So load it from memory each time round.
2311 v_wfuncnop
= l_ptr_const(&wfunc
->wfuncno
,
2312 l_ptr(LLVMInt32TypeInContext(lc
)));
2313 v_wfuncno
= l_load(b
, LLVMInt32TypeInContext(lc
), v_wfuncnop
, "v_wfuncno");
2315 /* load window func value / null */
2316 value
= l_load_gep1(b
, TypeSizeT
, v_aggvalues
, v_wfuncno
,
2318 isnull
= l_load_gep1(b
, TypeStorageBool
, v_aggnulls
, v_wfuncno
,
2321 LLVMBuildStore(b
, value
, v_resvaluep
);
2322 LLVMBuildStore(b
, isnull
, v_resnullp
);
2324 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
2328 case EEOP_MERGE_SUPPORT_FUNC
:
2329 build_EvalXFunc(b
, mod
, "ExecEvalMergeSupportFunc",
2330 v_state
, op
, v_econtext
);
2331 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
2335 build_EvalXFunc(b
, mod
, "ExecEvalSubPlan",
2336 v_state
, op
, v_econtext
);
2337 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
2340 case EEOP_AGG_STRICT_DESERIALIZE
:
2341 case EEOP_AGG_DESERIALIZE
:
2344 FunctionCallInfo fcinfo
= op
->d
.agg_deserialize
.fcinfo_data
;
2346 LLVMValueRef v_retval
;
2347 LLVMValueRef v_fcinfo_isnull
;
2348 LLVMValueRef v_tmpcontext
;
2349 LLVMValueRef v_oldcontext
;
2351 if (opcode
== EEOP_AGG_STRICT_DESERIALIZE
)
2353 LLVMValueRef v_fcinfo
;
2354 LLVMValueRef v_argnull0
;
2355 LLVMBasicBlockRef b_deserialize
;
2357 b_deserialize
= l_bb_before_v(opblocks
[opno
+ 1],
2358 "op.%d.deserialize", opno
);
2360 v_fcinfo
= l_ptr_const(fcinfo
,
2361 l_ptr(StructFunctionCallInfoData
));
2362 v_argnull0
= l_funcnull(b
, v_fcinfo
, 0);
2370 opblocks
[op
->d
.agg_deserialize
.jumpnull
],
2372 LLVMPositionBuilderAtEnd(b
, b_deserialize
);
2375 aggstate
= castNode(AggState
, state
->parent
);
2376 fcinfo
= op
->d
.agg_deserialize
.fcinfo_data
;
2379 l_ptr_const(aggstate
->tmpcontext
->ecxt_per_tuple_memory
,
2380 l_ptr(StructMemoryContextData
));
2381 v_oldcontext
= l_mcxt_switch(mod
, b
, v_tmpcontext
);
2382 v_retval
= BuildV1Call(context
, b
, mod
, fcinfo
,
2384 l_mcxt_switch(mod
, b
, v_oldcontext
);
2386 LLVMBuildStore(b
, v_retval
, v_resvaluep
);
2387 LLVMBuildStore(b
, v_fcinfo_isnull
, v_resnullp
);
2389 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
2393 case EEOP_AGG_STRICT_INPUT_CHECK_ARGS
:
2394 case EEOP_AGG_STRICT_INPUT_CHECK_NULLS
:
2396 int nargs
= op
->d
.agg_strict_input_check
.nargs
;
2397 NullableDatum
*args
= op
->d
.agg_strict_input_check
.args
;
2398 bool *nulls
= op
->d
.agg_strict_input_check
.nulls
;
2401 LLVMValueRef v_argsp
;
2402 LLVMValueRef v_nullsp
;
2403 LLVMBasicBlockRef
*b_checknulls
;
2407 jumpnull
= op
->d
.agg_strict_input_check
.jumpnull
;
2408 v_argsp
= l_ptr_const(args
, l_ptr(StructNullableDatum
));
2409 v_nullsp
= l_ptr_const(nulls
, l_ptr(TypeStorageBool
));
2411 /* create blocks for checking args */
2412 b_checknulls
= palloc(sizeof(LLVMBasicBlockRef
*) * nargs
);
2413 for (int argno
= 0; argno
< nargs
; argno
++)
2415 b_checknulls
[argno
] =
2416 l_bb_before_v(opblocks
[opno
+ 1],
2417 "op.%d.check-null.%d",
2421 LLVMBuildBr(b
, b_checknulls
[0]);
2423 /* strict function, check for NULL args */
2424 for (int argno
= 0; argno
< nargs
; argno
++)
2426 LLVMValueRef v_argno
= l_int32_const(lc
, argno
);
2427 LLVMValueRef v_argisnull
;
2428 LLVMBasicBlockRef b_argnotnull
;
2430 LLVMPositionBuilderAtEnd(b
, b_checknulls
[argno
]);
2432 if (argno
+ 1 == nargs
)
2433 b_argnotnull
= opblocks
[opno
+ 1];
2435 b_argnotnull
= b_checknulls
[argno
+ 1];
2437 if (opcode
== EEOP_AGG_STRICT_INPUT_CHECK_NULLS
)
2438 v_argisnull
= l_load_gep1(b
, TypeStorageBool
, v_nullsp
, v_argno
, "");
2441 LLVMValueRef v_argn
;
2443 v_argn
= l_gep(b
, StructNullableDatum
, v_argsp
, &v_argno
, 1, "");
2445 l_load_struct_gep(b
, StructNullableDatum
, v_argn
,
2446 FIELDNO_NULLABLE_DATUM_ISNULL
,
2454 l_sbool_const(1), ""),
2462 case EEOP_AGG_PLAIN_PERGROUP_NULLCHECK
:
2465 LLVMValueRef v_aggstatep
;
2466 LLVMValueRef v_allpergroupsp
;
2467 LLVMValueRef v_pergroup_allaggs
;
2468 LLVMValueRef v_setoff
;
2470 jumpnull
= op
->d
.agg_plain_pergroup_nullcheck
.jumpnull
;
2473 * pergroup_allaggs = aggstate->all_pergroups
2474 * [op->d.agg_plain_pergroup_nullcheck.setoff];
2476 v_aggstatep
= LLVMBuildBitCast(b
, v_parent
,
2477 l_ptr(StructAggState
), "");
2479 v_allpergroupsp
= l_load_struct_gep(b
,
2482 FIELDNO_AGGSTATE_ALL_PERGROUPS
,
2483 "aggstate.all_pergroups");
2485 v_setoff
= l_int32_const(lc
, op
->d
.agg_plain_pergroup_nullcheck
.setoff
);
2487 v_pergroup_allaggs
= l_load_gep1(b
, l_ptr(StructAggStatePerGroupData
),
2488 v_allpergroupsp
, v_setoff
, "");
2491 LLVMBuildICmp(b
, LLVMIntEQ
,
2492 LLVMBuildPtrToInt(b
, v_pergroup_allaggs
, TypeSizeT
, ""),
2493 l_sizet_const(0), ""),
2495 opblocks
[opno
+ 1]);
2499 case EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL
:
2500 case EEOP_AGG_PLAIN_TRANS_STRICT_BYVAL
:
2501 case EEOP_AGG_PLAIN_TRANS_BYVAL
:
2502 case EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF
:
2503 case EEOP_AGG_PLAIN_TRANS_STRICT_BYREF
:
2504 case EEOP_AGG_PLAIN_TRANS_BYREF
:
2507 AggStatePerTrans pertrans
;
2508 FunctionCallInfo fcinfo
;
2510 LLVMValueRef v_aggstatep
;
2511 LLVMValueRef v_fcinfo
;
2512 LLVMValueRef v_fcinfo_isnull
;
2514 LLVMValueRef v_transvaluep
;
2515 LLVMValueRef v_transnullp
;
2517 LLVMValueRef v_setoff
;
2518 LLVMValueRef v_transno
;
2520 LLVMValueRef v_aggcontext
;
2522 LLVMValueRef v_allpergroupsp
;
2523 LLVMValueRef v_current_setp
;
2524 LLVMValueRef v_current_pertransp
;
2525 LLVMValueRef v_curaggcontext
;
2527 LLVMValueRef v_pertransp
;
2529 LLVMValueRef v_pergroupp
;
2531 LLVMValueRef v_retval
;
2533 LLVMValueRef v_tmpcontext
;
2534 LLVMValueRef v_oldcontext
;
2536 aggstate
= castNode(AggState
, state
->parent
);
2537 pertrans
= op
->d
.agg_trans
.pertrans
;
2539 fcinfo
= pertrans
->transfn_fcinfo
;
2542 LLVMBuildBitCast(b
, v_parent
, l_ptr(StructAggState
), "");
2543 v_pertransp
= l_ptr_const(pertrans
,
2544 l_ptr(StructAggStatePerTransData
));
2547 * pergroup = &aggstate->all_pergroups
2548 * [op->d.agg_trans.setoff] [op->d.agg_trans.transno];
2551 l_load_struct_gep(b
,
2554 FIELDNO_AGGSTATE_ALL_PERGROUPS
,
2555 "aggstate.all_pergroups");
2556 v_setoff
= l_int32_const(lc
, op
->d
.agg_trans
.setoff
);
2557 v_transno
= l_int32_const(lc
, op
->d
.agg_trans
.transno
);
2560 StructAggStatePerGroupData
,
2561 l_load_gep1(b
, l_ptr(StructAggStatePerGroupData
),
2562 v_allpergroupsp
, v_setoff
, ""),
2566 if (opcode
== EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL
||
2567 opcode
== EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF
)
2569 LLVMValueRef v_notransvalue
;
2570 LLVMBasicBlockRef b_init
;
2571 LLVMBasicBlockRef b_no_init
;
2574 l_load_struct_gep(b
,
2575 StructAggStatePerGroupData
,
2577 FIELDNO_AGGSTATEPERGROUPDATA_NOTRANSVALUE
,
2580 b_init
= l_bb_before_v(opblocks
[opno
+ 1],
2581 "op.%d.inittrans", opno
);
2582 b_no_init
= l_bb_before_v(opblocks
[opno
+ 1],
2583 "op.%d.no_inittrans", opno
);
2586 LLVMBuildICmp(b
, LLVMIntEQ
, v_notransvalue
,
2587 l_sbool_const(1), ""),
2591 /* block to init the transition value if necessary */
2593 LLVMValueRef params
[4];
2595 LLVMPositionBuilderAtEnd(b
, b_init
);
2597 v_aggcontext
= l_ptr_const(op
->d
.agg_trans
.aggcontext
,
2598 l_ptr(StructExprContext
));
2600 params
[0] = v_aggstatep
;
2601 params
[1] = v_pertransp
;
2602 params
[2] = v_pergroupp
;
2603 params
[3] = v_aggcontext
;
2606 llvm_pg_var_func_type("ExecAggInitGroup"),
2607 llvm_pg_func(mod
, "ExecAggInitGroup"),
2608 params
, lengthof(params
),
2611 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
2614 LLVMPositionBuilderAtEnd(b
, b_no_init
);
2617 if (opcode
== EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL
||
2618 opcode
== EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF
||
2619 opcode
== EEOP_AGG_PLAIN_TRANS_STRICT_BYVAL
||
2620 opcode
== EEOP_AGG_PLAIN_TRANS_STRICT_BYREF
)
2622 LLVMValueRef v_transnull
;
2623 LLVMBasicBlockRef b_strictpass
;
2625 b_strictpass
= l_bb_before_v(opblocks
[opno
+ 1],
2626 "op.%d.strictpass", opno
);
2628 l_load_struct_gep(b
,
2629 StructAggStatePerGroupData
,
2631 FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL
,
2635 LLVMBuildICmp(b
, LLVMIntEQ
, v_transnull
,
2636 l_sbool_const(1), ""),
2640 LLVMPositionBuilderAtEnd(b
, b_strictpass
);
2644 v_fcinfo
= l_ptr_const(fcinfo
,
2645 l_ptr(StructFunctionCallInfoData
));
2646 v_aggcontext
= l_ptr_const(op
->d
.agg_trans
.aggcontext
,
2647 l_ptr(StructExprContext
));
2653 FIELDNO_AGGSTATE_CURRENT_SET
,
2654 "aggstate.current_set");
2659 FIELDNO_AGGSTATE_CURAGGCONTEXT
,
2660 "aggstate.curaggcontext");
2661 v_current_pertransp
=
2665 FIELDNO_AGGSTATE_CURPERTRANS
,
2666 "aggstate.curpertrans");
2668 /* set aggstate globals */
2669 LLVMBuildStore(b
, v_aggcontext
, v_curaggcontext
);
2670 LLVMBuildStore(b
, l_int32_const(lc
, op
->d
.agg_trans
.setno
),
2672 LLVMBuildStore(b
, v_pertransp
, v_current_pertransp
);
2674 /* invoke transition function in per-tuple context */
2676 l_ptr_const(aggstate
->tmpcontext
->ecxt_per_tuple_memory
,
2677 l_ptr(StructMemoryContextData
));
2678 v_oldcontext
= l_mcxt_switch(mod
, b
, v_tmpcontext
);
2680 /* store transvalue in fcinfo->args[0] */
2683 StructAggStatePerGroupData
,
2685 FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUE
,
2689 StructAggStatePerGroupData
,
2691 FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL
,
2698 l_funcvaluep(b
, v_fcinfo
, 0));
2700 l_load(b
, TypeStorageBool
, v_transnullp
, "transnull"),
2701 l_funcnullp(b
, v_fcinfo
, 0));
2703 /* and invoke transition function */
2704 v_retval
= BuildV1Call(context
, b
, mod
, fcinfo
,
2708 * For pass-by-ref datatype, must copy the new value into
2709 * aggcontext and free the prior transValue. But if
2710 * transfn returned a pointer to its first input, we don't
2711 * need to do anything. Also, if transfn returned a
2712 * pointer to a R/W expanded object that is already a
2713 * child of the aggcontext, assume we can adopt that value
2714 * without copying it.
2716 if (opcode
== EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF
||
2717 opcode
== EEOP_AGG_PLAIN_TRANS_STRICT_BYREF
||
2718 opcode
== EEOP_AGG_PLAIN_TRANS_BYREF
)
2720 LLVMBasicBlockRef b_call
;
2721 LLVMBasicBlockRef b_nocall
;
2723 LLVMValueRef v_transvalue
;
2724 LLVMValueRef v_transnull
;
2725 LLVMValueRef v_newval
;
2726 LLVMValueRef params
[6];
2728 b_call
= l_bb_before_v(opblocks
[opno
+ 1],
2729 "op.%d.transcall", opno
);
2730 b_nocall
= l_bb_before_v(opblocks
[opno
+ 1],
2731 "op.%d.transnocall", opno
);
2733 v_transvalue
= l_load(b
, TypeSizeT
, v_transvaluep
, "");
2734 v_transnull
= l_load(b
, TypeStorageBool
, v_transnullp
, "");
2737 * DatumGetPointer(newVal) !=
2738 * DatumGetPointer(pergroup->transValue))
2741 LLVMBuildICmp(b
, LLVMIntEQ
,
2746 /* returned datum not passed datum, reparent */
2747 LLVMPositionBuilderAtEnd(b
, b_call
);
2749 params
[0] = v_aggstatep
;
2750 params
[1] = v_pertransp
;
2751 params
[2] = v_retval
;
2752 params
[3] = LLVMBuildTrunc(b
, v_fcinfo_isnull
,
2754 params
[4] = v_transvalue
;
2755 params
[5] = LLVMBuildTrunc(b
, v_transnull
,
2758 v_fn
= llvm_pg_func(mod
, "ExecAggCopyTransValue");
2761 LLVMGetFunctionType(v_fn
),
2763 params
, lengthof(params
),
2766 /* store trans value */
2767 LLVMBuildStore(b
, v_newval
, v_transvaluep
);
2768 LLVMBuildStore(b
, v_fcinfo_isnull
, v_transnullp
);
2770 l_mcxt_switch(mod
, b
, v_oldcontext
);
2771 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
2773 /* returned datum passed datum, no need to reparent */
2774 LLVMPositionBuilderAtEnd(b
, b_nocall
);
2777 /* store trans value */
2778 LLVMBuildStore(b
, v_retval
, v_transvaluep
);
2779 LLVMBuildStore(b
, v_fcinfo_isnull
, v_transnullp
);
2781 l_mcxt_switch(mod
, b
, v_oldcontext
);
2783 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
2787 case EEOP_AGG_PRESORTED_DISTINCT_SINGLE
:
2789 AggState
*aggstate
= castNode(AggState
, state
->parent
);
2790 AggStatePerTrans pertrans
= op
->d
.agg_presorted_distinctcheck
.pertrans
;
2791 int jumpdistinct
= op
->d
.agg_presorted_distinctcheck
.jumpdistinct
;
2793 LLVMValueRef v_fn
= llvm_pg_func(mod
, "ExecEvalPreOrderedDistinctSingle");
2794 LLVMValueRef v_args
[2];
2797 v_args
[0] = l_ptr_const(aggstate
, l_ptr(StructAggState
));
2798 v_args
[1] = l_ptr_const(pertrans
, l_ptr(StructAggStatePerTransData
));
2800 v_ret
= l_call(b
, LLVMGetFunctionType(v_fn
), v_fn
, v_args
, 2, "");
2801 v_ret
= LLVMBuildZExt(b
, v_ret
, TypeStorageBool
, "");
2804 LLVMBuildICmp(b
, LLVMIntEQ
, v_ret
,
2805 l_sbool_const(1), ""),
2807 opblocks
[jumpdistinct
]);
2811 case EEOP_AGG_PRESORTED_DISTINCT_MULTI
:
2813 AggState
*aggstate
= castNode(AggState
, state
->parent
);
2814 AggStatePerTrans pertrans
= op
->d
.agg_presorted_distinctcheck
.pertrans
;
2815 int jumpdistinct
= op
->d
.agg_presorted_distinctcheck
.jumpdistinct
;
2817 LLVMValueRef v_fn
= llvm_pg_func(mod
, "ExecEvalPreOrderedDistinctMulti");
2818 LLVMValueRef v_args
[2];
2821 v_args
[0] = l_ptr_const(aggstate
, l_ptr(StructAggState
));
2822 v_args
[1] = l_ptr_const(pertrans
, l_ptr(StructAggStatePerTransData
));
2824 v_ret
= l_call(b
, LLVMGetFunctionType(v_fn
), v_fn
, v_args
, 2, "");
2825 v_ret
= LLVMBuildZExt(b
, v_ret
, TypeStorageBool
, "");
2828 LLVMBuildICmp(b
, LLVMIntEQ
, v_ret
,
2829 l_sbool_const(1), ""),
2831 opblocks
[jumpdistinct
]);
2835 case EEOP_AGG_ORDERED_TRANS_DATUM
:
2836 build_EvalXFunc(b
, mod
, "ExecEvalAggOrderedTransDatum",
2837 v_state
, op
, v_econtext
);
2838 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
2841 case EEOP_AGG_ORDERED_TRANS_TUPLE
:
2842 build_EvalXFunc(b
, mod
, "ExecEvalAggOrderedTransTuple",
2843 v_state
, op
, v_econtext
);
2844 LLVMBuildBr(b
, opblocks
[opno
+ 1]);
2853 LLVMDisposeBuilder(b
);
2856 * Don't immediately emit function, instead do so the first time the
2857 * expression is actually evaluated. That allows to emit a lot of
2858 * functions together, avoiding a lot of repeated llvm and memory
2859 * remapping overhead.
2863 CompiledExprState
*cstate
= palloc0(sizeof(CompiledExprState
));
2865 cstate
->context
= context
;
2866 cstate
->funcname
= funcname
;
2868 state
->evalfunc
= ExecRunCompiledExpr
;
2869 state
->evalfunc_private
= cstate
;
2872 llvm_leave_fatal_on_oom();
2874 INSTR_TIME_SET_CURRENT(endtime
);
2875 INSTR_TIME_ACCUM_DIFF(context
->base
.instr
.generation_counter
,
2876 endtime
, starttime
);
2882 * Run compiled expression.
2884 * This will only be called the first time a JITed expression is called. We
2885 * first make sure the expression is still up-to-date, and then get a pointer to
2886 * the emitted function. The latter can be the first thing that triggers
2887 * optimizing and emitting all the generated functions.
2890 ExecRunCompiledExpr(ExprState
*state
, ExprContext
*econtext
, bool *isNull
)
2892 CompiledExprState
*cstate
= state
->evalfunc_private
;
2893 ExprStateEvalFunc func
;
2895 CheckExprStillValid(state
, econtext
);
2897 llvm_enter_fatal_on_oom();
2898 func
= (ExprStateEvalFunc
) llvm_get_function(cstate
->context
,
2900 llvm_leave_fatal_on_oom();
2903 /* remove indirection via this function for future calls */
2904 state
->evalfunc
= func
;
2906 return func(state
, econtext
, isNull
);
2910 BuildV1Call(LLVMJitContext
*context
, LLVMBuilderRef b
,
2911 LLVMModuleRef mod
, FunctionCallInfo fcinfo
,
2912 LLVMValueRef
*v_fcinfo_isnull
)
2916 LLVMValueRef v_fcinfo_isnullp
;
2917 LLVMValueRef v_retval
;
2918 LLVMValueRef v_fcinfo
;
2920 lc
= LLVMGetModuleContext(mod
);
2922 v_fn
= llvm_function_reference(context
, b
, mod
, fcinfo
);
2924 v_fcinfo
= l_ptr_const(fcinfo
, l_ptr(StructFunctionCallInfoData
));
2925 v_fcinfo_isnullp
= l_struct_gep(b
,
2926 StructFunctionCallInfoData
,
2928 FIELDNO_FUNCTIONCALLINFODATA_ISNULL
,
2930 LLVMBuildStore(b
, l_sbool_const(0), v_fcinfo_isnullp
);
2932 v_retval
= l_call(b
, LLVMGetFunctionType(AttributeTemplate
), v_fn
, &v_fcinfo
, 1, "funccall");
2934 if (v_fcinfo_isnull
)
2935 *v_fcinfo_isnull
= l_load(b
, TypeStorageBool
, v_fcinfo_isnullp
, "");
2938 * Add lifetime-end annotation, signaling that writes to memory don't have
2939 * to be retained (important for inlining potential).
2942 LLVMValueRef v_lifetime
= create_LifetimeEnd(mod
);
2943 LLVMValueRef params
[2];
2945 params
[0] = l_int64_const(lc
, sizeof(NullableDatum
) * fcinfo
->nargs
);
2946 params
[1] = l_ptr_const(fcinfo
->args
, l_ptr(LLVMInt8TypeInContext(lc
)));
2947 l_call(b
, LLVMGetFunctionType(v_lifetime
), v_lifetime
, params
, lengthof(params
), "");
2949 params
[0] = l_int64_const(lc
, sizeof(fcinfo
->isnull
));
2950 params
[1] = l_ptr_const(&fcinfo
->isnull
, l_ptr(LLVMInt8TypeInContext(lc
)));
2951 l_call(b
, LLVMGetFunctionType(v_lifetime
), v_lifetime
, params
, lengthof(params
), "");
2958 * Implement an expression step by calling the function funcname.
2961 build_EvalXFuncInt(LLVMBuilderRef b
, LLVMModuleRef mod
, const char *funcname
,
2962 LLVMValueRef v_state
, ExprEvalStep
*op
,
2963 int nargs
, LLVMValueRef
*v_args
)
2965 LLVMValueRef v_fn
= llvm_pg_func(mod
, funcname
);
2966 LLVMValueRef
*params
;
2970 /* cheap pre-check as llvm just asserts out */
2971 if (LLVMCountParams(v_fn
) != (nargs
+ 2))
2972 elog(ERROR
, "parameter mismatch: %s expects %d passed %d",
2973 funcname
, LLVMCountParams(v_fn
), nargs
+ 2);
2975 params
= palloc(sizeof(LLVMValueRef
) * (2 + nargs
));
2977 params
[argno
++] = v_state
;
2978 params
[argno
++] = l_ptr_const(op
, l_ptr(StructExprEvalStep
));
2980 for (int i
= 0; i
< nargs
; i
++)
2981 params
[argno
++] = v_args
[i
];
2983 v_ret
= l_call(b
, LLVMGetFunctionType(v_fn
), v_fn
, params
, argno
, "");
2991 create_LifetimeEnd(LLVMModuleRef mod
)
2995 LLVMTypeRef param_types
[2];
2998 /* variadic pointer argument */
2999 const char *nm
= "llvm.lifetime.end.p0";
3001 fn
= LLVMGetNamedFunction(mod
, nm
);
3005 lc
= LLVMGetModuleContext(mod
);
3006 param_types
[0] = LLVMInt64TypeInContext(lc
);
3007 param_types
[1] = l_ptr(LLVMInt8TypeInContext(lc
));
3009 sig
= LLVMFunctionType(LLVMVoidTypeInContext(lc
), param_types
,
3010 lengthof(param_types
), false);
3011 fn
= LLVMAddFunction(mod
, nm
, sig
);
3013 LLVMSetFunctionCallConv(fn
, LLVMCCallConv
);
3015 Assert(LLVMGetIntrinsicID(fn
));