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 mode, NULL inputs result in NULL. Save
2115 : : * the NULL to the ExprState's resnull/resvalue fields
2116 : : * directly, then goto jumpdone.
2117 : : */
2118 : 0 : LLVMBuildStore(b, l_sbool_const(1), v_tmpisnullp);
2119 : 0 : LLVMBuildStore(b, l_datum_const(0), v_tmpvaluep);
2120 : 0 : LLVMBuildBr(b, opblocks[op->d.hashdatum.jumpdone]);
2121 : : }
2122 : : else
2123 : : {
2124 : 0 : b_ifnullblock = l_bb_before_v(b_ifnotnull,
2125 : : "b.%d.null",
2126 : : opno);
2127 : :
2128 : 0 : LLVMPositionBuilderAtEnd(b, b_ifnullblock);
2129 : :
2130 : :
2131 : 0 : LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
2132 : :
2133 [ # # ]: 0 : if (opcode == EEOP_HASHDATUM_NEXT32)
2134 : : {
2135 : : Assert(v_prevhash != NULL);
2136 : :
2137 : : /*
2138 : : * Save the rotated hash value and skip to the
2139 : : * next op.
2140 : : */
2141 : 0 : LLVMBuildStore(b, v_prevhash, v_resvaluep);
2142 : : }
2143 : : else
2144 : : {
2145 : : Assert(opcode == EEOP_HASHDATUM_FIRST);
2146 : :
2147 : : /*
2148 : : * Store a zero Datum when the Datum to hash is
2149 : : * NULL
2150 : : */
2151 : 0 : LLVMBuildStore(b, l_datum_const(0), v_resvaluep);
2152 : : }
2153 : :
2154 : 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2155 : : }
2156 : :
2157 : 0 : LLVMPositionBuilderAtEnd(b, b_checkargnull);
2158 : :
2159 : : /* emit code to check if the input parameter is NULL */
2160 : 0 : v_argisnull = l_funcnull(b, v_fcinfo, 0);
2161 : 0 : LLVMBuildCondBr(b,
2162 : : LLVMBuildICmp(b,
2163 : : LLVMIntEQ,
2164 : : v_argisnull,
2165 : : l_sbool_const(1),
2166 : : ""),
2167 : : b_ifnullblock,
2168 : : b_ifnotnull);
2169 : :
2170 : 0 : LLVMPositionBuilderAtEnd(b, b_ifnotnull);
2171 : :
2172 : : /*
2173 : : * Rotate the previously stored hash value when performing
2174 : : * NEXT32 in strict mode. In non-strict mode we already
2175 : : * did this before checking for NULLs.
2176 : : */
2177 [ # # ]: 0 : if (opcode == EEOP_HASHDATUM_NEXT32_STRICT)
2178 : : {
2179 : : LLVMValueRef v_tmp1;
2180 : : LLVMValueRef v_tmp2;
2181 : : LLVMValueRef tmp;
2182 : :
2183 : 0 : tmp = l_ptr_const(&op->d.hashdatum.iresult->value,
2184 : : l_ptr(TypeDatum));
2185 : :
2186 : : /*
2187 : : * Fetch the previously hashed value from where the
2188 : : * previous hash operation stored it.
2189 : : */
2190 : 0 : v_prevhash = l_load(b, TypeDatum, tmp, "prevhash");
2191 : :
2192 : : /*
2193 : : * Rotate bits left by 1 bit. Be careful not to
2194 : : * overflow uint32 when working with Datum.
2195 : : */
2196 : 0 : v_tmp1 = LLVMBuildShl(b, v_prevhash, l_datum_const(1),
2197 : : "");
2198 : 0 : v_tmp1 = LLVMBuildAnd(b, v_tmp1,
2199 : : l_datum_const(0xffffffff), "");
2200 : 0 : v_tmp2 = LLVMBuildLShr(b, v_prevhash,
2201 : : l_datum_const(31), "");
2202 : 0 : v_prevhash = LLVMBuildOr(b, v_tmp1, v_tmp2,
2203 : : "rotatedhash");
2204 : : }
2205 : :
2206 : : /* call the hash function */
2207 : 0 : v_retval = BuildV1Call(context, b, mod, fcinfo,
2208 : : &v_fcinfo_isnull);
2209 : :
2210 : : /*
2211 : : * For NEXT32 ops, XOR (^) the returned hash value with
2212 : : * the existing hash value.
2213 : : */
2214 [ # # # # ]: 0 : if (opcode == EEOP_HASHDATUM_NEXT32 ||
2215 : : opcode == EEOP_HASHDATUM_NEXT32_STRICT)
2216 : 0 : v_retval = LLVMBuildXor(b, v_prevhash, v_retval,
2217 : : "xorhash");
2218 : :
2219 : 0 : LLVMBuildStore(b, v_retval, v_resvaluep);
2220 : 0 : LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
2221 : :
2222 : 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2223 : 0 : break;
2224 : : }
2225 : :
2226 : 0 : case EEOP_CONVERT_ROWTYPE:
2227 : 0 : build_EvalXFunc(b, mod, "ExecEvalConvertRowtype",
2228 : : v_state, op, v_econtext);
2229 : 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2230 : 0 : break;
2231 : :
2232 : 0 : case EEOP_SCALARARRAYOP:
2233 : 0 : build_EvalXFunc(b, mod, "ExecEvalScalarArrayOp",
2234 : : v_state, op);
2235 : 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2236 : 0 : break;
2237 : :
2238 : 0 : case EEOP_HASHED_SCALARARRAYOP:
2239 : 0 : build_EvalXFunc(b, mod, "ExecEvalHashedScalarArrayOp",
2240 : : v_state, op, v_econtext);
2241 : 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2242 : 0 : break;
2243 : :
2244 : 0 : case EEOP_XMLEXPR:
2245 : 0 : build_EvalXFunc(b, mod, "ExecEvalXmlExpr",
2246 : : v_state, op);
2247 : 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2248 : 0 : break;
2249 : :
2250 : 0 : case EEOP_JSON_CONSTRUCTOR:
2251 : 0 : build_EvalXFunc(b, mod, "ExecEvalJsonConstructor",
2252 : : v_state, op, v_econtext);
2253 : 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2254 : 0 : break;
2255 : :
2256 : 0 : case EEOP_IS_JSON:
2257 : 0 : build_EvalXFunc(b, mod, "ExecEvalJsonIsPredicate",
2258 : : v_state, op);
2259 : 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2260 : 0 : break;
2261 : :
2262 : 0 : case EEOP_JSONEXPR_PATH:
2263 : : {
2264 : 0 : JsonExprState *jsestate = op->d.jsonexpr.jsestate;
2265 : : LLVMValueRef v_ret;
2266 : :
2267 : : /*
2268 : : * Call ExecEvalJsonExprPath(). It returns the address of
2269 : : * the step to perform next.
2270 : : */
2271 : 0 : v_ret = build_EvalXFunc(b, mod, "ExecEvalJsonExprPath",
2272 : : v_state, op, v_econtext);
2273 : :
2274 : : /*
2275 : : * Build a switch to map the return value (v_ret above),
2276 : : * which is a runtime value of the step address to perform
2277 : : * next, to either jump_empty, jump_error,
2278 : : * jump_eval_coercion, or jump_end.
2279 : : */
2280 [ # # ]: 0 : if (jsestate->jump_empty >= 0 ||
2281 [ # # ]: 0 : jsestate->jump_error >= 0 ||
2282 [ # # ]: 0 : jsestate->jump_eval_coercion >= 0)
2283 : : {
2284 : : LLVMValueRef v_jump_empty;
2285 : : LLVMValueRef v_jump_error;
2286 : : LLVMValueRef v_jump_coercion;
2287 : : LLVMValueRef v_switch;
2288 : : LLVMBasicBlockRef b_done,
2289 : : b_empty,
2290 : : b_error,
2291 : : b_coercion;
2292 : :
2293 : : b_empty =
2294 : 0 : l_bb_before_v(opblocks[opno + 1],
2295 : : "op.%d.jsonexpr_empty", opno);
2296 : : b_error =
2297 : 0 : l_bb_before_v(opblocks[opno + 1],
2298 : : "op.%d.jsonexpr_error", opno);
2299 : : b_coercion =
2300 : 0 : l_bb_before_v(opblocks[opno + 1],
2301 : : "op.%d.jsonexpr_coercion", opno);
2302 : : b_done =
2303 : 0 : l_bb_before_v(opblocks[opno + 1],
2304 : : "op.%d.jsonexpr_done", opno);
2305 : :
2306 : 0 : v_switch = LLVMBuildSwitch(b,
2307 : : v_ret,
2308 : : b_done,
2309 : : 3);
2310 : : /* Returned jsestate->jump_empty? */
2311 [ # # ]: 0 : if (jsestate->jump_empty >= 0)
2312 : : {
2313 : 0 : v_jump_empty = l_int32_const(lc, jsestate->jump_empty);
2314 : 0 : LLVMAddCase(v_switch, v_jump_empty, b_empty);
2315 : : }
2316 : : /* ON EMPTY code */
2317 : 0 : LLVMPositionBuilderAtEnd(b, b_empty);
2318 [ # # ]: 0 : if (jsestate->jump_empty >= 0)
2319 : 0 : LLVMBuildBr(b, opblocks[jsestate->jump_empty]);
2320 : : else
2321 : 0 : LLVMBuildUnreachable(b);
2322 : :
2323 : : /* Returned jsestate->jump_error? */
2324 [ # # ]: 0 : if (jsestate->jump_error >= 0)
2325 : : {
2326 : 0 : v_jump_error = l_int32_const(lc, jsestate->jump_error);
2327 : 0 : LLVMAddCase(v_switch, v_jump_error, b_error);
2328 : : }
2329 : : /* ON ERROR code */
2330 : 0 : LLVMPositionBuilderAtEnd(b, b_error);
2331 [ # # ]: 0 : if (jsestate->jump_error >= 0)
2332 : 0 : LLVMBuildBr(b, opblocks[jsestate->jump_error]);
2333 : : else
2334 : 0 : LLVMBuildUnreachable(b);
2335 : :
2336 : : /* Returned jsestate->jump_eval_coercion? */
2337 [ # # ]: 0 : if (jsestate->jump_eval_coercion >= 0)
2338 : : {
2339 : 0 : v_jump_coercion = l_int32_const(lc, jsestate->jump_eval_coercion);
2340 : 0 : LLVMAddCase(v_switch, v_jump_coercion, b_coercion);
2341 : : }
2342 : : /* jump_eval_coercion code */
2343 : 0 : LLVMPositionBuilderAtEnd(b, b_coercion);
2344 [ # # ]: 0 : if (jsestate->jump_eval_coercion >= 0)
2345 : 0 : LLVMBuildBr(b, opblocks[jsestate->jump_eval_coercion]);
2346 : : else
2347 : 0 : LLVMBuildUnreachable(b);
2348 : :
2349 : 0 : LLVMPositionBuilderAtEnd(b, b_done);
2350 : : }
2351 : :
2352 : 0 : LLVMBuildBr(b, opblocks[jsestate->jump_end]);
2353 : 0 : break;
2354 : : }
2355 : :
2356 : 0 : case EEOP_JSONEXPR_COERCION:
2357 : 0 : build_EvalXFunc(b, mod, "ExecEvalJsonCoercion",
2358 : : v_state, op, v_econtext);
2359 : :
2360 : 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2361 : 0 : break;
2362 : :
2363 : 0 : case EEOP_JSONEXPR_COERCION_FINISH:
2364 : 0 : build_EvalXFunc(b, mod, "ExecEvalJsonCoercionFinish",
2365 : : v_state, op);
2366 : :
2367 : 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2368 : 0 : break;
2369 : :
2370 : 0 : case EEOP_AGGREF:
2371 : : {
2372 : : LLVMValueRef v_aggno;
2373 : : LLVMValueRef value,
2374 : : isnull;
2375 : :
2376 : 0 : v_aggno = l_int32_const(lc, op->d.aggref.aggno);
2377 : :
2378 : : /* load agg value / null */
2379 : 0 : value = l_load_gep1(b, TypeDatum, v_aggvalues, v_aggno, "aggvalue");
2380 : 0 : isnull = l_load_gep1(b, TypeStorageBool, v_aggnulls, v_aggno, "aggnull");
2381 : :
2382 : : /* and store result */
2383 : 0 : LLVMBuildStore(b, value, v_resvaluep);
2384 : 0 : LLVMBuildStore(b, isnull, v_resnullp);
2385 : :
2386 : 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2387 : 0 : break;
2388 : : }
2389 : :
2390 : 0 : case EEOP_GROUPING_FUNC:
2391 : 0 : build_EvalXFunc(b, mod, "ExecEvalGroupingFunc",
2392 : : v_state, op);
2393 : 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2394 : 0 : break;
2395 : :
2396 : 0 : case EEOP_WINDOW_FUNC:
2397 : : {
2398 : 0 : WindowFuncExprState *wfunc = op->d.window_func.wfstate;
2399 : : LLVMValueRef v_wfuncnop;
2400 : : LLVMValueRef v_wfuncno;
2401 : : LLVMValueRef value,
2402 : : isnull;
2403 : :
2404 : : /*
2405 : : * At this point aggref->wfuncno is not yet set (it's set
2406 : : * up in ExecInitWindowAgg() after initializing the
2407 : : * expression). So load it from memory each time round.
2408 : : */
2409 : 0 : v_wfuncnop = l_ptr_const(&wfunc->wfuncno,
2410 : : l_ptr(LLVMInt32TypeInContext(lc)));
2411 : 0 : v_wfuncno = l_load(b, LLVMInt32TypeInContext(lc), v_wfuncnop, "v_wfuncno");
2412 : :
2413 : : /* load window func value / null */
2414 : 0 : value = l_load_gep1(b, TypeDatum, v_aggvalues, v_wfuncno,
2415 : : "windowvalue");
2416 : 0 : isnull = l_load_gep1(b, TypeStorageBool, v_aggnulls, v_wfuncno,
2417 : : "windownull");
2418 : :
2419 : 0 : LLVMBuildStore(b, value, v_resvaluep);
2420 : 0 : LLVMBuildStore(b, isnull, v_resnullp);
2421 : :
2422 : 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2423 : 0 : break;
2424 : : }
2425 : :
2426 : 0 : case EEOP_MERGE_SUPPORT_FUNC:
2427 : 0 : build_EvalXFunc(b, mod, "ExecEvalMergeSupportFunc",
2428 : : v_state, op, v_econtext);
2429 : 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2430 : 0 : break;
2431 : :
2432 : 0 : case EEOP_SUBPLAN:
2433 : 0 : build_EvalXFunc(b, mod, "ExecEvalSubPlan",
2434 : : v_state, op, v_econtext);
2435 : 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2436 : 0 : break;
2437 : :
2438 : 0 : case EEOP_AGG_STRICT_DESERIALIZE:
2439 : : case EEOP_AGG_DESERIALIZE:
2440 : : {
2441 : : AggState *aggstate;
2442 : 0 : FunctionCallInfo fcinfo = op->d.agg_deserialize.fcinfo_data;
2443 : :
2444 : : LLVMValueRef v_retval;
2445 : : LLVMValueRef v_fcinfo_isnull;
2446 : : LLVMValueRef v_tmpcontext;
2447 : : LLVMValueRef v_oldcontext;
2448 : :
2449 [ # # ]: 0 : if (opcode == EEOP_AGG_STRICT_DESERIALIZE)
2450 : : {
2451 : : LLVMValueRef v_fcinfo;
2452 : : LLVMValueRef v_argnull0;
2453 : : LLVMBasicBlockRef b_deserialize;
2454 : :
2455 : 0 : b_deserialize = l_bb_before_v(opblocks[opno + 1],
2456 : : "op.%d.deserialize", opno);
2457 : :
2458 : 0 : v_fcinfo = l_ptr_const(fcinfo,
2459 : : l_ptr(StructFunctionCallInfoData));
2460 : 0 : v_argnull0 = l_funcnull(b, v_fcinfo, 0);
2461 : :
2462 : 0 : LLVMBuildCondBr(b,
2463 : : LLVMBuildICmp(b,
2464 : : LLVMIntEQ,
2465 : : v_argnull0,
2466 : : l_sbool_const(1),
2467 : : ""),
2468 : 0 : opblocks[op->d.agg_deserialize.jumpnull],
2469 : : b_deserialize);
2470 : 0 : LLVMPositionBuilderAtEnd(b, b_deserialize);
2471 : : }
2472 : :
2473 : 0 : aggstate = castNode(AggState, state->parent);
2474 : 0 : fcinfo = op->d.agg_deserialize.fcinfo_data;
2475 : :
2476 : : v_tmpcontext =
2477 : 0 : l_ptr_const(aggstate->tmpcontext->ecxt_per_tuple_memory,
2478 : : l_ptr(StructMemoryContextData));
2479 : 0 : v_oldcontext = l_mcxt_switch(mod, b, v_tmpcontext);
2480 : 0 : v_retval = BuildV1Call(context, b, mod, fcinfo,
2481 : : &v_fcinfo_isnull);
2482 : 0 : l_mcxt_switch(mod, b, v_oldcontext);
2483 : :
2484 : 0 : LLVMBuildStore(b, v_retval, v_resvaluep);
2485 : 0 : LLVMBuildStore(b, v_fcinfo_isnull, v_resnullp);
2486 : :
2487 : 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2488 : 0 : break;
2489 : : }
2490 : :
2491 : 0 : case EEOP_AGG_STRICT_INPUT_CHECK_ARGS:
2492 : : case EEOP_AGG_STRICT_INPUT_CHECK_ARGS_1:
2493 : : case EEOP_AGG_STRICT_INPUT_CHECK_NULLS:
2494 : : {
2495 : 0 : int nargs = op->d.agg_strict_input_check.nargs;
2496 : 0 : NullableDatum *args = op->d.agg_strict_input_check.args;
2497 : 0 : bool *nulls = op->d.agg_strict_input_check.nulls;
2498 : : int jumpnull;
2499 : :
2500 : : LLVMValueRef v_argsp;
2501 : : LLVMValueRef v_nullsp;
2502 : : LLVMBasicBlockRef *b_checknulls;
2503 : :
2504 : : Assert(nargs > 0);
2505 : :
2506 : 0 : jumpnull = op->d.agg_strict_input_check.jumpnull;
2507 : 0 : v_argsp = l_ptr_const(args, l_ptr(StructNullableDatum));
2508 : 0 : v_nullsp = l_ptr_const(nulls, l_ptr(TypeStorageBool));
2509 : :
2510 : : /* create blocks for checking args */
2511 : 0 : b_checknulls = palloc_array(LLVMBasicBlockRef, nargs);
2512 [ # # ]: 0 : for (int argno = 0; argno < nargs; argno++)
2513 : : {
2514 : 0 : b_checknulls[argno] =
2515 : 0 : l_bb_before_v(opblocks[opno + 1],
2516 : : "op.%d.check-null.%d",
2517 : : opno, argno);
2518 : : }
2519 : :
2520 : 0 : LLVMBuildBr(b, b_checknulls[0]);
2521 : :
2522 : : /* strict function, check for NULL args */
2523 [ # # ]: 0 : for (int argno = 0; argno < nargs; argno++)
2524 : : {
2525 : 0 : LLVMValueRef v_argno = l_int32_const(lc, argno);
2526 : : LLVMValueRef v_argisnull;
2527 : : LLVMBasicBlockRef b_argnotnull;
2528 : :
2529 : 0 : LLVMPositionBuilderAtEnd(b, b_checknulls[argno]);
2530 : :
2531 [ # # ]: 0 : if (argno + 1 == nargs)
2532 : 0 : b_argnotnull = opblocks[opno + 1];
2533 : : else
2534 : 0 : b_argnotnull = b_checknulls[argno + 1];
2535 : :
2536 [ # # ]: 0 : if (opcode == EEOP_AGG_STRICT_INPUT_CHECK_NULLS)
2537 : 0 : v_argisnull = l_load_gep1(b, TypeStorageBool, v_nullsp, v_argno, "");
2538 : : else
2539 : : {
2540 : : LLVMValueRef v_argn;
2541 : :
2542 : 0 : v_argn = l_gep(b, StructNullableDatum, v_argsp, &v_argno, 1, "");
2543 : : v_argisnull =
2544 : 0 : l_load_struct_gep(b, StructNullableDatum, v_argn,
2545 : : FIELDNO_NULLABLE_DATUM_ISNULL,
2546 : : "");
2547 : : }
2548 : :
2549 : 0 : LLVMBuildCondBr(b,
2550 : : LLVMBuildICmp(b,
2551 : : LLVMIntEQ,
2552 : : v_argisnull,
2553 : : l_sbool_const(1), ""),
2554 : 0 : opblocks[jumpnull],
2555 : : b_argnotnull);
2556 : : }
2557 : :
2558 : 0 : break;
2559 : : }
2560 : :
2561 : 0 : case EEOP_AGG_PLAIN_PERGROUP_NULLCHECK:
2562 : : {
2563 : : int jumpnull;
2564 : : LLVMValueRef v_aggstatep;
2565 : : LLVMValueRef v_allpergroupsp;
2566 : : LLVMValueRef v_pergroup_allaggs;
2567 : : LLVMValueRef v_setoff;
2568 : :
2569 : 0 : jumpnull = op->d.agg_plain_pergroup_nullcheck.jumpnull;
2570 : :
2571 : : /*
2572 : : * pergroup_allaggs = aggstate->all_pergroups
2573 : : * [op->d.agg_plain_pergroup_nullcheck.setoff];
2574 : : */
2575 : 0 : v_aggstatep = LLVMBuildBitCast(b, v_parent,
2576 : : l_ptr(StructAggState), "");
2577 : :
2578 : 0 : v_allpergroupsp = l_load_struct_gep(b,
2579 : : StructAggState,
2580 : : v_aggstatep,
2581 : : FIELDNO_AGGSTATE_ALL_PERGROUPS,
2582 : : "aggstate.all_pergroups");
2583 : :
2584 : 0 : v_setoff = l_int32_const(lc, op->d.agg_plain_pergroup_nullcheck.setoff);
2585 : :
2586 : 0 : v_pergroup_allaggs = l_load_gep1(b, l_ptr(StructAggStatePerGroupData),
2587 : : v_allpergroupsp, v_setoff, "");
2588 : :
2589 : 0 : LLVMBuildCondBr(b,
2590 : : LLVMBuildICmp(b, LLVMIntEQ,
2591 : : LLVMBuildPtrToInt(b, v_pergroup_allaggs, TypeDatum, ""),
2592 : : l_datum_const(0), ""),
2593 : 0 : opblocks[jumpnull],
2594 : 0 : opblocks[opno + 1]);
2595 : 0 : break;
2596 : : }
2597 : :
2598 : 0 : case EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL:
2599 : : case EEOP_AGG_PLAIN_TRANS_STRICT_BYVAL:
2600 : : case EEOP_AGG_PLAIN_TRANS_BYVAL:
2601 : : case EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF:
2602 : : case EEOP_AGG_PLAIN_TRANS_STRICT_BYREF:
2603 : : case EEOP_AGG_PLAIN_TRANS_BYREF:
2604 : : {
2605 : : AggState *aggstate;
2606 : : AggStatePerTrans pertrans;
2607 : : FunctionCallInfo fcinfo;
2608 : :
2609 : : LLVMValueRef v_aggstatep;
2610 : : LLVMValueRef v_fcinfo;
2611 : : LLVMValueRef v_fcinfo_isnull;
2612 : :
2613 : : LLVMValueRef v_transvaluep;
2614 : : LLVMValueRef v_transnullp;
2615 : :
2616 : : LLVMValueRef v_setoff;
2617 : : LLVMValueRef v_transno;
2618 : :
2619 : : LLVMValueRef v_aggcontext;
2620 : :
2621 : : LLVMValueRef v_allpergroupsp;
2622 : : LLVMValueRef v_current_setp;
2623 : : LLVMValueRef v_current_pertransp;
2624 : : LLVMValueRef v_curaggcontext;
2625 : :
2626 : : LLVMValueRef v_pertransp;
2627 : :
2628 : : LLVMValueRef v_pergroupp;
2629 : :
2630 : : LLVMValueRef v_retval;
2631 : :
2632 : : LLVMValueRef v_tmpcontext;
2633 : : LLVMValueRef v_oldcontext;
2634 : :
2635 : 0 : aggstate = castNode(AggState, state->parent);
2636 : 0 : pertrans = op->d.agg_trans.pertrans;
2637 : :
2638 : 0 : fcinfo = pertrans->transfn_fcinfo;
2639 : :
2640 : : v_aggstatep =
2641 : 0 : LLVMBuildBitCast(b, v_parent, l_ptr(StructAggState), "");
2642 : 0 : v_pertransp = l_ptr_const(pertrans,
2643 : : l_ptr(StructAggStatePerTransData));
2644 : :
2645 : : /*
2646 : : * pergroup = &aggstate->all_pergroups
2647 : : * [op->d.agg_trans.setoff] [op->d.agg_trans.transno];
2648 : : */
2649 : : v_allpergroupsp =
2650 : 0 : l_load_struct_gep(b,
2651 : : StructAggState,
2652 : : v_aggstatep,
2653 : : FIELDNO_AGGSTATE_ALL_PERGROUPS,
2654 : : "aggstate.all_pergroups");
2655 : 0 : v_setoff = l_int32_const(lc, op->d.agg_trans.setoff);
2656 : 0 : v_transno = l_int32_const(lc, op->d.agg_trans.transno);
2657 : : v_pergroupp =
2658 : 0 : l_gep(b,
2659 : : StructAggStatePerGroupData,
2660 : : l_load_gep1(b, l_ptr(StructAggStatePerGroupData),
2661 : : v_allpergroupsp, v_setoff, ""),
2662 : : &v_transno, 1, "");
2663 : :
2664 : :
2665 [ # # # # ]: 0 : if (opcode == EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL ||
2666 : : opcode == EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF)
2667 : : {
2668 : : LLVMValueRef v_notransvalue;
2669 : : LLVMBasicBlockRef b_init;
2670 : : LLVMBasicBlockRef b_no_init;
2671 : :
2672 : : v_notransvalue =
2673 : 0 : l_load_struct_gep(b,
2674 : : StructAggStatePerGroupData,
2675 : : v_pergroupp,
2676 : : FIELDNO_AGGSTATEPERGROUPDATA_NOTRANSVALUE,
2677 : : "notransvalue");
2678 : :
2679 : 0 : b_init = l_bb_before_v(opblocks[opno + 1],
2680 : : "op.%d.inittrans", opno);
2681 : 0 : b_no_init = l_bb_before_v(opblocks[opno + 1],
2682 : : "op.%d.no_inittrans", opno);
2683 : :
2684 : 0 : LLVMBuildCondBr(b,
2685 : : LLVMBuildICmp(b, LLVMIntEQ, v_notransvalue,
2686 : : l_sbool_const(1), ""),
2687 : : b_init,
2688 : : b_no_init);
2689 : :
2690 : : /* block to init the transition value if necessary */
2691 : : {
2692 : : LLVMValueRef params[4];
2693 : :
2694 : 0 : LLVMPositionBuilderAtEnd(b, b_init);
2695 : :
2696 : 0 : v_aggcontext = l_ptr_const(op->d.agg_trans.aggcontext,
2697 : : l_ptr(StructExprContext));
2698 : :
2699 : 0 : params[0] = v_aggstatep;
2700 : 0 : params[1] = v_pertransp;
2701 : 0 : params[2] = v_pergroupp;
2702 : 0 : params[3] = v_aggcontext;
2703 : :
2704 : 0 : l_call(b,
2705 : : llvm_pg_var_func_type("ExecAggInitGroup"),
2706 : : llvm_pg_func(mod, "ExecAggInitGroup"),
2707 : : params, lengthof(params),
2708 : : "");
2709 : :
2710 : 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2711 : : }
2712 : :
2713 : 0 : LLVMPositionBuilderAtEnd(b, b_no_init);
2714 : : }
2715 : :
2716 [ # # # # ]: 0 : if (opcode == EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYVAL ||
2717 [ # # ]: 0 : opcode == EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF ||
2718 [ # # ]: 0 : opcode == EEOP_AGG_PLAIN_TRANS_STRICT_BYVAL ||
2719 : : opcode == EEOP_AGG_PLAIN_TRANS_STRICT_BYREF)
2720 : : {
2721 : : LLVMValueRef v_transnull;
2722 : : LLVMBasicBlockRef b_strictpass;
2723 : :
2724 : 0 : b_strictpass = l_bb_before_v(opblocks[opno + 1],
2725 : : "op.%d.strictpass", opno);
2726 : : v_transnull =
2727 : 0 : l_load_struct_gep(b,
2728 : : StructAggStatePerGroupData,
2729 : : v_pergroupp,
2730 : : FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL,
2731 : : "transnull");
2732 : :
2733 : 0 : LLVMBuildCondBr(b,
2734 : : LLVMBuildICmp(b, LLVMIntEQ, v_transnull,
2735 : : l_sbool_const(1), ""),
2736 : 0 : opblocks[opno + 1],
2737 : : b_strictpass);
2738 : :
2739 : 0 : LLVMPositionBuilderAtEnd(b, b_strictpass);
2740 : : }
2741 : :
2742 : :
2743 : 0 : v_fcinfo = l_ptr_const(fcinfo,
2744 : : l_ptr(StructFunctionCallInfoData));
2745 : 0 : v_aggcontext = l_ptr_const(op->d.agg_trans.aggcontext,
2746 : : l_ptr(StructExprContext));
2747 : :
2748 : : v_current_setp =
2749 : 0 : l_struct_gep(b,
2750 : : StructAggState,
2751 : : v_aggstatep,
2752 : : FIELDNO_AGGSTATE_CURRENT_SET,
2753 : : "aggstate.current_set");
2754 : : v_curaggcontext =
2755 : 0 : l_struct_gep(b,
2756 : : StructAggState,
2757 : : v_aggstatep,
2758 : : FIELDNO_AGGSTATE_CURAGGCONTEXT,
2759 : : "aggstate.curaggcontext");
2760 : : v_current_pertransp =
2761 : 0 : l_struct_gep(b,
2762 : : StructAggState,
2763 : : v_aggstatep,
2764 : : FIELDNO_AGGSTATE_CURPERTRANS,
2765 : : "aggstate.curpertrans");
2766 : :
2767 : : /* set aggstate globals */
2768 : 0 : LLVMBuildStore(b, v_aggcontext, v_curaggcontext);
2769 : 0 : LLVMBuildStore(b, l_int32_const(lc, op->d.agg_trans.setno),
2770 : : v_current_setp);
2771 : 0 : LLVMBuildStore(b, v_pertransp, v_current_pertransp);
2772 : :
2773 : : /* invoke transition function in per-tuple context */
2774 : : v_tmpcontext =
2775 : 0 : l_ptr_const(aggstate->tmpcontext->ecxt_per_tuple_memory,
2776 : : l_ptr(StructMemoryContextData));
2777 : 0 : v_oldcontext = l_mcxt_switch(mod, b, v_tmpcontext);
2778 : :
2779 : : /* store transvalue in fcinfo->args[0] */
2780 : : v_transvaluep =
2781 : 0 : l_struct_gep(b,
2782 : : StructAggStatePerGroupData,
2783 : : v_pergroupp,
2784 : : FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUE,
2785 : : "transvalue");
2786 : : v_transnullp =
2787 : 0 : l_struct_gep(b,
2788 : : StructAggStatePerGroupData,
2789 : : v_pergroupp,
2790 : : FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL,
2791 : : "transnullp");
2792 : 0 : LLVMBuildStore(b,
2793 : : l_load(b,
2794 : : TypeDatum,
2795 : : v_transvaluep,
2796 : : "transvalue"),
2797 : : l_funcvaluep(b, v_fcinfo, 0));
2798 : 0 : LLVMBuildStore(b,
2799 : : l_load(b, TypeStorageBool, v_transnullp, "transnull"),
2800 : : l_funcnullp(b, v_fcinfo, 0));
2801 : :
2802 : : /* and invoke transition function */
2803 : 0 : v_retval = BuildV1Call(context, b, mod, fcinfo,
2804 : : &v_fcinfo_isnull);
2805 : :
2806 : : /*
2807 : : * For pass-by-ref datatype, must copy the new value into
2808 : : * aggcontext and free the prior transValue. But if
2809 : : * transfn returned a pointer to its first input, we don't
2810 : : * need to do anything. Also, if transfn returned a
2811 : : * pointer to a R/W expanded object that is already a
2812 : : * child of the aggcontext, assume we can adopt that value
2813 : : * without copying it.
2814 : : */
2815 [ # # # # ]: 0 : if (opcode == EEOP_AGG_PLAIN_TRANS_INIT_STRICT_BYREF ||
2816 [ # # ]: 0 : opcode == EEOP_AGG_PLAIN_TRANS_STRICT_BYREF ||
2817 : : opcode == EEOP_AGG_PLAIN_TRANS_BYREF)
2818 : : {
2819 : : LLVMBasicBlockRef b_call;
2820 : : LLVMBasicBlockRef b_nocall;
2821 : : LLVMValueRef v_fn;
2822 : : LLVMValueRef v_transvalue;
2823 : : LLVMValueRef v_transnull;
2824 : : LLVMValueRef v_newval;
2825 : : LLVMValueRef params[6];
2826 : :
2827 : 0 : b_call = l_bb_before_v(opblocks[opno + 1],
2828 : : "op.%d.transcall", opno);
2829 : 0 : b_nocall = l_bb_before_v(opblocks[opno + 1],
2830 : : "op.%d.transnocall", opno);
2831 : :
2832 : 0 : v_transvalue = l_load(b, TypeDatum, v_transvaluep, "");
2833 : 0 : v_transnull = l_load(b, TypeStorageBool, v_transnullp, "");
2834 : :
2835 : : /*
2836 : : * DatumGetPointer(newVal) !=
2837 : : * DatumGetPointer(pergroup->transValue))
2838 : : */
2839 : 0 : LLVMBuildCondBr(b,
2840 : : LLVMBuildICmp(b, LLVMIntEQ,
2841 : : v_transvalue,
2842 : : v_retval, ""),
2843 : : b_nocall, b_call);
2844 : :
2845 : : /* returned datum not passed datum, reparent */
2846 : 0 : LLVMPositionBuilderAtEnd(b, b_call);
2847 : :
2848 : 0 : params[0] = v_aggstatep;
2849 : 0 : params[1] = v_pertransp;
2850 : 0 : params[2] = v_retval;
2851 : 0 : params[3] = LLVMBuildTrunc(b, v_fcinfo_isnull,
2852 : : TypeParamBool, "");
2853 : 0 : params[4] = v_transvalue;
2854 : 0 : params[5] = LLVMBuildTrunc(b, v_transnull,
2855 : : TypeParamBool, "");
2856 : :
2857 : 0 : v_fn = llvm_pg_func(mod, "ExecAggCopyTransValue");
2858 : : v_newval =
2859 : 0 : l_call(b,
2860 : : LLVMGetFunctionType(v_fn),
2861 : : v_fn,
2862 : : params, lengthof(params),
2863 : : "");
2864 : :
2865 : : /* store trans value */
2866 : 0 : LLVMBuildStore(b, v_newval, v_transvaluep);
2867 : 0 : LLVMBuildStore(b, v_fcinfo_isnull, v_transnullp);
2868 : :
2869 : 0 : l_mcxt_switch(mod, b, v_oldcontext);
2870 : 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2871 : :
2872 : : /* returned datum passed datum, no need to reparent */
2873 : 0 : LLVMPositionBuilderAtEnd(b, b_nocall);
2874 : : }
2875 : :
2876 : : /* store trans value */
2877 : 0 : LLVMBuildStore(b, v_retval, v_transvaluep);
2878 : 0 : LLVMBuildStore(b, v_fcinfo_isnull, v_transnullp);
2879 : :
2880 : 0 : l_mcxt_switch(mod, b, v_oldcontext);
2881 : :
2882 : 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2883 : 0 : break;
2884 : : }
2885 : :
2886 : 0 : case EEOP_AGG_PRESORTED_DISTINCT_SINGLE:
2887 : : {
2888 : 0 : AggState *aggstate = castNode(AggState, state->parent);
2889 : 0 : AggStatePerTrans pertrans = op->d.agg_presorted_distinctcheck.pertrans;
2890 : 0 : int jumpdistinct = op->d.agg_presorted_distinctcheck.jumpdistinct;
2891 : :
2892 : 0 : LLVMValueRef v_fn = llvm_pg_func(mod, "ExecEvalPreOrderedDistinctSingle");
2893 : : LLVMValueRef v_args[2];
2894 : : LLVMValueRef v_ret;
2895 : :
2896 : 0 : v_args[0] = l_ptr_const(aggstate, l_ptr(StructAggState));
2897 : 0 : v_args[1] = l_ptr_const(pertrans, l_ptr(StructAggStatePerTransData));
2898 : :
2899 : 0 : v_ret = l_call(b, LLVMGetFunctionType(v_fn), v_fn, v_args, 2, "");
2900 : 0 : v_ret = LLVMBuildZExt(b, v_ret, TypeStorageBool, "");
2901 : :
2902 : 0 : LLVMBuildCondBr(b,
2903 : : LLVMBuildICmp(b, LLVMIntEQ, v_ret,
2904 : : l_sbool_const(1), ""),
2905 : 0 : opblocks[opno + 1],
2906 : 0 : opblocks[jumpdistinct]);
2907 : 0 : break;
2908 : : }
2909 : :
2910 : 0 : case EEOP_AGG_PRESORTED_DISTINCT_MULTI:
2911 : : {
2912 : 0 : AggState *aggstate = castNode(AggState, state->parent);
2913 : 0 : AggStatePerTrans pertrans = op->d.agg_presorted_distinctcheck.pertrans;
2914 : 0 : int jumpdistinct = op->d.agg_presorted_distinctcheck.jumpdistinct;
2915 : :
2916 : 0 : LLVMValueRef v_fn = llvm_pg_func(mod, "ExecEvalPreOrderedDistinctMulti");
2917 : : LLVMValueRef v_args[2];
2918 : : LLVMValueRef v_ret;
2919 : :
2920 : 0 : v_args[0] = l_ptr_const(aggstate, l_ptr(StructAggState));
2921 : 0 : v_args[1] = l_ptr_const(pertrans, l_ptr(StructAggStatePerTransData));
2922 : :
2923 : 0 : v_ret = l_call(b, LLVMGetFunctionType(v_fn), v_fn, v_args, 2, "");
2924 : 0 : v_ret = LLVMBuildZExt(b, v_ret, TypeStorageBool, "");
2925 : :
2926 : 0 : LLVMBuildCondBr(b,
2927 : : LLVMBuildICmp(b, LLVMIntEQ, v_ret,
2928 : : l_sbool_const(1), ""),
2929 : 0 : opblocks[opno + 1],
2930 : 0 : opblocks[jumpdistinct]);
2931 : 0 : break;
2932 : : }
2933 : :
2934 : 0 : case EEOP_AGG_ORDERED_TRANS_DATUM:
2935 : 0 : build_EvalXFunc(b, mod, "ExecEvalAggOrderedTransDatum",
2936 : : v_state, op, v_econtext);
2937 : 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2938 : 0 : break;
2939 : :
2940 : 0 : case EEOP_AGG_ORDERED_TRANS_TUPLE:
2941 : 0 : build_EvalXFunc(b, mod, "ExecEvalAggOrderedTransTuple",
2942 : : v_state, op, v_econtext);
2943 : 0 : LLVMBuildBr(b, opblocks[opno + 1]);
2944 : 0 : break;
2945 : :
2946 : 0 : case EEOP_LAST:
2947 : : Assert(false);
2948 : 0 : break;
2949 : : }
2950 : : }
2951 : :
2952 : 0 : LLVMDisposeBuilder(b);
2953 : :
2954 : : /*
2955 : : * Don't immediately emit function, instead do so the first time the
2956 : : * expression is actually evaluated. That allows to emit a lot of
2957 : : * functions together, avoiding a lot of repeated llvm and memory
2958 : : * remapping overhead.
2959 : : */
2960 : : {
2961 : :
2962 : 0 : CompiledExprState *cstate = palloc0_object(CompiledExprState);
2963 : :
2964 : 0 : cstate->context = context;
2965 : 0 : cstate->funcname = funcname;
2966 : :
2967 : 0 : state->evalfunc = ExecRunCompiledExpr;
2968 : 0 : state->evalfunc_private = cstate;
2969 : : }
2970 : :
2971 : 0 : llvm_leave_fatal_on_oom();
2972 : :
2973 : 0 : INSTR_TIME_SET_CURRENT(endtime);
2974 : 0 : INSTR_TIME_ACCUM_DIFF(context->base.instr.generation_counter,
2975 : : endtime, starttime);
2976 : :
2977 : 0 : return true;
2978 : : }
2979 : :
2980 : : /*
2981 : : * Run compiled expression.
2982 : : *
2983 : : * This will only be called the first time a JITed expression is called. We
2984 : : * first make sure the expression is still up-to-date, and then get a pointer to
2985 : : * the emitted function. The latter can be the first thing that triggers
2986 : : * optimizing and emitting all the generated functions.
2987 : : */
2988 : : static Datum
2989 : 0 : ExecRunCompiledExpr(ExprState *state, ExprContext *econtext, bool *isNull)
2990 : : {
2991 : 0 : CompiledExprState *cstate = state->evalfunc_private;
2992 : : ExprStateEvalFunc func;
2993 : :
2994 : 0 : CheckExprStillValid(state, econtext);
2995 : :
2996 : 0 : llvm_enter_fatal_on_oom();
2997 : 0 : func = (ExprStateEvalFunc) llvm_get_function(cstate->context,
2998 : : cstate->funcname);
2999 : 0 : llvm_leave_fatal_on_oom();
3000 : : Assert(func);
3001 : :
3002 : : /* remove indirection via this function for future calls */
3003 : 0 : state->evalfunc = func;
3004 : :
3005 : 0 : return func(state, econtext, isNull);
3006 : : }
3007 : :
3008 : : static LLVMValueRef
3009 : 0 : BuildV1Call(LLVMJitContext *context, LLVMBuilderRef b,
3010 : : LLVMModuleRef mod, FunctionCallInfo fcinfo,
3011 : : LLVMValueRef *v_fcinfo_isnull)
3012 : : {
3013 : : LLVMValueRef v_fn;
3014 : : LLVMValueRef v_fcinfo_isnullp;
3015 : : LLVMValueRef v_retval;
3016 : : LLVMValueRef v_fcinfo;
3017 : :
3018 : 0 : v_fn = llvm_function_reference(context, b, mod, fcinfo);
3019 : :
3020 : 0 : v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
3021 : 0 : v_fcinfo_isnullp = l_struct_gep(b,
3022 : : StructFunctionCallInfoData,
3023 : : v_fcinfo,
3024 : : FIELDNO_FUNCTIONCALLINFODATA_ISNULL,
3025 : : "v_fcinfo_isnull");
3026 : 0 : LLVMBuildStore(b, l_sbool_const(0), v_fcinfo_isnullp);
3027 : :
3028 : 0 : v_retval = l_call(b, LLVMGetFunctionType(AttributeTemplate), v_fn, &v_fcinfo, 1, "funccall");
3029 : :
3030 [ # # ]: 0 : if (v_fcinfo_isnull)
3031 : 0 : *v_fcinfo_isnull = l_load(b, TypeStorageBool, v_fcinfo_isnullp, "");
3032 : :
3033 : : #if LLVM_VERSION_MAJOR < 22
3034 : :
3035 : : /*
3036 : : * Add lifetime-end annotation, signaling that writes to memory don't have
3037 : : * to be retained (important for inlining potential).
3038 : : */
3039 : : {
3040 : 0 : LLVMContextRef lc = LLVMGetModuleContext(mod);
3041 : 0 : LLVMValueRef v_lifetime = create_LifetimeEnd(mod);
3042 : : LLVMValueRef params[2];
3043 : :
3044 : 0 : params[0] = l_int64_const(lc, sizeof(NullableDatum) * fcinfo->nargs);
3045 : 0 : params[1] = l_ptr_const(fcinfo->args, l_ptr(LLVMInt8TypeInContext(lc)));
3046 : 0 : l_call(b, LLVMGetFunctionType(v_lifetime), v_lifetime, params, lengthof(params), "");
3047 : :
3048 : 0 : params[0] = l_int64_const(lc, sizeof(fcinfo->isnull));
3049 : 0 : params[1] = l_ptr_const(&fcinfo->isnull, l_ptr(LLVMInt8TypeInContext(lc)));
3050 : 0 : l_call(b, LLVMGetFunctionType(v_lifetime), v_lifetime, params, lengthof(params), "");
3051 : : }
3052 : : #endif
3053 : :
3054 : 0 : return v_retval;
3055 : : }
3056 : :
3057 : : /*
3058 : : * Implement an expression step by calling the function funcname.
3059 : : */
3060 : : static LLVMValueRef
3061 : 0 : build_EvalXFuncInt(LLVMBuilderRef b, LLVMModuleRef mod, const char *funcname,
3062 : : LLVMValueRef v_state, ExprEvalStep *op,
3063 : : int nargs, LLVMValueRef *v_args)
3064 : : {
3065 : 0 : LLVMValueRef v_fn = llvm_pg_func(mod, funcname);
3066 : : LLVMValueRef *params;
3067 : 0 : int argno = 0;
3068 : : LLVMValueRef v_ret;
3069 : :
3070 : : /* cheap pre-check as llvm just asserts out */
3071 [ # # ]: 0 : if (LLVMCountParams(v_fn) != (nargs + 2))
3072 [ # # ]: 0 : elog(ERROR, "parameter mismatch: %s expects %d passed %d",
3073 : : funcname, LLVMCountParams(v_fn), nargs + 2);
3074 : :
3075 : 0 : params = palloc_array(LLVMValueRef, (2 + nargs));
3076 : :
3077 : 0 : params[argno++] = v_state;
3078 : 0 : params[argno++] = l_ptr_const(op, l_ptr(StructExprEvalStep));
3079 : :
3080 [ # # ]: 0 : for (int i = 0; i < nargs; i++)
3081 : 0 : params[argno++] = v_args[i];
3082 : :
3083 : 0 : v_ret = l_call(b, LLVMGetFunctionType(v_fn), v_fn, params, argno, "");
3084 : :
3085 : 0 : pfree(params);
3086 : :
3087 : 0 : return v_ret;
3088 : : }
3089 : :
3090 : : #if LLVM_VERSION_MAJOR < 22
3091 : : static LLVMValueRef
3092 : 0 : create_LifetimeEnd(LLVMModuleRef mod)
3093 : : {
3094 : : LLVMTypeRef sig;
3095 : : LLVMValueRef fn;
3096 : : LLVMTypeRef param_types[2];
3097 : : LLVMContextRef lc;
3098 : :
3099 : : /* variadic pointer argument */
3100 : 0 : const char *nm = "llvm.lifetime.end.p0";
3101 : :
3102 : 0 : fn = LLVMGetNamedFunction(mod, nm);
3103 [ # # ]: 0 : if (fn)
3104 : 0 : return fn;
3105 : :
3106 : 0 : lc = LLVMGetModuleContext(mod);
3107 : 0 : param_types[0] = LLVMInt64TypeInContext(lc);
3108 : 0 : param_types[1] = l_ptr(LLVMInt8TypeInContext(lc));
3109 : :
3110 : 0 : sig = LLVMFunctionType(LLVMVoidTypeInContext(lc), param_types,
3111 : : lengthof(param_types), false);
3112 : 0 : fn = LLVMAddFunction(mod, nm, sig);
3113 : :
3114 : 0 : LLVMSetFunctionCallConv(fn, LLVMCCallConv);
3115 : :
3116 : : Assert(LLVMGetIntrinsicID(fn));
3117 : :
3118 : 0 : return fn;
3119 : : }
3120 : : #endif
|