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