PostgreSQL Source Code  git master
llvmjit_expr.c File Reference
#include "postgres.h"
#include <llvm-c/Core.h>
#include <llvm-c/Target.h>
#include "access/htup_details.h"
#include "access/nbtree.h"
#include "access/tupconvert.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_type.h"
#include "executor/execdebug.h"
#include "executor/nodeAgg.h"
#include "executor/nodeSubplan.h"
#include "executor/execExpr.h"
#include "funcapi.h"
#include "jit/llvmjit.h"
#include "jit/llvmjit_emit.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "parser/parse_coerce.h"
#include "parser/parsetree.h"
#include "pgstat.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/date.h"
#include "utils/fmgrtab.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/timestamp.h"
#include "utils/typcache.h"
#include "utils/xml.h"
Include dependency graph for llvmjit_expr.c:

Go to the source code of this file.

Data Structures

struct  CompiledExprState
 

Typedefs

typedef struct CompiledExprState CompiledExprState
 

Functions

static Datum ExecRunCompiledExpr (ExprState *state, ExprContext *econtext, bool *isNull)
 
static LLVMValueRef BuildV1Call (LLVMJitContext *context, LLVMBuilderRef b, LLVMModuleRef mod, FunctionCallInfo fcinfo, LLVMValueRef *v_fcinfo_isnull)
 
static void build_EvalXFunc (LLVMBuilderRef b, LLVMModuleRef mod, const char *funcname, LLVMValueRef v_state, LLVMValueRef v_econtext, ExprEvalStep *op)
 
static LLVMValueRef create_LifetimeEnd (LLVMModuleRef mod)
 
bool llvm_compile_expr (ExprState *state)
 

Typedef Documentation

◆ CompiledExprState

Function Documentation

◆ build_EvalXFunc()

static void build_EvalXFunc ( LLVMBuilderRef  b,
LLVMModuleRef  mod,
const char *  funcname,
LLVMValueRef  v_state,
LLVMValueRef  v_econtext,
ExprEvalStep op 
)
static

Definition at line 2543 of file llvmjit_expr.c.

References lengthof, sig, StructExprContext, StructExprEvalStep, and StructExprState.

Referenced by llvm_compile_expr().

2546 {
2547  LLVMTypeRef sig;
2548  LLVMValueRef v_fn;
2549  LLVMTypeRef param_types[3];
2550  LLVMValueRef params[3];
2551 
2552  v_fn = LLVMGetNamedFunction(mod, funcname);
2553  if (!v_fn)
2554  {
2555  param_types[0] = l_ptr(StructExprState);
2556  param_types[1] = l_ptr(StructExprEvalStep);
2557  param_types[2] = l_ptr(StructExprContext);
2558 
2559  sig = LLVMFunctionType(LLVMVoidType(),
2560  param_types, lengthof(param_types),
2561  false);
2562  v_fn = LLVMAddFunction(mod, funcname, sig);
2563  }
2564 
2565  params[0] = v_state;
2566  params[1] = l_ptr_const(op, l_ptr(StructExprEvalStep));
2567  params[2] = v_econtext;
2568 
2569  LLVMBuildCall(b,
2570  v_fn,
2571  params, lengthof(params), "");
2572 }
LLVMTypeRef StructExprEvalStep
Definition: llvmjit.c:76
LLVMTypeRef StructExprState
Definition: llvmjit.c:77
#define lengthof(array)
Definition: c.h:662
LLVMTypeRef StructExprContext
Definition: llvmjit.c:75
static int sig
Definition: pg_ctl.c:84

◆ BuildV1Call()

static LLVMValueRef BuildV1Call ( LLVMJitContext *  context,
LLVMBuilderRef  b,
LLVMModuleRef  mod,
FunctionCallInfo  fcinfo,
LLVMValueRef *  v_fcinfo_isnull 
)
static

Definition at line 2497 of file llvmjit_expr.c.

References FunctionCallInfoBaseData::args, create_LifetimeEnd(), FIELDNO_FUNCTIONCALLINFODATA_ISNULL, FunctionCallInfoBaseData::isnull, lengthof, llvm_function_reference(), FunctionCallInfoBaseData::nargs, and StructFunctionCallInfoData.

Referenced by llvm_compile_expr().

