src/backend/jit/llvm/llvmjit_expr.c - Coverage Report

← Back to Overview

# src/backend/jit/llvm/llvmjit_expr.c

Coverage: 18/18 lines (100.0%)
Total Lines
18
modified
Covered
18
100.0%
Uncovered
0
0.0%
Keyboard navigation
llvm_compile_expr() lines 80-3051
Modified Lines Coverage: 18/18 lines (100.0%)

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