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