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