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 "catalog/objectaccess.h"
#include "catalog/pg_type.h"
#include "executor/execExpr.h"
#include "executor/execdebug.h"
#include "executor/nodeAgg.h"
#include "executor/nodeSubplan.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
 

Macros

#define build_EvalXFunc(b, mod, funcname, v_state, op, ...)
 

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 LLVMValueRef build_EvalXFuncInt (LLVMBuilderRef b, LLVMModuleRef mod, const char *funcname, LLVMValueRef v_state, ExprEvalStep *op, int natts, LLVMValueRef v_args[])
 
static LLVMValueRef create_LifetimeEnd (LLVMModuleRef mod)
 
bool llvm_compile_expr (ExprState *state)
 

Macro Definition Documentation

◆ build_EvalXFunc

#define build_EvalXFunc (   b,
  mod,
  funcname,
  v_state,
  op,
  ... 
)
Value:
build_EvalXFuncInt(b, mod, funcname, v_state, op, \
lengthof(((LLVMValueRef[]){__VA_ARGS__})), \
((LLVMValueRef[]){__VA_ARGS__}))
#define lengthof(array)
Definition: c.h:668
static LLVMValueRef build_EvalXFuncInt(LLVMBuilderRef b, LLVMModuleRef mod, const char *funcname, LLVMValueRef v_state, ExprEvalStep *op, int natts, LLVMValueRef v_args[])

Definition at line 68 of file llvmjit_expr.c.

Referenced by llvm_compile_expr().

Typedef Documentation

◆ CompiledExprState

Function Documentation

◆ build_EvalXFuncInt()

static LLVMValueRef build_EvalXFuncInt ( LLVMBuilderRef  b,
LLVMModuleRef  mod,
const char *  funcname,
LLVMValueRef  v_state,
ExprEvalStep op,
int  natts,
LLVMValueRef  v_args[] 
)
static

Definition at line 2503 of file llvmjit_expr.c.

References elog, ERROR, i, llvm_pg_func(), palloc(), pfree(), and StructExprEvalStep.

2506 {
2507  LLVMValueRef v_fn = llvm_pg_func(mod, funcname);
2508  LLVMValueRef *params;
2509  int argno = 0;
2510  LLVMValueRef v_ret;
2511 
2512  /* cheap pre-check as llvm just asserts out */
2513  if (LLVMCountParams(v_fn) != (nargs + 2))
2514  elog(ERROR, "parameter mismatch: %s expects %d passed %d",
2515  funcname, LLVMCountParams(v_fn), nargs + 2);
2516 
2517  params = palloc(sizeof(LLVMValueRef) * (2 + nargs));
2518 
2519  params[argno++] = v_state;
2520  params[argno++] = l_ptr_const(op, l_ptr(StructExprEvalStep));
2521 
2522  for (int i = 0; i < nargs; i++)
2523  params[argno++] = v_args[i];
2524 
2525  v_ret = LLVMBuildCall(b, v_fn, params, argno, "");
2526 
2527  pfree(params);
2528 
2529  return v_ret;
2530 }
LLVMTypeRef StructExprEvalStep
Definition: llvmjit.c:72
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
void * palloc(Size size)
Definition: mcxt.c:949
#define elog(elevel,...)
Definition: elog.h:228
int i
LLVMValueRef llvm_pg_func(LLVMModuleRef mod, const char *funcname)
Definition: llvmjit.c:303

◆ BuildV1Call()

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

Definition at line 2457 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().