2500 {
2501  LLVMValueRef v_fn;
2502  LLVMValueRef v_fcinfo_isnullp;
2503  LLVMValueRef v_retval;
2504  LLVMValueRef v_fcinfo;
2505 
2506  v_fn = llvm_function_reference(context, b, mod, fcinfo);
2507 
2508  v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
2509  v_fcinfo_isnullp = LLVMBuildStructGEP(b, v_fcinfo,
2511  "v_fcinfo_isnull");
2512  LLVMBuildStore(b, l_sbool_const(0), v_fcinfo_isnullp);
2513 
2514  v_retval = LLVMBuildCall(b, v_fn, &v_fcinfo, 1, "funccall");
2515 
2516  if (v_fcinfo_isnull)
2517  *v_fcinfo_isnull = LLVMBuildLoad(b, v_fcinfo_isnullp, "");
2518 
2519  /*
2520  * Add lifetime-end annotation, signalling that writes to memory don't
2521  * have to be retained (important for inlining potential).
2522  */
2523  {
2524  LLVMValueRef v_lifetime = create_LifetimeEnd(mod);
2525  LLVMValueRef params[2];
2526 
2527  params[0] = l_int64_const(sizeof(NullableDatum) * fcinfo->nargs);
2528  params[1] = l_ptr_const(fcinfo->args, l_ptr(LLVMInt8Type()));
2529  LLVMBuildCall(b, v_lifetime, params, lengthof(params), "");
2530 
2531  params[0] = l_int64_const(sizeof(fcinfo->isnull));
2532  params[1] = l_ptr_const(&fcinfo->isnull, l_ptr(LLVMInt8Type()));
2533  LLVMBuildCall(b, v_lifetime, params, lengthof(params), "");
2534  }
2535 
2536  return v_retval;
2537 }
#define FIELDNO_FUNCTIONCALLINFODATA_ISNULL
Definition: fmgr.h:91
LLVMTypeRef StructFunctionCallInfoData
Definition: llvmjit.c:74
static LLVMValueRef create_LifetimeEnd(LLVMModuleRef mod)
LLVMValueRef llvm_function_reference(LLVMJitContext *context, LLVMBuilderRef builder, LLVMModuleRef mod, FunctionCallInfo fcinfo)
Definition: llvmjit.c:359
#define lengthof(array)
Definition: c.h:662
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
Definition: fmgr.h:95

◆ create_LifetimeEnd()

static LLVMValueRef create_LifetimeEnd ( LLVMModuleRef  mod)
static

Definition at line 2575 of file llvmjit_expr.c.

References Assert, fn(), lengthof, and sig.

Referenced by BuildV1Call().

2576 {
2577  LLVMTypeRef sig;
2578  LLVMValueRef fn;
2579  LLVMTypeRef param_types[2];
2580 
2581  /* LLVM 5+ has a variadic pointer argument */
2582 #if LLVM_VERSION_MAJOR < 5
2583  const char *nm = "llvm.lifetime.end";
2584 #else
2585  const char *nm = "llvm.lifetime.end.p0i8";
2586 #endif
2587 
2588  fn = LLVMGetNamedFunction(mod, nm);
2589  if (fn)
2590  return fn;
2591 
2592  param_types[0] = LLVMInt64Type();
2593  param_types[1] = l_ptr(LLVMInt8Type());
2594 
2595  sig = LLVMFunctionType(LLVMVoidType(),
2596  param_types, lengthof(param_types),
2597  false);
2598  fn = LLVMAddFunction(mod, nm, sig);
2599 
2600  LLVMSetFunctionCallConv(fn, LLVMCCallConv);
2601 
2602  Assert(LLVMGetIntrinsicID(fn));
2603 
2604  return fn;
2605 }
#define lengthof(array)
Definition: c.h:662
static int sig
Definition: pg_ctl.c:84
static void * fn(void *arg)
#define Assert(condition)
Definition: c.h:732

◆ ExecRunCompiledExpr()

static Datum ExecRunCompiledExpr ( ExprState state,
ExprContext econtext,
bool isNull 
)
static

Definition at line 2477 of file llvmjit_expr.c.

References Assert, CheckExprStillValid(), CompiledExprState::context, ExprState::evalfunc, ExprState::evalfunc_private, CompiledExprState::funcname, llvm_enter_fatal_on_oom(), llvm_get_function(), and llvm_leave_fatal_on_oom().

Referenced by llvm_compile_expr().

