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