2460 {
2461  LLVMValueRef v_fn;
2462  LLVMValueRef v_fcinfo_isnullp;
2463  LLVMValueRef v_retval;
2464  LLVMValueRef v_fcinfo;
2465 
2466  v_fn = llvm_function_reference(context, b, mod, fcinfo);
2467 
2468  v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
2469  v_fcinfo_isnullp = LLVMBuildStructGEP(b, v_fcinfo,
2471  "v_fcinfo_isnull");
2472  LLVMBuildStore(b, l_sbool_const(0), v_fcinfo_isnullp);
2473 
2474  v_retval = LLVMBuildCall(b, v_fn, &v_fcinfo, 1, "funccall");
2475 
2476  if (v_fcinfo_isnull)
2477  *v_fcinfo_isnull = LLVMBuildLoad(b, v_fcinfo_isnullp, "");
2478 
2479  /*
2480  * Add lifetime-end annotation, signalling that writes to memory don't
2481  * have to be retained (important for inlining potential).
2482  */
2483  {
2484  LLVMValueRef v_lifetime = create_LifetimeEnd(mod);
2485  LLVMValueRef params[2];
2486 
2487  params[0] = l_int64_const(sizeof(NullableDatum) * fcinfo->nargs);
2488  params[1] = l_ptr_const(fcinfo->args, l_ptr(LLVMInt8Type()));
2489  LLVMBuildCall(b, v_lifetime, params, lengthof(params), "");
2490 
2491  params[0] = l_int64_const(sizeof(fcinfo->isnull));
2492  params[1] = l_ptr_const(&fcinfo->isnull, l_ptr(LLVMInt8Type()));
2493  LLVMBuildCall(b, v_lifetime, params, lengthof(params), "");
2494  }
2495 
2496  return v_retval;
2497 }
#define FIELDNO_FUNCTIONCALLINFODATA_ISNULL
Definition: fmgr.h:91
LLVMTypeRef StructFunctionCallInfoData
Definition: llvmjit.c:70
static LLVMValueRef create_LifetimeEnd(LLVMModuleRef mod)
LLVMValueRef llvm_function_reference(LLVMJitContext *context, LLVMBuilderRef builder, LLVMModuleRef mod, FunctionCallInfo fcinfo)
Definition: llvmjit.c:353
#define lengthof(array)
Definition: c.h:668
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
Definition: fmgr.h:95

◆ create_LifetimeEnd()

static LLVMValueRef create_LifetimeEnd ( LLVMModuleRef  mod)
static

Definition at line 2533 of file llvmjit_expr.c.

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

Referenced by BuildV1Call().

2534 {
2535  LLVMTypeRef sig;
2536  LLVMValueRef fn;
2537  LLVMTypeRef param_types[2];
2538 
2539  /* LLVM 5+ has a variadic pointer argument */
2540 #if LLVM_VERSION_MAJOR < 5
2541  const char *nm = "llvm.lifetime.end";
2542 #else
2543  const char *nm = "llvm.lifetime.end.p0i8";
2544 #endif
2545 
2546  fn = LLVMGetNamedFunction(mod, nm);
2547  if (fn)
2548  return fn;
2549 
2550  param_types[0] = LLVMInt64Type();
2551  param_types[1] = l_ptr(LLVMInt8Type());
2552 
2553  sig = LLVMFunctionType(LLVMVoidType(),
2554  param_types, lengthof(param_types),
2555  false);
2556  fn = LLVMAddFunction(mod, nm, sig);
2557 
2558  LLVMSetFunctionCallConv(fn, LLVMCCallConv);
2559 
2560  Assert(LLVMGetIntrinsicID(fn));
2561 
2562  return fn;
2563 }
#define lengthof(array)
Definition: c.h:668
static int sig
Definition: pg_ctl.c:84
static void * fn(void *arg)
#define Assert(condition)
Definition: c.h:738

◆ ExecRunCompiledExpr()

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

Definition at line 2437 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().

2438 {
2439  CompiledExprState *cstate = state->evalfunc_private;
2440  ExprStateEvalFunc func;
2441 
2442  CheckExprStillValid(state, econtext);
2443 
2445  func = (ExprStateEvalFunc) llvm_get_function(cstate->context,
2446  cstate->funcname);
2448  Assert(func);
2449 
2450  /* remove indirection via this function for future calls */
2451  state->evalfunc = func;
2452 
2453  return func(state, econtext, isNull);
2454 }
Datum(* ExprStateEvalFunc)(struct ExprState *expression, struct ExprContext *econtext, bool *isNull)
Definition: execnodes.h:53
LLVMJitContext * context
Definition: llvmjit_expr.c:50
ExprStateEvalFunc evalfunc
Definition: execnodes.h:91
void * evalfunc_private
Definition: execnodes.h:97
#define Assert(condition)
Definition: c.h:738
void * llvm_get_function(LLVMJitContext *context, const char *funcname)
Definition: llvmjit.c:235
void llvm_enter_fatal_on_oom(void)
const char * funcname
Definition: llvmjit_expr.c:51
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 78 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, castNode, 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, 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_PARENT, 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, ExprEvalStep::func, CompiledExprState::funcname, 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_function_reference(), llvm_leave_fatal_on_oom(), llvm_mutable_module(), llvm_pg_func(), 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, StructAggState, StructAggStatePerTransData, StructExprContext, StructExprState, StructFunctionCallInfoData, StructMemoryContextData, StructNullableDatum, AggState::tmpcontext, AggStatePerTransData::transfn_fcinfo, TTSOpsVirtual, TypeParamBool, TypeSizeT, TypeStorageBool, value, ExprEvalStep::var, WindowFuncExprState::wfuncno, and ExprEvalStep::window_func.

Referenced by _PG_jit_provider_init().

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