2478 {
2479  CompiledExprState *cstate = state->evalfunc_private;
2480  ExprStateEvalFunc func;
2481 
2482  CheckExprStillValid(state, econtext);
2483 
2485  func = (ExprStateEvalFunc) llvm_get_function(cstate->context,
2486  cstate->funcname);
2488  Assert(func);
2489 
2490  /* remove indirection via this function for future calls */
2491  state->evalfunc = func;
2492 
2493  return func(state, econtext, isNull);
2494 }
Datum(* ExprStateEvalFunc)(struct ExprState *expression, struct ExprContext *econtext, bool *isNull)
Definition: execnodes.h:54
LLVMJitContext * context
Definition: llvmjit_expr.c:52
ExprStateEvalFunc evalfunc
Definition: execnodes.h:92
void * evalfunc_private
Definition: execnodes.h:98
#define Assert(condition)
Definition: c.h:732
void * llvm_get_function(LLVMJitContext *context, const char *funcname)
Definition: llvmjit.c:247
void llvm_enter_fatal_on_oom(void)
const char * funcname
Definition: llvmjit_expr.c:53
void CheckExprStillValid(ExprState *state, ExprContext *econtext)
void llvm_leave_fatal_on_oom(void)

◆ llvm_compile_expr()

bool llvm_compile_expr ( ExprState state)

Definition at line 73 of file llvmjit_expr.c.

