Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * llvmjit_expr.c
4 : * JIT compile expressions.
5 : *
6 : * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : *
10 : * IDENTIFICATION
11 : * src/backend/jit/llvm/llvmjit_expr.c
12 : *
13 : *-------------------------------------------------------------------------
14 : */
15 :
16 : #include "postgres.h"
17 :
18 : #include <llvm-c/Core.h>
19 : #include <llvm-c/Target.h>
20 :
21 : #include "access/htup_details.h"
22 : #include "access/nbtree.h"
23 : #include "catalog/objectaccess.h"
24 : #include "catalog/pg_type.h"
25 : #include "executor/execExpr.h"
26 : #include "executor/execdebug.h"
27 : #include "executor/nodeAgg.h"
28 : #include "executor/nodeSubplan.h"
29 : #include "funcapi.h"
30 : #include "jit/llvmjit.h"
31 : #include "jit/llvmjit_emit.h"
32 : #include "miscadmin.h"
33 : #include "nodes/makefuncs.h"
34 : #include "nodes/nodeFuncs.h"
35 : #include "parser/parse_coerce.h"
36 : #include "parser/parsetree.h"
37 : #include "pgstat.h"
38 : #include "utils/acl.h"
39 : #include "utils/builtins.h"
40 : #include "utils/date.h"
41 : #include "utils/fmgrtab.h"
42 : #include "utils/lsyscache.h"
43 : #include "utils/memutils.h"
44 : #include "utils/timestamp.h"
45 : #include "utils/typcache.h"
46 : #include "utils/xml.h"
47 :
48 : typedef struct CompiledExprState
49 : {
50 : LLVMJitContext *context;
51 : const char *funcname;
52 : } CompiledExprState;
53 :
54 :
55 : static Datum ExecRunCompiledExpr(ExprState *state, ExprContext *econtext, bool *isNull);
56 :
57 : static LLVMValueRef BuildV1Call(LLVMJitContext *context, LLVMBuilderRef b,
58 : LLVMModuleRef mod, FunctionCallInfo fcinfo,
59 : LLVMValueRef *v_fcinfo_isnull);
60 : static LLVMValueRef build_EvalXFuncInt(LLVMBuilderRef b, LLVMModuleRef mod,
61 : const char *funcname,
62 : LLVMValueRef v_state,
63 : ExprEvalStep *op,
64 : int natts, LLVMValueRef *v_args);
65 : static LLVMValueRef create_LifetimeEnd(LLVMModuleRef mod);
66 :
67 : /* macro making it easier to call ExecEval* functions */
68 : #define build_EvalXFunc(b, mod, funcname, v_state, op, ...) \
69 : build_EvalXFuncInt(b, mod, funcname, v_state, op, \
70 : lengthof(((LLVMValueRef[]){__VA_ARGS__})), \
71 : ((LLVMValueRef[]){__VA_ARGS__}))
72 :
73 :
74 : /*
75 : * JIT compile expression.
76 : */
77 : bool
78 9078 : llvm_compile_expr(ExprState *state)
79 : {
80 9078 : PlanState *parent = state->parent;
81 : char *funcname;
82 :
83 9078 : LLVMJitContext *context = NULL;
84 :
85 : LLVMBuilderRef b;
86 : LLVMModuleRef mod;
87 : LLVMContextRef lc;
88 : LLVMValueRef eval_fn;
89 : LLVMBasicBlockRef entry;
90 : LLVMBasicBlockRef *opblocks;
91 :
92 : /* state itself */
93 : LLVMValueRef v_state;
94 : LLVMValueRef v_econtext;
95 : LLVMValueRef v_parent;
96 :
97 : /* returnvalue */
98 : LLVMValueRef v_isnullp;
99 :
100 : /* tmp vars in state */
101 : LLVMValueRef v_tmpvaluep;
102 : LLVMValueRef v_tmpisnullp;
103 :
104 : /* slots */
105 : LLVMValueRef v_innerslot;
106 : LLVMValueRef v_outerslot;
107 : LLVMValueRef v_scanslot;
108 : LLVMValueRef v_oldslot;
109 : LLVMValueRef v_newslot;
110 : LLVMValueRef v_resultslot;
111 :
112 : /* nulls/values of slots */
113 : LLVMValueRef v_innervalues;
114 : LLVMValueRef v_innernulls;
115 : LLVMValueRef v_outervalues;
116 : LLVMValueRef v_outernulls;
117 : LLVMValueRef v_scanvalues;
118 : LLVMValueRef v_scannulls;
119 : LLVMValueRef v_oldvalues;
120 : LLVMValueRef v_oldnulls;
121 : LLVMValueRef v_newvalues;
122 : LLVMValueRef v_newnulls;
123 : LLVMValueRef v_resultvalues;
124 : LLVMValueRef v_resultnulls;
125 :
126 : /* stuff in econtext */
127 : LLVMValueRef v_aggvalues;
128 : LLVMValueRef v_aggnulls;
129 :
130 : instr_time starttime;
131 : instr_time deform_starttime;
132 : instr_time endtime;
133 : instr_time deform_endtime;
134 :
135 9078 : llvm_enter_fatal_on_oom();
136 :
137 : /*
138 : * Right now we don't support compiling expressions without a parent, as
139 : * we need access to the EState.
140 : */
141 : Assert(parent);
142 :
143 : /* get or create JIT context */
144 9078 : if (parent->state->es_jit)
145 7856 : context = (LLVMJitContext *) parent->state->es_jit;
146 : else
147 : {
148 1222 : context = llvm_create_context(parent->state->es_jit_flags);
149 1222 : parent->state->es_jit = &context->base;
150 : }
151 :
152 9078 : INSTR_TIME_SET_CURRENT(starttime);
153 :
154 9078 : mod = llvm_mutable_module(context);
155 9078 : lc = LLVMGetModuleContext(mod);
156 :
157 9078 : b = LLVMCreateBuilderInContext(lc);
158 :
159 9078 : funcname = llvm_expand_funcname(context, "evalexpr");
160 :
161 : /* create function */
162 9078 : eval_fn = LLVMAddFunction(mod, funcname,
163 : llvm_pg_var_func_type("ExecInterpExprStillValid"));
164 9078 : LLVMSetLinkage(eval_fn, LLVMExternalLinkage);
165 9078 : LLVMSetVisibility(eval_fn, LLVMDefaultVisibility);
166 9078 : llvm_copy_attributes(AttributeTemplate, eval_fn);
167 :
168 9078 : entry = LLVMAppendBasicBlockInContext(lc, eval_fn, "entry");
169 :
170 : /* build state */
171 9078 : v_state = LLVMGetParam(eval_fn, 0);
172 9078 : v_econtext = LLVMGetParam(eval_fn, 1);
173 9078 : v_isnullp = LLVMGetParam(eval_fn, 2);
174 :
175 9078 : LLVMPositionBuilderAtEnd(b, entry);
176 :
177 9078 : v_tmpvaluep = l_struct_gep(b,
178 : StructExprState,
179 : v_state,
180 : FIELDNO_EXPRSTATE_RESVALUE,
181 : "v.state.resvalue");
182 9078 : v_tmpisnullp = l_struct_gep(b,
183 : StructExprState,
184 : v_state,
185 : FIELDNO_EXPRSTATE_RESNULL,
186 : "v.state.resnull");
187 9078 : v_parent = l_load_struct_gep(b,
188 : StructExprState,
189 : v_state,
190 : FIELDNO_EXPRSTATE_PARENT,
191 : "v.state.parent");
192 :
193 : /* build global slots */
194 9078 : v_scanslot = l_load_struct_gep(b,
195 : StructExprContext,
196 : v_econtext,
197 : FIELDNO_EXPRCONTEXT_SCANTUPLE,
198 : "v_scanslot");
199 9078 : v_innerslot = l_load_struct_gep(b,
200 : StructExprContext,
201 : v_econtext,
202 : FIELDNO_EXPRCONTEXT_INNERTUPLE,
203 : "v_innerslot");
204 9078 : v_outerslot = l_load_struct_gep(b,
205 : StructExprContext,
206 : v_econtext,
207 : FIELDNO_EXPRCONTEXT_OUTERTUPLE,
208 : "v_outerslot");
209 9078 : v_oldslot = l_load_struct_gep(b,
210 : StructExprContext,
211 : v_econtext,
212 : FIELDNO_EXPRCONTEXT_OLDTUPLE,
213 : "v_oldslot");
214 9078 : v_newslot = l_load_struct_gep(b,
215 : StructExprContext,
216 : v_econtext,
217 : FIELDNO_EXPRCONTEXT_NEWTUPLE,
218 : "v_newslot");
219 9078 : v_resultslot = l_load_struct_gep(b,
220 : StructExprState,
221 : v_state,
222 : FIELDNO_EXPRSTATE_RESULTSLOT,
223 : "v_resultslot");
224 :
225 : /* build global values/isnull pointers */
226 9078 : v_scanvalues = l_load_struct_gep(b,
227 : StructTupleTableSlot,
228 : v_scanslot,
229 : FIELDNO_TUPLETABLESLOT_VALUES,
230 : "v_scanvalues");
231 9078 : v_scannulls = l_load_struct_gep(b,
232 : StructTupleTableSlot,
233 : v_scanslot,
234 : FIELDNO_TUPLETABLESLOT_ISNULL,
235 : "v_scannulls");
236 9078 : v_innervalues = l_load_struct_gep(b,
237 : StructTupleTableSlot,
238 : v_innerslot,
239 : FIELDNO_TUPLETABLESLOT_VALUES,
240 : "v_innervalues");
241 9078 : v_innernulls = l_load_struct_gep(b,
242 : StructTupleTableSlot,
243 : v_innerslot,
244 : FIELDNO_TUPLETABLESLOT_ISNULL,
245 : "v_innernulls");
246 9078 : v_outervalues = l_load_struct_gep(b,
247 : StructTupleTableSlot,
248 : v_outerslot,
249 : FIELDNO_TUPLETABLESLOT_VALUES,
250 : "v_outervalues");
251 9078 : v_outernulls = l_load_struct_gep(b,
252 : StructTupleTableSlot,
253 : v_outerslot,
254 : FIELDNO_TUPLETABLESLOT_ISNULL,
255 : "v_outernulls");
256 9078 : v_oldvalues = l_load_struct_gep(b,
257 : StructTupleTableSlot,
258 : v_oldslot,
259 : FIELDNO_TUPLETABLESLOT_VALUES,
260 : "v_oldvalues");
261 9078 : v_oldnulls = l_load_struct_gep(b,
262 : StructTupleTableSlot,
263 : v_oldslot,
264 : FIELDNO_TUPLETABLESLOT_ISNULL,
265 : "v_oldnulls");
266 9078 : v_newvalues = l_load_struct_gep(b,
267 : StructTupleTableSlot,
268 : v_newslot,
269 : FIELDNO_TUPLETABLESLOT_VALUES,
270 : "v_newvalues");
271 9078 : v_newnulls = l_load_struct_gep(b,
272 : StructTupleTableSlot,
273 : v_newslot,
274 : FIELDNO_TUPLETABLESLOT_ISNULL,
275 : "v_newnulls");
276 9078 : v_resultvalues = l_load_struct_gep(b,
277 : StructTupleTableSlot,
278 : v_resultslot,
279 : FIELDNO_TUPLETABLESLOT_VALUES,
280 : "v_resultvalues");
281 9078 : v_resultnulls = l_load_struct_gep(b,
282 : StructTupleTableSlot,
283 : v_resultslot,
284 : FIELDNO_TUPLETABLESLOT_ISNULL,
285 : "v_resultnulls");
286 :
287 : /* aggvalues/aggnulls */
288 9078 : v_aggvalues = l_load_struct_gep(b,
289 : StructExprContext,
290 : v_econtext,
291 : FIELDNO_EXPRCONTEXT_AGGVALUES,
292 : "v.econtext.aggvalues");
293 9078 : v_aggnulls = l_load_struct_gep(b,
294 : StructExprContext,
295 : v_econtext,
296 : FIELDNO_EXPRCONTEXT_AGGNULLS,
297 : "v.econtext.aggnulls");
298 :
299 : /* allocate blocks for each op upfront, so we can do jumps easily */
300 9078 : opblocks = palloc(sizeof(LLVMBasicBlockRef) * state->steps_len);
301 56866 : for (int opno = 0; opno < state->steps_len; opno++)
302 47788 : opblocks[opno] = l_bb_append_v(eval_fn, "b.op.%d.start", opno);
303 :
304 : /* jump from entry to first block */
305 9078 : LLVMBuildBr(b, opblocks[0]);
306 :
307 56866 : for (int opno = 0; opno < state->steps_len; opno++)
308 : {
309 : ExprEvalStep *op;
310 : ExprEvalOp opcode;
311 : LLVMValueRef v_resvaluep;
312 : LLVMValueRef v_resnullp;
313 :
314 47788 : LLVMPositionBuilderAtEnd(b, opblocks[opno]);
315 :
316 47788 : op = &state->steps[opno];
317 47788 : opcode = ExecEvalStepOp(state, op);
318 :
319 47788 : v_resvaluep = l_ptr_const(op->resvalue, l_ptr(TypeSizeT));
320 47788 : v_resnullp = l_ptr_const(op->resnull, l_ptr(TypeStorageBool));
321 :
322 47788 : switch (opcode)
323 : {
324 4856 : case EEOP_DONE_RETURN:
325 : {
326 : LLVMValueRef v_tmpisnull;
327 : LLVMValueRef v_tmpvalue;
328 :
329 4856 : v_tmpvalue = l_load(b, TypeSizeT, v_tmpvaluep, "");
330 4856 : v_tmpisnull = l_load(b, TypeStorageBool, v_tmpisnullp, "");
331 :
332 4856 : LLVMBuildStore(b, v_tmpisnull, v_isnullp);
333 :
334 4856 : LLVMBuildRet(b, v_tmpvalue);
335 4856 : break;
336 : }
337 :
338 4222 : case EEOP_DONE_NO_RETURN:
339 4222 : LLVMBuildRet(b, l_sizet_const(0));
340 4222 : break;
341 :
342 6606 : case EEOP_INNER_FETCHSOME:
343 : case EEOP_OUTER_FETCHSOME:
344 : case EEOP_SCAN_FETCHSOME:
345 : case EEOP_OLD_FETCHSOME:
346 : case EEOP_NEW_FETCHSOME:
347 : {
348 6606 : TupleDesc desc = NULL;
349 : LLVMValueRef v_slot;
350 : LLVMBasicBlockRef b_fetch;
351 : LLVMValueRef v_nvalid;
352 6606 : LLVMValueRef l_jit_deform = NULL;
353 6606 : const TupleTableSlotOps *tts_ops = NULL;
354 :
355 6606 : b_fetch = l_bb_before_v(opblocks[opno + 1],
356 : "op.%d.fetch", opno);
357 :
358 6606 : if (op->d.fetch.known_desc)
359 5664 : desc = op->d.fetch.known_desc;
360 :
361 6606 : if (op->d.fetch.fixed)
362 5664 : tts_ops = op->d.fetch.kind;
363 :
364 : /* step should not have been generated */
365 : Assert(tts_ops != &TTSOpsVirtual);
366 :
367 6606 : if (opcode == EEOP_INNER_FETCHSOME)
368 2128 : v_slot = v_innerslot;
369 4478 : else if (opcode == EEOP_OUTER_FETCHSOME)
370 2228 : v_slot = v_outerslot;
371 2250 : else if (opcode == EEOP_SCAN_FETCHSOME)
372 2238 : v_slot = v_scanslot;
373 12 : else if (opcode == EEOP_OLD_FETCHSOME)
374 6 : v_slot = v_oldslot;
375 : else
376 6 : v_slot = v_newslot;
377 :
378 : /*
379 : * Check if all required attributes are available, or
380 : * whether deforming is required.
381 : */
382 : v_nvalid =
383 6606 : l_load_struct_gep(b,
384 : StructTupleTableSlot,
385 : v_slot,
386 : FIELDNO_TUPLETABLESLOT_NVALID,
387 : "");
388 6606 : LLVMBuildCondBr(b,
389 : LLVMBuildICmp(b, LLVMIntUGE, v_nvalid,
390 6606 : l_int16_const(lc, op->d.fetch.last_var),
391 : ""),
392 6606 : opblocks[opno + 1], b_fetch);
393 :
394 6606 : LLVMPositionBuilderAtEnd(b, b_fetch);
395 :
396 : /*
397 : * If the tupledesc of the to-be-deformed tuple is known,
398 : * and JITing of deforming is enabled, build deform
399 : * function specific to tupledesc and the exact number of
400 : * to-be-extracted attributes.
401 : */
402 6606 : if (tts_ops && desc && (context->base.flags & PGJIT_DEFORM))
403 : {
404 5664 : INSTR_TIME_SET_CURRENT(deform_starttime);
405 : l_jit_deform =
406 5664 : slot_compile_deform(context, desc,
407 : tts_ops,
408 : op->d.fetch.last_var);
409 5664 : INSTR_TIME_SET_CURRENT(deform_endtime);
410 5664 : INSTR_TIME_ACCUM_DIFF(context->base.instr.deform_counter,
411 : deform_endtime, deform_starttime);
412 : }
413 :
414 6606 : if (l_jit_deform)
415 : {
416 : LLVMValueRef params[1];
417 :
418 5664 : params[0] = v_slot;
419 :
420 5664 : l_call(b,
421 : LLVMGetFunctionType(l_jit_deform),
422 : l_jit_deform,
423 : params, lengthof(params), "");
424 : }
425 : else
426 : {
427 : LLVMValueRef params[2];
428 :
429 942 : params[0] = v_slot;
430 942 : params[1] = l_int32_const(lc, op->d.fetch.last_var);
431 :
432 942 : l_call(b,
433 : llvm_pg_var_func_type("slot_getsomeattrs_int"),
434 : llvm_pg_func(mod, "slot_getsomeattrs_int"),
435 : params, lengthof(params), "");
436 : }
437 :
438 6606 : LLVMBuildBr(b, opblocks[opno + 1]);
439 6606 : break;
440 : }
441 :
442 8124 : case EEOP_INNER_VAR:
443 : case EEOP_OUTER_VAR:
444 : case EEOP_SCAN_VAR:
445 : case EEOP_OLD_VAR:
446 : case EEOP_NEW_VAR:
447 : {
448 : LLVMValueRef value,
449 : isnull;
450 : LLVMValueRef v_attnum;
451 : LLVMValueRef v_values;
452 : LLVMValueRef v_nulls;
453 :
454 8124 : if (opcode == EEOP_INNER_VAR)
455 : {
456 2620 : v_values = v_innervalues;
457 2620 : v_nulls = v_innernulls;
458 : }
459 5504 : else if (opcode == EEOP_OUTER_VAR)
460 : {
461 3936 : v_values = v_outervalues;
462 3936 : v_nulls = v_outernulls;
463 : }
464 1568 : else if (opcode == EEOP_SCAN_VAR)
465 : {
466 1520 : v_values = v_scanvalues;
467 1520 : v_nulls = v_scannulls;
468 : }
469 48 : else if (opcode == EEOP_OLD_VAR)
470 : {
471 24 : v_values = v_oldvalues;
472 24 : v_nulls = v_oldnulls;
473 : }
474 : else
475 : {
476 24 : v_values = v_newvalues;
477 24 : v_nulls = v_newnulls;
478 : }
479 :
480 8124 : v_attnum = l_int32_const(lc, op->d.var.attnum);
481 8124 : value = l_load_gep1(b, TypeSizeT, v_values, v_attnum, "");
482 8124 : isnull = l_load_gep1(b, TypeStorageBool, v_nulls, v_attnum, "");
483 8124 : LLVMBuildStore(b, value, v_resvaluep);
484 8124 : LLVMBuildStore(b, isnull, v_resnullp);
485 :
486 8124 : LLVMBuildBr(b, opblocks[opno + 1]);
487 8124 : break;
488 : }
489 :
490 444 : case EEOP_INNER_SYSVAR:
491 : case EEOP_OUTER_SYSVAR:
492 : case EEOP_SCAN_SYSVAR:
493 : case EEOP_OLD_SYSVAR:
494 : case EEOP_NEW_SYSVAR:
495 : {
496 : LLVMValueRef v_slot;
497 :
498 444 : if (opcode == EEOP_INNER_SYSVAR)
499 0 : v_slot = v_innerslot;
500 444 : else if (opcode == EEOP_OUTER_SYSVAR)
501 0 : v_slot = v_outerslot;
502 444 : else if (opcode == EEOP_SCAN_SYSVAR)
503 444 : v_slot = v_scanslot;
504 0 : else if (opcode == EEOP_OLD_SYSVAR)
505 0 : v_slot = v_oldslot;
506 : else
507 0 : v_slot = v_newslot;
508 :
509 444 : build_EvalXFunc(b, mod, "ExecEvalSysVar",
510 : v_state, op, v_econtext, v_slot);
511 :
512 444 : LLVMBuildBr(b, opblocks[opno + 1]);
513 444 : break;
514 : }
515 :
516 120 : case EEOP_WHOLEROW:
517 120 : build_EvalXFunc(b, mod, "ExecEvalWholeRowVar",
518 : v_state, op, v_econtext);
519 120 : LLVMBuildBr(b, opblocks[opno + 1]);
520 120 : break;
521 :
522 6336 : case EEOP_ASSIGN_INNER_VAR:
523 : case EEOP_ASSIGN_OUTER_VAR:
524 : case EEOP_ASSIGN_SCAN_VAR:
525 : case EEOP_ASSIGN_OLD_VAR:
526 : case EEOP_ASSIGN_NEW_VAR:
527 : {
528 : LLVMValueRef v_value;
529 : LLVMValueRef v_isnull;
530 : LLVMValueRef v_rvaluep;
531 : LLVMValueRef v_risnullp;
532 : LLVMValueRef v_attnum;
533 : LLVMValueRef v_resultnum;
534 : LLVMValueRef v_values;
535 : LLVMValueRef v_nulls;
536 :
537 6336 : if (opcode == EEOP_ASSIGN_INNER_VAR)
538 : {
539 1404 : v_values = v_innervalues;
540 1404 : v_nulls = v_innernulls;
541 : }
542 4932 : else if (opcode == EEOP_ASSIGN_OUTER_VAR)
543 : {
544 3022 : v_values = v_outervalues;
545 3022 : v_nulls = v_outernulls;
546 : }
547 1910 : else if (opcode == EEOP_ASSIGN_SCAN_VAR)
548 : {
549 1886 : v_values = v_scanvalues;
550 1886 : v_nulls = v_scannulls;
551 : }
552 24 : else if (opcode == EEOP_ASSIGN_OLD_VAR)
553 : {
554 12 : v_values = v_oldvalues;
555 12 : v_nulls = v_oldnulls;
556 : }
557 : else
558 : {
559 12 : v_values = v_newvalues;
560 12 : v_nulls = v_newnulls;
561 : }
562 :
563 : /* load data */
564 6336 : v_attnum = l_int32_const(lc, op->d.assign_var.attnum);
565 6336 : v_value = l_load_gep1(b, TypeSizeT, v_values, v_attnum, "");
566 6336 : v_isnull = l_load_gep1(b, TypeStorageBool, v_nulls, v_attnum, "");
567 :
568 : /* compute addresses of targets */
569 6336 : v_resultnum = l_int32_const(lc, op->d.assign_var.resultnum);
570 6336 : v_rvaluep = l_gep(b,
571 : TypeSizeT,
572 : v_resultvalues,
573 : &v_resultnum, 1, "");
574 6336 : v_risnullp = l_gep(b,
575 : TypeStorageBool,
576 : v_resultnulls,
577 : &v_resultnum, 1, "");
578 :
579 : /* and store */
580 6336 : LLVMBuildStore(b, v_value, v_rvaluep);
581 6336 : LLVMBuildStore(b, v_isnull, v_risnullp);
582 :
583 6336 : LLVMBuildBr(b, opblocks[opno + 1]);
584 6336 : break;
585 : }
586 :
587 2442 : case EEOP_ASSIGN_TMP:
588 : case EEOP_ASSIGN_TMP_MAKE_RO:
589 : {
590 : LLVMValueRef v_value,
591 : v_isnull;
592 : LLVMValueRef v_rvaluep,
593 : v_risnullp;
594 : LLVMValueRef v_resultnum;
595 2442 : size_t resultnum = op->d.assign_tmp.resultnum;
596 :
597 : /* load data */
598 2442 : v_value = l_load(b, TypeSizeT, v_tmpvaluep, "");
599 2442 : v_isnull = l_load(b, TypeStorageBool, v_tmpisnullp, "");
600 :
601 : /* compute addresses of targets */
602 2442 : v_resultnum = l_int32_const(lc, resultnum);
603 : v_rvaluep =
604 2442 : l_gep(b, TypeSizeT, v_resultvalues, &v_resultnum, 1, "");
605 : v_risnullp =
606 2442 : l_gep(b, TypeStorageBool, v_resultnulls, &v_resultnum, 1, "");
607 :
608 : /* store nullness */
609 2442 : LLVMBuildStore(b, v_isnull, v_risnullp);
610 :
611 : /* make value readonly if necessary */
612 2442 : if (opcode == EEOP_ASSIGN_TMP_MAKE_RO)
613 : {
614 : LLVMBasicBlockRef b_notnull;
615 : LLVMValueRef v_params[1];
616 :
617 918 : b_notnull = l_bb_before_v(opblocks[opno + 1],
618 : "op.%d.assign_tmp.notnull", opno);
619 :
620 : /* check if value is NULL */
621 918 : LLVMBuildCondBr(b,
622 : LLVMBuildICmp(b, LLVMIntEQ, v_isnull,
623 : l_sbool_const(0), ""),
624 918 : b_notnull, opblocks[opno + 1]);
625 :
626 : /* if value is not null, convert to RO datum */
627 918 : LLVMPositionBuilderAtEnd(b, b_notnull);
628 918 : v_params[0] = v_value;
629 : v_value =
630 918 : l_call(b,
631 : llvm_pg_var_func_type("MakeExpandedObjectReadOnlyInternal"),
632 : llvm_pg_func(mod, "MakeExpandedObjectReadOnlyInternal"),
633 : v_params, lengthof(v_params), "");
634 :
635 : /*
636 : * Falling out of the if () with builder in b_notnull,
637 : * which is fine - the null is already stored above.
638 : */
639 : }
640 :
641 : /* and finally store result */
642 2442 : LLVMBuildStore(b, v_value, v_rvaluep);
643 :
644 2442 : LLVMBuildBr(b, opblocks[opno + 1]);
645 2442 : break;
646 : }
647 :
648 900 : case EEOP_CONST:
649 : {
650 : LLVMValueRef v_constvalue,
651 : v_constnull;
652 :
653 900 : v_constvalue = l_sizet_const(op->d.constval.value);
654 900 : v_constnull = l_sbool_const(op->d.constval.isnull);
655 :
656 900 : LLVMBuildStore(b, v_constvalue, v_resvaluep);
657 900 : LLVMBuildStore(b, v_constnull, v_resnullp);
658 :
659 900 : LLVMBuildBr(b, opblocks[opno + 1]);
660 900 : break;
661 : }
662 :
663 2712 : case EEOP_FUNCEXPR:
664 : case EEOP_FUNCEXPR_STRICT:
665 : case EEOP_FUNCEXPR_STRICT_1:
666 : case EEOP_FUNCEXPR_STRICT_2:
667 : {
668 2712 : FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
669 : LLVMValueRef v_fcinfo_isnull;
670 : LLVMValueRef v_retval;
671 :
672 2712 : if (opcode == EEOP_FUNCEXPR_STRICT ||
673 2370 : opcode == EEOP_FUNCEXPR_STRICT_1 ||
674 : opcode == EEOP_FUNCEXPR_STRICT_2)
675 : {
676 : LLVMBasicBlockRef b_nonull;
677 : LLVMBasicBlockRef *b_checkargnulls;
678 : LLVMValueRef v_fcinfo;
679 :
680 : /*
681 : * Block for the actual function call, if args are
682 : * non-NULL.
683 : */
684 2620 : b_nonull = l_bb_before_v(opblocks[opno + 1],
685 : "b.%d.no-null-args", opno);
686 :
687 : /* should make sure they're optimized beforehand */
688 2620 : if (op->d.func.nargs == 0)
689 0 : elog(ERROR, "argumentless strict functions are pointless");
690 :
691 : v_fcinfo =
692 2620 : l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
693 :
694 : /*
695 : * set resnull to true, if the function is actually
696 : * called, it'll be reset
697 : */
698 2620 : LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
699 :
700 : /* create blocks for checking args, one for each */
701 : b_checkargnulls =
702 2620 : palloc(sizeof(LLVMBasicBlockRef *) * op->d.func.nargs);
703 7518 : for (int argno = 0; argno < op->d.func.nargs; argno++)
704 4898 : b_checkargnulls[argno] =
705 4898 : l_bb_before_v(b_nonull, "b.%d.isnull.%d", opno,
706 : argno);
707 :
708 : /* jump to check of first argument */
709 2620 : LLVMBuildBr(b, b_checkargnulls[0]);
710 :
711 : /* check each arg for NULLness */
712 7518 : for (int argno = 0; argno < op->d.func.nargs; argno++)
713 : {
714 : LLVMValueRef v_argisnull;
715 : LLVMBasicBlockRef b_argnotnull;
716 :
717 4898 : LLVMPositionBuilderAtEnd(b, b_checkargnulls[argno]);
718 :
719 : /*
720 : * Compute block to jump to if argument is not
721 : * null.
722 : */
723 4898 : if (argno + 1 == op->d.func.nargs)
724 2620 : b_argnotnull = b_nonull;
725 : else
726 2278 : b_argnotnull = b_checkargnulls[argno + 1];
727 :
728 : /* and finally load & check NULLness of arg */
729 4898 : v_argisnull = l_funcnull(b, v_fcinfo, argno);
730 4898 : LLVMBuildCondBr(b,
731 : LLVMBuildICmp(b, LLVMIntEQ,
732 : v_argisnull,
733 : l_sbool_const(1),
734 : ""),
735 4898 : opblocks[opno + 1],
736 : b_argnotnull);
737 : }
738 :
739 2620 : LLVMPositionBuilderAtEnd(b, b_nonull);
740 : }
741 :
742 2712 : v_retval = BuildV1Call(context, b, mod, fcinfo,
743 : &v_fcinfo_isnull);
744 2712 : LLVMBuildStore(b, v_retval, v_resvaluep);
745 2712 : LLVMBuildStore(b, v_fcinfo_isnull, v_resnullp);
746 :
747 2712 : LLVMBuildBr(b, opblocks[opno + 1]);
748 2712 : break;
749 : }
750 :
751 0 : case EEOP_FUNCEXPR_FUSAGE:
752 0 : build_EvalXFunc(b, mod, "ExecEvalFuncExprFusage",
753 : v_state, op, v_econtext);
754 0 : LLVMBuildBr(b, opblocks[opno + 1]);
755 0 : break;
756 :
757 :
758 0 : case EEOP_FUNCEXPR_STRICT_FUSAGE:
759 0 : build_EvalXFunc(b, mod, "ExecEvalFuncExprStrictFusage",
760 : v_state, op, v_econtext);
761 0 : LLVMBuildBr(b, opblocks[opno + 1]);
762 0 : break;
763 :
764 : /*
765 : * Treat them the same for now, optimizer can remove
766 : * redundancy. Could be worthwhile to optimize during emission
767 : * though.
768 : */
769 40 : case EEOP_BOOL_AND_STEP_FIRST:
770 : case EEOP_BOOL_AND_STEP:
771 : case EEOP_BOOL_AND_STEP_LAST:
772 : {
773 : LLVMValueRef v_boolvalue;
774 : LLVMValueRef v_boolnull;
775 : LLVMValueRef v_boolanynullp,
776 : v_boolanynull;
777 : LLVMBasicBlockRef b_boolisnull;
778 : LLVMBasicBlockRef b_boolcheckfalse;
779 : LLVMBasicBlockRef b_boolisfalse;
780 : LLVMBasicBlockRef b_boolcont;
781 : LLVMBasicBlockRef b_boolisanynull;
782 :
783 40 : b_boolisnull = l_bb_before_v(opblocks[opno + 1],
784 : "b.%d.boolisnull", opno);
785 40 : b_boolcheckfalse = l_bb_before_v(opblocks[opno + 1],
786 : "b.%d.boolcheckfalse", opno);
787 40 : b_boolisfalse = l_bb_before_v(opblocks[opno + 1],
788 : "b.%d.boolisfalse", opno);
789 40 : b_boolisanynull = l_bb_before_v(opblocks[opno + 1],
790 : "b.%d.boolisanynull", opno);
791 40 : b_boolcont = l_bb_before_v(opblocks[opno + 1],
792 : "b.%d.boolcont", opno);
793 :
794 40 : v_boolanynullp = l_ptr_const(op->d.boolexpr.anynull,
795 : l_ptr(TypeStorageBool));
796 :
797 40 : if (opcode == EEOP_BOOL_AND_STEP_FIRST)
798 20 : LLVMBuildStore(b, l_sbool_const(0), v_boolanynullp);
799 :
800 40 : v_boolnull = l_load(b, TypeStorageBool, v_resnullp, "");
801 40 : v_boolvalue = l_load(b, TypeSizeT, v_resvaluep, "");
802 :
803 : /* check if current input is NULL */
804 40 : LLVMBuildCondBr(b,
805 : LLVMBuildICmp(b, LLVMIntEQ, v_boolnull,
806 : l_sbool_const(1), ""),
807 : b_boolisnull,
808 : b_boolcheckfalse);
809 :
810 : /* build block that sets anynull */
811 40 : LLVMPositionBuilderAtEnd(b, b_boolisnull);
812 : /* set boolanynull to true */
813 40 : LLVMBuildStore(b, l_sbool_const(1), v_boolanynullp);
814 : /* and jump to next block */
815 40 : LLVMBuildBr(b, b_boolcont);
816 :
817 : /* build block checking for false */
818 40 : LLVMPositionBuilderAtEnd(b, b_boolcheckfalse);
819 40 : LLVMBuildCondBr(b,
820 : LLVMBuildICmp(b, LLVMIntEQ, v_boolvalue,
821 : l_sizet_const(0), ""),
822 : b_boolisfalse,
823 : b_boolcont);
824 :
825 : /*
826 : * Build block handling FALSE. Value is false, so short
827 : * circuit.
828 : */
829 40 : LLVMPositionBuilderAtEnd(b, b_boolisfalse);
830 : /* result is already set to FALSE, need not change it */
831 : /* and jump to the end of the AND expression */
832 40 : LLVMBuildBr(b, opblocks[op->d.boolexpr.jumpdone]);
833 :
834 : /* Build block that continues if bool is TRUE. */
835 40 : LLVMPositionBuilderAtEnd(b, b_boolcont);
836 :
837 40 : v_boolanynull = l_load(b, TypeStorageBool, v_boolanynullp, "");
838 :
839 : /* set value to NULL if any previous values were NULL */
840 40 : LLVMBuildCondBr(b,
841 : LLVMBuildICmp(b, LLVMIntEQ, v_boolanynull,
842 : l_sbool_const(0), ""),
843 40 : opblocks[opno + 1], b_boolisanynull);
844 :
845 40 : LLVMPositionBuilderAtEnd(b, b_boolisanynull);
846 : /* set resnull to true */
847 40 : LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
848 : /* reset resvalue */
849 40 : LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
850 :
851 40 : LLVMBuildBr(b, opblocks[opno + 1]);
852 40 : break;
853 : }
854 :
855 : /*
856 : * Treat them the same for now, optimizer can remove
857 : * redundancy. Could be worthwhile to optimize during emission
858 : * though.
859 : */
860 60 : case EEOP_BOOL_OR_STEP_FIRST:
861 : case EEOP_BOOL_OR_STEP:
862 : case EEOP_BOOL_OR_STEP_LAST:
863 : {
864 : LLVMValueRef v_boolvalue;
865 : LLVMValueRef v_boolnull;
866 : LLVMValueRef v_boolanynullp,
867 : v_boolanynull;
868 :
869 : LLVMBasicBlockRef b_boolisnull;
870 : LLVMBasicBlockRef b_boolchecktrue;
871 : LLVMBasicBlockRef b_boolistrue;
872 : LLVMBasicBlockRef b_boolcont;
873 : LLVMBasicBlockRef b_boolisanynull;
874 :
875 60 : b_boolisnull = l_bb_before_v(opblocks[opno + 1],
876 : "b.%d.boolisnull", opno);
877 60 : b_boolchecktrue = l_bb_before_v(opblocks[opno + 1],
878 : "b.%d.boolchecktrue", opno);
879 60 : b_boolistrue = l_bb_before_v(opblocks[opno + 1],
880 : "b.%d.boolistrue", opno);
881 60 : b_boolisanynull = l_bb_before_v(opblocks[opno + 1],
882 : "b.%d.boolisanynull", opno);
883 60 : b_boolcont = l_bb_before_v(opblocks[opno + 1],
884 : "b.%d.boolcont", opno);
885 :
886 60 : v_boolanynullp = l_ptr_const(op->d.boolexpr.anynull,
887 : l_ptr(TypeStorageBool));
888 :
889 60 : if (opcode == EEOP_BOOL_OR_STEP_FIRST)
890 30 : LLVMBuildStore(b, l_sbool_const(0), v_boolanynullp);
891 60 : v_boolnull = l_load(b, TypeStorageBool, v_resnullp, "");
892 60 : v_boolvalue = l_load(b, TypeSizeT, v_resvaluep, "");
893 :
894 60 : LLVMBuildCondBr(b,
895 : LLVMBuildICmp(b, LLVMIntEQ, v_boolnull,
896 : l_sbool_const(1), ""),
897 : b_boolisnull,
898 : b_boolchecktrue);
899 :
900 : /* build block that sets anynull */
901 60 : LLVMPositionBuilderAtEnd(b, b_boolisnull);
902 : /* set boolanynull to true */
903 60 : LLVMBuildStore(b, l_sbool_const(1), v_boolanynullp);
904 : /* and jump to next block */
905 60 : LLVMBuildBr(b, b_boolcont);
906 :
907 : /* build block checking for true */
908 60 : LLVMPositionBuilderAtEnd(b, b_boolchecktrue);
909 60 : LLVMBuildCondBr(b,
910 : LLVMBuildICmp(b, LLVMIntEQ, v_boolvalue,
911 : l_sizet_const(1), ""),
912 : b_boolistrue,
913 : b_boolcont);
914 :
915 : /*
916 : * Build block handling True. Value is true, so short
917 : * circuit.
918 : */
919 60 : LLVMPositionBuilderAtEnd(b, b_boolistrue);
920 : /* result is already set to TRUE, need not change it */
921 : /* and jump to the end of the OR expression */
922 60 : LLVMBuildBr(b, opblocks[op->d.boolexpr.jumpdone]);
923 :
924 : /* build block that continues if bool is FALSE */
925 60 : LLVMPositionBuilderAtEnd(b, b_boolcont);
926 :
927 60 : v_boolanynull = l_load(b, TypeStorageBool, v_boolanynullp, "");
928 :
929 : /* set value to NULL if any previous values were NULL */
930 60 : LLVMBuildCondBr(b,
931 : LLVMBuildICmp(b, LLVMIntEQ, v_boolanynull,
932 : l_sbool_const(0), ""),
933 60 : opblocks[opno + 1], b_boolisanynull);
934 :
935 60 : LLVMPositionBuilderAtEnd(b, b_boolisanynull);
936 : /* set resnull to true */
937 60 : LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
938 : /* reset resvalue */
939 60 : LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
940 :
941 60 : LLVMBuildBr(b, opblocks[opno + 1]);
942 60 : break;
943 : }
944 :
945 32 : case EEOP_BOOL_NOT_STEP:
946 : {
947 : LLVMValueRef v_boolvalue;
948 : LLVMValueRef v_negbool;
949 :
950 : /* compute !boolvalue */
951 32 : v_boolvalue = l_load(b, TypeSizeT, v_resvaluep, "");
952 32 : v_negbool = LLVMBuildZExt(b,
953 : LLVMBuildICmp(b, LLVMIntEQ,
954 : v_boolvalue,
955 : l_sizet_const(0),
956 : ""),
957 : TypeSizeT, "");
958 :
959 : /*
960 : * Store it back in resvalue. We can ignore resnull here;
961 : * if it was true, it stays true, and the value we store
962 : * in resvalue doesn't matter.
963 : */
964 32 : LLVMBuildStore(b, v_negbool, v_resvaluep);
965 :
966 32 : LLVMBuildBr(b, opblocks[opno + 1]);
967 32 : break;
968 : }
969 :
970 2958 : case EEOP_QUAL:
971 : {
972 : LLVMValueRef v_resnull;
973 : LLVMValueRef v_resvalue;
974 : LLVMValueRef v_nullorfalse;
975 : LLVMBasicBlockRef b_qualfail;
976 :
977 2958 : b_qualfail = l_bb_before_v(opblocks[opno + 1],
978 : "op.%d.qualfail", opno);
979 :
980 2958 : v_resvalue = l_load(b, TypeSizeT, v_resvaluep, "");
981 2958 : v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
982 :
983 : v_nullorfalse =
984 2958 : LLVMBuildOr(b,
985 : LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
986 : l_sbool_const(1), ""),
987 : LLVMBuildICmp(b, LLVMIntEQ, v_resvalue,
988 : l_sizet_const(0), ""),
989 : "");
990 :
991 2958 : LLVMBuildCondBr(b,
992 : v_nullorfalse,
993 : b_qualfail,
994 2958 : opblocks[opno + 1]);
995 :
996 : /* build block handling NULL or false */
997 2958 : LLVMPositionBuilderAtEnd(b, b_qualfail);
998 : /* set resnull to false */
999 2958 : LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1000 : /* set resvalue to false */
1001 2958 : LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
1002 : /* and jump out */
1003 2958 : LLVMBuildBr(b, opblocks[op->d.qualexpr.jumpdone]);
1004 2958 : break;
1005 : }
1006 :
1007 42 : case EEOP_JUMP:
1008 : {
1009 42 : LLVMBuildBr(b, opblocks[op->d.jump.jumpdone]);
1010 42 : break;
1011 : }
1012 :
1013 30 : case EEOP_JUMP_IF_NULL:
1014 : {
1015 : LLVMValueRef v_resnull;
1016 :
1017 : /* Transfer control if current result is null */
1018 :
1019 30 : v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
1020 :
1021 30 : LLVMBuildCondBr(b,
1022 : LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
1023 : l_sbool_const(1), ""),
1024 30 : opblocks[op->d.jump.jumpdone],
1025 30 : opblocks[opno + 1]);
1026 30 : break;
1027 : }
1028 :
1029 60 : case EEOP_JUMP_IF_NOT_NULL:
1030 : {
1031 : LLVMValueRef v_resnull;
1032 :
1033 : /* Transfer control if current result is non-null */
1034 :
1035 60 : v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
1036 :
1037 60 : LLVMBuildCondBr(b,
1038 : LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
1039 : l_sbool_const(0), ""),
1040 60 : opblocks[op->d.jump.jumpdone],
1041 60 : opblocks[opno + 1]);
1042 60 : break;
1043 : }
1044 :
1045 :
1046 42 : case EEOP_JUMP_IF_NOT_TRUE:
1047 : {
1048 : LLVMValueRef v_resnull;
1049 : LLVMValueRef v_resvalue;
1050 : LLVMValueRef v_nullorfalse;
1051 :
1052 : /* Transfer control if current result is null or false */
1053 :
1054 42 : v_resvalue = l_load(b, TypeSizeT, v_resvaluep, "");
1055 42 : v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
1056 :
1057 : v_nullorfalse =
1058 42 : LLVMBuildOr(b,
1059 : LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
1060 : l_sbool_const(1), ""),
1061 : LLVMBuildICmp(b, LLVMIntEQ, v_resvalue,
1062 : l_sizet_const(0), ""),
1063 : "");
1064 :
1065 42 : LLVMBuildCondBr(b,
1066 : v_nullorfalse,
1067 42 : opblocks[op->d.jump.jumpdone],
1068 42 : opblocks[opno + 1]);
1069 42 : break;
1070 : }
1071 :
1072 34 : case EEOP_NULLTEST_ISNULL:
1073 : {
1074 34 : LLVMValueRef v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
1075 : LLVMValueRef v_resvalue;
1076 :
1077 : v_resvalue =
1078 34 : LLVMBuildSelect(b,
1079 : LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
1080 : l_sbool_const(1), ""),
1081 : l_sizet_const(1),
1082 : l_sizet_const(0),
1083 : "");
1084 34 : LLVMBuildStore(b, v_resvalue, v_resvaluep);
1085 34 : LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1086 :
1087 34 : LLVMBuildBr(b, opblocks[opno + 1]);
1088 34 : break;
1089 : }
1090 :
1091 24 : case EEOP_NULLTEST_ISNOTNULL:
1092 : {
1093 24 : LLVMValueRef v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
1094 : LLVMValueRef v_resvalue;
1095 :
1096 : v_resvalue =
1097 24 : LLVMBuildSelect(b,
1098 : LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
1099 : l_sbool_const(1), ""),
1100 : l_sizet_const(0),
1101 : l_sizet_const(1),
1102 : "");
1103 24 : LLVMBuildStore(b, v_resvalue, v_resvaluep);
1104 24 : LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1105 :
1106 24 : LLVMBuildBr(b, opblocks[opno + 1]);
1107 24 : break;
1108 : }
1109 :
1110 0 : case EEOP_NULLTEST_ROWISNULL:
1111 0 : build_EvalXFunc(b, mod, "ExecEvalRowNull",
1112 : v_state, op, v_econtext);
1113 0 : LLVMBuildBr(b, opblocks[opno + 1]);
1114 0 : break;
1115 :
1116 0 : case EEOP_NULLTEST_ROWISNOTNULL:
1117 0 : build_EvalXFunc(b, mod, "ExecEvalRowNotNull",
1118 : v_state, op, v_econtext);
1119 0 : LLVMBuildBr(b, opblocks[opno + 1]);
1120 0 : break;
1121 :
1122 0 : case EEOP_BOOLTEST_IS_TRUE:
1123 : case EEOP_BOOLTEST_IS_NOT_FALSE:
1124 : case EEOP_BOOLTEST_IS_FALSE:
1125 : case EEOP_BOOLTEST_IS_NOT_TRUE:
1126 : {
1127 : LLVMBasicBlockRef b_isnull,
1128 : b_notnull;
1129 0 : LLVMValueRef v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
1130 :
1131 0 : b_isnull = l_bb_before_v(opblocks[opno + 1],
1132 : "op.%d.isnull", opno);
1133 0 : b_notnull = l_bb_before_v(opblocks[opno + 1],
1134 : "op.%d.isnotnull", opno);
1135 :
1136 : /* check if value is NULL */
1137 0 : LLVMBuildCondBr(b,
1138 : LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
1139 : l_sbool_const(1), ""),
1140 : b_isnull, b_notnull);
1141 :
1142 : /* if value is NULL, return false */
1143 0 : LLVMPositionBuilderAtEnd(b, b_isnull);
1144 :
1145 : /* result is not null */
1146 0 : LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1147 :
1148 0 : if (opcode == EEOP_BOOLTEST_IS_TRUE ||
1149 : opcode == EEOP_BOOLTEST_IS_FALSE)
1150 : {
1151 0 : LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
1152 : }
1153 : else
1154 : {
1155 0 : LLVMBuildStore(b, l_sizet_const(1), v_resvaluep);
1156 : }
1157 :
1158 0 : LLVMBuildBr(b, opblocks[opno + 1]);
1159 :
1160 0 : LLVMPositionBuilderAtEnd(b, b_notnull);
1161 :
1162 0 : if (opcode == EEOP_BOOLTEST_IS_TRUE ||
1163 : opcode == EEOP_BOOLTEST_IS_NOT_FALSE)
1164 : {
1165 : /*
1166 : * if value is not null NULL, return value (already
1167 : * set)
1168 : */
1169 : }
1170 : else
1171 : {
1172 : LLVMValueRef v_value =
1173 0 : l_load(b, TypeSizeT, v_resvaluep, "");
1174 :
1175 0 : v_value = LLVMBuildZExt(b,
1176 : LLVMBuildICmp(b, LLVMIntEQ,
1177 : v_value,
1178 : l_sizet_const(0),
1179 : ""),
1180 : TypeSizeT, "");
1181 0 : LLVMBuildStore(b, v_value, v_resvaluep);
1182 : }
1183 0 : LLVMBuildBr(b, opblocks[opno + 1]);
1184 0 : break;
1185 : }
1186 :
1187 1382 : case EEOP_PARAM_EXEC:
1188 1382 : build_EvalXFunc(b, mod, "ExecEvalParamExec",
1189 : v_state, op, v_econtext);
1190 1382 : LLVMBuildBr(b, opblocks[opno + 1]);
1191 1382 : break;
1192 :
1193 0 : case EEOP_PARAM_EXTERN:
1194 0 : build_EvalXFunc(b, mod, "ExecEvalParamExtern",
1195 : v_state, op, v_econtext);
1196 0 : LLVMBuildBr(b, opblocks[opno + 1]);
1197 0 : break;
1198 :
1199 0 : case EEOP_PARAM_CALLBACK:
1200 : {
1201 : LLVMValueRef v_func;
1202 : LLVMValueRef v_params[3];
1203 :
1204 0 : v_func = l_ptr_const(op->d.cparam.paramfunc,
1205 : llvm_pg_var_type("TypeExecEvalSubroutine"));
1206 :
1207 0 : v_params[0] = v_state;
1208 0 : v_params[1] = l_ptr_const(op, l_ptr(StructExprEvalStep));
1209 0 : v_params[2] = v_econtext;
1210 0 : l_call(b,
1211 : LLVMGetFunctionType(ExecEvalSubroutineTemplate),
1212 : v_func,
1213 : v_params, lengthof(v_params), "");
1214 :
1215 0 : LLVMBuildBr(b, opblocks[opno + 1]);
1216 0 : break;
1217 : }
1218 :
1219 652 : case EEOP_PARAM_SET:
1220 652 : build_EvalXFunc(b, mod, "ExecEvalParamSet",
1221 : v_state, op, v_econtext);
1222 652 : LLVMBuildBr(b, opblocks[opno + 1]);
1223 652 : break;
1224 :
1225 30 : case EEOP_SBSREF_SUBSCRIPTS:
1226 : {
1227 30 : int jumpdone = op->d.sbsref_subscript.jumpdone;
1228 : LLVMValueRef v_func;
1229 : LLVMValueRef v_params[3];
1230 : LLVMValueRef v_ret;
1231 :
1232 30 : v_func = l_ptr_const(op->d.sbsref_subscript.subscriptfunc,
1233 : llvm_pg_var_type("TypeExecEvalBoolSubroutine"));
1234 :
1235 30 : v_params[0] = v_state;
1236 30 : v_params[1] = l_ptr_const(op, l_ptr(StructExprEvalStep));
1237 30 : v_params[2] = v_econtext;
1238 30 : v_ret = l_call(b,
1239 : LLVMGetFunctionType(ExecEvalBoolSubroutineTemplate),
1240 : v_func,
1241 : v_params, lengthof(v_params), "");
1242 30 : v_ret = LLVMBuildZExt(b, v_ret, TypeStorageBool, "");
1243 :
1244 30 : LLVMBuildCondBr(b,
1245 : LLVMBuildICmp(b, LLVMIntEQ, v_ret,
1246 : l_sbool_const(1), ""),
1247 30 : opblocks[opno + 1],
1248 30 : opblocks[jumpdone]);
1249 30 : break;
1250 : }
1251 :
1252 30 : case EEOP_SBSREF_OLD:
1253 : case EEOP_SBSREF_ASSIGN:
1254 : case EEOP_SBSREF_FETCH:
1255 : {
1256 : LLVMValueRef v_func;
1257 : LLVMValueRef v_params[3];
1258 :
1259 30 : v_func = l_ptr_const(op->d.sbsref.subscriptfunc,
1260 : llvm_pg_var_type("TypeExecEvalSubroutine"));
1261 :
1262 30 : v_params[0] = v_state;
1263 30 : v_params[1] = l_ptr_const(op, l_ptr(StructExprEvalStep));
1264 30 : v_params[2] = v_econtext;
1265 30 : l_call(b,
1266 : LLVMGetFunctionType(ExecEvalSubroutineTemplate),
1267 : v_func,
1268 : v_params, lengthof(v_params), "");
1269 :
1270 30 : LLVMBuildBr(b, opblocks[opno + 1]);
1271 30 : break;
1272 : }
1273 :
1274 18 : case EEOP_CASE_TESTVAL:
1275 : {
1276 : LLVMValueRef v_casevaluep,
1277 : v_casevalue;
1278 : LLVMValueRef v_casenullp,
1279 : v_casenull;
1280 :
1281 18 : v_casevaluep = l_ptr_const(op->d.casetest.value,
1282 : l_ptr(TypeSizeT));
1283 18 : v_casenullp = l_ptr_const(op->d.casetest.isnull,
1284 : l_ptr(TypeStorageBool));
1285 :
1286 18 : v_casevalue = l_load(b, TypeSizeT, v_casevaluep, "");
1287 18 : v_casenull = l_load(b, TypeStorageBool, v_casenullp, "");
1288 18 : LLVMBuildStore(b, v_casevalue, v_resvaluep);
1289 18 : LLVMBuildStore(b, v_casenull, v_resnullp);
1290 :
1291 18 : LLVMBuildBr(b, opblocks[opno + 1]);
1292 18 : break;
1293 : }
1294 :
1295 0 : case EEOP_CASE_TESTVAL_EXT:
1296 : {
1297 : LLVMValueRef v_casevalue;
1298 : LLVMValueRef v_casenull;
1299 :
1300 : v_casevalue =
1301 0 : l_load_struct_gep(b,
1302 : StructExprContext,
1303 : v_econtext,
1304 : FIELDNO_EXPRCONTEXT_CASEDATUM, "");
1305 : v_casenull =
1306 0 : l_load_struct_gep(b,
1307 : StructExprContext,
1308 : v_econtext,
1309 : FIELDNO_EXPRCONTEXT_CASENULL, "");
1310 0 : LLVMBuildStore(b, v_casevalue, v_resvaluep);
1311 0 : LLVMBuildStore(b, v_casenull, v_resnullp);
1312 :
1313 0 : LLVMBuildBr(b, opblocks[opno + 1]);
1314 0 : break;
1315 : }
1316 :
1317 0 : case EEOP_MAKE_READONLY:
1318 : {
1319 : LLVMBasicBlockRef b_notnull;
1320 : LLVMValueRef v_params[1];
1321 : LLVMValueRef v_ret;
1322 : LLVMValueRef v_nullp;
1323 : LLVMValueRef v_valuep;
1324 : LLVMValueRef v_null;
1325 : LLVMValueRef v_value;
1326 :
1327 0 : b_notnull = l_bb_before_v(opblocks[opno + 1],
1328 : "op.%d.readonly.notnull", opno);
1329 :
1330 0 : v_nullp = l_ptr_const(op->d.make_readonly.isnull,
1331 : l_ptr(TypeStorageBool));
1332 :
1333 0 : v_null = l_load(b, TypeStorageBool, v_nullp, "");
1334 :
1335 : /* store null isnull value in result */
1336 0 : LLVMBuildStore(b, v_null, v_resnullp);
1337 :
1338 : /* check if value is NULL */
1339 0 : LLVMBuildCondBr(b,
1340 : LLVMBuildICmp(b, LLVMIntEQ, v_null,
1341 : l_sbool_const(1), ""),
1342 0 : opblocks[opno + 1], b_notnull);
1343 :
1344 : /* if value is not null, convert to RO datum */
1345 0 : LLVMPositionBuilderAtEnd(b, b_notnull);
1346 :
1347 0 : v_valuep = l_ptr_const(op->d.make_readonly.value,
1348 : l_ptr(TypeSizeT));
1349 :
1350 0 : v_value = l_load(b, TypeSizeT, v_valuep, "");
1351 :
1352 0 : v_params[0] = v_value;
1353 : v_ret =
1354 0 : l_call(b,
1355 : llvm_pg_var_func_type("MakeExpandedObjectReadOnlyInternal"),
1356 : llvm_pg_func(mod, "MakeExpandedObjectReadOnlyInternal"),
1357 : v_params, lengthof(v_params), "");
1358 0 : LLVMBuildStore(b, v_ret, v_resvaluep);
1359 :
1360 0 : LLVMBuildBr(b, opblocks[opno + 1]);
1361 0 : break;
1362 : }
1363 :
1364 96 : case EEOP_IOCOERCE:
1365 : {
1366 : FunctionCallInfo fcinfo_out,
1367 : fcinfo_in;
1368 : LLVMValueRef v_fn_out,
1369 : v_fn_in;
1370 : LLVMValueRef v_fcinfo_out,
1371 : v_fcinfo_in;
1372 : LLVMValueRef v_fcinfo_in_isnullp;
1373 : LLVMValueRef v_retval;
1374 : LLVMValueRef v_resvalue;
1375 : LLVMValueRef v_resnull;
1376 :
1377 : LLVMValueRef v_output_skip;
1378 : LLVMValueRef v_output;
1379 :
1380 : LLVMBasicBlockRef b_skipoutput;
1381 : LLVMBasicBlockRef b_calloutput;
1382 : LLVMBasicBlockRef b_input;
1383 : LLVMBasicBlockRef b_inputcall;
1384 :
1385 96 : fcinfo_out = op->d.iocoerce.fcinfo_data_out;
1386 96 : fcinfo_in = op->d.iocoerce.fcinfo_data_in;
1387 :
1388 96 : b_skipoutput = l_bb_before_v(opblocks[opno + 1],
1389 : "op.%d.skipoutputnull", opno);
1390 96 : b_calloutput = l_bb_before_v(opblocks[opno + 1],
1391 : "op.%d.calloutput", opno);
1392 96 : b_input = l_bb_before_v(opblocks[opno + 1],
1393 : "op.%d.input", opno);
1394 96 : b_inputcall = l_bb_before_v(opblocks[opno + 1],
1395 : "op.%d.inputcall", opno);
1396 :
1397 96 : v_fn_out = llvm_function_reference(context, b, mod, fcinfo_out);
1398 96 : v_fn_in = llvm_function_reference(context, b, mod, fcinfo_in);
1399 96 : v_fcinfo_out = l_ptr_const(fcinfo_out, l_ptr(StructFunctionCallInfoData));
1400 96 : v_fcinfo_in = l_ptr_const(fcinfo_in, l_ptr(StructFunctionCallInfoData));
1401 :
1402 : v_fcinfo_in_isnullp =
1403 96 : l_struct_gep(b,
1404 : StructFunctionCallInfoData,
1405 : v_fcinfo_in,
1406 : FIELDNO_FUNCTIONCALLINFODATA_ISNULL,
1407 : "v_fcinfo_in_isnull");
1408 :
1409 : /* output functions are not called on nulls */
1410 96 : v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
1411 96 : LLVMBuildCondBr(b,
1412 : LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
1413 : l_sbool_const(1), ""),
1414 : b_skipoutput,
1415 : b_calloutput);
1416 :
1417 96 : LLVMPositionBuilderAtEnd(b, b_skipoutput);
1418 96 : v_output_skip = l_sizet_const(0);
1419 96 : LLVMBuildBr(b, b_input);
1420 :
1421 96 : LLVMPositionBuilderAtEnd(b, b_calloutput);
1422 96 : v_resvalue = l_load(b, TypeSizeT, v_resvaluep, "");
1423 :
1424 : /* set arg[0] */
1425 96 : LLVMBuildStore(b,
1426 : v_resvalue,
1427 : l_funcvaluep(b, v_fcinfo_out, 0));
1428 96 : LLVMBuildStore(b,
1429 : l_sbool_const(0),
1430 : l_funcnullp(b, v_fcinfo_out, 0));
1431 : /* and call output function (can never return NULL) */
1432 96 : v_output = l_call(b,
1433 : LLVMGetFunctionType(v_fn_out),
1434 : v_fn_out, &v_fcinfo_out,
1435 : 1, "funccall_coerce_out");
1436 96 : LLVMBuildBr(b, b_input);
1437 :
1438 : /* build block handling input function call */
1439 96 : LLVMPositionBuilderAtEnd(b, b_input);
1440 :
1441 : /* phi between resnull and output function call branches */
1442 : {
1443 : LLVMValueRef incoming_values[2];
1444 : LLVMBasicBlockRef incoming_blocks[2];
1445 :
1446 96 : incoming_values[0] = v_output_skip;
1447 96 : incoming_blocks[0] = b_skipoutput;
1448 :
1449 96 : incoming_values[1] = v_output;
1450 96 : incoming_blocks[1] = b_calloutput;
1451 :
1452 96 : v_output = LLVMBuildPhi(b, TypeSizeT, "output");
1453 96 : LLVMAddIncoming(v_output,
1454 : incoming_values, incoming_blocks,
1455 : lengthof(incoming_blocks));
1456 : }
1457 :
1458 : /*
1459 : * If input function is strict, skip if input string is
1460 : * NULL.
1461 : */
1462 96 : if (op->d.iocoerce.finfo_in->fn_strict)
1463 : {
1464 96 : LLVMBuildCondBr(b,
1465 : LLVMBuildICmp(b, LLVMIntEQ, v_output,
1466 : l_sizet_const(0), ""),
1467 96 : opblocks[opno + 1],
1468 : b_inputcall);
1469 : }
1470 : else
1471 : {
1472 0 : LLVMBuildBr(b, b_inputcall);
1473 : }
1474 :
1475 96 : LLVMPositionBuilderAtEnd(b, b_inputcall);
1476 : /* set arguments */
1477 : /* arg0: output */
1478 96 : LLVMBuildStore(b, v_output,
1479 : l_funcvaluep(b, v_fcinfo_in, 0));
1480 96 : LLVMBuildStore(b, v_resnull,
1481 : l_funcnullp(b, v_fcinfo_in, 0));
1482 :
1483 : /* arg1: ioparam: preset in execExpr.c */
1484 : /* arg2: typmod: preset in execExpr.c */
1485 :
1486 : /* reset fcinfo_in->isnull */
1487 96 : LLVMBuildStore(b, l_sbool_const(0), v_fcinfo_in_isnullp);
1488 : /* and call function */
1489 96 : v_retval = l_call(b,
1490 : LLVMGetFunctionType(v_fn_in),
1491 : v_fn_in, &v_fcinfo_in, 1,
1492 : "funccall_iocoerce_in");
1493 :
1494 96 : LLVMBuildStore(b, v_retval, v_resvaluep);
1495 :
1496 96 : LLVMBuildBr(b, opblocks[opno + 1]);
1497 96 : break;
1498 : }
1499 :
1500 0 : case EEOP_IOCOERCE_SAFE:
1501 0 : build_EvalXFunc(b, mod, "ExecEvalCoerceViaIOSafe",
1502 : v_state, op);
1503 0 : LLVMBuildBr(b, opblocks[opno + 1]);
1504 0 : break;
1505 :
1506 934 : case EEOP_DISTINCT:
1507 : case EEOP_NOT_DISTINCT:
1508 : {
1509 934 : FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
1510 :
1511 : LLVMValueRef v_fcinfo;
1512 : LLVMValueRef v_fcinfo_isnull;
1513 :
1514 : LLVMValueRef v_argnull0,
1515 : v_argisnull0;
1516 : LLVMValueRef v_argnull1,
1517 : v_argisnull1;
1518 :
1519 : LLVMValueRef v_anyargisnull;
1520 : LLVMValueRef v_bothargisnull;
1521 :
1522 : LLVMValueRef v_result;
1523 :
1524 : LLVMBasicBlockRef b_noargnull;
1525 : LLVMBasicBlockRef b_checkbothargnull;
1526 : LLVMBasicBlockRef b_bothargnull;
1527 : LLVMBasicBlockRef b_anyargnull;
1528 :
1529 934 : b_noargnull = l_bb_before_v(opblocks[opno + 1], "op.%d.noargnull", opno);
1530 934 : b_checkbothargnull = l_bb_before_v(opblocks[opno + 1], "op.%d.checkbothargnull", opno);
1531 934 : b_bothargnull = l_bb_before_v(opblocks[opno + 1], "op.%d.bothargnull", opno);
1532 934 : b_anyargnull = l_bb_before_v(opblocks[opno + 1], "op.%d.anyargnull", opno);
1533 :
1534 934 : v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
1535 :
1536 : /* load args[0|1].isnull for both arguments */
1537 934 : v_argnull0 = l_funcnull(b, v_fcinfo, 0);
1538 934 : v_argisnull0 = LLVMBuildICmp(b, LLVMIntEQ, v_argnull0,
1539 : l_sbool_const(1), "");
1540 934 : v_argnull1 = l_funcnull(b, v_fcinfo, 1);
1541 934 : v_argisnull1 = LLVMBuildICmp(b, LLVMIntEQ, v_argnull1,
1542 : l_sbool_const(1), "");
1543 :
1544 934 : v_anyargisnull = LLVMBuildOr(b, v_argisnull0, v_argisnull1, "");
1545 934 : v_bothargisnull = LLVMBuildAnd(b, v_argisnull0, v_argisnull1, "");
1546 :
1547 : /*
1548 : * Check function arguments for NULLness: If either is
1549 : * NULL, we check if both args are NULL. Otherwise call
1550 : * comparator.
1551 : */
1552 934 : LLVMBuildCondBr(b, v_anyargisnull, b_checkbothargnull,
1553 : b_noargnull);
1554 :
1555 : /*
1556 : * build block checking if any arg is null
1557 : */
1558 934 : LLVMPositionBuilderAtEnd(b, b_checkbothargnull);
1559 934 : LLVMBuildCondBr(b, v_bothargisnull, b_bothargnull,
1560 : b_anyargnull);
1561 :
1562 :
1563 : /* Both NULL? Then is not distinct... */
1564 934 : LLVMPositionBuilderAtEnd(b, b_bothargnull);
1565 934 : LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1566 934 : if (opcode == EEOP_NOT_DISTINCT)
1567 934 : LLVMBuildStore(b, l_sizet_const(1), v_resvaluep);
1568 : else
1569 0 : LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
1570 :
1571 934 : LLVMBuildBr(b, opblocks[opno + 1]);
1572 :
1573 : /* Only one is NULL? Then is distinct... */
1574 934 : LLVMPositionBuilderAtEnd(b, b_anyargnull);
1575 934 : LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1576 934 : if (opcode == EEOP_NOT_DISTINCT)
1577 934 : LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
1578 : else
1579 0 : LLVMBuildStore(b, l_sizet_const(1), v_resvaluep);
1580 934 : LLVMBuildBr(b, opblocks[opno + 1]);
1581 :
1582 : /* neither argument is null: compare */
1583 934 : LLVMPositionBuilderAtEnd(b, b_noargnull);
1584 :
1585 934 : v_result = BuildV1Call(context, b, mod, fcinfo,
1586 : &v_fcinfo_isnull);
1587 :
1588 934 : if (opcode == EEOP_DISTINCT)
1589 : {
1590 : /* Must invert result of "=" */
1591 : v_result =
1592 0 : LLVMBuildZExt(b,
1593 : LLVMBuildICmp(b, LLVMIntEQ,
1594 : v_result,
1595 : l_sizet_const(0), ""),
1596 : TypeSizeT, "");
1597 : }
1598 :
1599 934 : LLVMBuildStore(b, v_fcinfo_isnull, v_resnullp);
1600 934 : LLVMBuildStore(b, v_result, v_resvaluep);
1601 :
1602 934 : LLVMBuildBr(b, opblocks[opno + 1]);
1603 934 : break;
1604 : }
1605 :
1606 0 : case EEOP_NULLIF:
1607 : {
1608 0 : FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
1609 :
1610 : LLVMValueRef v_fcinfo;
1611 : LLVMValueRef v_fcinfo_isnull;
1612 : LLVMValueRef v_argnull0;
1613 : LLVMValueRef v_argnull1;
1614 : LLVMValueRef v_anyargisnull;
1615 : LLVMValueRef v_arg0;
1616 : LLVMBasicBlockRef b_hasnull;
1617 : LLVMBasicBlockRef b_nonull;
1618 : LLVMBasicBlockRef b_argsequal;
1619 : LLVMValueRef v_retval;
1620 : LLVMValueRef v_argsequal;
1621 :
1622 0 : b_hasnull = l_bb_before_v(opblocks[opno + 1],
1623 : "b.%d.null-args", opno);
1624 0 : b_nonull = l_bb_before_v(opblocks[opno + 1],
1625 : "b.%d.no-null-args", opno);
1626 0 : b_argsequal = l_bb_before_v(opblocks[opno + 1],
1627 : "b.%d.argsequal", opno);
1628 :
1629 0 : v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
1630 :
1631 : /* save original arg[0] */
1632 0 : v_arg0 = l_funcvalue(b, v_fcinfo, 0);
1633 :
1634 : /* if either argument is NULL they can't be equal */
1635 0 : v_argnull0 = l_funcnull(b, v_fcinfo, 0);
1636 0 : v_argnull1 = l_funcnull(b, v_fcinfo, 1);
1637 :
1638 : v_anyargisnull =
1639 0 : LLVMBuildOr(b,
1640 : LLVMBuildICmp(b, LLVMIntEQ, v_argnull0,
1641 : l_sbool_const(1), ""),
1642 : LLVMBuildICmp(b, LLVMIntEQ, v_argnull1,
1643 : l_sbool_const(1), ""),
1644 : "");
1645 :
1646 0 : LLVMBuildCondBr(b, v_anyargisnull, b_hasnull, b_nonull);
1647 :
1648 : /* one (or both) of the arguments are null, return arg[0] */
1649 0 : LLVMPositionBuilderAtEnd(b, b_hasnull);
1650 0 : LLVMBuildStore(b, v_argnull0, v_resnullp);
1651 0 : LLVMBuildStore(b, v_arg0, v_resvaluep);
1652 0 : LLVMBuildBr(b, opblocks[opno + 1]);
1653 :
1654 : /* build block to invoke function and check result */
1655 0 : LLVMPositionBuilderAtEnd(b, b_nonull);
1656 :
1657 : /*
1658 : * If first argument is of varlena type, it might be an
1659 : * expanded datum. We need to ensure that the value
1660 : * passed to the comparison function is a read-only
1661 : * pointer. However, if we end by returning the first
1662 : * argument, that will be the original read-write pointer
1663 : * if it was read-write.
1664 : */
1665 0 : if (op->d.func.make_ro)
1666 : {
1667 : LLVMValueRef v_params[1];
1668 : LLVMValueRef v_arg0_ro;
1669 :
1670 0 : v_params[0] = v_arg0;
1671 : v_arg0_ro =
1672 0 : l_call(b,
1673 : llvm_pg_var_func_type("MakeExpandedObjectReadOnlyInternal"),
1674 : llvm_pg_func(mod, "MakeExpandedObjectReadOnlyInternal"),
1675 : v_params, lengthof(v_params), "");
1676 0 : LLVMBuildStore(b, v_arg0_ro,
1677 : l_funcvaluep(b, v_fcinfo, 0));
1678 : }
1679 :
1680 0 : v_retval = BuildV1Call(context, b, mod, fcinfo, &v_fcinfo_isnull);
1681 :
1682 : /*
1683 : * If result not null and arguments are equal return null,
1684 : * else return arg[0] (same result as if there'd been
1685 : * NULLs, hence reuse b_hasnull).
1686 : */
1687 0 : v_argsequal = LLVMBuildAnd(b,
1688 : LLVMBuildICmp(b, LLVMIntEQ,
1689 : v_fcinfo_isnull,
1690 : l_sbool_const(0),
1691 : ""),
1692 : LLVMBuildICmp(b, LLVMIntEQ,
1693 : v_retval,
1694 : l_sizet_const(1),
1695 : ""),
1696 : "");
1697 0 : LLVMBuildCondBr(b, v_argsequal, b_argsequal, b_hasnull);
1698 :
1699 : /* build block setting result to NULL, if args are equal */
1700 0 : LLVMPositionBuilderAtEnd(b, b_argsequal);
1701 0 : LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
1702 0 : LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
1703 :
1704 0 : LLVMBuildBr(b, opblocks[opno + 1]);
1705 0 : break;
1706 : }
1707 :
1708 0 : case EEOP_SQLVALUEFUNCTION:
1709 0 : build_EvalXFunc(b, mod, "ExecEvalSQLValueFunction",
1710 : v_state, op);
1711 0 : LLVMBuildBr(b, opblocks[opno + 1]);
1712 0 : break;
1713 :
1714 0 : case EEOP_CURRENTOFEXPR:
1715 0 : build_EvalXFunc(b, mod, "ExecEvalCurrentOfExpr",
1716 : v_state, op);
1717 0 : LLVMBuildBr(b, opblocks[opno + 1]);
1718 0 : break;
1719 :
1720 0 : case EEOP_NEXTVALUEEXPR:
1721 0 : build_EvalXFunc(b, mod, "ExecEvalNextValueExpr",
1722 : v_state, op);
1723 0 : LLVMBuildBr(b, opblocks[opno + 1]);
1724 0 : break;
1725 :
1726 60 : case EEOP_RETURNINGEXPR:
1727 : {
1728 : LLVMBasicBlockRef b_isnull;
1729 : LLVMValueRef v_flagsp;
1730 : LLVMValueRef v_flags;
1731 : LLVMValueRef v_nullflag;
1732 :
1733 60 : b_isnull = l_bb_before_v(opblocks[opno + 1],
1734 : "op.%d.row.isnull", opno);
1735 :
1736 : /*
1737 : * The next op actually evaluates the expression. If the
1738 : * OLD/NEW row doesn't exist, skip that and return NULL.
1739 : */
1740 60 : v_flagsp = l_struct_gep(b,
1741 : StructExprState,
1742 : v_state,
1743 : FIELDNO_EXPRSTATE_FLAGS,
1744 : "v.state.flags");
1745 60 : v_flags = l_load(b, TypeStorageBool, v_flagsp, "");
1746 :
1747 60 : v_nullflag = l_int8_const(lc, op->d.returningexpr.nullflag);
1748 :
1749 60 : LLVMBuildCondBr(b,
1750 : LLVMBuildICmp(b, LLVMIntEQ,
1751 : LLVMBuildAnd(b, v_flags,
1752 : v_nullflag, ""),
1753 : l_sbool_const(0), ""),
1754 60 : opblocks[opno + 1], b_isnull);
1755 :
1756 60 : LLVMPositionBuilderAtEnd(b, b_isnull);
1757 :
1758 60 : LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
1759 60 : LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
1760 :
1761 60 : LLVMBuildBr(b, opblocks[op->d.returningexpr.jumpdone]);
1762 60 : break;
1763 : }
1764 :
1765 78 : case EEOP_ARRAYEXPR:
1766 78 : build_EvalXFunc(b, mod, "ExecEvalArrayExpr",
1767 : v_state, op);
1768 78 : LLVMBuildBr(b, opblocks[opno + 1]);
1769 78 : break;
1770 :
1771 48 : case EEOP_ARRAYCOERCE:
1772 48 : build_EvalXFunc(b, mod, "ExecEvalArrayCoerce",
1773 : v_state, op, v_econtext);
1774 48 : LLVMBuildBr(b, opblocks[opno + 1]);
1775 48 : break;
1776 :
1777 84 : case EEOP_ROW:
1778 84 : build_EvalXFunc(b, mod, "ExecEvalRow",
1779 : v_state, op);
1780 84 : LLVMBuildBr(b, opblocks[opno + 1]);
1781 84 : break;
1782 :
1783 0 : case EEOP_ROWCOMPARE_STEP:
1784 : {
1785 0 : FunctionCallInfo fcinfo = op->d.rowcompare_step.fcinfo_data;
1786 : LLVMValueRef v_fcinfo_isnull;
1787 : LLVMBasicBlockRef b_null;
1788 : LLVMBasicBlockRef b_compare;
1789 : LLVMBasicBlockRef b_compare_result;
1790 :
1791 : LLVMValueRef v_retval;
1792 :
1793 0 : b_null = l_bb_before_v(opblocks[opno + 1],
1794 : "op.%d.row-null", opno);
1795 0 : b_compare = l_bb_before_v(opblocks[opno + 1],
1796 : "op.%d.row-compare", opno);
1797 : b_compare_result =
1798 0 : l_bb_before_v(opblocks[opno + 1],
1799 : "op.%d.row-compare-result",
1800 : opno);
1801 :
1802 : /*
1803 : * If function is strict, and either arg is null, we're
1804 : * done.
1805 : */
1806 0 : if (op->d.rowcompare_step.finfo->fn_strict)
1807 : {
1808 : LLVMValueRef v_fcinfo;
1809 : LLVMValueRef v_argnull0;
1810 : LLVMValueRef v_argnull1;
1811 : LLVMValueRef v_anyargisnull;
1812 :
1813 0 : v_fcinfo = l_ptr_const(fcinfo,
1814 : l_ptr(StructFunctionCallInfoData));
1815 :
1816 0 : v_argnull0 = l_funcnull(b, v_fcinfo, 0);
1817 0 : v_argnull1 = l_funcnull(b, v_fcinfo, 1);
1818 :
1819 : v_anyargisnull =
1820 0 : LLVMBuildOr(b,
1821 : LLVMBuildICmp(b,
1822 : LLVMIntEQ,
1823 : v_argnull0,
1824 : l_sbool_const(1),
1825 : ""),
1826 : LLVMBuildICmp(b, LLVMIntEQ,
1827 : v_argnull1,
1828 : l_sbool_const(1), ""),
1829 : "");
1830 :
1831 0 : LLVMBuildCondBr(b, v_anyargisnull, b_null, b_compare);
1832 : }
1833 : else
1834 : {
1835 0 : LLVMBuildBr(b, b_compare);
1836 : }
1837 :
1838 : /* build block invoking comparison function */
1839 0 : LLVMPositionBuilderAtEnd(b, b_compare);
1840 :
1841 : /* call function */
1842 0 : v_retval = BuildV1Call(context, b, mod, fcinfo,
1843 : &v_fcinfo_isnull);
1844 0 : LLVMBuildStore(b, v_retval, v_resvaluep);
1845 :
1846 : /* if result of function is NULL, force NULL result */
1847 0 : LLVMBuildCondBr(b,
1848 : LLVMBuildICmp(b,
1849 : LLVMIntEQ,
1850 : v_fcinfo_isnull,
1851 : l_sbool_const(0),
1852 : ""),
1853 : b_compare_result,
1854 : b_null);
1855 :
1856 : /* build block analyzing the !NULL comparator result */
1857 0 : LLVMPositionBuilderAtEnd(b, b_compare_result);
1858 :
1859 : /* if results equal, compare next, otherwise done */
1860 0 : LLVMBuildCondBr(b,
1861 : LLVMBuildICmp(b,
1862 : LLVMIntEQ,
1863 : v_retval,
1864 : l_sizet_const(0), ""),
1865 0 : opblocks[opno + 1],
1866 0 : opblocks[op->d.rowcompare_step.jumpdone]);
1867 :
1868 : /*
1869 : * Build block handling NULL input or NULL comparator
1870 : * result.
1871 : */
1872 0 : LLVMPositionBuilderAtEnd(b, b_null);
1873 0 : LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
1874 0 : LLVMBuildBr(b, opblocks[op->d.rowcompare_step.jumpnull]);
1875 :
1876 0 : break;
1877 : }
1878 :
1879 0 : case EEOP_ROWCOMPARE_FINAL:
1880 : {
1881 0 : CompareType cmptype = op->d.rowcompare_final.cmptype;
1882 :
1883 : LLVMValueRef v_cmpresult;
1884 : LLVMValueRef v_result;
1885 : LLVMIntPredicate predicate;
1886 :
1887 : /*
1888 : * Btree comparators return 32 bit results, need to be
1889 : * careful about sign (used as a 64 bit value it's
1890 : * otherwise wrong).
1891 : */
1892 : v_cmpresult =
1893 0 : LLVMBuildTrunc(b,
1894 : l_load(b, TypeSizeT, v_resvaluep, ""),
1895 : LLVMInt32TypeInContext(lc), "");
1896 :
1897 : switch (cmptype)
1898 : {
1899 0 : case COMPARE_LT:
1900 0 : predicate = LLVMIntSLT;
1901 0 : break;
1902 0 : case COMPARE_LE:
1903 0 : predicate = LLVMIntSLE;
1904 0 : break;
1905 0 : case COMPARE_GT:
1906 0 : predicate = LLVMIntSGT;
1907 0 : break;
1908 0 : case COMPARE_GE:
1909 0 : predicate = LLVMIntSGE;
1910 0 : break;
1911 0 : default:
1912 : /* EQ and NE cases aren't allowed here */
1913 : Assert(false);
1914 0 : predicate = 0; /* prevent compiler warning */
1915 0 : break;
1916 : }
1917 :
1918 0 : v_result = LLVMBuildICmp(b,
1919 : predicate,
1920 : v_cmpresult,
1921 : l_int32_const(lc, 0),
1922 : "");
1923 0 : v_result = LLVMBuildZExt(b, v_result, TypeSizeT, "");
1924 :
1925 0 : LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
1926 0 : LLVMBuildStore(b, v_result, v_resvaluep);
1927 :
1928 0 : LLVMBuildBr(b, opblocks[opno + 1]);
1929 0 : break;
1930 : }
1931 :
1932 0 : case EEOP_MINMAX:
1933 0 : build_EvalXFunc(b, mod, "ExecEvalMinMax",
1934 : v_state, op);
1935 0 : LLVMBuildBr(b, opblocks[opno + 1]);
1936 0 : break;
1937 :
1938 114 : case EEOP_FIELDSELECT:
1939 114 : build_EvalXFunc(b, mod, "ExecEvalFieldSelect",
1940 : v_state, op, v_econtext);
1941 114 : LLVMBuildBr(b, opblocks[opno + 1]);
1942 114 : break;
1943 :
1944 0 : case EEOP_FIELDSTORE_DEFORM:
1945 0 : build_EvalXFunc(b, mod, "ExecEvalFieldStoreDeForm",
1946 : v_state, op, v_econtext);
1947 0 : LLVMBuildBr(b, opblocks[opno + 1]);
1948 0 : break;
1949 :
1950 0 : case EEOP_FIELDSTORE_FORM:
1951 0 : build_EvalXFunc(b, mod, "ExecEvalFieldStoreForm",
1952 : v_state, op, v_econtext);
1953 0 : LLVMBuildBr(b, opblocks[opno + 1]);
1954 0 : break;
1955 :
1956 0 : case EEOP_DOMAIN_TESTVAL:
1957 : {
1958 : LLVMValueRef v_casevaluep,
1959 : v_casevalue;
1960 : LLVMValueRef v_casenullp,
1961 : v_casenull;
1962 :
1963 0 : v_casevaluep = l_ptr_const(op->d.casetest.value,
1964 : l_ptr(TypeSizeT));
1965 0 : v_casenullp = l_ptr_const(op->d.casetest.isnull,
1966 : l_ptr(TypeStorageBool));
1967 :
1968 0 : v_casevalue = l_load(b, TypeSizeT, v_casevaluep, "");
1969 0 : v_casenull = l_load(b, TypeStorageBool, v_casenullp, "");
1970 0 : LLVMBuildStore(b, v_casevalue, v_resvaluep);
1971 0 : LLVMBuildStore(b, v_casenull, v_resnullp);
1972 :
1973 0 : LLVMBuildBr(b, opblocks[opno + 1]);
1974 0 : break;
1975 : }
1976 :
1977 0 : case EEOP_DOMAIN_TESTVAL_EXT:
1978 : {
1979 : LLVMValueRef v_casevalue;
1980 : LLVMValueRef v_casenull;
1981 :
1982 : v_casevalue =
1983 0 : l_load_struct_gep(b,
1984 : StructExprContext,
1985 : v_econtext,
1986 : FIELDNO_EXPRCONTEXT_DOMAINDATUM,
1987 : "");
1988 : v_casenull =
1989 0 : l_load_struct_gep(b,
1990 : StructExprContext,
1991 : v_econtext,
1992 : FIELDNO_EXPRCONTEXT_DOMAINNULL,
1993 : "");
1994 0 : LLVMBuildStore(b, v_casevalue, v_resvaluep);
1995 0 : LLVMBuildStore(b, v_casenull, v_resnullp);
1996 :
1997 0 : LLVMBuildBr(b, opblocks[opno + 1]);
1998 0 : break;
1999 : }
2000 :
2001 0 : case EEOP_DOMAIN_NOTNULL:
2002 0 : build_EvalXFunc(b, mod, "ExecEvalConstraintNotNull",
2003 : v_state, op);
2004 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2005 0 : break;
2006 :
2007 0 : case EEOP_DOMAIN_CHECK:
2008 0 : build_EvalXFunc(b, mod, "ExecEvalConstraintCheck",
2009 : v_state, op);
2010 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2011 0 : break;
2012 :
2013 0 : case EEOP_HASHDATUM_SET_INITVAL:
2014 : {
2015 : LLVMValueRef v_initvalue;
2016 :
2017 0 : v_initvalue = l_sizet_const(op->d.hashdatum_initvalue.init_value);
2018 :
2019 0 : LLVMBuildStore(b, v_initvalue, v_resvaluep);
2020 0 : LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
2021 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2022 0 : break;
2023 : }
2024 :
2025 1506 : case EEOP_HASHDATUM_FIRST:
2026 : case EEOP_HASHDATUM_FIRST_STRICT:
2027 : case EEOP_HASHDATUM_NEXT32:
2028 : case EEOP_HASHDATUM_NEXT32_STRICT:
2029 : {
2030 1506 : FunctionCallInfo fcinfo = op->d.hashdatum.fcinfo_data;
2031 : LLVMValueRef v_fcinfo;
2032 : LLVMValueRef v_fcinfo_isnull;
2033 : LLVMValueRef v_retval;
2034 : LLVMBasicBlockRef b_checkargnull;
2035 : LLVMBasicBlockRef b_ifnotnull;
2036 : LLVMBasicBlockRef b_ifnullblock;
2037 : LLVMValueRef v_argisnull;
2038 1506 : LLVMValueRef v_prevhash = NULL;
2039 :
2040 : /*
2041 : * When performing the next hash and not in strict mode we
2042 : * perform a rotation of the previously stored hash value
2043 : * before doing the NULL check. We want to do this even
2044 : * when we receive a NULL Datum to hash. In strict mode,
2045 : * we do this after the NULL check so as not to waste the
2046 : * effort of rotating the bits when we're going to throw
2047 : * away the hash value and return NULL.
2048 : */
2049 1506 : if (opcode == EEOP_HASHDATUM_NEXT32)
2050 : {
2051 : LLVMValueRef v_tmp1;
2052 : LLVMValueRef v_tmp2;
2053 : LLVMValueRef tmp;
2054 :
2055 212 : tmp = l_ptr_const(&op->d.hashdatum.iresult->value,
2056 : l_ptr(TypeSizeT));
2057 :
2058 : /*
2059 : * Fetch the previously hashed value from where the
2060 : * previous hash operation stored it.
2061 : */
2062 212 : v_prevhash = l_load(b, TypeSizeT, tmp, "prevhash");
2063 :
2064 : /*
2065 : * Rotate bits left by 1 bit. Be careful not to
2066 : * overflow uint32 when working with size_t.
2067 : */
2068 212 : v_tmp1 = LLVMBuildShl(b, v_prevhash, l_sizet_const(1),
2069 : "");
2070 212 : v_tmp1 = LLVMBuildAnd(b, v_tmp1,
2071 : l_sizet_const(0xffffffff), "");
2072 212 : v_tmp2 = LLVMBuildLShr(b, v_prevhash,
2073 : l_sizet_const(31), "");
2074 212 : v_prevhash = LLVMBuildOr(b, v_tmp1, v_tmp2,
2075 : "rotatedhash");
2076 : }
2077 :
2078 : /*
2079 : * Block for the actual function call, if args are
2080 : * non-NULL.
2081 : */
2082 1506 : b_ifnotnull = l_bb_before_v(opblocks[opno + 1],
2083 : "b.%d.ifnotnull",
2084 : opno);
2085 :
2086 : /* we expect the hash function to have 1 argument */
2087 1506 : if (fcinfo->nargs != 1)
2088 0 : elog(ERROR, "incorrect number of function arguments");
2089 :
2090 1506 : v_fcinfo = l_ptr_const(fcinfo,
2091 : l_ptr(StructFunctionCallInfoData));
2092 :
2093 1506 : b_checkargnull = l_bb_before_v(b_ifnotnull,
2094 : "b.%d.isnull.0", opno);
2095 :
2096 1506 : LLVMBuildBr(b, b_checkargnull);
2097 :
2098 : /*
2099 : * Determine what to do if we find the argument to be
2100 : * NULL.
2101 : */
2102 1506 : if (opcode == EEOP_HASHDATUM_FIRST_STRICT ||
2103 : opcode == EEOP_HASHDATUM_NEXT32_STRICT)
2104 : {
2105 1002 : b_ifnullblock = l_bb_before_v(b_ifnotnull,
2106 : "b.%d.strictnull",
2107 : opno);
2108 :
2109 1002 : LLVMPositionBuilderAtEnd(b, b_ifnullblock);
2110 :
2111 : /*
2112 : * In strict node, NULL inputs result in NULL. Save
2113 : * the NULL result and goto jumpdone.
2114 : */
2115 1002 : LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
2116 1002 : LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
2117 1002 : LLVMBuildBr(b, opblocks[op->d.hashdatum.jumpdone]);
2118 : }
2119 : else
2120 : {
2121 504 : b_ifnullblock = l_bb_before_v(b_ifnotnull,
2122 : "b.%d.null",
2123 : opno);
2124 :
2125 504 : LLVMPositionBuilderAtEnd(b, b_ifnullblock);
2126 :
2127 :
2128 504 : LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
2129 :
2130 504 : if (opcode == EEOP_HASHDATUM_NEXT32)
2131 : {
2132 : Assert(v_prevhash != NULL);
2133 :
2134 : /*
2135 : * Save the rotated hash value and skip to the
2136 : * next op.
2137 : */
2138 212 : LLVMBuildStore(b, v_prevhash, v_resvaluep);
2139 : }
2140 : else
2141 : {
2142 : Assert(opcode == EEOP_HASHDATUM_FIRST);
2143 :
2144 : /*
2145 : * Store a zero Datum when the Datum to hash is
2146 : * NULL
2147 : */
2148 292 : LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
2149 : }
2150 :
2151 504 : LLVMBuildBr(b, opblocks[opno + 1]);
2152 : }
2153 :
2154 1506 : LLVMPositionBuilderAtEnd(b, b_checkargnull);
2155 :
2156 : /* emit code to check if the input parameter is NULL */
2157 1506 : v_argisnull = l_funcnull(b, v_fcinfo, 0);
2158 1506 : LLVMBuildCondBr(b,
2159 : LLVMBuildICmp(b,
2160 : LLVMIntEQ,
2161 : v_argisnull,
2162 : l_sbool_const(1),
2163 : ""),
2164 : b_ifnullblock,
2165 : b_ifnotnull);
2166 :
2167 1506 : LLVMPositionBuilderAtEnd(b, b_ifnotnull);
2168 :
2169 : /*
2170 : * Rotate the previously stored hash value when performing
2171 : * NEXT32 in strict mode. In non-strict mode we already
2172 : * did this before checking for NULLs.
2173 : */
2174 1506 : if (opcode == EEOP_HASHDATUM_NEXT32_STRICT)
2175 : {
2176 : LLVMValueRef v_tmp1;
2177 : LLVMValueRef v_tmp2;
2178 : LLVMValueRef tmp;
2179 :
2180 12 : tmp = l_ptr_const(&op->d.hashdatum.iresult->value,
2181 : l_ptr(TypeSizeT));
2182 :
2183 : /*
2184 : * Fetch the previously hashed value from where the
2185 : * previous hash operation stored it.
2186 : */
2187 12 : v_prevhash = l_load(b, TypeSizeT, tmp, "prevhash");
2188 :
2189 : /*
2190 : * Rotate bits left by 1 bit. Be careful not to
2191 : * overflow uint32 when working with size_t.
2192 : */
2193 12 : v_tmp1 = LLVMBuildShl(b, v_prevhash, l_sizet_const(1),
2194 : "");
2195 12 : v_tmp1 = LLVMBuildAnd(b, v_tmp1,
2196 : l_sizet_const(0xffffffff), "");
2197 12 : v_tmp2 = LLVMBuildLShr(b, v_prevhash,
2198 : l_sizet_const(31), "");
2199 12 : v_prevhash = LLVMBuildOr(b, v_tmp1, v_tmp2,
2200 : "rotatedhash");
2201 : }
2202 :
2203 : /* call the hash function */
2204 1506 : v_retval = BuildV1Call(context, b, mod, fcinfo,
2205 : &v_fcinfo_isnull);
2206 :
2207 : /*
2208 : * For NEXT32 ops, XOR (^) the returned hash value with
2209 : * the existing hash value.
2210 : */
2211 1506 : if (opcode == EEOP_HASHDATUM_NEXT32 ||
2212 : opcode == EEOP_HASHDATUM_NEXT32_STRICT)
2213 224 : v_retval = LLVMBuildXor(b, v_prevhash, v_retval,
2214 : "xorhash");
2215 :
2216 1506 : LLVMBuildStore(b, v_retval, v_resvaluep);
2217 1506 : LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
2218 :
2219 1506 : LLVMBuildBr(b, opblocks[opno + 1]);
2220 1506 : break;
2221 : }
2222 :
2223 54 : case EEOP_CONVERT_ROWTYPE:
2224 54 : build_EvalXFunc(b, mod, "ExecEvalConvertRowtype",
2225 : v_state, op, v_econtext);
2226 54 : LLVMBuildBr(b, opblocks[opno + 1]);
2227 54 : break;
2228 :
2229 50 : case EEOP_SCALARARRAYOP:
2230 50 : build_EvalXFunc(b, mod, "ExecEvalScalarArrayOp",
2231 : v_state, op);
2232 50 : LLVMBuildBr(b, opblocks[opno + 1]);
2233 50 : break;
2234 :
2235 0 : case EEOP_HASHED_SCALARARRAYOP:
2236 0 : build_EvalXFunc(b, mod, "ExecEvalHashedScalarArrayOp",
2237 : v_state, op, v_econtext);
2238 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2239 0 : break;
2240 :
2241 0 : case EEOP_XMLEXPR:
2242 0 : build_EvalXFunc(b, mod, "ExecEvalXmlExpr",
2243 : v_state, op);
2244 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2245 0 : break;
2246 :
2247 0 : case EEOP_JSON_CONSTRUCTOR:
2248 0 : build_EvalXFunc(b, mod, "ExecEvalJsonConstructor",
2249 : v_state, op, v_econtext);
2250 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2251 0 : break;
2252 :
2253 0 : case EEOP_IS_JSON:
2254 0 : build_EvalXFunc(b, mod, "ExecEvalJsonIsPredicate",
2255 : v_state, op);
2256 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2257 0 : break;
2258 :
2259 0 : case EEOP_JSONEXPR_PATH:
2260 : {
2261 0 : JsonExprState *jsestate = op->d.jsonexpr.jsestate;
2262 : LLVMValueRef v_ret;
2263 :
2264 : /*
2265 : * Call ExecEvalJsonExprPath(). It returns the address of
2266 : * the step to perform next.
2267 : */
2268 0 : v_ret = build_EvalXFunc(b, mod, "ExecEvalJsonExprPath",
2269 : v_state, op, v_econtext);
2270 :
2271 : /*
2272 : * Build a switch to map the return value (v_ret above),
2273 : * which is a runtime value of the step address to perform
2274 : * next, to either jump_empty, jump_error,
2275 : * jump_eval_coercion, or jump_end.
2276 : */
2277 0 : if (jsestate->jump_empty >= 0 ||
2278 0 : jsestate->jump_error >= 0 ||
2279 0 : jsestate->jump_eval_coercion >= 0)
2280 : {
2281 : LLVMValueRef v_jump_empty;
2282 : LLVMValueRef v_jump_error;
2283 : LLVMValueRef v_jump_coercion;
2284 : LLVMValueRef v_switch;
2285 : LLVMBasicBlockRef b_done,
2286 : b_empty,
2287 : b_error,
2288 : b_coercion;
2289 :
2290 : b_empty =
2291 0 : l_bb_before_v(opblocks[opno + 1],
2292 : "op.%d.jsonexpr_empty", opno);
2293 : b_error =
2294 0 : l_bb_before_v(opblocks[opno + 1],
2295 : "op.%d.jsonexpr_error", opno);
2296 : b_coercion =
2297 0 : l_bb_before_v(opblocks[opno + 1],
2298 : "op.%d.jsonexpr_coercion", opno);
2299 : b_done =
2300 0 : l_bb_before_v(opblocks[opno + 1],
2301 : "op.%d.jsonexpr_done", opno);
2302 :
2303 0 : v_switch = LLVMBuildSwitch(b,
2304 : v_ret,
2305 : b_done,
2306 : 3);
2307 : /* Returned jsestate->jump_empty? */
2308 0 : if (jsestate->jump_empty >= 0)
2309 : {
2310 0 : v_jump_empty = l_int32_const(lc, jsestate->jump_empty);
2311 0 : LLVMAddCase(v_switch, v_jump_empty, b_empty);
2312 : }
2313 : /* ON EMPTY code */
2314 0 : LLVMPositionBuilderAtEnd(b, b_empty);
2315 0 : if (jsestate->jump_empty >= 0)
2316 0 : LLVMBuildBr(b, opblocks[jsestate->jump_empty]);
2317 : else
2318 0 : LLVMBuildUnreachable(b);
2319 :
2320 : /* Returned jsestate->jump_error? */
2321 0 : if (jsestate->jump_error >= 0)
2322 : {
2323 0 : v_jump_error = l_int32_const(lc, jsestate->jump_error);
2324 0 : LLVMAddCase(v_switch, v_jump_error, b_error);
2325 : }
2326 : /* ON ERROR code */
2327 0 : LLVMPositionBuilderAtEnd(b, b_error);
2328 0 : if (jsestate->jump_error >= 0)
2329 0 : LLVMBuildBr(b, opblocks[jsestate->jump_error]);
2330 : else
2331 0 : LLVMBuildUnreachable(b);
2332 :
2333 : /* Returned jsestate->jump_eval_coercion? */
2334 0 : if (jsestate->jump_eval_coercion >= 0)
2335 : {
2336 0 : v_jump_coercion = l_int32_const(lc, jsestate->jump_eval_coercion);
2337 0 : LLVMAddCase(v_switch, v_jump_coercion, b_coercion);
2338 : }
2339 : /* jump_eval_coercion code */
2340 0 : LLVMPositionBuilderAtEnd(b, b_coercion);
2341 0 : if (jsestate->jump_eval_coercion >= 0)
2342 0 : LLVMBuildBr(b, opblocks[jsestate->jump_eval_coercion]);
2343 : else
2344 0 : LLVMBuildUnreachable(b);
2345 :
2346 0 : LLVMPositionBuilderAtEnd(b, b_done);
2347 : }
2348 :
2349 0 : LLVMBuildBr(b, opblocks[jsestate->jump_end]);
2350 0 : break;
2351 : }
2352 :
2353 0 : case EEOP_JSONEXPR_COERCION:
2354 0 : build_EvalXFunc(b, mod, "ExecEvalJsonCoercion",
2355 : v_state, op, v_econtext);
2356 :
2357 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2358 0 : break;
2359 :
2360 0 : case EEOP_JSONEXPR_COERCION_FINISH:
2361 0 : build_EvalXFunc(b, mod, "ExecEvalJsonCoercionFinish",
2362 : v_state, op);
2363 :
2364 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2365 0 : break;
2366 :
2367 364 : case EEOP_AGGREF:
2368 : {
2369 : LLVMValueRef v_aggno;
2370 : LLVMValueRef value,
2371 : isnull;
2372 :
2373 364 : v_aggno = l_int32_const(lc, op->d.aggref.aggno);
2374 :
2375 : /* load agg value / null */
2376 364 : value = l_load_gep1(b, TypeSizeT, v_aggvalues, v_aggno, "aggvalue");
2377 364 : isnull = l_load_gep1(b, TypeStorageBool, v_aggnulls, v_aggno, "aggnull");
2378 :
2379 : /* and store result */
2380 364 : LLVMBuildStore(b, value, v_resvaluep);
2381 364 : LLVMBuildStore(b, isnull, v_resnullp);
2382 :
2383 364 : LLVMBuildBr(b, opblocks[opno + 1]);
2384 364 : break;
2385 : }
2386 :
2387 72 : case EEOP_GROUPING_FUNC:
2388 72 : build_EvalXFunc(b, mod, "ExecEvalGroupingFunc",
2389 : v_state, op);
2390 72 : LLVMBuildBr(b, opblocks[opno + 1]);
2391 72 : break;
2392 :
2393 12 : case EEOP_WINDOW_FUNC:
2394 : {
2395 12 : WindowFuncExprState *wfunc = op->d.window_func.wfstate;
2396 : LLVMValueRef v_wfuncnop;
2397 : LLVMValueRef v_wfuncno;
2398 : LLVMValueRef value,
2399 : isnull;
2400 :
2401 : /*
2402 : * At this point aggref->wfuncno is not yet set (it's set
2403 : * up in ExecInitWindowAgg() after initializing the
2404 : * expression). So load it from memory each time round.
2405 : */
2406 12 : v_wfuncnop = l_ptr_const(&wfunc->wfuncno,
2407 : l_ptr(LLVMInt32TypeInContext(lc)));
2408 12 : v_wfuncno = l_load(b, LLVMInt32TypeInContext(lc), v_wfuncnop, "v_wfuncno");
2409 :
2410 : /* load window func value / null */
2411 12 : value = l_load_gep1(b, TypeSizeT, v_aggvalues, v_wfuncno,
2412 : "windowvalue");
2413 12 : isnull = l_load_gep1(b, TypeStorageBool, v_aggnulls, v_wfuncno,
2414 : "windownull");
2415 :
2416 12 : LLVMBuildStore(b, value, v_resvaluep);
2417 12 : LLVMBuildStore(b, isnull, v_resnullp);
2418 :
2419 12 : LLVMBuildBr(b, opblocks[opno + 1]);
2420 12 : break;
2421 : }
2422 :
2423 6 : case EEOP_MERGE_SUPPORT_FUNC:
2424 6 : build_EvalXFunc(b, mod, "ExecEvalMergeSupportFunc",
2425 : v_state, op, v_econtext);
2426 6 : LLVMBuildBr(b, opblocks[opno + 1]);
2427 6 : break;
2428 :
2429 532 : case EEOP_SUBPLAN:
2430 532 : build_EvalXFunc(b, mod, "ExecEvalSubPlan",
2431 : v_state, op, v_econtext);
2432 532 : LLVMBuildBr(b, opblocks[opno + 1]);
2433 532 : break;
2434 :
2435 0 : case EEOP_AGG_STRICT_DESERIALIZE:
2436 : case EEOP_AGG_DESERIALIZE:
2437 : {
2438 : AggState *aggstate;
2439 0 : FunctionCallInfo fcinfo = op->d.agg_deserialize.fcinfo_data;
2440 :
2441 : LLVMValueRef v_retval;
2442 : LLVMValueRef v_fcinfo_isnull;
2443 : LLVMValueRef v_tmpcontext;
2444 : LLVMValueRef v_oldcontext;
2445 :
2446 0 : if (opcode == EEOP_AGG_STRICT_DESERIALIZE)
2447 : {
2448 : LLVMValueRef v_fcinfo;
2449 : LLVMValueRef v_argnull0;
2450 : LLVMBasicBlockRef b_deserialize;
2451 :
2452 0 : b_deserialize = l_bb_before_v(opblocks[opno + 1],
2453 : "op.%d.deserialize", opno);
2454 :
2455 0 : v_fcinfo = l_ptr_const(fcinfo,
2456 : l_ptr(StructFunctionCallInfoData));
2457 0 : v_argnull0 = l_funcnull(b, v_fcinfo, 0);
2458 :
2459 0 : LLVMBuildCondBr(b,
2460 : LLVMBuildICmp(b,
2461 : LLVMIntEQ,
2462 : v_argnull0,
2463 : l_sbool_const(1),
2464 : ""),
2465 0 : opblocks[op->d.agg_deserialize.jumpnull],
2466 : b_deserialize);
2467 0 : LLVMPositionBuilderAtEnd(b, b_deserialize);
2468 : }
2469 :
2470 0 : aggstate = castNode(AggState, state->parent);
2471 0 : fcinfo = op->d.agg_deserialize.fcinfo_data;
2472 :
2473 : v_tmpcontext =
2474 0 : l_ptr_const(aggstate->tmpcontext->ecxt_per_tuple_memory,
2475 : l_ptr(StructMemoryContextData));
2476 0 : v_oldcontext = l_mcxt_switch(mod, b, v_tmpcontext);
2477 0 : v_retval = BuildV1Call(context, b, mod, fcinfo,
2478 : &v_fcinfo_isnull);
2479 0 : l_mcxt_switch(mod, b, v_oldcontext);
2480 :
2481 0 : LLVMBuildStore(b, v_retval, v_resvaluep);
2482 0 : LLVMBuildStore(b, v_fcinfo_isnull, v_resnullp);
2483 :
2484 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2485 0 : break;
2486 : }
2487 :
2488 66 : case EEOP_AGG_STRICT_INPUT_CHECK_ARGS:
2489 : case EEOP_AGG_STRICT_INPUT_CHECK_ARGS_1:
2490 : case EEOP_AGG_STRICT_INPUT_CHECK_NULLS:
2491 : {
2492 66 : int nargs = op->d.agg_strict_input_check.nargs;
2493 66 : NullableDatum *args = op->d.agg_strict_input_check.args;
2494 66 : bool *nulls = op->d.agg_strict_input_check.nulls;
2495 : int jumpnull;
2496 :
2497 : LLVMValueRef v_argsp;
2498 : LLVMValueRef v_nullsp;
2499 : LLVMBasicBlockRef *b_checknulls;
2500 :
2501 : Assert(nargs > 0);
2502 :
2503 66 : jumpnull = op->d.agg_strict_input_check.jumpnull;
2504 66 : v_argsp = l_ptr_const(args, l_ptr(StructNullableDatum));
2505 66 : v_nullsp = l_ptr_const(nulls, l_ptr(TypeStorageBool));
2506 :
2507 : /* create blocks for checking args */
2508 66 : b_checknulls = palloc(sizeof(LLVMBasicBlockRef *) * nargs);
2509 132 : for (int argno = 0; argno < nargs; argno++)
2510 : {
2511 66 : b_checknulls[argno] =
2512 66 : l_bb_before_v(opblocks[opno + 1],
2513 : "op.%d.check-null.%d",
2514 : opno, argno);
2515 : }
2516 :
2517 66 : LLVMBuildBr(b, b_checknulls[0]);
2518 :
2519 : /* strict function, check for NULL args */
2520 132 : for (int argno = 0; argno < nargs; argno++)
2521 : {
2522 66 : LLVMValueRef v_argno = l_int32_const(lc, argno);
2523 : LLVMValueRef v_argisnull;
2524 : LLVMBasicBlockRef b_argnotnull;
2525 :
2526 66 : LLVMPositionBuilderAtEnd(b, b_checknulls[argno]);
2527 :
2528 66 : if (argno + 1 == nargs)
2529 66 : b_argnotnull = opblocks[opno + 1];
2530 : else
2531 0 : b_argnotnull = b_checknulls[argno + 1];
2532 :
2533 66 : if (opcode == EEOP_AGG_STRICT_INPUT_CHECK_NULLS)
2534 0 : v_argisnull = l_load_gep1(b, TypeStorageBool, v_nullsp, v_argno, "");
2535 : else
2536 : {
2537 : LLVMValueRef v_argn;
2538 :
2539 66 : v_argn = l_gep(b, StructNullableDatum, v_argsp, &v_argno, 1, "");
2540 : v_argisnull =
2541 66 : l_load_struct_gep(b, StructNullableDatum, v_argn,
2542 : FIELDNO_NULLABLE_DATUM_ISNULL,
2543 : "");
2544 : }
2545 :
2546 66 : LLVMBuildCondBr(b,
2547 : LLVMBuildICmp(b,
2548 : LLVMIntEQ,
2549 : v_argisnull,
2550 : l_sbool_const(1), ""),
2551 66 : opblocks[jumpnull],
2552 : b_argnotnull);
2553 : }
2554 :
2555 66 : break;
2556 : }
2557 :
2558 318 : case EEOP_AGG_PLAIN_PERGROUP_NULLCHECK:
2559 : {
2560 : int jumpnull;
2561 : LLVMValueRef v_aggstatep;
2562 : LLVMValueRef v_allpergroupsp;
2563 : LLVMValueRef v_pergroup_allaggs;
2564 : LLVMValueRef v_setoff;
2565 :
2566 318 : jumpnull = op->d.agg_plain_pergroup_nullcheck.jumpnull;
2567 :
2568 : /*
2569 : * pergroup_allaggs = aggstate->all_pergroups
2570 : * [op->d.agg_plain_pergroup_nullcheck.setoff];
2571 : */
2572 318 : v_aggstatep = LLVMBuildBitCast(b, v_parent,
2573 : l_ptr(StructAggState), "");
2574 :
2575 318 : v_allpergroupsp = l_load_struct_gep(b,
2576 : StructAggState,
2577 : v_aggstatep,
2578 : FIELDNO_AGGSTATE_ALL_PERGROUPS,
2579 : "aggstate.all_pergroups");
2580 :
2581 318 : v_setoff = l_int32_const(lc, op->d.agg_plain_pergroup_nullcheck.setoff);
2582 :
2583 318 : v_pergroup_allaggs = l_load_gep1(b, l_ptr(StructAggStatePerGroupData),
2584 : v_allpergroupsp, v_setoff, "");
2585 :
2586 318 : LLVMBuildCondBr(b,
2587 : LLVMBuildICmp(b, LLVMIntEQ,
2588 : LLVMBuildPtrToInt(b, v_pergroup_allaggs, TypeSizeT, ""),
2589 : l_sizet_const(0), ""),
2590 318 : opblocks[jumpnull],
2591 318 : opblocks[opno + 1]);
2592 318 : break;
2593 : }
2594 :
2595 1198 : case EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL:
2596 : case EEOP_AGG_PLAIN_TRANS_STRICT_BYVAL:
2597 : case EEOP_AGG_PLAIN_TRANS_BYVAL:
2598 : case EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF:
2599 : case EEOP_AGG_PLAIN_TRANS_STRICT_BYREF:
2600 : case EEOP_AGG_PLAIN_TRANS_BYREF:
2601 : {
2602 : AggState *aggstate;
2603 : AggStatePerTrans pertrans;
2604 : FunctionCallInfo fcinfo;
2605 :
2606 : LLVMValueRef v_aggstatep;
2607 : LLVMValueRef v_fcinfo;
2608 : LLVMValueRef v_fcinfo_isnull;
2609 :
2610 : LLVMValueRef v_transvaluep;
2611 : LLVMValueRef v_transnullp;
2612 :
2613 : LLVMValueRef v_setoff;
2614 : LLVMValueRef v_transno;
2615 :
2616 : LLVMValueRef v_aggcontext;
2617 :
2618 : LLVMValueRef v_allpergroupsp;
2619 : LLVMValueRef v_current_setp;
2620 : LLVMValueRef v_current_pertransp;
2621 : LLVMValueRef v_curaggcontext;
2622 :
2623 : LLVMValueRef v_pertransp;
2624 :
2625 : LLVMValueRef v_pergroupp;
2626 :
2627 : LLVMValueRef v_retval;
2628 :
2629 : LLVMValueRef v_tmpcontext;
2630 : LLVMValueRef v_oldcontext;
2631 :
2632 1198 : aggstate = castNode(AggState, state->parent);
2633 1198 : pertrans = op->d.agg_trans.pertrans;
2634 :
2635 1198 : fcinfo = pertrans->transfn_fcinfo;
2636 :
2637 : v_aggstatep =
2638 1198 : LLVMBuildBitCast(b, v_parent, l_ptr(StructAggState), "");
2639 1198 : v_pertransp = l_ptr_const(pertrans,
2640 : l_ptr(StructAggStatePerTransData));
2641 :
2642 : /*
2643 : * pergroup = &aggstate->all_pergroups
2644 : * [op->d.agg_trans.setoff] [op->d.agg_trans.transno];
2645 : */
2646 : v_allpergroupsp =
2647 1198 : l_load_struct_gep(b,
2648 : StructAggState,
2649 : v_aggstatep,
2650 : FIELDNO_AGGSTATE_ALL_PERGROUPS,
2651 : "aggstate.all_pergroups");
2652 1198 : v_setoff = l_int32_const(lc, op->d.agg_trans.setoff);
2653 1198 : v_transno = l_int32_const(lc, op->d.agg_trans.transno);
2654 : v_pergroupp =
2655 1198 : l_gep(b,
2656 : StructAggStatePerGroupData,
2657 : l_load_gep1(b, l_ptr(StructAggStatePerGroupData),
2658 : v_allpergroupsp, v_setoff, ""),
2659 : &v_transno, 1, "");
2660 :
2661 :
2662 1198 : if (opcode == EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL ||
2663 : opcode == EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF)
2664 : {
2665 : LLVMValueRef v_notransvalue;
2666 : LLVMBasicBlockRef b_init;
2667 : LLVMBasicBlockRef b_no_init;
2668 :
2669 : v_notransvalue =
2670 288 : l_load_struct_gep(b,
2671 : StructAggStatePerGroupData,
2672 : v_pergroupp,
2673 : FIELDNO_AGGSTATEPERGROUPDATA_NOTRANSVALUE,
2674 : "notransvalue");
2675 :
2676 288 : b_init = l_bb_before_v(opblocks[opno + 1],
2677 : "op.%d.inittrans", opno);
2678 288 : b_no_init = l_bb_before_v(opblocks[opno + 1],
2679 : "op.%d.no_inittrans", opno);
2680 :
2681 288 : LLVMBuildCondBr(b,
2682 : LLVMBuildICmp(b, LLVMIntEQ, v_notransvalue,
2683 : l_sbool_const(1), ""),
2684 : b_init,
2685 : b_no_init);
2686 :
2687 : /* block to init the transition value if necessary */
2688 : {
2689 : LLVMValueRef params[4];
2690 :
2691 288 : LLVMPositionBuilderAtEnd(b, b_init);
2692 :
2693 288 : v_aggcontext = l_ptr_const(op->d.agg_trans.aggcontext,
2694 : l_ptr(StructExprContext));
2695 :
2696 288 : params[0] = v_aggstatep;
2697 288 : params[1] = v_pertransp;
2698 288 : params[2] = v_pergroupp;
2699 288 : params[3] = v_aggcontext;
2700 :
2701 288 : l_call(b,
2702 : llvm_pg_var_func_type("ExecAggInitGroup"),
2703 : llvm_pg_func(mod, "ExecAggInitGroup"),
2704 : params, lengthof(params),
2705 : "");
2706 :
2707 288 : LLVMBuildBr(b, opblocks[opno + 1]);
2708 : }
2709 :
2710 288 : LLVMPositionBuilderAtEnd(b, b_no_init);
2711 : }
2712 :
2713 1198 : if (opcode == EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL ||
2714 910 : opcode == EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF ||
2715 396 : opcode == EEOP_AGG_PLAIN_TRANS_STRICT_BYVAL ||
2716 : opcode == EEOP_AGG_PLAIN_TRANS_STRICT_BYREF)
2717 : {
2718 : LLVMValueRef v_transnull;
2719 : LLVMBasicBlockRef b_strictpass;
2720 :
2721 802 : b_strictpass = l_bb_before_v(opblocks[opno + 1],
2722 : "op.%d.strictpass", opno);
2723 : v_transnull =
2724 802 : l_load_struct_gep(b,
2725 : StructAggStatePerGroupData,
2726 : v_pergroupp,
2727 : FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL,
2728 : "transnull");
2729 :
2730 802 : LLVMBuildCondBr(b,
2731 : LLVMBuildICmp(b, LLVMIntEQ, v_transnull,
2732 : l_sbool_const(1), ""),
2733 802 : opblocks[opno + 1],
2734 : b_strictpass);
2735 :
2736 802 : LLVMPositionBuilderAtEnd(b, b_strictpass);
2737 : }
2738 :
2739 :
2740 1198 : v_fcinfo = l_ptr_const(fcinfo,
2741 : l_ptr(StructFunctionCallInfoData));
2742 1198 : v_aggcontext = l_ptr_const(op->d.agg_trans.aggcontext,
2743 : l_ptr(StructExprContext));
2744 :
2745 : v_current_setp =
2746 1198 : l_struct_gep(b,
2747 : StructAggState,
2748 : v_aggstatep,
2749 : FIELDNO_AGGSTATE_CURRENT_SET,
2750 : "aggstate.current_set");
2751 : v_curaggcontext =
2752 1198 : l_struct_gep(b,
2753 : StructAggState,
2754 : v_aggstatep,
2755 : FIELDNO_AGGSTATE_CURAGGCONTEXT,
2756 : "aggstate.curaggcontext");
2757 : v_current_pertransp =
2758 1198 : l_struct_gep(b,
2759 : StructAggState,
2760 : v_aggstatep,
2761 : FIELDNO_AGGSTATE_CURPERTRANS,
2762 : "aggstate.curpertrans");
2763 :
2764 : /* set aggstate globals */
2765 1198 : LLVMBuildStore(b, v_aggcontext, v_curaggcontext);
2766 1198 : LLVMBuildStore(b, l_int32_const(lc, op->d.agg_trans.setno),
2767 : v_current_setp);
2768 1198 : LLVMBuildStore(b, v_pertransp, v_current_pertransp);
2769 :
2770 : /* invoke transition function in per-tuple context */
2771 : v_tmpcontext =
2772 1198 : l_ptr_const(aggstate->tmpcontext->ecxt_per_tuple_memory,
2773 : l_ptr(StructMemoryContextData));
2774 1198 : v_oldcontext = l_mcxt_switch(mod, b, v_tmpcontext);
2775 :
2776 : /* store transvalue in fcinfo->args[0] */
2777 : v_transvaluep =
2778 1198 : l_struct_gep(b,
2779 : StructAggStatePerGroupData,
2780 : v_pergroupp,
2781 : FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUE,
2782 : "transvalue");
2783 : v_transnullp =
2784 1198 : l_struct_gep(b,
2785 : StructAggStatePerGroupData,
2786 : v_pergroupp,
2787 : FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL,
2788 : "transnullp");
2789 1198 : LLVMBuildStore(b,
2790 : l_load(b,
2791 : TypeSizeT,
2792 : v_transvaluep,
2793 : "transvalue"),
2794 : l_funcvaluep(b, v_fcinfo, 0));
2795 1198 : LLVMBuildStore(b,
2796 : l_load(b, TypeStorageBool, v_transnullp, "transnull"),
2797 : l_funcnullp(b, v_fcinfo, 0));
2798 :
2799 : /* and invoke transition function */
2800 1198 : v_retval = BuildV1Call(context, b, mod, fcinfo,
2801 : &v_fcinfo_isnull);
2802 :
2803 : /*
2804 : * For pass-by-ref datatype, must copy the new value into
2805 : * aggcontext and free the prior transValue. But if
2806 : * transfn returned a pointer to its first input, we don't
2807 : * need to do anything. Also, if transfn returned a
2808 : * pointer to a R/W expanded object that is already a
2809 : * child of the aggcontext, assume we can adopt that value
2810 : * without copying it.
2811 : */
2812 1198 : if (opcode == EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF ||
2813 916 : opcode == EEOP_AGG_PLAIN_TRANS_STRICT_BYREF ||
2814 : opcode == EEOP_AGG_PLAIN_TRANS_BYREF)
2815 : {
2816 : LLVMBasicBlockRef b_call;
2817 : LLVMBasicBlockRef b_nocall;
2818 : LLVMValueRef v_fn;
2819 : LLVMValueRef v_transvalue;
2820 : LLVMValueRef v_transnull;
2821 : LLVMValueRef v_newval;
2822 : LLVMValueRef params[6];
2823 :
2824 282 : b_call = l_bb_before_v(opblocks[opno + 1],
2825 : "op.%d.transcall", opno);
2826 282 : b_nocall = l_bb_before_v(opblocks[opno + 1],
2827 : "op.%d.transnocall", opno);
2828 :
2829 282 : v_transvalue = l_load(b, TypeSizeT, v_transvaluep, "");
2830 282 : v_transnull = l_load(b, TypeStorageBool, v_transnullp, "");
2831 :
2832 : /*
2833 : * DatumGetPointer(newVal) !=
2834 : * DatumGetPointer(pergroup->transValue))
2835 : */
2836 282 : LLVMBuildCondBr(b,
2837 : LLVMBuildICmp(b, LLVMIntEQ,
2838 : v_transvalue,
2839 : v_retval, ""),
2840 : b_nocall, b_call);
2841 :
2842 : /* returned datum not passed datum, reparent */
2843 282 : LLVMPositionBuilderAtEnd(b, b_call);
2844 :
2845 282 : params[0] = v_aggstatep;
2846 282 : params[1] = v_pertransp;
2847 282 : params[2] = v_retval;
2848 282 : params[3] = LLVMBuildTrunc(b, v_fcinfo_isnull,
2849 : TypeParamBool, "");
2850 282 : params[4] = v_transvalue;
2851 282 : params[5] = LLVMBuildTrunc(b, v_transnull,
2852 : TypeParamBool, "");
2853 :
2854 282 : v_fn = llvm_pg_func(mod, "ExecAggCopyTransValue");
2855 : v_newval =
2856 282 : l_call(b,
2857 : LLVMGetFunctionType(v_fn),
2858 : v_fn,
2859 : params, lengthof(params),
2860 : "");
2861 :
2862 : /* store trans value */
2863 282 : LLVMBuildStore(b, v_newval, v_transvaluep);
2864 282 : LLVMBuildStore(b, v_fcinfo_isnull, v_transnullp);
2865 :
2866 282 : l_mcxt_switch(mod, b, v_oldcontext);
2867 282 : LLVMBuildBr(b, opblocks[opno + 1]);
2868 :
2869 : /* returned datum passed datum, no need to reparent */
2870 282 : LLVMPositionBuilderAtEnd(b, b_nocall);
2871 : }
2872 :
2873 : /* store trans value */
2874 1198 : LLVMBuildStore(b, v_retval, v_transvaluep);
2875 1198 : LLVMBuildStore(b, v_fcinfo_isnull, v_transnullp);
2876 :
2877 1198 : l_mcxt_switch(mod, b, v_oldcontext);
2878 :
2879 1198 : LLVMBuildBr(b, opblocks[opno + 1]);
2880 1198 : break;
2881 : }
2882 :
2883 0 : case EEOP_AGG_PRESORTED_DISTINCT_SINGLE:
2884 : {
2885 0 : AggState *aggstate = castNode(AggState, state->parent);
2886 0 : AggStatePerTrans pertrans = op->d.agg_presorted_distinctcheck.pertrans;
2887 0 : int jumpdistinct = op->d.agg_presorted_distinctcheck.jumpdistinct;
2888 :
2889 0 : LLVMValueRef v_fn = llvm_pg_func(mod, "ExecEvalPreOrderedDistinctSingle");
2890 : LLVMValueRef v_args[2];
2891 : LLVMValueRef v_ret;
2892 :
2893 0 : v_args[0] = l_ptr_const(aggstate, l_ptr(StructAggState));
2894 0 : v_args[1] = l_ptr_const(pertrans, l_ptr(StructAggStatePerTransData));
2895 :
2896 0 : v_ret = l_call(b, LLVMGetFunctionType(v_fn), v_fn, v_args, 2, "");
2897 0 : v_ret = LLVMBuildZExt(b, v_ret, TypeStorageBool, "");
2898 :
2899 0 : LLVMBuildCondBr(b,
2900 : LLVMBuildICmp(b, LLVMIntEQ, v_ret,
2901 : l_sbool_const(1), ""),
2902 0 : opblocks[opno + 1],
2903 0 : opblocks[jumpdistinct]);
2904 0 : break;
2905 : }
2906 :
2907 0 : case EEOP_AGG_PRESORTED_DISTINCT_MULTI:
2908 : {
2909 0 : AggState *aggstate = castNode(AggState, state->parent);
2910 0 : AggStatePerTrans pertrans = op->d.agg_presorted_distinctcheck.pertrans;
2911 0 : int jumpdistinct = op->d.agg_presorted_distinctcheck.jumpdistinct;
2912 :
2913 0 : LLVMValueRef v_fn = llvm_pg_func(mod, "ExecEvalPreOrderedDistinctMulti");
2914 : LLVMValueRef v_args[2];
2915 : LLVMValueRef v_ret;
2916 :
2917 0 : v_args[0] = l_ptr_const(aggstate, l_ptr(StructAggState));
2918 0 : v_args[1] = l_ptr_const(pertrans, l_ptr(StructAggStatePerTransData));
2919 :
2920 0 : v_ret = l_call(b, LLVMGetFunctionType(v_fn), v_fn, v_args, 2, "");
2921 0 : v_ret = LLVMBuildZExt(b, v_ret, TypeStorageBool, "");
2922 :
2923 0 : LLVMBuildCondBr(b,
2924 : LLVMBuildICmp(b, LLVMIntEQ, v_ret,
2925 : l_sbool_const(1), ""),
2926 0 : opblocks[opno + 1],
2927 0 : opblocks[jumpdistinct]);
2928 0 : break;
2929 : }
2930 :
2931 0 : case EEOP_AGG_ORDERED_TRANS_DATUM:
2932 0 : build_EvalXFunc(b, mod, "ExecEvalAggOrderedTransDatum",
2933 : v_state, op, v_econtext);
2934 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2935 0 : break;
2936 :
2937 0 : case EEOP_AGG_ORDERED_TRANS_TUPLE:
2938 0 : build_EvalXFunc(b, mod, "ExecEvalAggOrderedTransTuple",
2939 : v_state, op, v_econtext);
2940 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2941 0 : break;
2942 :
2943 0 : case EEOP_LAST:
2944 : Assert(false);
2945 0 : break;
2946 : }
2947 47788 : }
2948 :
2949 9078 : LLVMDisposeBuilder(b);
2950 :
2951 : /*
2952 : * Don't immediately emit function, instead do so the first time the
2953 : * expression is actually evaluated. That allows to emit a lot of
2954 : * functions together, avoiding a lot of repeated llvm and memory
2955 : * remapping overhead.
2956 : */
2957 : {
2958 :
2959 9078 : CompiledExprState *cstate = palloc0(sizeof(CompiledExprState));
2960 :
2961 9078 : cstate->context = context;
2962 9078 : cstate->funcname = funcname;
2963 :
2964 9078 : state->evalfunc = ExecRunCompiledExpr;
2965 9078 : state->evalfunc_private = cstate;
2966 : }
2967 :
2968 9078 : llvm_leave_fatal_on_oom();
2969 :
2970 9078 : INSTR_TIME_SET_CURRENT(endtime);
2971 9078 : INSTR_TIME_ACCUM_DIFF(context->base.instr.generation_counter,
2972 : endtime, starttime);
2973 :
2974 9078 : return true;
2975 : }
2976 :
2977 : /*
2978 : * Run compiled expression.
2979 : *
2980 : * This will only be called the first time a JITed expression is called. We
2981 : * first make sure the expression is still up-to-date, and then get a pointer to
2982 : * the emitted function. The latter can be the first thing that triggers
2983 : * optimizing and emitting all the generated functions.
2984 : */
2985 : static Datum
2986 5482 : ExecRunCompiledExpr(ExprState *state, ExprContext *econtext, bool *isNull)
2987 : {
2988 5482 : CompiledExprState *cstate = state->evalfunc_private;
2989 : ExprStateEvalFunc func;
2990 :
2991 5482 : CheckExprStillValid(state, econtext);
2992 :
2993 5482 : llvm_enter_fatal_on_oom();
2994 5482 : func = (ExprStateEvalFunc) llvm_get_function(cstate->context,
2995 : cstate->funcname);
2996 5482 : llvm_leave_fatal_on_oom();
2997 : Assert(func);
2998 :
2999 : /* remove indirection via this function for future calls */
3000 5482 : state->evalfunc = func;
3001 :
3002 5482 : return func(state, econtext, isNull);
3003 : }
3004 :
3005 : static LLVMValueRef
3006 6350 : BuildV1Call(LLVMJitContext *context, LLVMBuilderRef b,
3007 : LLVMModuleRef mod, FunctionCallInfo fcinfo,
3008 : LLVMValueRef *v_fcinfo_isnull)
3009 : {
3010 : LLVMContextRef lc;
3011 : LLVMValueRef v_fn;
3012 : LLVMValueRef v_fcinfo_isnullp;
3013 : LLVMValueRef v_retval;
3014 : LLVMValueRef v_fcinfo;
3015 :
3016 6350 : lc = LLVMGetModuleContext(mod);
3017 :
3018 6350 : v_fn = llvm_function_reference(context, b, mod, fcinfo);
3019 :
3020 6350 : v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
3021 6350 : v_fcinfo_isnullp = l_struct_gep(b,
3022 : StructFunctionCallInfoData,
3023 : v_fcinfo,
3024 : FIELDNO_FUNCTIONCALLINFODATA_ISNULL,
3025 : "v_fcinfo_isnull");
3026 6350 : LLVMBuildStore(b, l_sbool_const(0), v_fcinfo_isnullp);
3027 :
3028 6350 : v_retval = l_call(b, LLVMGetFunctionType(AttributeTemplate), v_fn, &v_fcinfo, 1, "funccall");
3029 :
3030 6350 : if (v_fcinfo_isnull)
3031 6350 : *v_fcinfo_isnull = l_load(b, TypeStorageBool, v_fcinfo_isnullp, "");
3032 :
3033 : /*
3034 : * Add lifetime-end annotation, signaling that writes to memory don't have
3035 : * to be retained (important for inlining potential).
3036 : */
3037 : {
3038 6350 : LLVMValueRef v_lifetime = create_LifetimeEnd(mod);
3039 : LLVMValueRef params[2];
3040 :
3041 6350 : params[0] = l_int64_const(lc, sizeof(NullableDatum) * fcinfo->nargs);
3042 6350 : params[1] = l_ptr_const(fcinfo->args, l_ptr(LLVMInt8TypeInContext(lc)));
3043 6350 : l_call(b, LLVMGetFunctionType(v_lifetime), v_lifetime, params, lengthof(params), "");
3044 :
3045 6350 : params[0] = l_int64_const(lc, sizeof(fcinfo->isnull));
3046 6350 : params[1] = l_ptr_const(&fcinfo->isnull, l_ptr(LLVMInt8TypeInContext(lc)));
3047 6350 : l_call(b, LLVMGetFunctionType(v_lifetime), v_lifetime, params, lengthof(params), "");
3048 : }
3049 :
3050 6350 : return v_retval;
3051 : }
3052 :
3053 : /*
3054 : * Implement an expression step by calling the function funcname.
3055 : */
3056 : static LLVMValueRef
3057 3636 : build_EvalXFuncInt(LLVMBuilderRef b, LLVMModuleRef mod, const char *funcname,
3058 : LLVMValueRef v_state, ExprEvalStep *op,
3059 : int nargs, LLVMValueRef *v_args)
3060 : {
3061 3636 : LLVMValueRef v_fn = llvm_pg_func(mod, funcname);
3062 : LLVMValueRef *params;
3063 3636 : int argno = 0;
3064 : LLVMValueRef v_ret;
3065 :
3066 : /* cheap pre-check as llvm just asserts out */
3067 3636 : if (LLVMCountParams(v_fn) != (nargs + 2))
3068 0 : elog(ERROR, "parameter mismatch: %s expects %d passed %d",
3069 : funcname, LLVMCountParams(v_fn), nargs + 2);
3070 :
3071 3636 : params = palloc(sizeof(LLVMValueRef) * (2 + nargs));
3072 :
3073 3636 : params[argno++] = v_state;
3074 3636 : params[argno++] = l_ptr_const(op, l_ptr(StructExprEvalStep));
3075 :
3076 7432 : for (int i = 0; i < nargs; i++)
3077 3796 : params[argno++] = v_args[i];
3078 :
3079 3636 : v_ret = l_call(b, LLVMGetFunctionType(v_fn), v_fn, params, argno, "");
3080 :
3081 3636 : pfree(params);
3082 :
3083 3636 : return v_ret;
3084 : }
3085 :
3086 : static LLVMValueRef
3087 6350 : create_LifetimeEnd(LLVMModuleRef mod)
3088 : {
3089 : LLVMTypeRef sig;
3090 : LLVMValueRef fn;
3091 : LLVMTypeRef param_types[2];
3092 : LLVMContextRef lc;
3093 :
3094 : /* variadic pointer argument */
3095 6350 : const char *nm = "llvm.lifetime.end.p0";
3096 :
3097 6350 : fn = LLVMGetNamedFunction(mod, nm);
3098 6350 : if (fn)
3099 5248 : return fn;
3100 :
3101 1102 : lc = LLVMGetModuleContext(mod);
3102 1102 : param_types[0] = LLVMInt64TypeInContext(lc);
3103 1102 : param_types[1] = l_ptr(LLVMInt8TypeInContext(lc));
3104 :
3105 1102 : sig = LLVMFunctionType(LLVMVoidTypeInContext(lc), param_types,
3106 : lengthof(param_types), false);
3107 1102 : fn = LLVMAddFunction(mod, nm, sig);
3108 :
3109 1102 : LLVMSetFunctionCallConv(fn, LLVMCCallConv);
3110 :
3111 : Assert(LLVMGetIntrinsicID(fn));
3112 :
3113 1102 : return fn;
3114 : }
|