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