References ExprEvalStep::agg_deserialize, ExprEvalStep::agg_init_trans, ExprEvalStep::agg_strict_input_check, ExprEvalStep::agg_strict_trans_check, ExprEvalStep::agg_trans, AggrefExprState::aggno, ExprEvalStep::aggref, generate_unaccent_rules::args, Assert, ExprEvalStep::assign_tmp, ExprEvalStep::assign_var, AttributeTemplate, ExprEvalStep::boolexpr, build_EvalXFunc(), BuildV1Call(), ExprEvalStep::casetest, ExprEvalStep::constval, CompiledExprState::context, ExprEvalStep::cparam, ExprEvalStep::d, ExprContext::ecxt_per_tuple_memory, EEOP_AGG_DESERIALIZE, EEOP_AGG_INIT_TRANS, EEOP_AGG_ORDERED_TRANS_DATUM, EEOP_AGG_ORDERED_TRANS_TUPLE, EEOP_AGG_PLAIN_TRANS, EEOP_AGG_PLAIN_TRANS_BYVAL, EEOP_AGG_STRICT_DESERIALIZE, EEOP_AGG_STRICT_INPUT_CHECK_ARGS, EEOP_AGG_STRICT_INPUT_CHECK_NULLS, EEOP_AGG_STRICT_TRANS_CHECK, EEOP_AGGREF, EEOP_ALTERNATIVE_SUBPLAN, EEOP_ARRAYCOERCE, EEOP_ARRAYEXPR, EEOP_ASSIGN_INNER_VAR, EEOP_ASSIGN_OUTER_VAR, EEOP_ASSIGN_SCAN_VAR, EEOP_ASSIGN_TMP, EEOP_ASSIGN_TMP_MAKE_RO, EEOP_BOOL_AND_STEP, EEOP_BOOL_AND_STEP_FIRST, EEOP_BOOL_AND_STEP_LAST, EEOP_BOOL_NOT_STEP, EEOP_BOOL_OR_STEP, EEOP_BOOL_OR_STEP_FIRST, EEOP_BOOL_OR_STEP_LAST, EEOP_BOOLTEST_IS_FALSE, EEOP_BOOLTEST_IS_NOT_FALSE, EEOP_BOOLTEST_IS_NOT_TRUE, EEOP_BOOLTEST_IS_TRUE, EEOP_CASE_TESTVAL, EEOP_CONST, EEOP_CONVERT_ROWTYPE, EEOP_CURRENTOFEXPR, EEOP_DISTINCT, EEOP_DOMAIN_CHECK, EEOP_DOMAIN_NOTNULL, EEOP_DOMAIN_TESTVAL, EEOP_DONE, EEOP_FIELDSELECT, EEOP_FIELDSTORE_DEFORM, EEOP_FIELDSTORE_FORM, EEOP_FUNCEXPR, EEOP_FUNCEXPR_FUSAGE, EEOP_FUNCEXPR_STRICT, EEOP_FUNCEXPR_STRICT_FUSAGE, EEOP_GROUPING_FUNC, EEOP_INNER_FETCHSOME, EEOP_INNER_SYSVAR, EEOP_INNER_VAR, EEOP_IOCOERCE, EEOP_JUMP, EEOP_JUMP_IF_NOT_NULL, EEOP_JUMP_IF_NOT_TRUE, EEOP_JUMP_IF_NULL, EEOP_LAST, EEOP_MAKE_READONLY, EEOP_MINMAX, EEOP_NEXTVALUEEXPR, EEOP_NOT_DISTINCT, EEOP_NULLIF, EEOP_NULLTEST_ISNOTNULL, EEOP_NULLTEST_ISNULL, EEOP_NULLTEST_ROWISNOTNULL, EEOP_NULLTEST_ROWISNULL, EEOP_OUTER_FETCHSOME, EEOP_OUTER_SYSVAR, EEOP_OUTER_VAR, EEOP_PARAM_CALLBACK, EEOP_PARAM_EXEC, EEOP_PARAM_EXTERN, EEOP_QUAL, EEOP_ROW, EEOP_ROWCOMPARE_FINAL, EEOP_ROWCOMPARE_STEP, EEOP_SBSREF_ASSIGN, EEOP_SBSREF_FETCH, EEOP_SBSREF_OLD, EEOP_SBSREF_SUBSCRIPT, EEOP_SCALARARRAYOP, EEOP_SCAN_FETCHSOME, EEOP_SCAN_SYSVAR, EEOP_SCAN_VAR, EEOP_SQLVALUEFUNCTION, EEOP_SUBPLAN, EEOP_WHOLEROW, EEOP_WINDOW_FUNC, EEOP_XMLEXPR, elog, ERROR, EState::es_jit, EState::es_jit_flags, ExprState::evalfunc, ExprState::evalfunc_private, ExecEvalStepOp(), ExecRunCompiledExpr(), ExprEvalStep::fetch, FIELDNO_AGGSTATE_ALL_PERGROUPS, FIELDNO_AGGSTATE_CURAGGCONTEXT, FIELDNO_AGGSTATE_CURPERTRANS, FIELDNO_AGGSTATE_CURRENT_SET, FIELDNO_AGGSTATEPERGROUPDATA_NOTRANSVALUE, FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUE, FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL, FIELDNO_EXPRCONTEXT_AGGNULLS, FIELDNO_EXPRCONTEXT_AGGVALUES, FIELDNO_EXPRCONTEXT_CASEDATUM, FIELDNO_EXPRCONTEXT_CASENULL, FIELDNO_EXPRCONTEXT_DOMAINDATUM, FIELDNO_EXPRCONTEXT_DOMAINNULL, FIELDNO_EXPRCONTEXT_INNERTUPLE, FIELDNO_EXPRCONTEXT_OUTERTUPLE, FIELDNO_EXPRCONTEXT_SCANTUPLE, FIELDNO_EXPRSTATE_RESNULL, FIELDNO_EXPRSTATE_RESULTSLOT, FIELDNO_EXPRSTATE_RESVALUE, FIELDNO_FUNCTIONCALLINFODATA_ISNULL, FIELDNO_NULLABLE_DATUM_ISNULL, FIELDNO_TUPLETABLESLOT_ISNULL, FIELDNO_TUPLETABLESLOT_NVALID, FIELDNO_TUPLETABLESLOT_VALUES, FunctionCallInfoBaseData::flinfo, FmgrInfo::fn_addr, ExprEvalStep::func, FuncExecAggInitGroup, FuncExecAggTransReparent, FuncExecEvalSubscriptingRef, FuncExecEvalSysVar, FuncMakeExpandedObjectReadOnlyInternal, CompiledExprState::funcname, FuncSlotGetsomeattrsInt, i, INSTR_TIME_ACCUM_DIFF, INSTR_TIME_SET_CURRENT, ExprEvalStep::iocoerce, ExprEvalStep::jump, lengthof, llvm_copy_attributes(), llvm_create_context(), llvm_enter_fatal_on_oom(), llvm_expand_funcname(), llvm_get_decl(), llvm_leave_fatal_on_oom(), llvm_mutable_module(), ExprEvalStep::make_readonly, palloc(), palloc0(), ExprState::parent, PGJIT_DEFORM, ExprEvalStep::qualexpr, ExprEvalStep::resnull, ExprEvalStep::resvalue, ExprEvalStep::rowcompare_final, ROWCOMPARE_GE, ROWCOMPARE_GT, ROWCOMPARE_LE, ROWCOMPARE_LT, ExprEvalStep::rowcompare_step, ExprEvalStep::sbsref_subscript, slot_compile_deform(), PlanState::state, ExprState::steps, ExprState::steps_len, StructAggState, StructAggStatePerTransData, StructExprContext, StructExprEvalStep, StructExprState, StructFunctionCallInfoData, StructMemoryContextData, StructNullableDatum, AggState::tmpcontext, AggStatePerTransData::transfn_fcinfo, TypeParamBool, TypePGFunction, TypeSizeT, TypeStorageBool, value, ExprEvalStep::var, WindowFuncExprState::wfuncno, and ExprEvalStep::window_func.

Referenced by _PG_jit_provider_init().

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