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