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