Use caller's memory context for radix tree iteration state
[pgsql.git] / src / backend / jit / llvm / llvmjit_expr.c
blob6c4915e373107dc42cc61b3c33b8e1db2d652608
1 /*-------------------------------------------------------------------------
3 * llvmjit_expr.c
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
10 * IDENTIFICATION
11 * src/backend/jit/llvm/llvmjit_expr.c
13 *-------------------------------------------------------------------------
16 #include "postgres.h"
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"
29 #include "funcapi.h"
30 #include "jit/llvmjit.h"
31 #include "jit/llvmjit_emit.h"
32 #include "miscadmin.h"
33 #include "nodes/makefuncs.h"
34 #include "nodes/nodeFuncs.h"
35 #include "parser/parse_coerce.h"
36 #include "parser/parsetree.h"
37 #include "pgstat.h"
38 #include "utils/acl.h"
39 #include "utils/builtins.h"
40 #include "utils/date.h"
41 #include "utils/fmgrtab.h"
42 #include "utils/lsyscache.h"
43 #include "utils/memutils.h"
44 #include "utils/timestamp.h"
45 #include "utils/typcache.h"
46 #include "utils/xml.h"
48 typedef struct CompiledExprState
50 LLVMJitContext *context;
51 const char *funcname;
52 } CompiledExprState;
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,
61 const char *funcname,
62 LLVMValueRef v_state,
63 ExprEvalStep *op,
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.
77 bool
78 llvm_compile_expr(ExprState *state)
80 PlanState *parent = state->parent;
81 char *funcname;
83 LLVMJitContext *context = NULL;
85 LLVMBuilderRef b;
86 LLVMModuleRef mod;
87 LLVMContextRef lc;
88 LLVMValueRef eval_fn;
89 LLVMBasicBlockRef entry;
90 LLVMBasicBlockRef *opblocks;
92 /* state itself */
93 LLVMValueRef v_state;
94 LLVMValueRef v_econtext;
95 LLVMValueRef v_parent;
97 /* returnvalue */
98 LLVMValueRef v_isnullp;
100 /* tmp vars in state */
101 LLVMValueRef v_tmpvaluep;
102 LLVMValueRef v_tmpisnullp;
104 /* slots */
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;
126 instr_time endtime;
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.
135 Assert(parent);
137 /* get or create JIT context */
138 if (parent->state->es_jit)
139 context = (LLVMJitContext *) parent->state->es_jit;
140 else
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");
164 /* build state */
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,
172 StructExprState,
173 v_state,
174 FIELDNO_EXPRSTATE_RESVALUE,
175 "v.state.resvalue");
176 v_tmpisnullp = l_struct_gep(b,
177 StructExprState,
178 v_state,
179 FIELDNO_EXPRSTATE_RESNULL,
180 "v.state.resnull");
181 v_parent = l_load_struct_gep(b,
182 StructExprState,
183 v_state,
184 FIELDNO_EXPRSTATE_PARENT,
185 "v.state.parent");
187 /* build global slots */
188 v_scanslot = l_load_struct_gep(b,
189 StructExprContext,
190 v_econtext,
191 FIELDNO_EXPRCONTEXT_SCANTUPLE,
192 "v_scanslot");
193 v_innerslot = l_load_struct_gep(b,
194 StructExprContext,
195 v_econtext,
196 FIELDNO_EXPRCONTEXT_INNERTUPLE,
197 "v_innerslot");
198 v_outerslot = l_load_struct_gep(b,
199 StructExprContext,
200 v_econtext,
201 FIELDNO_EXPRCONTEXT_OUTERTUPLE,
202 "v_outerslot");
203 v_resultslot = l_load_struct_gep(b,
204 StructExprState,
205 v_state,
206 FIELDNO_EXPRSTATE_RESULTSLOT,
207 "v_resultslot");
209 /* build global values/isnull pointers */
210 v_scanvalues = l_load_struct_gep(b,
211 StructTupleTableSlot,
212 v_scanslot,
213 FIELDNO_TUPLETABLESLOT_VALUES,
214 "v_scanvalues");
215 v_scannulls = l_load_struct_gep(b,
216 StructTupleTableSlot,
217 v_scanslot,
218 FIELDNO_TUPLETABLESLOT_ISNULL,
219 "v_scannulls");
220 v_innervalues = l_load_struct_gep(b,
221 StructTupleTableSlot,
222 v_innerslot,
223 FIELDNO_TUPLETABLESLOT_VALUES,
224 "v_innervalues");
225 v_innernulls = l_load_struct_gep(b,
226 StructTupleTableSlot,
227 v_innerslot,
228 FIELDNO_TUPLETABLESLOT_ISNULL,
229 "v_innernulls");
230 v_outervalues = l_load_struct_gep(b,
231 StructTupleTableSlot,
232 v_outerslot,
233 FIELDNO_TUPLETABLESLOT_VALUES,
234 "v_outervalues");
235 v_outernulls = l_load_struct_gep(b,
236 StructTupleTableSlot,
237 v_outerslot,
238 FIELDNO_TUPLETABLESLOT_ISNULL,
239 "v_outernulls");
240 v_resultvalues = l_load_struct_gep(b,
241 StructTupleTableSlot,
242 v_resultslot,
243 FIELDNO_TUPLETABLESLOT_VALUES,
244 "v_resultvalues");
245 v_resultnulls = l_load_struct_gep(b,
246 StructTupleTableSlot,
247 v_resultslot,
248 FIELDNO_TUPLETABLESLOT_ISNULL,
249 "v_resultnulls");
251 /* aggvalues/aggnulls */
252 v_aggvalues = l_load_struct_gep(b,
253 StructExprContext,
254 v_econtext,
255 FIELDNO_EXPRCONTEXT_AGGVALUES,
256 "v.econtext.aggvalues");
257 v_aggnulls = l_load_struct_gep(b,
258 StructExprContext,
259 v_econtext,
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++)
273 ExprEvalStep *op;
274 ExprEvalOp opcode;
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));
286 switch (opcode)
288 case EEOP_DONE:
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);
299 break;
302 case EEOP_INNER_FETCHSOME:
303 case EEOP_OUTER_FETCHSOME:
304 case EEOP_SCAN_FETCHSOME:
306 TupleDesc desc = NULL;
307 LLVMValueRef v_slot;
308 LLVMBasicBlockRef b_fetch;
309 LLVMValueRef v_nvalid;
310 LLVMValueRef l_jit_deform = NULL;
311 const TupleTableSlotOps *tts_ops = NULL;
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;
329 else
330 v_slot = v_scanslot;
333 * Check if all required attributes are available, or
334 * whether deforming is required.
336 v_nvalid =
337 l_load_struct_gep(b,
338 StructTupleTableSlot,
339 v_slot,
340 FIELDNO_TUPLETABLESLOT_NVALID,
341 "");
342 LLVMBuildCondBr(b,
343 LLVMBuildICmp(b, LLVMIntUGE, v_nvalid,
344 l_int16_const(lc, op->d.fetch.last_var),
345 ""),
346 opblocks[opno + 1], b_fetch);
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);
359 l_jit_deform =
360 slot_compile_deform(context, desc,
361 tts_ops,
362 op->d.fetch.last_var);
363 INSTR_TIME_SET_CURRENT(deform_endtime);
364 INSTR_TIME_ACCUM_DIFF(context->base.instr.deform_counter,
365 deform_endtime, deform_starttime);
368 if (l_jit_deform)
370 LLVMValueRef params[1];
372 params[0] = v_slot;
374 l_call(b,
375 LLVMGetFunctionType(l_jit_deform),
376 l_jit_deform,
377 params, lengthof(params), "");
379 else
381 LLVMValueRef params[2];
383 params[0] = v_slot;
384 params[1] = l_int32_const(lc, op->d.fetch.last_var);
386 l_call(b,
387 llvm_pg_var_func_type("slot_getsomeattrs_int"),
388 llvm_pg_func(mod, "slot_getsomeattrs_int"),
389 params, lengthof(params), "");
392 LLVMBuildBr(b, opblocks[opno + 1]);
393 break;
396 case EEOP_INNER_VAR:
397 case EEOP_OUTER_VAR:
398 case EEOP_SCAN_VAR:
400 LLVMValueRef value,
401 isnull;
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;
416 else
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]);
429 break;
432 case EEOP_INNER_SYSVAR:
433 case EEOP_OUTER_SYSVAR:
434 case EEOP_SCAN_SYSVAR:
436 LLVMValueRef v_slot;
438 if (opcode == EEOP_INNER_SYSVAR)
439 v_slot = v_innerslot;
440 else if (opcode == EEOP_OUTER_SYSVAR)
441 v_slot = v_outerslot;
442 else
443 v_slot = v_scanslot;
445 build_EvalXFunc(b, mod, "ExecEvalSysVar",
446 v_state, op, v_econtext, v_slot);
448 LLVMBuildBr(b, opblocks[opno + 1]);
449 break;
452 case EEOP_WHOLEROW:
453 build_EvalXFunc(b, mod, "ExecEvalWholeRowVar",
454 v_state, op, v_econtext);
455 LLVMBuildBr(b, opblocks[opno + 1]);
456 break;
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;
481 else
483 v_values = v_scanvalues;
484 v_nulls = v_scannulls;
487 /* load data */
488 v_attnum = l_int32_const(lc, op->d.assign_var.attnum);
489 v_value = l_load_gep1(b, TypeSizeT, v_values, v_attnum, "");
490 v_isnull = l_load_gep1(b, TypeStorageBool, v_nulls, v_attnum, "");
492 /* compute addresses of targets */
493 v_resultnum = l_int32_const(lc, op->d.assign_var.resultnum);
494 v_rvaluep = l_gep(b,
495 TypeSizeT,
496 v_resultvalues,
497 &v_resultnum, 1, "");
498 v_risnullp = l_gep(b,
499 TypeStorageBool,
500 v_resultnulls,
501 &v_resultnum, 1, "");
503 /* and store */
504 LLVMBuildStore(b, v_value, v_rvaluep);
505 LLVMBuildStore(b, v_isnull, v_risnullp);
507 LLVMBuildBr(b, opblocks[opno + 1]);
508 break;
511 case EEOP_ASSIGN_TMP:
512 case EEOP_ASSIGN_TMP_MAKE_RO:
514 LLVMValueRef v_value,
515 v_isnull;
516 LLVMValueRef v_rvaluep,
517 v_risnullp;
518 LLVMValueRef v_resultnum;
519 size_t resultnum = op->d.assign_tmp.resultnum;
521 /* load data */
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);
527 v_rvaluep =
528 l_gep(b, TypeSizeT, v_resultvalues, &v_resultnum, 1, "");
529 v_risnullp =
530 l_gep(b, TypeStorageBool, v_resultnulls, &v_resultnum, 1, "");
532 /* store nullness */
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 */
545 LLVMBuildCondBr(b,
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;
553 v_value =
554 l_call(b,
555 llvm_pg_var_func_type("MakeExpandedObjectReadOnlyInternal"),
556 llvm_pg_func(mod, "MakeExpandedObjectReadOnlyInternal"),
557 v_params, lengthof(v_params), "");
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]);
569 break;
572 case EEOP_CONST:
574 LLVMValueRef v_constvalue,
575 v_constnull;
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]);
584 break;
587 case EEOP_FUNCEXPR:
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
602 * non-NULL.
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");
611 v_fcinfo =
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 */
621 b_checkargnulls =
622 palloc(sizeof(LLVMBasicBlockRef *) * op->d.func.nargs);
623 for (int argno = 0; argno < op->d.func.nargs; argno++)
624 b_checkargnulls[argno] =
625 l_bb_before_v(b_nonull, "b.%d.isnull.%d", opno,
626 argno);
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
641 * null.
643 if (argno + 1 == op->d.func.nargs)
644 b_argnotnull = b_nonull;
645 else
646 b_argnotnull = b_checkargnulls[argno + 1];
648 /* and finally load & check NULLness of arg */
649 v_argisnull = l_funcnull(b, v_fcinfo, argno);
650 LLVMBuildCondBr(b,
651 LLVMBuildICmp(b, LLVMIntEQ,
652 v_argisnull,
653 l_sbool_const(1),
654 ""),
655 opblocks[opno + 1],
656 b_argnotnull);
659 LLVMPositionBuilderAtEnd(b, b_nonull);
662 v_retval = BuildV1Call(context, b, mod, fcinfo,
663 &v_fcinfo_isnull);
664 LLVMBuildStore(b, v_retval, v_resvaluep);
665 LLVMBuildStore(b, v_fcinfo_isnull, v_resnullp);
667 LLVMBuildBr(b, opblocks[opno + 1]);
668 break;
671 case EEOP_FUNCEXPR_FUSAGE:
672 build_EvalXFunc(b, mod, "ExecEvalFuncExprFusage",
673 v_state, op, v_econtext);
674 LLVMBuildBr(b, opblocks[opno + 1]);
675 break;
678 case EEOP_FUNCEXPR_STRICT_FUSAGE:
679 build_EvalXFunc(b, mod, "ExecEvalFuncExprStrictFusage",
680 v_state, op, v_econtext);
681 LLVMBuildBr(b, opblocks[opno + 1]);
682 break;
685 * Treat them the same for now, optimizer can remove
686 * redundancy. Could be worthwhile to optimize during emission
687 * though.
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,
696 v_boolanynull;
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 */
724 LLVMBuildCondBr(b,
725 LLVMBuildICmp(b, LLVMIntEQ, v_boolnull,
726 l_sbool_const(1), ""),
727 b_boolisnull,
728 b_boolcheckfalse);
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);
739 LLVMBuildCondBr(b,
740 LLVMBuildICmp(b, LLVMIntEQ, v_boolvalue,
741 l_sizet_const(0), ""),
742 b_boolisfalse,
743 b_boolcont);
746 * Build block handling FALSE. Value is false, so short
747 * circuit.
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 */
760 LLVMBuildCondBr(b,
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);
768 /* reset resvalue */
769 LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
771 LLVMBuildBr(b, opblocks[opno + 1]);
772 break;
776 * Treat them the same for now, optimizer can remove
777 * redundancy. Could be worthwhile to optimize during emission
778 * though.
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,
787 v_boolanynull;
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, "");
814 LLVMBuildCondBr(b,
815 LLVMBuildICmp(b, LLVMIntEQ, v_boolnull,
816 l_sbool_const(1), ""),
817 b_boolisnull,
818 b_boolchecktrue);
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);
829 LLVMBuildCondBr(b,
830 LLVMBuildICmp(b, LLVMIntEQ, v_boolvalue,
831 l_sizet_const(1), ""),
832 b_boolistrue,
833 b_boolcont);
836 * Build block handling True. Value is true, so short
837 * circuit.
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 */
850 LLVMBuildCondBr(b,
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);
858 /* reset resvalue */
859 LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
861 LLVMBuildBr(b, opblocks[opno + 1]);
862 break;
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,
874 v_boolvalue,
875 l_sizet_const(0),
876 ""),
877 TypeSizeT, "");
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]);
887 break;
890 case EEOP_QUAL:
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, "");
903 v_nullorfalse =
904 LLVMBuildOr(b,
905 LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
906 l_sbool_const(1), ""),
907 LLVMBuildICmp(b, LLVMIntEQ, v_resvalue,
908 l_sizet_const(0), ""),
909 "");
911 LLVMBuildCondBr(b,
912 v_nullorfalse,
913 b_qualfail,
914 opblocks[opno + 1]);
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);
922 /* and jump out */
923 LLVMBuildBr(b, opblocks[op->d.qualexpr.jumpdone]);
924 break;
927 case EEOP_JUMP:
929 LLVMBuildBr(b, opblocks[op->d.jump.jumpdone]);
930 break;
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, "");
941 LLVMBuildCondBr(b,
942 LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
943 l_sbool_const(1), ""),
944 opblocks[op->d.jump.jumpdone],
945 opblocks[opno + 1]);
946 break;
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, "");
957 LLVMBuildCondBr(b,
958 LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
959 l_sbool_const(0), ""),
960 opblocks[op->d.jump.jumpdone],
961 opblocks[opno + 1]);
962 break;
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, "");
977 v_nullorfalse =
978 LLVMBuildOr(b,
979 LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
980 l_sbool_const(1), ""),
981 LLVMBuildICmp(b, LLVMIntEQ, v_resvalue,
982 l_sizet_const(0), ""),
983 "");
985 LLVMBuildCondBr(b,
986 v_nullorfalse,
987 opblocks[op->d.jump.jumpdone],
988 opblocks[opno + 1]);
989 break;
992 case EEOP_NULLTEST_ISNULL:
994 LLVMValueRef v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
995 LLVMValueRef v_resvalue;
997 v_resvalue =
998 LLVMBuildSelect(b,
999 LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
1000 l_sbool_const(1), ""),
1001 l_sizet_const(1),
1002 l_sizet_const(0),
1003 "");
1004 LLVMBuildStore(b, v_resvalue, v_resvaluep);
1005 LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1007 LLVMBuildBr(b, opblocks[opno + 1]);
1008 break;
1011 case EEOP_NULLTEST_ISNOTNULL:
1013 LLVMValueRef v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
1014 LLVMValueRef v_resvalue;
1016 v_resvalue =
1017 LLVMBuildSelect(b,
1018 LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
1019 l_sbool_const(1), ""),
1020 l_sizet_const(0),
1021 l_sizet_const(1),
1022 "");
1023 LLVMBuildStore(b, v_resvalue, v_resvaluep);
1024 LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1026 LLVMBuildBr(b, opblocks[opno + 1]);
1027 break;
1030 case EEOP_NULLTEST_ROWISNULL:
1031 build_EvalXFunc(b, mod, "ExecEvalRowNull",
1032 v_state, op, v_econtext);
1033 LLVMBuildBr(b, opblocks[opno + 1]);
1034 break;
1036 case EEOP_NULLTEST_ROWISNOTNULL:
1037 build_EvalXFunc(b, mod, "ExecEvalRowNotNull",
1038 v_state, op, v_econtext);
1039 LLVMBuildBr(b, opblocks[opno + 1]);
1040 break;
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,
1048 b_notnull;
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 */
1057 LLVMBuildCondBr(b,
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);
1073 else
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
1087 * set)
1090 else
1092 LLVMValueRef v_value =
1093 l_load(b, TypeSizeT, v_resvaluep, "");
1095 v_value = LLVMBuildZExt(b,
1096 LLVMBuildICmp(b, LLVMIntEQ,
1097 v_value,
1098 l_sizet_const(0),
1099 ""),
1100 TypeSizeT, "");
1101 LLVMBuildStore(b, v_value, v_resvaluep);
1103 LLVMBuildBr(b, opblocks[opno + 1]);
1104 break;
1107 case EEOP_PARAM_EXEC:
1108 build_EvalXFunc(b, mod, "ExecEvalParamExec",
1109 v_state, op, v_econtext);
1110 LLVMBuildBr(b, opblocks[opno + 1]);
1111 break;
1113 case EEOP_PARAM_EXTERN:
1114 build_EvalXFunc(b, mod, "ExecEvalParamExtern",
1115 v_state, op, v_econtext);
1116 LLVMBuildBr(b, opblocks[opno + 1]);
1117 break;
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;
1130 l_call(b,
1131 LLVMGetFunctionType(ExecEvalSubroutineTemplate),
1132 v_func,
1133 v_params, lengthof(v_params), "");
1135 LLVMBuildBr(b, opblocks[opno + 1]);
1136 break;
1139 case EEOP_PARAM_SET:
1140 build_EvalXFunc(b, mod, "ExecEvalParamSet",
1141 v_state, op, v_econtext);
1142 LLVMBuildBr(b, opblocks[opno + 1]);
1143 break;
1145 case EEOP_SBSREF_SUBSCRIPTS:
1147 int jumpdone = op->d.sbsref_subscript.jumpdone;
1148 LLVMValueRef v_func;
1149 LLVMValueRef v_params[3];
1150 LLVMValueRef v_ret;
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;
1158 v_ret = l_call(b,
1159 LLVMGetFunctionType(ExecEvalBoolSubroutineTemplate),
1160 v_func,
1161 v_params, lengthof(v_params), "");
1162 v_ret = LLVMBuildZExt(b, v_ret, TypeStorageBool, "");
1164 LLVMBuildCondBr(b,
1165 LLVMBuildICmp(b, LLVMIntEQ, v_ret,
1166 l_sbool_const(1), ""),
1167 opblocks[opno + 1],
1168 opblocks[jumpdone]);
1169 break;
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;
1185 l_call(b,
1186 LLVMGetFunctionType(ExecEvalSubroutineTemplate),
1187 v_func,
1188 v_params, lengthof(v_params), "");
1190 LLVMBuildBr(b, opblocks[opno + 1]);
1191 break;
1194 case EEOP_CASE_TESTVAL:
1196 LLVMBasicBlockRef b_avail,
1197 b_notavail;
1198 LLVMValueRef v_casevaluep,
1199 v_casevalue;
1200 LLVMValueRef v_casenullp,
1201 v_casenull;
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,
1210 l_ptr(TypeSizeT));
1211 v_casenullp = l_ptr_const(op->d.casetest.isnull,
1212 l_ptr(TypeStorageBool));
1214 v_casevaluenull =
1215 LLVMBuildICmp(b, LLVMIntEQ,
1216 LLVMBuildPtrToInt(b, v_casevaluep,
1217 TypeSizeT, ""),
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);
1231 v_casevalue =
1232 l_load_struct_gep(b,
1233 StructExprContext,
1234 v_econtext,
1235 FIELDNO_EXPRCONTEXT_CASEDATUM, "");
1236 v_casenull =
1237 l_load_struct_gep(b,
1238 StructExprContext,
1239 v_econtext,
1240 FIELDNO_EXPRCONTEXT_CASENULL, "");
1241 LLVMBuildStore(b, v_casevalue, v_resvaluep);
1242 LLVMBuildStore(b, v_casenull, v_resnullp);
1244 LLVMBuildBr(b, opblocks[opno + 1]);
1245 break;
1248 case EEOP_MAKE_READONLY:
1250 LLVMBasicBlockRef b_notnull;
1251 LLVMValueRef v_params[1];
1252 LLVMValueRef v_ret;
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 */
1270 LLVMBuildCondBr(b,
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,
1279 l_ptr(TypeSizeT));
1281 v_value = l_load(b, TypeSizeT, v_valuep, "");
1283 v_params[0] = v_value;
1284 v_ret =
1285 l_call(b,
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]);
1292 break;
1295 case EEOP_IOCOERCE:
1297 FunctionCallInfo fcinfo_out,
1298 fcinfo_in;
1299 LLVMValueRef v_fn_out,
1300 v_fn_in;
1301 LLVMValueRef v_fcinfo_out,
1302 v_fcinfo_in;
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 =
1334 l_struct_gep(b,
1335 StructFunctionCallInfoData,
1336 v_fcinfo_in,
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, "");
1342 LLVMBuildCondBr(b,
1343 LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
1344 l_sbool_const(1), ""),
1345 b_skipoutput,
1346 b_calloutput);
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, "");
1355 /* set arg[0] */
1356 LLVMBuildStore(b,
1357 v_resvalue,
1358 l_funcvaluep(b, v_fcinfo_out, 0));
1359 LLVMBuildStore(b,
1360 l_sbool_const(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
1391 * NULL.
1393 if (op->d.iocoerce.finfo_in->fn_strict)
1395 LLVMBuildCondBr(b,
1396 LLVMBuildICmp(b, LLVMIntEQ, v_output,
1397 l_sizet_const(0), ""),
1398 opblocks[opno + 1],
1399 b_inputcall);
1401 else
1403 LLVMBuildBr(b, b_inputcall);
1406 LLVMPositionBuilderAtEnd(b, b_inputcall);
1407 /* set arguments */
1408 /* arg0: output */
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]);
1428 break;
1431 case EEOP_IOCOERCE_SAFE:
1432 build_EvalXFunc(b, mod, "ExecEvalCoerceViaIOSafe",
1433 v_state, op);
1434 LLVMBuildBr(b, opblocks[opno + 1]);
1435 break;
1437 case EEOP_DISTINCT:
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,
1446 v_argisnull0;
1447 LLVMValueRef v_argnull1,
1448 v_argisnull1;
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
1481 * comparator.
1483 LLVMBuildCondBr(b, v_anyargisnull, b_checkbothargnull,
1484 b_noargnull);
1487 * build block checking if any arg is null
1489 LLVMPositionBuilderAtEnd(b, b_checkbothargnull);
1490 LLVMBuildCondBr(b, v_bothargisnull, b_bothargnull,
1491 b_anyargnull);
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);
1499 else
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);
1509 else
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,
1517 &v_fcinfo_isnull);
1519 if (opcode == EEOP_DISTINCT)
1521 /* Must invert result of "=" */
1522 v_result =
1523 LLVMBuildZExt(b,
1524 LLVMBuildICmp(b, LLVMIntEQ,
1525 v_result,
1526 l_sizet_const(0), ""),
1527 TypeSizeT, "");
1530 LLVMBuildStore(b, v_fcinfo_isnull, v_resnullp);
1531 LLVMBuildStore(b, v_result, v_resvaluep);
1533 LLVMBuildBr(b, opblocks[opno + 1]);
1534 break;
1537 case EEOP_NULLIF:
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);
1569 v_anyargisnull =
1570 LLVMBuildOr(b,
1571 LLVMBuildICmp(b, LLVMIntEQ, v_argnull0,
1572 l_sbool_const(1), ""),
1573 LLVMBuildICmp(b, LLVMIntEQ, v_argnull1,
1574 l_sbool_const(1), ""),
1575 "");
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;
1602 v_arg0_ro =
1603 l_call(b,
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,
1620 v_fcinfo_isnull,
1621 l_sbool_const(0),
1622 ""),
1623 LLVMBuildICmp(b, LLVMIntEQ,
1624 v_retval,
1625 l_sizet_const(1),
1626 ""),
1627 "");
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]);
1636 break;
1639 case EEOP_SQLVALUEFUNCTION:
1640 build_EvalXFunc(b, mod, "ExecEvalSQLValueFunction",
1641 v_state, op);
1642 LLVMBuildBr(b, opblocks[opno + 1]);
1643 break;
1645 case EEOP_CURRENTOFEXPR:
1646 build_EvalXFunc(b, mod, "ExecEvalCurrentOfExpr",
1647 v_state, op);
1648 LLVMBuildBr(b, opblocks[opno + 1]);
1649 break;
1651 case EEOP_NEXTVALUEEXPR:
1652 build_EvalXFunc(b, mod, "ExecEvalNextValueExpr",
1653 v_state, op);
1654 LLVMBuildBr(b, opblocks[opno + 1]);
1655 break;
1657 case EEOP_ARRAYEXPR:
1658 build_EvalXFunc(b, mod, "ExecEvalArrayExpr",
1659 v_state, op);
1660 LLVMBuildBr(b, opblocks[opno + 1]);
1661 break;
1663 case EEOP_ARRAYCOERCE:
1664 build_EvalXFunc(b, mod, "ExecEvalArrayCoerce",
1665 v_state, op, v_econtext);
1666 LLVMBuildBr(b, opblocks[opno + 1]);
1667 break;
1669 case EEOP_ROW:
1670 build_EvalXFunc(b, mod, "ExecEvalRow",
1671 v_state, op);
1672 LLVMBuildBr(b, opblocks[opno + 1]);
1673 break;
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);
1689 b_compare_result =
1690 l_bb_before_v(opblocks[opno + 1],
1691 "op.%d.row-compare-result",
1692 opno);
1695 * If function is strict, and either arg is null, we're
1696 * done.
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);
1711 v_anyargisnull =
1712 LLVMBuildOr(b,
1713 LLVMBuildICmp(b,
1714 LLVMIntEQ,
1715 v_argnull0,
1716 l_sbool_const(1),
1717 ""),
1718 LLVMBuildICmp(b, LLVMIntEQ,
1719 v_argnull1,
1720 l_sbool_const(1), ""),
1721 "");
1723 LLVMBuildCondBr(b, v_anyargisnull, b_null, b_compare);
1725 else
1727 LLVMBuildBr(b, b_compare);
1730 /* build block invoking comparison function */
1731 LLVMPositionBuilderAtEnd(b, b_compare);
1733 /* call function */
1734 v_retval = BuildV1Call(context, b, mod, fcinfo,
1735 &v_fcinfo_isnull);
1736 LLVMBuildStore(b, v_retval, v_resvaluep);
1738 /* if result of function is NULL, force NULL result */
1739 LLVMBuildCondBr(b,
1740 LLVMBuildICmp(b,
1741 LLVMIntEQ,
1742 v_fcinfo_isnull,
1743 l_sbool_const(0),
1744 ""),
1745 b_compare_result,
1746 b_null);
1748 /* build block analyzing the !NULL comparator result */
1749 LLVMPositionBuilderAtEnd(b, b_compare_result);
1751 /* if results equal, compare next, otherwise done */
1752 LLVMBuildCondBr(b,
1753 LLVMBuildICmp(b,
1754 LLVMIntEQ,
1755 v_retval,
1756 l_sizet_const(0), ""),
1757 opblocks[opno + 1],
1758 opblocks[op->d.rowcompare_step.jumpdone]);
1761 * Build block handling NULL input or NULL comparator
1762 * result.
1764 LLVMPositionBuilderAtEnd(b, b_null);
1765 LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
1766 LLVMBuildBr(b, opblocks[op->d.rowcompare_step.jumpnull]);
1768 break;
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
1782 * otherwise wrong).
1784 v_cmpresult =
1785 LLVMBuildTrunc(b,
1786 l_load(b, TypeSizeT, v_resvaluep, ""),
1787 LLVMInt32TypeInContext(lc), "");
1789 switch (rctype)
1791 case ROWCOMPARE_LT:
1792 predicate = LLVMIntSLT;
1793 break;
1794 case ROWCOMPARE_LE:
1795 predicate = LLVMIntSLE;
1796 break;
1797 case ROWCOMPARE_GT:
1798 predicate = LLVMIntSGT;
1799 break;
1800 case ROWCOMPARE_GE:
1801 predicate = LLVMIntSGE;
1802 break;
1803 default:
1804 /* EQ and NE cases aren't allowed here */
1805 Assert(false);
1806 predicate = 0; /* prevent compiler warning */
1807 break;
1810 v_result = LLVMBuildICmp(b,
1811 predicate,
1812 v_cmpresult,
1813 l_int32_const(lc, 0),
1814 "");
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]);
1821 break;
1824 case EEOP_MINMAX:
1825 build_EvalXFunc(b, mod, "ExecEvalMinMax",
1826 v_state, op);
1827 LLVMBuildBr(b, opblocks[opno + 1]);
1828 break;
1830 case EEOP_FIELDSELECT:
1831 build_EvalXFunc(b, mod, "ExecEvalFieldSelect",
1832 v_state, op, v_econtext);
1833 LLVMBuildBr(b, opblocks[opno + 1]);
1834 break;
1836 case EEOP_FIELDSTORE_DEFORM:
1837 build_EvalXFunc(b, mod, "ExecEvalFieldStoreDeForm",
1838 v_state, op, v_econtext);
1839 LLVMBuildBr(b, opblocks[opno + 1]);
1840 break;
1842 case EEOP_FIELDSTORE_FORM:
1843 build_EvalXFunc(b, mod, "ExecEvalFieldStoreForm",
1844 v_state, op, v_econtext);
1845 LLVMBuildBr(b, opblocks[opno + 1]);
1846 break;
1848 case EEOP_DOMAIN_TESTVAL:
1850 LLVMBasicBlockRef b_avail,
1851 b_notavail;
1852 LLVMValueRef v_casevaluep,
1853 v_casevalue;
1854 LLVMValueRef v_casenullp,
1855 v_casenull;
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,
1864 l_ptr(TypeSizeT));
1865 v_casenullp = l_ptr_const(op->d.casetest.isnull,
1866 l_ptr(TypeStorageBool));
1868 v_casevaluenull =
1869 LLVMBuildICmp(b, LLVMIntEQ,
1870 LLVMBuildPtrToInt(b, v_casevaluep,
1871 TypeSizeT, ""),
1872 l_sizet_const(0), "");
1873 LLVMBuildCondBr(b,
1874 v_casevaluenull,
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);
1887 v_casevalue =
1888 l_load_struct_gep(b,
1889 StructExprContext,
1890 v_econtext,
1891 FIELDNO_EXPRCONTEXT_DOMAINDATUM,
1892 "");
1893 v_casenull =
1894 l_load_struct_gep(b,
1895 StructExprContext,
1896 v_econtext,
1897 FIELDNO_EXPRCONTEXT_DOMAINNULL,
1898 "");
1899 LLVMBuildStore(b, v_casevalue, v_resvaluep);
1900 LLVMBuildStore(b, v_casenull, v_resnullp);
1902 LLVMBuildBr(b, opblocks[opno + 1]);
1903 break;
1906 case EEOP_DOMAIN_NOTNULL:
1907 build_EvalXFunc(b, mod, "ExecEvalConstraintNotNull",
1908 v_state, op);
1909 LLVMBuildBr(b, opblocks[opno + 1]);
1910 break;
1912 case EEOP_DOMAIN_CHECK:
1913 build_EvalXFunc(b, mod, "ExecEvalConstraintCheck",
1914 v_state, op);
1915 LLVMBuildBr(b, opblocks[opno + 1]);
1916 break;
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]);
1927 break;
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;
1958 LLVMValueRef tmp;
1960 tmp = l_ptr_const(&op->d.hashdatum.iresult->value,
1961 l_ptr(TypeSizeT));
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),
1974 "");
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,
1980 "rotatedhash");
1984 * Block for the actual function call, if args are
1985 * non-NULL.
1987 b_ifnotnull = l_bb_before_v(opblocks[opno + 1],
1988 "b.%d.ifnotnull",
1989 opno);
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
2005 * NULL.
2007 if (opcode == EEOP_HASHDATUM_FIRST_STRICT ||
2008 opcode == EEOP_HASHDATUM_NEXT32_STRICT)
2010 b_ifnullblock = l_bb_before_v(b_ifnotnull,
2011 "b.%d.strictnull",
2012 opno);
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]);
2024 else
2026 b_ifnullblock = l_bb_before_v(b_ifnotnull,
2027 "b.%d.null",
2028 opno);
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
2041 * next op.
2043 LLVMBuildStore(b, v_prevhash, v_resvaluep);
2045 else
2047 Assert(opcode == EEOP_HASHDATUM_FIRST);
2050 * Store a zero Datum when the Datum to hash is
2051 * NULL
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);
2063 LLVMBuildCondBr(b,
2064 LLVMBuildICmp(b,
2065 LLVMIntEQ,
2066 v_argisnull,
2067 l_sbool_const(1),
2068 ""),
2069 b_ifnullblock,
2070 b_ifnotnull);
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;
2083 LLVMValueRef tmp;
2085 tmp = l_ptr_const(&op->d.hashdatum.iresult->value,
2086 l_ptr(TypeSizeT));
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),
2099 "");
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,
2105 "rotatedhash");
2108 /* call the hash function */
2109 v_retval = BuildV1Call(context, b, mod, fcinfo,
2110 &v_fcinfo_isnull);
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,
2119 "xorhash");
2121 LLVMBuildStore(b, v_retval, v_resvaluep);
2122 LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
2124 LLVMBuildBr(b, opblocks[opno + 1]);
2125 break;
2128 case EEOP_CONVERT_ROWTYPE:
2129 build_EvalXFunc(b, mod, "ExecEvalConvertRowtype",
2130 v_state, op, v_econtext);
2131 LLVMBuildBr(b, opblocks[opno + 1]);
2132 break;
2134 case EEOP_SCALARARRAYOP:
2135 build_EvalXFunc(b, mod, "ExecEvalScalarArrayOp",
2136 v_state, op);
2137 LLVMBuildBr(b, opblocks[opno + 1]);
2138 break;
2140 case EEOP_HASHED_SCALARARRAYOP:
2141 build_EvalXFunc(b, mod, "ExecEvalHashedScalarArrayOp",
2142 v_state, op, v_econtext);
2143 LLVMBuildBr(b, opblocks[opno + 1]);
2144 break;
2146 case EEOP_XMLEXPR:
2147 build_EvalXFunc(b, mod, "ExecEvalXmlExpr",
2148 v_state, op);
2149 LLVMBuildBr(b, opblocks[opno + 1]);
2150 break;
2152 case EEOP_JSON_CONSTRUCTOR:
2153 build_EvalXFunc(b, mod, "ExecEvalJsonConstructor",
2154 v_state, op, v_econtext);
2155 LLVMBuildBr(b, opblocks[opno + 1]);
2156 break;
2158 case EEOP_IS_JSON:
2159 build_EvalXFunc(b, mod, "ExecEvalJsonIsPredicate",
2160 v_state, op);
2161 LLVMBuildBr(b, opblocks[opno + 1]);
2162 break;
2164 case EEOP_JSONEXPR_PATH:
2166 JsonExprState *jsestate = op->d.jsonexpr.jsestate;
2167 LLVMValueRef v_ret;
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,
2191 b_empty,
2192 b_error,
2193 b_coercion;
2195 b_empty =
2196 l_bb_before_v(opblocks[opno + 1],
2197 "op.%d.jsonexpr_empty", opno);
2198 b_error =
2199 l_bb_before_v(opblocks[opno + 1],
2200 "op.%d.jsonexpr_error", opno);
2201 b_coercion =
2202 l_bb_before_v(opblocks[opno + 1],
2203 "op.%d.jsonexpr_coercion", opno);
2204 b_done =
2205 l_bb_before_v(opblocks[opno + 1],
2206 "op.%d.jsonexpr_done", opno);
2208 v_switch = LLVMBuildSwitch(b,
2209 v_ret,
2210 b_done,
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);
2218 /* ON EMPTY code */
2219 LLVMPositionBuilderAtEnd(b, b_empty);
2220 if (jsestate->jump_empty >= 0)
2221 LLVMBuildBr(b, opblocks[jsestate->jump_empty]);
2222 else
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);
2231 /* ON ERROR code */
2232 LLVMPositionBuilderAtEnd(b, b_error);
2233 if (jsestate->jump_error >= 0)
2234 LLVMBuildBr(b, opblocks[jsestate->jump_error]);
2235 else
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]);
2248 else
2249 LLVMBuildUnreachable(b);
2251 LLVMPositionBuilderAtEnd(b, b_done);
2254 LLVMBuildBr(b, opblocks[jsestate->jump_end]);
2255 break;
2258 case EEOP_JSONEXPR_COERCION:
2259 build_EvalXFunc(b, mod, "ExecEvalJsonCoercion",
2260 v_state, op, v_econtext);
2262 LLVMBuildBr(b, opblocks[opno + 1]);
2263 break;
2265 case EEOP_JSONEXPR_COERCION_FINISH:
2266 build_EvalXFunc(b, mod, "ExecEvalJsonCoercionFinish",
2267 v_state, op);
2269 LLVMBuildBr(b, opblocks[opno + 1]);
2270 break;
2272 case EEOP_AGGREF:
2274 LLVMValueRef v_aggno;
2275 LLVMValueRef value,
2276 isnull;
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]);
2289 break;
2292 case EEOP_GROUPING_FUNC:
2293 build_EvalXFunc(b, mod, "ExecEvalGroupingFunc",
2294 v_state, op);
2295 LLVMBuildBr(b, opblocks[opno + 1]);
2296 break;
2298 case EEOP_WINDOW_FUNC:
2300 WindowFuncExprState *wfunc = op->d.window_func.wfstate;
2301 LLVMValueRef v_wfuncnop;
2302 LLVMValueRef v_wfuncno;
2303 LLVMValueRef value,
2304 isnull;
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,
2317 "windowvalue");
2318 isnull = l_load_gep1(b, TypeStorageBool, v_aggnulls, v_wfuncno,
2319 "windownull");
2321 LLVMBuildStore(b, value, v_resvaluep);
2322 LLVMBuildStore(b, isnull, v_resnullp);
2324 LLVMBuildBr(b, opblocks[opno + 1]);
2325 break;
2328 case EEOP_MERGE_SUPPORT_FUNC:
2329 build_EvalXFunc(b, mod, "ExecEvalMergeSupportFunc",
2330 v_state, op, v_econtext);
2331 LLVMBuildBr(b, opblocks[opno + 1]);
2332 break;
2334 case EEOP_SUBPLAN:
2335 build_EvalXFunc(b, mod, "ExecEvalSubPlan",
2336 v_state, op, v_econtext);
2337 LLVMBuildBr(b, opblocks[opno + 1]);
2338 break;
2340 case EEOP_AGG_STRICT_DESERIALIZE:
2341 case EEOP_AGG_DESERIALIZE:
2343 AggState *aggstate;
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);
2364 LLVMBuildCondBr(b,
2365 LLVMBuildICmp(b,
2366 LLVMIntEQ,
2367 v_argnull0,
2368 l_sbool_const(1),
2369 ""),
2370 opblocks[op->d.agg_deserialize.jumpnull],
2371 b_deserialize);
2372 LLVMPositionBuilderAtEnd(b, b_deserialize);
2375 aggstate = castNode(AggState, state->parent);
2376 fcinfo = op->d.agg_deserialize.fcinfo_data;
2378 v_tmpcontext =
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,
2383 &v_fcinfo_isnull);
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]);
2390 break;
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;
2399 int jumpnull;
2401 LLVMValueRef v_argsp;
2402 LLVMValueRef v_nullsp;
2403 LLVMBasicBlockRef *b_checknulls;
2405 Assert(nargs > 0);
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",
2418 opno, argno);
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];
2434 else
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, "");
2439 else
2441 LLVMValueRef v_argn;
2443 v_argn = l_gep(b, StructNullableDatum, v_argsp, &v_argno, 1, "");
2444 v_argisnull =
2445 l_load_struct_gep(b, StructNullableDatum, v_argn,
2446 FIELDNO_NULLABLE_DATUM_ISNULL,
2447 "");
2450 LLVMBuildCondBr(b,
2451 LLVMBuildICmp(b,
2452 LLVMIntEQ,
2453 v_argisnull,
2454 l_sbool_const(1), ""),
2455 opblocks[jumpnull],
2456 b_argnotnull);
2459 break;
2462 case EEOP_AGG_PLAIN_PERGROUP_NULLCHECK:
2464 int jumpnull;
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,
2480 StructAggState,
2481 v_aggstatep,
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, "");
2490 LLVMBuildCondBr(b,
2491 LLVMBuildICmp(b, LLVMIntEQ,
2492 LLVMBuildPtrToInt(b, v_pergroup_allaggs, TypeSizeT, ""),
2493 l_sizet_const(0), ""),
2494 opblocks[jumpnull],
2495 opblocks[opno + 1]);
2496 break;
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:
2506 AggState *aggstate;
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;
2541 v_aggstatep =
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];
2550 v_allpergroupsp =
2551 l_load_struct_gep(b,
2552 StructAggState,
2553 v_aggstatep,
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);
2558 v_pergroupp =
2559 l_gep(b,
2560 StructAggStatePerGroupData,
2561 l_load_gep1(b, l_ptr(StructAggStatePerGroupData),
2562 v_allpergroupsp, v_setoff, ""),
2563 &v_transno, 1, "");
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;
2573 v_notransvalue =
2574 l_load_struct_gep(b,
2575 StructAggStatePerGroupData,
2576 v_pergroupp,
2577 FIELDNO_AGGSTATEPERGROUPDATA_NOTRANSVALUE,
2578 "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);
2585 LLVMBuildCondBr(b,
2586 LLVMBuildICmp(b, LLVMIntEQ, v_notransvalue,
2587 l_sbool_const(1), ""),
2588 b_init,
2589 b_no_init);
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;
2605 l_call(b,
2606 llvm_pg_var_func_type("ExecAggInitGroup"),
2607 llvm_pg_func(mod, "ExecAggInitGroup"),
2608 params, lengthof(params),
2609 "");
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);
2627 v_transnull =
2628 l_load_struct_gep(b,
2629 StructAggStatePerGroupData,
2630 v_pergroupp,
2631 FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL,
2632 "transnull");
2634 LLVMBuildCondBr(b,
2635 LLVMBuildICmp(b, LLVMIntEQ, v_transnull,
2636 l_sbool_const(1), ""),
2637 opblocks[opno + 1],
2638 b_strictpass);
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));
2649 v_current_setp =
2650 l_struct_gep(b,
2651 StructAggState,
2652 v_aggstatep,
2653 FIELDNO_AGGSTATE_CURRENT_SET,
2654 "aggstate.current_set");
2655 v_curaggcontext =
2656 l_struct_gep(b,
2657 StructAggState,
2658 v_aggstatep,
2659 FIELDNO_AGGSTATE_CURAGGCONTEXT,
2660 "aggstate.curaggcontext");
2661 v_current_pertransp =
2662 l_struct_gep(b,
2663 StructAggState,
2664 v_aggstatep,
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),
2671 v_current_setp);
2672 LLVMBuildStore(b, v_pertransp, v_current_pertransp);
2674 /* invoke transition function in per-tuple context */
2675 v_tmpcontext =
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] */
2681 v_transvaluep =
2682 l_struct_gep(b,
2683 StructAggStatePerGroupData,
2684 v_pergroupp,
2685 FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUE,
2686 "transvalue");
2687 v_transnullp =
2688 l_struct_gep(b,
2689 StructAggStatePerGroupData,
2690 v_pergroupp,
2691 FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL,
2692 "transnullp");
2693 LLVMBuildStore(b,
2694 l_load(b,
2695 TypeSizeT,
2696 v_transvaluep,
2697 "transvalue"),
2698 l_funcvaluep(b, v_fcinfo, 0));
2699 LLVMBuildStore(b,
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,
2705 &v_fcinfo_isnull);
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;
2722 LLVMValueRef v_fn;
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))
2740 LLVMBuildCondBr(b,
2741 LLVMBuildICmp(b, LLVMIntEQ,
2742 v_transvalue,
2743 v_retval, ""),
2744 b_nocall, b_call);
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,
2753 TypeParamBool, "");
2754 params[4] = v_transvalue;
2755 params[5] = LLVMBuildTrunc(b, v_transnull,
2756 TypeParamBool, "");
2758 v_fn = llvm_pg_func(mod, "ExecAggCopyTransValue");
2759 v_newval =
2760 l_call(b,
2761 LLVMGetFunctionType(v_fn),
2762 v_fn,
2763 params, lengthof(params),
2764 "");
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]);
2784 break;
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];
2795 LLVMValueRef v_ret;
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, "");
2803 LLVMBuildCondBr(b,
2804 LLVMBuildICmp(b, LLVMIntEQ, v_ret,
2805 l_sbool_const(1), ""),
2806 opblocks[opno + 1],
2807 opblocks[jumpdistinct]);
2808 break;
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];
2819 LLVMValueRef v_ret;
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, "");
2827 LLVMBuildCondBr(b,
2828 LLVMBuildICmp(b, LLVMIntEQ, v_ret,
2829 l_sbool_const(1), ""),
2830 opblocks[opno + 1],
2831 opblocks[jumpdistinct]);
2832 break;
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]);
2839 break;
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]);
2845 break;
2847 case EEOP_LAST:
2848 Assert(false);
2849 break;
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);
2878 return true;
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.
2889 static Datum
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,
2899 cstate->funcname);
2900 llvm_leave_fatal_on_oom();
2901 Assert(func);
2903 /* remove indirection via this function for future calls */
2904 state->evalfunc = func;
2906 return func(state, econtext, isNull);
2909 static LLVMValueRef
2910 BuildV1Call(LLVMJitContext *context, LLVMBuilderRef b,
2911 LLVMModuleRef mod, FunctionCallInfo fcinfo,
2912 LLVMValueRef *v_fcinfo_isnull)
2914 LLVMContextRef lc;
2915 LLVMValueRef v_fn;
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,
2927 v_fcinfo,
2928 FIELDNO_FUNCTIONCALLINFODATA_ISNULL,
2929 "v_fcinfo_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), "");
2954 return v_retval;
2958 * Implement an expression step by calling the function funcname.
2960 static LLVMValueRef
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;
2967 int argno = 0;
2968 LLVMValueRef v_ret;
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, "");
2985 pfree(params);
2987 return v_ret;
2990 static LLVMValueRef
2991 create_LifetimeEnd(LLVMModuleRef mod)
2993 LLVMTypeRef sig;
2994 LLVMValueRef fn;
2995 LLVMTypeRef param_types[2];
2996 LLVMContextRef lc;
2998 /* variadic pointer argument */
2999 const char *nm = "llvm.lifetime.end.p0";
3001 fn = LLVMGetNamedFunction(mod, nm);
3002 if (fn)
3003 return fn;
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));
3017 return fn;