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