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