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