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