PoC. The saving of the compiled jit-code in the plan cache

Started by Vladlen Popolitov11 months ago7 messages
#1Vladlen Popolitov
v.popolitov@postgrespro.ru
4 attachment(s)

Dear colleagues,

I implemented the patch to store in the plan cache an already compiled
jit
code. If a query is executed many times, the query time can be decreased
by
20-30% for long queries with big share of expressions in the code.

This patch can be applied to the current master and passes tests, but it
is
only the Proof of the Concept, and I need to get opinions and advice for
nexts
steps. It is not ready for commitfest, does not cover all scenarios
(craches
in some sutuation that need special solution), and source code is not
clean.

The code source has removed old code marked by // comments to easier
compare,
what was changed, especially in llvmjit_expr.c and llvmjit_deform.c

Implementation details.

1. Changes in jit-code generation.

a) the load of the absolute address (as const) changed to the load of
this
address from a struct member:

old version:
v_resvaluep = l_ptr_const(op->resvalue, l_ptr(TypeSizeT));
new version
v_resvaluep = l_load_struct_gep( b, g->StructExprEvalStep, v_op,
FIELDNO_EXPREVALSTEP_RESVALUE, "v_resvaluep");

b) the load of the absolute address or the value from union changed to
the load of the union value using the offset of the union member

old version
fcinfo - the union member value
v_fcinfo = l_ptr_const(fcinfo, l_ptr(g->StructFunctionCallInfoData));
new version
v_fcinfo = l_load_member_value_by_offset(b,lc, v_op,
l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep,
d.func.fcinfo_data ));

c) every cached plan has own LLVM-context and 1 module in it. As result,
some functions require context parameter to correctly address it instead
of the global llvm_context variable.

d) llvm_types moved from global variables to the struct LLVMJitTypes.
Not cached queries use old setup, but all types definitions are stored
in global struct LLVMJitTypes llvm_jit_types_struct, instead of many
global variables. Chached queries allocate struct LLVMJitTypes during
query
executon, and pfree it when cached plan is deallocated. llvm_types
module is
read for every cached statement (not 1 time during global context
creation).

e) llvm_function_reference still uses l_ptr_const with the absolute
address
of the function, it needs to be checked, as the function can change
address.

f) new GUC variabe jit_cached is added, off by default.

2. Changes in cached plan.
To store cached context I use struct PlannedStmt (in ExprState
state->parent->state->es_plannedstmt).
New member struct CachedJitContext *jit_context added to store
information
about jit context. In new plans this field in NULL. If plan is stored to
cache,
it filled by CACHED_JITCONTEXT_EMPTY and replaced by actual jit context
pointer
in llvmjit_expr.c .
When cached plan is deallocated, this member used to free jit resources
and
memory.

3. Current problems.
When module is compiled, it needs to connect ExprState and function
addresses.
In old implementation funcname is stored in ExprState.
In cached implementation the fuction will be called second and more
times,
and calling code does not have information about function name for
ExprState.
a) The current cached implementation uses the number of the call to
connect
f.e. 1st expresion and 1st function. It does not work for queries, that
generates an expression after module compilation (f.e. HashJoin) and
tries
to compile it.
b) Also query with aggregate functions generates an expresion every
time, when
executed. It work with current approach, but these expressions should be
considered, as they have different expression address every time.

One of the solution for a) and b) - generate jit-code for Expr pointers
only
in cached plan. Every new created expression either should be ignored by
the compiler and executed by the standard interpreter, or compiled in
the
standard (not cached) jit (it will run compilation every query run and
eliminate all gain from jit-cache).

c) new jit-code generation (use the stuct member instead of the direct
absolute address) slightly decreases the jit-code performance. It is
possible
to compile old version for not cached queries, and new code for cached
queries.
In this case two big 3000 lines funtions llvm_compile_expr() need to be
maintained in similar way, when new expresiions or features are added.

Attached files have
1) the patch (branched from 83ea6c54025bea67bcd4949a6d58d3fc11c3e21b
master),
2 and 3) benchmark files jitinit.sql to create jitbench database and
bash
script jitbench.sh (change to own user and password if you need) to run
banchmark.
4) chart for this benchmark and the query in the benchmark (comparison
with jit=off as 1 unit). It is easy to find query, where jit is higher
or
lower than jit-off. Here I demonstate the difference of standard and new
jit-code (the decrease of the performance with compilation without
optimization), and high gain of cached version with optimization and
high lost of not cached version with optimization due to the running
of the optimization for every the query.

--
Best regards,

Vladlen Popolitov.

Attachments:

v4-0001-jit-saved-for-cached-plans.patchtext/x-diff; name=v4-0001-jit-saved-for-cached-plans.patchDownload
From a3be11abb36120ba25aaa0dd8eff26ae84fadaa7 Mon Sep 17 00:00:00 2001
From: Vladlen Popolitov <v.popolitov@postgrespro.ru>
Date: Wed, 12 Feb 2025 21:41:48 +0700
Subject: [PATCH v4] jit saved for cached plans

---
 src/backend/jit/jit.c                 |    1 +
 src/backend/jit/llvm/llvmjit.c        |  202 +++--
 src/backend/jit/llvm/llvmjit_deform.c |   88 +-
 src/backend/jit/llvm/llvmjit_expr.c   | 1065 +++++++++++++++----------
 src/backend/jit/llvm/llvmjit_types.c  |    1 +
 src/backend/nodes/copyfuncs.c         |    3 +
 src/backend/nodes/equalfuncs.c        |    6 +
 src/backend/nodes/gen_node_support.pl |   13 +
 src/backend/nodes/outfuncs.c          |    4 +
 src/backend/nodes/readfuncs.c         |    6 +
 src/backend/utils/cache/plancache.c   |   19 +
 src/backend/utils/misc/guc_tables.c   |   12 +
 src/include/executor/execExpr.h       |    2 +
 src/include/jit/jit.h                 |    1 +
 src/include/jit/llvmjit.h             |   91 ++-
 src/include/jit/llvmjit_emit.h        |   74 +-
 src/include/nodes/execnodes.h         |    3 +
 src/include/nodes/plannodes.h         |    4 +-
 18 files changed, 1039 insertions(+), 556 deletions(-)

diff --git a/src/backend/jit/jit.c b/src/backend/jit/jit.c
index d2ccef9de85..3927f7c5f73 100644
--- a/src/backend/jit/jit.c
+++ b/src/backend/jit/jit.c
@@ -30,6 +30,7 @@
 
 /* GUCs */
 bool		jit_enabled = true;
+bool		jit_cached = false;
 char	   *jit_provider = NULL;
 bool		jit_debugging_support = false;
 bool		jit_dump_bitcode = false;
diff --git a/src/backend/jit/llvm/llvmjit.c b/src/backend/jit/llvm/llvmjit.c
index 614926720fb..e34fa2b11e7 100644
--- a/src/backend/jit/llvm/llvmjit.c
+++ b/src/backend/jit/llvm/llvmjit.c
@@ -53,6 +53,7 @@ typedef struct LLVMJitHandle
 
 
 /* types & functions commonly needed for JITing */
+/*
 LLVMTypeRef TypeSizeT;
 LLVMTypeRef TypeParamBool;
 LLVMTypeRef TypeStorageBool;
@@ -74,10 +75,14 @@ LLVMTypeRef StructAggState;
 LLVMTypeRef StructAggStatePerGroupData;
 LLVMTypeRef StructAggStatePerTransData;
 LLVMTypeRef StructPlanState;
+LLVMTypeRef StructWindowFuncExprState;
 
 LLVMValueRef AttributeTemplate;
 LLVMValueRef ExecEvalSubroutineTemplate;
 LLVMValueRef ExecEvalBoolSubroutineTemplate;
+*/
+char * llvm_expand_funcname_general(struct LLVMJitContext *context, const char *basename, int *counter);
+LLVMJitTypes llvm_jit_types_struct;
 
 static LLVMModuleRef llvm_types_module = NULL;
 
@@ -99,7 +104,8 @@ static LLVMOrcThreadSafeContextRef llvm_ts_context;
 static LLVMOrcLLJITRef llvm_opt0_orc;
 static LLVMOrcLLJITRef llvm_opt3_orc;
 
-
+static void llvm_create_types_context(LLVMJitTypes *jit_types_struct,
+			LLVMModuleRef *llvm_types_module, LLVMContextRef llvm_context);
 static void llvm_release_context(JitContext *context);
 static void llvm_session_initialize(void);
 static void llvm_shutdown(int code, Datum arg);
@@ -232,6 +238,8 @@ llvm_create_context(int jitFlags)
 	context = MemoryContextAllocZero(TopMemoryContext,
 									 sizeof(LLVMJitContext));
 	context->base.flags = jitFlags;
+	context->jit_types = &llvm_jit_types_struct;
+	context->llvm_types_module = llvm_types_module;
 
 	/* ensure cleanup */
 	context->resowner = CurrentResourceOwner;
@@ -242,6 +250,51 @@ llvm_create_context(int jitFlags)
 	return context;
 }
 
+/*
+ * Create a cached context for JITing work.
+ *
+ * The context, including subsidiary resources, will be cleaned up either when
+ * the context is explicitly released.
+ */
+LLVMJitContext *
+llvm_create_cached_context(int jitFlags)
+{
+	LLVMJitContext *context;
+
+	llvm_assert_in_fatal_section();
+
+	llvm_session_initialize();
+
+	context = MemoryContextAllocZero(TopMemoryContext,
+									 sizeof(LLVMJitContext));
+	context->base.flags = jitFlags;
+	context->llvm_context = LLVMContextCreate();
+	context->jit_types = MemoryContextAllocZero(TopMemoryContext,
+									 sizeof(LLVMJitTypes));
+
+
+
+	/// llvm_recreate_llvm_context();
+	/*
+	 * Synchronize types early, as that also includes inferring the target
+	 * triple.
+	 */
+	llvm_create_types_context(context->jit_types, &context->llvm_types_module, context->llvm_context);
+
+	///ResourceOwnerEnlarge(CurrentResourceOwner);
+
+
+
+	/* ensure cleanup */
+	///context->resowner = CurrentResourceOwner;
+	///ResourceOwnerRememberJIT(CurrentResourceOwner, context);
+
+	llvm_jit_context_in_use_count++;
+
+	return context;
+}
+
+
 /*
  * Release resources required by one llvm context.
  */
@@ -272,6 +325,11 @@ llvm_release_context(JitContext *context)
 		LLVMDisposeModule(llvm_jit_context->module);
 		llvm_jit_context->module = NULL;
 	}
+	if (llvm_jit_context->llvm_context && llvm_jit_context->llvm_types_module)
+	{
+		LLVMDisposeModule(llvm_jit_context->llvm_types_module);
+		llvm_jit_context->llvm_types_module = NULL;
+	}
 
 	foreach(lc, llvm_jit_context->handles)
 	{
@@ -304,6 +362,12 @@ llvm_release_context(JitContext *context)
 
 	if (llvm_jit_context->resowner)
 		ResourceOwnerForgetJIT(llvm_jit_context->resowner, llvm_jit_context);
+
+	if (llvm_jit_context->llvm_context)
+	{
+		LLVMContextDispose(llvm_context);
+		llvm_jit_context->llvm_context = NULL;
+	}
 }
 
 /*
@@ -321,7 +385,8 @@ llvm_mutable_module(LLVMJitContext *context)
 	{
 		context->compiled = false;
 		context->module_generation = llvm_generation++;
-		context->module = LLVMModuleCreateWithNameInContext("pg", llvm_context);
+		context->module = LLVMModuleCreateWithNameInContext("pg",
+			context->llvm_context? context->llvm_context : llvm_context);
 		LLVMSetTarget(context->module, llvm_triple);
 		LLVMSetDataLayout(context->module, llvm_layout);
 	}
@@ -335,9 +400,9 @@ llvm_mutable_module(LLVMJitContext *context)
  * a Module.
  */
 char *
-llvm_expand_funcname(struct LLVMJitContext *context, const char *basename)
+llvm_expand_funcname_general(struct LLVMJitContext *context, const char *basename, int *counter)
 {
-	Assert(context->module != NULL);
+	///Assert(context->module != NULL);
 
 	context->base.instr.created_functions++;
 
@@ -348,9 +413,18 @@ llvm_expand_funcname(struct LLVMJitContext *context, const char *basename)
 	return psprintf("%s_%zu_%d",
 					basename,
 					context->module_generation,
-					context->counter++);
+					(*counter)++);
+}
+char *
+llvm_expand_funcname_expr(struct LLVMJitContext *context, const char *basename)
+{
+	return llvm_expand_funcname_general(context, basename, &context->counter_expr);
+}
+char *
+llvm_expand_funcname_deform(struct LLVMJitContext *context, const char *basename)
+{
+	return llvm_expand_funcname_general(context, basename, &context->counter_deform);
 }
-
 /*
  * Return pointer to function funcname, which has to exist. If there's pending
  * code to be optimized and emitted, do so first.
@@ -416,7 +490,7 @@ llvm_get_function(LLVMJitContext *context, const char *funcname)
  * in sync between plain C and JIT related code.
  */
 LLVMTypeRef
-llvm_pg_var_type(const char *varname)
+llvm_pg_var_type(LLVMModuleRef llvm_types_module, const char *varname)
 {
 	LLVMValueRef v_srcvar;
 	LLVMTypeRef typ;
@@ -436,12 +510,12 @@ llvm_pg_var_type(const char *varname)
  * keep function types in sync between C and JITed code.
  */
 LLVMTypeRef
-llvm_pg_var_func_type(const char *varname)
+llvm_pg_var_func_type(LLVMJitContext *context, const char *varname)
 {
 	LLVMValueRef v_srcvar;
 	LLVMTypeRef typ;
 
-	v_srcvar = LLVMGetNamedFunction(llvm_types_module, varname);
+	v_srcvar = LLVMGetNamedFunction(context->llvm_types_module, varname);
 	if (!v_srcvar)
 		elog(ERROR, "function %s not in llvmjit_types.c", varname);
 
@@ -458,22 +532,22 @@ llvm_pg_var_func_type(const char *varname)
  * the module that's currently being worked on.
  */
 LLVMValueRef
-llvm_pg_func(LLVMModuleRef mod, const char *funcname)
+llvm_pg_func(LLVMJitContext *context /*LLVMModuleRef mod*/, const char *funcname)
 {
 	LLVMValueRef v_srcfn;
 	LLVMValueRef v_fn;
 
 	/* don't repeatedly add function */
-	v_fn = LLVMGetNamedFunction(mod, funcname);
+	v_fn = LLVMGetNamedFunction(context->module, funcname);
 	if (v_fn)
 		return v_fn;
 
-	v_srcfn = LLVMGetNamedFunction(llvm_types_module, funcname);
+	v_srcfn = LLVMGetNamedFunction(context->llvm_types_module ? context->llvm_types_module : llvm_types_module, funcname);
 
 	if (!v_srcfn)
 		elog(ERROR, "function %s not in llvmjit_types.c", funcname);
 
-	v_fn = LLVMAddFunction(mod,
+	v_fn = LLVMAddFunction(context->module,
 						   funcname,
 						   LLVMGetFunctionType(v_srcfn));
 	llvm_copy_attributes(v_srcfn, v_fn);
@@ -537,7 +611,8 @@ LLVMValueRef
 llvm_function_reference(LLVMJitContext *context,
 						LLVMBuilderRef builder,
 						LLVMModuleRef mod,
-						FunctionCallInfo fcinfo)
+						FunctionCallInfo fcinfo,
+						LLVMValueRef v_fcinfo)
 {
 	char	   *modname;
 	char	   *basename;
@@ -570,17 +645,22 @@ llvm_function_reference(LLVMJitContext *context,
 							fcinfo->flinfo->fn_oid);
 		v_fn = LLVMGetNamedGlobal(mod, funcname);
 		if (v_fn != 0)
-			return l_load(builder, TypePGFunction, v_fn, "");
-
-		v_fn_addr = l_ptr_const(fcinfo->flinfo->fn_addr, TypePGFunction);
-
-		v_fn = LLVMAddGlobal(mod, TypePGFunction, funcname);
+			return l_load(builder, context->jit_types->TypePGFunction, v_fn, "");
+
+		v_fn_addr = l_ptr_const(fcinfo->flinfo->fn_addr, context->jit_types->TypePGFunction, context->jit_types->TypeSizeT);
+		///tmp = l_ptr_const_step(d.hashdatum.iresult, l_ptr(g->StructNullableDatum));
+		///tmp = l_struct_gep(b, g->StructNullableDatum, tmp, FIELDNO_NULLABLE_DATUM_DATUM, "");
+		/// params[1] =  ///l_ptr_const(fcinfo->args, l_ptr(LLVMInt8TypeInContext(lc)));
+		///			l_load_member_value_by_offset(b, lc , v_fcinfo, l_ptr(LLVMInt8TypeInContext(lc)), offsetof(FunctionCallInfoBaseData, args));
+		////v_fn_addr = l_load_member_value_by_offset(builder, lc , v_fcinfo, l_ptr(LLVMInt8TypeInContext(lc)), offsetof(FunctionCallInfoBaseData, flinfo));
+		////v_fn_addr = l_load_member_value_by_offset(builder, lc , v_fn_addr, context->jit_types->TypePGFunction, offsetof(FmgrInfo, fn_addr));
+		v_fn = LLVMAddGlobal(mod, context->jit_types->TypePGFunction, funcname);
 		LLVMSetInitializer(v_fn, v_fn_addr);
 		LLVMSetGlobalConstant(v_fn, true);
 		LLVMSetLinkage(v_fn, LLVMPrivateLinkage);
 		LLVMSetUnnamedAddr(v_fn, true);
 
-		return l_load(builder, TypePGFunction, v_fn, "");
+		return l_load(builder, context->jit_types->TypePGFunction, v_fn, "");
 	}
 
 	/* check if function already has been added */
@@ -588,7 +668,7 @@ llvm_function_reference(LLVMJitContext *context,
 	if (v_fn != 0)
 		return v_fn;
 
-	v_fn = LLVMAddFunction(mod, funcname, LLVMGetFunctionType(AttributeTemplate));
+	v_fn = LLVMAddFunction(mod, funcname, LLVMGetFunctionType(context->jit_types->AttributeTemplate));
 
 	return v_fn;
 }
@@ -779,6 +859,9 @@ llvm_compile_module(LLVMJitContext *context)
 		 */
 
 		context->module = NULL; /* will be owned by LLJIT */
+		context->counter_expr = 0;
+		context->counter_deform = 0;
+
 		error = LLVMOrcLLJITAddLLVMIRModuleWithRT(compile_orc,
 												  handle->resource_tracker,
 												  ts_module);
@@ -795,6 +878,8 @@ llvm_compile_module(LLVMJitContext *context)
 						  endtime, starttime);
 
 	context->module = NULL;
+	context->counter_expr = 0;
+	context->counter_deform = 0;
 	context->compiled = true;
 
 	/* remember emitted code for cleanup and lookups */
@@ -980,12 +1065,10 @@ llvm_set_target(void)
 
 /*
  * Load required information, types, function signatures from llvmjit_types.c
- * and make them available in global variables.
- *
- * Those global variables are then used while emitting code.
+ * and save it in LLVMJitTypes struct.
  */
 static void
-llvm_create_types(void)
+llvm_create_types_context(LLVMJitTypes *jit_types_struct, LLVMModuleRef *llvm_types_module, LLVMContextRef llvm_context)
 {
 	char		path[MAXPGPATH];
 	LLVMMemoryBufferRef buf;
@@ -1001,39 +1084,56 @@ llvm_create_types(void)
 	}
 
 	/* eagerly load contents, going to need it all */
-	if (LLVMParseBitcodeInContext2(llvm_context, buf, &llvm_types_module))
+	if (LLVMParseBitcodeInContext2(llvm_context, buf, llvm_types_module))
 	{
 		elog(ERROR, "LLVMParseBitcodeInContext2 of %s failed", path);
 	}
 	LLVMDisposeMemoryBuffer(buf);
 
-	TypeSizeT = llvm_pg_var_type("TypeSizeT");
-	TypeParamBool = load_return_type(llvm_types_module, "FunctionReturningBool");
-	TypeStorageBool = llvm_pg_var_type("TypeStorageBool");
-	TypePGFunction = llvm_pg_var_type("TypePGFunction");
-	StructNullableDatum = llvm_pg_var_type("StructNullableDatum");
-	StructExprContext = llvm_pg_var_type("StructExprContext");
-	StructExprEvalStep = llvm_pg_var_type("StructExprEvalStep");
-	StructExprState = llvm_pg_var_type("StructExprState");
-	StructFunctionCallInfoData = llvm_pg_var_type("StructFunctionCallInfoData");
-	StructMemoryContextData = llvm_pg_var_type("StructMemoryContextData");
-	StructTupleTableSlot = llvm_pg_var_type("StructTupleTableSlot");
-	StructHeapTupleTableSlot = llvm_pg_var_type("StructHeapTupleTableSlot");
-	StructMinimalTupleTableSlot = llvm_pg_var_type("StructMinimalTupleTableSlot");
-	StructHeapTupleData = llvm_pg_var_type("StructHeapTupleData");
-	StructHeapTupleHeaderData = llvm_pg_var_type("StructHeapTupleHeaderData");
-	StructTupleDescData = llvm_pg_var_type("StructTupleDescData");
-	StructAggState = llvm_pg_var_type("StructAggState");
-	StructAggStatePerGroupData = llvm_pg_var_type("StructAggStatePerGroupData");
-	StructAggStatePerTransData = llvm_pg_var_type("StructAggStatePerTransData");
-	StructPlanState = llvm_pg_var_type("StructPlanState");
-	StructMinimalTupleData = llvm_pg_var_type("StructMinimalTupleData");
-
-	AttributeTemplate = LLVMGetNamedFunction(llvm_types_module, "AttributeTemplate");
-	ExecEvalSubroutineTemplate = LLVMGetNamedFunction(llvm_types_module, "ExecEvalSubroutineTemplate");
-	ExecEvalBoolSubroutineTemplate = LLVMGetNamedFunction(llvm_types_module, "ExecEvalBoolSubroutineTemplate");
+	jit_types_struct->TypeSizeT = llvm_pg_var_type(*llvm_types_module, "TypeSizeT");
+	jit_types_struct->TypeParamBool = load_return_type(*llvm_types_module, "FunctionReturningBool");
+	jit_types_struct->TypeStorageBool = llvm_pg_var_type(*llvm_types_module, "TypeStorageBool");
+	jit_types_struct->TypePGFunction = llvm_pg_var_type(*llvm_types_module, "TypePGFunction");
+	jit_types_struct->StructNullableDatum = llvm_pg_var_type(*llvm_types_module, "StructNullableDatum");
+	jit_types_struct->StructExprContext = llvm_pg_var_type(*llvm_types_module, "StructExprContext");
+	jit_types_struct->StructExprEvalStep = llvm_pg_var_type(*llvm_types_module, "StructExprEvalStep");
+	jit_types_struct->StructExprState = llvm_pg_var_type(*llvm_types_module, "StructExprState");
+	jit_types_struct->StructFunctionCallInfoData = llvm_pg_var_type(*llvm_types_module, "StructFunctionCallInfoData");
+	jit_types_struct->StructMemoryContextData = llvm_pg_var_type(*llvm_types_module, "StructMemoryContextData");
+	jit_types_struct->StructTupleTableSlot = llvm_pg_var_type(*llvm_types_module, "StructTupleTableSlot");
+	jit_types_struct->StructHeapTupleTableSlot = llvm_pg_var_type(*llvm_types_module, "StructHeapTupleTableSlot");
+	jit_types_struct->StructMinimalTupleTableSlot = llvm_pg_var_type(*llvm_types_module, "StructMinimalTupleTableSlot");
+	jit_types_struct->StructHeapTupleData = llvm_pg_var_type(*llvm_types_module, "StructHeapTupleData");
+	jit_types_struct->StructHeapTupleHeaderData = llvm_pg_var_type(*llvm_types_module, "StructHeapTupleHeaderData");
+	jit_types_struct->StructTupleDescData = llvm_pg_var_type(*llvm_types_module, "StructTupleDescData");
+	jit_types_struct->StructAggState = llvm_pg_var_type(*llvm_types_module, "StructAggState");
+	jit_types_struct->StructAggStatePerGroupData = llvm_pg_var_type(*llvm_types_module, "StructAggStatePerGroupData");
+	jit_types_struct->StructAggStatePerTransData = llvm_pg_var_type(*llvm_types_module, "StructAggStatePerTransData");
+	jit_types_struct->StructPlanState = llvm_pg_var_type(*llvm_types_module, "StructPlanState");
+	jit_types_struct->StructMinimalTupleData = llvm_pg_var_type(*llvm_types_module, "StructMinimalTupleData");
+	jit_types_struct->StructWindowFuncExprState = llvm_pg_var_type(*llvm_types_module, "StructWindowFuncExprState");
+
+	jit_types_struct->AttributeTemplate = LLVMGetNamedFunction(*llvm_types_module, "AttributeTemplate");
+	jit_types_struct->ExecEvalSubroutineTemplate = LLVMGetNamedFunction(*llvm_types_module, "ExecEvalSubroutineTemplate");
+	jit_types_struct->ExecEvalBoolSubroutineTemplate = LLVMGetNamedFunction(*llvm_types_module, "ExecEvalBoolSubroutineTemplate");
+	{
+		char *error = NULL;
+		LLVMVerifyModule(*llvm_types_module, LLVMAbortProcessAction, &error);
+		LLVMDisposeMessage(error);
+	}
 }
 
+/*
+ * Load required information, types, function signatures from llvmjit_types.c
+ * and make them available in global variables.
+ *
+ * Those global variables are then used while emitting code.
+ */
+static void
+llvm_create_types(void)
+{
+	llvm_create_types_context(&llvm_jit_types_struct, &llvm_types_module, llvm_context);
+}
 /*
  * Split a symbol into module / function parts.  If the function is in the
  * main binary (or an external library) *modname will be NULL.
diff --git a/src/backend/jit/llvm/llvmjit_deform.c b/src/backend/jit/llvm/llvmjit_deform.c
index 5d169c7a40b..98b32a4954c 100644
--- a/src/backend/jit/llvm/llvmjit_deform.c
+++ b/src/backend/jit/llvm/llvmjit_deform.c
@@ -78,6 +78,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 	LLVMValueRef v_hoff;
 
 	LLVMValueRef v_hasnulls;
+	LLVMJitTypes	*g;
 
 	/* last column (0 indexed) guaranteed to exist */
 	int			guaranteed_column_number = -1;
@@ -101,8 +102,9 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 
 	mod = llvm_mutable_module(context);
 	lc = LLVMGetModuleContext(mod);
+	g = context->jit_types;
 
-	funcname = llvm_expand_funcname(context, "deform");
+	funcname = llvm_expand_funcname_deform(context, "deform");
 
 	/*
 	 * Check which columns have to exist, so we don't have to check the row's
@@ -133,7 +135,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 	{
 		LLVMTypeRef param_types[1];
 
-		param_types[0] = l_ptr(StructTupleTableSlot);
+		param_types[0] = l_ptr(g->StructTupleTableSlot);
 
 		deform_sig = LLVMFunctionType(LLVMVoidTypeInContext(lc),
 									  param_types, lengthof(param_types), 0);
@@ -141,7 +143,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 	v_deform_fn = LLVMAddFunction(mod, funcname, deform_sig);
 	LLVMSetLinkage(v_deform_fn, LLVMInternalLinkage);
 	LLVMSetParamAlignment(LLVMGetParam(v_deform_fn, 0), MAXIMUM_ALIGNOF);
-	llvm_copy_attributes(AttributeTemplate, v_deform_fn);
+	llvm_copy_attributes(g->AttributeTemplate, v_deform_fn);
 
 	b_entry =
 		LLVMAppendBasicBlockInContext(lc, v_deform_fn, "entry");
@@ -168,18 +170,18 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 	LLVMPositionBuilderAtEnd(b, b_entry);
 
 	/* perform allocas first, llvm only converts those to registers */
-	v_offp = LLVMBuildAlloca(b, TypeSizeT, "v_offp");
+	v_offp = LLVMBuildAlloca(b, g->TypeSizeT, "v_offp");
 
 	v_slot = LLVMGetParam(v_deform_fn, 0);
 
 	v_tts_values =
-		l_load_struct_gep(b, StructTupleTableSlot, v_slot, FIELDNO_TUPLETABLESLOT_VALUES,
+		l_load_struct_gep(b, g->StructTupleTableSlot, v_slot, FIELDNO_TUPLETABLESLOT_VALUES,
 						  "tts_values");
 	v_tts_nulls =
-		l_load_struct_gep(b, StructTupleTableSlot, v_slot, FIELDNO_TUPLETABLESLOT_ISNULL,
+		l_load_struct_gep(b, g->StructTupleTableSlot, v_slot, FIELDNO_TUPLETABLESLOT_ISNULL,
 						  "tts_ISNULL");
-	v_flagsp = l_struct_gep(b, StructTupleTableSlot, v_slot, FIELDNO_TUPLETABLESLOT_FLAGS, "");
-	v_nvalidp = l_struct_gep(b, StructTupleTableSlot, v_slot, FIELDNO_TUPLETABLESLOT_NVALID, "");
+	v_flagsp = l_struct_gep(b, g->StructTupleTableSlot, v_slot, FIELDNO_TUPLETABLESLOT_FLAGS, "");
+	v_nvalidp = l_struct_gep(b, g->StructTupleTableSlot, v_slot, FIELDNO_TUPLETABLESLOT_NVALID, "");
 
 	if (ops == &TTSOpsHeapTuple || ops == &TTSOpsBufferHeapTuple)
 	{
@@ -188,11 +190,11 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 		v_heapslot =
 			LLVMBuildBitCast(b,
 							 v_slot,
-							 l_ptr(StructHeapTupleTableSlot),
+							 l_ptr(g->StructHeapTupleTableSlot),
 							 "heapslot");
-		v_slotoffp = l_struct_gep(b, StructHeapTupleTableSlot, v_heapslot, FIELDNO_HEAPTUPLETABLESLOT_OFF, "");
+		v_slotoffp = l_struct_gep(b, g->StructHeapTupleTableSlot, v_heapslot, FIELDNO_HEAPTUPLETABLESLOT_OFF, "");
 		v_tupleheaderp =
-			l_load_struct_gep(b, StructHeapTupleTableSlot, v_heapslot, FIELDNO_HEAPTUPLETABLESLOT_TUPLE,
+			l_load_struct_gep(b, g->StructHeapTupleTableSlot, v_heapslot, FIELDNO_HEAPTUPLETABLESLOT_TUPLE,
 							  "tupleheader");
 	}
 	else if (ops == &TTSOpsMinimalTuple)
@@ -202,15 +204,15 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 		v_minimalslot =
 			LLVMBuildBitCast(b,
 							 v_slot,
-							 l_ptr(StructMinimalTupleTableSlot),
+							 l_ptr(g->StructMinimalTupleTableSlot),
 							 "minimalslot");
 		v_slotoffp = l_struct_gep(b,
-								  StructMinimalTupleTableSlot,
+								  g->StructMinimalTupleTableSlot,
 								  v_minimalslot,
 								  FIELDNO_MINIMALTUPLETABLESLOT_OFF, "");
 		v_tupleheaderp =
 			l_load_struct_gep(b,
-							  StructMinimalTupleTableSlot,
+							  g->StructMinimalTupleTableSlot,
 							  v_minimalslot,
 							  FIELDNO_MINIMALTUPLETABLESLOT_TUPLE,
 							  "tupleheader");
@@ -223,14 +225,14 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 
 	v_tuplep =
 		l_load_struct_gep(b,
-						  StructHeapTupleData,
+						  g->StructHeapTupleData,
 						  v_tupleheaderp,
 						  FIELDNO_HEAPTUPLEDATA_DATA,
 						  "tuple");
 	v_bits =
 		LLVMBuildBitCast(b,
 						 l_struct_gep(b,
-									  StructHeapTupleHeaderData,
+									  g->StructHeapTupleHeaderData,
 									  v_tuplep,
 									  FIELDNO_HEAPTUPLEHEADERDATA_BITS,
 									  ""),
@@ -238,13 +240,13 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 						 "t_bits");
 	v_infomask1 =
 		l_load_struct_gep(b,
-						  StructHeapTupleHeaderData,
+						  g->StructHeapTupleHeaderData,
 						  v_tuplep,
 						  FIELDNO_HEAPTUPLEHEADERDATA_INFOMASK,
 						  "infomask1");
 	v_infomask2 =
 		l_load_struct_gep(b,
-						  StructHeapTupleHeaderData,
+						  g->StructHeapTupleHeaderData,
 						  v_tuplep, FIELDNO_HEAPTUPLEHEADERDATA_INFOMASK2,
 						  "infomask2");
 
@@ -270,7 +272,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 	v_hoff =
 		LLVMBuildZExt(b,
 					  l_load_struct_gep(b,
-										StructHeapTupleHeaderData,
+										g->StructHeapTupleHeaderData,
 										v_tuplep,
 										FIELDNO_HEAPTUPLEHEADERDATA_HOFF,
 										""),
@@ -293,7 +295,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 		LLVMValueRef v_off_start;
 
 		v_off_start = l_load(b, LLVMInt32TypeInContext(lc), v_slotoffp, "v_slot_off");
-		v_off_start = LLVMBuildZExt(b, v_off_start, TypeSizeT, "");
+		v_off_start = LLVMBuildZExt(b, v_off_start, g->TypeSizeT, "");
 		LLVMBuildStore(b, v_off_start, v_offp);
 	}
 
@@ -349,7 +351,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 		v_params[0] = v_slot;
 		v_params[1] = LLVMBuildZExt(b, v_maxatt, LLVMInt32TypeInContext(lc), "");
 		v_params[2] = l_int32_const(lc, natts);
-		f = llvm_pg_func(mod, "slot_getmissingattrs");
+		f = llvm_pg_func(context, "slot_getmissingattrs");
 		l_call(b,
 			   LLVMGetFunctionType(f), f,
 			   v_params, lengthof(v_params), "");
@@ -409,7 +411,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 		 */
 		if (attnum == 0)
 		{
-			LLVMBuildStore(b, l_sizet_const(0), v_offp);
+			LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_offp);
 		}
 
 		/*
@@ -479,8 +481,8 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 						   l_gep(b, LLVMInt8TypeInContext(lc), v_tts_nulls, &l_attno, 1, ""));
 			/* store zero datum */
 			LLVMBuildStore(b,
-						   l_sizet_const(0),
-						   l_gep(b, TypeSizeT, v_tts_values, &l_attno, 1, ""));
+						   LLVMConstInt(g->TypeSizeT, 0, false),
+						   l_gep(b, g->TypeSizeT, v_tts_values, &l_attno, 1, ""));
 
 			LLVMBuildBr(b, b_next);
 			attguaranteedalign = false;
@@ -524,7 +526,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 				/* don't know if short varlena or not */
 				attguaranteedalign = false;
 
-				v_off = l_load(b, TypeSizeT, v_offp, "");
+				v_off = l_load(b, g->TypeSizeT, v_offp, "");
 
 				v_possible_padbyte =
 					l_load_gep1(b, LLVMInt8TypeInContext(lc), v_tupdata_base, v_off, "padbyte");
@@ -546,16 +548,16 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 			/* translation of alignment code (cf TYPEALIGN()) */
 			{
 				LLVMValueRef v_off_aligned;
-				LLVMValueRef v_off = l_load(b, TypeSizeT, v_offp, "");
+				LLVMValueRef v_off = l_load(b, g->TypeSizeT, v_offp, "");
 
 				/* ((ALIGNVAL) - 1) */
-				LLVMValueRef v_alignval = l_sizet_const(alignto - 1);
+				LLVMValueRef v_alignval = LLVMConstInt(g->TypeSizeT, alignto - 1, false);
 
 				/* ((uintptr_t) (LEN) + ((ALIGNVAL) - 1)) */
 				LLVMValueRef v_lh = LLVMBuildAdd(b, v_off, v_alignval, "");
 
 				/* ~((uintptr_t) ((ALIGNVAL) - 1)) */
-				LLVMValueRef v_rh = l_sizet_const(~(alignto - 1));
+				LLVMValueRef v_rh = LLVMConstInt(g->TypeSizeT, ~(alignto - 1), false);
 
 				v_off_aligned = LLVMBuildAnd(b, v_lh, v_rh, "aligned_offset");
 
@@ -594,7 +596,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 		if (attguaranteedalign)
 		{
 			Assert(known_alignment >= 0);
-			LLVMBuildStore(b, l_sizet_const(known_alignment), v_offp);
+			LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, known_alignment, false), v_offp);
 		}
 
 		/* compute what following columns are aligned to */
@@ -635,18 +637,18 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 
 		/* compute address to load data from */
 		{
-			LLVMValueRef v_off = l_load(b, TypeSizeT, v_offp, "");
+			LLVMValueRef v_off = l_load(b, g->TypeSizeT, v_offp, "");
 
 			v_attdatap =
 				l_gep(b, LLVMInt8TypeInContext(lc), v_tupdata_base, &v_off, 1, "");
 		}
 
 		/* compute address to store value at */
-		v_resultp = l_gep(b, TypeSizeT, v_tts_values, &l_attno, 1, "");
+		v_resultp = l_gep(b, g->TypeSizeT, v_tts_values, &l_attno, 1, "");
 
 		/* store null-byte (false) */
 		LLVMBuildStore(b, l_int8_const(lc, 0),
-					   l_gep(b, TypeStorageBool, v_tts_nulls, &l_attno, 1, ""));
+					   l_gep(b, g->TypeStorageBool, v_tts_nulls, &l_attno, 1, ""));
 
 		/*
 		 * Store datum. For byval: datums copy the value, extend to Datum's
@@ -661,7 +663,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 			v_tmp_loaddata =
 				LLVMBuildPointerCast(b, v_attdatap, vartypep, "");
 			v_tmp_loaddata = l_load(b, vartype, v_tmp_loaddata, "attr_byval");
-			v_tmp_loaddata = LLVMBuildZExt(b, v_tmp_loaddata, TypeSizeT, "");
+			v_tmp_loaddata = LLVMBuildZExt(b, v_tmp_loaddata, g->TypeSizeT, "");
 
 			LLVMBuildStore(b, v_tmp_loaddata, v_resultp);
 		}
@@ -673,7 +675,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 			v_tmp_loaddata =
 				LLVMBuildPtrToInt(b,
 								  v_attdatap,
-								  TypeSizeT,
+								  g->TypeSizeT,
 								  "attr_ptr");
 			LLVMBuildStore(b, v_tmp_loaddata, v_resultp);
 		}
@@ -681,13 +683,13 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 		/* increment data pointer */
 		if (att->attlen > 0)
 		{
-			v_incby = l_sizet_const(att->attlen);
+			v_incby = LLVMConstInt(g->TypeSizeT, att->attlen, false);
 		}
 		else if (att->attlen == -1)
 		{
 			v_incby = l_call(b,
-							 llvm_pg_var_func_type("varsize_any"),
-							 llvm_pg_func(mod, "varsize_any"),
+							 llvm_pg_var_func_type(context, "varsize_any"),
+							 llvm_pg_func(context, "varsize_any"),
 							 &v_attdatap, 1,
 							 "varsize_any");
 			l_callsite_ro(v_incby);
@@ -696,14 +698,14 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 		else if (att->attlen == -2)
 		{
 			v_incby = l_call(b,
-							 llvm_pg_var_func_type("strlen"),
-							 llvm_pg_func(mod, "strlen"),
+							 llvm_pg_var_func_type(context, "strlen"),
+							 llvm_pg_func(context, "strlen"),
 							 &v_attdatap, 1, "strlen");
 
 			l_callsite_ro(v_incby);
 
 			/* add 1 for NUL byte */
-			v_incby = LLVMBuildAdd(b, v_incby, l_sizet_const(1), "");
+			v_incby = LLVMBuildAdd(b, v_incby, LLVMConstInt(g->TypeSizeT, 1, false), "");
 		}
 		else
 		{
@@ -714,11 +716,11 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 		if (attguaranteedalign)
 		{
 			Assert(known_alignment >= 0);
-			LLVMBuildStore(b, l_sizet_const(known_alignment), v_offp);
+			LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, known_alignment, false), v_offp);
 		}
 		else
 		{
-			LLVMValueRef v_off = l_load(b, TypeSizeT, v_offp, "");
+			LLVMValueRef v_off = l_load(b, g->TypeSizeT, v_offp, "");
 
 			v_off = LLVMBuildAdd(b, v_off, v_incby, "increment_offset");
 			LLVMBuildStore(b, v_off, v_offp);
@@ -744,7 +746,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 	LLVMPositionBuilderAtEnd(b, b_out);
 
 	{
-		LLVMValueRef v_off = l_load(b, TypeSizeT, v_offp, "");
+		LLVMValueRef v_off = l_load(b, g->TypeSizeT, v_offp, "");
 		LLVMValueRef v_flags;
 
 		LLVMBuildStore(b, l_int16_const(lc, natts), v_nvalidp);
diff --git a/src/backend/jit/llvm/llvmjit_expr.c b/src/backend/jit/llvm/llvmjit_expr.c
index f0f5c3bd49f..91968ea248f 100644
--- a/src/backend/jit/llvm/llvmjit_expr.c
+++ b/src/backend/jit/llvm/llvmjit_expr.c
@@ -17,6 +17,7 @@
 
 #include <llvm-c/Core.h>
 #include <llvm-c/Target.h>
+#include <llvm-c/Analysis.h>
 
 #include "access/htup_details.h"
 #include "access/nbtree.h"
@@ -57,16 +58,22 @@ static Datum ExecRunCompiledExpr(ExprState *state, ExprContext *econtext, bool *
 static LLVMValueRef BuildV1Call(LLVMJitContext *context, LLVMBuilderRef b,
 								LLVMModuleRef mod, FunctionCallInfo fcinfo,
 								LLVMValueRef *v_fcinfo_isnull);
+static LLVMValueRef BuildV1CallLLVM(LLVMJitContext *context, LLVMBuilderRef b,
+			LLVMModuleRef mod, FunctionCallInfo fcinfo,
+			LLVMValueRef v_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 build_EvalXFuncIntLLVM(LLVMBuilderRef b, LLVMJitContext *context, const char *funcname,
+				   LLVMValueRef v_state, LLVMValueRef v_op,
+				   int nargs, LLVMValueRef *v_args);
 static LLVMValueRef create_LifetimeEnd(LLVMModuleRef mod);
 
 /* macro making it easier to call ExecEval* functions */
-#define build_EvalXFunc(b, mod, funcname, v_state, op, ...) \
-	build_EvalXFuncInt(b, mod, funcname, v_state, op, \
+#define build_EvalXFunc(b, context, funcname, v_state, op, ...) \
+	build_EvalXFuncIntLLVM(b, context, funcname, v_state, op, \
 					   lengthof(((LLVMValueRef[]){__VA_ARGS__})), \
 					   ((LLVMValueRef[]){__VA_ARGS__}))
 
@@ -84,6 +91,7 @@ llvm_compile_expr(ExprState *state)
 
 	LLVMBuilderRef b;
 	LLVMModuleRef mod;
+	LLVMModuleRef typesmod;
 	LLVMContextRef lc;
 	LLVMValueRef eval_fn;
 	LLVMBasicBlockRef entry;
@@ -93,6 +101,7 @@ llvm_compile_expr(ExprState *state)
 	LLVMValueRef v_state;
 	LLVMValueRef v_econtext;
 	LLVMValueRef v_parent;
+	LLVMValueRef v_steps;
 
 	/* returnvalue */
 	LLVMValueRef v_isnullp;
@@ -132,6 +141,9 @@ llvm_compile_expr(ExprState *state)
 	instr_time	endtime;
 	instr_time	deform_endtime;
 
+	bool		cached_plan;
+	LLVMJitTypes	*g;
+
 	llvm_enter_fatal_on_oom();
 
 	/*
@@ -141,29 +153,82 @@ llvm_compile_expr(ExprState *state)
 	Assert(parent);
 
 	/* get or create JIT context */
-	if (parent->state->es_jit)
-		context = (LLVMJitContext *) parent->state->es_jit;
-	else
+	if (parent->state->es_plannedstmt->jit_context == NULL || !jit_cached)
 	{
-		context = llvm_create_context(parent->state->es_jit_flags);
-		parent->state->es_jit = &context->base;
+		if (parent->state->es_jit)
+			context = (LLVMJitContext *) parent->state->es_jit;
+		else
+		{
+			context = llvm_create_context(parent->state->es_jit_flags);
+			parent->state->es_jit = &context->base;
+		}
+		mod = llvm_mutable_module(context);
+		funcname = llvm_expand_funcname_expr(context, "evalexpr");
+
+		cached_plan = false;
+		g = context->jit_types;
 	}
+	else
+	{
+		cached_plan = true;
+		if (parent->state->es_plannedstmt->jit_context == CACHED_JITCONTEXT_EMPTY)
+		{
+			parent->state->es_plannedstmt->jit_context = llvm_create_cached_context(parent->state->es_jit_flags);
+			parent->state->es_plannedstmt->jit_context->jit.first_expr = state->expr;
+
+		}
 
+
+		context = &parent->state->es_plannedstmt->jit_context->jit;
+		context->first_expr = state->expr;
+
+		g = context->jit_types;
+		if (!parent->state->es_plannedstmt->jit_context->jit.compiled)
+		{
+			mod = llvm_mutable_module(context);
+			funcname = llvm_expand_funcname_expr(context, "evalexpr");
+			context->max_counter_expr = context->counter_expr;
+			///elog(NOTICE,"Compile %s max %d counter %d, context=%zx", funcname, context->max_counter_expr , context->counter_expr, (Size)context);
+		}
+		else
+		{
+			ExprStateEvalFunc func;
+			/* find and assign binary function: first call - first expression
+				Attention!
+				This alogorithm is wrong and will fail, if query compiles additional
+				expressions after the module compilation (f.e. for HashJoin). Needs new implementation
+				to assign expressions and compiled functions
+			*/
+			///elog(NOTICE,"1 Look for Compiled before max %d counter %d, context=%zx", context->max_counter_expr , context->counter_expr, (Size)context);
+			if (context->max_counter_expr == context->counter_expr)
+			{
+				context->counter_expr = 0;
+				context->counter_deform = 0;
+			}
+			funcname = llvm_expand_funcname_expr(context, "evalexpr");
+			func = (ExprStateEvalFunc) llvm_get_function(context,funcname);
+			llvm_leave_fatal_on_oom();
+			Assert(func);
+			/* remove indirection via this function for future calls */
+			state->evalfunc = func;
+			pfree(funcname);
+			return true;
+		}
+	}
 	INSTR_TIME_SET_CURRENT(starttime);
 
-	mod = llvm_mutable_module(context);
 	lc = LLVMGetModuleContext(mod);
+	typesmod = context->llvm_types_module;
 
 	b = LLVMCreateBuilderInContext(lc);
 
-	funcname = llvm_expand_funcname(context, "evalexpr");
 
 	/* create function */
 	eval_fn = LLVMAddFunction(mod, funcname,
-							  llvm_pg_var_func_type("ExecInterpExprStillValid"));
+							  llvm_pg_var_func_type(context, "ExecInterpExprStillValid"));
 	LLVMSetLinkage(eval_fn, LLVMExternalLinkage);
 	LLVMSetVisibility(eval_fn, LLVMDefaultVisibility);
-	llvm_copy_attributes(AttributeTemplate, eval_fn);
+	llvm_copy_attributes(g->AttributeTemplate, eval_fn);
 
 	entry = LLVMAppendBasicBlockInContext(lc, eval_fn, "entry");
 
@@ -175,123 +240,128 @@ llvm_compile_expr(ExprState *state)
 	LLVMPositionBuilderAtEnd(b, entry);
 
 	v_tmpvaluep = l_struct_gep(b,
-							   StructExprState,
+							   g->StructExprState,
 							   v_state,
 							   FIELDNO_EXPRSTATE_RESVALUE,
 							   "v.state.resvalue");
 	v_tmpisnullp = l_struct_gep(b,
-								StructExprState,
+								g->StructExprState,
 								v_state,
 								FIELDNO_EXPRSTATE_RESNULL,
 								"v.state.resnull");
 	v_parent = l_load_struct_gep(b,
-								 StructExprState,
+								 g->StructExprState,
 								 v_state,
 								 FIELDNO_EXPRSTATE_PARENT,
 								 "v.state.parent");
+	v_steps = l_load_struct_gep(b,
+								g->StructExprState,
+								v_state,
+								FIELDNO_EXPRSTATE_STEPS,
+								"v_state_steps");
 
 	/* build global slots */
 	v_scanslot = l_load_struct_gep(b,
-								   StructExprContext,
+								   g->StructExprContext,
 								   v_econtext,
 								   FIELDNO_EXPRCONTEXT_SCANTUPLE,
 								   "v_scanslot");
 	v_innerslot = l_load_struct_gep(b,
-									StructExprContext,
+									g->StructExprContext,
 									v_econtext,
 									FIELDNO_EXPRCONTEXT_INNERTUPLE,
 									"v_innerslot");
 	v_outerslot = l_load_struct_gep(b,
-									StructExprContext,
+									g->StructExprContext,
 									v_econtext,
 									FIELDNO_EXPRCONTEXT_OUTERTUPLE,
 									"v_outerslot");
 	v_oldslot = l_load_struct_gep(b,
-								  StructExprContext,
+								  g->StructExprContext,
 								  v_econtext,
 								  FIELDNO_EXPRCONTEXT_OLDTUPLE,
 								  "v_oldslot");
 	v_newslot = l_load_struct_gep(b,
-								  StructExprContext,
+								  g->StructExprContext,
 								  v_econtext,
 								  FIELDNO_EXPRCONTEXT_NEWTUPLE,
 								  "v_newslot");
 	v_resultslot = l_load_struct_gep(b,
-									 StructExprState,
+									 g->StructExprState,
 									 v_state,
 									 FIELDNO_EXPRSTATE_RESULTSLOT,
 									 "v_resultslot");
 
 	/* build global values/isnull pointers */
 	v_scanvalues = l_load_struct_gep(b,
-									 StructTupleTableSlot,
+									 g->StructTupleTableSlot,
 									 v_scanslot,
 									 FIELDNO_TUPLETABLESLOT_VALUES,
 									 "v_scanvalues");
 	v_scannulls = l_load_struct_gep(b,
-									StructTupleTableSlot,
+									g->StructTupleTableSlot,
 									v_scanslot,
 									FIELDNO_TUPLETABLESLOT_ISNULL,
 									"v_scannulls");
 	v_innervalues = l_load_struct_gep(b,
-									  StructTupleTableSlot,
+									  g->StructTupleTableSlot,
 									  v_innerslot,
 									  FIELDNO_TUPLETABLESLOT_VALUES,
 									  "v_innervalues");
 	v_innernulls = l_load_struct_gep(b,
-									 StructTupleTableSlot,
+									 g->StructTupleTableSlot,
 									 v_innerslot,
 									 FIELDNO_TUPLETABLESLOT_ISNULL,
 									 "v_innernulls");
 	v_outervalues = l_load_struct_gep(b,
-									  StructTupleTableSlot,
+									  g->StructTupleTableSlot,
 									  v_outerslot,
 									  FIELDNO_TUPLETABLESLOT_VALUES,
 									  "v_outervalues");
 	v_outernulls = l_load_struct_gep(b,
-									 StructTupleTableSlot,
+									 g->StructTupleTableSlot,
 									 v_outerslot,
 									 FIELDNO_TUPLETABLESLOT_ISNULL,
 									 "v_outernulls");
 	v_oldvalues = l_load_struct_gep(b,
-									StructTupleTableSlot,
+									g->StructTupleTableSlot,
 									v_oldslot,
 									FIELDNO_TUPLETABLESLOT_VALUES,
 									"v_oldvalues");
 	v_oldnulls = l_load_struct_gep(b,
-								   StructTupleTableSlot,
+								   g->StructTupleTableSlot,
 								   v_oldslot,
 								   FIELDNO_TUPLETABLESLOT_ISNULL,
 								   "v_oldnulls");
 	v_newvalues = l_load_struct_gep(b,
-									StructTupleTableSlot,
+									g->StructTupleTableSlot,
 									v_newslot,
 									FIELDNO_TUPLETABLESLOT_VALUES,
 									"v_newvalues");
 	v_newnulls = l_load_struct_gep(b,
-								   StructTupleTableSlot,
+								   g->StructTupleTableSlot,
 								   v_newslot,
 								   FIELDNO_TUPLETABLESLOT_ISNULL,
 								   "v_newnulls");
 	v_resultvalues = l_load_struct_gep(b,
-									   StructTupleTableSlot,
+									   g->StructTupleTableSlot,
 									   v_resultslot,
 									   FIELDNO_TUPLETABLESLOT_VALUES,
 									   "v_resultvalues");
 	v_resultnulls = l_load_struct_gep(b,
-									  StructTupleTableSlot,
+									  g->StructTupleTableSlot,
 									  v_resultslot,
 									  FIELDNO_TUPLETABLESLOT_ISNULL,
 									  "v_resultnulls");
 
 	/* aggvalues/aggnulls */
 	v_aggvalues = l_load_struct_gep(b,
-									StructExprContext,
+									g->StructExprContext,
 									v_econtext,
 									FIELDNO_EXPRCONTEXT_AGGVALUES,
 									"v.econtext.aggvalues");
 	v_aggnulls = l_load_struct_gep(b,
-								   StructExprContext,
+								   g->StructExprContext,
 								   v_econtext,
 								   FIELDNO_EXPRCONTEXT_AGGNULLS,
 								   "v.econtext.aggnulls");
@@ -308,16 +378,22 @@ llvm_compile_expr(ExprState *state)
 	{
 		ExprEvalStep *op;
 		ExprEvalOp	opcode;
+		LLVMValueRef v_op;
+		LLVMValueRef v_opno;
 		LLVMValueRef v_resvaluep;
 		LLVMValueRef v_resnullp;
 
+
 		LLVMPositionBuilderAtEnd(b, opblocks[opno]);
 
 		op = &state->steps[opno];
 		opcode = ExecEvalStepOp(state, op);
-
-		v_resvaluep = l_ptr_const(op->resvalue, l_ptr(TypeSizeT));
-		v_resnullp = l_ptr_const(op->resnull, l_ptr(TypeStorageBool));
+		v_opno = l_int32_const(lc, opno);
+		v_op = l_gep(b, g->StructExprEvalStep, v_steps, &v_opno, 1, "v_op_step");
+		///v_resvaluep = l_ptr_const(op->resvalue, l_ptr(TypeSizeT));
+		///v_resnullp = l_ptr_const(op->resnull, l_ptr(g->TypeStorageBool));
+		v_resvaluep = l_load_struct_gep( b, g->StructExprEvalStep, v_op, FIELDNO_EXPREVALSTEP_RESVALUE, "v_resvaluep");
+		v_resnullp = l_load_struct_gep( b, g->StructExprEvalStep, v_op, FIELDNO_EXPREVALSTEP_RESNULL, "v_resnullp");
 
 		switch (opcode)
 		{
@@ -326,8 +402,8 @@ llvm_compile_expr(ExprState *state)
 					LLVMValueRef v_tmpisnull;
 					LLVMValueRef v_tmpvalue;
 
-					v_tmpvalue = l_load(b, TypeSizeT, v_tmpvaluep, "");
-					v_tmpisnull = l_load(b, TypeStorageBool, v_tmpisnullp, "");
+					v_tmpvalue = l_load(b, g->TypeSizeT, v_tmpvaluep, "");
+					v_tmpisnull = l_load(b, g->TypeStorageBool, v_tmpisnullp, "");
 
 					LLVMBuildStore(b, v_tmpisnull, v_isnullp);
 
@@ -377,7 +453,7 @@ llvm_compile_expr(ExprState *state)
 					 */
 					v_nvalid =
 						l_load_struct_gep(b,
-										  StructTupleTableSlot,
+										  g->StructTupleTableSlot,
 										  v_slot,
 										  FIELDNO_TUPLETABLESLOT_NVALID,
 										  "");
@@ -426,8 +502,8 @@ llvm_compile_expr(ExprState *state)
 						params[1] = l_int32_const(lc, op->d.fetch.last_var);
 
 						l_call(b,
-							   llvm_pg_var_func_type("slot_getsomeattrs_int"),
-							   llvm_pg_func(mod, "slot_getsomeattrs_int"),
+							   llvm_pg_var_func_type(context, "slot_getsomeattrs_int"),
+							   llvm_pg_func(context, "slot_getsomeattrs_int"),
 							   params, lengthof(params), "");
 					}
 
@@ -474,8 +550,8 @@ llvm_compile_expr(ExprState *state)
 					}
 
 					v_attnum = l_int32_const(lc, op->d.var.attnum);
-					value = l_load_gep1(b, TypeSizeT, v_values, v_attnum, "");
-					isnull = l_load_gep1(b, TypeStorageBool, v_nulls, v_attnum, "");
+					value = l_load_gep1(b, g->TypeSizeT, v_values, v_attnum, "");
+					isnull = l_load_gep1(b, g->TypeStorageBool, v_nulls, v_attnum, "");
 					LLVMBuildStore(b, value, v_resvaluep);
 					LLVMBuildStore(b, isnull, v_resnullp);
 
@@ -502,16 +578,16 @@ llvm_compile_expr(ExprState *state)
 					else
 						v_slot = v_newslot;
 
-					build_EvalXFunc(b, mod, "ExecEvalSysVar",
-									v_state, op, v_econtext, v_slot);
+					build_EvalXFunc(b, context, "ExecEvalSysVar",
+									v_state, v_op, v_econtext, v_slot);
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
 					break;
 				}
 
 			case EEOP_WHOLEROW:
-				build_EvalXFunc(b, mod, "ExecEvalWholeRowVar",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalWholeRowVar",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -558,17 +634,17 @@ llvm_compile_expr(ExprState *state)
 
 					/* load data */
 					v_attnum = l_int32_const(lc, op->d.assign_var.attnum);
-					v_value = l_load_gep1(b, TypeSizeT, v_values, v_attnum, "");
-					v_isnull = l_load_gep1(b, TypeStorageBool, v_nulls, v_attnum, "");
+					v_value = l_load_gep1(b, g->TypeSizeT, v_values, v_attnum, "");
+					v_isnull = l_load_gep1(b, g->TypeStorageBool, v_nulls, v_attnum, "");
 
 					/* compute addresses of targets */
 					v_resultnum = l_int32_const(lc, op->d.assign_var.resultnum);
 					v_rvaluep = l_gep(b,
-									  TypeSizeT,
+									  g->TypeSizeT,
 									  v_resultvalues,
 									  &v_resultnum, 1, "");
 					v_risnullp = l_gep(b,
-									   TypeStorageBool,
+									   g->TypeStorageBool,
 									   v_resultnulls,
 									   &v_resultnum, 1, "");
 
@@ -591,15 +667,15 @@ llvm_compile_expr(ExprState *state)
 					size_t		resultnum = op->d.assign_tmp.resultnum;
 
 					/* load data */
-					v_value = l_load(b, TypeSizeT, v_tmpvaluep, "");
-					v_isnull = l_load(b, TypeStorageBool, v_tmpisnullp, "");
+					v_value = l_load(b, g->TypeSizeT, v_tmpvaluep, "");
+					v_isnull = l_load(b, g->TypeStorageBool, v_tmpisnullp, "");
 
 					/* compute addresses of targets */
 					v_resultnum = l_int32_const(lc, resultnum);
 					v_rvaluep =
-						l_gep(b, TypeSizeT, v_resultvalues, &v_resultnum, 1, "");
+						l_gep(b, g->TypeSizeT, v_resultvalues, &v_resultnum, 1, "");
 					v_risnullp =
-						l_gep(b, TypeStorageBool, v_resultnulls, &v_resultnum, 1, "");
+						l_gep(b, g->TypeStorageBool, v_resultnulls, &v_resultnum, 1, "");
 
 					/* store nullness */
 					LLVMBuildStore(b, v_isnull, v_risnullp);
@@ -616,7 +692,7 @@ llvm_compile_expr(ExprState *state)
 						/* check if value is NULL */
 						LLVMBuildCondBr(b,
 										LLVMBuildICmp(b, LLVMIntEQ, v_isnull,
-													  l_sbool_const(0), ""),
+													  LLVMConstInt(g->TypeStorageBool, (int)(0), false), ""),
 										b_notnull, opblocks[opno + 1]);
 
 						/* if value is not null, convert to RO datum */
@@ -624,8 +700,8 @@ llvm_compile_expr(ExprState *state)
 						v_params[0] = v_value;
 						v_value =
 							l_call(b,
-								   llvm_pg_var_func_type("MakeExpandedObjectReadOnlyInternal"),
-								   llvm_pg_func(mod, "MakeExpandedObjectReadOnlyInternal"),
+								   llvm_pg_var_func_type(context, "MakeExpandedObjectReadOnlyInternal"),
+								   llvm_pg_func(context, "MakeExpandedObjectReadOnlyInternal"),
 								   v_params, lengthof(v_params), "");
 
 						/*
@@ -646,8 +722,8 @@ llvm_compile_expr(ExprState *state)
 					LLVMValueRef v_constvalue,
 								v_constnull;
 
-					v_constvalue = l_sizet_const(op->d.constval.value);
-					v_constnull = l_sbool_const(op->d.constval.isnull);
+					v_constvalue = LLVMConstInt(g->TypeSizeT, op->d.constval.value, false);
+					v_constnull = LLVMConstInt(g->TypeStorageBool, (int)(op->d.constval.isnull), false);
 
 					LLVMBuildStore(b, v_constvalue, v_resvaluep);
 					LLVMBuildStore(b, v_constnull, v_resnullp);
@@ -662,12 +738,12 @@ llvm_compile_expr(ExprState *state)
 					FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
 					LLVMValueRef v_fcinfo_isnull;
 					LLVMValueRef v_retval;
+					LLVMValueRef v_fcinfo;
 
 					if (opcode == EEOP_FUNCEXPR_STRICT)
 					{
 						LLVMBasicBlockRef b_nonull;
 						LLVMBasicBlockRef *b_checkargnulls;
-						LLVMValueRef v_fcinfo;
 
 						/*
 						 * Block for the actual function call, if args are
@@ -680,14 +756,18 @@ llvm_compile_expr(ExprState *state)
 						if (op->d.func.nargs == 0)
 							elog(ERROR, "argumentless strict functions are pointless");
 
+						///v_fcinfo =
+						///	l_ptr_const(fcinfo, l_ptr(g->StructFunctionCallInfoData));
 						v_fcinfo =
-							l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
+							///l_struct_member_ptr_by_offset(b,lc, v_op, offsetof(ExprEvalStep ,d.func.fcinfo_data ));
+							l_load_member_value_by_offset(b,lc, v_op,
+								l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep ,d.func.fcinfo_data ));
 
 						/*
 						 * set resnull to true, if the function is actually
 						 * called, it'll be reset
 						 */
-						LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(1), false), v_resnullp);
 
 						/* create blocks for checking args, one for each */
 						b_checkargnulls =
@@ -718,11 +798,11 @@ llvm_compile_expr(ExprState *state)
 								b_argnotnull = b_checkargnulls[argno + 1];
 
 							/* and finally load & check NULLness of arg */
-							v_argisnull = l_funcnull(b, v_fcinfo, argno);
+							v_argisnull = l_funcnull(b, v_fcinfo, argno, g);
 							LLVMBuildCondBr(b,
 											LLVMBuildICmp(b, LLVMIntEQ,
 														  v_argisnull,
-														  l_sbool_const(1),
+														  LLVMConstInt(g->TypeStorageBool, (int)(1), false),
 														  ""),
 											opblocks[opno + 1],
 											b_argnotnull);
@@ -730,8 +810,13 @@ llvm_compile_expr(ExprState *state)
 
 						LLVMPositionBuilderAtEnd(b, b_nonull);
 					}
+					else
+					{
+						v_fcinfo = l_load_member_value_by_offset(b,lc, v_op,
+								l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep ,d.func.fcinfo_data ));
+					}
 
-					v_retval = BuildV1Call(context, b, mod, fcinfo,
+					v_retval = BuildV1CallLLVM(context, b, mod, fcinfo, v_fcinfo,
 										   &v_fcinfo_isnull);
 					LLVMBuildStore(b, v_retval, v_resvaluep);
 					LLVMBuildStore(b, v_fcinfo_isnull, v_resnullp);
@@ -741,15 +826,15 @@ llvm_compile_expr(ExprState *state)
 				}
 
 			case EEOP_FUNCEXPR_FUSAGE:
-				build_EvalXFunc(b, mod, "ExecEvalFuncExprFusage",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalFuncExprFusage",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 
 			case EEOP_FUNCEXPR_STRICT_FUSAGE:
-				build_EvalXFunc(b, mod, "ExecEvalFuncExprStrictFusage",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalFuncExprStrictFusage",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -783,26 +868,28 @@ llvm_compile_expr(ExprState *state)
 					b_boolcont = l_bb_before_v(opblocks[opno + 1],
 											   "b.%d.boolcont", opno);
 
-					v_boolanynullp = l_ptr_const(op->d.boolexpr.anynull,
-												 l_ptr(TypeStorageBool));
+					v_boolanynullp = ///l_ptr_const(op->d.boolexpr.anynull,
+									///			 l_ptr(g->TypeStorageBool));
+									l_load_member_value_by_offset(b,lc, v_op,
+								l_ptr(g->TypeStorageBool), offsetof(ExprEvalStep ,d.boolexpr.anynull ));
 
 					if (opcode == EEOP_BOOL_AND_STEP_FIRST)
-						LLVMBuildStore(b, l_sbool_const(0), v_boolanynullp);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_boolanynullp);
 
-					v_boolnull = l_load(b, TypeStorageBool, v_resnullp, "");
-					v_boolvalue = l_load(b, TypeSizeT, v_resvaluep, "");
+					v_boolnull = l_load(b, g->TypeStorageBool, v_resnullp, "");
+					v_boolvalue = l_load(b, g->TypeSizeT, v_resvaluep, "");
 
 					/* check if current input is NULL */
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_boolnull,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									b_boolisnull,
 									b_boolcheckfalse);
 
 					/* build block that sets anynull */
 					LLVMPositionBuilderAtEnd(b, b_boolisnull);
 					/* set boolanynull to true */
-					LLVMBuildStore(b, l_sbool_const(1), v_boolanynullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(1), false), v_boolanynullp);
 					/* and jump to next block */
 					LLVMBuildBr(b, b_boolcont);
 
@@ -810,7 +897,7 @@ llvm_compile_expr(ExprState *state)
 					LLVMPositionBuilderAtEnd(b, b_boolcheckfalse);
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_boolvalue,
-												  l_sizet_const(0), ""),
+												  LLVMConstInt(g->TypeSizeT, 0, false), ""),
 									b_boolisfalse,
 									b_boolcont);
 
@@ -826,19 +913,19 @@ llvm_compile_expr(ExprState *state)
 					/* Build block that continues if bool is TRUE. */
 					LLVMPositionBuilderAtEnd(b, b_boolcont);
 
-					v_boolanynull = l_load(b, TypeStorageBool, v_boolanynullp, "");
+					v_boolanynull = l_load(b, g->TypeStorageBool, v_boolanynullp, "");
 
 					/* set value to NULL if any previous values were NULL */
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_boolanynull,
-												  l_sbool_const(0), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(0), false), ""),
 									opblocks[opno + 1], b_boolisanynull);
 
 					LLVMPositionBuilderAtEnd(b, b_boolisanynull);
 					/* set resnull to true */
-					LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(1), false), v_resnullp);
 					/* reset resvalue */
-					LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_resvaluep);
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
 					break;
@@ -875,24 +962,26 @@ llvm_compile_expr(ExprState *state)
 					b_boolcont = l_bb_before_v(opblocks[opno + 1],
 											   "b.%d.boolcont", opno);
 
-					v_boolanynullp = l_ptr_const(op->d.boolexpr.anynull,
-												 l_ptr(TypeStorageBool));
+					v_boolanynullp = ///l_ptr_const(op->d.boolexpr.anynull,
+									///			 l_ptr(g->TypeStorageBool));
+									 l_ptr_const_step(d.boolexpr.anynull,
+												 l_ptr(g->TypeStorageBool));
 
 					if (opcode == EEOP_BOOL_OR_STEP_FIRST)
-						LLVMBuildStore(b, l_sbool_const(0), v_boolanynullp);
-					v_boolnull = l_load(b, TypeStorageBool, v_resnullp, "");
-					v_boolvalue = l_load(b, TypeSizeT, v_resvaluep, "");
+						LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_boolanynullp);
+					v_boolnull = l_load(b, g->TypeStorageBool, v_resnullp, "");
+					v_boolvalue = l_load(b, g->TypeSizeT, v_resvaluep, "");
 
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_boolnull,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									b_boolisnull,
 									b_boolchecktrue);
 
 					/* build block that sets anynull */
 					LLVMPositionBuilderAtEnd(b, b_boolisnull);
 					/* set boolanynull to true */
-					LLVMBuildStore(b, l_sbool_const(1), v_boolanynullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(1), false), v_boolanynullp);
 					/* and jump to next block */
 					LLVMBuildBr(b, b_boolcont);
 
@@ -900,7 +989,7 @@ llvm_compile_expr(ExprState *state)
 					LLVMPositionBuilderAtEnd(b, b_boolchecktrue);
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_boolvalue,
-												  l_sizet_const(1), ""),
+												  LLVMConstInt(g->TypeSizeT, 1, false), ""),
 									b_boolistrue,
 									b_boolcont);
 
@@ -916,19 +1005,19 @@ llvm_compile_expr(ExprState *state)
 					/* build block that continues if bool is FALSE */
 					LLVMPositionBuilderAtEnd(b, b_boolcont);
 
-					v_boolanynull = l_load(b, TypeStorageBool, v_boolanynullp, "");
+					v_boolanynull = l_load(b, g->TypeStorageBool, v_boolanynullp, "");
 
 					/* set value to NULL if any previous values were NULL */
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_boolanynull,
-												  l_sbool_const(0), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(0), false), ""),
 									opblocks[opno + 1], b_boolisanynull);
 
 					LLVMPositionBuilderAtEnd(b, b_boolisanynull);
 					/* set resnull to true */
-					LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(1), false), v_resnullp);
 					/* reset resvalue */
-					LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_resvaluep);
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
 					break;
@@ -940,13 +1029,13 @@ llvm_compile_expr(ExprState *state)
 					LLVMValueRef v_negbool;
 
 					/* compute !boolvalue */
-					v_boolvalue = l_load(b, TypeSizeT, v_resvaluep, "");
+					v_boolvalue = l_load(b, g->TypeSizeT, v_resvaluep, "");
 					v_negbool = LLVMBuildZExt(b,
 											  LLVMBuildICmp(b, LLVMIntEQ,
 															v_boolvalue,
-															l_sizet_const(0),
+															LLVMConstInt(g->TypeSizeT, 0, false),
 															""),
-											  TypeSizeT, "");
+											  g->TypeSizeT, "");
 
 					/*
 					 * Store it back in resvalue.  We can ignore resnull here;
@@ -969,15 +1058,15 @@ llvm_compile_expr(ExprState *state)
 					b_qualfail = l_bb_before_v(opblocks[opno + 1],
 											   "op.%d.qualfail", opno);
 
-					v_resvalue = l_load(b, TypeSizeT, v_resvaluep, "");
-					v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
+					v_resvalue = l_load(b, g->TypeSizeT, v_resvaluep, "");
+					v_resnull = l_load(b, g->TypeStorageBool, v_resnullp, "");
 
 					v_nullorfalse =
 						LLVMBuildOr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									LLVMBuildICmp(b, LLVMIntEQ, v_resvalue,
-												  l_sizet_const(0), ""),
+												  LLVMConstInt(g->TypeSizeT, 0, false), ""),
 									"");
 
 					LLVMBuildCondBr(b,
@@ -988,9 +1077,9 @@ llvm_compile_expr(ExprState *state)
 					/* build block handling NULL or false */
 					LLVMPositionBuilderAtEnd(b, b_qualfail);
 					/* set resnull to false */
-					LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_resnullp);
 					/* set resvalue to false */
-					LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_resvaluep);
 					/* and jump out */
 					LLVMBuildBr(b, opblocks[op->d.qualexpr.jumpdone]);
 					break;
@@ -1008,11 +1097,11 @@ llvm_compile_expr(ExprState *state)
 
 					/* Transfer control if current result is null */
 
-					v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
+					v_resnull = l_load(b, g->TypeStorageBool, v_resnullp, "");
 
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									opblocks[op->d.jump.jumpdone],
 									opblocks[opno + 1]);
 					break;
@@ -1024,11 +1113,11 @@ llvm_compile_expr(ExprState *state)
 
 					/* Transfer control if current result is non-null */
 
-					v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
+					v_resnull = l_load(b, g->TypeStorageBool, v_resnullp, "");
 
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
-												  l_sbool_const(0), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(0), false), ""),
 									opblocks[op->d.jump.jumpdone],
 									opblocks[opno + 1]);
 					break;
@@ -1043,15 +1132,15 @@ llvm_compile_expr(ExprState *state)
 
 					/* Transfer control if current result is null or false */
 
-					v_resvalue = l_load(b, TypeSizeT, v_resvaluep, "");
-					v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
+					v_resvalue = l_load(b, g->TypeSizeT, v_resvaluep, "");
+					v_resnull = l_load(b, g->TypeStorageBool, v_resnullp, "");
 
 					v_nullorfalse =
 						LLVMBuildOr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									LLVMBuildICmp(b, LLVMIntEQ, v_resvalue,
-												  l_sizet_const(0), ""),
+												  LLVMConstInt(g->TypeSizeT, 0, false), ""),
 									"");
 
 					LLVMBuildCondBr(b,
@@ -1063,18 +1152,18 @@ llvm_compile_expr(ExprState *state)
 
 			case EEOP_NULLTEST_ISNULL:
 				{
-					LLVMValueRef v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
+					LLVMValueRef v_resnull = l_load(b, g->TypeStorageBool, v_resnullp, "");
 					LLVMValueRef v_resvalue;
 
 					v_resvalue =
 						LLVMBuildSelect(b,
 										LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
-													  l_sbool_const(1), ""),
-										l_sizet_const(1),
-										l_sizet_const(0),
+													  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
+										LLVMConstInt(g->TypeSizeT, 1, false),
+										LLVMConstInt(g->TypeSizeT, 0, false),
 										"");
 					LLVMBuildStore(b, v_resvalue, v_resvaluep);
-					LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_resnullp);
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
 					break;
@@ -1082,32 +1171,32 @@ llvm_compile_expr(ExprState *state)
 
 			case EEOP_NULLTEST_ISNOTNULL:
 				{
-					LLVMValueRef v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
+					LLVMValueRef v_resnull = l_load(b, g->TypeStorageBool, v_resnullp, "");
 					LLVMValueRef v_resvalue;
 
 					v_resvalue =
 						LLVMBuildSelect(b,
 										LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
-													  l_sbool_const(1), ""),
-										l_sizet_const(0),
-										l_sizet_const(1),
+													  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
+										LLVMConstInt(g->TypeSizeT, 0, false),
+										LLVMConstInt(g->TypeSizeT, 1, false),
 										"");
 					LLVMBuildStore(b, v_resvalue, v_resvaluep);
-					LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_resnullp);
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
 					break;
 				}
 
 			case EEOP_NULLTEST_ROWISNULL:
-				build_EvalXFunc(b, mod, "ExecEvalRowNull",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalRowNull",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_NULLTEST_ROWISNOTNULL:
-				build_EvalXFunc(b, mod, "ExecEvalRowNotNull",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalRowNotNull",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -1118,7 +1207,7 @@ llvm_compile_expr(ExprState *state)
 				{
 					LLVMBasicBlockRef b_isnull,
 								b_notnull;
-					LLVMValueRef v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
+					LLVMValueRef v_resnull = l_load(b, g->TypeStorageBool, v_resnullp, "");
 
 					b_isnull = l_bb_before_v(opblocks[opno + 1],
 											 "op.%d.isnull", opno);
@@ -1128,23 +1217,23 @@ llvm_compile_expr(ExprState *state)
 					/* check if value is NULL */
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									b_isnull, b_notnull);
 
 					/* if value is NULL, return false */
 					LLVMPositionBuilderAtEnd(b, b_isnull);
 
 					/* result is not null */
-					LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_resnullp);
 
 					if (opcode == EEOP_BOOLTEST_IS_TRUE ||
 						opcode == EEOP_BOOLTEST_IS_FALSE)
 					{
-						LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_resvaluep);
 					}
 					else
 					{
-						LLVMBuildStore(b, l_sizet_const(1), v_resvaluep);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 1, false), v_resvaluep);
 					}
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
@@ -1162,14 +1251,14 @@ llvm_compile_expr(ExprState *state)
 					else
 					{
 						LLVMValueRef v_value =
-							l_load(b, TypeSizeT, v_resvaluep, "");
+							l_load(b, g->TypeSizeT, v_resvaluep, "");
 
 						v_value = LLVMBuildZExt(b,
 												LLVMBuildICmp(b, LLVMIntEQ,
 															  v_value,
-															  l_sizet_const(0),
+															  LLVMConstInt(g->TypeSizeT, 0, false),
 															  ""),
-												TypeSizeT, "");
+												g->TypeSizeT, "");
 						LLVMBuildStore(b, v_value, v_resvaluep);
 					}
 					LLVMBuildBr(b, opblocks[opno + 1]);
@@ -1177,14 +1266,14 @@ llvm_compile_expr(ExprState *state)
 				}
 
 			case EEOP_PARAM_EXEC:
-				build_EvalXFunc(b, mod, "ExecEvalParamExec",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalParamExec",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_PARAM_EXTERN:
-				build_EvalXFunc(b, mod, "ExecEvalParamExtern",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalParamExtern",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -1193,14 +1282,17 @@ llvm_compile_expr(ExprState *state)
 					LLVMValueRef v_func;
 					LLVMValueRef v_params[3];
 
-					v_func = l_ptr_const(op->d.cparam.paramfunc,
-										 llvm_pg_var_type("TypeExecEvalSubroutine"));
+					v_func = ///l_ptr_const(op->d.cparam.paramfunc,
+							///			 llvm_pg_var_type("TypeExecEvalSubroutine"));
+							l_ptr_const_step(d.cparam.paramfunc,
+										 llvm_pg_var_type(typesmod, "TypeExecEvalSubroutine"));
 
 					v_params[0] = v_state;
-					v_params[1] = l_ptr_const(op, l_ptr(StructExprEvalStep));
+					v_params[1] = ///l_ptr_const(op, l_ptr(g->StructExprEvalStep));
+								v_op;
 					v_params[2] = v_econtext;
 					l_call(b,
-						   LLVMGetFunctionType(ExecEvalSubroutineTemplate),
+						   LLVMGetFunctionType(g->ExecEvalSubroutineTemplate),
 						   v_func,
 						   v_params, lengthof(v_params), "");
 
@@ -1209,8 +1301,8 @@ llvm_compile_expr(ExprState *state)
 				}
 
 			case EEOP_PARAM_SET:
-				build_EvalXFunc(b, mod, "ExecEvalParamSet",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalParamSet",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -1221,21 +1313,23 @@ llvm_compile_expr(ExprState *state)
 					LLVMValueRef v_params[3];
 					LLVMValueRef v_ret;
 
-					v_func = l_ptr_const(op->d.sbsref_subscript.subscriptfunc,
-										 llvm_pg_var_type("TypeExecEvalBoolSubroutine"));
+					v_func = ///l_ptr_const(op->d.sbsref_subscript.subscriptfunc,
+								///		 llvm_pg_var_type("TypeExecEvalBoolSubroutine"));
+								l_ptr_const_step(d.sbsref_subscript.subscriptfunc,
+										 llvm_pg_var_type(typesmod, "TypeExecEvalBoolSubroutine"));
 
 					v_params[0] = v_state;
-					v_params[1] = l_ptr_const(op, l_ptr(StructExprEvalStep));
+					v_params[1] = v_op; /// l_ptr_const(op, l_ptr(g->StructExprEvalStep));
 					v_params[2] = v_econtext;
 					v_ret = l_call(b,
-								   LLVMGetFunctionType(ExecEvalBoolSubroutineTemplate),
+								   LLVMGetFunctionType(g->ExecEvalBoolSubroutineTemplate),
 								   v_func,
 								   v_params, lengthof(v_params), "");
-					v_ret = LLVMBuildZExt(b, v_ret, TypeStorageBool, "");
+					v_ret = LLVMBuildZExt(b, v_ret, g->TypeStorageBool, "");
 
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_ret,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									opblocks[opno + 1],
 									opblocks[jumpdone]);
 					break;
@@ -1248,14 +1342,16 @@ llvm_compile_expr(ExprState *state)
 					LLVMValueRef v_func;
 					LLVMValueRef v_params[3];
 
-					v_func = l_ptr_const(op->d.sbsref.subscriptfunc,
-										 llvm_pg_var_type("TypeExecEvalSubroutine"));
+					v_func = ///l_ptr_const(op->d.sbsref.subscriptfunc,
+							///			 llvm_pg_var_type("TypeExecEvalSubroutine"));
+							l_ptr_const_step(d.sbsref.subscriptfunc,
+										 llvm_pg_var_type(typesmod, "TypeExecEvalSubroutine"));
 
 					v_params[0] = v_state;
-					v_params[1] = l_ptr_const(op, l_ptr(StructExprEvalStep));
+					v_params[1] = v_op; ///l_ptr_const(op, l_ptr(g->StructExprEvalStep));
 					v_params[2] = v_econtext;
 					l_call(b,
-						   LLVMGetFunctionType(ExecEvalSubroutineTemplate),
+						   LLVMGetFunctionType(g->ExecEvalSubroutineTemplate),
 						   v_func,
 						   v_params, lengthof(v_params), "");
 
@@ -1270,13 +1366,17 @@ llvm_compile_expr(ExprState *state)
 					LLVMValueRef v_casenullp,
 								v_casenull;
 
-					v_casevaluep = l_ptr_const(op->d.casetest.value,
-											   l_ptr(TypeSizeT));
-					v_casenullp = l_ptr_const(op->d.casetest.isnull,
-											  l_ptr(TypeStorageBool));
-
-					v_casevalue = l_load(b, TypeSizeT, v_casevaluep, "");
-					v_casenull = l_load(b, TypeStorageBool, v_casenullp, "");
+					v_casevaluep = ///l_ptr_const(op->d.casetest.value,
+									///		   l_ptr(TypeSizeT));
+									l_ptr_const_step(d.casetest.value,
+											   l_ptr(g->TypeSizeT));
+					v_casenullp = ///l_ptr_const(op->d.casetest.isnull,
+								///			  l_ptr(g->TypeStorageBool));
+								l_ptr_const_step(d.casetest.isnull,
+											  l_ptr(g->TypeStorageBool));
+
+					v_casevalue = l_load(b, g->TypeSizeT, v_casevaluep, "");
+					v_casenull = l_load(b, g->TypeStorageBool, v_casenullp, "");
 					LLVMBuildStore(b, v_casevalue, v_resvaluep);
 					LLVMBuildStore(b, v_casenull, v_resnullp);
 
@@ -1291,12 +1391,12 @@ llvm_compile_expr(ExprState *state)
 
 					v_casevalue =
 						l_load_struct_gep(b,
-										  StructExprContext,
+										  g->StructExprContext,
 										  v_econtext,
 										  FIELDNO_EXPRCONTEXT_CASEDATUM, "");
 					v_casenull =
 						l_load_struct_gep(b,
-										  StructExprContext,
+										  g->StructExprContext,
 										  v_econtext,
 										  FIELDNO_EXPRCONTEXT_CASENULL, "");
 					LLVMBuildStore(b, v_casevalue, v_resvaluep);
@@ -1319,10 +1419,12 @@ llvm_compile_expr(ExprState *state)
 					b_notnull = l_bb_before_v(opblocks[opno + 1],
 											  "op.%d.readonly.notnull", opno);
 
-					v_nullp = l_ptr_const(op->d.make_readonly.isnull,
-										  l_ptr(TypeStorageBool));
+					v_nullp = ///l_ptr_const(op->d.make_readonly.isnull,
+								///		  l_ptr(g->TypeStorageBool));
+							l_ptr_const_step(d.make_readonly.isnull,
+										  l_ptr(g->TypeStorageBool));
 
-					v_null = l_load(b, TypeStorageBool, v_nullp, "");
+					v_null = l_load(b, g->TypeStorageBool, v_nullp, "");
 
 					/* store null isnull value in result */
 					LLVMBuildStore(b, v_null, v_resnullp);
@@ -1330,22 +1432,24 @@ llvm_compile_expr(ExprState *state)
 					/* check if value is NULL */
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_null,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									opblocks[opno + 1], b_notnull);
 
 					/* if value is not null, convert to RO datum */
 					LLVMPositionBuilderAtEnd(b, b_notnull);
 
-					v_valuep = l_ptr_const(op->d.make_readonly.value,
-										   l_ptr(TypeSizeT));
+					v_valuep = ///l_ptr_const(op->d.make_readonly.value,
+								///		   l_ptr(TypeSizeT));
+								l_ptr_const_step(d.make_readonly.value,
+										   l_ptr(g->TypeSizeT));
 
-					v_value = l_load(b, TypeSizeT, v_valuep, "");
+					v_value = l_load(b, g->TypeSizeT, v_valuep, "");
 
 					v_params[0] = v_value;
 					v_ret =
 						l_call(b,
-							   llvm_pg_var_func_type("MakeExpandedObjectReadOnlyInternal"),
-							   llvm_pg_func(mod, "MakeExpandedObjectReadOnlyInternal"),
+							   llvm_pg_var_func_type(context, "MakeExpandedObjectReadOnlyInternal"),
+							   llvm_pg_func(context, "MakeExpandedObjectReadOnlyInternal"),
 							   v_params, lengthof(v_params), "");
 					LLVMBuildStore(b, v_ret, v_resvaluep);
 
@@ -1386,40 +1490,43 @@ llvm_compile_expr(ExprState *state)
 					b_inputcall = l_bb_before_v(opblocks[opno + 1],
 												"op.%d.inputcall", opno);
 
-					v_fn_out = llvm_function_reference(context, b, mod, fcinfo_out);
-					v_fn_in = llvm_function_reference(context, b, mod, fcinfo_in);
-					v_fcinfo_out = l_ptr_const(fcinfo_out, l_ptr(StructFunctionCallInfoData));
-					v_fcinfo_in = l_ptr_const(fcinfo_in, l_ptr(StructFunctionCallInfoData));
-
+					v_fcinfo_out = l_load_member_value_by_offset(b,lc, v_op,
+								l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep ,d.iocoerce.fcinfo_data_out ));
+					v_fcinfo_in = l_load_member_value_by_offset(b,lc, v_op,
+								l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep ,d.iocoerce.fcinfo_data_in ));
+					v_fn_out = llvm_function_reference(context, b, mod, fcinfo_out, v_fcinfo_out);
+					v_fn_in = llvm_function_reference(context, b, mod, fcinfo_in, v_fcinfo_in);
+					///v_fcinfo_out = l_ptr_const(fcinfo_out, l_ptr(g->StructFunctionCallInfoData));
+					///v_fcinfo_in = l_ptr_const(fcinfo_in, l_ptr(g->StructFunctionCallInfoData));
 					v_fcinfo_in_isnullp =
 						l_struct_gep(b,
-									 StructFunctionCallInfoData,
+									 g->StructFunctionCallInfoData,
 									 v_fcinfo_in,
 									 FIELDNO_FUNCTIONCALLINFODATA_ISNULL,
 									 "v_fcinfo_in_isnull");
 
 					/* output functions are not called on nulls */
-					v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
+					v_resnull = l_load(b, g->TypeStorageBool, v_resnullp, "");
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									b_skipoutput,
 									b_calloutput);
 
 					LLVMPositionBuilderAtEnd(b, b_skipoutput);
-					v_output_skip = l_sizet_const(0);
+					v_output_skip = LLVMConstInt(g->TypeSizeT, 0, false);
 					LLVMBuildBr(b, b_input);
 
 					LLVMPositionBuilderAtEnd(b, b_calloutput);
-					v_resvalue = l_load(b, TypeSizeT, v_resvaluep, "");
+					v_resvalue = l_load(b, g->TypeSizeT, v_resvaluep, "");
 
 					/* set arg[0] */
 					LLVMBuildStore(b,
 								   v_resvalue,
-								   l_funcvaluep(b, v_fcinfo_out, 0));
+								   l_funcvaluep(b, v_fcinfo_out, 0, g));
 					LLVMBuildStore(b,
-								   l_sbool_const(0),
-								   l_funcnullp(b, v_fcinfo_out, 0));
+								   LLVMConstInt(g->TypeStorageBool, (int)(0), false),
+								   l_funcnullp(b, v_fcinfo_out, 0, g));
 					/* and call output function (can never return NULL) */
 					v_output = l_call(b,
 									  LLVMGetFunctionType(v_fn_out),
@@ -1441,7 +1548,7 @@ llvm_compile_expr(ExprState *state)
 						incoming_values[1] = v_output;
 						incoming_blocks[1] = b_calloutput;
 
-						v_output = LLVMBuildPhi(b, TypeSizeT, "output");
+						v_output = LLVMBuildPhi(b, g->TypeSizeT, "output");
 						LLVMAddIncoming(v_output,
 										incoming_values, incoming_blocks,
 										lengthof(incoming_blocks));
@@ -1455,7 +1562,7 @@ llvm_compile_expr(ExprState *state)
 					{
 						LLVMBuildCondBr(b,
 										LLVMBuildICmp(b, LLVMIntEQ, v_output,
-													  l_sizet_const(0), ""),
+													  LLVMConstInt(g->TypeSizeT, 0, false), ""),
 										opblocks[opno + 1],
 										b_inputcall);
 					}
@@ -1468,15 +1575,15 @@ llvm_compile_expr(ExprState *state)
 					/* set arguments */
 					/* arg0: output */
 					LLVMBuildStore(b, v_output,
-								   l_funcvaluep(b, v_fcinfo_in, 0));
+								   l_funcvaluep(b, v_fcinfo_in, 0, g));
 					LLVMBuildStore(b, v_resnull,
-								   l_funcnullp(b, v_fcinfo_in, 0));
+								   l_funcnullp(b, v_fcinfo_in, 0, g));
 
 					/* arg1: ioparam: preset in execExpr.c */
 					/* arg2: typmod: preset in execExpr.c  */
 
 					/* reset fcinfo_in->isnull */
-					LLVMBuildStore(b, l_sbool_const(0), v_fcinfo_in_isnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_fcinfo_in_isnullp);
 					/* and call function */
 					v_retval = l_call(b,
 									  LLVMGetFunctionType(v_fn_in),
@@ -1490,8 +1597,8 @@ llvm_compile_expr(ExprState *state)
 				}
 
 			case EEOP_IOCOERCE_SAFE:
-				build_EvalXFunc(b, mod, "ExecEvalCoerceViaIOSafe",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalCoerceViaIOSafe",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -1523,15 +1630,17 @@ llvm_compile_expr(ExprState *state)
 					b_bothargnull = l_bb_before_v(opblocks[opno + 1], "op.%d.bothargnull", opno);
 					b_anyargnull = l_bb_before_v(opblocks[opno + 1], "op.%d.anyargnull", opno);
 
-					v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
+					v_fcinfo = /// l_ptr_const(fcinfo, l_ptr(g->StructFunctionCallInfoData));
+														l_load_member_value_by_offset(b,lc, v_op,
+								l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep ,d.func.fcinfo_data ));
 
 					/* load args[0|1].isnull for both arguments */
-					v_argnull0 = l_funcnull(b, v_fcinfo, 0);
+					v_argnull0 = l_funcnull(b, v_fcinfo, 0, g);
 					v_argisnull0 = LLVMBuildICmp(b, LLVMIntEQ, v_argnull0,
-												 l_sbool_const(1), "");
-					v_argnull1 = l_funcnull(b, v_fcinfo, 1);
+												 LLVMConstInt(g->TypeStorageBool, (int)(1), false), "");
+					v_argnull1 = l_funcnull(b, v_fcinfo, 1, g);
 					v_argisnull1 = LLVMBuildICmp(b, LLVMIntEQ, v_argnull1,
-												 l_sbool_const(1), "");
+												 LLVMConstInt(g->TypeStorageBool, (int)(1), false), "");
 
 					v_anyargisnull = LLVMBuildOr(b, v_argisnull0, v_argisnull1, "");
 					v_bothargisnull = LLVMBuildAnd(b, v_argisnull0, v_argisnull1, "");
@@ -1554,27 +1663,27 @@ llvm_compile_expr(ExprState *state)
 
 					/* Both NULL? Then is not distinct... */
 					LLVMPositionBuilderAtEnd(b, b_bothargnull);
-					LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_resnullp);
 					if (opcode == EEOP_NOT_DISTINCT)
-						LLVMBuildStore(b, l_sizet_const(1), v_resvaluep);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 1, false), v_resvaluep);
 					else
-						LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_resvaluep);
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
 
 					/* Only one is NULL? Then is distinct... */
 					LLVMPositionBuilderAtEnd(b, b_anyargnull);
-					LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_resnullp);
 					if (opcode == EEOP_NOT_DISTINCT)
-						LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_resvaluep);
 					else
-						LLVMBuildStore(b, l_sizet_const(1), v_resvaluep);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 1, false), v_resvaluep);
 					LLVMBuildBr(b, opblocks[opno + 1]);
 
 					/* neither argument is null: compare */
 					LLVMPositionBuilderAtEnd(b, b_noargnull);
 
-					v_result = BuildV1Call(context, b, mod, fcinfo,
+					v_result = BuildV1CallLLVM(context, b, mod, fcinfo, v_fcinfo,
 										   &v_fcinfo_isnull);
 
 					if (opcode == EEOP_DISTINCT)
@@ -1584,8 +1693,8 @@ llvm_compile_expr(ExprState *state)
 							LLVMBuildZExt(b,
 										  LLVMBuildICmp(b, LLVMIntEQ,
 														v_result,
-														l_sizet_const(0), ""),
-										  TypeSizeT, "");
+														LLVMConstInt(g->TypeSizeT, 0, false), ""),
+										  g->TypeSizeT, "");
 					}
 
 					LLVMBuildStore(b, v_fcinfo_isnull, v_resnullp);
@@ -1618,21 +1727,23 @@ llvm_compile_expr(ExprState *state)
 					b_argsequal = l_bb_before_v(opblocks[opno + 1],
 												"b.%d.argsequal", opno);
 
-					v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
+					v_fcinfo = /// l_ptr_const(fcinfo, l_ptr(g->StructFunctionCallInfoData));
+								l_load_member_value_by_offset(b,lc, v_op,
+								l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep ,d.func.fcinfo_data));
 
 					/* save original arg[0] */
-					v_arg0 = l_funcvalue(b, v_fcinfo, 0);
+					v_arg0 = l_funcvalue(b, v_fcinfo, 0, g);
 
 					/* if either argument is NULL they can't be equal */
-					v_argnull0 = l_funcnull(b, v_fcinfo, 0);
-					v_argnull1 = l_funcnull(b, v_fcinfo, 1);
+					v_argnull0 = l_funcnull(b, v_fcinfo, 0, g);
+					v_argnull1 = l_funcnull(b, v_fcinfo, 1, g);
 
 					v_anyargisnull =
 						LLVMBuildOr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_argnull0,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									LLVMBuildICmp(b, LLVMIntEQ, v_argnull1,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									"");
 
 					LLVMBuildCondBr(b, v_anyargisnull, b_hasnull, b_nonull);
@@ -1662,14 +1773,14 @@ llvm_compile_expr(ExprState *state)
 						v_params[0] = v_arg0;
 						v_arg0_ro =
 							l_call(b,
-								   llvm_pg_var_func_type("MakeExpandedObjectReadOnlyInternal"),
-								   llvm_pg_func(mod, "MakeExpandedObjectReadOnlyInternal"),
+								   llvm_pg_var_func_type(context, "MakeExpandedObjectReadOnlyInternal"),
+								   llvm_pg_func(context, "MakeExpandedObjectReadOnlyInternal"),
 								   v_params, lengthof(v_params), "");
 						LLVMBuildStore(b, v_arg0_ro,
-									   l_funcvaluep(b, v_fcinfo, 0));
+									   l_funcvaluep(b, v_fcinfo, 0, g));
 					}
 
-					v_retval = BuildV1Call(context, b, mod, fcinfo, &v_fcinfo_isnull);
+					v_retval = BuildV1CallLLVM(context, b, mod, fcinfo, v_fcinfo, &v_fcinfo_isnull);
 
 					/*
 					 * If result not null and arguments are equal return null,
@@ -1679,39 +1790,39 @@ llvm_compile_expr(ExprState *state)
 					v_argsequal = LLVMBuildAnd(b,
 											   LLVMBuildICmp(b, LLVMIntEQ,
 															 v_fcinfo_isnull,
-															 l_sbool_const(0),
+															 LLVMConstInt(g->TypeStorageBool, (int)(0), false),
 															 ""),
 											   LLVMBuildICmp(b, LLVMIntEQ,
 															 v_retval,
-															 l_sizet_const(1),
+															 LLVMConstInt(g->TypeSizeT, 1, false),
 															 ""),
 											   "");
 					LLVMBuildCondBr(b, v_argsequal, b_argsequal, b_hasnull);
 
 					/* build block setting result to NULL, if args are equal */
 					LLVMPositionBuilderAtEnd(b, b_argsequal);
-					LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
-					LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(1), false), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_resvaluep);
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
 					break;
 				}
 
 			case EEOP_SQLVALUEFUNCTION:
-				build_EvalXFunc(b, mod, "ExecEvalSQLValueFunction",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalSQLValueFunction",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_CURRENTOFEXPR:
-				build_EvalXFunc(b, mod, "ExecEvalCurrentOfExpr",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalCurrentOfExpr",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_NEXTVALUEEXPR:
-				build_EvalXFunc(b, mod, "ExecEvalNextValueExpr",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalNextValueExpr",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -1730,11 +1841,11 @@ llvm_compile_expr(ExprState *state)
 					 * OLD/NEW row doesn't exist, skip that and return NULL.
 					 */
 					v_flagsp = l_struct_gep(b,
-											StructExprState,
+											g->StructExprState,
 											v_state,
 											FIELDNO_EXPRSTATE_FLAGS,
 											"v.state.flags");
-					v_flags = l_load(b, TypeStorageBool, v_flagsp, "");
+					v_flags = l_load(b, g->TypeStorageBool, v_flagsp, "");
 
 					v_nullflag = l_int8_const(lc, op->d.returningexpr.nullflag);
 
@@ -1742,33 +1853,33 @@ llvm_compile_expr(ExprState *state)
 									LLVMBuildICmp(b, LLVMIntEQ,
 												  LLVMBuildAnd(b, v_flags,
 															   v_nullflag, ""),
-												  l_sbool_const(0), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(0), false), ""),
 									opblocks[opno + 1], b_isnull);
 
 					LLVMPositionBuilderAtEnd(b, b_isnull);
 
-					LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
-					LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_resvaluep);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(1), false), v_resnullp);
 
 					LLVMBuildBr(b, opblocks[op->d.returningexpr.jumpdone]);
 					break;
 				}
 
 			case EEOP_ARRAYEXPR:
-				build_EvalXFunc(b, mod, "ExecEvalArrayExpr",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalArrayExpr",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_ARRAYCOERCE:
-				build_EvalXFunc(b, mod, "ExecEvalArrayCoerce",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalArrayCoerce",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_ROW:
-				build_EvalXFunc(b, mod, "ExecEvalRow",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalRow",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -1779,6 +1890,7 @@ llvm_compile_expr(ExprState *state)
 					LLVMBasicBlockRef b_null;
 					LLVMBasicBlockRef b_compare;
 					LLVMBasicBlockRef b_compare_result;
+					LLVMValueRef v_fcinfo;
 
 					LLVMValueRef v_retval;
 
@@ -1790,34 +1902,34 @@ llvm_compile_expr(ExprState *state)
 						l_bb_before_v(opblocks[opno + 1],
 									  "op.%d.row-compare-result",
 									  opno);
-
+					v_fcinfo = l_load_member_value_by_offset(b, lc, v_op,
+								l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep ,d.rowcompare_step.fcinfo_data));
 					/*
 					 * If function is strict, and either arg is null, we're
 					 * done.
 					 */
 					if (op->d.rowcompare_step.finfo->fn_strict)
 					{
-						LLVMValueRef v_fcinfo;
 						LLVMValueRef v_argnull0;
 						LLVMValueRef v_argnull1;
 						LLVMValueRef v_anyargisnull;
 
-						v_fcinfo = l_ptr_const(fcinfo,
-											   l_ptr(StructFunctionCallInfoData));
+						///v_fcinfo = l_ptr_const(fcinfo,
+						///					   l_ptr(g->StructFunctionCallInfoData));
 
-						v_argnull0 = l_funcnull(b, v_fcinfo, 0);
-						v_argnull1 = l_funcnull(b, v_fcinfo, 1);
+						v_argnull0 = l_funcnull(b, v_fcinfo, 0, g);
+						v_argnull1 = l_funcnull(b, v_fcinfo, 1, g);
 
 						v_anyargisnull =
 							LLVMBuildOr(b,
 										LLVMBuildICmp(b,
 													  LLVMIntEQ,
 													  v_argnull0,
-													  l_sbool_const(1),
+													  LLVMConstInt(g->TypeStorageBool, (int)(1), false),
 													  ""),
 										LLVMBuildICmp(b, LLVMIntEQ,
 													  v_argnull1,
-													  l_sbool_const(1), ""),
+													  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 										"");
 
 						LLVMBuildCondBr(b, v_anyargisnull, b_null, b_compare);
@@ -1831,7 +1943,7 @@ llvm_compile_expr(ExprState *state)
 					LLVMPositionBuilderAtEnd(b, b_compare);
 
 					/* call function */
-					v_retval = BuildV1Call(context, b, mod, fcinfo,
+					v_retval = BuildV1CallLLVM(context, b, mod, fcinfo, v_fcinfo,
 										   &v_fcinfo_isnull);
 					LLVMBuildStore(b, v_retval, v_resvaluep);
 
@@ -1840,7 +1952,7 @@ llvm_compile_expr(ExprState *state)
 									LLVMBuildICmp(b,
 												  LLVMIntEQ,
 												  v_fcinfo_isnull,
-												  l_sbool_const(0),
+												  LLVMConstInt(g->TypeStorageBool, (int)(0), false),
 												  ""),
 									b_compare_result,
 									b_null);
@@ -1853,7 +1965,7 @@ llvm_compile_expr(ExprState *state)
 									LLVMBuildICmp(b,
 												  LLVMIntEQ,
 												  v_retval,
-												  l_sizet_const(0), ""),
+												  LLVMConstInt(g->TypeSizeT, 0, false), ""),
 									opblocks[opno + 1],
 									opblocks[op->d.rowcompare_step.jumpdone]);
 
@@ -1862,7 +1974,7 @@ llvm_compile_expr(ExprState *state)
 					 * result.
 					 */
 					LLVMPositionBuilderAtEnd(b, b_null);
-					LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(1), false), v_resnullp);
 					LLVMBuildBr(b, opblocks[op->d.rowcompare_step.jumpnull]);
 
 					break;
@@ -1883,7 +1995,7 @@ llvm_compile_expr(ExprState *state)
 					 */
 					v_cmpresult =
 						LLVMBuildTrunc(b,
-									   l_load(b, TypeSizeT, v_resvaluep, ""),
+									   l_load(b, g->TypeSizeT, v_resvaluep, ""),
 									   LLVMInt32TypeInContext(lc), "");
 
 					switch (cmptype)
@@ -1912,9 +2024,9 @@ llvm_compile_expr(ExprState *state)
 											 v_cmpresult,
 											 l_int32_const(lc, 0),
 											 "");
-					v_result = LLVMBuildZExt(b, v_result, TypeSizeT, "");
+					v_result = LLVMBuildZExt(b, v_result, g->TypeSizeT, "");
 
-					LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_resnullp);
 					LLVMBuildStore(b, v_result, v_resvaluep);
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
@@ -1922,26 +2034,26 @@ llvm_compile_expr(ExprState *state)
 				}
 
 			case EEOP_MINMAX:
-				build_EvalXFunc(b, mod, "ExecEvalMinMax",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalMinMax",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_FIELDSELECT:
-				build_EvalXFunc(b, mod, "ExecEvalFieldSelect",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalFieldSelect",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_FIELDSTORE_DEFORM:
-				build_EvalXFunc(b, mod, "ExecEvalFieldStoreDeForm",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalFieldStoreDeForm",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_FIELDSTORE_FORM:
-				build_EvalXFunc(b, mod, "ExecEvalFieldStoreForm",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalFieldStoreForm",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -1952,13 +2064,13 @@ llvm_compile_expr(ExprState *state)
 					LLVMValueRef v_casenullp,
 								v_casenull;
 
-					v_casevaluep = l_ptr_const(op->d.casetest.value,
-											   l_ptr(TypeSizeT));
-					v_casenullp = l_ptr_const(op->d.casetest.isnull,
-											  l_ptr(TypeStorageBool));
+					v_casevaluep = l_ptr_const_step(d.casetest.value,
+											   l_ptr(g->TypeSizeT));
+					v_casenullp = l_ptr_const_step(d.casetest.isnull,
+											  l_ptr(g->TypeStorageBool));
 
-					v_casevalue = l_load(b, TypeSizeT, v_casevaluep, "");
-					v_casenull = l_load(b, TypeStorageBool, v_casenullp, "");
+					v_casevalue = l_load(b, g->TypeSizeT, v_casevaluep, "");
+					v_casenull = l_load(b, g->TypeStorageBool, v_casenullp, "");
 					LLVMBuildStore(b, v_casevalue, v_resvaluep);
 					LLVMBuildStore(b, v_casenull, v_resnullp);
 
@@ -1973,13 +2085,13 @@ llvm_compile_expr(ExprState *state)
 
 					v_casevalue =
 						l_load_struct_gep(b,
-										  StructExprContext,
+										  g->StructExprContext,
 										  v_econtext,
 										  FIELDNO_EXPRCONTEXT_DOMAINDATUM,
 										  "");
 					v_casenull =
 						l_load_struct_gep(b,
-										  StructExprContext,
+										  g->StructExprContext,
 										  v_econtext,
 										  FIELDNO_EXPRCONTEXT_DOMAINNULL,
 										  "");
@@ -1991,14 +2103,14 @@ llvm_compile_expr(ExprState *state)
 				}
 
 			case EEOP_DOMAIN_NOTNULL:
-				build_EvalXFunc(b, mod, "ExecEvalConstraintNotNull",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalConstraintNotNull",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_DOMAIN_CHECK:
-				build_EvalXFunc(b, mod, "ExecEvalConstraintCheck",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalConstraintCheck",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -2006,10 +2118,10 @@ llvm_compile_expr(ExprState *state)
 				{
 					LLVMValueRef v_initvalue;
 
-					v_initvalue = l_sizet_const(op->d.hashdatum_initvalue.init_value);
+					v_initvalue = LLVMConstInt(g->TypeSizeT, op->d.hashdatum_initvalue.init_value, false);
 
 					LLVMBuildStore(b, v_initvalue, v_resvaluep);
-					LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_resnullp);
 					LLVMBuildBr(b, opblocks[opno + 1]);
 					break;
 				}
@@ -2044,25 +2156,31 @@ llvm_compile_expr(ExprState *state)
 						LLVMValueRef v_tmp2;
 						LLVMValueRef tmp;
 
-						tmp = l_ptr_const(&op->d.hashdatum.iresult->value,
-										  l_ptr(TypeSizeT));
+						///tmp = l_ptr_const(&op->d.hashdatum.iresult->value,
+						///				  l_ptr(TypeSizeT));
+						tmp = l_ptr_const_step(d.hashdatum.iresult, l_ptr(g->StructNullableDatum));
+						tmp = l_struct_gep(b, g->StructNullableDatum, tmp,
+												  FIELDNO_NULLABLE_DATUM_DATUM,
+												  "");
+
+						///l_ptr(TypeSizeT));
 
 						/*
 						 * Fetch the previously hashed value from where the
 						 * previous hash operation stored it.
 						 */
-						v_prevhash = l_load(b, TypeSizeT, tmp, "prevhash");
+						v_prevhash = l_load(b, g->TypeSizeT, tmp, "prevhash");
 
 						/*
 						 * Rotate bits left by 1 bit.  Be careful not to
 						 * overflow uint32 when working with size_t.
 						 */
-						v_tmp1 = LLVMBuildShl(b, v_prevhash, l_sizet_const(1),
+						v_tmp1 = LLVMBuildShl(b, v_prevhash, LLVMConstInt(g->TypeSizeT, 1, false),
 											  "");
 						v_tmp1 = LLVMBuildAnd(b, v_tmp1,
-											  l_sizet_const(0xffffffff), "");
+											  LLVMConstInt(g->TypeSizeT, 0xffffffff, false), "");
 						v_tmp2 = LLVMBuildLShr(b, v_prevhash,
-											   l_sizet_const(31), "");
+											   LLVMConstInt(g->TypeSizeT, 31, false), "");
 						v_prevhash = LLVMBuildOr(b, v_tmp1, v_tmp2,
 												 "rotatedhash");
 					}
@@ -2079,8 +2197,10 @@ llvm_compile_expr(ExprState *state)
 					if (fcinfo->nargs != 1)
 						elog(ERROR, "incorrect number of function arguments");
 
-					v_fcinfo = l_ptr_const(fcinfo,
-										   l_ptr(StructFunctionCallInfoData));
+					v_fcinfo = ///l_ptr_const(fcinfo,
+								///		   l_ptr(g->StructFunctionCallInfoData));
+								l_load_member_value_by_offset(b, lc, v_op,
+								l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep, d.hashdatum.fcinfo_data));
 
 					b_checkargnull = l_bb_before_v(b_ifnotnull,
 												   "b.%d.isnull.0", opno);
@@ -2104,8 +2224,8 @@ llvm_compile_expr(ExprState *state)
 						 * In strict node, NULL inputs result in NULL.  Save
 						 * the NULL result and goto jumpdone.
 						 */
-						LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
-						LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(1), false), v_resnullp);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_resvaluep);
 						LLVMBuildBr(b, opblocks[op->d.hashdatum.jumpdone]);
 					}
 					else
@@ -2117,7 +2237,7 @@ llvm_compile_expr(ExprState *state)
 						LLVMPositionBuilderAtEnd(b, b_ifnullblock);
 
 
-						LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_resnullp);
 
 						if (opcode == EEOP_HASHDATUM_NEXT32)
 						{
@@ -2137,7 +2257,7 @@ llvm_compile_expr(ExprState *state)
 							 * Store a zero Datum when the Datum to hash is
 							 * NULL
 							 */
-							LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
+							LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_resvaluep);
 						}
 
 						LLVMBuildBr(b, opblocks[opno + 1]);
@@ -2146,12 +2266,12 @@ llvm_compile_expr(ExprState *state)
 					LLVMPositionBuilderAtEnd(b, b_checkargnull);
 
 					/* emit code to check if the input parameter is NULL */
-					v_argisnull = l_funcnull(b, v_fcinfo, 0);
+					v_argisnull = l_funcnull(b, v_fcinfo, 0, g);
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b,
 												  LLVMIntEQ,
 												  v_argisnull,
-												  l_sbool_const(1),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false),
 												  ""),
 									b_ifnullblock,
 									b_ifnotnull);
@@ -2169,31 +2289,34 @@ llvm_compile_expr(ExprState *state)
 						LLVMValueRef v_tmp2;
 						LLVMValueRef tmp;
 
-						tmp = l_ptr_const(&op->d.hashdatum.iresult->value,
-										  l_ptr(TypeSizeT));
-
+						///tmp = l_ptr_const(&op->d.hashdatum.iresult->value,
+						///				  l_ptr(TypeSizeT));
+						tmp = l_ptr_const_step(d.hashdatum.iresult, l_ptr(g->StructNullableDatum));
+						tmp = l_struct_gep(b, g->StructNullableDatum, tmp,
+												  FIELDNO_NULLABLE_DATUM_DATUM,
+												  "");
 						/*
 						 * Fetch the previously hashed value from where the
 						 * previous hash operation stored it.
 						 */
-						v_prevhash = l_load(b, TypeSizeT, tmp, "prevhash");
+						v_prevhash = l_load(b, g->TypeSizeT, tmp, "prevhash");
 
 						/*
 						 * Rotate bits left by 1 bit.  Be careful not to
 						 * overflow uint32 when working with size_t.
 						 */
-						v_tmp1 = LLVMBuildShl(b, v_prevhash, l_sizet_const(1),
+						v_tmp1 = LLVMBuildShl(b, v_prevhash, LLVMConstInt(g->TypeSizeT, 1, false),
 											  "");
 						v_tmp1 = LLVMBuildAnd(b, v_tmp1,
-											  l_sizet_const(0xffffffff), "");
+											  LLVMConstInt(g->TypeSizeT, 0xffffffff, false), "");
 						v_tmp2 = LLVMBuildLShr(b, v_prevhash,
-											   l_sizet_const(31), "");
+											   LLVMConstInt(g->TypeSizeT, 31, false), "");
 						v_prevhash = LLVMBuildOr(b, v_tmp1, v_tmp2,
 												 "rotatedhash");
 					}
 
 					/* call the hash function */
-					v_retval = BuildV1Call(context, b, mod, fcinfo,
+					v_retval = BuildV1CallLLVM(context, b, mod, fcinfo, v_fcinfo,
 										   &v_fcinfo_isnull);
 
 					/*
@@ -2206,45 +2329,45 @@ llvm_compile_expr(ExprState *state)
 												"xorhash");
 
 					LLVMBuildStore(b, v_retval, v_resvaluep);
-					LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_resnullp);
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
 					break;
 				}
 
 			case EEOP_CONVERT_ROWTYPE:
-				build_EvalXFunc(b, mod, "ExecEvalConvertRowtype",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalConvertRowtype",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_SCALARARRAYOP:
-				build_EvalXFunc(b, mod, "ExecEvalScalarArrayOp",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalScalarArrayOp",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_HASHED_SCALARARRAYOP:
-				build_EvalXFunc(b, mod, "ExecEvalHashedScalarArrayOp",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalHashedScalarArrayOp",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_XMLEXPR:
-				build_EvalXFunc(b, mod, "ExecEvalXmlExpr",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalXmlExpr",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_JSON_CONSTRUCTOR:
-				build_EvalXFunc(b, mod, "ExecEvalJsonConstructor",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalJsonConstructor",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_IS_JSON:
-				build_EvalXFunc(b, mod, "ExecEvalJsonIsPredicate",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalJsonIsPredicate",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -2257,8 +2380,8 @@ llvm_compile_expr(ExprState *state)
 					 * Call ExecEvalJsonExprPath().  It returns the address of
 					 * the step to perform next.
 					 */
-					v_ret = build_EvalXFunc(b, mod, "ExecEvalJsonExprPath",
-											v_state, op, v_econtext);
+					v_ret = build_EvalXFunc(b, context, "ExecEvalJsonExprPath",
+											v_state, v_op, v_econtext);
 
 					/*
 					 * Build a switch to map the return value (v_ret above),
@@ -2343,15 +2466,15 @@ llvm_compile_expr(ExprState *state)
 				}
 
 			case EEOP_JSONEXPR_COERCION:
-				build_EvalXFunc(b, mod, "ExecEvalJsonCoercion",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalJsonCoercion",
+								v_state, v_op, v_econtext);
 
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_JSONEXPR_COERCION_FINISH:
-				build_EvalXFunc(b, mod, "ExecEvalJsonCoercionFinish",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalJsonCoercionFinish",
+								v_state, v_op);
 
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
@@ -2365,8 +2488,8 @@ llvm_compile_expr(ExprState *state)
 					v_aggno = l_int32_const(lc, op->d.aggref.aggno);
 
 					/* load agg value / null */
-					value = l_load_gep1(b, TypeSizeT, v_aggvalues, v_aggno, "aggvalue");
-					isnull = l_load_gep1(b, TypeStorageBool, v_aggnulls, v_aggno, "aggnull");
+					value = l_load_gep1(b, g->TypeSizeT, v_aggvalues, v_aggno, "aggvalue");
+					isnull = l_load_gep1(b, g->TypeStorageBool, v_aggnulls, v_aggno, "aggnull");
 
 					/* and store result */
 					LLVMBuildStore(b, value, v_resvaluep);
@@ -2377,8 +2500,8 @@ llvm_compile_expr(ExprState *state)
 				}
 
 			case EEOP_GROUPING_FUNC:
-				build_EvalXFunc(b, mod, "ExecEvalGroupingFunc",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalGroupingFunc",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -2395,14 +2518,17 @@ llvm_compile_expr(ExprState *state)
 					 * up in ExecInitWindowAgg() after initializing the
 					 * expression). So load it from memory each time round.
 					 */
-					v_wfuncnop = l_ptr_const(&wfunc->wfuncno,
-											 l_ptr(LLVMInt32TypeInContext(lc)));
+					v_wfuncnop = ///l_ptr_const(&wfunc->wfuncno,
+								///			 l_ptr(LLVMInt32TypeInContext(lc)));
+								l_ptr_const_step(d.window_func.wfstate, l_ptr(g->StructWindowFuncExprState));
+					v_wfuncnop = l_struct_member_ptr_by_offset(b, lc, v_wfuncnop, offsetof(WindowFuncExprState, wfuncno) );
+
 					v_wfuncno = l_load(b, LLVMInt32TypeInContext(lc), v_wfuncnop, "v_wfuncno");
 
 					/* load window func value / null */
-					value = l_load_gep1(b, TypeSizeT, v_aggvalues, v_wfuncno,
+					value = l_load_gep1(b, g->TypeSizeT, v_aggvalues, v_wfuncno,
 										"windowvalue");
-					isnull = l_load_gep1(b, TypeStorageBool, v_aggnulls, v_wfuncno,
+					isnull = l_load_gep1(b, g->TypeStorageBool, v_aggnulls, v_wfuncno,
 										 "windownull");
 
 					LLVMBuildStore(b, value, v_resvaluep);
@@ -2413,14 +2539,14 @@ llvm_compile_expr(ExprState *state)
 				}
 
 			case EEOP_MERGE_SUPPORT_FUNC:
-				build_EvalXFunc(b, mod, "ExecEvalMergeSupportFunc",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalMergeSupportFunc",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_SUBPLAN:
-				build_EvalXFunc(b, mod, "ExecEvalSubPlan",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalSubPlan",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -2434,41 +2560,53 @@ llvm_compile_expr(ExprState *state)
 					LLVMValueRef v_fcinfo_isnull;
 					LLVMValueRef v_tmpcontext;
 					LLVMValueRef v_oldcontext;
+					LLVMValueRef v_fcinfo;
 
 					if (opcode == EEOP_AGG_STRICT_DESERIALIZE)
 					{
-						LLVMValueRef v_fcinfo;
 						LLVMValueRef v_argnull0;
 						LLVMBasicBlockRef b_deserialize;
 
 						b_deserialize = l_bb_before_v(opblocks[opno + 1],
 													  "op.%d.deserialize", opno);
 
-						v_fcinfo = l_ptr_const(fcinfo,
-											   l_ptr(StructFunctionCallInfoData));
-						v_argnull0 = l_funcnull(b, v_fcinfo, 0);
+						v_fcinfo = ///l_ptr_const(fcinfo,
+									///		   l_ptr(g->StructFunctionCallInfoData));
+									l_load_member_value_by_offset(b, lc, v_op,
+									l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep, d.agg_deserialize.fcinfo_data));
+						v_argnull0 = l_funcnull(b, v_fcinfo, 0, g);
 
 						LLVMBuildCondBr(b,
 										LLVMBuildICmp(b,
 													  LLVMIntEQ,
 													  v_argnull0,
-													  l_sbool_const(1),
+													  LLVMConstInt(g->TypeStorageBool, (int)(1), false),
 													  ""),
 										opblocks[op->d.agg_deserialize.jumpnull],
 										b_deserialize);
 						LLVMPositionBuilderAtEnd(b, b_deserialize);
 					}
+					else
+					{
+						v_fcinfo = l_load_member_value_by_offset(b, lc, v_op,
+									l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep, d.agg_deserialize.fcinfo_data));
+					}
 
 					aggstate = castNode(AggState, state->parent);
 					fcinfo = op->d.agg_deserialize.fcinfo_data;
 
-					v_tmpcontext =
-						l_ptr_const(aggstate->tmpcontext->ecxt_per_tuple_memory,
-									l_ptr(StructMemoryContextData));
-					v_oldcontext = l_mcxt_switch(mod, b, v_tmpcontext);
-					v_retval = BuildV1Call(context, b, mod, fcinfo,
+					///v_tmpcontext =
+						///l_ptr_const(aggstate->tmpcontext->ecxt_per_tuple_memory,
+						///			l_ptr(g->StructMemoryContextData));
+					///	l_load_struct_gep(b, StructExprState, v_state, FIELDNO_EXPRSTATE_PARENT,"");
+					v_tmpcontext = l_load_struct_gep(b, g->StructExprState, v_state, FIELDNO_EXPRSTATE_PARENT,"");
+					v_tmpcontext = l_load_struct_gep(b, g->StructAggState, v_tmpcontext, FIELDNO_AGGSTATE_TMPCONTEXT,"");
+					v_tmpcontext = l_load_struct_gep(b, g->StructExprContext, v_tmpcontext, FIELDNO_EXPRCONTEXT_PERTUPLEMEMORY,"");
+
+					v_oldcontext = l_mcxt_switch(mod, b, v_tmpcontext, g);
+					v_retval = BuildV1CallLLVM(context, b, mod, fcinfo, v_fcinfo,
 										   &v_fcinfo_isnull);
-					l_mcxt_switch(mod, b, v_oldcontext);
+					l_mcxt_switch(mod, b, v_oldcontext, g);
 
 					LLVMBuildStore(b, v_retval, v_resvaluep);
 					LLVMBuildStore(b, v_fcinfo_isnull, v_resnullp);
@@ -2492,8 +2630,10 @@ llvm_compile_expr(ExprState *state)
 					Assert(nargs > 0);
 
 					jumpnull = op->d.agg_strict_input_check.jumpnull;
-					v_argsp = l_ptr_const(args, l_ptr(StructNullableDatum));
-					v_nullsp = l_ptr_const(nulls, l_ptr(TypeStorageBool));
+					v_argsp = ///l_ptr_const(args, l_ptr(g->StructNullableDatum));
+							l_ptr_const_step(d.agg_strict_input_check.args, l_ptr(g->StructNullableDatum));
+					v_nullsp = ///l_ptr_const(nulls, l_ptr(g->TypeStorageBool));
+							l_ptr_const_step(d.agg_strict_input_check.nulls, l_ptr(g->TypeStorageBool));
 
 					/* create blocks for checking args */
 					b_checknulls = palloc(sizeof(LLVMBasicBlockRef *) * nargs);
@@ -2522,14 +2662,14 @@ llvm_compile_expr(ExprState *state)
 							b_argnotnull = b_checknulls[argno + 1];
 
 						if (opcode == EEOP_AGG_STRICT_INPUT_CHECK_NULLS)
-							v_argisnull = l_load_gep1(b, TypeStorageBool, v_nullsp, v_argno, "");
+							v_argisnull = l_load_gep1(b, g->TypeStorageBool, v_nullsp, v_argno, "");
 						else
 						{
 							LLVMValueRef v_argn;
 
-							v_argn = l_gep(b, StructNullableDatum, v_argsp, &v_argno, 1, "");
+							v_argn = l_gep(b, g->StructNullableDatum, v_argsp, &v_argno, 1, "");
 							v_argisnull =
-								l_load_struct_gep(b, StructNullableDatum, v_argn,
+								l_load_struct_gep(b, g->StructNullableDatum, v_argn,
 												  FIELDNO_NULLABLE_DATUM_ISNULL,
 												  "");
 						}
@@ -2538,7 +2678,7 @@ llvm_compile_expr(ExprState *state)
 										LLVMBuildICmp(b,
 													  LLVMIntEQ,
 													  v_argisnull,
-													  l_sbool_const(1), ""),
+													  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 										opblocks[jumpnull],
 										b_argnotnull);
 					}
@@ -2561,23 +2701,23 @@ llvm_compile_expr(ExprState *state)
 					 * [op->d.agg_plain_pergroup_nullcheck.setoff];
 					 */
 					v_aggstatep = LLVMBuildBitCast(b, v_parent,
-												   l_ptr(StructAggState), "");
+												   l_ptr(g->StructAggState), "");
 
 					v_allpergroupsp = l_load_struct_gep(b,
-														StructAggState,
+														g->StructAggState,
 														v_aggstatep,
 														FIELDNO_AGGSTATE_ALL_PERGROUPS,
 														"aggstate.all_pergroups");
 
 					v_setoff = l_int32_const(lc, op->d.agg_plain_pergroup_nullcheck.setoff);
 
-					v_pergroup_allaggs = l_load_gep1(b, l_ptr(StructAggStatePerGroupData),
+					v_pergroup_allaggs = l_load_gep1(b, l_ptr(g->StructAggStatePerGroupData),
 													 v_allpergroupsp, v_setoff, "");
 
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ,
-												  LLVMBuildPtrToInt(b, v_pergroup_allaggs, TypeSizeT, ""),
-												  l_sizet_const(0), ""),
+												  LLVMBuildPtrToInt(b, v_pergroup_allaggs, g->TypeSizeT, ""),
+												  LLVMConstInt(g->TypeSizeT, 0, false), ""),
 									opblocks[jumpnull],
 									opblocks[opno + 1]);
 					break;
@@ -2626,17 +2766,18 @@ llvm_compile_expr(ExprState *state)
 					fcinfo = pertrans->transfn_fcinfo;
 
 					v_aggstatep =
-						LLVMBuildBitCast(b, v_parent, l_ptr(StructAggState), "");
-					v_pertransp = l_ptr_const(pertrans,
-											  l_ptr(StructAggStatePerTransData));
-
+						LLVMBuildBitCast(b, v_parent, l_ptr(g->StructAggState), "");
+					v_pertransp = ///l_ptr_const(pertrans,
+									///			  l_ptr(g->StructAggStatePerTransData));
+									l_ptr_const_step(d.agg_trans.pertrans,
+												  l_ptr(g->StructAggStatePerTransData));
 					/*
 					 * pergroup = &aggstate->all_pergroups
 					 * [op->d.agg_trans.setoff] [op->d.agg_trans.transno];
 					 */
 					v_allpergroupsp =
 						l_load_struct_gep(b,
-										  StructAggState,
+										  g->StructAggState,
 										  v_aggstatep,
 										  FIELDNO_AGGSTATE_ALL_PERGROUPS,
 										  "aggstate.all_pergroups");
@@ -2644,8 +2785,8 @@ llvm_compile_expr(ExprState *state)
 					v_transno = l_int32_const(lc, op->d.agg_trans.transno);
 					v_pergroupp =
 						l_gep(b,
-							  StructAggStatePerGroupData,
-							  l_load_gep1(b, l_ptr(StructAggStatePerGroupData),
+							  g->StructAggStatePerGroupData,
+							  l_load_gep1(b, l_ptr(g->StructAggStatePerGroupData),
 										  v_allpergroupsp, v_setoff, ""),
 							  &v_transno, 1, "");
 
@@ -2659,7 +2800,7 @@ llvm_compile_expr(ExprState *state)
 
 						v_notransvalue =
 							l_load_struct_gep(b,
-											  StructAggStatePerGroupData,
+											  g->StructAggStatePerGroupData,
 											  v_pergroupp,
 											  FIELDNO_AGGSTATEPERGROUPDATA_NOTRANSVALUE,
 											  "notransvalue");
@@ -2671,7 +2812,7 @@ llvm_compile_expr(ExprState *state)
 
 						LLVMBuildCondBr(b,
 										LLVMBuildICmp(b, LLVMIntEQ, v_notransvalue,
-													  l_sbool_const(1), ""),
+													  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 										b_init,
 										b_no_init);
 
@@ -2681,8 +2822,8 @@ llvm_compile_expr(ExprState *state)
 
 							LLVMPositionBuilderAtEnd(b, b_init);
 
-							v_aggcontext = l_ptr_const(op->d.agg_trans.aggcontext,
-													   l_ptr(StructExprContext));
+							v_aggcontext = l_ptr_const_step(d.agg_trans.aggcontext,
+													   l_ptr(g->StructExprContext));
 
 							params[0] = v_aggstatep;
 							params[1] = v_pertransp;
@@ -2690,8 +2831,8 @@ llvm_compile_expr(ExprState *state)
 							params[3] = v_aggcontext;
 
 							l_call(b,
-								   llvm_pg_var_func_type("ExecAggInitGroup"),
-								   llvm_pg_func(mod, "ExecAggInitGroup"),
+								   llvm_pg_var_func_type(context, "ExecAggInitGroup"),
+								   llvm_pg_func(context, "ExecAggInitGroup"),
 								   params, lengthof(params),
 								   "");
 
@@ -2713,14 +2854,14 @@ llvm_compile_expr(ExprState *state)
 													 "op.%d.strictpass", opno);
 						v_transnull =
 							l_load_struct_gep(b,
-											  StructAggStatePerGroupData,
+											  g->StructAggStatePerGroupData,
 											  v_pergroupp,
 											  FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL,
 											  "transnull");
 
 						LLVMBuildCondBr(b,
 										LLVMBuildICmp(b, LLVMIntEQ, v_transnull,
-													  l_sbool_const(1), ""),
+													  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 										opblocks[opno + 1],
 										b_strictpass);
 
@@ -2728,26 +2869,32 @@ llvm_compile_expr(ExprState *state)
 					}
 
 
-					v_fcinfo = l_ptr_const(fcinfo,
-										   l_ptr(StructFunctionCallInfoData));
-					v_aggcontext = l_ptr_const(op->d.agg_trans.aggcontext,
-											   l_ptr(StructExprContext));
+					v_fcinfo = ///l_ptr_const(fcinfo,
+								///		   l_ptr(g->StructFunctionCallInfoData));
+								l_load_member_value_by_offset(b, lc, v_op,
+									l_ptr(g->StructAggStatePerTransData), offsetof(ExprEvalStep, d.agg_trans.pertrans));
+					v_fcinfo = ///l_ptr_const(fcinfo,
+								///		   l_ptr(g->StructFunctionCallInfoData));
+								l_load_member_value_by_offset(b, lc, v_fcinfo,
+									l_ptr(g->StructFunctionCallInfoData), offsetof(AggStatePerTransData, transfn_fcinfo));
+					v_aggcontext = l_ptr_const_step(d.agg_trans.aggcontext,
+											   l_ptr(g->StructExprContext));
 
 					v_current_setp =
 						l_struct_gep(b,
-									 StructAggState,
+									 g->StructAggState,
 									 v_aggstatep,
 									 FIELDNO_AGGSTATE_CURRENT_SET,
 									 "aggstate.current_set");
 					v_curaggcontext =
 						l_struct_gep(b,
-									 StructAggState,
+									 g->StructAggState,
 									 v_aggstatep,
 									 FIELDNO_AGGSTATE_CURAGGCONTEXT,
 									 "aggstate.curaggcontext");
 					v_current_pertransp =
 						l_struct_gep(b,
-									 StructAggState,
+									 g->StructAggState,
 									 v_aggstatep,
 									 FIELDNO_AGGSTATE_CURPERTRANS,
 									 "aggstate.curpertrans");
@@ -2759,36 +2906,40 @@ llvm_compile_expr(ExprState *state)
 					LLVMBuildStore(b, v_pertransp, v_current_pertransp);
 
 					/* invoke transition function in per-tuple context */
-					v_tmpcontext =
-						l_ptr_const(aggstate->tmpcontext->ecxt_per_tuple_memory,
-									l_ptr(StructMemoryContextData));
-					v_oldcontext = l_mcxt_switch(mod, b, v_tmpcontext);
+					///v_tmpcontext =
+					///	l_ptr_const(aggstate->tmpcontext->ecxt_per_tuple_memory,
+					///				l_ptr(g->StructMemoryContextData));
+					v_tmpcontext = l_load_struct_gep(b, g->StructExprState, v_state, FIELDNO_EXPRSTATE_PARENT,"");
+					v_tmpcontext = l_load_struct_gep(b, g->StructAggState, v_tmpcontext, FIELDNO_AGGSTATE_TMPCONTEXT,"");
+					v_tmpcontext = l_load_struct_gep(b, g->StructExprContext, v_tmpcontext, FIELDNO_EXPRCONTEXT_PERTUPLEMEMORY,"");
+
+					v_oldcontext = l_mcxt_switch(mod, b, v_tmpcontext, g);
 
 					/* store transvalue in fcinfo->args[0] */
 					v_transvaluep =
 						l_struct_gep(b,
-									 StructAggStatePerGroupData,
+									 g->StructAggStatePerGroupData,
 									 v_pergroupp,
 									 FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUE,
 									 "transvalue");
 					v_transnullp =
 						l_struct_gep(b,
-									 StructAggStatePerGroupData,
+									 g->StructAggStatePerGroupData,
 									 v_pergroupp,
 									 FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL,
 									 "transnullp");
 					LLVMBuildStore(b,
 								   l_load(b,
-										  TypeSizeT,
+										  g->TypeSizeT,
 										  v_transvaluep,
 										  "transvalue"),
-								   l_funcvaluep(b, v_fcinfo, 0));
+								   l_funcvaluep(b, v_fcinfo, 0, g));
 					LLVMBuildStore(b,
-								   l_load(b, TypeStorageBool, v_transnullp, "transnull"),
-								   l_funcnullp(b, v_fcinfo, 0));
+								   l_load(b, g->TypeStorageBool, v_transnullp, "transnull"),
+								   l_funcnullp(b, v_fcinfo, 0, g));
 
 					/* and invoke transition function */
-					v_retval = BuildV1Call(context, b, mod, fcinfo,
+					v_retval = BuildV1CallLLVM(context, b, mod, fcinfo, v_fcinfo,
 										   &v_fcinfo_isnull);
 
 					/*
@@ -2817,8 +2968,8 @@ llvm_compile_expr(ExprState *state)
 						b_nocall = l_bb_before_v(opblocks[opno + 1],
 												 "op.%d.transnocall", opno);
 
-						v_transvalue = l_load(b, TypeSizeT, v_transvaluep, "");
-						v_transnull = l_load(b, TypeStorageBool, v_transnullp, "");
+						v_transvalue = l_load(b, g->TypeSizeT, v_transvaluep, "");
+						v_transnull = l_load(b, g->TypeStorageBool, v_transnullp, "");
 
 						/*
 						 * DatumGetPointer(newVal) !=
@@ -2837,12 +2988,12 @@ llvm_compile_expr(ExprState *state)
 						params[1] = v_pertransp;
 						params[2] = v_retval;
 						params[3] = LLVMBuildTrunc(b, v_fcinfo_isnull,
-												   TypeParamBool, "");
+												   g->TypeParamBool, "");
 						params[4] = v_transvalue;
 						params[5] = LLVMBuildTrunc(b, v_transnull,
-												   TypeParamBool, "");
+												   g->TypeParamBool, "");
 
-						v_fn = llvm_pg_func(mod, "ExecAggCopyTransValue");
+						v_fn = llvm_pg_func(context, "ExecAggCopyTransValue");
 						v_newval =
 							l_call(b,
 								   LLVMGetFunctionType(v_fn),
@@ -2854,7 +3005,7 @@ llvm_compile_expr(ExprState *state)
 						LLVMBuildStore(b, v_newval, v_transvaluep);
 						LLVMBuildStore(b, v_fcinfo_isnull, v_transnullp);
 
-						l_mcxt_switch(mod, b, v_oldcontext);
+						l_mcxt_switch(mod, b, v_oldcontext, g);
 						LLVMBuildBr(b, opblocks[opno + 1]);
 
 						/* returned datum passed datum, no need to reparent */
@@ -2865,7 +3016,7 @@ llvm_compile_expr(ExprState *state)
 					LLVMBuildStore(b, v_retval, v_transvaluep);
 					LLVMBuildStore(b, v_fcinfo_isnull, v_transnullp);
 
-					l_mcxt_switch(mod, b, v_oldcontext);
+					l_mcxt_switch(mod, b, v_oldcontext, g);
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
 					break;
@@ -2877,19 +3028,21 @@ llvm_compile_expr(ExprState *state)
 					AggStatePerTrans pertrans = op->d.agg_presorted_distinctcheck.pertrans;
 					int			jumpdistinct = op->d.agg_presorted_distinctcheck.jumpdistinct;
 
-					LLVMValueRef v_fn = llvm_pg_func(mod, "ExecEvalPreOrderedDistinctSingle");
+					LLVMValueRef v_fn = llvm_pg_func(context, "ExecEvalPreOrderedDistinctSingle");
 					LLVMValueRef v_args[2];
 					LLVMValueRef v_ret;
 
-					v_args[0] = l_ptr_const(aggstate, l_ptr(StructAggState));
-					v_args[1] = l_ptr_const(pertrans, l_ptr(StructAggStatePerTransData));
+					///v_args[0] = l_ptr_const(aggstate, l_ptr(g->StructAggState));
+					v_args[0] = v_parent;
+					/// v_args[1] = l_ptr_const(pertrans, l_ptr(g->StructAggStatePerTransData));
+					v_args[1] = l_ptr_const_step(d.agg_presorted_distinctcheck.pertrans, l_ptr(g->StructAggStatePerTransData));
 
 					v_ret = l_call(b, LLVMGetFunctionType(v_fn), v_fn, v_args, 2, "");
-					v_ret = LLVMBuildZExt(b, v_ret, TypeStorageBool, "");
+					v_ret = LLVMBuildZExt(b, v_ret, g->TypeStorageBool, "");
 
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_ret,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									opblocks[opno + 1],
 									opblocks[jumpdistinct]);
 					break;
@@ -2901,33 +3054,35 @@ llvm_compile_expr(ExprState *state)
 					AggStatePerTrans pertrans = op->d.agg_presorted_distinctcheck.pertrans;
 					int			jumpdistinct = op->d.agg_presorted_distinctcheck.jumpdistinct;
 
-					LLVMValueRef v_fn = llvm_pg_func(mod, "ExecEvalPreOrderedDistinctMulti");
+					LLVMValueRef v_fn = llvm_pg_func(context, "ExecEvalPreOrderedDistinctMulti");
 					LLVMValueRef v_args[2];
 					LLVMValueRef v_ret;
 
-					v_args[0] = l_ptr_const(aggstate, l_ptr(StructAggState));
-					v_args[1] = l_ptr_const(pertrans, l_ptr(StructAggStatePerTransData));
+					///v_args[0] = l_ptr_const(aggstate, l_ptr(g->StructAggState));
+					v_args[0] = v_parent;
+					///v_args[1] = l_ptr_const(pertrans, l_ptr(g->StructAggStatePerTransData));
+					v_args[1] = l_ptr_const_step(d.agg_presorted_distinctcheck.pertrans, l_ptr(g->StructAggStatePerTransData));
 
 					v_ret = l_call(b, LLVMGetFunctionType(v_fn), v_fn, v_args, 2, "");
-					v_ret = LLVMBuildZExt(b, v_ret, TypeStorageBool, "");
+					v_ret = LLVMBuildZExt(b, v_ret, g->TypeStorageBool, "");
 
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_ret,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									opblocks[opno + 1],
 									opblocks[jumpdistinct]);
 					break;
 				}
 
 			case EEOP_AGG_ORDERED_TRANS_DATUM:
-				build_EvalXFunc(b, mod, "ExecEvalAggOrderedTransDatum",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalAggOrderedTransDatum",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_AGG_ORDERED_TRANS_TUPLE:
-				build_EvalXFunc(b, mod, "ExecEvalAggOrderedTransTuple",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalAggOrderedTransTuple",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -2955,7 +3110,12 @@ llvm_compile_expr(ExprState *state)
 		state->evalfunc = ExecRunCompiledExpr;
 		state->evalfunc_private = cstate;
 	}
-
+	{
+		char *error = NULL;
+		///LLVMDumpModule(context->module);
+		LLVMVerifyModule(context->module, LLVMAbortProcessAction, &error);
+		LLVMDisposeMessage(error);
+	}
 	llvm_leave_fatal_on_oom();
 
 	INSTR_TIME_SET_CURRENT(endtime);
@@ -2992,7 +3152,7 @@ ExecRunCompiledExpr(ExprState *state, ExprContext *econtext, bool *isNull)
 
 	return func(state, econtext, isNull);
 }
-
+#ifdef DELETE_IT
 static LLVMValueRef
 BuildV1Call(LLVMJitContext *context, LLVMBuilderRef b,
 			LLVMModuleRef mod, FunctionCallInfo fcinfo,
@@ -3008,18 +3168,18 @@ BuildV1Call(LLVMJitContext *context, LLVMBuilderRef b,
 
 	v_fn = llvm_function_reference(context, b, mod, fcinfo);
 
-	v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
+	v_fcinfo = l_ptr_const(fcinfo, l_ptr(g->StructFunctionCallInfoData));
 	v_fcinfo_isnullp = l_struct_gep(b,
-									StructFunctionCallInfoData,
+									g->StructFunctionCallInfoData,
 									v_fcinfo,
 									FIELDNO_FUNCTIONCALLINFODATA_ISNULL,
 									"v_fcinfo_isnull");
-	LLVMBuildStore(b, l_sbool_const(0), v_fcinfo_isnullp);
+	LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_fcinfo_isnullp);
 
 	v_retval = l_call(b, LLVMGetFunctionType(AttributeTemplate), v_fn, &v_fcinfo, 1, "funccall");
 
 	if (v_fcinfo_isnull)
-		*v_fcinfo_isnull = l_load(b, TypeStorageBool, v_fcinfo_isnullp, "");
+		*v_fcinfo_isnull = l_load(b, g->TypeStorageBool, v_fcinfo_isnullp, "");
 
 	/*
 	 * Add lifetime-end annotation, signaling that writes to memory don't have
@@ -3040,7 +3200,57 @@ BuildV1Call(LLVMJitContext *context, LLVMBuilderRef b,
 
 	return v_retval;
 }
+#endif
+static LLVMValueRef
+BuildV1CallLLVM(LLVMJitContext *context, LLVMBuilderRef b,
+			LLVMModuleRef mod, FunctionCallInfo fcinfo2,
+			LLVMValueRef v_fcinfo, LLVMValueRef *v_fcinfo_isnull)
+{
+	LLVMContextRef lc;
+	LLVMValueRef v_fn;
+	LLVMValueRef v_fcinfo_isnullp;
+	LLVMValueRef v_retval;
+
+	lc = LLVMGetModuleContext(mod);
 
+	v_fn = llvm_function_reference(context, b, mod, fcinfo2, v_fcinfo);
+
+	///v_fcinfo = l_ptr_const(fcinfo, l_ptr(g->StructFunctionCallInfoData));
+	v_fcinfo_isnullp = l_struct_gep(b,
+									context->jit_types->StructFunctionCallInfoData,
+									v_fcinfo,
+									FIELDNO_FUNCTIONCALLINFODATA_ISNULL,
+									"v_fcinfo_isnull");
+	LLVMBuildStore(b, LLVMConstInt(context->jit_types->TypeStorageBool, (int)(0), false), v_fcinfo_isnullp);
+
+	v_retval = l_call(b, LLVMGetFunctionType(context->jit_types->AttributeTemplate), v_fn, &v_fcinfo, 1, "funccall");
+
+	if (v_fcinfo_isnull)
+		*v_fcinfo_isnull = l_load(b, context->jit_types->TypeStorageBool, v_fcinfo_isnullp, "");
+
+	/*
+	 * Add lifetime-end annotation, signaling that writes to memory don't have
+	 * to be retained (important for inlining potential).
+	 */
+	{
+		LLVMValueRef v_lifetime = create_LifetimeEnd(mod);
+		LLVMValueRef params[2];
+		/* TODO check fcinfo2->nargs is const or is changed from call to call */
+		params[0] = l_int64_const(lc, sizeof(NullableDatum) * fcinfo2->nargs);
+		params[1] =  ///l_ptr_const(fcinfo->args, l_ptr(LLVMInt8TypeInContext(lc)));
+					l_load_member_value_by_offset(b, lc , v_fcinfo, l_ptr(LLVMInt8TypeInContext(lc)), offsetof(FunctionCallInfoBaseData, args) );
+		l_call(b, LLVMGetFunctionType(v_lifetime), v_lifetime, params, lengthof(params), "");
+
+		params[0] = l_int64_const(lc, sizeof(fcinfo2->isnull));
+		params[1] = /// l_ptr_const(&fcinfo->isnull, l_ptr(LLVMInt8TypeInContext(lc)));
+					l_struct_member_ptr_by_offset(b, lc, v_fcinfo, offsetof(FunctionCallInfoBaseData, isnull));
+		l_call(b, LLVMGetFunctionType(v_lifetime), v_lifetime, params, lengthof(params), "");
+	}
+
+	return v_retval;
+}
+
+#ifdef DELETE_IT
 /*
  * Implement an expression step by calling the function funcname.
  */
@@ -3049,7 +3259,40 @@ build_EvalXFuncInt(LLVMBuilderRef b, LLVMModuleRef mod, const char *funcname,
 				   LLVMValueRef v_state, ExprEvalStep *op,
 				   int nargs, LLVMValueRef *v_args)
 {
-	LLVMValueRef v_fn = llvm_pg_func(mod, funcname);
+	LLVMValueRef v_fn = llvm_pg_func(context, funcname);
+	LLVMValueRef *params;
+	int			argno = 0;
+	LLVMValueRef v_ret;
+
+	/* cheap pre-check as llvm just asserts out */
+	if (LLVMCountParams(v_fn) != (nargs + 2))
+		elog(ERROR, "parameter mismatch: %s expects %d passed %d",
+			 funcname, LLVMCountParams(v_fn), nargs + 2);
+
+	params = palloc(sizeof(LLVMValueRef) * (2 + nargs));
+
+	params[argno++] = v_state;
+	params[argno++] = l_ptr_const(op, l_ptr(g->StructExprEvalStep));
+
+	for (int i = 0; i < nargs; i++)
+		params[argno++] = v_args[i];
+
+	v_ret = l_call(b, LLVMGetFunctionType(v_fn), v_fn, params, argno, "");
+
+	pfree(params);
+
+	return v_ret;
+}
+#endif
+/*
+ * Implement an expression step by calling the function funcname.
+ */
+static LLVMValueRef
+build_EvalXFuncIntLLVM(LLVMBuilderRef b, LLVMJitContext *context, const char *funcname,
+				   LLVMValueRef v_state, LLVMValueRef v_op,
+				   int nargs, LLVMValueRef *v_args)
+{
+	LLVMValueRef v_fn = llvm_pg_func(context, funcname);
 	LLVMValueRef *params;
 	int			argno = 0;
 	LLVMValueRef v_ret;
@@ -3062,7 +3305,7 @@ build_EvalXFuncInt(LLVMBuilderRef b, LLVMModuleRef mod, const char *funcname,
 	params = palloc(sizeof(LLVMValueRef) * (2 + nargs));
 
 	params[argno++] = v_state;
-	params[argno++] = l_ptr_const(op, l_ptr(StructExprEvalStep));
+	params[argno++] = v_op;
 
 	for (int i = 0; i < nargs; i++)
 		params[argno++] = v_args[i];
diff --git a/src/backend/jit/llvm/llvmjit_types.c b/src/backend/jit/llvm/llvmjit_types.c
index dbe0282e98f..f39ddfc30a6 100644
--- a/src/backend/jit/llvm/llvmjit_types.c
+++ b/src/backend/jit/llvm/llvmjit_types.c
@@ -69,6 +69,7 @@ MinimalTupleTableSlot StructMinimalTupleTableSlot;
 TupleDescData StructTupleDescData;
 PlanState	StructPlanState;
 MinimalTupleData StructMinimalTupleData;
+WindowFuncExprState StructWindowFuncExprState;
 
 
 /*
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 45915767825..9bb8ae0e076 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -61,6 +61,9 @@
 #define COPY_LOCATION_FIELD(fldname) \
 	(newnode->fldname = from->fldname)
 
+/* Copy a saved jit context */
+#define COPY_JITCONTEXT_FIELD(fldname) \
+	(newnode->fldname = from->fldname)
 
 #include "copyfuncs.funcs.c"
 
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index f2598a1b69a..6cd16db0a0d 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -84,6 +84,12 @@
 #define COMPARE_COERCIONFORM_FIELD(fldname) \
 	((void) 0)
 
+/* Compare a saved jit context */
+#define COMPARE_JITCONTEXT_FIELD(fldname) \
+	do { \
+		if (a->fldname != b->fldname) \
+			return false; \
+	} while (0)
 
 #include "equalfuncs.funcs.c"
 
diff --git a/src/backend/nodes/gen_node_support.pl b/src/backend/nodes/gen_node_support.pl
index 1a657f7e0ae..d2c284af857 100644
--- a/src/backend/nodes/gen_node_support.pl
+++ b/src/backend/nodes/gen_node_support.pl
@@ -865,6 +865,14 @@ _equal${n}(const $n *a, const $n *b)
 			print $cff "\tCOPY_SCALAR_FIELD($f);\n" unless $copy_ignore;
 			print $eff "\tCOMPARE_SCALAR_FIELD($f);\n" unless $equal_ignore;
 		}
+		elsif ($t eq 'struct CachedJitContext*')
+		{
+			# Fields of these types are required to be a pointer to a
+			# static struct.  So we don't copy the struct itself,
+			# just reference the original one.
+			print $cff "\tCOPY_SCALAR_FIELD($f);\n" unless $copy_ignore;
+			print $eff "\tCOMPARE_SCALAR_FIELD($f);\n" unless $equal_ignore;
+		}
 		else
 		{
 			die
@@ -1214,6 +1222,11 @@ _read${n}(void)
 	}
 ! unless $no_read;
 		}
+		elsif ($t eq 'struct CachedJitContext*')
+		{
+			print $off "\tWRITE_JITCONTEXT_FIELD($f);\n";
+			print $rff "\tREAD_JITCONTEXT_FIELD($f);\n" unless $no_read;
+		}
 		else
 		{
 			die
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index bb9bdd67192..9c772a00197 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -93,6 +93,10 @@ static void outDouble(StringInfo str, double d);
 #define WRITE_LOCATION_FIELD(fldname) \
 	appendStringInfo(str, " :" CppAsString(fldname) " %d", write_location_fields ? node->fldname : -1)
 
+/* Write a parse jit context field (actually same as INT case) */
+#define WRITE_JITCONTEXT_FIELD(fldname) \
+	appendStringInfo(str, " :" CppAsString(fldname) " %d", 0)
+
 /* Write a Node field */
 #define WRITE_NODE_FIELD(fldname) \
 	(appendStringInfoString(str, " :" CppAsString(fldname) " "), \
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index 64d3a09f765..b4bb27353a5 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -131,6 +131,12 @@
 	local_node->fldname = -1	/* set field to "unknown" */
 #endif
 
+/* Read a parse jit context field*/
+#define READ_JITCONTEXT_FIELD(fldname) \
+	token = pg_strtok(&length);		/* skip :fldname */ \
+	token = pg_strtok(&length);		/* get field value */ \
+	local_node->fldname = (struct CachedJitContext*)atoi(token)
+
 /* Read a Node field */
 #define READ_NODE_FIELD(fldname) \
 	token = pg_strtok(&length);		/* skip :fldname */ \
diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c
index 55db8f53705..f2016ed79d3 100644
--- a/src/backend/utils/cache/plancache.c
+++ b/src/backend/utils/cache/plancache.c
@@ -72,6 +72,7 @@
 #include "utils/rls.h"
 #include "utils/snapmgr.h"
 #include "utils/syscache.h"
+#include "jit/jit.h"
 
 
 /*
@@ -1015,6 +1016,10 @@ BuildCachedPlan(CachedPlanSource *plansource, List *qlist,
 			is_transient = true;
 		if (plannedstmt->dependsOnRole)
 			plan->dependsOnRole = true;
+		if (!plansource->is_oneshot && !plannedstmt->jit_context)
+		{
+			plannedstmt->jit_context = CACHED_JITCONTEXT_EMPTY;
+		}
 	}
 	if (is_transient)
 	{
@@ -1305,7 +1310,21 @@ ReleaseCachedPlan(CachedPlan *plan, ResourceOwner owner)
 
 		/* One-shot plans do not own their context, so we can't free them */
 		if (!plan->is_oneshot)
+		{
+			/* release cached jit contexts */
+			ListCell   *lc;
+			foreach(lc, plan->stmt_list)
+			{
+				PlannedStmt *plannedstmt = lfirst_node(PlannedStmt, lc);
+
+				if (plannedstmt->jit_context &&
+					plannedstmt->jit_context != CACHED_JITCONTEXT_EMPTY)
+				{
+					jit_release_context(plannedstmt->jit_context); /* todo fix to correct pointer to jit context (.jit)*/
+				}
+			}
 			MemoryContextDelete(plan->context);
+		}
 	}
 }
 
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index ce7534d4d23..0fe8349e9b8 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -1983,6 +1983,18 @@ struct config_bool ConfigureNamesBool[] =
 		NULL, NULL, NULL
 	},
 
+	{
+		{"jit_cached", PGC_USERSET, QUERY_TUNING_OTHER,
+			gettext_noop("Allow JIT compilation to store in a plan cache."),
+			NULL,
+			GUC_EXPLAIN
+		},
+		&jit_cached,
+		false,
+		NULL, NULL, NULL
+	},
+
+
 	{
 		{"jit_debugging_support", PGC_SU_BACKEND, DEVELOPER_OPTIONS,
 			gettext_noop("Register JIT-compiled functions with debugger."),
diff --git a/src/include/executor/execExpr.h b/src/include/executor/execExpr.h
index 51bd35dcb07..092d3f850fb 100644
--- a/src/include/executor/execExpr.h
+++ b/src/include/executor/execExpr.h
@@ -301,7 +301,9 @@ typedef struct ExprEvalStep
 	intptr_t	opcode;
 
 	/* where to store the result of this step */
+#define FIELDNO_EXPREVALSTEP_RESVALUE	1
 	Datum	   *resvalue;
+#define FIELDNO_EXPREVALSTEP_RESNULL	2
 	bool	   *resnull;
 
 	/*
diff --git a/src/include/jit/jit.h b/src/include/jit/jit.h
index 33cb36c5d2e..ca8dc047c7f 100644
--- a/src/include/jit/jit.h
+++ b/src/include/jit/jit.h
@@ -81,6 +81,7 @@ struct JitProviderCallbacks
 
 /* GUCs */
 extern PGDLLIMPORT bool jit_enabled;
+extern PGDLLIMPORT bool jit_cached;
 extern PGDLLIMPORT char *jit_provider;
 extern PGDLLIMPORT bool jit_debugging_support;
 extern PGDLLIMPORT bool jit_dump_bitcode;
diff --git a/src/include/jit/llvmjit.h b/src/include/jit/llvmjit.h
index 5038cf33e3f..b4489786a03 100644
--- a/src/include/jit/llvmjit.h
+++ b/src/include/jit/llvmjit.h
@@ -40,6 +40,38 @@ extern "C"
 #include "jit/jit.h"
 #include "nodes/pg_list.h"
 
+/* type and struct definitions */
+typedef struct LLVMJitTypes
+{
+	LLVMTypeRef TypeParamBool;
+	LLVMTypeRef TypePGFunction;
+	LLVMTypeRef TypeSizeT;
+	LLVMTypeRef TypeStorageBool;
+
+	LLVMTypeRef StructNullableDatum;
+	LLVMTypeRef StructTupleDescData;
+	LLVMTypeRef StructHeapTupleData;
+	LLVMTypeRef StructHeapTupleHeaderData;
+	LLVMTypeRef StructMinimalTupleData;
+	LLVMTypeRef StructTupleTableSlot;
+	LLVMTypeRef StructHeapTupleTableSlot;
+	LLVMTypeRef StructMinimalTupleTableSlot;
+	LLVMTypeRef StructMemoryContextData;
+	LLVMTypeRef StructFunctionCallInfoData;
+	LLVMTypeRef StructExprContext;
+	LLVMTypeRef StructExprEvalStep;
+	LLVMTypeRef StructExprState;
+	LLVMTypeRef StructAggState;
+	LLVMTypeRef StructAggStatePerTransData;
+	LLVMTypeRef StructAggStatePerGroupData;
+	LLVMTypeRef StructPlanState;
+	LLVMTypeRef StructWindowFuncExprState;
+
+	LLVMValueRef AttributeTemplate;
+	LLVMValueRef ExecEvalBoolSubroutineTemplate;
+	LLVMValueRef ExecEvalSubroutineTemplate;
+} LLVMJitTypes;
+
 typedef struct LLVMJitContext
 {
 	JitContext	base;
@@ -60,44 +92,34 @@ typedef struct LLVMJitContext
 	/* current, "open for write", module */
 	LLVMModuleRef module;
 
+	/* types module in llvm_context or NULL */
+	LLVMModuleRef llvm_types_module;
+
+	/* types defined in types module */
+	LLVMJitTypes *jit_types;
+
 	/* is there any pending code that needs to be emitted */
 	bool		compiled;
 
 	/* # of objects emitted, used to generate non-conflicting names */
-	int			counter;
+	int			counter_expr;
+
+	/* max # of objects emitted, used to start counting from 0 */
+	int			max_counter_expr;
+
+	/* # of objects emitted, used to generate non-conflicting names */
+	int			counter_deform;
 
 	/* list of handles for code emitted via Orc */
 	List	   *handles;
 } LLVMJitContext;
 
-/* type and struct definitions */
-extern PGDLLIMPORT LLVMTypeRef TypeParamBool;
-extern PGDLLIMPORT LLVMTypeRef TypePGFunction;
-extern PGDLLIMPORT LLVMTypeRef TypeSizeT;
-extern PGDLLIMPORT LLVMTypeRef TypeStorageBool;
-
-extern PGDLLIMPORT LLVMTypeRef StructNullableDatum;
-extern PGDLLIMPORT LLVMTypeRef StructTupleDescData;
-extern PGDLLIMPORT LLVMTypeRef StructHeapTupleData;
-extern PGDLLIMPORT LLVMTypeRef StructHeapTupleHeaderData;
-extern PGDLLIMPORT LLVMTypeRef StructMinimalTupleData;
-extern PGDLLIMPORT LLVMTypeRef StructTupleTableSlot;
-extern PGDLLIMPORT LLVMTypeRef StructHeapTupleTableSlot;
-extern PGDLLIMPORT LLVMTypeRef StructMinimalTupleTableSlot;
-extern PGDLLIMPORT LLVMTypeRef StructMemoryContextData;
-extern PGDLLIMPORT LLVMTypeRef StructFunctionCallInfoData;
-extern PGDLLIMPORT LLVMTypeRef StructExprContext;
-extern PGDLLIMPORT LLVMTypeRef StructExprEvalStep;
-extern PGDLLIMPORT LLVMTypeRef StructExprState;
-extern PGDLLIMPORT LLVMTypeRef StructAggState;
-extern PGDLLIMPORT LLVMTypeRef StructAggStatePerTransData;
-extern PGDLLIMPORT LLVMTypeRef StructAggStatePerGroupData;
-extern PGDLLIMPORT LLVMTypeRef StructPlanState;
-
-extern PGDLLIMPORT LLVMValueRef AttributeTemplate;
-extern PGDLLIMPORT LLVMValueRef ExecEvalBoolSubroutineTemplate;
-extern PGDLLIMPORT LLVMValueRef ExecEvalSubroutineTemplate;
+struct CachedJitContext
+{
+	LLVMJitContext	jit;
+};
 
+extern PGDLLIMPORT LLVMJitTypes llvm_jit_types_struct;
 
 extern void llvm_enter_fatal_on_oom(void);
 extern void llvm_leave_fatal_on_oom(void);
@@ -106,18 +128,21 @@ extern void llvm_reset_after_error(void);
 extern void llvm_assert_in_fatal_section(void);
 
 extern LLVMJitContext *llvm_create_context(int jitFlags);
+extern LLVMJitContext *llvm_create_cached_context(int jitFlags);
 extern LLVMModuleRef llvm_mutable_module(LLVMJitContext *context);
-extern char *llvm_expand_funcname(LLVMJitContext *context, const char *basename);
+extern char *llvm_expand_funcname_expr(LLVMJitContext *context, const char *basename);
+extern char *llvm_expand_funcname_deform(LLVMJitContext *context, const char *basename);
 extern void *llvm_get_function(LLVMJitContext *context, const char *funcname);
 extern void llvm_split_symbol_name(const char *name, char **modname, char **funcname);
-extern LLVMTypeRef llvm_pg_var_type(const char *varname);
-extern LLVMTypeRef llvm_pg_var_func_type(const char *varname);
-extern LLVMValueRef llvm_pg_func(LLVMModuleRef mod, const char *funcname);
+extern LLVMTypeRef llvm_pg_var_type(LLVMModuleRef llvm_types_module, const char *varname);
+extern LLVMTypeRef llvm_pg_var_func_type(LLVMJitContext *context, const char *varname);
+extern LLVMValueRef llvm_pg_func(LLVMJitContext *context /*LLVMModuleRef mod*/, const char *funcname);
 extern void llvm_copy_attributes(LLVMValueRef from, LLVMValueRef to);
 extern LLVMValueRef llvm_function_reference(LLVMJitContext *context,
 						LLVMBuilderRef builder,
 						LLVMModuleRef mod,
-						FunctionCallInfo fcinfo);
+						FunctionCallInfo fcinfo,
+						LLVMValueRef v_fcinfo);
 
 extern void llvm_inline_reset_caches(void);
 extern void llvm_inline(LLVMModuleRef mod);
diff --git a/src/include/jit/llvmjit_emit.h b/src/include/jit/llvmjit_emit.h
index df5a9fc8500..6f8d0e83649 100644
--- a/src/include/jit/llvmjit_emit.h
+++ b/src/include/jit/llvmjit_emit.h
@@ -25,7 +25,7 @@
  * Emit a non-LLVM pointer as an LLVM constant.
  */
 static inline LLVMValueRef
-l_ptr_const(void *ptr, LLVMTypeRef type)
+l_ptr_const(void *ptr, LLVMTypeRef type, LLVMTypeRef TypeSizeT)
 {
 	LLVMValueRef c = LLVMConstInt(TypeSizeT, (uintptr_t) ptr, false);
 
@@ -76,7 +76,7 @@ l_int64_const(LLVMContextRef lc, int64 i)
 {
 	return LLVMConstInt(LLVMInt64TypeInContext(lc), i, false);
 }
-
+#ifdef DELETE_IT
 /*
  * Emit constant integer.
  */
@@ -95,6 +95,7 @@ l_sbool_const(bool i)
 	return LLVMConstInt(TypeStorageBool, (int) i, false);
 }
 
+
 /*
  * Emit constant boolean, as used for parameters (e.g. function parameters).
  */
@@ -103,6 +104,7 @@ l_pbool_const(bool i)
 {
 	return LLVMConstInt(TypeParamBool, (int) i, false);
 }
+#endif
 
 static inline LLVMValueRef
 l_struct_gep(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, int32 idx, const char *name)
@@ -149,6 +151,44 @@ l_load_gep1(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, LLVMValueRef idx, c
 	return l_load(b, t, l_gep(b, t, v, &idx, 1, ""), name);
 }
 
+#ifndef DELETE_IT
+/*
+ * Load value of a structure using offset of member in structure.
+ * b - builder
+ * v - value of sturcture
+ * dest - the type of the structure member
+ * offset - the offset of the structure member in the structure v
+ */
+static inline LLVMValueRef
+l_load_member_value_by_offset(LLVMBuilderRef b, LLVMContextRef lc, LLVMValueRef v, LLVMTypeRef dest, int offset)
+{
+#ifdef _DELETE_IT
+    LLVMValueRef castbase = LLVMBuildPtrToInt(b, v, LLVMInt64TypeInContext(llvm_context), "base_pointer");
+    LLVMValueRef castchar1offset = LLVMBuildAdd(b, castbase, l_int64_const(llvm_context, offset), "member_pointer_int");
+    LLVMValueRef castchar2 = LLVMBuildIntToPtr(b, castchar1offset,  l_ptr(dest), "member_pointer");
+    return l_load(b, dest, castchar2, "member_value");
+#endif
+    LLVMValueRef offsets = l_int32_const(lc, offset);
+    LLVMValueRef member_address = l_gep(b,(LLVMInt8TypeInContext(lc)), v, &offsets, 1, "member_address");
+    return l_load(b, dest, member_address, "member_value");
+}
+
+#define l_ptr_const_step(m,t) l_load_member_value_by_offset(b,lc, v_op, t, offsetof(ExprEvalStep ,m))
+
+static inline LLVMValueRef
+l_struct_member_ptr_by_offset(LLVMBuilderRef b, LLVMContextRef lc, LLVMValueRef v, /* LLVMTypeRef dest, */ int offset)
+{
+#ifdef _DELETE_IT
+    LLVMValueRef castbase = LLVMBuildPtrToInt(b, v, LLVMInt64TypeInContext(llvm_context), "base_pointer");
+    LLVMValueRef castchar1offset = LLVMBuildAdd(b, castbase, l_int64_const(llvm_context, offset), "member_pointer_int");
+    LLVMValueRef castchar2 = LLVMBuildIntToPtr(b, castchar1offset,  l_ptr(dest), "member_pointer");
+    return l_load(b, dest, castchar2, "member_value");
+#endif
+    LLVMValueRef offsets = l_int32_const(lc, offset);
+    LLVMValueRef member_address = l_gep(b,(LLVMInt8TypeInContext(lc)), v, &offsets, 1, "member_address");
+    return member_address;
+}
+#endif
 /* separate, because pg_attribute_printf(2, 3) can't appear in definition */
 static inline LLVMBasicBlockRef l_bb_before_v(LLVMBasicBlockRef r, const char *fmt,...) pg_attribute_printf(2, 3);
 
@@ -232,15 +272,15 @@ l_callsite_alwaysinline(LLVMValueRef f)
  * Emit code to switch memory context.
  */
 static inline LLVMValueRef
-l_mcxt_switch(LLVMModuleRef mod, LLVMBuilderRef b, LLVMValueRef nc)
+l_mcxt_switch(LLVMModuleRef mod, LLVMBuilderRef b, LLVMValueRef nc, LLVMJitTypes *g)
 {
 	const char *cmc = "CurrentMemoryContext";
 	LLVMValueRef cur;
 	LLVMValueRef ret;
 
 	if (!(cur = LLVMGetNamedGlobal(mod, cmc)))
-		cur = LLVMAddGlobal(mod, l_ptr(StructMemoryContextData), cmc);
-	ret = l_load(b, l_ptr(StructMemoryContextData), cur, cmc);
+		cur = LLVMAddGlobal(mod, l_ptr(g->StructMemoryContextData), cmc);
+	ret = l_load(b, l_ptr(g->StructMemoryContextData), cur, cmc);
 	LLVMBuildStore(b, nc, cur);
 
 	return ret;
@@ -250,23 +290,23 @@ l_mcxt_switch(LLVMModuleRef mod, LLVMBuilderRef b, LLVMValueRef nc)
  * Return pointer to the argno'th argument nullness.
  */
 static inline LLVMValueRef
-l_funcnullp(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
+l_funcnullp(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno, LLVMJitTypes *g)
 {
 	LLVMValueRef v_args;
 	LLVMValueRef v_argn;
 
 	v_args = l_struct_gep(b,
-						  StructFunctionCallInfoData,
+						  g->StructFunctionCallInfoData,
 						  v_fcinfo,
 						  FIELDNO_FUNCTIONCALLINFODATA_ARGS,
 						  "");
 	v_argn = l_struct_gep(b,
-						  LLVMArrayType(StructNullableDatum, 0),
+						  LLVMArrayType(g->StructNullableDatum, 0),
 						  v_args,
 						  argno,
 						  "");
 	return l_struct_gep(b,
-						StructNullableDatum,
+						g->StructNullableDatum,
 						v_argn,
 						FIELDNO_NULLABLE_DATUM_ISNULL,
 						"");
@@ -276,23 +316,23 @@ l_funcnullp(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
  * Return pointer to the argno'th argument datum.
  */
 static inline LLVMValueRef
-l_funcvaluep(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
+l_funcvaluep(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno, LLVMJitTypes *g)
 {
 	LLVMValueRef v_args;
 	LLVMValueRef v_argn;
 
 	v_args = l_struct_gep(b,
-						  StructFunctionCallInfoData,
+						  g->StructFunctionCallInfoData,
 						  v_fcinfo,
 						  FIELDNO_FUNCTIONCALLINFODATA_ARGS,
 						  "");
 	v_argn = l_struct_gep(b,
-						  LLVMArrayType(StructNullableDatum, 0),
+						  LLVMArrayType(g->StructNullableDatum, 0),
 						  v_args,
 						  argno,
 						  "");
 	return l_struct_gep(b,
-						StructNullableDatum,
+						g->StructNullableDatum,
 						v_argn,
 						FIELDNO_NULLABLE_DATUM_DATUM,
 						"");
@@ -302,18 +342,18 @@ l_funcvaluep(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
  * Return argno'th argument nullness.
  */
 static inline LLVMValueRef
-l_funcnull(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
+l_funcnull(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno, LLVMJitTypes *g)
 {
-	return l_load(b, TypeStorageBool, l_funcnullp(b, v_fcinfo, argno), "");
+	return l_load(b, g->TypeStorageBool, l_funcnullp(b, v_fcinfo, argno, g), "");
 }
 
 /*
  * Return argno'th argument datum.
  */
 static inline LLVMValueRef
-l_funcvalue(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
+l_funcvalue(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno, LLVMJitTypes *g)
 {
-	return l_load(b, TypeSizeT, l_funcvaluep(b, v_fcinfo, argno), "");
+	return l_load(b, g->TypeSizeT, l_funcvaluep(b, v_fcinfo, argno, g), "");
 }
 
 #endif							/* USE_LLVM */
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index e2d1dc1e067..0267781b25d 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -108,6 +108,7 @@ typedef struct ExprState
 	/*
 	 * Instructions to compute expression's return value.
 	 */
+#define FIELDNO_EXPRSTATE_STEPS	5
 	struct ExprEvalStep *steps;
 
 	/*
@@ -272,6 +273,7 @@ typedef struct ExprContext
 
 	/* Memory contexts for expression evaluation --- see notes above */
 	MemoryContext ecxt_per_query_memory;
+#define FIELDNO_EXPRCONTEXT_PERTUPLEMEMORY 5
 	MemoryContext ecxt_per_tuple_memory;
 
 	/* Values to substitute for Param nodes in expression */
@@ -2534,6 +2536,7 @@ typedef struct AggState
 	AggStatePerTrans pertrans;	/* per-Trans state information */
 	ExprContext *hashcontext;	/* econtexts for long-lived data (hashtable) */
 	ExprContext **aggcontexts;	/* econtexts for long-lived data (per GS) */
+#define FIELDNO_AGGSTATE_TMPCONTEXT 13
 	ExprContext *tmpcontext;	/* econtext for input expressions */
 #define FIELDNO_AGGSTATE_CURAGGCONTEXT 14
 	ExprContext *curaggcontext; /* currently active aggcontext */
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 2a2cf816cb6..a5c0a310191 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -22,7 +22,8 @@
 #include "nodes/lockoptions.h"
 #include "nodes/primnodes.h"
 
-
+struct CachedJitContext;
+#define CACHED_JITCONTEXT_EMPTY ((struct CachedJitContext*)(-1))
 /* ----------------------------------------------------------------
  *						node definitions
  * ----------------------------------------------------------------
@@ -104,6 +105,7 @@ typedef struct PlannedStmt
 	/* statement location in source string (copied from Query) */
 	ParseLoc	stmt_location;	/* start location, or -1 if unknown */
 	ParseLoc	stmt_len;		/* length in bytes; 0 means "rest of string" */
+	struct CachedJitContext	*jit_context;	/* context of save jit-module */
 } PlannedStmt;
 
 /* macro for fetching the Plan associated with a SubPlan node */
-- 
2.39.5 (Apple Git-154)

jitinit.sqltext/plain; name=jitinit.sqlDownload
jitbench.shtext/plain; name=jitbench.shDownload
jit_cached_bench.pngimage/png; name=jit_cached_bench.pngDownload
�PNG


IHDR�S����	pHYs��%��z IDATx���{\Tu�?��(��Y.�U��$� "&�X(iF����Ws�U7����(�7���l��V31���oY (yY�@�`B�����eQn2r~�p��9s�33����3���|���y��r��0!�B1����B!�b�(�$�B!�B�$!�B�
$	!�BH�P I!�B��IB!��-HB!��n��@����X�b
%�|��P�TX�~=���-�:B!����&��'O"&&_~�%jjjD����b��=��s'���5k�X���B!}�M���G^^���$����{��e���/#++��-$�B��l2�		���#�����GZZ�����(�;w�B�#�B�X��r��]xzz���c��?����W���vvv\������	!�t������g�fbU}6�;v,,XGGG,Y��=�n����c�ry�|�I�m���m��B�A����n!Vg�C�R���QRRx���������vdggC�Tj��B!�gl2������a�������(6UUU8|�0�}�]�������R(
���+��{��[M!������vjj�hzXX.\�pww��s����gggK6�B!�_��I)
��W��J� �B!�<l�GRJ@@���@!��o��IB!�b9HB!��n�@�B!�t��B!�[(�$�B!�B�$!�B�
$	!�BH�P I!�B��IB!��-HB!��n�@�B!�t��B!�[(�$�B!�B�$!�B�
$	!�BH�P I!�B�e���]��_GRR����������={p��Y����'c��l!!�BH�f�����'�e�444`����y������0���C-�DB!��>�&����#//O<��d���:��9!!!l!�BH�a�s$CBB0r�H�y����g��������GAA��ZG!��?�d��1��[///��5|����PZZ��'##�h����[���B!6��FR6$88�����������NNN(//���%����#::Z�fB����A�h�C�R���QRR����c������y�+�JxyyY����4��wk~B!D�Mm���!##w��ETT����b>|w����������b���hhh�����w�^���Y���4�������A��L�m�U�F!��&6H������������E�a��Ehnn��!C,�<b�tH�c��n�;� ���B�E����B�������(�$F����D�m<S5������[����B��l�GRJ@@���@l�������9�����KW������g*�PB�w�T I�I�=��R������B�g���6!&q���7;�ml��������B!}�H���mK��������B���4Z�a;,��x����9�� ��GP )7v����>��=�&�8�^�B�
$�&(`��q���� ��K)v!��$�b�(��4�Q@i9�wk�5��[z%��h/���-�������-"	!��A�m��
���a����Bnbw�1t9k��>�������M�������!��^�Is�����nkh���w]J�o�u������K�U���oQ i	����bW������N�������4�s=���k��4������+��^���oP iI��U,�Ct��)O�����c�J_/�1�����5e��_��A�@����$��+Q i
�@QP6]���[�)���T�<�A�D��#~�;�[��NW~zmBH�A��5I�>�'_7����i���}���#�!z@7�d��)�$��D�do!6�����=Y���p_�����$��%�?/����Bl���)'Q�I�6�������
c�u���mO�K�%�H�#u�)C���6����^�I[%���u�m����==�����]~>:i����X�s���`;[V_z}�]��A���;
�]��"��/1��r��wf�z�	�Q6H^�~III�������d���zl����0e�����E��Q����1��4a��?1I�4���5h�Pg�g��P�5.v�#.������a���|rYZe�D�iO�����(�$����@������e�|�r�y_|�E=z�?���Zgab'a}C�Zi&�������e.�7�W6���_l8"�C�3�������?z��6Ge�X������@��a����������'�xBo���4\�~�?���Z���������m������g�O}=���c
�d�,���~"u;HS����M�;�[H'5����k������>�&����y~��g�_�999��y�Z�������
$�ObC��|�S�H�����X/�Yz��A�L�tCu�TB�
��@����o���/c��I�y222�0�VZzzz��U����,�5�GYgY�����ub��5��y�����]1xj[������{v	1��y�}�W�`��x����U���� ������B�������p��1�=����z�*���WWW��9O>���v�������a�����?��G��������b2��@z��v<���@���mmmP*��������9�3f����������w�%M I!��G�d �����{QQQ:t(���q��a��s���GDD������M��������d�f�K��$�B�
��@25U��aaa�p��N���n�&�'�9b�B!��{k7@N
��W��v3�k�d�B!���O�����k7C?�������,y�k��B!���@����H6����z,	!�b3lr�d���A�c	�+5���A�B��(��
�6v�,�����������K��B!�X���0t��{�����f�%M���`�!�t
0I#|���a���B&Lc��]�-~;��t��Jb�
�F�� ��nv�����4c���c��4%��.��������8B��������R\�����:��|���� &���p�!������'4���)�
"�*���
��4@;�c�d���;?���6�u�qi��E�<�/�=���1��0�������������u��[?�d���z�buH����C�w��Dpg���>���
����?��O�b'N~/�TOOo#���-����+y�+�=>bA���.��ghJb��w|��Jm+���7�Z��cL�=+�Q�}u�"=B��P i���K�d%u2��R��T��������G�����,C��P�7J�W�reW�lk�p��&3�*��M�z��z��z����'�O�:�9~���
��wR��6����tI}+S�!c����?�/M�X������_C����������_Bz
$�"�Y��X��Blh����!���
{��i����{
Pa��C�������dC�{��9~���jO<cz���<c���T���W��l�K���rlO�(��O�'[S�K��w@3d�<Cw��Z����
��n�j#���'mnoJ��y�R�cS��:����@W�GH,��G_�9!��F�d'�|���/>ve���-��M��=�aZ6�
�y� K16�b{8����9������dHU���B�=
$�8C=lM�4��T��W���B8�;����N��C��/��l
�B�H���
�����y,6���W�#,��g�+�����F
�!���@��K�P���^a�'\d���b�U�"
	!���@���X�����c{��{�)�B!G�$�a0(\������B�����BtP�H!���
$�_��+V���P����$%%A�R!11UUUn!!�BH�f�����'�/��555�y^|�ETTT ))	7o���/�l�VB!��m69Gr�������O<!�g��E������#�|�r<��3l!!�BH�g��dHH��<�>�,n����G���������/��B!����@�Xuuu�x�"Z[[1l�0��322�0�VZzz���G!�b��d ������j�������������'�,Y�B��{��'��KOOGtt���K!�Q�!6��FJyy9JJJ�V�1{�l�����_�888X�y�B!}�M�qqq6l����a�����
�����GGG�������
www�[�~�!F�a��B!��69����*��."##���f2���#�B�l�GR�B�������(�$�B1����`�&B!��}�G�B!�X��B!�[d�.))AZZ�^��~��<�|}}�1c��]!�B��z$[[[�c�����a���b������B}}=f���>�rUI!�v��}444p����-��t�QPP��_~111�6m�y�$&&���+(((@uu�\UB!�����`���o@3�������mh������E]]�{�9��G��}���U!�Bl�J��J���nll��%KPZZj��������z$'M������X�t)��]��'j�477�U!�B����l,[������2��;���)))���?�x�
477#''�>�,bcc����E����I�}����J����SO=�E����������7il�l=�
��o�FZZ�`���������B�7��4�O]���O�b�(������h���Z���}�y�t����VTWWs�w�����X�>}Zoy�����m._��T*899A�T����8{�,�;�Y�f������IXj�Z4����h����M������~���xzz"::���F��-�-������S�0c�<x��VhB!2��N#.��$k�m�$��~ {}s���Z^VV"##1~��\�J�+W�@�TB�T"44������r�e������E� ����	�R��%""%%%�?�����HN�4	�����������W�^��B!&�:��G�Z�����9p�����Ce-���
t�0���5j����Kwp��O�X~�����V���6l���e�hh�B��6�bcL������K{~m������q��=������{�n444����N�BBB�l��*��1��������@yy9&L�����c���F��-���6��3�<���Wc��a�u�F��1c����N��!���x{{&N����6�|>>>X�~=f��������",,����5R����J4C�O?�4<==������H�����1��Y �0x���q��)�=?���z�-�������Ezz:�����B!6��=w��	$''#33�K{���j5
dp{v8�?�,'������kN�>���f��|���
���G>;;��G}}=������<���F�U �BH�WTT���,]�T+���UUU��s��v�6m���/��7nU�����+\����������&xyyqm��appp��;w���!wu�B�Ac����C�0u�T��<<<�e��������,)AAAx���d)���H��77nDEE<==q��%�?��HB!�pF���xrrr����e�G���(
(
���[���\\\P\\�i�����/���9"w5�~�:V�X���B������k�.�T*l��7n���
�B!��Yf�>6l0G���'Ob��-hhh����E�l�����x��������^z	����D!����g���
>yyyx��'$���=���=z4���g[���B1�����*���f�1��M��m��v��>���C�yyyZ����_���we�#$$#G�����g�����+������g���~B!��\NNV�X�����+�J��R����x�b����^G���>BRR�j5z�!@{{;���Q]]-�-�������ukF���v����(--�'�|�s�����|MB!�]GR^����>}:JKK���n�_S���:�qqqppp��?��
%��������}�������Oc��QHOO����N�'�|R���,!�c���[�	6/;;��U�p��A��ueee�;w��@,%%|�����|�rl��yyyHNN�0������3���
ggg�2rrr$�������G}$��p���uvv��#Gp�����`��Ux���v�us���EEE�x�"�N��/�����Z�8p���:Q���hkk����m��Q�F������L"�Bz��{�L5��J����^}N��"����InmmEuu5�{��]���5D���b��m�|�2\\\�R�����R��������8v�f������
,-G�V�����-������z�����������Gaa!���������t�H[�l�����M�������(..�{�.���0t�P�����s�����]��������_��1c���B!����J�-�����������eee!22����J���+W�T*�T*
���Cyy����������{zz������z***0b������.8YYY�3�tss������w���������������EnQ�L��)!�_���B��\�����K����������������6�*{{{������\�1�&���|C��R�Z����;���h��ck7p1����={D�a�:��m�(
�^��l��La�V!����)�$��=O���X�(w`�u�������{�EEEa���hhh���#N�:�����!U~{{�lu�����$a���HII�����u��l��?����T���#$$Dg������
bcc%o��Sf)��(�$�B���L�8��]��A�D����`����5k�j5/^���0�;w�����PH����mp[S�������[�]�&66��}�6�.�������B�����/���DDD <<
������������Rvr��>SX�3E??�����+��	
,	!�v��>z���HNN������V�%�H>�Z
@�u�,�������6899��3������kjj����q��)ddd ##&L0GU�1���)�%?���|������)��o,��<B��(�����"���a���HLL�z�����s��v�6m�������Y�a�@R�V�����_�:���%?�
,��*;~%}{����g
�
$���%;SX��#g1gJWpK=����������CEE�N��3�����7n�n7~�x���]��e�^�����t�R���h���{��,�p��\���W��KSz����s>Y��O�k�'�?��BD�5Jr����&O�,K=r�Et�H~���

Bff�Q���?�4���Js	�/���L�}��m%�B�I�@r��	�x�"�}�&���C)��jj�y��ez�4ayl}B�zr�rMH<r���l�����S��C�#���=������������z����OBH��H4G�ENNy�.���Cf�E"�<}=��]nQ�h�`(�����z�P3`�E�O�^X��y��2l��~���`���ug~/{|
����A'�������G��(���������cih���Q	S?/����>���1d�477c��V�_�^�����W�����������_��&L�GGG��9��)A�9��|�@�����}�v����z_�m�	x�\u��ih�w�s��5�H}�0�3�UH���h�?.��byL������������jr1e?����c��uj�5GlCNN�������c��}����PRR����g��>����]�v�����Z�%��1�H����8u�F���~�	o���D��sB���K^��\=b�[�Xo��C���3�0��\)���9S�����7=@��/!��z�$��j�����
����nX��������;_��L}]���A��J�J������%K����������\,}|�!{t����������hllDDD��y�7I��CY��5��e5T�#���[V��jl�w�j6��<$��i==��~;~5[��#������Yo2?���\�X�9��[���
�G��1S"��5� IDATN��L2�� �o�������j�*<x�n�BYY���������1%%|�����|�rl��yyyHNN�0������3���
ggg���^�Zt;S�:;;���#8p�ZZZ�j�*���;������s��o:::p��E,_����*�,Yb�������&xyyqA��a�����;w�����I�����_����>4������t�]8E�6tw�~w�����������w�A��?�4��0cG$�X�=4���e>�>0�M�1�������O��u�[[[Q]]����kbcc
I�����m._��T*899A�T����8{�,�;�Y�f������D�a�U������������(,,���3������������~�)


������h$''}|,I�@r��y��q#***����K�.a����&��/�A~�&�;� =g(h4�-�}�f�5��sm�L	:
�A������"y�d��L���g�Z\VV"##1~��}�R�p��(�J(�J��jn=������r���������1b���ppp@VV��@Rj?<==�T*���@II	���o��X���������q��������^������z���.�x?�*��e��(����6*hd��5�~����i>P�����\]�%=������eS����Q���-��������>d��$��U;=w��s�����e-���Mk����������+�n��:S���V������� @PP��N4}������c��aF��e�e�����a�s��	Ol/;<J=X����������
,��S.��S`i��d�-C������m���m`_s|b'`[A���l���b���R�?�\}<����w���|QQQ��{7����S�N!!!�-��R������� �9)))pw�������vTTT���&L�����r�J���%�Rj����^,��J�KSug�Z��N�\���~��o����	���f�^��7���
:�u���)�>aO���c_k���@����L�8��]��A�D����`����5k�j5/^���0�;g�uS�����N^oool�����P��x�����,������R���O?���:���#22NNNK�c��v#z���tDGG�^�����@�����4hd���<Y��p>[,��5�;8���a���^}\���_e�e�`=���q���+F�(_�)|d-�k�Y�=c�sFr��	$''#33�K{���j�QA;���.1������6.�3�p?222��W�lg�r|,������<466"22�K{�������C��V����������x���w;�%zk��I
�
{���'$v";�Y:�����<1VO�5Z��^�p���R������{~�\�z���Yk?���=N��bJ�J=�k�2��>C��-6�xW�NJ����$�;)Mi�Q�i��rb{��������K�j�;88���
;w��n��M���`\y��
�������ViL����D����.�(k��G}���$�K���������j���]'O���-[����?�P+h5%����]�[�a	�q�����1z[��]��Y
��co6�������1?~��O6���������j�;i�*5�.��k�z${����:u��pqKKn��!��������bt=r�������UUU���^L����8888��������������-�4�y�����O�(�Y�}�X��^�,�b��9�������}m��pHN_`i��]���>��,��9��s>Y�9 ��ZY�z9�
|
���i�C|���Pw^���~���^��W�?���?5j�BY���	�'O��9��T�
�
��L-��l�dQQ.^���S���/�@qq�������e�K�5�L�c6����{�KF���CT�3�0m����H��������<������c�o��R��;���[�u���b���M_�o��!6G�@�����M�����|�wM�eedd@8������2�ee��t����?�,h	�,����]c�D��u����K��j��;�������g0K�3�N�9����N���Q��-�����r�R;�Q��}e��7���}�i*�L;��~���������M�>k?~����o�m��>;	!���UWW���+�:u*>����?��a��urU�cO>������w����4C�l�$e��v�6���_+<��7
�����F��9�X�R�����`��S�����=��/�<��Pnh���hO;�,�#����W^y����s"z���mmm���1K�&Y�����3�*�^J�x�+o����3<O����O���D�7�5����������`K����}zh�q��)���~��,���/�"A��x,(�?4�~~�v��}��6���1b�E�njj���#��}cc#h�e~�"�I�a���c�����z����,Y���CFF������(:���8|�0�������K�a�gi1���
*�%�{�K}g�9?P�����%�s���sX�,�'�����>�z�����1��X�����i(�2�I}��n�A���Lc�^�����}��a�����o>��3���X�C���3x����}���7#((/����-3��������<��3x��7�p�B��uM�S��x����{�n��������T����0\�pAo�2�K	�av�����c�����J����_O��1y�����S*���X�^vR��c�[����cjk��I1l�%������2���c?�!�J�J������%K������-�
��x�HN�2YYY��q#�/_�)S��������|�2~�������f��V(X�z��������P��O��I����?�z��������|�����s�Z���n����������={R<��VS=Csp��X�1�
�:2�zx���kr&b����+�dgg����X�j<�[�n���s�������n{��A������x����|�r$$$���?Fss3��Y��[,/���cll,rss��>����8r�8����Z�
/����_��W8p=���� ����� 99� 773g�Djj*�������>����X�|96l��!C�H�gffb��}�������|�r����X�d����\d]J=~�x|��g�{�.�_���7o���J�R�K��c������^"C�a|���z�����"�,Z�d�����>
�sxPx��|
����}�9S�pn����i�Q�E��=��5�\����������E�[[[Q]]����kbcc
E�}��o���/���,���/������_C�Vc���X�l:::t����.((�;���c��a��Y����������x���������=<�o������4i�{�9�6��j?~g���*�����m��������J'''��?_4}���hoo���~���xzz"::���F/s2�5y�����c����(�ob�n���!���L@�Np�F�h	�B���a�f���
��A�k���k�B,�Ze�����dffb��y3f����`�����kn��	@s����J�����'#4T��������rTTT`����?�-	���0t�P���q7�N�R�S������Hn��J���+W@2�-��0���@II	�����(��wqG�a��������C���9��Awzq��iH�b��	�q�Kikk�IKKK��~�;$''c��q8s��d^�6�X�V�����

���>��s��<0�NWWW��������moo�Q�FI���j�VY��
3X�%�-�lkkCmm-���z���	(� ���%68m�����q��=��������~uuu`!!!�����y����������M4onn�d�*�
III

���#���www����hnnF]]��=�_���&�cTTv�����8::���SHHH��1cD�Y(//��	p��y�\����eNf����]�c��������y�p�����6�j�R:�=��`�+6�B�<oo���&N��k��a��A��|}}��/`�����>6o����h�������<��y�f�?^'��������m��u+BCC�V���C!66

���'\\\����������M�������1k�,��j,^�aaa4h�h:K�T����F]]����]����2';Fx��***����7l��	)))x���0g�dffb��!rV%;Y�l��K&A���B���~��N�8���ddffri<�Z�6*(b�{��O�a�����j��{L���������\p���zOI�G,=##�v�����u�7�x��e���y�&&M���ppp��r=�4w���1<`W[��k��o������^JB!}DQQt��������*���St�M�6����nfgg�k�7u������]k����q��v��j��v
c)Yn��]��H��j������7o����+���p����Fz�}��fI�������������IB�E�G�g���PQQ��S�����������?...�h�A�jgmm-���z�e���0`�������k��a����6m���������G����}^J���LL�N�����B�M5j���d>'''L�<��-2����^r�7�=�lnn�_��\�pmmm�����#)�!k��3]��?��y�������IB!�X���dZZJJJ��������K���mzv���n�n8p4Fx�x��M�%!�B,D�@r�������{��>��!�������;vhS0I!���677c������I����hll���E�t�=���5������c�=���4x{{#::��iii�������3x��G�g�JB!�XNNV�X�������}��,\����o��Y����c %++�/6*����#��_`���x����D:::�]a�A#����R&&�5)	!��J*�
*������K�,��v�?r�57�{$��_���CDDBBB�k^����K+�~�Kk,[9�Ky�L�P�����KI!�������e���111(++���s
n{��A���G�$$$�������k���7/��|Oll,�����SO���	p�����"00{���Z�F{{;^�u�7�����������<���\��-��OIIApp0�����o����;���7Cy��Cn��H6)))���/��#�p�)))�b�M����.c��_a�{Sh�����"��k�����/����;�R8��%�RB��x�% '�����������VTWWs�w�����X�^�D��������q��E���b�����Eqq1���k��j�;��-CGG�N�'�xPPP�w�y����Y���W_������(,,���3���{{{<x�|�
���1i�$<��s�mT��8~�8��=�U����m����/���*�
NNN���Duu��mY����Wj?BBBz��	�Hzxx����N��W������������x��������"p�'�H`m�W�i=�_Z������<X��kv���{�D
W���=�����N��g�kWx�-��}`(����3G{�qn��o��&�f���"���)._�vz���L��7c������al���v����7h����J�����'#44������rTTT`����?��c���0t�P���q�t7�=�T*u����������S_�r�����m�����Gj?z} 9z�h�=Z�bMv��Il��


X�|�e*u���X3���C���������h=h�����r�l0��=�������������;\���X`"v�#~>���z������{|����]���.?��^l�?]*M8�87W7�-W�?[�T����o* v�YC�6�p*{�Ua��n���;�5��o�O�vz���6����4��w�Crr2���3����,��m�L�V������LPP<<<����ku�=x��`;]]]u�okk��\����0�����#�r�-�,**���1u�T���G��Xth{���������-f�!�r�����n�����{�B6������t����e���V/g~Y
���q�=#�kR����0�Rh������������+�~��b'r~R�
�������3�-����1���\��]��@^����6'.�lSDX�c�����~�#���Z���/�*������h�{��{��@���F:�]w��?[�coo�{���7�|��������0		ALL���������mmm�ys�/&"T*�����#G"%%������G������:�={���/M����(���


ptt��S�������v���Gj?�&[ ����i�������8q��� ?�����X4�����h�34?M�4��n%�
����q��eZ'F�o��;S�n����_E~i
�os���V������t���NTbw�a{)��(M�	c�,M�n����9��N^�0g��o�o������?S�,v"�}gbb�q���ha�6?0e�k�{-�~�?}�|��x��uRi��9s��,�n���6��q`,.w>w�e]�D�����B[��/�l�&�3 �^���@��.�4�w_"-��(����}x8�^\s��B~M���f�K�
�����@L]�����������}4w<����3-�vw,/�imNX��#��ql�	�mN�g���s�B��c�Q��+�^76M��ol������L�8��]��A�D������^����q��}l�����������?y�$&&b���8��N^K�a���

�Z��C=���X888 44���pqq���?��WRx�p�����_�Y�fA�Vc���Cvv��mM�Gj?�f�0�����������5���������j��"188�������y,##2�>G1�{�>�m����N�:���&(`�/4�?�7`�� �{k��C�P��f���E��msK����tej*���/ =-
�<z��T�4�����
���$����;��U���oj�������\���U(�j���i,�<6Mq�*�Oy�(�eqq���3�=l�LJo���#.�����UcJc���x/p	`H�m,�9��������Z��4���Z�Lxlp���<�;�4C���	o�������kol@���Q�����Y�W[����Z�M��=?i�������m���������X�,�&�z���q��_@��j������o�4a=?�>�C
��_bu���m�c!V���A�X�il=��9�A\��emZil=Rib���YStt���`�N�8���ddffri<�Z��"��U��P1�0hii��
�Z�=&�kHGG���t.8�^��LmOwI��L�(k����������g�����������~��'��OOO��C��h����=�M�K)#�fFG�zW:{[n1�^��\Zn���4MA��i�r�.A�������c���8q	�,[~Btt�����\����]�Q��J%��F*�^�b����7��z���+Wt{�xi��G5i..\�Y�������E�=��p�=��5\�deM�K5sIn�~kN�����yO���/j���9�����\�\��{�;�l����7��tM�+�;�����y��
�W�|�����P������Ui�S8�Yw��j��-n����91
�.��"<�G?����
~��~���-f|�>��z[���������0P�)���������
��;����i��"��K�����L�tCt�&�S�M�`�{�$��s�)�R�Ic�=�������k��������y=��4�R�m����50?�Q.-��*��B���Kl���h�=��k���\=����V��{]H��p�^��>zR
�J�=��"8�O�=q������;b��O��!7M�s�����p���4�c��n~>kIOO�j�����			X�t�V�������s�N��6m�___�A����V��������^4�����
��)�R����C.�����������hv IDAT�����6���9���o.&�G�,�������?7��_��5o�
t�����
�MU�!��?#pP�N �ClH���Vl�;�Y���E;�0�Kk��3@<���U�K��=S	�;�-oMtW�%��jaW�����4v�H�u-����2�4~�������0\��y,�:������=���1�������9�����������kW��K��[X�T{�,��Yf�����������m�0��h����X��~s,��������[T(�&�?�����7�]c����C�0u�T��<<<�e�������������?.`&qqq������w��C�����rO,�$�c�`���?kN������Y�_Z,\�������d���h���xZ�o���h��	�G�����nNw�O���M~�n�#�'T��0g�ta�����d���6JO��dlpjl�*U�-��X�����
��m5j��jeprr����-�"��J;�I�@�?��R;�sY��z%{B�H�(��1S��c�� �sQ�����)l^�����q��M+�;Q����il��T��N��z���9�L~�N��vJ��<B�>�#��?����X�n�.]�u��~��J��0��&:����5]�������?S����'C�R��$�B�G�@r�������'�|�)S�`���X�j���LZ��g�`��\� ��F|���C���iJ�BH�w��}ntss3F�a�������������J.da�M�>Ys��"{dggg�3f���+N�:���J��;�>���}"�
�W�������ikN����y��4����HBH�����+Vp�����"u�9s;/���7o����%������,,^�������c/{�dss3N�8���7o���u�p��q��� 22���f]��+��^���`�B�>�J�J������%K�h��V��M�����c/{�dnn.>��s����}�~�����������m��{^�Y�34�$@���BH���l,[������2�e������9r���ooo�7������������X�������BS��"�G�Ahh(�w�^��j������_��q����J��
��N>���\]�-��2%�X��IIIApp0�����o������x����h�"���#>>���&{>�{$����s�NL�0A����7�]��p�����W�B��j�����
��{8������j���]���b�'������}�v\�x���X�`|}}Q\\����j�c����e��������'���w���c�0k�,|��W���F||<
������p����7�|���zL�4I����}4W�9~�8��=�U�)y��%uK���Rl��
�/_���T*�������O?����Dtt4����>�B�����8~�8>��C���}�4Ad�%���z��M!�pZ���_effb��y3fM��0�n��]�v�����������R'/k���

������1b���@s����,:aaaP(P(���J�R�.///��J�K*����Bdd$w�l�J�+W����J�������`���&�K�@r������O���
���:����]�mq�4_��w�R I!�8N������������w�����1n�8������)u���[���j���#((|���\@sOpS�����eJ^�vIikk������=wx������
f��h�=���������466b��ppp�)��o�W�B�!���n��������{���?o��6����0BBB�y��!""(++C[[�h�\=��U�THJJBPPF�������#88G�Ess3���p��Y�����s���j����(���


ptt��S�������vTTT���&L�����r�J������mF�������C^^������C�$�9 v��B!���L�8QoO���/^x�L�>�=���Y�U�V!77�����_����Dl���������!ymkoool�����������I�&!((��������9s�����+i�u�Mm��_��f�B@@BCC@3t���O���������4���1���EEE�����M�6!%%o��������L2D��d������h�W�t	�\���y0����$�"+��3��'N 99���\���V�1h� ���C�lg�0hii��
�m��y
���@[[��%��[�T���;##�v�����u���c����w��y�&M������N�go�H!����			X�t�V�������s�N��6m�__��QaPhgg�k�7ud���^4X����
��)'~���_�~�2��7�d��T��������7n��	WWW������{oa�o��+I!6�z${����:u��pnKKn��!��������b�&d�vv����ZTUUq��{H�� ??����v�����i���]���^IB!���Q��U�BNNN�<y��[d:k��;���/��YV���� &&1114s��u"!�Bl�������`gg��coo�u+ �����n�H!�#{ �p�B<x�<@{{;��?�����Y�����@�-	!�����---����


:��=�4+����1`���=?���9��}�+I!�h)))M��y����999X�b���R�����?���,((���]=k���())�{S577�O�.]����'���^������#55�}�������1�P���o�+I!�kll��%K���m,�J�J��wO���z����#��_�~~~5jf���-[�����������?������.��+W����c��9�����������l��;�M���B����:���a��������c����2��;���x���1n�8������Roy���X�l������IIIApp0�����o���999x��gwww,Z����}���!�������z
�-���;���Q__o��X#���o3S�La0QQQ���C�)S�0�n�b�a���{\GGG��~�:�0����`����<j��:t(STT�0�|��7���]o�iii=ns�4�l���m��G�~j���-�B�F�s�>����x�$����Lk��a�9W�#�V~��a��������o��0��o��=�-W�������O2��]���>���x�$��=����9���-m�s���7���QSw�H��j^�Y]ug������7�d�y��a��������\�t����b�a���2^^^��?��|��w�����*==�y������r�
W�����3nnn�?�����2��Og����|������������ ���?�[��6RuH����3��������5k�s�N����^��Gr��MX�`ZZZ��_���k������'�����7��q����'�777��y������q�����;�-��}�v��7(1Q�3w.�c�i�
�T�n�+k�!�����f\�����Ztt^N���}.��Ms��65��pOs�����j���2��Y�k�������U�n���Z��X/^w����k���>���l������z�~�w�b���P|��������<���C���.\@XX
~�a����rL��������c��QP�T�r�
�}�CCCaoo???���,Ol�:��#F ""�W��d�6G�a�������<x0`���X�f
���'N�2�|��}�75wttD{{�V��������<.�j���add��\�{����4T"QDL��\�R�[n��o��f�d�����If�yK����*f���K-�	��M�m���qVf�a�y=�y��s�|�9����=�|��1��O��?�h���;w���ezz�]�O~���kV^{
�_��^�p~�T+��y��2���i���|��/������i���]�7���9M,��K�����}���yk�k�����#$������T��I�=�T"�M+�uK�u��y���K�n��nh�����r�����Dvv6v���u��!11�~�{�[EE��#�jjj�������2x��D"��,�m���tkhjsuX�[��lM9m��i�n5
{�m����T*JJJ��J���d"##�.�(�J@\�zU!Duu� .^�X'onn���u�v��I���POm��%KV��U�S���&"jV�jj�%��e���{�B���R@���K�d2!�{��={��o�����HII1[����'Nh�3����"44T���o�!C����w���w�!C�h���3G|���2���:��k������R�#G��7o�j�����%	��������!44���v����			X�b*++�j�*���!!!P(�a�7�x
�			��c�L�����,9Y>.Y�K{�5�����n��@�����z����9�MDDN�w���;w.����A�!))	���������QQQ��>�a��5xT2<<\[^UU��<�7o���3::��3��ansu�K�S�&L@XX��m���8���I�3,�����L&]�v�<�����B*���������-�r� BCC�����B$%%�9s�!�8p��

R�T0@�[n���\�D��C�ntR�P53���7n���Z��J��������o[U��_~)F�Q'��<s�Je���w�\�����b���B���o��4�D�����������������z�
�L&�g5���;���p��-H���;���q��!�<���|���9������d��$�� g����P��U�D�?����W��������Lpp�������������;sss��[o�)����N���������<�����{��e����6��e��:,����@��q$7!��6qb'O��L&CHH�M����c��1vn���hX0��8���L�3�$"jTMr��:***���['���J�R{����@�N�4�d���),,D^^���w�e5��H��&��`LwPu�J�DD���$��Y�Ts�����7�,��w��u�Cy�Cu��s����0�t��d�`r�~���m
(����������������Y���.�����"""�F�@��0��0*r%J""jAn�����
��WWWk�����Y�NM���O$���df�:�4~����A

*P�1�L��b��Mf���o�O�^g�9>�ZC���ddd`��qV�mj�j[O��/9��G�S���LkKK��U�DDVi��'w��M0YYYu>{��'���g��<g�s�N,_�����n�1^��������s)����G*��X����G��DDD������c��[�nGZZ������#&&J�������cGDEE������w�����e��,IMM��A���o_���;(//��}�0y�dL�4	�����?���o[,��6�����������g�!**
�����~�Je��w�����Li�*����b����J�3�A���[1�$"jz�W�_����N����=wN��c�:��Z�����2��S�-\�K{�uZB�.��u�����v����9�N����m�^���+ue������7�����'����'N����F��]�������c���8u�6n����\|ZYY�+W�,/_�\[�9YYYX�x1����!33_|���_�J��[���������q��u8p�b�mc�M;�����999x�����_b���X�~=�i���]�HML����e��kF+�S����������H��������~""����������������2���������������h]�������&��V����>u�K{�]��/k��������3gb���HNN�������C���Fpp0���1���;���@\\:u������c� ��!��@�(h�BQoy�����?M�fq����v�B@@RRR��������7�O��@���*����L������RP������4`��l�|K"��
���]�|�{���i����.�m[��D�K���Q�r�.�Gu�v��S�������W�8p�@dggc��]X�n����j?���0x�t�&�����*�g]K$�j��������T���R�m��"##���h���U����h�P�K?�4�X�RPij�Q?pL_�c��Y��%���}V����C�����
0�������|S7��w�����~�5J��n}�O<�]LKKCPPf���������%%%(�3�9h� l�����(**�O?���S��-��D�-���#Gb���())�������W_}�A���\J���������7�Ddd$����v�?���dK�	*5LM���C�>X��C�^z�)��TYT������u|w�u��;����$�;�R�zs����eM�4��
Q����S�cT]��|?�� ���?�0����R������;S���u��c����0���a��a
�����������N�����7C��J���q���6x�$�����c����kH�z_|�EDEEA�R�s���4iR�v�x�=.w+s�U��4�����;������~�M}A�=�@��r��FTXX��� ���POa�T*m�W^^__�z������v�Z����������Y
�������EUU|||��$�z\�����������XjF1��������T����V3�G��~c*_C��~���c.�5f�h�Gw��p�a.}�p���\���[u����p��)L�6
��8����{�9�����g
i�-e99���G�{N
�����{��9�RsN�&��ej��8r�@���BG2�o`*(m�z���A���-�����X~����i��3������u�KKK�T*er���v��S'�i.��6�R��c ���M0�T�m�����f]��V�q0������B�@�Tz}miI��=����l�a���n��A�$���������:�9��={b���4�s��Ul�����Gdd$f���.]�8���p�w�W����[R���F5M��x������3C�����m
�&�07������~>�5�
���&��~��a�rDr���v�����n�:(
l��I��i������-Bjj*��9�����b��u����4N�'���85�����jsb����k� �U����b���?�DN8�-��D"��s����R����`T�o��X�t)�����#..7o��X6�(� G�����QK����Q,����4�&@�}�a��7�>"��cF��y�&<==�^�\]]���r,7���mm�#���.))�����C&����� �LJJ������'O����Cbb�C�K����G�9��@�\koW_9�n_�����`�x�5vnm����1g	6�
�����={u�.\���H��=��v�����5k�}�v�es�5�zM����������Yo��r7��t�duu5��qzyy��3�B����Z�j����)k���0�MOOo�VS������k���4\�1\W�����]Ys)�9K_4��v�+��-w5�����|D��y�&������o���x���)��m�g��r���t�d�����q2�J�/^�L&�������o��C��W�^�={6�������	=z�A��� �`��0`��D[G6cJ���[�����9q`���C������Z:�X�3'����+**����q��xxx���^���kq��y�����~��o���>��;w�����������������]�t������L�������O>Ayy9�q��?����k!���?�����[�lA����m��Y�Ln����[��g�}��>�x���0{��zofnj_<�5k��������q$&&b���V��9NHzxx !!+V���%K�f����!!!P(���BDD�������^�z�M���%IDAT���J�h�����Ot��������Z��d��vC�YK��X)5@�uXgP�9P�M��e i��\��_!��{U9@���im��@(��i�4�1@�t�r�@u��@����+����@��;uoJ��S����(;\[mTw.P��N�s�0��G�3��%������7�����'����j�*�����2e
233q��a�_��N�Bqq1z���)S������J\�r�`y����4i�� )++�/���G������x���@.�c�����������!C����e��qmP�T&�mH���p������_��uk:��������/aaa��mN�8���0�3k����,q�@�{�=�=��-Chh(�mS�6m�����#%%���.������/�U�VHII�����[ND�Md[
���J ��T���R�~S���j+t����b]~M��}�2����|�]�"����y=�m@���w�W�JS������L�
�bTT���1s�L�=������?��:t���Fpp0�6������C�N�����;�\�\���(�g�+
��5�m��]�����������{wwwdddX$��KXX�r9���������g1b�����$�w����,��uR��qy���8t�u���Z�|N""�[��+m	<�>�����>�#@�&���k��u�5i��uez���H�.�4�����
�����M�nM�n����G�8p�@dggc��]X�n����j?�������v�����w�����`�X"� ((��m[m�~[���mM�U�Th���v:?22���7����}�<�[SG�6w��a�$5��H@}���Y��D9';?�IMS���=�~���
t�j���Y7
:����~�����_uG�_u�Y_��imHKKCPPf���������%%%(++4�7oFyy9�����O?a���u��@"�h�3g���X�r%JJJ����={���W_mP=�!>>o��&"##���T�k=L1�/J�999P(���~��g��1������Ic��Z"""j�z����~~~~P�THJJBt�:H����;���(��������
k��dxx��������u�DDD`��y2dT*�����h<x��}3�����
��/����(�T*t���&M�X��}��w/�r9&L����":qqq�{rZ�K������Wm��x�����B���
�z
[�Ri�kOS�����v�Z���������������V[[���*�7b7�x_v�����qZ�?&8�
�����e���O������B��'77o��V�2���p��)L�6��g������3�<��s�������6��eO�DDZ[��}1����!8"���.���Z<f8FEErss�����B�T"**��T����S�N�����6�RVC�Zwaa!����} G$����y����g��M�]c��Tukn�do��	JDDDD���$���$���$���$���$���$���$���$���$���$���$����
�Eyy9^�u9r={����Kh�g���B����4������\�S��-��k��z�j�[�3f�����
�,\�P�|��$%%������JDDD�b9] )�����q��9���c��%@qq���������_y�|������qT�����Z�;G�����[7���?d2


L���m`���M�@""""�t#�����D{yyA�T��������7�0����;��G���n���lNHj.��q�d2�J%.^��LV'oAA���k����G����c��1�o4�8x r��m$$$`�������U���O���@�P�������N�Bll,<==�b"""����Ix������_���+V���
�6m������N�<�.]�8��DDDD-��Mm@�������[�nA*�j����q��!�zbb�#�GDDD��rDRC?���O��5�A�!"""r-N9"iN�~��""""���#�DDDD�8$�����&$�����&$�����&$�����&$�����&$�����&$�����&$�����&$�����&$�����&$�����&$�����&$�����&$�����&$�����&NH������_�����`�����'� >>����B�h�V�lNH.Z�999X�z5<==1c��:y�l��U�V����Bhh(�~�i�������rBG7�!��H$8w����QZZ���!00P�/&&��O��O>	!jjj���a����t�3��w���Z3���t#�%%%�n�����!��PPP`�������c:v���#G����M�V"""����]3T]]
�Ht1����J�A�[�n!,,iii���o0k�,(
���i�����������z""j)��'D�����U*<==q��U�d2(�Jxyy����		�����#6l����Xm���|����-��:�5���A����~Pc?9������b�
TVVb��U���BBB�P(p��Y�#�<�-[�@�Tb�������H""""j������{�G���e��m��6m�����#%%����0a�����G�\����&"""jY�2����;���p��-H�Rmztt4:h��<���o�u���j*Q��tS����H��Y��DFDD��]-�B����~Pc?����DNx�
5�w�
5$�����&$�����&$������_�����`�;�IM�����/G||<�,Y���\��'�-BZZ�v}��������i���o�9�eM�����>���'c��}�tW��R�O>�?�0,X���k?s�~P�Tx�����+��gff��G��1c���_��������}�����'O6�[�R���"A��g��&M����x���EBB����d,X &N�(�;&���+&M�$�p�>��a� ^}�U!�[�nr�\�8qB����R�T���;���G�P�T*v��-���;!�JEaa�����u����������~+�R����p�~2d�0`���������	�T*�����?�,�R�8r������\?�~����w��J�����-��,Ht�@���V���BQRR"���"��il��U\�tI!��S��T*u�>������b��y�@r��q"55U�g��"==�QMltK�.O<��v���Z�z���K/���^�����w�~��c����0�V�^m�c���b��Ef�[S����-���;���q�����[t?Y���S�%%%�n�����!��PPP��f5��'��{����b���.�'B<���X�l�t��M������{w�zDD������q��y����o���������^?��9{������/L�<�G�����w��S������\.��������f�[S���{w�5
�P(�g������~ ������j�D��
///(�JG5��)�J,X������+\�O��[�6m�`��i�eee���=����E�Cqq1�J%8�m����g�A~~�����+WPVV���eee.��*++����]���@UU��������������~���p��"�|D�=n���L�R��/B&�9�eM���
&L@PP������___��'����={6�N��^x��������Ot��W�^���t�F����6�:���������?�
������a���x���0g�@��}��?�\?�k��=�\��]�|�2:t�`6�%��g�M��o���`��Z:�����@BBV�X���J�Z�
}��AHH����$/^��� l��^^^\�O<<<����'�|�F�����7���5j��]���B���O��k���&7�#F��/�Dqq1�^���G�"::����G�����������{�����A��#�y�f�={�����q#F�e6���x�"�����m	�����gi6���B.�"44T?~��Mj555� �R��UPP��}"�o����b���21v�Xm?m�����kdJ�R<��3B*���]��w�}W�z����+�\.r�\{��+����;��
,B�d�m���>+T*��tgf����������0�%�Q=��m=�n��T*ut3���Zyy9���������4	��^���j�PQQ�V�Z���� ���A_uu5�����*�����$1�$""""[$��9�DDDDd�DDDDd�DDDDd�DDDDd�DDDDd�DDDDd�DDDDd�DDDDd�DDDDd�DDDDd�DDDDd�DDDDd�D���O>	HNN�����������;�	DDd$�����x���q��l��;v���#G�l��x�������qqq�����B�����8���p��%���#..��GZZ�v�A�!''G���w��5&����CLL&M���;b���B�����8p �����>�III��?�����T*��?���?<h�N&"�F����2\�|�����������k?����s�=�s�����2djjjPPP��s��e�T*�T*,Z�G����/�v��'N����w���-[����5k�`��)8{�,n����]��I���GA��������������������o_L�:�d�!!!��mv�����R���P(x������������_����q�����QQQM��DDtwH9P��]�����S�����F�������<++������:t��Lf��c��>��s@��mq��)<����B���~W�^���;�S��}�Q��
8R�<�����={L����;�y����"??��]Cii���\��~�
s�������p���w"9I"JNNFJJ
N�<���\���B*�b����R	///�e����]����t���l�2����:`��P��M�������/��_|Q�<M^K�����FII���������f�>|����:t@NN���,Z�iii��q���GDD�s$�(99������o����^D@��q��QTUUA�P���k

��7�S�����������x���0q�D���!  �N�S�N������U+t���l�,�w��-dee���'N��}��g2����1`�L�0������j��uB?~G����s��W_a��]��^""jd�$r�K�.�K�.��7o���������S�LA��=������P���a���8p Z�n��={���={���o����xyy�G��1c�\�R�Lx��',�-<<�dy�o��L&��Y�P\\�������Ciii�����x��W�\�I�&!))	���<x0�o����z
��/Gyy9^{�5�u.5:7!�pt#�����
���`��A������wo�������N���Z(�Jx{{�,���k���?��9S'p5�����<�1YYY�v�W�~>�JwwwTWWk�#  nnn�u5I��&r����� $�� ����B����l�2�����3n�����<<<���f�/00�A$���$�)++������m�^�T<==mnCmm-�����M�� "�!��H9s�����RC"�0�$""�j�����l�@�����l�@�����l�@�����l�@�����l�@�����l�@�����l�@�����l�@�����l�@�����l�@�����l�@�����l�@�����l�@�����l� ��� """"�S���-��<���IEND�B`�
#2Vladlen Popolitov
v.popolitov@postgrespro.ru
In reply to: Vladlen Popolitov (#1)
1 attachment(s)
Re: PoC. The saving of the compiled jit-code in the plan cache

Dear colleagues,

It is updated patch (compiled with current master, the same
description, as
below, no other features yet)

If you need to patch the same master version, you can:
git checkout 83ea6c54025bea67bcd4949a6d58d3fc11c3e21b
patch -p1 <v5-0001-jit-saved-for-cached-plans.patch

Vladlen Popolitov писал(а) 2025-02-13 16:01:
Dear colleagues,

I implemented the patch to store in the plan cache an already compiled
jit
code. If a query is executed many times, the query time can be
decreased by
20-30% for long queries with big share of expressions in the code.

This patch can be applied to the current master and passes tests, but
it is
only the Proof of the Concept, and I need to get opinions and advice
for nexts
steps. It is not ready for commitfest, does not cover all scenarios
(craches
in some sutuation that need special solution), and source code is not
clean.

The code source has removed old code marked by // comments to easier
compare,
what was changed, especially in llvmjit_expr.c and llvmjit_deform.c

Implementation details.

1. Changes in jit-code generation.

a) the load of the absolute address (as const) changed to the load of
this
address from a struct member:

old version:
v_resvaluep = l_ptr_const(op->resvalue, l_ptr(TypeSizeT));
new version
v_resvaluep = l_load_struct_gep( b, g->StructExprEvalStep, v_op,
FIELDNO_EXPREVALSTEP_RESVALUE, "v_resvaluep");

b) the load of the absolute address or the value from union changed to
the load of the union value using the offset of the union member

old version
fcinfo - the union member value
v_fcinfo = l_ptr_const(fcinfo, l_ptr(g->StructFunctionCallInfoData));
new version
v_fcinfo = l_load_member_value_by_offset(b,lc, v_op,
l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep,
d.func.fcinfo_data ));

c) every cached plan has own LLVM-context and 1 module in it. As
result,
some functions require context parameter to correctly address it
instead
of the global llvm_context variable.

d) llvm_types moved from global variables to the struct LLVMJitTypes.
Not cached queries use old setup, but all types definitions are stored
in global struct LLVMJitTypes llvm_jit_types_struct, instead of many
global variables. Chached queries allocate struct LLVMJitTypes during
query
executon, and pfree it when cached plan is deallocated. llvm_types
module is
read for every cached statement (not 1 time during global context
creation).

e) llvm_function_reference still uses l_ptr_const with the absolute
address
of the function, it needs to be checked, as the function can change
address.

f) new GUC variabe jit_cached is added, off by default.

2. Changes in cached plan.
To store cached context I use struct PlannedStmt (in ExprState
state->parent->state->es_plannedstmt).
New member struct CachedJitContext *jit_context added to store
information
about jit context. In new plans this field in NULL. If plan is stored
to cache,
it filled by CACHED_JITCONTEXT_EMPTY and replaced by actual jit context
pointer
in llvmjit_expr.c .
When cached plan is deallocated, this member used to free jit resources
and
memory.

3. Current problems.
When module is compiled, it needs to connect ExprState and function
addresses.
In old implementation funcname is stored in ExprState.
In cached implementation the fuction will be called second and more
times,
and calling code does not have information about function name for
ExprState.
a) The current cached implementation uses the number of the call to
connect
f.e. 1st expresion and 1st function. It does not work for queries, that
generates an expression after module compilation (f.e. HashJoin) and
tries
to compile it.
b) Also query with aggregate functions generates an expresion every
time, when
executed. It work with current approach, but these expressions should
be
considered, as they have different expression address every time.

One of the solution for a) and b) - generate jit-code for Expr pointers
only
in cached plan. Every new created expression either should be ignored
by
the compiler and executed by the standard interpreter, or compiled in
the
standard (not cached) jit (it will run compilation every query run and
eliminate all gain from jit-cache).

c) new jit-code generation (use the stuct member instead of the direct
absolute address) slightly decreases the jit-code performance. It is
possible
to compile old version for not cached queries, and new code for cached
queries.
In this case two big 3000 lines funtions llvm_compile_expr() need to be
maintained in similar way, when new expresiions or features are added.

Attached files have
1) the patch (branched from 83ea6c54025bea67bcd4949a6d58d3fc11c3e21b
master),
2 and 3) benchmark files jitinit.sql to create jitbench database and
bash
script jitbench.sh (change to own user and password if you need) to run
banchmark.
4) chart for this benchmark and the query in the benchmark (comparison
with jit=off as 1 unit). It is easy to find query, where jit is higher
or
lower than jit-off. Here I demonstate the difference of standard and
new
jit-code (the decrease of the performance with compilation without
optimization), and high gain of cached version with optimization and
high lost of not cached version with optimization due to the running
of the optimization for every the query.

--
Best regards,

Vladlen Popolitov.

Attachments:

v5-0001-jit-saved-for-cached-plans.patchtext/x-diff; name=v5-0001-jit-saved-for-cached-plans.patchDownload
From c0565ec4e90ab9c94d35f4d43aa9f528af7dfeee Mon Sep 17 00:00:00 2001
From: Vladlen Popolitov <v.popolitov@postgrespro.ru>
Date: Thu, 13 Feb 2025 21:43:11 +0700
Subject: [PATCH v5] jit saved for cached plans

---
 src/backend/jit/jit.c                 |    1 +
 src/backend/jit/llvm/llvmjit.c        |  202 +++--
 src/backend/jit/llvm/llvmjit_deform.c |   88 +-
 src/backend/jit/llvm/llvmjit_expr.c   | 1061 +++++++++++++++----------
 src/backend/jit/llvm/llvmjit_types.c  |    1 +
 src/backend/nodes/copyfuncs.c         |    3 +
 src/backend/nodes/equalfuncs.c        |    6 +
 src/backend/nodes/gen_node_support.pl |   13 +
 src/backend/nodes/outfuncs.c          |    4 +
 src/backend/nodes/readfuncs.c         |    6 +
 src/backend/utils/cache/plancache.c   |   19 +
 src/backend/utils/misc/guc_tables.c   |   12 +
 src/include/executor/execExpr.h       |    2 +
 src/include/jit/jit.h                 |    1 +
 src/include/jit/llvmjit.h             |   91 ++-
 src/include/jit/llvmjit_emit.h        |   74 +-
 src/include/nodes/execnodes.h         |    3 +
 src/include/nodes/plannodes.h         |    4 +-
 18 files changed, 1035 insertions(+), 556 deletions(-)

diff --git a/src/backend/jit/jit.c b/src/backend/jit/jit.c
index d2ccef9de85..3927f7c5f73 100644
--- a/src/backend/jit/jit.c
+++ b/src/backend/jit/jit.c
@@ -30,6 +30,7 @@
 
 /* GUCs */
 bool		jit_enabled = true;
+bool		jit_cached = false;
 char	   *jit_provider = NULL;
 bool		jit_debugging_support = false;
 bool		jit_dump_bitcode = false;
diff --git a/src/backend/jit/llvm/llvmjit.c b/src/backend/jit/llvm/llvmjit.c
index 614926720fb..e34fa2b11e7 100644
--- a/src/backend/jit/llvm/llvmjit.c
+++ b/src/backend/jit/llvm/llvmjit.c
@@ -53,6 +53,7 @@ typedef struct LLVMJitHandle
 
 
 /* types & functions commonly needed for JITing */
+/*
 LLVMTypeRef TypeSizeT;
 LLVMTypeRef TypeParamBool;
 LLVMTypeRef TypeStorageBool;
@@ -74,10 +75,14 @@ LLVMTypeRef StructAggState;
 LLVMTypeRef StructAggStatePerGroupData;
 LLVMTypeRef StructAggStatePerTransData;
 LLVMTypeRef StructPlanState;
+LLVMTypeRef StructWindowFuncExprState;
 
 LLVMValueRef AttributeTemplate;
 LLVMValueRef ExecEvalSubroutineTemplate;
 LLVMValueRef ExecEvalBoolSubroutineTemplate;
+*/
+char * llvm_expand_funcname_general(struct LLVMJitContext *context, const char *basename, int *counter);
+LLVMJitTypes llvm_jit_types_struct;
 
 static LLVMModuleRef llvm_types_module = NULL;
 
@@ -99,7 +104,8 @@ static LLVMOrcThreadSafeContextRef llvm_ts_context;
 static LLVMOrcLLJITRef llvm_opt0_orc;
 static LLVMOrcLLJITRef llvm_opt3_orc;
 
-
+static void llvm_create_types_context(LLVMJitTypes *jit_types_struct,
+			LLVMModuleRef *llvm_types_module, LLVMContextRef llvm_context);
 static void llvm_release_context(JitContext *context);
 static void llvm_session_initialize(void);
 static void llvm_shutdown(int code, Datum arg);
@@ -232,6 +238,8 @@ llvm_create_context(int jitFlags)
 	context = MemoryContextAllocZero(TopMemoryContext,
 									 sizeof(LLVMJitContext));
 	context->base.flags = jitFlags;
+	context->jit_types = &llvm_jit_types_struct;
+	context->llvm_types_module = llvm_types_module;
 
 	/* ensure cleanup */
 	context->resowner = CurrentResourceOwner;
@@ -242,6 +250,51 @@ llvm_create_context(int jitFlags)
 	return context;
 }
 
+/*
+ * Create a cached context for JITing work.
+ *
+ * The context, including subsidiary resources, will be cleaned up either when
+ * the context is explicitly released.
+ */
+LLVMJitContext *
+llvm_create_cached_context(int jitFlags)
+{
+	LLVMJitContext *context;
+
+	llvm_assert_in_fatal_section();
+
+	llvm_session_initialize();
+
+	context = MemoryContextAllocZero(TopMemoryContext,
+									 sizeof(LLVMJitContext));
+	context->base.flags = jitFlags;
+	context->llvm_context = LLVMContextCreate();
+	context->jit_types = MemoryContextAllocZero(TopMemoryContext,
+									 sizeof(LLVMJitTypes));
+
+
+
+	/// llvm_recreate_llvm_context();
+	/*
+	 * Synchronize types early, as that also includes inferring the target
+	 * triple.
+	 */
+	llvm_create_types_context(context->jit_types, &context->llvm_types_module, context->llvm_context);
+
+	///ResourceOwnerEnlarge(CurrentResourceOwner);
+
+
+
+	/* ensure cleanup */
+	///context->resowner = CurrentResourceOwner;
+	///ResourceOwnerRememberJIT(CurrentResourceOwner, context);
+
+	llvm_jit_context_in_use_count++;
+
+	return context;
+}
+
+
 /*
  * Release resources required by one llvm context.
  */
@@ -272,6 +325,11 @@ llvm_release_context(JitContext *context)
 		LLVMDisposeModule(llvm_jit_context->module);
 		llvm_jit_context->module = NULL;
 	}
+	if (llvm_jit_context->llvm_context && llvm_jit_context->llvm_types_module)
+	{
+		LLVMDisposeModule(llvm_jit_context->llvm_types_module);
+		llvm_jit_context->llvm_types_module = NULL;
+	}
 
 	foreach(lc, llvm_jit_context->handles)
 	{
@@ -304,6 +362,12 @@ llvm_release_context(JitContext *context)
 
 	if (llvm_jit_context->resowner)
 		ResourceOwnerForgetJIT(llvm_jit_context->resowner, llvm_jit_context);
+
+	if (llvm_jit_context->llvm_context)
+	{
+		LLVMContextDispose(llvm_context);
+		llvm_jit_context->llvm_context = NULL;
+	}
 }
 
 /*
@@ -321,7 +385,8 @@ llvm_mutable_module(LLVMJitContext *context)
 	{
 		context->compiled = false;
 		context->module_generation = llvm_generation++;
-		context->module = LLVMModuleCreateWithNameInContext("pg", llvm_context);
+		context->module = LLVMModuleCreateWithNameInContext("pg",
+			context->llvm_context? context->llvm_context : llvm_context);
 		LLVMSetTarget(context->module, llvm_triple);
 		LLVMSetDataLayout(context->module, llvm_layout);
 	}
@@ -335,9 +400,9 @@ llvm_mutable_module(LLVMJitContext *context)
  * a Module.
  */
 char *
-llvm_expand_funcname(struct LLVMJitContext *context, const char *basename)
+llvm_expand_funcname_general(struct LLVMJitContext *context, const char *basename, int *counter)
 {
-	Assert(context->module != NULL);
+	///Assert(context->module != NULL);
 
 	context->base.instr.created_functions++;
 
@@ -348,9 +413,18 @@ llvm_expand_funcname(struct LLVMJitContext *context, const char *basename)
 	return psprintf("%s_%zu_%d",
 					basename,
 					context->module_generation,
-					context->counter++);
+					(*counter)++);
+}
+char *
+llvm_expand_funcname_expr(struct LLVMJitContext *context, const char *basename)
+{
+	return llvm_expand_funcname_general(context, basename, &context->counter_expr);
+}
+char *
+llvm_expand_funcname_deform(struct LLVMJitContext *context, const char *basename)
+{
+	return llvm_expand_funcname_general(context, basename, &context->counter_deform);
 }
-
 /*
  * Return pointer to function funcname, which has to exist. If there's pending
  * code to be optimized and emitted, do so first.
@@ -416,7 +490,7 @@ llvm_get_function(LLVMJitContext *context, const char *funcname)
  * in sync between plain C and JIT related code.
  */
 LLVMTypeRef
-llvm_pg_var_type(const char *varname)
+llvm_pg_var_type(LLVMModuleRef llvm_types_module, const char *varname)
 {
 	LLVMValueRef v_srcvar;
 	LLVMTypeRef typ;
@@ -436,12 +510,12 @@ llvm_pg_var_type(const char *varname)
  * keep function types in sync between C and JITed code.
  */
 LLVMTypeRef
-llvm_pg_var_func_type(const char *varname)
+llvm_pg_var_func_type(LLVMJitContext *context, const char *varname)
 {
 	LLVMValueRef v_srcvar;
 	LLVMTypeRef typ;
 
-	v_srcvar = LLVMGetNamedFunction(llvm_types_module, varname);
+	v_srcvar = LLVMGetNamedFunction(context->llvm_types_module, varname);
 	if (!v_srcvar)
 		elog(ERROR, "function %s not in llvmjit_types.c", varname);
 
@@ -458,22 +532,22 @@ llvm_pg_var_func_type(const char *varname)
  * the module that's currently being worked on.
  */
 LLVMValueRef
-llvm_pg_func(LLVMModuleRef mod, const char *funcname)
+llvm_pg_func(LLVMJitContext *context /*LLVMModuleRef mod*/, const char *funcname)
 {
 	LLVMValueRef v_srcfn;
 	LLVMValueRef v_fn;
 
 	/* don't repeatedly add function */
-	v_fn = LLVMGetNamedFunction(mod, funcname);
+	v_fn = LLVMGetNamedFunction(context->module, funcname);
 	if (v_fn)
 		return v_fn;
 
-	v_srcfn = LLVMGetNamedFunction(llvm_types_module, funcname);
+	v_srcfn = LLVMGetNamedFunction(context->llvm_types_module ? context->llvm_types_module : llvm_types_module, funcname);
 
 	if (!v_srcfn)
 		elog(ERROR, "function %s not in llvmjit_types.c", funcname);
 
-	v_fn = LLVMAddFunction(mod,
+	v_fn = LLVMAddFunction(context->module,
 						   funcname,
 						   LLVMGetFunctionType(v_srcfn));
 	llvm_copy_attributes(v_srcfn, v_fn);
@@ -537,7 +611,8 @@ LLVMValueRef
 llvm_function_reference(LLVMJitContext *context,
 						LLVMBuilderRef builder,
 						LLVMModuleRef mod,
-						FunctionCallInfo fcinfo)
+						FunctionCallInfo fcinfo,
+						LLVMValueRef v_fcinfo)
 {
 	char	   *modname;
 	char	   *basename;
@@ -570,17 +645,22 @@ llvm_function_reference(LLVMJitContext *context,
 							fcinfo->flinfo->fn_oid);
 		v_fn = LLVMGetNamedGlobal(mod, funcname);
 		if (v_fn != 0)
-			return l_load(builder, TypePGFunction, v_fn, "");
-
-		v_fn_addr = l_ptr_const(fcinfo->flinfo->fn_addr, TypePGFunction);
-
-		v_fn = LLVMAddGlobal(mod, TypePGFunction, funcname);
+			return l_load(builder, context->jit_types->TypePGFunction, v_fn, "");
+
+		v_fn_addr = l_ptr_const(fcinfo->flinfo->fn_addr, context->jit_types->TypePGFunction, context->jit_types->TypeSizeT);
+		///tmp = l_ptr_const_step(d.hashdatum.iresult, l_ptr(g->StructNullableDatum));
+		///tmp = l_struct_gep(b, g->StructNullableDatum, tmp, FIELDNO_NULLABLE_DATUM_DATUM, "");
+		/// params[1] =  ///l_ptr_const(fcinfo->args, l_ptr(LLVMInt8TypeInContext(lc)));
+		///			l_load_member_value_by_offset(b, lc , v_fcinfo, l_ptr(LLVMInt8TypeInContext(lc)), offsetof(FunctionCallInfoBaseData, args));
+		////v_fn_addr = l_load_member_value_by_offset(builder, lc , v_fcinfo, l_ptr(LLVMInt8TypeInContext(lc)), offsetof(FunctionCallInfoBaseData, flinfo));
+		////v_fn_addr = l_load_member_value_by_offset(builder, lc , v_fn_addr, context->jit_types->TypePGFunction, offsetof(FmgrInfo, fn_addr));
+		v_fn = LLVMAddGlobal(mod, context->jit_types->TypePGFunction, funcname);
 		LLVMSetInitializer(v_fn, v_fn_addr);
 		LLVMSetGlobalConstant(v_fn, true);
 		LLVMSetLinkage(v_fn, LLVMPrivateLinkage);
 		LLVMSetUnnamedAddr(v_fn, true);
 
-		return l_load(builder, TypePGFunction, v_fn, "");
+		return l_load(builder, context->jit_types->TypePGFunction, v_fn, "");
 	}
 
 	/* check if function already has been added */
@@ -588,7 +668,7 @@ llvm_function_reference(LLVMJitContext *context,
 	if (v_fn != 0)
 		return v_fn;
 
-	v_fn = LLVMAddFunction(mod, funcname, LLVMGetFunctionType(AttributeTemplate));
+	v_fn = LLVMAddFunction(mod, funcname, LLVMGetFunctionType(context->jit_types->AttributeTemplate));
 
 	return v_fn;
 }
@@ -779,6 +859,9 @@ llvm_compile_module(LLVMJitContext *context)
 		 */
 
 		context->module = NULL; /* will be owned by LLJIT */
+		context->counter_expr = 0;
+		context->counter_deform = 0;
+
 		error = LLVMOrcLLJITAddLLVMIRModuleWithRT(compile_orc,
 												  handle->resource_tracker,
 												  ts_module);
@@ -795,6 +878,8 @@ llvm_compile_module(LLVMJitContext *context)
 						  endtime, starttime);
 
 	context->module = NULL;
+	context->counter_expr = 0;
+	context->counter_deform = 0;
 	context->compiled = true;
 
 	/* remember emitted code for cleanup and lookups */
@@ -980,12 +1065,10 @@ llvm_set_target(void)
 
 /*
  * Load required information, types, function signatures from llvmjit_types.c
- * and make them available in global variables.
- *
- * Those global variables are then used while emitting code.
+ * and save it in LLVMJitTypes struct.
  */
 static void
-llvm_create_types(void)
+llvm_create_types_context(LLVMJitTypes *jit_types_struct, LLVMModuleRef *llvm_types_module, LLVMContextRef llvm_context)
 {
 	char		path[MAXPGPATH];
 	LLVMMemoryBufferRef buf;
@@ -1001,39 +1084,56 @@ llvm_create_types(void)
 	}
 
 	/* eagerly load contents, going to need it all */
-	if (LLVMParseBitcodeInContext2(llvm_context, buf, &llvm_types_module))
+	if (LLVMParseBitcodeInContext2(llvm_context, buf, llvm_types_module))
 	{
 		elog(ERROR, "LLVMParseBitcodeInContext2 of %s failed", path);
 	}
 	LLVMDisposeMemoryBuffer(buf);
 
-	TypeSizeT = llvm_pg_var_type("TypeSizeT");
-	TypeParamBool = load_return_type(llvm_types_module, "FunctionReturningBool");
-	TypeStorageBool = llvm_pg_var_type("TypeStorageBool");
-	TypePGFunction = llvm_pg_var_type("TypePGFunction");
-	StructNullableDatum = llvm_pg_var_type("StructNullableDatum");
-	StructExprContext = llvm_pg_var_type("StructExprContext");
-	StructExprEvalStep = llvm_pg_var_type("StructExprEvalStep");
-	StructExprState = llvm_pg_var_type("StructExprState");
-	StructFunctionCallInfoData = llvm_pg_var_type("StructFunctionCallInfoData");
-	StructMemoryContextData = llvm_pg_var_type("StructMemoryContextData");
-	StructTupleTableSlot = llvm_pg_var_type("StructTupleTableSlot");
-	StructHeapTupleTableSlot = llvm_pg_var_type("StructHeapTupleTableSlot");
-	StructMinimalTupleTableSlot = llvm_pg_var_type("StructMinimalTupleTableSlot");
-	StructHeapTupleData = llvm_pg_var_type("StructHeapTupleData");
-	StructHeapTupleHeaderData = llvm_pg_var_type("StructHeapTupleHeaderData");
-	StructTupleDescData = llvm_pg_var_type("StructTupleDescData");
-	StructAggState = llvm_pg_var_type("StructAggState");
-	StructAggStatePerGroupData = llvm_pg_var_type("StructAggStatePerGroupData");
-	StructAggStatePerTransData = llvm_pg_var_type("StructAggStatePerTransData");
-	StructPlanState = llvm_pg_var_type("StructPlanState");
-	StructMinimalTupleData = llvm_pg_var_type("StructMinimalTupleData");
-
-	AttributeTemplate = LLVMGetNamedFunction(llvm_types_module, "AttributeTemplate");
-	ExecEvalSubroutineTemplate = LLVMGetNamedFunction(llvm_types_module, "ExecEvalSubroutineTemplate");
-	ExecEvalBoolSubroutineTemplate = LLVMGetNamedFunction(llvm_types_module, "ExecEvalBoolSubroutineTemplate");
+	jit_types_struct->TypeSizeT = llvm_pg_var_type(*llvm_types_module, "TypeSizeT");
+	jit_types_struct->TypeParamBool = load_return_type(*llvm_types_module, "FunctionReturningBool");
+	jit_types_struct->TypeStorageBool = llvm_pg_var_type(*llvm_types_module, "TypeStorageBool");
+	jit_types_struct->TypePGFunction = llvm_pg_var_type(*llvm_types_module, "TypePGFunction");
+	jit_types_struct->StructNullableDatum = llvm_pg_var_type(*llvm_types_module, "StructNullableDatum");
+	jit_types_struct->StructExprContext = llvm_pg_var_type(*llvm_types_module, "StructExprContext");
+	jit_types_struct->StructExprEvalStep = llvm_pg_var_type(*llvm_types_module, "StructExprEvalStep");
+	jit_types_struct->StructExprState = llvm_pg_var_type(*llvm_types_module, "StructExprState");
+	jit_types_struct->StructFunctionCallInfoData = llvm_pg_var_type(*llvm_types_module, "StructFunctionCallInfoData");
+	jit_types_struct->StructMemoryContextData = llvm_pg_var_type(*llvm_types_module, "StructMemoryContextData");
+	jit_types_struct->StructTupleTableSlot = llvm_pg_var_type(*llvm_types_module, "StructTupleTableSlot");
+	jit_types_struct->StructHeapTupleTableSlot = llvm_pg_var_type(*llvm_types_module, "StructHeapTupleTableSlot");
+	jit_types_struct->StructMinimalTupleTableSlot = llvm_pg_var_type(*llvm_types_module, "StructMinimalTupleTableSlot");
+	jit_types_struct->StructHeapTupleData = llvm_pg_var_type(*llvm_types_module, "StructHeapTupleData");
+	jit_types_struct->StructHeapTupleHeaderData = llvm_pg_var_type(*llvm_types_module, "StructHeapTupleHeaderData");
+	jit_types_struct->StructTupleDescData = llvm_pg_var_type(*llvm_types_module, "StructTupleDescData");
+	jit_types_struct->StructAggState = llvm_pg_var_type(*llvm_types_module, "StructAggState");
+	jit_types_struct->StructAggStatePerGroupData = llvm_pg_var_type(*llvm_types_module, "StructAggStatePerGroupData");
+	jit_types_struct->StructAggStatePerTransData = llvm_pg_var_type(*llvm_types_module, "StructAggStatePerTransData");
+	jit_types_struct->StructPlanState = llvm_pg_var_type(*llvm_types_module, "StructPlanState");
+	jit_types_struct->StructMinimalTupleData = llvm_pg_var_type(*llvm_types_module, "StructMinimalTupleData");
+	jit_types_struct->StructWindowFuncExprState = llvm_pg_var_type(*llvm_types_module, "StructWindowFuncExprState");
+
+	jit_types_struct->AttributeTemplate = LLVMGetNamedFunction(*llvm_types_module, "AttributeTemplate");
+	jit_types_struct->ExecEvalSubroutineTemplate = LLVMGetNamedFunction(*llvm_types_module, "ExecEvalSubroutineTemplate");
+	jit_types_struct->ExecEvalBoolSubroutineTemplate = LLVMGetNamedFunction(*llvm_types_module, "ExecEvalBoolSubroutineTemplate");
+	{
+		char *error = NULL;
+		LLVMVerifyModule(*llvm_types_module, LLVMAbortProcessAction, &error);
+		LLVMDisposeMessage(error);
+	}
 }
 
+/*
+ * Load required information, types, function signatures from llvmjit_types.c
+ * and make them available in global variables.
+ *
+ * Those global variables are then used while emitting code.
+ */
+static void
+llvm_create_types(void)
+{
+	llvm_create_types_context(&llvm_jit_types_struct, &llvm_types_module, llvm_context);
+}
 /*
  * Split a symbol into module / function parts.  If the function is in the
  * main binary (or an external library) *modname will be NULL.
diff --git a/src/backend/jit/llvm/llvmjit_deform.c b/src/backend/jit/llvm/llvmjit_deform.c
index 5d169c7a40b..98b32a4954c 100644
--- a/src/backend/jit/llvm/llvmjit_deform.c
+++ b/src/backend/jit/llvm/llvmjit_deform.c
@@ -78,6 +78,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 	LLVMValueRef v_hoff;
 
 	LLVMValueRef v_hasnulls;
+	LLVMJitTypes	*g;
 
 	/* last column (0 indexed) guaranteed to exist */
 	int			guaranteed_column_number = -1;
@@ -101,8 +102,9 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 
 	mod = llvm_mutable_module(context);
 	lc = LLVMGetModuleContext(mod);
+	g = context->jit_types;
 
-	funcname = llvm_expand_funcname(context, "deform");
+	funcname = llvm_expand_funcname_deform(context, "deform");
 
 	/*
 	 * Check which columns have to exist, so we don't have to check the row's
@@ -133,7 +135,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 	{
 		LLVMTypeRef param_types[1];
 
-		param_types[0] = l_ptr(StructTupleTableSlot);
+		param_types[0] = l_ptr(g->StructTupleTableSlot);
 
 		deform_sig = LLVMFunctionType(LLVMVoidTypeInContext(lc),
 									  param_types, lengthof(param_types), 0);
@@ -141,7 +143,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 	v_deform_fn = LLVMAddFunction(mod, funcname, deform_sig);
 	LLVMSetLinkage(v_deform_fn, LLVMInternalLinkage);
 	LLVMSetParamAlignment(LLVMGetParam(v_deform_fn, 0), MAXIMUM_ALIGNOF);
-	llvm_copy_attributes(AttributeTemplate, v_deform_fn);
+	llvm_copy_attributes(g->AttributeTemplate, v_deform_fn);
 
 	b_entry =
 		LLVMAppendBasicBlockInContext(lc, v_deform_fn, "entry");
@@ -168,18 +170,18 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 	LLVMPositionBuilderAtEnd(b, b_entry);
 
 	/* perform allocas first, llvm only converts those to registers */
-	v_offp = LLVMBuildAlloca(b, TypeSizeT, "v_offp");
+	v_offp = LLVMBuildAlloca(b, g->TypeSizeT, "v_offp");
 
 	v_slot = LLVMGetParam(v_deform_fn, 0);
 
 	v_tts_values =
-		l_load_struct_gep(b, StructTupleTableSlot, v_slot, FIELDNO_TUPLETABLESLOT_VALUES,
+		l_load_struct_gep(b, g->StructTupleTableSlot, v_slot, FIELDNO_TUPLETABLESLOT_VALUES,
 						  "tts_values");
 	v_tts_nulls =
-		l_load_struct_gep(b, StructTupleTableSlot, v_slot, FIELDNO_TUPLETABLESLOT_ISNULL,
+		l_load_struct_gep(b, g->StructTupleTableSlot, v_slot, FIELDNO_TUPLETABLESLOT_ISNULL,
 						  "tts_ISNULL");
-	v_flagsp = l_struct_gep(b, StructTupleTableSlot, v_slot, FIELDNO_TUPLETABLESLOT_FLAGS, "");
-	v_nvalidp = l_struct_gep(b, StructTupleTableSlot, v_slot, FIELDNO_TUPLETABLESLOT_NVALID, "");
+	v_flagsp = l_struct_gep(b, g->StructTupleTableSlot, v_slot, FIELDNO_TUPLETABLESLOT_FLAGS, "");
+	v_nvalidp = l_struct_gep(b, g->StructTupleTableSlot, v_slot, FIELDNO_TUPLETABLESLOT_NVALID, "");
 
 	if (ops == &TTSOpsHeapTuple || ops == &TTSOpsBufferHeapTuple)
 	{
@@ -188,11 +190,11 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 		v_heapslot =
 			LLVMBuildBitCast(b,
 							 v_slot,
-							 l_ptr(StructHeapTupleTableSlot),
+							 l_ptr(g->StructHeapTupleTableSlot),
 							 "heapslot");
-		v_slotoffp = l_struct_gep(b, StructHeapTupleTableSlot, v_heapslot, FIELDNO_HEAPTUPLETABLESLOT_OFF, "");
+		v_slotoffp = l_struct_gep(b, g->StructHeapTupleTableSlot, v_heapslot, FIELDNO_HEAPTUPLETABLESLOT_OFF, "");
 		v_tupleheaderp =
-			l_load_struct_gep(b, StructHeapTupleTableSlot, v_heapslot, FIELDNO_HEAPTUPLETABLESLOT_TUPLE,
+			l_load_struct_gep(b, g->StructHeapTupleTableSlot, v_heapslot, FIELDNO_HEAPTUPLETABLESLOT_TUPLE,
 							  "tupleheader");
 	}
 	else if (ops == &TTSOpsMinimalTuple)
@@ -202,15 +204,15 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 		v_minimalslot =
 			LLVMBuildBitCast(b,
 							 v_slot,
-							 l_ptr(StructMinimalTupleTableSlot),
+							 l_ptr(g->StructMinimalTupleTableSlot),
 							 "minimalslot");
 		v_slotoffp = l_struct_gep(b,
-								  StructMinimalTupleTableSlot,
+								  g->StructMinimalTupleTableSlot,
 								  v_minimalslot,
 								  FIELDNO_MINIMALTUPLETABLESLOT_OFF, "");
 		v_tupleheaderp =
 			l_load_struct_gep(b,
-							  StructMinimalTupleTableSlot,
+							  g->StructMinimalTupleTableSlot,
 							  v_minimalslot,
 							  FIELDNO_MINIMALTUPLETABLESLOT_TUPLE,
 							  "tupleheader");
@@ -223,14 +225,14 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 
 	v_tuplep =
 		l_load_struct_gep(b,
-						  StructHeapTupleData,
+						  g->StructHeapTupleData,
 						  v_tupleheaderp,
 						  FIELDNO_HEAPTUPLEDATA_DATA,
 						  "tuple");
 	v_bits =
 		LLVMBuildBitCast(b,
 						 l_struct_gep(b,
-									  StructHeapTupleHeaderData,
+									  g->StructHeapTupleHeaderData,
 									  v_tuplep,
 									  FIELDNO_HEAPTUPLEHEADERDATA_BITS,
 									  ""),
@@ -238,13 +240,13 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 						 "t_bits");
 	v_infomask1 =
 		l_load_struct_gep(b,
-						  StructHeapTupleHeaderData,
+						  g->StructHeapTupleHeaderData,
 						  v_tuplep,
 						  FIELDNO_HEAPTUPLEHEADERDATA_INFOMASK,
 						  "infomask1");
 	v_infomask2 =
 		l_load_struct_gep(b,
-						  StructHeapTupleHeaderData,
+						  g->StructHeapTupleHeaderData,
 						  v_tuplep, FIELDNO_HEAPTUPLEHEADERDATA_INFOMASK2,
 						  "infomask2");
 
@@ -270,7 +272,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 	v_hoff =
 		LLVMBuildZExt(b,
 					  l_load_struct_gep(b,
-										StructHeapTupleHeaderData,
+										g->StructHeapTupleHeaderData,
 										v_tuplep,
 										FIELDNO_HEAPTUPLEHEADERDATA_HOFF,
 										""),
@@ -293,7 +295,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 		LLVMValueRef v_off_start;
 
 		v_off_start = l_load(b, LLVMInt32TypeInContext(lc), v_slotoffp, "v_slot_off");
-		v_off_start = LLVMBuildZExt(b, v_off_start, TypeSizeT, "");
+		v_off_start = LLVMBuildZExt(b, v_off_start, g->TypeSizeT, "");
 		LLVMBuildStore(b, v_off_start, v_offp);
 	}
 
@@ -349,7 +351,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 		v_params[0] = v_slot;
 		v_params[1] = LLVMBuildZExt(b, v_maxatt, LLVMInt32TypeInContext(lc), "");
 		v_params[2] = l_int32_const(lc, natts);
-		f = llvm_pg_func(mod, "slot_getmissingattrs");
+		f = llvm_pg_func(context, "slot_getmissingattrs");
 		l_call(b,
 			   LLVMGetFunctionType(f), f,
 			   v_params, lengthof(v_params), "");
@@ -409,7 +411,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 		 */
 		if (attnum == 0)
 		{
-			LLVMBuildStore(b, l_sizet_const(0), v_offp);
+			LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_offp);
 		}
 
 		/*
@@ -479,8 +481,8 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 						   l_gep(b, LLVMInt8TypeInContext(lc), v_tts_nulls, &l_attno, 1, ""));
 			/* store zero datum */
 			LLVMBuildStore(b,
-						   l_sizet_const(0),
-						   l_gep(b, TypeSizeT, v_tts_values, &l_attno, 1, ""));
+						   LLVMConstInt(g->TypeSizeT, 0, false),
+						   l_gep(b, g->TypeSizeT, v_tts_values, &l_attno, 1, ""));
 
 			LLVMBuildBr(b, b_next);
 			attguaranteedalign = false;
@@ -524,7 +526,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 				/* don't know if short varlena or not */
 				attguaranteedalign = false;
 
-				v_off = l_load(b, TypeSizeT, v_offp, "");
+				v_off = l_load(b, g->TypeSizeT, v_offp, "");
 
 				v_possible_padbyte =
 					l_load_gep1(b, LLVMInt8TypeInContext(lc), v_tupdata_base, v_off, "padbyte");
@@ -546,16 +548,16 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 			/* translation of alignment code (cf TYPEALIGN()) */
 			{
 				LLVMValueRef v_off_aligned;
-				LLVMValueRef v_off = l_load(b, TypeSizeT, v_offp, "");
+				LLVMValueRef v_off = l_load(b, g->TypeSizeT, v_offp, "");
 
 				/* ((ALIGNVAL) - 1) */
-				LLVMValueRef v_alignval = l_sizet_const(alignto - 1);
+				LLVMValueRef v_alignval = LLVMConstInt(g->TypeSizeT, alignto - 1, false);
 
 				/* ((uintptr_t) (LEN) + ((ALIGNVAL) - 1)) */
 				LLVMValueRef v_lh = LLVMBuildAdd(b, v_off, v_alignval, "");
 
 				/* ~((uintptr_t) ((ALIGNVAL) - 1)) */
-				LLVMValueRef v_rh = l_sizet_const(~(alignto - 1));
+				LLVMValueRef v_rh = LLVMConstInt(g->TypeSizeT, ~(alignto - 1), false);
 
 				v_off_aligned = LLVMBuildAnd(b, v_lh, v_rh, "aligned_offset");
 
@@ -594,7 +596,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 		if (attguaranteedalign)
 		{
 			Assert(known_alignment >= 0);
-			LLVMBuildStore(b, l_sizet_const(known_alignment), v_offp);
+			LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, known_alignment, false), v_offp);
 		}
 
 		/* compute what following columns are aligned to */
@@ -635,18 +637,18 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 
 		/* compute address to load data from */
 		{
-			LLVMValueRef v_off = l_load(b, TypeSizeT, v_offp, "");
+			LLVMValueRef v_off = l_load(b, g->TypeSizeT, v_offp, "");
 
 			v_attdatap =
 				l_gep(b, LLVMInt8TypeInContext(lc), v_tupdata_base, &v_off, 1, "");
 		}
 
 		/* compute address to store value at */
-		v_resultp = l_gep(b, TypeSizeT, v_tts_values, &l_attno, 1, "");
+		v_resultp = l_gep(b, g->TypeSizeT, v_tts_values, &l_attno, 1, "");
 
 		/* store null-byte (false) */
 		LLVMBuildStore(b, l_int8_const(lc, 0),
-					   l_gep(b, TypeStorageBool, v_tts_nulls, &l_attno, 1, ""));
+					   l_gep(b, g->TypeStorageBool, v_tts_nulls, &l_attno, 1, ""));
 
 		/*
 		 * Store datum. For byval: datums copy the value, extend to Datum's
@@ -661,7 +663,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 			v_tmp_loaddata =
 				LLVMBuildPointerCast(b, v_attdatap, vartypep, "");
 			v_tmp_loaddata = l_load(b, vartype, v_tmp_loaddata, "attr_byval");
-			v_tmp_loaddata = LLVMBuildZExt(b, v_tmp_loaddata, TypeSizeT, "");
+			v_tmp_loaddata = LLVMBuildZExt(b, v_tmp_loaddata, g->TypeSizeT, "");
 
 			LLVMBuildStore(b, v_tmp_loaddata, v_resultp);
 		}
@@ -673,7 +675,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 			v_tmp_loaddata =
 				LLVMBuildPtrToInt(b,
 								  v_attdatap,
-								  TypeSizeT,
+								  g->TypeSizeT,
 								  "attr_ptr");
 			LLVMBuildStore(b, v_tmp_loaddata, v_resultp);
 		}
@@ -681,13 +683,13 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 		/* increment data pointer */
 		if (att->attlen > 0)
 		{
-			v_incby = l_sizet_const(att->attlen);
+			v_incby = LLVMConstInt(g->TypeSizeT, att->attlen, false);
 		}
 		else if (att->attlen == -1)
 		{
 			v_incby = l_call(b,
-							 llvm_pg_var_func_type("varsize_any"),
-							 llvm_pg_func(mod, "varsize_any"),
+							 llvm_pg_var_func_type(context, "varsize_any"),
+							 llvm_pg_func(context, "varsize_any"),
 							 &v_attdatap, 1,
 							 "varsize_any");
 			l_callsite_ro(v_incby);
@@ -696,14 +698,14 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 		else if (att->attlen == -2)
 		{
 			v_incby = l_call(b,
-							 llvm_pg_var_func_type("strlen"),
-							 llvm_pg_func(mod, "strlen"),
+							 llvm_pg_var_func_type(context, "strlen"),
+							 llvm_pg_func(context, "strlen"),
 							 &v_attdatap, 1, "strlen");
 
 			l_callsite_ro(v_incby);
 
 			/* add 1 for NUL byte */
-			v_incby = LLVMBuildAdd(b, v_incby, l_sizet_const(1), "");
+			v_incby = LLVMBuildAdd(b, v_incby, LLVMConstInt(g->TypeSizeT, 1, false), "");
 		}
 		else
 		{
@@ -714,11 +716,11 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 		if (attguaranteedalign)
 		{
 			Assert(known_alignment >= 0);
-			LLVMBuildStore(b, l_sizet_const(known_alignment), v_offp);
+			LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, known_alignment, false), v_offp);
 		}
 		else
 		{
-			LLVMValueRef v_off = l_load(b, TypeSizeT, v_offp, "");
+			LLVMValueRef v_off = l_load(b, g->TypeSizeT, v_offp, "");
 
 			v_off = LLVMBuildAdd(b, v_off, v_incby, "increment_offset");
 			LLVMBuildStore(b, v_off, v_offp);
@@ -744,7 +746,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 	LLVMPositionBuilderAtEnd(b, b_out);
 
 	{
-		LLVMValueRef v_off = l_load(b, TypeSizeT, v_offp, "");
+		LLVMValueRef v_off = l_load(b, g->TypeSizeT, v_offp, "");
 		LLVMValueRef v_flags;
 
 		LLVMBuildStore(b, l_int16_const(lc, natts), v_nvalidp);
diff --git a/src/backend/jit/llvm/llvmjit_expr.c b/src/backend/jit/llvm/llvmjit_expr.c
index f0f5c3bd49f..6f5e32eee80 100644
--- a/src/backend/jit/llvm/llvmjit_expr.c
+++ b/src/backend/jit/llvm/llvmjit_expr.c
@@ -17,6 +17,7 @@
 
 #include <llvm-c/Core.h>
 #include <llvm-c/Target.h>
+#include <llvm-c/Analysis.h>
 
 #include "access/htup_details.h"
 #include "access/nbtree.h"
@@ -57,16 +58,22 @@ static Datum ExecRunCompiledExpr(ExprState *state, ExprContext *econtext, bool *
 static LLVMValueRef BuildV1Call(LLVMJitContext *context, LLVMBuilderRef b,
 								LLVMModuleRef mod, FunctionCallInfo fcinfo,
 								LLVMValueRef *v_fcinfo_isnull);
+static LLVMValueRef BuildV1CallLLVM(LLVMJitContext *context, LLVMBuilderRef b,
+			LLVMModuleRef mod, FunctionCallInfo fcinfo,
+			LLVMValueRef v_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 build_EvalXFuncIntLLVM(LLVMBuilderRef b, LLVMJitContext *context, const char *funcname,
+				   LLVMValueRef v_state, LLVMValueRef v_op,
+				   int nargs, LLVMValueRef *v_args);
 static LLVMValueRef create_LifetimeEnd(LLVMModuleRef mod);
 
 /* macro making it easier to call ExecEval* functions */
-#define build_EvalXFunc(b, mod, funcname, v_state, op, ...) \
-	build_EvalXFuncInt(b, mod, funcname, v_state, op, \
+#define build_EvalXFunc(b, context, funcname, v_state, op, ...) \
+	build_EvalXFuncIntLLVM(b, context, funcname, v_state, op, \
 					   lengthof(((LLVMValueRef[]){__VA_ARGS__})), \
 					   ((LLVMValueRef[]){__VA_ARGS__}))
 
@@ -84,6 +91,7 @@ llvm_compile_expr(ExprState *state)
 
 	LLVMBuilderRef b;
 	LLVMModuleRef mod;
+	LLVMModuleRef typesmod;
 	LLVMContextRef lc;
 	LLVMValueRef eval_fn;
 	LLVMBasicBlockRef entry;
@@ -93,6 +101,7 @@ llvm_compile_expr(ExprState *state)
 	LLVMValueRef v_state;
 	LLVMValueRef v_econtext;
 	LLVMValueRef v_parent;
+	LLVMValueRef v_steps;
 
 	/* returnvalue */
 	LLVMValueRef v_isnullp;
@@ -132,6 +141,9 @@ llvm_compile_expr(ExprState *state)
 	instr_time	endtime;
 	instr_time	deform_endtime;
 
+	bool		cached_plan;
+	LLVMJitTypes	*g;
+
 	llvm_enter_fatal_on_oom();
 
 	/*
@@ -141,29 +153,78 @@ llvm_compile_expr(ExprState *state)
 	Assert(parent);
 
 	/* get or create JIT context */
-	if (parent->state->es_jit)
-		context = (LLVMJitContext *) parent->state->es_jit;
-	else
+	if (parent->state->es_plannedstmt->jit_context == NULL || !jit_cached)
 	{
-		context = llvm_create_context(parent->state->es_jit_flags);
-		parent->state->es_jit = &context->base;
+		if (parent->state->es_jit)
+			context = (LLVMJitContext *) parent->state->es_jit;
+		else
+		{
+			context = llvm_create_context(parent->state->es_jit_flags);
+			parent->state->es_jit = &context->base;
+		}
+		mod = llvm_mutable_module(context);
+		funcname = llvm_expand_funcname_expr(context, "evalexpr");
+
+		cached_plan = false;
+		g = context->jit_types;
 	}
+	else
+	{
+		cached_plan = true;
+		if (parent->state->es_plannedstmt->jit_context == CACHED_JITCONTEXT_EMPTY)
+		{
+			parent->state->es_plannedstmt->jit_context = llvm_create_cached_context(parent->state->es_jit_flags);
+		}
 
+		context = &parent->state->es_plannedstmt->jit_context->jit;
+
+		g = context->jit_types;
+		if (!parent->state->es_plannedstmt->jit_context->jit.compiled)
+		{
+			mod = llvm_mutable_module(context);
+			funcname = llvm_expand_funcname_expr(context, "evalexpr");
+			context->max_counter_expr = context->counter_expr;
+			///elog(NOTICE,"Compile %s max %d counter %d, context=%zx", funcname, context->max_counter_expr , context->counter_expr, (Size)context);
+		}
+		else
+		{
+			ExprStateEvalFunc func;
+			/* find and assign binary function: first call - first expression
+				Attention!
+				This alogorithm is wrong and will fail, if query compiles additional
+				expressions after the module compilation (f.e. for HashJoin). Needs new implementation
+				to assign expressions and compiled functions
+			*/
+			///elog(NOTICE,"1 Look for Compiled before max %d counter %d, context=%zx", context->max_counter_expr , context->counter_expr, (Size)context);
+			if (context->max_counter_expr == context->counter_expr)
+			{
+				context->counter_expr = 0;
+				context->counter_deform = 0;
+			}
+			funcname = llvm_expand_funcname_expr(context, "evalexpr");
+			func = (ExprStateEvalFunc) llvm_get_function(context,funcname);
+			llvm_leave_fatal_on_oom();
+			Assert(func);
+			/* remove indirection via this function for future calls */
+			state->evalfunc = func;
+			pfree(funcname);
+			return true;
+		}
+	}
 	INSTR_TIME_SET_CURRENT(starttime);
 
-	mod = llvm_mutable_module(context);
 	lc = LLVMGetModuleContext(mod);
+	typesmod = context->llvm_types_module;
 
 	b = LLVMCreateBuilderInContext(lc);
 
-	funcname = llvm_expand_funcname(context, "evalexpr");
 
 	/* create function */
 	eval_fn = LLVMAddFunction(mod, funcname,
-							  llvm_pg_var_func_type("ExecInterpExprStillValid"));
+							  llvm_pg_var_func_type(context, "ExecInterpExprStillValid"));
 	LLVMSetLinkage(eval_fn, LLVMExternalLinkage);
 	LLVMSetVisibility(eval_fn, LLVMDefaultVisibility);
-	llvm_copy_attributes(AttributeTemplate, eval_fn);
+	llvm_copy_attributes(g->AttributeTemplate, eval_fn);
 
 	entry = LLVMAppendBasicBlockInContext(lc, eval_fn, "entry");
 
@@ -175,123 +236,128 @@ llvm_compile_expr(ExprState *state)
 	LLVMPositionBuilderAtEnd(b, entry);
 
 	v_tmpvaluep = l_struct_gep(b,
-							   StructExprState,
+							   g->StructExprState,
 							   v_state,
 							   FIELDNO_EXPRSTATE_RESVALUE,
 							   "v.state.resvalue");
 	v_tmpisnullp = l_struct_gep(b,
-								StructExprState,
+								g->StructExprState,
 								v_state,
 								FIELDNO_EXPRSTATE_RESNULL,
 								"v.state.resnull");
 	v_parent = l_load_struct_gep(b,
-								 StructExprState,
+								 g->StructExprState,
 								 v_state,
 								 FIELDNO_EXPRSTATE_PARENT,
 								 "v.state.parent");
+	v_steps = l_load_struct_gep(b,
+								g->StructExprState,
+								v_state,
+								FIELDNO_EXPRSTATE_STEPS,
+								"v_state_steps");
 
 	/* build global slots */
 	v_scanslot = l_load_struct_gep(b,
-								   StructExprContext,
+								   g->StructExprContext,
 								   v_econtext,
 								   FIELDNO_EXPRCONTEXT_SCANTUPLE,
 								   "v_scanslot");
 	v_innerslot = l_load_struct_gep(b,
-									StructExprContext,
+									g->StructExprContext,
 									v_econtext,
 									FIELDNO_EXPRCONTEXT_INNERTUPLE,
 									"v_innerslot");
 	v_outerslot = l_load_struct_gep(b,
-									StructExprContext,
+									g->StructExprContext,
 									v_econtext,
 									FIELDNO_EXPRCONTEXT_OUTERTUPLE,
 									"v_outerslot");
 	v_oldslot = l_load_struct_gep(b,
-								  StructExprContext,
+								  g->StructExprContext,
 								  v_econtext,
 								  FIELDNO_EXPRCONTEXT_OLDTUPLE,
 								  "v_oldslot");
 	v_newslot = l_load_struct_gep(b,
-								  StructExprContext,
+								  g->StructExprContext,
 								  v_econtext,
 								  FIELDNO_EXPRCONTEXT_NEWTUPLE,
 								  "v_newslot");
 	v_resultslot = l_load_struct_gep(b,
-									 StructExprState,
+									 g->StructExprState,
 									 v_state,
 									 FIELDNO_EXPRSTATE_RESULTSLOT,
 									 "v_resultslot");
 
 	/* build global values/isnull pointers */
 	v_scanvalues = l_load_struct_gep(b,
-									 StructTupleTableSlot,
+									 g->StructTupleTableSlot,
 									 v_scanslot,
 									 FIELDNO_TUPLETABLESLOT_VALUES,
 									 "v_scanvalues");
 	v_scannulls = l_load_struct_gep(b,
-									StructTupleTableSlot,
+									g->StructTupleTableSlot,
 									v_scanslot,
 									FIELDNO_TUPLETABLESLOT_ISNULL,
 									"v_scannulls");
 	v_innervalues = l_load_struct_gep(b,
-									  StructTupleTableSlot,
+									  g->StructTupleTableSlot,
 									  v_innerslot,
 									  FIELDNO_TUPLETABLESLOT_VALUES,
 									  "v_innervalues");
 	v_innernulls = l_load_struct_gep(b,
-									 StructTupleTableSlot,
+									 g->StructTupleTableSlot,
 									 v_innerslot,
 									 FIELDNO_TUPLETABLESLOT_ISNULL,
 									 "v_innernulls");
 	v_outervalues = l_load_struct_gep(b,
-									  StructTupleTableSlot,
+									  g->StructTupleTableSlot,
 									  v_outerslot,
 									  FIELDNO_TUPLETABLESLOT_VALUES,
 									  "v_outervalues");
 	v_outernulls = l_load_struct_gep(b,
-									 StructTupleTableSlot,
+									 g->StructTupleTableSlot,
 									 v_outerslot,
 									 FIELDNO_TUPLETABLESLOT_ISNULL,
 									 "v_outernulls");
 	v_oldvalues = l_load_struct_gep(b,
-									StructTupleTableSlot,
+									g->StructTupleTableSlot,
 									v_oldslot,
 									FIELDNO_TUPLETABLESLOT_VALUES,
 									"v_oldvalues");
 	v_oldnulls = l_load_struct_gep(b,
-								   StructTupleTableSlot,
+								   g->StructTupleTableSlot,
 								   v_oldslot,
 								   FIELDNO_TUPLETABLESLOT_ISNULL,
 								   "v_oldnulls");
 	v_newvalues = l_load_struct_gep(b,
-									StructTupleTableSlot,
+									g->StructTupleTableSlot,
 									v_newslot,
 									FIELDNO_TUPLETABLESLOT_VALUES,
 									"v_newvalues");
 	v_newnulls = l_load_struct_gep(b,
-								   StructTupleTableSlot,
+								   g->StructTupleTableSlot,
 								   v_newslot,
 								   FIELDNO_TUPLETABLESLOT_ISNULL,
 								   "v_newnulls");
 	v_resultvalues = l_load_struct_gep(b,
-									   StructTupleTableSlot,
+									   g->StructTupleTableSlot,
 									   v_resultslot,
 									   FIELDNO_TUPLETABLESLOT_VALUES,
 									   "v_resultvalues");
 	v_resultnulls = l_load_struct_gep(b,
-									  StructTupleTableSlot,
+									  g->StructTupleTableSlot,
 									  v_resultslot,
 									  FIELDNO_TUPLETABLESLOT_ISNULL,
 									  "v_resultnulls");
 
 	/* aggvalues/aggnulls */
 	v_aggvalues = l_load_struct_gep(b,
-									StructExprContext,
+									g->StructExprContext,
 									v_econtext,
 									FIELDNO_EXPRCONTEXT_AGGVALUES,
 									"v.econtext.aggvalues");
 	v_aggnulls = l_load_struct_gep(b,
-								   StructExprContext,
+								   g->StructExprContext,
 								   v_econtext,
 								   FIELDNO_EXPRCONTEXT_AGGNULLS,
 								   "v.econtext.aggnulls");
@@ -308,16 +374,22 @@ llvm_compile_expr(ExprState *state)
 	{
 		ExprEvalStep *op;
 		ExprEvalOp	opcode;
+		LLVMValueRef v_op;
+		LLVMValueRef v_opno;
 		LLVMValueRef v_resvaluep;
 		LLVMValueRef v_resnullp;
 
+
 		LLVMPositionBuilderAtEnd(b, opblocks[opno]);
 
 		op = &state->steps[opno];
 		opcode = ExecEvalStepOp(state, op);
-
-		v_resvaluep = l_ptr_const(op->resvalue, l_ptr(TypeSizeT));
-		v_resnullp = l_ptr_const(op->resnull, l_ptr(TypeStorageBool));
+		v_opno = l_int32_const(lc, opno);
+		v_op = l_gep(b, g->StructExprEvalStep, v_steps, &v_opno, 1, "v_op_step");
+		///v_resvaluep = l_ptr_const(op->resvalue, l_ptr(TypeSizeT));
+		///v_resnullp = l_ptr_const(op->resnull, l_ptr(g->TypeStorageBool));
+		v_resvaluep = l_load_struct_gep( b, g->StructExprEvalStep, v_op, FIELDNO_EXPREVALSTEP_RESVALUE, "v_resvaluep");
+		v_resnullp = l_load_struct_gep( b, g->StructExprEvalStep, v_op, FIELDNO_EXPREVALSTEP_RESNULL, "v_resnullp");
 
 		switch (opcode)
 		{
@@ -326,8 +398,8 @@ llvm_compile_expr(ExprState *state)
 					LLVMValueRef v_tmpisnull;
 					LLVMValueRef v_tmpvalue;
 
-					v_tmpvalue = l_load(b, TypeSizeT, v_tmpvaluep, "");
-					v_tmpisnull = l_load(b, TypeStorageBool, v_tmpisnullp, "");
+					v_tmpvalue = l_load(b, g->TypeSizeT, v_tmpvaluep, "");
+					v_tmpisnull = l_load(b, g->TypeStorageBool, v_tmpisnullp, "");
 
 					LLVMBuildStore(b, v_tmpisnull, v_isnullp);
 
@@ -377,7 +449,7 @@ llvm_compile_expr(ExprState *state)
 					 */
 					v_nvalid =
 						l_load_struct_gep(b,
-										  StructTupleTableSlot,
+										  g->StructTupleTableSlot,
 										  v_slot,
 										  FIELDNO_TUPLETABLESLOT_NVALID,
 										  "");
@@ -426,8 +498,8 @@ llvm_compile_expr(ExprState *state)
 						params[1] = l_int32_const(lc, op->d.fetch.last_var);
 
 						l_call(b,
-							   llvm_pg_var_func_type("slot_getsomeattrs_int"),
-							   llvm_pg_func(mod, "slot_getsomeattrs_int"),
+							   llvm_pg_var_func_type(context, "slot_getsomeattrs_int"),
+							   llvm_pg_func(context, "slot_getsomeattrs_int"),
 							   params, lengthof(params), "");
 					}
 
@@ -474,8 +546,8 @@ llvm_compile_expr(ExprState *state)
 					}
 
 					v_attnum = l_int32_const(lc, op->d.var.attnum);
-					value = l_load_gep1(b, TypeSizeT, v_values, v_attnum, "");
-					isnull = l_load_gep1(b, TypeStorageBool, v_nulls, v_attnum, "");
+					value = l_load_gep1(b, g->TypeSizeT, v_values, v_attnum, "");
+					isnull = l_load_gep1(b, g->TypeStorageBool, v_nulls, v_attnum, "");
 					LLVMBuildStore(b, value, v_resvaluep);
 					LLVMBuildStore(b, isnull, v_resnullp);
 
@@ -502,16 +574,16 @@ llvm_compile_expr(ExprState *state)
 					else
 						v_slot = v_newslot;
 
-					build_EvalXFunc(b, mod, "ExecEvalSysVar",
-									v_state, op, v_econtext, v_slot);
+					build_EvalXFunc(b, context, "ExecEvalSysVar",
+									v_state, v_op, v_econtext, v_slot);
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
 					break;
 				}
 
 			case EEOP_WHOLEROW:
-				build_EvalXFunc(b, mod, "ExecEvalWholeRowVar",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalWholeRowVar",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -558,17 +630,17 @@ llvm_compile_expr(ExprState *state)
 
 					/* load data */
 					v_attnum = l_int32_const(lc, op->d.assign_var.attnum);
-					v_value = l_load_gep1(b, TypeSizeT, v_values, v_attnum, "");
-					v_isnull = l_load_gep1(b, TypeStorageBool, v_nulls, v_attnum, "");
+					v_value = l_load_gep1(b, g->TypeSizeT, v_values, v_attnum, "");
+					v_isnull = l_load_gep1(b, g->TypeStorageBool, v_nulls, v_attnum, "");
 
 					/* compute addresses of targets */
 					v_resultnum = l_int32_const(lc, op->d.assign_var.resultnum);
 					v_rvaluep = l_gep(b,
-									  TypeSizeT,
+									  g->TypeSizeT,
 									  v_resultvalues,
 									  &v_resultnum, 1, "");
 					v_risnullp = l_gep(b,
-									   TypeStorageBool,
+									   g->TypeStorageBool,
 									   v_resultnulls,
 									   &v_resultnum, 1, "");
 
@@ -591,15 +663,15 @@ llvm_compile_expr(ExprState *state)
 					size_t		resultnum = op->d.assign_tmp.resultnum;
 
 					/* load data */
-					v_value = l_load(b, TypeSizeT, v_tmpvaluep, "");
-					v_isnull = l_load(b, TypeStorageBool, v_tmpisnullp, "");
+					v_value = l_load(b, g->TypeSizeT, v_tmpvaluep, "");
+					v_isnull = l_load(b, g->TypeStorageBool, v_tmpisnullp, "");
 
 					/* compute addresses of targets */
 					v_resultnum = l_int32_const(lc, resultnum);
 					v_rvaluep =
-						l_gep(b, TypeSizeT, v_resultvalues, &v_resultnum, 1, "");
+						l_gep(b, g->TypeSizeT, v_resultvalues, &v_resultnum, 1, "");
 					v_risnullp =
-						l_gep(b, TypeStorageBool, v_resultnulls, &v_resultnum, 1, "");
+						l_gep(b, g->TypeStorageBool, v_resultnulls, &v_resultnum, 1, "");
 
 					/* store nullness */
 					LLVMBuildStore(b, v_isnull, v_risnullp);
@@ -616,7 +688,7 @@ llvm_compile_expr(ExprState *state)
 						/* check if value is NULL */
 						LLVMBuildCondBr(b,
 										LLVMBuildICmp(b, LLVMIntEQ, v_isnull,
-													  l_sbool_const(0), ""),
+													  LLVMConstInt(g->TypeStorageBool, (int)(0), false), ""),
 										b_notnull, opblocks[opno + 1]);
 
 						/* if value is not null, convert to RO datum */
@@ -624,8 +696,8 @@ llvm_compile_expr(ExprState *state)
 						v_params[0] = v_value;
 						v_value =
 							l_call(b,
-								   llvm_pg_var_func_type("MakeExpandedObjectReadOnlyInternal"),
-								   llvm_pg_func(mod, "MakeExpandedObjectReadOnlyInternal"),
+								   llvm_pg_var_func_type(context, "MakeExpandedObjectReadOnlyInternal"),
+								   llvm_pg_func(context, "MakeExpandedObjectReadOnlyInternal"),
 								   v_params, lengthof(v_params), "");
 
 						/*
@@ -646,8 +718,8 @@ llvm_compile_expr(ExprState *state)
 					LLVMValueRef v_constvalue,
 								v_constnull;
 
-					v_constvalue = l_sizet_const(op->d.constval.value);
-					v_constnull = l_sbool_const(op->d.constval.isnull);
+					v_constvalue = LLVMConstInt(g->TypeSizeT, op->d.constval.value, false);
+					v_constnull = LLVMConstInt(g->TypeStorageBool, (int)(op->d.constval.isnull), false);
 
 					LLVMBuildStore(b, v_constvalue, v_resvaluep);
 					LLVMBuildStore(b, v_constnull, v_resnullp);
@@ -662,12 +734,12 @@ llvm_compile_expr(ExprState *state)
 					FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
 					LLVMValueRef v_fcinfo_isnull;
 					LLVMValueRef v_retval;
+					LLVMValueRef v_fcinfo;
 
 					if (opcode == EEOP_FUNCEXPR_STRICT)
 					{
 						LLVMBasicBlockRef b_nonull;
 						LLVMBasicBlockRef *b_checkargnulls;
-						LLVMValueRef v_fcinfo;
 
 						/*
 						 * Block for the actual function call, if args are
@@ -680,14 +752,18 @@ llvm_compile_expr(ExprState *state)
 						if (op->d.func.nargs == 0)
 							elog(ERROR, "argumentless strict functions are pointless");
 
+						///v_fcinfo =
+						///	l_ptr_const(fcinfo, l_ptr(g->StructFunctionCallInfoData));
 						v_fcinfo =
-							l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
+							///l_struct_member_ptr_by_offset(b,lc, v_op, offsetof(ExprEvalStep ,d.func.fcinfo_data ));
+							l_load_member_value_by_offset(b,lc, v_op,
+								l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep ,d.func.fcinfo_data ));
 
 						/*
 						 * set resnull to true, if the function is actually
 						 * called, it'll be reset
 						 */
-						LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(1), false), v_resnullp);
 
 						/* create blocks for checking args, one for each */
 						b_checkargnulls =
@@ -718,11 +794,11 @@ llvm_compile_expr(ExprState *state)
 								b_argnotnull = b_checkargnulls[argno + 1];
 
 							/* and finally load & check NULLness of arg */
-							v_argisnull = l_funcnull(b, v_fcinfo, argno);
+							v_argisnull = l_funcnull(b, v_fcinfo, argno, g);
 							LLVMBuildCondBr(b,
 											LLVMBuildICmp(b, LLVMIntEQ,
 														  v_argisnull,
-														  l_sbool_const(1),
+														  LLVMConstInt(g->TypeStorageBool, (int)(1), false),
 														  ""),
 											opblocks[opno + 1],
 											b_argnotnull);
@@ -730,8 +806,13 @@ llvm_compile_expr(ExprState *state)
 
 						LLVMPositionBuilderAtEnd(b, b_nonull);
 					}
+					else
+					{
+						v_fcinfo = l_load_member_value_by_offset(b,lc, v_op,
+								l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep ,d.func.fcinfo_data ));
+					}
 
-					v_retval = BuildV1Call(context, b, mod, fcinfo,
+					v_retval = BuildV1CallLLVM(context, b, mod, fcinfo, v_fcinfo,
 										   &v_fcinfo_isnull);
 					LLVMBuildStore(b, v_retval, v_resvaluep);
 					LLVMBuildStore(b, v_fcinfo_isnull, v_resnullp);
@@ -741,15 +822,15 @@ llvm_compile_expr(ExprState *state)
 				}
 
 			case EEOP_FUNCEXPR_FUSAGE:
-				build_EvalXFunc(b, mod, "ExecEvalFuncExprFusage",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalFuncExprFusage",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 
 			case EEOP_FUNCEXPR_STRICT_FUSAGE:
-				build_EvalXFunc(b, mod, "ExecEvalFuncExprStrictFusage",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalFuncExprStrictFusage",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -783,26 +864,28 @@ llvm_compile_expr(ExprState *state)
 					b_boolcont = l_bb_before_v(opblocks[opno + 1],
 											   "b.%d.boolcont", opno);
 
-					v_boolanynullp = l_ptr_const(op->d.boolexpr.anynull,
-												 l_ptr(TypeStorageBool));
+					v_boolanynullp = ///l_ptr_const(op->d.boolexpr.anynull,
+									///			 l_ptr(g->TypeStorageBool));
+									l_load_member_value_by_offset(b,lc, v_op,
+								l_ptr(g->TypeStorageBool), offsetof(ExprEvalStep ,d.boolexpr.anynull ));
 
 					if (opcode == EEOP_BOOL_AND_STEP_FIRST)
-						LLVMBuildStore(b, l_sbool_const(0), v_boolanynullp);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_boolanynullp);
 
-					v_boolnull = l_load(b, TypeStorageBool, v_resnullp, "");
-					v_boolvalue = l_load(b, TypeSizeT, v_resvaluep, "");
+					v_boolnull = l_load(b, g->TypeStorageBool, v_resnullp, "");
+					v_boolvalue = l_load(b, g->TypeSizeT, v_resvaluep, "");
 
 					/* check if current input is NULL */
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_boolnull,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									b_boolisnull,
 									b_boolcheckfalse);
 
 					/* build block that sets anynull */
 					LLVMPositionBuilderAtEnd(b, b_boolisnull);
 					/* set boolanynull to true */
-					LLVMBuildStore(b, l_sbool_const(1), v_boolanynullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(1), false), v_boolanynullp);
 					/* and jump to next block */
 					LLVMBuildBr(b, b_boolcont);
 
@@ -810,7 +893,7 @@ llvm_compile_expr(ExprState *state)
 					LLVMPositionBuilderAtEnd(b, b_boolcheckfalse);
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_boolvalue,
-												  l_sizet_const(0), ""),
+												  LLVMConstInt(g->TypeSizeT, 0, false), ""),
 									b_boolisfalse,
 									b_boolcont);
 
@@ -826,19 +909,19 @@ llvm_compile_expr(ExprState *state)
 					/* Build block that continues if bool is TRUE. */
 					LLVMPositionBuilderAtEnd(b, b_boolcont);
 
-					v_boolanynull = l_load(b, TypeStorageBool, v_boolanynullp, "");
+					v_boolanynull = l_load(b, g->TypeStorageBool, v_boolanynullp, "");
 
 					/* set value to NULL if any previous values were NULL */
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_boolanynull,
-												  l_sbool_const(0), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(0), false), ""),
 									opblocks[opno + 1], b_boolisanynull);
 
 					LLVMPositionBuilderAtEnd(b, b_boolisanynull);
 					/* set resnull to true */
-					LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(1), false), v_resnullp);
 					/* reset resvalue */
-					LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_resvaluep);
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
 					break;
@@ -875,24 +958,26 @@ llvm_compile_expr(ExprState *state)
 					b_boolcont = l_bb_before_v(opblocks[opno + 1],
 											   "b.%d.boolcont", opno);
 
-					v_boolanynullp = l_ptr_const(op->d.boolexpr.anynull,
-												 l_ptr(TypeStorageBool));
+					v_boolanynullp = ///l_ptr_const(op->d.boolexpr.anynull,
+									///			 l_ptr(g->TypeStorageBool));
+									 l_ptr_const_step(d.boolexpr.anynull,
+												 l_ptr(g->TypeStorageBool));
 
 					if (opcode == EEOP_BOOL_OR_STEP_FIRST)
-						LLVMBuildStore(b, l_sbool_const(0), v_boolanynullp);
-					v_boolnull = l_load(b, TypeStorageBool, v_resnullp, "");
-					v_boolvalue = l_load(b, TypeSizeT, v_resvaluep, "");
+						LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_boolanynullp);
+					v_boolnull = l_load(b, g->TypeStorageBool, v_resnullp, "");
+					v_boolvalue = l_load(b, g->TypeSizeT, v_resvaluep, "");
 
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_boolnull,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									b_boolisnull,
 									b_boolchecktrue);
 
 					/* build block that sets anynull */
 					LLVMPositionBuilderAtEnd(b, b_boolisnull);
 					/* set boolanynull to true */
-					LLVMBuildStore(b, l_sbool_const(1), v_boolanynullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(1), false), v_boolanynullp);
 					/* and jump to next block */
 					LLVMBuildBr(b, b_boolcont);
 
@@ -900,7 +985,7 @@ llvm_compile_expr(ExprState *state)
 					LLVMPositionBuilderAtEnd(b, b_boolchecktrue);
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_boolvalue,
-												  l_sizet_const(1), ""),
+												  LLVMConstInt(g->TypeSizeT, 1, false), ""),
 									b_boolistrue,
 									b_boolcont);
 
@@ -916,19 +1001,19 @@ llvm_compile_expr(ExprState *state)
 					/* build block that continues if bool is FALSE */
 					LLVMPositionBuilderAtEnd(b, b_boolcont);
 
-					v_boolanynull = l_load(b, TypeStorageBool, v_boolanynullp, "");
+					v_boolanynull = l_load(b, g->TypeStorageBool, v_boolanynullp, "");
 
 					/* set value to NULL if any previous values were NULL */
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_boolanynull,
-												  l_sbool_const(0), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(0), false), ""),
 									opblocks[opno + 1], b_boolisanynull);
 
 					LLVMPositionBuilderAtEnd(b, b_boolisanynull);
 					/* set resnull to true */
-					LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(1), false), v_resnullp);
 					/* reset resvalue */
-					LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_resvaluep);
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
 					break;
@@ -940,13 +1025,13 @@ llvm_compile_expr(ExprState *state)
 					LLVMValueRef v_negbool;
 
 					/* compute !boolvalue */
-					v_boolvalue = l_load(b, TypeSizeT, v_resvaluep, "");
+					v_boolvalue = l_load(b, g->TypeSizeT, v_resvaluep, "");
 					v_negbool = LLVMBuildZExt(b,
 											  LLVMBuildICmp(b, LLVMIntEQ,
 															v_boolvalue,
-															l_sizet_const(0),
+															LLVMConstInt(g->TypeSizeT, 0, false),
 															""),
-											  TypeSizeT, "");
+											  g->TypeSizeT, "");
 
 					/*
 					 * Store it back in resvalue.  We can ignore resnull here;
@@ -969,15 +1054,15 @@ llvm_compile_expr(ExprState *state)
 					b_qualfail = l_bb_before_v(opblocks[opno + 1],
 											   "op.%d.qualfail", opno);
 
-					v_resvalue = l_load(b, TypeSizeT, v_resvaluep, "");
-					v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
+					v_resvalue = l_load(b, g->TypeSizeT, v_resvaluep, "");
+					v_resnull = l_load(b, g->TypeStorageBool, v_resnullp, "");
 
 					v_nullorfalse =
 						LLVMBuildOr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									LLVMBuildICmp(b, LLVMIntEQ, v_resvalue,
-												  l_sizet_const(0), ""),
+												  LLVMConstInt(g->TypeSizeT, 0, false), ""),
 									"");
 
 					LLVMBuildCondBr(b,
@@ -988,9 +1073,9 @@ llvm_compile_expr(ExprState *state)
 					/* build block handling NULL or false */
 					LLVMPositionBuilderAtEnd(b, b_qualfail);
 					/* set resnull to false */
-					LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_resnullp);
 					/* set resvalue to false */
-					LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_resvaluep);
 					/* and jump out */
 					LLVMBuildBr(b, opblocks[op->d.qualexpr.jumpdone]);
 					break;
@@ -1008,11 +1093,11 @@ llvm_compile_expr(ExprState *state)
 
 					/* Transfer control if current result is null */
 
-					v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
+					v_resnull = l_load(b, g->TypeStorageBool, v_resnullp, "");
 
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									opblocks[op->d.jump.jumpdone],
 									opblocks[opno + 1]);
 					break;
@@ -1024,11 +1109,11 @@ llvm_compile_expr(ExprState *state)
 
 					/* Transfer control if current result is non-null */
 
-					v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
+					v_resnull = l_load(b, g->TypeStorageBool, v_resnullp, "");
 
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
-												  l_sbool_const(0), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(0), false), ""),
 									opblocks[op->d.jump.jumpdone],
 									opblocks[opno + 1]);
 					break;
@@ -1043,15 +1128,15 @@ llvm_compile_expr(ExprState *state)
 
 					/* Transfer control if current result is null or false */
 
-					v_resvalue = l_load(b, TypeSizeT, v_resvaluep, "");
-					v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
+					v_resvalue = l_load(b, g->TypeSizeT, v_resvaluep, "");
+					v_resnull = l_load(b, g->TypeStorageBool, v_resnullp, "");
 
 					v_nullorfalse =
 						LLVMBuildOr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									LLVMBuildICmp(b, LLVMIntEQ, v_resvalue,
-												  l_sizet_const(0), ""),
+												  LLVMConstInt(g->TypeSizeT, 0, false), ""),
 									"");
 
 					LLVMBuildCondBr(b,
@@ -1063,18 +1148,18 @@ llvm_compile_expr(ExprState *state)
 
 			case EEOP_NULLTEST_ISNULL:
 				{
-					LLVMValueRef v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
+					LLVMValueRef v_resnull = l_load(b, g->TypeStorageBool, v_resnullp, "");
 					LLVMValueRef v_resvalue;
 
 					v_resvalue =
 						LLVMBuildSelect(b,
 										LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
-													  l_sbool_const(1), ""),
-										l_sizet_const(1),
-										l_sizet_const(0),
+													  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
+										LLVMConstInt(g->TypeSizeT, 1, false),
+										LLVMConstInt(g->TypeSizeT, 0, false),
 										"");
 					LLVMBuildStore(b, v_resvalue, v_resvaluep);
-					LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_resnullp);
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
 					break;
@@ -1082,32 +1167,32 @@ llvm_compile_expr(ExprState *state)
 
 			case EEOP_NULLTEST_ISNOTNULL:
 				{
-					LLVMValueRef v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
+					LLVMValueRef v_resnull = l_load(b, g->TypeStorageBool, v_resnullp, "");
 					LLVMValueRef v_resvalue;
 
 					v_resvalue =
 						LLVMBuildSelect(b,
 										LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
-													  l_sbool_const(1), ""),
-										l_sizet_const(0),
-										l_sizet_const(1),
+													  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
+										LLVMConstInt(g->TypeSizeT, 0, false),
+										LLVMConstInt(g->TypeSizeT, 1, false),
 										"");
 					LLVMBuildStore(b, v_resvalue, v_resvaluep);
-					LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_resnullp);
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
 					break;
 				}
 
 			case EEOP_NULLTEST_ROWISNULL:
-				build_EvalXFunc(b, mod, "ExecEvalRowNull",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalRowNull",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_NULLTEST_ROWISNOTNULL:
-				build_EvalXFunc(b, mod, "ExecEvalRowNotNull",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalRowNotNull",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -1118,7 +1203,7 @@ llvm_compile_expr(ExprState *state)
 				{
 					LLVMBasicBlockRef b_isnull,
 								b_notnull;
-					LLVMValueRef v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
+					LLVMValueRef v_resnull = l_load(b, g->TypeStorageBool, v_resnullp, "");
 
 					b_isnull = l_bb_before_v(opblocks[opno + 1],
 											 "op.%d.isnull", opno);
@@ -1128,23 +1213,23 @@ llvm_compile_expr(ExprState *state)
 					/* check if value is NULL */
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									b_isnull, b_notnull);
 
 					/* if value is NULL, return false */
 					LLVMPositionBuilderAtEnd(b, b_isnull);
 
 					/* result is not null */
-					LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_resnullp);
 
 					if (opcode == EEOP_BOOLTEST_IS_TRUE ||
 						opcode == EEOP_BOOLTEST_IS_FALSE)
 					{
-						LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_resvaluep);
 					}
 					else
 					{
-						LLVMBuildStore(b, l_sizet_const(1), v_resvaluep);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 1, false), v_resvaluep);
 					}
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
@@ -1162,14 +1247,14 @@ llvm_compile_expr(ExprState *state)
 					else
 					{
 						LLVMValueRef v_value =
-							l_load(b, TypeSizeT, v_resvaluep, "");
+							l_load(b, g->TypeSizeT, v_resvaluep, "");
 
 						v_value = LLVMBuildZExt(b,
 												LLVMBuildICmp(b, LLVMIntEQ,
 															  v_value,
-															  l_sizet_const(0),
+															  LLVMConstInt(g->TypeSizeT, 0, false),
 															  ""),
-												TypeSizeT, "");
+												g->TypeSizeT, "");
 						LLVMBuildStore(b, v_value, v_resvaluep);
 					}
 					LLVMBuildBr(b, opblocks[opno + 1]);
@@ -1177,14 +1262,14 @@ llvm_compile_expr(ExprState *state)
 				}
 
 			case EEOP_PARAM_EXEC:
-				build_EvalXFunc(b, mod, "ExecEvalParamExec",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalParamExec",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_PARAM_EXTERN:
-				build_EvalXFunc(b, mod, "ExecEvalParamExtern",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalParamExtern",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -1193,14 +1278,17 @@ llvm_compile_expr(ExprState *state)
 					LLVMValueRef v_func;
 					LLVMValueRef v_params[3];
 
-					v_func = l_ptr_const(op->d.cparam.paramfunc,
-										 llvm_pg_var_type("TypeExecEvalSubroutine"));
+					v_func = ///l_ptr_const(op->d.cparam.paramfunc,
+							///			 llvm_pg_var_type("TypeExecEvalSubroutine"));
+							l_ptr_const_step(d.cparam.paramfunc,
+										 llvm_pg_var_type(typesmod, "TypeExecEvalSubroutine"));
 
 					v_params[0] = v_state;
-					v_params[1] = l_ptr_const(op, l_ptr(StructExprEvalStep));
+					v_params[1] = ///l_ptr_const(op, l_ptr(g->StructExprEvalStep));
+								v_op;
 					v_params[2] = v_econtext;
 					l_call(b,
-						   LLVMGetFunctionType(ExecEvalSubroutineTemplate),
+						   LLVMGetFunctionType(g->ExecEvalSubroutineTemplate),
 						   v_func,
 						   v_params, lengthof(v_params), "");
 
@@ -1209,8 +1297,8 @@ llvm_compile_expr(ExprState *state)
 				}
 
 			case EEOP_PARAM_SET:
-				build_EvalXFunc(b, mod, "ExecEvalParamSet",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalParamSet",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -1221,21 +1309,23 @@ llvm_compile_expr(ExprState *state)
 					LLVMValueRef v_params[3];
 					LLVMValueRef v_ret;
 
-					v_func = l_ptr_const(op->d.sbsref_subscript.subscriptfunc,
-										 llvm_pg_var_type("TypeExecEvalBoolSubroutine"));
+					v_func = ///l_ptr_const(op->d.sbsref_subscript.subscriptfunc,
+								///		 llvm_pg_var_type("TypeExecEvalBoolSubroutine"));
+								l_ptr_const_step(d.sbsref_subscript.subscriptfunc,
+										 llvm_pg_var_type(typesmod, "TypeExecEvalBoolSubroutine"));
 
 					v_params[0] = v_state;
-					v_params[1] = l_ptr_const(op, l_ptr(StructExprEvalStep));
+					v_params[1] = v_op; /// l_ptr_const(op, l_ptr(g->StructExprEvalStep));
 					v_params[2] = v_econtext;
 					v_ret = l_call(b,
-								   LLVMGetFunctionType(ExecEvalBoolSubroutineTemplate),
+								   LLVMGetFunctionType(g->ExecEvalBoolSubroutineTemplate),
 								   v_func,
 								   v_params, lengthof(v_params), "");
-					v_ret = LLVMBuildZExt(b, v_ret, TypeStorageBool, "");
+					v_ret = LLVMBuildZExt(b, v_ret, g->TypeStorageBool, "");
 
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_ret,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									opblocks[opno + 1],
 									opblocks[jumpdone]);
 					break;
@@ -1248,14 +1338,16 @@ llvm_compile_expr(ExprState *state)
 					LLVMValueRef v_func;
 					LLVMValueRef v_params[3];
 
-					v_func = l_ptr_const(op->d.sbsref.subscriptfunc,
-										 llvm_pg_var_type("TypeExecEvalSubroutine"));
+					v_func = ///l_ptr_const(op->d.sbsref.subscriptfunc,
+							///			 llvm_pg_var_type("TypeExecEvalSubroutine"));
+							l_ptr_const_step(d.sbsref.subscriptfunc,
+										 llvm_pg_var_type(typesmod, "TypeExecEvalSubroutine"));
 
 					v_params[0] = v_state;
-					v_params[1] = l_ptr_const(op, l_ptr(StructExprEvalStep));
+					v_params[1] = v_op; ///l_ptr_const(op, l_ptr(g->StructExprEvalStep));
 					v_params[2] = v_econtext;
 					l_call(b,
-						   LLVMGetFunctionType(ExecEvalSubroutineTemplate),
+						   LLVMGetFunctionType(g->ExecEvalSubroutineTemplate),
 						   v_func,
 						   v_params, lengthof(v_params), "");
 
@@ -1270,13 +1362,17 @@ llvm_compile_expr(ExprState *state)
 					LLVMValueRef v_casenullp,
 								v_casenull;
 
-					v_casevaluep = l_ptr_const(op->d.casetest.value,
-											   l_ptr(TypeSizeT));
-					v_casenullp = l_ptr_const(op->d.casetest.isnull,
-											  l_ptr(TypeStorageBool));
-
-					v_casevalue = l_load(b, TypeSizeT, v_casevaluep, "");
-					v_casenull = l_load(b, TypeStorageBool, v_casenullp, "");
+					v_casevaluep = ///l_ptr_const(op->d.casetest.value,
+									///		   l_ptr(TypeSizeT));
+									l_ptr_const_step(d.casetest.value,
+											   l_ptr(g->TypeSizeT));
+					v_casenullp = ///l_ptr_const(op->d.casetest.isnull,
+								///			  l_ptr(g->TypeStorageBool));
+								l_ptr_const_step(d.casetest.isnull,
+											  l_ptr(g->TypeStorageBool));
+
+					v_casevalue = l_load(b, g->TypeSizeT, v_casevaluep, "");
+					v_casenull = l_load(b, g->TypeStorageBool, v_casenullp, "");
 					LLVMBuildStore(b, v_casevalue, v_resvaluep);
 					LLVMBuildStore(b, v_casenull, v_resnullp);
 
@@ -1291,12 +1387,12 @@ llvm_compile_expr(ExprState *state)
 
 					v_casevalue =
 						l_load_struct_gep(b,
-										  StructExprContext,
+										  g->StructExprContext,
 										  v_econtext,
 										  FIELDNO_EXPRCONTEXT_CASEDATUM, "");
 					v_casenull =
 						l_load_struct_gep(b,
-										  StructExprContext,
+										  g->StructExprContext,
 										  v_econtext,
 										  FIELDNO_EXPRCONTEXT_CASENULL, "");
 					LLVMBuildStore(b, v_casevalue, v_resvaluep);
@@ -1319,10 +1415,12 @@ llvm_compile_expr(ExprState *state)
 					b_notnull = l_bb_before_v(opblocks[opno + 1],
 											  "op.%d.readonly.notnull", opno);
 
-					v_nullp = l_ptr_const(op->d.make_readonly.isnull,
-										  l_ptr(TypeStorageBool));
+					v_nullp = ///l_ptr_const(op->d.make_readonly.isnull,
+								///		  l_ptr(g->TypeStorageBool));
+							l_ptr_const_step(d.make_readonly.isnull,
+										  l_ptr(g->TypeStorageBool));
 
-					v_null = l_load(b, TypeStorageBool, v_nullp, "");
+					v_null = l_load(b, g->TypeStorageBool, v_nullp, "");
 
 					/* store null isnull value in result */
 					LLVMBuildStore(b, v_null, v_resnullp);
@@ -1330,22 +1428,24 @@ llvm_compile_expr(ExprState *state)
 					/* check if value is NULL */
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_null,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									opblocks[opno + 1], b_notnull);
 
 					/* if value is not null, convert to RO datum */
 					LLVMPositionBuilderAtEnd(b, b_notnull);
 
-					v_valuep = l_ptr_const(op->d.make_readonly.value,
-										   l_ptr(TypeSizeT));
+					v_valuep = ///l_ptr_const(op->d.make_readonly.value,
+								///		   l_ptr(TypeSizeT));
+								l_ptr_const_step(d.make_readonly.value,
+										   l_ptr(g->TypeSizeT));
 
-					v_value = l_load(b, TypeSizeT, v_valuep, "");
+					v_value = l_load(b, g->TypeSizeT, v_valuep, "");
 
 					v_params[0] = v_value;
 					v_ret =
 						l_call(b,
-							   llvm_pg_var_func_type("MakeExpandedObjectReadOnlyInternal"),
-							   llvm_pg_func(mod, "MakeExpandedObjectReadOnlyInternal"),
+							   llvm_pg_var_func_type(context, "MakeExpandedObjectReadOnlyInternal"),
+							   llvm_pg_func(context, "MakeExpandedObjectReadOnlyInternal"),
 							   v_params, lengthof(v_params), "");
 					LLVMBuildStore(b, v_ret, v_resvaluep);
 
@@ -1386,40 +1486,43 @@ llvm_compile_expr(ExprState *state)
 					b_inputcall = l_bb_before_v(opblocks[opno + 1],
 												"op.%d.inputcall", opno);
 
-					v_fn_out = llvm_function_reference(context, b, mod, fcinfo_out);
-					v_fn_in = llvm_function_reference(context, b, mod, fcinfo_in);
-					v_fcinfo_out = l_ptr_const(fcinfo_out, l_ptr(StructFunctionCallInfoData));
-					v_fcinfo_in = l_ptr_const(fcinfo_in, l_ptr(StructFunctionCallInfoData));
-
+					v_fcinfo_out = l_load_member_value_by_offset(b,lc, v_op,
+								l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep ,d.iocoerce.fcinfo_data_out ));
+					v_fcinfo_in = l_load_member_value_by_offset(b,lc, v_op,
+								l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep ,d.iocoerce.fcinfo_data_in ));
+					v_fn_out = llvm_function_reference(context, b, mod, fcinfo_out, v_fcinfo_out);
+					v_fn_in = llvm_function_reference(context, b, mod, fcinfo_in, v_fcinfo_in);
+					///v_fcinfo_out = l_ptr_const(fcinfo_out, l_ptr(g->StructFunctionCallInfoData));
+					///v_fcinfo_in = l_ptr_const(fcinfo_in, l_ptr(g->StructFunctionCallInfoData));
 					v_fcinfo_in_isnullp =
 						l_struct_gep(b,
-									 StructFunctionCallInfoData,
+									 g->StructFunctionCallInfoData,
 									 v_fcinfo_in,
 									 FIELDNO_FUNCTIONCALLINFODATA_ISNULL,
 									 "v_fcinfo_in_isnull");
 
 					/* output functions are not called on nulls */
-					v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
+					v_resnull = l_load(b, g->TypeStorageBool, v_resnullp, "");
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									b_skipoutput,
 									b_calloutput);
 
 					LLVMPositionBuilderAtEnd(b, b_skipoutput);
-					v_output_skip = l_sizet_const(0);
+					v_output_skip = LLVMConstInt(g->TypeSizeT, 0, false);
 					LLVMBuildBr(b, b_input);
 
 					LLVMPositionBuilderAtEnd(b, b_calloutput);
-					v_resvalue = l_load(b, TypeSizeT, v_resvaluep, "");
+					v_resvalue = l_load(b, g->TypeSizeT, v_resvaluep, "");
 
 					/* set arg[0] */
 					LLVMBuildStore(b,
 								   v_resvalue,
-								   l_funcvaluep(b, v_fcinfo_out, 0));
+								   l_funcvaluep(b, v_fcinfo_out, 0, g));
 					LLVMBuildStore(b,
-								   l_sbool_const(0),
-								   l_funcnullp(b, v_fcinfo_out, 0));
+								   LLVMConstInt(g->TypeStorageBool, (int)(0), false),
+								   l_funcnullp(b, v_fcinfo_out, 0, g));
 					/* and call output function (can never return NULL) */
 					v_output = l_call(b,
 									  LLVMGetFunctionType(v_fn_out),
@@ -1441,7 +1544,7 @@ llvm_compile_expr(ExprState *state)
 						incoming_values[1] = v_output;
 						incoming_blocks[1] = b_calloutput;
 
-						v_output = LLVMBuildPhi(b, TypeSizeT, "output");
+						v_output = LLVMBuildPhi(b, g->TypeSizeT, "output");
 						LLVMAddIncoming(v_output,
 										incoming_values, incoming_blocks,
 										lengthof(incoming_blocks));
@@ -1455,7 +1558,7 @@ llvm_compile_expr(ExprState *state)
 					{
 						LLVMBuildCondBr(b,
 										LLVMBuildICmp(b, LLVMIntEQ, v_output,
-													  l_sizet_const(0), ""),
+													  LLVMConstInt(g->TypeSizeT, 0, false), ""),
 										opblocks[opno + 1],
 										b_inputcall);
 					}
@@ -1468,15 +1571,15 @@ llvm_compile_expr(ExprState *state)
 					/* set arguments */
 					/* arg0: output */
 					LLVMBuildStore(b, v_output,
-								   l_funcvaluep(b, v_fcinfo_in, 0));
+								   l_funcvaluep(b, v_fcinfo_in, 0, g));
 					LLVMBuildStore(b, v_resnull,
-								   l_funcnullp(b, v_fcinfo_in, 0));
+								   l_funcnullp(b, v_fcinfo_in, 0, g));
 
 					/* arg1: ioparam: preset in execExpr.c */
 					/* arg2: typmod: preset in execExpr.c  */
 
 					/* reset fcinfo_in->isnull */
-					LLVMBuildStore(b, l_sbool_const(0), v_fcinfo_in_isnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_fcinfo_in_isnullp);
 					/* and call function */
 					v_retval = l_call(b,
 									  LLVMGetFunctionType(v_fn_in),
@@ -1490,8 +1593,8 @@ llvm_compile_expr(ExprState *state)
 				}
 
 			case EEOP_IOCOERCE_SAFE:
-				build_EvalXFunc(b, mod, "ExecEvalCoerceViaIOSafe",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalCoerceViaIOSafe",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -1523,15 +1626,17 @@ llvm_compile_expr(ExprState *state)
 					b_bothargnull = l_bb_before_v(opblocks[opno + 1], "op.%d.bothargnull", opno);
 					b_anyargnull = l_bb_before_v(opblocks[opno + 1], "op.%d.anyargnull", opno);
 
-					v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
+					v_fcinfo = /// l_ptr_const(fcinfo, l_ptr(g->StructFunctionCallInfoData));
+														l_load_member_value_by_offset(b,lc, v_op,
+								l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep ,d.func.fcinfo_data ));
 
 					/* load args[0|1].isnull for both arguments */
-					v_argnull0 = l_funcnull(b, v_fcinfo, 0);
+					v_argnull0 = l_funcnull(b, v_fcinfo, 0, g);
 					v_argisnull0 = LLVMBuildICmp(b, LLVMIntEQ, v_argnull0,
-												 l_sbool_const(1), "");
-					v_argnull1 = l_funcnull(b, v_fcinfo, 1);
+												 LLVMConstInt(g->TypeStorageBool, (int)(1), false), "");
+					v_argnull1 = l_funcnull(b, v_fcinfo, 1, g);
 					v_argisnull1 = LLVMBuildICmp(b, LLVMIntEQ, v_argnull1,
-												 l_sbool_const(1), "");
+												 LLVMConstInt(g->TypeStorageBool, (int)(1), false), "");
 
 					v_anyargisnull = LLVMBuildOr(b, v_argisnull0, v_argisnull1, "");
 					v_bothargisnull = LLVMBuildAnd(b, v_argisnull0, v_argisnull1, "");
@@ -1554,27 +1659,27 @@ llvm_compile_expr(ExprState *state)
 
 					/* Both NULL? Then is not distinct... */
 					LLVMPositionBuilderAtEnd(b, b_bothargnull);
-					LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_resnullp);
 					if (opcode == EEOP_NOT_DISTINCT)
-						LLVMBuildStore(b, l_sizet_const(1), v_resvaluep);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 1, false), v_resvaluep);
 					else
-						LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_resvaluep);
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
 
 					/* Only one is NULL? Then is distinct... */
 					LLVMPositionBuilderAtEnd(b, b_anyargnull);
-					LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_resnullp);
 					if (opcode == EEOP_NOT_DISTINCT)
-						LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_resvaluep);
 					else
-						LLVMBuildStore(b, l_sizet_const(1), v_resvaluep);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 1, false), v_resvaluep);
 					LLVMBuildBr(b, opblocks[opno + 1]);
 
 					/* neither argument is null: compare */
 					LLVMPositionBuilderAtEnd(b, b_noargnull);
 
-					v_result = BuildV1Call(context, b, mod, fcinfo,
+					v_result = BuildV1CallLLVM(context, b, mod, fcinfo, v_fcinfo,
 										   &v_fcinfo_isnull);
 
 					if (opcode == EEOP_DISTINCT)
@@ -1584,8 +1689,8 @@ llvm_compile_expr(ExprState *state)
 							LLVMBuildZExt(b,
 										  LLVMBuildICmp(b, LLVMIntEQ,
 														v_result,
-														l_sizet_const(0), ""),
-										  TypeSizeT, "");
+														LLVMConstInt(g->TypeSizeT, 0, false), ""),
+										  g->TypeSizeT, "");
 					}
 
 					LLVMBuildStore(b, v_fcinfo_isnull, v_resnullp);
@@ -1618,21 +1723,23 @@ llvm_compile_expr(ExprState *state)
 					b_argsequal = l_bb_before_v(opblocks[opno + 1],
 												"b.%d.argsequal", opno);
 
-					v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
+					v_fcinfo = /// l_ptr_const(fcinfo, l_ptr(g->StructFunctionCallInfoData));
+								l_load_member_value_by_offset(b,lc, v_op,
+								l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep ,d.func.fcinfo_data));
 
 					/* save original arg[0] */
-					v_arg0 = l_funcvalue(b, v_fcinfo, 0);
+					v_arg0 = l_funcvalue(b, v_fcinfo, 0, g);
 
 					/* if either argument is NULL they can't be equal */
-					v_argnull0 = l_funcnull(b, v_fcinfo, 0);
-					v_argnull1 = l_funcnull(b, v_fcinfo, 1);
+					v_argnull0 = l_funcnull(b, v_fcinfo, 0, g);
+					v_argnull1 = l_funcnull(b, v_fcinfo, 1, g);
 
 					v_anyargisnull =
 						LLVMBuildOr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_argnull0,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									LLVMBuildICmp(b, LLVMIntEQ, v_argnull1,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									"");
 
 					LLVMBuildCondBr(b, v_anyargisnull, b_hasnull, b_nonull);
@@ -1662,14 +1769,14 @@ llvm_compile_expr(ExprState *state)
 						v_params[0] = v_arg0;
 						v_arg0_ro =
 							l_call(b,
-								   llvm_pg_var_func_type("MakeExpandedObjectReadOnlyInternal"),
-								   llvm_pg_func(mod, "MakeExpandedObjectReadOnlyInternal"),
+								   llvm_pg_var_func_type(context, "MakeExpandedObjectReadOnlyInternal"),
+								   llvm_pg_func(context, "MakeExpandedObjectReadOnlyInternal"),
 								   v_params, lengthof(v_params), "");
 						LLVMBuildStore(b, v_arg0_ro,
-									   l_funcvaluep(b, v_fcinfo, 0));
+									   l_funcvaluep(b, v_fcinfo, 0, g));
 					}
 
-					v_retval = BuildV1Call(context, b, mod, fcinfo, &v_fcinfo_isnull);
+					v_retval = BuildV1CallLLVM(context, b, mod, fcinfo, v_fcinfo, &v_fcinfo_isnull);
 
 					/*
 					 * If result not null and arguments are equal return null,
@@ -1679,39 +1786,39 @@ llvm_compile_expr(ExprState *state)
 					v_argsequal = LLVMBuildAnd(b,
 											   LLVMBuildICmp(b, LLVMIntEQ,
 															 v_fcinfo_isnull,
-															 l_sbool_const(0),
+															 LLVMConstInt(g->TypeStorageBool, (int)(0), false),
 															 ""),
 											   LLVMBuildICmp(b, LLVMIntEQ,
 															 v_retval,
-															 l_sizet_const(1),
+															 LLVMConstInt(g->TypeSizeT, 1, false),
 															 ""),
 											   "");
 					LLVMBuildCondBr(b, v_argsequal, b_argsequal, b_hasnull);
 
 					/* build block setting result to NULL, if args are equal */
 					LLVMPositionBuilderAtEnd(b, b_argsequal);
-					LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
-					LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(1), false), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_resvaluep);
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
 					break;
 				}
 
 			case EEOP_SQLVALUEFUNCTION:
-				build_EvalXFunc(b, mod, "ExecEvalSQLValueFunction",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalSQLValueFunction",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_CURRENTOFEXPR:
-				build_EvalXFunc(b, mod, "ExecEvalCurrentOfExpr",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalCurrentOfExpr",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_NEXTVALUEEXPR:
-				build_EvalXFunc(b, mod, "ExecEvalNextValueExpr",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalNextValueExpr",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -1730,11 +1837,11 @@ llvm_compile_expr(ExprState *state)
 					 * OLD/NEW row doesn't exist, skip that and return NULL.
 					 */
 					v_flagsp = l_struct_gep(b,
-											StructExprState,
+											g->StructExprState,
 											v_state,
 											FIELDNO_EXPRSTATE_FLAGS,
 											"v.state.flags");
-					v_flags = l_load(b, TypeStorageBool, v_flagsp, "");
+					v_flags = l_load(b, g->TypeStorageBool, v_flagsp, "");
 
 					v_nullflag = l_int8_const(lc, op->d.returningexpr.nullflag);
 
@@ -1742,33 +1849,33 @@ llvm_compile_expr(ExprState *state)
 									LLVMBuildICmp(b, LLVMIntEQ,
 												  LLVMBuildAnd(b, v_flags,
 															   v_nullflag, ""),
-												  l_sbool_const(0), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(0), false), ""),
 									opblocks[opno + 1], b_isnull);
 
 					LLVMPositionBuilderAtEnd(b, b_isnull);
 
-					LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
-					LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_resvaluep);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(1), false), v_resnullp);
 
 					LLVMBuildBr(b, opblocks[op->d.returningexpr.jumpdone]);
 					break;
 				}
 
 			case EEOP_ARRAYEXPR:
-				build_EvalXFunc(b, mod, "ExecEvalArrayExpr",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalArrayExpr",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_ARRAYCOERCE:
-				build_EvalXFunc(b, mod, "ExecEvalArrayCoerce",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalArrayCoerce",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_ROW:
-				build_EvalXFunc(b, mod, "ExecEvalRow",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalRow",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -1779,6 +1886,7 @@ llvm_compile_expr(ExprState *state)
 					LLVMBasicBlockRef b_null;
 					LLVMBasicBlockRef b_compare;
 					LLVMBasicBlockRef b_compare_result;
+					LLVMValueRef v_fcinfo;
 
 					LLVMValueRef v_retval;
 
@@ -1790,34 +1898,34 @@ llvm_compile_expr(ExprState *state)
 						l_bb_before_v(opblocks[opno + 1],
 									  "op.%d.row-compare-result",
 									  opno);
-
+					v_fcinfo = l_load_member_value_by_offset(b, lc, v_op,
+								l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep ,d.rowcompare_step.fcinfo_data));
 					/*
 					 * If function is strict, and either arg is null, we're
 					 * done.
 					 */
 					if (op->d.rowcompare_step.finfo->fn_strict)
 					{
-						LLVMValueRef v_fcinfo;
 						LLVMValueRef v_argnull0;
 						LLVMValueRef v_argnull1;
 						LLVMValueRef v_anyargisnull;
 
-						v_fcinfo = l_ptr_const(fcinfo,
-											   l_ptr(StructFunctionCallInfoData));
+						///v_fcinfo = l_ptr_const(fcinfo,
+						///					   l_ptr(g->StructFunctionCallInfoData));
 
-						v_argnull0 = l_funcnull(b, v_fcinfo, 0);
-						v_argnull1 = l_funcnull(b, v_fcinfo, 1);
+						v_argnull0 = l_funcnull(b, v_fcinfo, 0, g);
+						v_argnull1 = l_funcnull(b, v_fcinfo, 1, g);
 
 						v_anyargisnull =
 							LLVMBuildOr(b,
 										LLVMBuildICmp(b,
 													  LLVMIntEQ,
 													  v_argnull0,
-													  l_sbool_const(1),
+													  LLVMConstInt(g->TypeStorageBool, (int)(1), false),
 													  ""),
 										LLVMBuildICmp(b, LLVMIntEQ,
 													  v_argnull1,
-													  l_sbool_const(1), ""),
+													  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 										"");
 
 						LLVMBuildCondBr(b, v_anyargisnull, b_null, b_compare);
@@ -1831,7 +1939,7 @@ llvm_compile_expr(ExprState *state)
 					LLVMPositionBuilderAtEnd(b, b_compare);
 
 					/* call function */
-					v_retval = BuildV1Call(context, b, mod, fcinfo,
+					v_retval = BuildV1CallLLVM(context, b, mod, fcinfo, v_fcinfo,
 										   &v_fcinfo_isnull);
 					LLVMBuildStore(b, v_retval, v_resvaluep);
 
@@ -1840,7 +1948,7 @@ llvm_compile_expr(ExprState *state)
 									LLVMBuildICmp(b,
 												  LLVMIntEQ,
 												  v_fcinfo_isnull,
-												  l_sbool_const(0),
+												  LLVMConstInt(g->TypeStorageBool, (int)(0), false),
 												  ""),
 									b_compare_result,
 									b_null);
@@ -1853,7 +1961,7 @@ llvm_compile_expr(ExprState *state)
 									LLVMBuildICmp(b,
 												  LLVMIntEQ,
 												  v_retval,
-												  l_sizet_const(0), ""),
+												  LLVMConstInt(g->TypeSizeT, 0, false), ""),
 									opblocks[opno + 1],
 									opblocks[op->d.rowcompare_step.jumpdone]);
 
@@ -1862,7 +1970,7 @@ llvm_compile_expr(ExprState *state)
 					 * result.
 					 */
 					LLVMPositionBuilderAtEnd(b, b_null);
-					LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(1), false), v_resnullp);
 					LLVMBuildBr(b, opblocks[op->d.rowcompare_step.jumpnull]);
 
 					break;
@@ -1883,7 +1991,7 @@ llvm_compile_expr(ExprState *state)
 					 */
 					v_cmpresult =
 						LLVMBuildTrunc(b,
-									   l_load(b, TypeSizeT, v_resvaluep, ""),
+									   l_load(b, g->TypeSizeT, v_resvaluep, ""),
 									   LLVMInt32TypeInContext(lc), "");
 
 					switch (cmptype)
@@ -1912,9 +2020,9 @@ llvm_compile_expr(ExprState *state)
 											 v_cmpresult,
 											 l_int32_const(lc, 0),
 											 "");
-					v_result = LLVMBuildZExt(b, v_result, TypeSizeT, "");
+					v_result = LLVMBuildZExt(b, v_result, g->TypeSizeT, "");
 
-					LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_resnullp);
 					LLVMBuildStore(b, v_result, v_resvaluep);
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
@@ -1922,26 +2030,26 @@ llvm_compile_expr(ExprState *state)
 				}
 
 			case EEOP_MINMAX:
-				build_EvalXFunc(b, mod, "ExecEvalMinMax",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalMinMax",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_FIELDSELECT:
-				build_EvalXFunc(b, mod, "ExecEvalFieldSelect",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalFieldSelect",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_FIELDSTORE_DEFORM:
-				build_EvalXFunc(b, mod, "ExecEvalFieldStoreDeForm",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalFieldStoreDeForm",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_FIELDSTORE_FORM:
-				build_EvalXFunc(b, mod, "ExecEvalFieldStoreForm",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalFieldStoreForm",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -1952,13 +2060,13 @@ llvm_compile_expr(ExprState *state)
 					LLVMValueRef v_casenullp,
 								v_casenull;
 
-					v_casevaluep = l_ptr_const(op->d.casetest.value,
-											   l_ptr(TypeSizeT));
-					v_casenullp = l_ptr_const(op->d.casetest.isnull,
-											  l_ptr(TypeStorageBool));
+					v_casevaluep = l_ptr_const_step(d.casetest.value,
+											   l_ptr(g->TypeSizeT));
+					v_casenullp = l_ptr_const_step(d.casetest.isnull,
+											  l_ptr(g->TypeStorageBool));
 
-					v_casevalue = l_load(b, TypeSizeT, v_casevaluep, "");
-					v_casenull = l_load(b, TypeStorageBool, v_casenullp, "");
+					v_casevalue = l_load(b, g->TypeSizeT, v_casevaluep, "");
+					v_casenull = l_load(b, g->TypeStorageBool, v_casenullp, "");
 					LLVMBuildStore(b, v_casevalue, v_resvaluep);
 					LLVMBuildStore(b, v_casenull, v_resnullp);
 
@@ -1973,13 +2081,13 @@ llvm_compile_expr(ExprState *state)
 
 					v_casevalue =
 						l_load_struct_gep(b,
-										  StructExprContext,
+										  g->StructExprContext,
 										  v_econtext,
 										  FIELDNO_EXPRCONTEXT_DOMAINDATUM,
 										  "");
 					v_casenull =
 						l_load_struct_gep(b,
-										  StructExprContext,
+										  g->StructExprContext,
 										  v_econtext,
 										  FIELDNO_EXPRCONTEXT_DOMAINNULL,
 										  "");
@@ -1991,14 +2099,14 @@ llvm_compile_expr(ExprState *state)
 				}
 
 			case EEOP_DOMAIN_NOTNULL:
-				build_EvalXFunc(b, mod, "ExecEvalConstraintNotNull",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalConstraintNotNull",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_DOMAIN_CHECK:
-				build_EvalXFunc(b, mod, "ExecEvalConstraintCheck",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalConstraintCheck",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -2006,10 +2114,10 @@ llvm_compile_expr(ExprState *state)
 				{
 					LLVMValueRef v_initvalue;
 
-					v_initvalue = l_sizet_const(op->d.hashdatum_initvalue.init_value);
+					v_initvalue = LLVMConstInt(g->TypeSizeT, op->d.hashdatum_initvalue.init_value, false);
 
 					LLVMBuildStore(b, v_initvalue, v_resvaluep);
-					LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_resnullp);
 					LLVMBuildBr(b, opblocks[opno + 1]);
 					break;
 				}
@@ -2044,25 +2152,31 @@ llvm_compile_expr(ExprState *state)
 						LLVMValueRef v_tmp2;
 						LLVMValueRef tmp;
 
-						tmp = l_ptr_const(&op->d.hashdatum.iresult->value,
-										  l_ptr(TypeSizeT));
+						///tmp = l_ptr_const(&op->d.hashdatum.iresult->value,
+						///				  l_ptr(TypeSizeT));
+						tmp = l_ptr_const_step(d.hashdatum.iresult, l_ptr(g->StructNullableDatum));
+						tmp = l_struct_gep(b, g->StructNullableDatum, tmp,
+												  FIELDNO_NULLABLE_DATUM_DATUM,
+												  "");
+
+						///l_ptr(TypeSizeT));
 
 						/*
 						 * Fetch the previously hashed value from where the
 						 * previous hash operation stored it.
 						 */
-						v_prevhash = l_load(b, TypeSizeT, tmp, "prevhash");
+						v_prevhash = l_load(b, g->TypeSizeT, tmp, "prevhash");
 
 						/*
 						 * Rotate bits left by 1 bit.  Be careful not to
 						 * overflow uint32 when working with size_t.
 						 */
-						v_tmp1 = LLVMBuildShl(b, v_prevhash, l_sizet_const(1),
+						v_tmp1 = LLVMBuildShl(b, v_prevhash, LLVMConstInt(g->TypeSizeT, 1, false),
 											  "");
 						v_tmp1 = LLVMBuildAnd(b, v_tmp1,
-											  l_sizet_const(0xffffffff), "");
+											  LLVMConstInt(g->TypeSizeT, 0xffffffff, false), "");
 						v_tmp2 = LLVMBuildLShr(b, v_prevhash,
-											   l_sizet_const(31), "");
+											   LLVMConstInt(g->TypeSizeT, 31, false), "");
 						v_prevhash = LLVMBuildOr(b, v_tmp1, v_tmp2,
 												 "rotatedhash");
 					}
@@ -2079,8 +2193,10 @@ llvm_compile_expr(ExprState *state)
 					if (fcinfo->nargs != 1)
 						elog(ERROR, "incorrect number of function arguments");
 
-					v_fcinfo = l_ptr_const(fcinfo,
-										   l_ptr(StructFunctionCallInfoData));
+					v_fcinfo = ///l_ptr_const(fcinfo,
+								///		   l_ptr(g->StructFunctionCallInfoData));
+								l_load_member_value_by_offset(b, lc, v_op,
+								l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep, d.hashdatum.fcinfo_data));
 
 					b_checkargnull = l_bb_before_v(b_ifnotnull,
 												   "b.%d.isnull.0", opno);
@@ -2104,8 +2220,8 @@ llvm_compile_expr(ExprState *state)
 						 * In strict node, NULL inputs result in NULL.  Save
 						 * the NULL result and goto jumpdone.
 						 */
-						LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
-						LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(1), false), v_resnullp);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_resvaluep);
 						LLVMBuildBr(b, opblocks[op->d.hashdatum.jumpdone]);
 					}
 					else
@@ -2117,7 +2233,7 @@ llvm_compile_expr(ExprState *state)
 						LLVMPositionBuilderAtEnd(b, b_ifnullblock);
 
 
-						LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_resnullp);
 
 						if (opcode == EEOP_HASHDATUM_NEXT32)
 						{
@@ -2137,7 +2253,7 @@ llvm_compile_expr(ExprState *state)
 							 * Store a zero Datum when the Datum to hash is
 							 * NULL
 							 */
-							LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
+							LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_resvaluep);
 						}
 
 						LLVMBuildBr(b, opblocks[opno + 1]);
@@ -2146,12 +2262,12 @@ llvm_compile_expr(ExprState *state)
 					LLVMPositionBuilderAtEnd(b, b_checkargnull);
 
 					/* emit code to check if the input parameter is NULL */
-					v_argisnull = l_funcnull(b, v_fcinfo, 0);
+					v_argisnull = l_funcnull(b, v_fcinfo, 0, g);
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b,
 												  LLVMIntEQ,
 												  v_argisnull,
-												  l_sbool_const(1),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false),
 												  ""),
 									b_ifnullblock,
 									b_ifnotnull);
@@ -2169,31 +2285,34 @@ llvm_compile_expr(ExprState *state)
 						LLVMValueRef v_tmp2;
 						LLVMValueRef tmp;
 
-						tmp = l_ptr_const(&op->d.hashdatum.iresult->value,
-										  l_ptr(TypeSizeT));
-
+						///tmp = l_ptr_const(&op->d.hashdatum.iresult->value,
+						///				  l_ptr(TypeSizeT));
+						tmp = l_ptr_const_step(d.hashdatum.iresult, l_ptr(g->StructNullableDatum));
+						tmp = l_struct_gep(b, g->StructNullableDatum, tmp,
+												  FIELDNO_NULLABLE_DATUM_DATUM,
+												  "");
 						/*
 						 * Fetch the previously hashed value from where the
 						 * previous hash operation stored it.
 						 */
-						v_prevhash = l_load(b, TypeSizeT, tmp, "prevhash");
+						v_prevhash = l_load(b, g->TypeSizeT, tmp, "prevhash");
 
 						/*
 						 * Rotate bits left by 1 bit.  Be careful not to
 						 * overflow uint32 when working with size_t.
 						 */
-						v_tmp1 = LLVMBuildShl(b, v_prevhash, l_sizet_const(1),
+						v_tmp1 = LLVMBuildShl(b, v_prevhash, LLVMConstInt(g->TypeSizeT, 1, false),
 											  "");
 						v_tmp1 = LLVMBuildAnd(b, v_tmp1,
-											  l_sizet_const(0xffffffff), "");
+											  LLVMConstInt(g->TypeSizeT, 0xffffffff, false), "");
 						v_tmp2 = LLVMBuildLShr(b, v_prevhash,
-											   l_sizet_const(31), "");
+											   LLVMConstInt(g->TypeSizeT, 31, false), "");
 						v_prevhash = LLVMBuildOr(b, v_tmp1, v_tmp2,
 												 "rotatedhash");
 					}
 
 					/* call the hash function */
-					v_retval = BuildV1Call(context, b, mod, fcinfo,
+					v_retval = BuildV1CallLLVM(context, b, mod, fcinfo, v_fcinfo,
 										   &v_fcinfo_isnull);
 
 					/*
@@ -2206,45 +2325,45 @@ llvm_compile_expr(ExprState *state)
 												"xorhash");
 
 					LLVMBuildStore(b, v_retval, v_resvaluep);
-					LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_resnullp);
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
 					break;
 				}
 
 			case EEOP_CONVERT_ROWTYPE:
-				build_EvalXFunc(b, mod, "ExecEvalConvertRowtype",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalConvertRowtype",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_SCALARARRAYOP:
-				build_EvalXFunc(b, mod, "ExecEvalScalarArrayOp",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalScalarArrayOp",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_HASHED_SCALARARRAYOP:
-				build_EvalXFunc(b, mod, "ExecEvalHashedScalarArrayOp",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalHashedScalarArrayOp",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_XMLEXPR:
-				build_EvalXFunc(b, mod, "ExecEvalXmlExpr",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalXmlExpr",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_JSON_CONSTRUCTOR:
-				build_EvalXFunc(b, mod, "ExecEvalJsonConstructor",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalJsonConstructor",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_IS_JSON:
-				build_EvalXFunc(b, mod, "ExecEvalJsonIsPredicate",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalJsonIsPredicate",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -2257,8 +2376,8 @@ llvm_compile_expr(ExprState *state)
 					 * Call ExecEvalJsonExprPath().  It returns the address of
 					 * the step to perform next.
 					 */
-					v_ret = build_EvalXFunc(b, mod, "ExecEvalJsonExprPath",
-											v_state, op, v_econtext);
+					v_ret = build_EvalXFunc(b, context, "ExecEvalJsonExprPath",
+											v_state, v_op, v_econtext);
 
 					/*
 					 * Build a switch to map the return value (v_ret above),
@@ -2343,15 +2462,15 @@ llvm_compile_expr(ExprState *state)
 				}
 
 			case EEOP_JSONEXPR_COERCION:
-				build_EvalXFunc(b, mod, "ExecEvalJsonCoercion",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalJsonCoercion",
+								v_state, v_op, v_econtext);
 
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_JSONEXPR_COERCION_FINISH:
-				build_EvalXFunc(b, mod, "ExecEvalJsonCoercionFinish",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalJsonCoercionFinish",
+								v_state, v_op);
 
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
@@ -2365,8 +2484,8 @@ llvm_compile_expr(ExprState *state)
 					v_aggno = l_int32_const(lc, op->d.aggref.aggno);
 
 					/* load agg value / null */
-					value = l_load_gep1(b, TypeSizeT, v_aggvalues, v_aggno, "aggvalue");
-					isnull = l_load_gep1(b, TypeStorageBool, v_aggnulls, v_aggno, "aggnull");
+					value = l_load_gep1(b, g->TypeSizeT, v_aggvalues, v_aggno, "aggvalue");
+					isnull = l_load_gep1(b, g->TypeStorageBool, v_aggnulls, v_aggno, "aggnull");
 
 					/* and store result */
 					LLVMBuildStore(b, value, v_resvaluep);
@@ -2377,8 +2496,8 @@ llvm_compile_expr(ExprState *state)
 				}
 
 			case EEOP_GROUPING_FUNC:
-				build_EvalXFunc(b, mod, "ExecEvalGroupingFunc",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalGroupingFunc",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -2395,14 +2514,17 @@ llvm_compile_expr(ExprState *state)
 					 * up in ExecInitWindowAgg() after initializing the
 					 * expression). So load it from memory each time round.
 					 */
-					v_wfuncnop = l_ptr_const(&wfunc->wfuncno,
-											 l_ptr(LLVMInt32TypeInContext(lc)));
+					v_wfuncnop = ///l_ptr_const(&wfunc->wfuncno,
+								///			 l_ptr(LLVMInt32TypeInContext(lc)));
+								l_ptr_const_step(d.window_func.wfstate, l_ptr(g->StructWindowFuncExprState));
+					v_wfuncnop = l_struct_member_ptr_by_offset(b, lc, v_wfuncnop, offsetof(WindowFuncExprState, wfuncno) );
+
 					v_wfuncno = l_load(b, LLVMInt32TypeInContext(lc), v_wfuncnop, "v_wfuncno");
 
 					/* load window func value / null */
-					value = l_load_gep1(b, TypeSizeT, v_aggvalues, v_wfuncno,
+					value = l_load_gep1(b, g->TypeSizeT, v_aggvalues, v_wfuncno,
 										"windowvalue");
-					isnull = l_load_gep1(b, TypeStorageBool, v_aggnulls, v_wfuncno,
+					isnull = l_load_gep1(b, g->TypeStorageBool, v_aggnulls, v_wfuncno,
 										 "windownull");
 
 					LLVMBuildStore(b, value, v_resvaluep);
@@ -2413,14 +2535,14 @@ llvm_compile_expr(ExprState *state)
 				}
 
 			case EEOP_MERGE_SUPPORT_FUNC:
-				build_EvalXFunc(b, mod, "ExecEvalMergeSupportFunc",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalMergeSupportFunc",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_SUBPLAN:
-				build_EvalXFunc(b, mod, "ExecEvalSubPlan",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalSubPlan",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -2434,41 +2556,53 @@ llvm_compile_expr(ExprState *state)
 					LLVMValueRef v_fcinfo_isnull;
 					LLVMValueRef v_tmpcontext;
 					LLVMValueRef v_oldcontext;
+					LLVMValueRef v_fcinfo;
 
 					if (opcode == EEOP_AGG_STRICT_DESERIALIZE)
 					{
-						LLVMValueRef v_fcinfo;
 						LLVMValueRef v_argnull0;
 						LLVMBasicBlockRef b_deserialize;
 
 						b_deserialize = l_bb_before_v(opblocks[opno + 1],
 													  "op.%d.deserialize", opno);
 
-						v_fcinfo = l_ptr_const(fcinfo,
-											   l_ptr(StructFunctionCallInfoData));
-						v_argnull0 = l_funcnull(b, v_fcinfo, 0);
+						v_fcinfo = ///l_ptr_const(fcinfo,
+									///		   l_ptr(g->StructFunctionCallInfoData));
+									l_load_member_value_by_offset(b, lc, v_op,
+									l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep, d.agg_deserialize.fcinfo_data));
+						v_argnull0 = l_funcnull(b, v_fcinfo, 0, g);
 
 						LLVMBuildCondBr(b,
 										LLVMBuildICmp(b,
 													  LLVMIntEQ,
 													  v_argnull0,
-													  l_sbool_const(1),
+													  LLVMConstInt(g->TypeStorageBool, (int)(1), false),
 													  ""),
 										opblocks[op->d.agg_deserialize.jumpnull],
 										b_deserialize);
 						LLVMPositionBuilderAtEnd(b, b_deserialize);
 					}
+					else
+					{
+						v_fcinfo = l_load_member_value_by_offset(b, lc, v_op,
+									l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep, d.agg_deserialize.fcinfo_data));
+					}
 
 					aggstate = castNode(AggState, state->parent);
 					fcinfo = op->d.agg_deserialize.fcinfo_data;
 
-					v_tmpcontext =
-						l_ptr_const(aggstate->tmpcontext->ecxt_per_tuple_memory,
-									l_ptr(StructMemoryContextData));
-					v_oldcontext = l_mcxt_switch(mod, b, v_tmpcontext);
-					v_retval = BuildV1Call(context, b, mod, fcinfo,
+					///v_tmpcontext =
+						///l_ptr_const(aggstate->tmpcontext->ecxt_per_tuple_memory,
+						///			l_ptr(g->StructMemoryContextData));
+					///	l_load_struct_gep(b, StructExprState, v_state, FIELDNO_EXPRSTATE_PARENT,"");
+					v_tmpcontext = l_load_struct_gep(b, g->StructExprState, v_state, FIELDNO_EXPRSTATE_PARENT,"");
+					v_tmpcontext = l_load_struct_gep(b, g->StructAggState, v_tmpcontext, FIELDNO_AGGSTATE_TMPCONTEXT,"");
+					v_tmpcontext = l_load_struct_gep(b, g->StructExprContext, v_tmpcontext, FIELDNO_EXPRCONTEXT_PERTUPLEMEMORY,"");
+
+					v_oldcontext = l_mcxt_switch(mod, b, v_tmpcontext, g);
+					v_retval = BuildV1CallLLVM(context, b, mod, fcinfo, v_fcinfo,
 										   &v_fcinfo_isnull);
-					l_mcxt_switch(mod, b, v_oldcontext);
+					l_mcxt_switch(mod, b, v_oldcontext, g);
 
 					LLVMBuildStore(b, v_retval, v_resvaluep);
 					LLVMBuildStore(b, v_fcinfo_isnull, v_resnullp);
@@ -2492,8 +2626,10 @@ llvm_compile_expr(ExprState *state)
 					Assert(nargs > 0);
 
 					jumpnull = op->d.agg_strict_input_check.jumpnull;
-					v_argsp = l_ptr_const(args, l_ptr(StructNullableDatum));
-					v_nullsp = l_ptr_const(nulls, l_ptr(TypeStorageBool));
+					v_argsp = ///l_ptr_const(args, l_ptr(g->StructNullableDatum));
+							l_ptr_const_step(d.agg_strict_input_check.args, l_ptr(g->StructNullableDatum));
+					v_nullsp = ///l_ptr_const(nulls, l_ptr(g->TypeStorageBool));
+							l_ptr_const_step(d.agg_strict_input_check.nulls, l_ptr(g->TypeStorageBool));
 
 					/* create blocks for checking args */
 					b_checknulls = palloc(sizeof(LLVMBasicBlockRef *) * nargs);
@@ -2522,14 +2658,14 @@ llvm_compile_expr(ExprState *state)
 							b_argnotnull = b_checknulls[argno + 1];
 
 						if (opcode == EEOP_AGG_STRICT_INPUT_CHECK_NULLS)
-							v_argisnull = l_load_gep1(b, TypeStorageBool, v_nullsp, v_argno, "");
+							v_argisnull = l_load_gep1(b, g->TypeStorageBool, v_nullsp, v_argno, "");
 						else
 						{
 							LLVMValueRef v_argn;
 
-							v_argn = l_gep(b, StructNullableDatum, v_argsp, &v_argno, 1, "");
+							v_argn = l_gep(b, g->StructNullableDatum, v_argsp, &v_argno, 1, "");
 							v_argisnull =
-								l_load_struct_gep(b, StructNullableDatum, v_argn,
+								l_load_struct_gep(b, g->StructNullableDatum, v_argn,
 												  FIELDNO_NULLABLE_DATUM_ISNULL,
 												  "");
 						}
@@ -2538,7 +2674,7 @@ llvm_compile_expr(ExprState *state)
 										LLVMBuildICmp(b,
 													  LLVMIntEQ,
 													  v_argisnull,
-													  l_sbool_const(1), ""),
+													  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 										opblocks[jumpnull],
 										b_argnotnull);
 					}
@@ -2561,23 +2697,23 @@ llvm_compile_expr(ExprState *state)
 					 * [op->d.agg_plain_pergroup_nullcheck.setoff];
 					 */
 					v_aggstatep = LLVMBuildBitCast(b, v_parent,
-												   l_ptr(StructAggState), "");
+												   l_ptr(g->StructAggState), "");
 
 					v_allpergroupsp = l_load_struct_gep(b,
-														StructAggState,
+														g->StructAggState,
 														v_aggstatep,
 														FIELDNO_AGGSTATE_ALL_PERGROUPS,
 														"aggstate.all_pergroups");
 
 					v_setoff = l_int32_const(lc, op->d.agg_plain_pergroup_nullcheck.setoff);
 
-					v_pergroup_allaggs = l_load_gep1(b, l_ptr(StructAggStatePerGroupData),
+					v_pergroup_allaggs = l_load_gep1(b, l_ptr(g->StructAggStatePerGroupData),
 													 v_allpergroupsp, v_setoff, "");
 
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ,
-												  LLVMBuildPtrToInt(b, v_pergroup_allaggs, TypeSizeT, ""),
-												  l_sizet_const(0), ""),
+												  LLVMBuildPtrToInt(b, v_pergroup_allaggs, g->TypeSizeT, ""),
+												  LLVMConstInt(g->TypeSizeT, 0, false), ""),
 									opblocks[jumpnull],
 									opblocks[opno + 1]);
 					break;
@@ -2626,17 +2762,18 @@ llvm_compile_expr(ExprState *state)
 					fcinfo = pertrans->transfn_fcinfo;
 
 					v_aggstatep =
-						LLVMBuildBitCast(b, v_parent, l_ptr(StructAggState), "");
-					v_pertransp = l_ptr_const(pertrans,
-											  l_ptr(StructAggStatePerTransData));
-
+						LLVMBuildBitCast(b, v_parent, l_ptr(g->StructAggState), "");
+					v_pertransp = ///l_ptr_const(pertrans,
+									///			  l_ptr(g->StructAggStatePerTransData));
+									l_ptr_const_step(d.agg_trans.pertrans,
+												  l_ptr(g->StructAggStatePerTransData));
 					/*
 					 * pergroup = &aggstate->all_pergroups
 					 * [op->d.agg_trans.setoff] [op->d.agg_trans.transno];
 					 */
 					v_allpergroupsp =
 						l_load_struct_gep(b,
-										  StructAggState,
+										  g->StructAggState,
 										  v_aggstatep,
 										  FIELDNO_AGGSTATE_ALL_PERGROUPS,
 										  "aggstate.all_pergroups");
@@ -2644,8 +2781,8 @@ llvm_compile_expr(ExprState *state)
 					v_transno = l_int32_const(lc, op->d.agg_trans.transno);
 					v_pergroupp =
 						l_gep(b,
-							  StructAggStatePerGroupData,
-							  l_load_gep1(b, l_ptr(StructAggStatePerGroupData),
+							  g->StructAggStatePerGroupData,
+							  l_load_gep1(b, l_ptr(g->StructAggStatePerGroupData),
 										  v_allpergroupsp, v_setoff, ""),
 							  &v_transno, 1, "");
 
@@ -2659,7 +2796,7 @@ llvm_compile_expr(ExprState *state)
 
 						v_notransvalue =
 							l_load_struct_gep(b,
-											  StructAggStatePerGroupData,
+											  g->StructAggStatePerGroupData,
 											  v_pergroupp,
 											  FIELDNO_AGGSTATEPERGROUPDATA_NOTRANSVALUE,
 											  "notransvalue");
@@ -2671,7 +2808,7 @@ llvm_compile_expr(ExprState *state)
 
 						LLVMBuildCondBr(b,
 										LLVMBuildICmp(b, LLVMIntEQ, v_notransvalue,
-													  l_sbool_const(1), ""),
+													  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 										b_init,
 										b_no_init);
 
@@ -2681,8 +2818,8 @@ llvm_compile_expr(ExprState *state)
 
 							LLVMPositionBuilderAtEnd(b, b_init);
 
-							v_aggcontext = l_ptr_const(op->d.agg_trans.aggcontext,
-													   l_ptr(StructExprContext));
+							v_aggcontext = l_ptr_const_step(d.agg_trans.aggcontext,
+													   l_ptr(g->StructExprContext));
 
 							params[0] = v_aggstatep;
 							params[1] = v_pertransp;
@@ -2690,8 +2827,8 @@ llvm_compile_expr(ExprState *state)
 							params[3] = v_aggcontext;
 
 							l_call(b,
-								   llvm_pg_var_func_type("ExecAggInitGroup"),
-								   llvm_pg_func(mod, "ExecAggInitGroup"),
+								   llvm_pg_var_func_type(context, "ExecAggInitGroup"),
+								   llvm_pg_func(context, "ExecAggInitGroup"),
 								   params, lengthof(params),
 								   "");
 
@@ -2713,14 +2850,14 @@ llvm_compile_expr(ExprState *state)
 													 "op.%d.strictpass", opno);
 						v_transnull =
 							l_load_struct_gep(b,
-											  StructAggStatePerGroupData,
+											  g->StructAggStatePerGroupData,
 											  v_pergroupp,
 											  FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL,
 											  "transnull");
 
 						LLVMBuildCondBr(b,
 										LLVMBuildICmp(b, LLVMIntEQ, v_transnull,
-													  l_sbool_const(1), ""),
+													  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 										opblocks[opno + 1],
 										b_strictpass);
 
@@ -2728,26 +2865,32 @@ llvm_compile_expr(ExprState *state)
 					}
 
 
-					v_fcinfo = l_ptr_const(fcinfo,
-										   l_ptr(StructFunctionCallInfoData));
-					v_aggcontext = l_ptr_const(op->d.agg_trans.aggcontext,
-											   l_ptr(StructExprContext));
+					v_fcinfo = ///l_ptr_const(fcinfo,
+								///		   l_ptr(g->StructFunctionCallInfoData));
+								l_load_member_value_by_offset(b, lc, v_op,
+									l_ptr(g->StructAggStatePerTransData), offsetof(ExprEvalStep, d.agg_trans.pertrans));
+					v_fcinfo = ///l_ptr_const(fcinfo,
+								///		   l_ptr(g->StructFunctionCallInfoData));
+								l_load_member_value_by_offset(b, lc, v_fcinfo,
+									l_ptr(g->StructFunctionCallInfoData), offsetof(AggStatePerTransData, transfn_fcinfo));
+					v_aggcontext = l_ptr_const_step(d.agg_trans.aggcontext,
+											   l_ptr(g->StructExprContext));
 
 					v_current_setp =
 						l_struct_gep(b,
-									 StructAggState,
+									 g->StructAggState,
 									 v_aggstatep,
 									 FIELDNO_AGGSTATE_CURRENT_SET,
 									 "aggstate.current_set");
 					v_curaggcontext =
 						l_struct_gep(b,
-									 StructAggState,
+									 g->StructAggState,
 									 v_aggstatep,
 									 FIELDNO_AGGSTATE_CURAGGCONTEXT,
 									 "aggstate.curaggcontext");
 					v_current_pertransp =
 						l_struct_gep(b,
-									 StructAggState,
+									 g->StructAggState,
 									 v_aggstatep,
 									 FIELDNO_AGGSTATE_CURPERTRANS,
 									 "aggstate.curpertrans");
@@ -2759,36 +2902,40 @@ llvm_compile_expr(ExprState *state)
 					LLVMBuildStore(b, v_pertransp, v_current_pertransp);
 
 					/* invoke transition function in per-tuple context */
-					v_tmpcontext =
-						l_ptr_const(aggstate->tmpcontext->ecxt_per_tuple_memory,
-									l_ptr(StructMemoryContextData));
-					v_oldcontext = l_mcxt_switch(mod, b, v_tmpcontext);
+					///v_tmpcontext =
+					///	l_ptr_const(aggstate->tmpcontext->ecxt_per_tuple_memory,
+					///				l_ptr(g->StructMemoryContextData));
+					v_tmpcontext = l_load_struct_gep(b, g->StructExprState, v_state, FIELDNO_EXPRSTATE_PARENT,"");
+					v_tmpcontext = l_load_struct_gep(b, g->StructAggState, v_tmpcontext, FIELDNO_AGGSTATE_TMPCONTEXT,"");
+					v_tmpcontext = l_load_struct_gep(b, g->StructExprContext, v_tmpcontext, FIELDNO_EXPRCONTEXT_PERTUPLEMEMORY,"");
+
+					v_oldcontext = l_mcxt_switch(mod, b, v_tmpcontext, g);
 
 					/* store transvalue in fcinfo->args[0] */
 					v_transvaluep =
 						l_struct_gep(b,
-									 StructAggStatePerGroupData,
+									 g->StructAggStatePerGroupData,
 									 v_pergroupp,
 									 FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUE,
 									 "transvalue");
 					v_transnullp =
 						l_struct_gep(b,
-									 StructAggStatePerGroupData,
+									 g->StructAggStatePerGroupData,
 									 v_pergroupp,
 									 FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL,
 									 "transnullp");
 					LLVMBuildStore(b,
 								   l_load(b,
-										  TypeSizeT,
+										  g->TypeSizeT,
 										  v_transvaluep,
 										  "transvalue"),
-								   l_funcvaluep(b, v_fcinfo, 0));
+								   l_funcvaluep(b, v_fcinfo, 0, g));
 					LLVMBuildStore(b,
-								   l_load(b, TypeStorageBool, v_transnullp, "transnull"),
-								   l_funcnullp(b, v_fcinfo, 0));
+								   l_load(b, g->TypeStorageBool, v_transnullp, "transnull"),
+								   l_funcnullp(b, v_fcinfo, 0, g));
 
 					/* and invoke transition function */
-					v_retval = BuildV1Call(context, b, mod, fcinfo,
+					v_retval = BuildV1CallLLVM(context, b, mod, fcinfo, v_fcinfo,
 										   &v_fcinfo_isnull);
 
 					/*
@@ -2817,8 +2964,8 @@ llvm_compile_expr(ExprState *state)
 						b_nocall = l_bb_before_v(opblocks[opno + 1],
 												 "op.%d.transnocall", opno);
 
-						v_transvalue = l_load(b, TypeSizeT, v_transvaluep, "");
-						v_transnull = l_load(b, TypeStorageBool, v_transnullp, "");
+						v_transvalue = l_load(b, g->TypeSizeT, v_transvaluep, "");
+						v_transnull = l_load(b, g->TypeStorageBool, v_transnullp, "");
 
 						/*
 						 * DatumGetPointer(newVal) !=
@@ -2837,12 +2984,12 @@ llvm_compile_expr(ExprState *state)
 						params[1] = v_pertransp;
 						params[2] = v_retval;
 						params[3] = LLVMBuildTrunc(b, v_fcinfo_isnull,
-												   TypeParamBool, "");
+												   g->TypeParamBool, "");
 						params[4] = v_transvalue;
 						params[5] = LLVMBuildTrunc(b, v_transnull,
-												   TypeParamBool, "");
+												   g->TypeParamBool, "");
 
-						v_fn = llvm_pg_func(mod, "ExecAggCopyTransValue");
+						v_fn = llvm_pg_func(context, "ExecAggCopyTransValue");
 						v_newval =
 							l_call(b,
 								   LLVMGetFunctionType(v_fn),
@@ -2854,7 +3001,7 @@ llvm_compile_expr(ExprState *state)
 						LLVMBuildStore(b, v_newval, v_transvaluep);
 						LLVMBuildStore(b, v_fcinfo_isnull, v_transnullp);
 
-						l_mcxt_switch(mod, b, v_oldcontext);
+						l_mcxt_switch(mod, b, v_oldcontext, g);
 						LLVMBuildBr(b, opblocks[opno + 1]);
 
 						/* returned datum passed datum, no need to reparent */
@@ -2865,7 +3012,7 @@ llvm_compile_expr(ExprState *state)
 					LLVMBuildStore(b, v_retval, v_transvaluep);
 					LLVMBuildStore(b, v_fcinfo_isnull, v_transnullp);
 
-					l_mcxt_switch(mod, b, v_oldcontext);
+					l_mcxt_switch(mod, b, v_oldcontext, g);
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
 					break;
@@ -2877,19 +3024,21 @@ llvm_compile_expr(ExprState *state)
 					AggStatePerTrans pertrans = op->d.agg_presorted_distinctcheck.pertrans;
 					int			jumpdistinct = op->d.agg_presorted_distinctcheck.jumpdistinct;
 
-					LLVMValueRef v_fn = llvm_pg_func(mod, "ExecEvalPreOrderedDistinctSingle");
+					LLVMValueRef v_fn = llvm_pg_func(context, "ExecEvalPreOrderedDistinctSingle");
 					LLVMValueRef v_args[2];
 					LLVMValueRef v_ret;
 
-					v_args[0] = l_ptr_const(aggstate, l_ptr(StructAggState));
-					v_args[1] = l_ptr_const(pertrans, l_ptr(StructAggStatePerTransData));
+					///v_args[0] = l_ptr_const(aggstate, l_ptr(g->StructAggState));
+					v_args[0] = v_parent;
+					/// v_args[1] = l_ptr_const(pertrans, l_ptr(g->StructAggStatePerTransData));
+					v_args[1] = l_ptr_const_step(d.agg_presorted_distinctcheck.pertrans, l_ptr(g->StructAggStatePerTransData));
 
 					v_ret = l_call(b, LLVMGetFunctionType(v_fn), v_fn, v_args, 2, "");
-					v_ret = LLVMBuildZExt(b, v_ret, TypeStorageBool, "");
+					v_ret = LLVMBuildZExt(b, v_ret, g->TypeStorageBool, "");
 
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_ret,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									opblocks[opno + 1],
 									opblocks[jumpdistinct]);
 					break;
@@ -2901,33 +3050,35 @@ llvm_compile_expr(ExprState *state)
 					AggStatePerTrans pertrans = op->d.agg_presorted_distinctcheck.pertrans;
 					int			jumpdistinct = op->d.agg_presorted_distinctcheck.jumpdistinct;
 
-					LLVMValueRef v_fn = llvm_pg_func(mod, "ExecEvalPreOrderedDistinctMulti");
+					LLVMValueRef v_fn = llvm_pg_func(context, "ExecEvalPreOrderedDistinctMulti");
 					LLVMValueRef v_args[2];
 					LLVMValueRef v_ret;
 
-					v_args[0] = l_ptr_const(aggstate, l_ptr(StructAggState));
-					v_args[1] = l_ptr_const(pertrans, l_ptr(StructAggStatePerTransData));
+					///v_args[0] = l_ptr_const(aggstate, l_ptr(g->StructAggState));
+					v_args[0] = v_parent;
+					///v_args[1] = l_ptr_const(pertrans, l_ptr(g->StructAggStatePerTransData));
+					v_args[1] = l_ptr_const_step(d.agg_presorted_distinctcheck.pertrans, l_ptr(g->StructAggStatePerTransData));
 
 					v_ret = l_call(b, LLVMGetFunctionType(v_fn), v_fn, v_args, 2, "");
-					v_ret = LLVMBuildZExt(b, v_ret, TypeStorageBool, "");
+					v_ret = LLVMBuildZExt(b, v_ret, g->TypeStorageBool, "");
 
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_ret,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									opblocks[opno + 1],
 									opblocks[jumpdistinct]);
 					break;
 				}
 
 			case EEOP_AGG_ORDERED_TRANS_DATUM:
-				build_EvalXFunc(b, mod, "ExecEvalAggOrderedTransDatum",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalAggOrderedTransDatum",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_AGG_ORDERED_TRANS_TUPLE:
-				build_EvalXFunc(b, mod, "ExecEvalAggOrderedTransTuple",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalAggOrderedTransTuple",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -2955,7 +3106,12 @@ llvm_compile_expr(ExprState *state)
 		state->evalfunc = ExecRunCompiledExpr;
 		state->evalfunc_private = cstate;
 	}
-
+	{
+		char *error = NULL;
+		///LLVMDumpModule(context->module);
+		LLVMVerifyModule(context->module, LLVMAbortProcessAction, &error);
+		LLVMDisposeMessage(error);
+	}
 	llvm_leave_fatal_on_oom();
 
 	INSTR_TIME_SET_CURRENT(endtime);
@@ -2992,7 +3148,7 @@ ExecRunCompiledExpr(ExprState *state, ExprContext *econtext, bool *isNull)
 
 	return func(state, econtext, isNull);
 }
-
+#ifdef DELETE_IT
 static LLVMValueRef
 BuildV1Call(LLVMJitContext *context, LLVMBuilderRef b,
 			LLVMModuleRef mod, FunctionCallInfo fcinfo,
@@ -3008,18 +3164,18 @@ BuildV1Call(LLVMJitContext *context, LLVMBuilderRef b,
 
 	v_fn = llvm_function_reference(context, b, mod, fcinfo);
 
-	v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
+	v_fcinfo = l_ptr_const(fcinfo, l_ptr(g->StructFunctionCallInfoData));
 	v_fcinfo_isnullp = l_struct_gep(b,
-									StructFunctionCallInfoData,
+									g->StructFunctionCallInfoData,
 									v_fcinfo,
 									FIELDNO_FUNCTIONCALLINFODATA_ISNULL,
 									"v_fcinfo_isnull");
-	LLVMBuildStore(b, l_sbool_const(0), v_fcinfo_isnullp);
+	LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_fcinfo_isnullp);
 
 	v_retval = l_call(b, LLVMGetFunctionType(AttributeTemplate), v_fn, &v_fcinfo, 1, "funccall");
 
 	if (v_fcinfo_isnull)
-		*v_fcinfo_isnull = l_load(b, TypeStorageBool, v_fcinfo_isnullp, "");
+		*v_fcinfo_isnull = l_load(b, g->TypeStorageBool, v_fcinfo_isnullp, "");
 
 	/*
 	 * Add lifetime-end annotation, signaling that writes to memory don't have
@@ -3040,7 +3196,57 @@ BuildV1Call(LLVMJitContext *context, LLVMBuilderRef b,
 
 	return v_retval;
 }
+#endif
+static LLVMValueRef
+BuildV1CallLLVM(LLVMJitContext *context, LLVMBuilderRef b,
+			LLVMModuleRef mod, FunctionCallInfo fcinfo2,
+			LLVMValueRef v_fcinfo, LLVMValueRef *v_fcinfo_isnull)
+{
+	LLVMContextRef lc;
+	LLVMValueRef v_fn;
+	LLVMValueRef v_fcinfo_isnullp;
+	LLVMValueRef v_retval;
+
+	lc = LLVMGetModuleContext(mod);
+
+	v_fn = llvm_function_reference(context, b, mod, fcinfo2, v_fcinfo);
 
+	///v_fcinfo = l_ptr_const(fcinfo, l_ptr(g->StructFunctionCallInfoData));
+	v_fcinfo_isnullp = l_struct_gep(b,
+									context->jit_types->StructFunctionCallInfoData,
+									v_fcinfo,
+									FIELDNO_FUNCTIONCALLINFODATA_ISNULL,
+									"v_fcinfo_isnull");
+	LLVMBuildStore(b, LLVMConstInt(context->jit_types->TypeStorageBool, (int)(0), false), v_fcinfo_isnullp);
+
+	v_retval = l_call(b, LLVMGetFunctionType(context->jit_types->AttributeTemplate), v_fn, &v_fcinfo, 1, "funccall");
+
+	if (v_fcinfo_isnull)
+		*v_fcinfo_isnull = l_load(b, context->jit_types->TypeStorageBool, v_fcinfo_isnullp, "");
+
+	/*
+	 * Add lifetime-end annotation, signaling that writes to memory don't have
+	 * to be retained (important for inlining potential).
+	 */
+	{
+		LLVMValueRef v_lifetime = create_LifetimeEnd(mod);
+		LLVMValueRef params[2];
+		/* TODO check fcinfo2->nargs is const or is changed from call to call */
+		params[0] = l_int64_const(lc, sizeof(NullableDatum) * fcinfo2->nargs);
+		params[1] =  ///l_ptr_const(fcinfo->args, l_ptr(LLVMInt8TypeInContext(lc)));
+					l_load_member_value_by_offset(b, lc , v_fcinfo, l_ptr(LLVMInt8TypeInContext(lc)), offsetof(FunctionCallInfoBaseData, args) );
+		l_call(b, LLVMGetFunctionType(v_lifetime), v_lifetime, params, lengthof(params), "");
+
+		params[0] = l_int64_const(lc, sizeof(fcinfo2->isnull));
+		params[1] = /// l_ptr_const(&fcinfo->isnull, l_ptr(LLVMInt8TypeInContext(lc)));
+					l_struct_member_ptr_by_offset(b, lc, v_fcinfo, offsetof(FunctionCallInfoBaseData, isnull));
+		l_call(b, LLVMGetFunctionType(v_lifetime), v_lifetime, params, lengthof(params), "");
+	}
+
+	return v_retval;
+}
+
+#ifdef DELETE_IT
 /*
  * Implement an expression step by calling the function funcname.
  */
@@ -3049,7 +3255,40 @@ build_EvalXFuncInt(LLVMBuilderRef b, LLVMModuleRef mod, const char *funcname,
 				   LLVMValueRef v_state, ExprEvalStep *op,
 				   int nargs, LLVMValueRef *v_args)
 {
-	LLVMValueRef v_fn = llvm_pg_func(mod, funcname);
+	LLVMValueRef v_fn = llvm_pg_func(context, funcname);
+	LLVMValueRef *params;
+	int			argno = 0;
+	LLVMValueRef v_ret;
+
+	/* cheap pre-check as llvm just asserts out */
+	if (LLVMCountParams(v_fn) != (nargs + 2))
+		elog(ERROR, "parameter mismatch: %s expects %d passed %d",
+			 funcname, LLVMCountParams(v_fn), nargs + 2);
+
+	params = palloc(sizeof(LLVMValueRef) * (2 + nargs));
+
+	params[argno++] = v_state;
+	params[argno++] = l_ptr_const(op, l_ptr(g->StructExprEvalStep));
+
+	for (int i = 0; i < nargs; i++)
+		params[argno++] = v_args[i];
+
+	v_ret = l_call(b, LLVMGetFunctionType(v_fn), v_fn, params, argno, "");
+
+	pfree(params);
+
+	return v_ret;
+}
+#endif
+/*
+ * Implement an expression step by calling the function funcname.
+ */
+static LLVMValueRef
+build_EvalXFuncIntLLVM(LLVMBuilderRef b, LLVMJitContext *context, const char *funcname,
+				   LLVMValueRef v_state, LLVMValueRef v_op,
+				   int nargs, LLVMValueRef *v_args)
+{
+	LLVMValueRef v_fn = llvm_pg_func(context, funcname);
 	LLVMValueRef *params;
 	int			argno = 0;
 	LLVMValueRef v_ret;
@@ -3062,7 +3301,7 @@ build_EvalXFuncInt(LLVMBuilderRef b, LLVMModuleRef mod, const char *funcname,
 	params = palloc(sizeof(LLVMValueRef) * (2 + nargs));
 
 	params[argno++] = v_state;
-	params[argno++] = l_ptr_const(op, l_ptr(StructExprEvalStep));
+	params[argno++] = v_op;
 
 	for (int i = 0; i < nargs; i++)
 		params[argno++] = v_args[i];
diff --git a/src/backend/jit/llvm/llvmjit_types.c b/src/backend/jit/llvm/llvmjit_types.c
index dbe0282e98f..f39ddfc30a6 100644
--- a/src/backend/jit/llvm/llvmjit_types.c
+++ b/src/backend/jit/llvm/llvmjit_types.c
@@ -69,6 +69,7 @@ MinimalTupleTableSlot StructMinimalTupleTableSlot;
 TupleDescData StructTupleDescData;
 PlanState	StructPlanState;
 MinimalTupleData StructMinimalTupleData;
+WindowFuncExprState StructWindowFuncExprState;
 
 
 /*
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 45915767825..9bb8ae0e076 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -61,6 +61,9 @@
 #define COPY_LOCATION_FIELD(fldname) \
 	(newnode->fldname = from->fldname)
 
+/* Copy a saved jit context */
+#define COPY_JITCONTEXT_FIELD(fldname) \
+	(newnode->fldname = from->fldname)
 
 #include "copyfuncs.funcs.c"
 
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index f2598a1b69a..6cd16db0a0d 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -84,6 +84,12 @@
 #define COMPARE_COERCIONFORM_FIELD(fldname) \
 	((void) 0)
 
+/* Compare a saved jit context */
+#define COMPARE_JITCONTEXT_FIELD(fldname) \
+	do { \
+		if (a->fldname != b->fldname) \
+			return false; \
+	} while (0)
 
 #include "equalfuncs.funcs.c"
 
diff --git a/src/backend/nodes/gen_node_support.pl b/src/backend/nodes/gen_node_support.pl
index 1a657f7e0ae..d2c284af857 100644
--- a/src/backend/nodes/gen_node_support.pl
+++ b/src/backend/nodes/gen_node_support.pl
@@ -865,6 +865,14 @@ _equal${n}(const $n *a, const $n *b)
 			print $cff "\tCOPY_SCALAR_FIELD($f);\n" unless $copy_ignore;
 			print $eff "\tCOMPARE_SCALAR_FIELD($f);\n" unless $equal_ignore;
 		}
+		elsif ($t eq 'struct CachedJitContext*')
+		{
+			# Fields of these types are required to be a pointer to a
+			# static struct.  So we don't copy the struct itself,
+			# just reference the original one.
+			print $cff "\tCOPY_SCALAR_FIELD($f);\n" unless $copy_ignore;
+			print $eff "\tCOMPARE_SCALAR_FIELD($f);\n" unless $equal_ignore;
+		}
 		else
 		{
 			die
@@ -1214,6 +1222,11 @@ _read${n}(void)
 	}
 ! unless $no_read;
 		}
+		elsif ($t eq 'struct CachedJitContext*')
+		{
+			print $off "\tWRITE_JITCONTEXT_FIELD($f);\n";
+			print $rff "\tREAD_JITCONTEXT_FIELD($f);\n" unless $no_read;
+		}
 		else
 		{
 			die
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index bb9bdd67192..9c772a00197 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -93,6 +93,10 @@ static void outDouble(StringInfo str, double d);
 #define WRITE_LOCATION_FIELD(fldname) \
 	appendStringInfo(str, " :" CppAsString(fldname) " %d", write_location_fields ? node->fldname : -1)
 
+/* Write a parse jit context field (actually same as INT case) */
+#define WRITE_JITCONTEXT_FIELD(fldname) \
+	appendStringInfo(str, " :" CppAsString(fldname) " %d", 0)
+
 /* Write a Node field */
 #define WRITE_NODE_FIELD(fldname) \
 	(appendStringInfoString(str, " :" CppAsString(fldname) " "), \
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index 64d3a09f765..b4bb27353a5 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -131,6 +131,12 @@
 	local_node->fldname = -1	/* set field to "unknown" */
 #endif
 
+/* Read a parse jit context field*/
+#define READ_JITCONTEXT_FIELD(fldname) \
+	token = pg_strtok(&length);		/* skip :fldname */ \
+	token = pg_strtok(&length);		/* get field value */ \
+	local_node->fldname = (struct CachedJitContext*)atoi(token)
+
 /* Read a Node field */
 #define READ_NODE_FIELD(fldname) \
 	token = pg_strtok(&length);		/* skip :fldname */ \
diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c
index 55db8f53705..f2016ed79d3 100644
--- a/src/backend/utils/cache/plancache.c
+++ b/src/backend/utils/cache/plancache.c
@@ -72,6 +72,7 @@
 #include "utils/rls.h"
 #include "utils/snapmgr.h"
 #include "utils/syscache.h"
+#include "jit/jit.h"
 
 
 /*
@@ -1015,6 +1016,10 @@ BuildCachedPlan(CachedPlanSource *plansource, List *qlist,
 			is_transient = true;
 		if (plannedstmt->dependsOnRole)
 			plan->dependsOnRole = true;
+		if (!plansource->is_oneshot && !plannedstmt->jit_context)
+		{
+			plannedstmt->jit_context = CACHED_JITCONTEXT_EMPTY;
+		}
 	}
 	if (is_transient)
 	{
@@ -1305,7 +1310,21 @@ ReleaseCachedPlan(CachedPlan *plan, ResourceOwner owner)
 
 		/* One-shot plans do not own their context, so we can't free them */
 		if (!plan->is_oneshot)
+		{
+			/* release cached jit contexts */
+			ListCell   *lc;
+			foreach(lc, plan->stmt_list)
+			{
+				PlannedStmt *plannedstmt = lfirst_node(PlannedStmt, lc);
+
+				if (plannedstmt->jit_context &&
+					plannedstmt->jit_context != CACHED_JITCONTEXT_EMPTY)
+				{
+					jit_release_context(plannedstmt->jit_context); /* todo fix to correct pointer to jit context (.jit)*/
+				}
+			}
 			MemoryContextDelete(plan->context);
+		}
 	}
 }
 
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index ce7534d4d23..0fe8349e9b8 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -1983,6 +1983,18 @@ struct config_bool ConfigureNamesBool[] =
 		NULL, NULL, NULL
 	},
 
+	{
+		{"jit_cached", PGC_USERSET, QUERY_TUNING_OTHER,
+			gettext_noop("Allow JIT compilation to store in a plan cache."),
+			NULL,
+			GUC_EXPLAIN
+		},
+		&jit_cached,
+		false,
+		NULL, NULL, NULL
+	},
+
+
 	{
 		{"jit_debugging_support", PGC_SU_BACKEND, DEVELOPER_OPTIONS,
 			gettext_noop("Register JIT-compiled functions with debugger."),
diff --git a/src/include/executor/execExpr.h b/src/include/executor/execExpr.h
index 51bd35dcb07..092d3f850fb 100644
--- a/src/include/executor/execExpr.h
+++ b/src/include/executor/execExpr.h
@@ -301,7 +301,9 @@ typedef struct ExprEvalStep
 	intptr_t	opcode;
 
 	/* where to store the result of this step */
+#define FIELDNO_EXPREVALSTEP_RESVALUE	1
 	Datum	   *resvalue;
+#define FIELDNO_EXPREVALSTEP_RESNULL	2
 	bool	   *resnull;
 
 	/*
diff --git a/src/include/jit/jit.h b/src/include/jit/jit.h
index 33cb36c5d2e..ca8dc047c7f 100644
--- a/src/include/jit/jit.h
+++ b/src/include/jit/jit.h
@@ -81,6 +81,7 @@ struct JitProviderCallbacks
 
 /* GUCs */
 extern PGDLLIMPORT bool jit_enabled;
+extern PGDLLIMPORT bool jit_cached;
 extern PGDLLIMPORT char *jit_provider;
 extern PGDLLIMPORT bool jit_debugging_support;
 extern PGDLLIMPORT bool jit_dump_bitcode;
diff --git a/src/include/jit/llvmjit.h b/src/include/jit/llvmjit.h
index 5038cf33e3f..b4489786a03 100644
--- a/src/include/jit/llvmjit.h
+++ b/src/include/jit/llvmjit.h
@@ -40,6 +40,38 @@ extern "C"
 #include "jit/jit.h"
 #include "nodes/pg_list.h"
 
+/* type and struct definitions */
+typedef struct LLVMJitTypes
+{
+	LLVMTypeRef TypeParamBool;
+	LLVMTypeRef TypePGFunction;
+	LLVMTypeRef TypeSizeT;
+	LLVMTypeRef TypeStorageBool;
+
+	LLVMTypeRef StructNullableDatum;
+	LLVMTypeRef StructTupleDescData;
+	LLVMTypeRef StructHeapTupleData;
+	LLVMTypeRef StructHeapTupleHeaderData;
+	LLVMTypeRef StructMinimalTupleData;
+	LLVMTypeRef StructTupleTableSlot;
+	LLVMTypeRef StructHeapTupleTableSlot;
+	LLVMTypeRef StructMinimalTupleTableSlot;
+	LLVMTypeRef StructMemoryContextData;
+	LLVMTypeRef StructFunctionCallInfoData;
+	LLVMTypeRef StructExprContext;
+	LLVMTypeRef StructExprEvalStep;
+	LLVMTypeRef StructExprState;
+	LLVMTypeRef StructAggState;
+	LLVMTypeRef StructAggStatePerTransData;
+	LLVMTypeRef StructAggStatePerGroupData;
+	LLVMTypeRef StructPlanState;
+	LLVMTypeRef StructWindowFuncExprState;
+
+	LLVMValueRef AttributeTemplate;
+	LLVMValueRef ExecEvalBoolSubroutineTemplate;
+	LLVMValueRef ExecEvalSubroutineTemplate;
+} LLVMJitTypes;
+
 typedef struct LLVMJitContext
 {
 	JitContext	base;
@@ -60,44 +92,34 @@ typedef struct LLVMJitContext
 	/* current, "open for write", module */
 	LLVMModuleRef module;
 
+	/* types module in llvm_context or NULL */
+	LLVMModuleRef llvm_types_module;
+
+	/* types defined in types module */
+	LLVMJitTypes *jit_types;
+
 	/* is there any pending code that needs to be emitted */
 	bool		compiled;
 
 	/* # of objects emitted, used to generate non-conflicting names */
-	int			counter;
+	int			counter_expr;
+
+	/* max # of objects emitted, used to start counting from 0 */
+	int			max_counter_expr;
+
+	/* # of objects emitted, used to generate non-conflicting names */
+	int			counter_deform;
 
 	/* list of handles for code emitted via Orc */
 	List	   *handles;
 } LLVMJitContext;
 
-/* type and struct definitions */
-extern PGDLLIMPORT LLVMTypeRef TypeParamBool;
-extern PGDLLIMPORT LLVMTypeRef TypePGFunction;
-extern PGDLLIMPORT LLVMTypeRef TypeSizeT;
-extern PGDLLIMPORT LLVMTypeRef TypeStorageBool;
-
-extern PGDLLIMPORT LLVMTypeRef StructNullableDatum;
-extern PGDLLIMPORT LLVMTypeRef StructTupleDescData;
-extern PGDLLIMPORT LLVMTypeRef StructHeapTupleData;
-extern PGDLLIMPORT LLVMTypeRef StructHeapTupleHeaderData;
-extern PGDLLIMPORT LLVMTypeRef StructMinimalTupleData;
-extern PGDLLIMPORT LLVMTypeRef StructTupleTableSlot;
-extern PGDLLIMPORT LLVMTypeRef StructHeapTupleTableSlot;
-extern PGDLLIMPORT LLVMTypeRef StructMinimalTupleTableSlot;
-extern PGDLLIMPORT LLVMTypeRef StructMemoryContextData;
-extern PGDLLIMPORT LLVMTypeRef StructFunctionCallInfoData;
-extern PGDLLIMPORT LLVMTypeRef StructExprContext;
-extern PGDLLIMPORT LLVMTypeRef StructExprEvalStep;
-extern PGDLLIMPORT LLVMTypeRef StructExprState;
-extern PGDLLIMPORT LLVMTypeRef StructAggState;
-extern PGDLLIMPORT LLVMTypeRef StructAggStatePerTransData;
-extern PGDLLIMPORT LLVMTypeRef StructAggStatePerGroupData;
-extern PGDLLIMPORT LLVMTypeRef StructPlanState;
-
-extern PGDLLIMPORT LLVMValueRef AttributeTemplate;
-extern PGDLLIMPORT LLVMValueRef ExecEvalBoolSubroutineTemplate;
-extern PGDLLIMPORT LLVMValueRef ExecEvalSubroutineTemplate;
+struct CachedJitContext
+{
+	LLVMJitContext	jit;
+};
 
+extern PGDLLIMPORT LLVMJitTypes llvm_jit_types_struct;
 
 extern void llvm_enter_fatal_on_oom(void);
 extern void llvm_leave_fatal_on_oom(void);
@@ -106,18 +128,21 @@ extern void llvm_reset_after_error(void);
 extern void llvm_assert_in_fatal_section(void);
 
 extern LLVMJitContext *llvm_create_context(int jitFlags);
+extern LLVMJitContext *llvm_create_cached_context(int jitFlags);
 extern LLVMModuleRef llvm_mutable_module(LLVMJitContext *context);
-extern char *llvm_expand_funcname(LLVMJitContext *context, const char *basename);
+extern char *llvm_expand_funcname_expr(LLVMJitContext *context, const char *basename);
+extern char *llvm_expand_funcname_deform(LLVMJitContext *context, const char *basename);
 extern void *llvm_get_function(LLVMJitContext *context, const char *funcname);
 extern void llvm_split_symbol_name(const char *name, char **modname, char **funcname);
-extern LLVMTypeRef llvm_pg_var_type(const char *varname);
-extern LLVMTypeRef llvm_pg_var_func_type(const char *varname);
-extern LLVMValueRef llvm_pg_func(LLVMModuleRef mod, const char *funcname);
+extern LLVMTypeRef llvm_pg_var_type(LLVMModuleRef llvm_types_module, const char *varname);
+extern LLVMTypeRef llvm_pg_var_func_type(LLVMJitContext *context, const char *varname);
+extern LLVMValueRef llvm_pg_func(LLVMJitContext *context /*LLVMModuleRef mod*/, const char *funcname);
 extern void llvm_copy_attributes(LLVMValueRef from, LLVMValueRef to);
 extern LLVMValueRef llvm_function_reference(LLVMJitContext *context,
 						LLVMBuilderRef builder,
 						LLVMModuleRef mod,
-						FunctionCallInfo fcinfo);
+						FunctionCallInfo fcinfo,
+						LLVMValueRef v_fcinfo);
 
 extern void llvm_inline_reset_caches(void);
 extern void llvm_inline(LLVMModuleRef mod);
diff --git a/src/include/jit/llvmjit_emit.h b/src/include/jit/llvmjit_emit.h
index df5a9fc8500..6f8d0e83649 100644
--- a/src/include/jit/llvmjit_emit.h
+++ b/src/include/jit/llvmjit_emit.h
@@ -25,7 +25,7 @@
  * Emit a non-LLVM pointer as an LLVM constant.
  */
 static inline LLVMValueRef
-l_ptr_const(void *ptr, LLVMTypeRef type)
+l_ptr_const(void *ptr, LLVMTypeRef type, LLVMTypeRef TypeSizeT)
 {
 	LLVMValueRef c = LLVMConstInt(TypeSizeT, (uintptr_t) ptr, false);
 
@@ -76,7 +76,7 @@ l_int64_const(LLVMContextRef lc, int64 i)
 {
 	return LLVMConstInt(LLVMInt64TypeInContext(lc), i, false);
 }
-
+#ifdef DELETE_IT
 /*
  * Emit constant integer.
  */
@@ -95,6 +95,7 @@ l_sbool_const(bool i)
 	return LLVMConstInt(TypeStorageBool, (int) i, false);
 }
 
+
 /*
  * Emit constant boolean, as used for parameters (e.g. function parameters).
  */
@@ -103,6 +104,7 @@ l_pbool_const(bool i)
 {
 	return LLVMConstInt(TypeParamBool, (int) i, false);
 }
+#endif
 
 static inline LLVMValueRef
 l_struct_gep(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, int32 idx, const char *name)
@@ -149,6 +151,44 @@ l_load_gep1(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, LLVMValueRef idx, c
 	return l_load(b, t, l_gep(b, t, v, &idx, 1, ""), name);
 }
 
+#ifndef DELETE_IT
+/*
+ * Load value of a structure using offset of member in structure.
+ * b - builder
+ * v - value of sturcture
+ * dest - the type of the structure member
+ * offset - the offset of the structure member in the structure v
+ */
+static inline LLVMValueRef
+l_load_member_value_by_offset(LLVMBuilderRef b, LLVMContextRef lc, LLVMValueRef v, LLVMTypeRef dest, int offset)
+{
+#ifdef _DELETE_IT
+    LLVMValueRef castbase = LLVMBuildPtrToInt(b, v, LLVMInt64TypeInContext(llvm_context), "base_pointer");
+    LLVMValueRef castchar1offset = LLVMBuildAdd(b, castbase, l_int64_const(llvm_context, offset), "member_pointer_int");
+    LLVMValueRef castchar2 = LLVMBuildIntToPtr(b, castchar1offset,  l_ptr(dest), "member_pointer");
+    return l_load(b, dest, castchar2, "member_value");
+#endif
+    LLVMValueRef offsets = l_int32_const(lc, offset);
+    LLVMValueRef member_address = l_gep(b,(LLVMInt8TypeInContext(lc)), v, &offsets, 1, "member_address");
+    return l_load(b, dest, member_address, "member_value");
+}
+
+#define l_ptr_const_step(m,t) l_load_member_value_by_offset(b,lc, v_op, t, offsetof(ExprEvalStep ,m))
+
+static inline LLVMValueRef
+l_struct_member_ptr_by_offset(LLVMBuilderRef b, LLVMContextRef lc, LLVMValueRef v, /* LLVMTypeRef dest, */ int offset)
+{
+#ifdef _DELETE_IT
+    LLVMValueRef castbase = LLVMBuildPtrToInt(b, v, LLVMInt64TypeInContext(llvm_context), "base_pointer");
+    LLVMValueRef castchar1offset = LLVMBuildAdd(b, castbase, l_int64_const(llvm_context, offset), "member_pointer_int");
+    LLVMValueRef castchar2 = LLVMBuildIntToPtr(b, castchar1offset,  l_ptr(dest), "member_pointer");
+    return l_load(b, dest, castchar2, "member_value");
+#endif
+    LLVMValueRef offsets = l_int32_const(lc, offset);
+    LLVMValueRef member_address = l_gep(b,(LLVMInt8TypeInContext(lc)), v, &offsets, 1, "member_address");
+    return member_address;
+}
+#endif
 /* separate, because pg_attribute_printf(2, 3) can't appear in definition */
 static inline LLVMBasicBlockRef l_bb_before_v(LLVMBasicBlockRef r, const char *fmt,...) pg_attribute_printf(2, 3);
 
@@ -232,15 +272,15 @@ l_callsite_alwaysinline(LLVMValueRef f)
  * Emit code to switch memory context.
  */
 static inline LLVMValueRef
-l_mcxt_switch(LLVMModuleRef mod, LLVMBuilderRef b, LLVMValueRef nc)
+l_mcxt_switch(LLVMModuleRef mod, LLVMBuilderRef b, LLVMValueRef nc, LLVMJitTypes *g)
 {
 	const char *cmc = "CurrentMemoryContext";
 	LLVMValueRef cur;
 	LLVMValueRef ret;
 
 	if (!(cur = LLVMGetNamedGlobal(mod, cmc)))
-		cur = LLVMAddGlobal(mod, l_ptr(StructMemoryContextData), cmc);
-	ret = l_load(b, l_ptr(StructMemoryContextData), cur, cmc);
+		cur = LLVMAddGlobal(mod, l_ptr(g->StructMemoryContextData), cmc);
+	ret = l_load(b, l_ptr(g->StructMemoryContextData), cur, cmc);
 	LLVMBuildStore(b, nc, cur);
 
 	return ret;
@@ -250,23 +290,23 @@ l_mcxt_switch(LLVMModuleRef mod, LLVMBuilderRef b, LLVMValueRef nc)
  * Return pointer to the argno'th argument nullness.
  */
 static inline LLVMValueRef
-l_funcnullp(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
+l_funcnullp(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno, LLVMJitTypes *g)
 {
 	LLVMValueRef v_args;
 	LLVMValueRef v_argn;
 
 	v_args = l_struct_gep(b,
-						  StructFunctionCallInfoData,
+						  g->StructFunctionCallInfoData,
 						  v_fcinfo,
 						  FIELDNO_FUNCTIONCALLINFODATA_ARGS,
 						  "");
 	v_argn = l_struct_gep(b,
-						  LLVMArrayType(StructNullableDatum, 0),
+						  LLVMArrayType(g->StructNullableDatum, 0),
 						  v_args,
 						  argno,
 						  "");
 	return l_struct_gep(b,
-						StructNullableDatum,
+						g->StructNullableDatum,
 						v_argn,
 						FIELDNO_NULLABLE_DATUM_ISNULL,
 						"");
@@ -276,23 +316,23 @@ l_funcnullp(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
  * Return pointer to the argno'th argument datum.
  */
 static inline LLVMValueRef
-l_funcvaluep(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
+l_funcvaluep(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno, LLVMJitTypes *g)
 {
 	LLVMValueRef v_args;
 	LLVMValueRef v_argn;
 
 	v_args = l_struct_gep(b,
-						  StructFunctionCallInfoData,
+						  g->StructFunctionCallInfoData,
 						  v_fcinfo,
 						  FIELDNO_FUNCTIONCALLINFODATA_ARGS,
 						  "");
 	v_argn = l_struct_gep(b,
-						  LLVMArrayType(StructNullableDatum, 0),
+						  LLVMArrayType(g->StructNullableDatum, 0),
 						  v_args,
 						  argno,
 						  "");
 	return l_struct_gep(b,
-						StructNullableDatum,
+						g->StructNullableDatum,
 						v_argn,
 						FIELDNO_NULLABLE_DATUM_DATUM,
 						"");
@@ -302,18 +342,18 @@ l_funcvaluep(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
  * Return argno'th argument nullness.
  */
 static inline LLVMValueRef
-l_funcnull(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
+l_funcnull(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno, LLVMJitTypes *g)
 {
-	return l_load(b, TypeStorageBool, l_funcnullp(b, v_fcinfo, argno), "");
+	return l_load(b, g->TypeStorageBool, l_funcnullp(b, v_fcinfo, argno, g), "");
 }
 
 /*
  * Return argno'th argument datum.
  */
 static inline LLVMValueRef
-l_funcvalue(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
+l_funcvalue(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno, LLVMJitTypes *g)
 {
-	return l_load(b, TypeSizeT, l_funcvaluep(b, v_fcinfo, argno), "");
+	return l_load(b, g->TypeSizeT, l_funcvaluep(b, v_fcinfo, argno, g), "");
 }
 
 #endif							/* USE_LLVM */
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index e2d1dc1e067..0267781b25d 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -108,6 +108,7 @@ typedef struct ExprState
 	/*
 	 * Instructions to compute expression's return value.
 	 */
+#define FIELDNO_EXPRSTATE_STEPS	5
 	struct ExprEvalStep *steps;
 
 	/*
@@ -272,6 +273,7 @@ typedef struct ExprContext
 
 	/* Memory contexts for expression evaluation --- see notes above */
 	MemoryContext ecxt_per_query_memory;
+#define FIELDNO_EXPRCONTEXT_PERTUPLEMEMORY 5
 	MemoryContext ecxt_per_tuple_memory;
 
 	/* Values to substitute for Param nodes in expression */
@@ -2534,6 +2536,7 @@ typedef struct AggState
 	AggStatePerTrans pertrans;	/* per-Trans state information */
 	ExprContext *hashcontext;	/* econtexts for long-lived data (hashtable) */
 	ExprContext **aggcontexts;	/* econtexts for long-lived data (per GS) */
+#define FIELDNO_AGGSTATE_TMPCONTEXT 13
 	ExprContext *tmpcontext;	/* econtext for input expressions */
 #define FIELDNO_AGGSTATE_CURAGGCONTEXT 14
 	ExprContext *curaggcontext; /* currently active aggcontext */
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index 2a2cf816cb6..a5c0a310191 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -22,7 +22,8 @@
 #include "nodes/lockoptions.h"
 #include "nodes/primnodes.h"
 
-
+struct CachedJitContext;
+#define CACHED_JITCONTEXT_EMPTY ((struct CachedJitContext*)(-1))
 /* ----------------------------------------------------------------
  *						node definitions
  * ----------------------------------------------------------------
@@ -104,6 +105,7 @@ typedef struct PlannedStmt
 	/* statement location in source string (copied from Query) */
 	ParseLoc	stmt_location;	/* start location, or -1 if unknown */
 	ParseLoc	stmt_len;		/* length in bytes; 0 means "rest of string" */
+	struct CachedJitContext	*jit_context;	/* context of save jit-module */
 } PlannedStmt;
 
 /* macro for fetching the Plan associated with a SubPlan node */
-- 
2.39.5 (Apple Git-154)

#3Vladlen Popolitov
v.popolitov@postgrespro.ru
In reply to: Vladlen Popolitov (#2)
1 attachment(s)
Re: PoC. The saving of the compiled jit-code in the plan cache

Vladlen Popolitov писал(а) 2025-02-13 21:49:
Dear colleagues,

Updated patch rebased to the current master. Also I resolved the
problems
with the lookup of the compiled expressions.
Cached jit compiles only expressions from cached plan - they are
recognized by memory context - if Expr is not NULL and belong to the
same
memory context as cached plan, this expression is compiled to the
function
with expression address in the name (expression address casted to Size
type).
All other expression (generated later than plan, f.e. expressions in
aggregates, hash join, hash aggregates) are not compiled and are
executed
by standard expression interpreter.

This version is more stable comparing to previous, make check passed
with SET jit_cached=on.

P.S. this patch is not for commit fest, it is for discussion of the
cached
jit feature.

Dear colleagues,

It is updated patch (compiled with current master, the same
description, as
below, no other features yet)

If you need to patch the same master version, you can:
git checkout 83ea6c54025bea67bcd4949a6d58d3fc11c3e21b
patch -p1 <v5-0001-jit-saved-for-cached-plans.patch

Vladlen Popolitov писал(а) 2025-02-13 16:01:
Dear colleagues,

I implemented the patch to store in the plan cache an already compiled
jit
code. If a query is executed many times, the query time can be
decreased by
20-30% for long queries with big share of expressions in the code.

This patch can be applied to the current master and passes tests, but
it is
only the Proof of the Concept, and I need to get opinions and advice
for nexts
steps. It is not ready for commitfest, does not cover all scenarios
(craches
in some sutuation that need special solution), and source code is not
clean.

The code source has removed old code marked by // comments to easier
compare,
what was changed, especially in llvmjit_expr.c and llvmjit_deform.c

Implementation details.

1. Changes in jit-code generation.

a) the load of the absolute address (as const) changed to the load of
this
address from a struct member:

old version:
v_resvaluep = l_ptr_const(op->resvalue, l_ptr(TypeSizeT));
new version
v_resvaluep = l_load_struct_gep( b, g->StructExprEvalStep, v_op,
FIELDNO_EXPREVALSTEP_RESVALUE, "v_resvaluep");

b) the load of the absolute address or the value from union changed to
the load of the union value using the offset of the union member

old version
fcinfo - the union member value
v_fcinfo = l_ptr_const(fcinfo, l_ptr(g->StructFunctionCallInfoData));
new version
v_fcinfo = l_load_member_value_by_offset(b,lc, v_op,
l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep,
d.func.fcinfo_data ));

c) every cached plan has own LLVM-context and 1 module in it. As
result,
some functions require context parameter to correctly address it
instead
of the global llvm_context variable.

d) llvm_types moved from global variables to the struct LLVMJitTypes.
Not cached queries use old setup, but all types definitions are stored
in global struct LLVMJitTypes llvm_jit_types_struct, instead of many
global variables. Chached queries allocate struct LLVMJitTypes during
query
executon, and pfree it when cached plan is deallocated. llvm_types
module is
read for every cached statement (not 1 time during global context
creation).

e) llvm_function_reference still uses l_ptr_const with the absolute
address
of the function, it needs to be checked, as the function can change
address.

f) new GUC variabe jit_cached is added, off by default.

2. Changes in cached plan.
To store cached context I use struct PlannedStmt (in ExprState
state->parent->state->es_plannedstmt).
New member struct CachedJitContext *jit_context added to store
information
about jit context. In new plans this field in NULL. If plan is stored
to cache,
it filled by CACHED_JITCONTEXT_EMPTY and replaced by actual jit
context pointer
in llvmjit_expr.c .
When cached plan is deallocated, this member used to free jit
resources and
memory.

3. Current problems.
When module is compiled, it needs to connect ExprState and function
addresses.
In old implementation funcname is stored in ExprState.
In cached implementation the fuction will be called second and more
times,
and calling code does not have information about function name for
ExprState.
a) The current cached implementation uses the number of the call to
connect
f.e. 1st expresion and 1st function. It does not work for queries,
that
generates an expression after module compilation (f.e. HashJoin) and
tries
to compile it.
b) Also query with aggregate functions generates an expresion every
time, when
executed. It work with current approach, but these expressions should
be
considered, as they have different expression address every time.

One of the solution for a) and b) - generate jit-code for Expr
pointers only
in cached plan. Every new created expression either should be ignored
by
the compiler and executed by the standard interpreter, or compiled in
the
standard (not cached) jit (it will run compilation every query run and
eliminate all gain from jit-cache).

c) new jit-code generation (use the stuct member instead of the direct
absolute address) slightly decreases the jit-code performance. It is
possible
to compile old version for not cached queries, and new code for cached
queries.
In this case two big 3000 lines funtions llvm_compile_expr() need to
be
maintained in similar way, when new expresiions or features are added.

Attached files have
1) the patch (branched from 83ea6c54025bea67bcd4949a6d58d3fc11c3e21b
master),
2 and 3) benchmark files jitinit.sql to create jitbench database and
bash
script jitbench.sh (change to own user and password if you need) to
run
banchmark.
4) chart for this benchmark and the query in the benchmark (comparison
with jit=off as 1 unit). It is easy to find query, where jit is higher
or
lower than jit-off. Here I demonstate the difference of standard and
new
jit-code (the decrease of the performance with compilation without
optimization), and high gain of cached version with optimization and
high lost of not cached version with optimization due to the running
of the optimization for every the query.

--
Best regards,

Vladlen Popolitov.

Attachments:

v8-0001-jit-saved-to-plan-cache.patchtext/x-diff; name=v8-0001-jit-saved-to-plan-cache.patchDownload
From 2423cb7f68de654a6ba70d88ff8ede6778af30d0 Mon Sep 17 00:00:00 2001
From: Vladlen Popolitov <v.popolitov@postgrespro.ru>
Date: Tue, 18 Feb 2025 16:34:04 +0700
Subject: [PATCH v8] jit saved to plan cache

---
 src/backend/jit/jit.c                 |    1 +
 src/backend/jit/llvm/llvmjit.c        |  208 +++--
 src/backend/jit/llvm/llvmjit_deform.c |   86 +-
 src/backend/jit/llvm/llvmjit_expr.c   | 1051 ++++++++++++++-----------
 src/backend/jit/llvm/llvmjit_types.c  |    1 +
 src/backend/nodes/copyfuncs.c         |    3 +
 src/backend/nodes/equalfuncs.c        |    6 +
 src/backend/nodes/gen_node_support.pl |   13 +
 src/backend/nodes/outfuncs.c          |    4 +
 src/backend/nodes/readfuncs.c         |    6 +
 src/backend/utils/cache/plancache.c   |   21 +
 src/backend/utils/misc/guc_tables.c   |   12 +
 src/include/executor/execExpr.h       |    2 +
 src/include/jit/jit.h                 |    1 +
 src/include/jit/llvmjit.h             |   83 +-
 src/include/jit/llvmjit_emit.h        |   84 +-
 src/include/nodes/execnodes.h         |    3 +
 src/include/nodes/plannodes.h         |    5 +-
 18 files changed, 971 insertions(+), 619 deletions(-)

diff --git a/src/backend/jit/jit.c b/src/backend/jit/jit.c
index d2ccef9de85..3927f7c5f73 100644
--- a/src/backend/jit/jit.c
+++ b/src/backend/jit/jit.c
@@ -30,6 +30,7 @@
 
 /* GUCs */
 bool		jit_enabled = true;
+bool		jit_cached = false;
 char	   *jit_provider = NULL;
 bool		jit_debugging_support = false;
 bool		jit_dump_bitcode = false;
diff --git a/src/backend/jit/llvm/llvmjit.c b/src/backend/jit/llvm/llvmjit.c
index 614926720fb..4b6ebdd4d8b 100644
--- a/src/backend/jit/llvm/llvmjit.c
+++ b/src/backend/jit/llvm/llvmjit.c
@@ -53,6 +53,7 @@ typedef struct LLVMJitHandle
 
 
 /* types & functions commonly needed for JITing */
+/*
 LLVMTypeRef TypeSizeT;
 LLVMTypeRef TypeParamBool;
 LLVMTypeRef TypeStorageBool;
@@ -74,10 +75,14 @@ LLVMTypeRef StructAggState;
 LLVMTypeRef StructAggStatePerGroupData;
 LLVMTypeRef StructAggStatePerTransData;
 LLVMTypeRef StructPlanState;
+LLVMTypeRef StructWindowFuncExprState;
 
 LLVMValueRef AttributeTemplate;
 LLVMValueRef ExecEvalSubroutineTemplate;
 LLVMValueRef ExecEvalBoolSubroutineTemplate;
+*/
+char * llvm_expand_funcname_general(struct LLVMJitContext *context, const char *basename, int *counter);
+LLVMJitTypes llvm_jit_types_struct;
 
 static LLVMModuleRef llvm_types_module = NULL;
 
@@ -99,7 +104,8 @@ static LLVMOrcThreadSafeContextRef llvm_ts_context;
 static LLVMOrcLLJITRef llvm_opt0_orc;
 static LLVMOrcLLJITRef llvm_opt3_orc;
 
-
+static void llvm_create_types_context(LLVMJitTypes *jit_types_struct,
+			LLVMModuleRef *llvm_types_module, LLVMContextRef llvm_context);
 static void llvm_release_context(JitContext *context);
 static void llvm_session_initialize(void);
 static void llvm_shutdown(int code, Datum arg);
@@ -232,6 +238,8 @@ llvm_create_context(int jitFlags)
 	context = MemoryContextAllocZero(TopMemoryContext,
 									 sizeof(LLVMJitContext));
 	context->base.flags = jitFlags;
+	context->jit_types = &llvm_jit_types_struct;
+	context->llvm_types_module = llvm_types_module;
 
 	/* ensure cleanup */
 	context->resowner = CurrentResourceOwner;
@@ -242,6 +250,49 @@ llvm_create_context(int jitFlags)
 	return context;
 }
 
+/*
+ * Create a cached context for JITing work.
+ *
+ * The context, including subsidiary resources, will be cleaned up either when
+ * the context is explicitly released.
+ */
+LLVMJitContext *
+llvm_create_cached_context(int jitFlags)
+{
+	LLVMJitContext *context;
+
+	llvm_assert_in_fatal_section();
+
+	llvm_session_initialize();
+
+	context = MemoryContextAllocZero(TopMemoryContext,
+									 sizeof(LLVMJitContext));
+	context->base.flags = jitFlags;
+	context->llvm_context = LLVMContextCreate();
+	context->jit_types = MemoryContextAllocZero(TopMemoryContext,
+									 sizeof(LLVMJitTypes));
+
+	/// llvm_recreate_llvm_context();
+	/*
+	 * Synchronize types early, as that also includes inferring the target
+	 * triple.
+	 */
+	llvm_create_types_context(context->jit_types, &context->llvm_types_module, context->llvm_context);
+
+	///ResourceOwnerEnlarge(CurrentResourceOwner);
+
+
+
+	/* ensure cleanup */
+	///context->resowner = CurrentResourceOwner;
+	///ResourceOwnerRememberJIT(CurrentResourceOwner, context);
+
+	llvm_jit_context_in_use_count++;
+
+	return context;
+}
+
+
 /*
  * Release resources required by one llvm context.
  */
@@ -272,6 +323,11 @@ llvm_release_context(JitContext *context)
 		LLVMDisposeModule(llvm_jit_context->module);
 		llvm_jit_context->module = NULL;
 	}
+	if (llvm_jit_context->llvm_context && llvm_jit_context->llvm_types_module)
+	{
+		LLVMDisposeModule(llvm_jit_context->llvm_types_module);
+		llvm_jit_context->llvm_types_module = NULL;
+	}
 
 	foreach(lc, llvm_jit_context->handles)
 	{
@@ -304,6 +360,12 @@ llvm_release_context(JitContext *context)
 
 	if (llvm_jit_context->resowner)
 		ResourceOwnerForgetJIT(llvm_jit_context->resowner, llvm_jit_context);
+
+	if (llvm_jit_context->llvm_context)
+	{
+		LLVMContextDispose(llvm_context);
+		llvm_jit_context->llvm_context = NULL;
+	}
 }
 
 /*
@@ -321,7 +383,8 @@ llvm_mutable_module(LLVMJitContext *context)
 	{
 		context->compiled = false;
 		context->module_generation = llvm_generation++;
-		context->module = LLVMModuleCreateWithNameInContext("pg", llvm_context);
+		context->module = LLVMModuleCreateWithNameInContext("pg",
+			context->llvm_context? context->llvm_context : llvm_context);
 		LLVMSetTarget(context->module, llvm_triple);
 		LLVMSetDataLayout(context->module, llvm_layout);
 	}
@@ -329,28 +392,36 @@ llvm_mutable_module(LLVMJitContext *context)
 	return context->module;
 }
 
+char *
+llvm_expand_funcname_name(struct LLVMJitContext *context, const char *basename, Size counter)
+{
+		/*
+	 * Previously we used dots to separate, but turns out some tools, e.g.
+	 * GDB, don't like that and truncate name.
+	 */
+	return psprintf("%s_%zu_%zd",
+					basename,
+					context->module_generation,
+					counter);
+}
 /*
  * Expand function name to be non-conflicting. This should be used by code
  * generating code, when adding new externally visible function definitions to
  * a Module.
  */
 char *
-llvm_expand_funcname(struct LLVMJitContext *context, const char *basename)
+llvm_expand_funcname_general(struct LLVMJitContext *context, const char *basename, int *counter)
 {
-	Assert(context->module != NULL);
-
 	context->base.instr.created_functions++;
 
-	/*
-	 * Previously we used dots to separate, but turns out some tools, e.g.
-	 * GDB, don't like that and truncate name.
-	 */
-	return psprintf("%s_%zu_%d",
-					basename,
-					context->module_generation,
-					context->counter++);
+	return llvm_expand_funcname_name(context, basename, ++(*counter));
 }
 
+char *
+llvm_expand_funcname(struct LLVMJitContext *context, const char *basename)
+{
+	return llvm_expand_funcname_general(context, basename, &context->counter);
+}
 /*
  * Return pointer to function funcname, which has to exist. If there's pending
  * code to be optimized and emitted, do so first.
@@ -416,7 +487,7 @@ llvm_get_function(LLVMJitContext *context, const char *funcname)
  * in sync between plain C and JIT related code.
  */
 LLVMTypeRef
-llvm_pg_var_type(const char *varname)
+llvm_pg_var_type(LLVMModuleRef llvm_types_module, const char *varname)
 {
 	LLVMValueRef v_srcvar;
 	LLVMTypeRef typ;
@@ -436,12 +507,12 @@ llvm_pg_var_type(const char *varname)
  * keep function types in sync between C and JITed code.
  */
 LLVMTypeRef
-llvm_pg_var_func_type(const char *varname)
+llvm_pg_var_func_type(LLVMJitContext *context, const char *varname)
 {
 	LLVMValueRef v_srcvar;
 	LLVMTypeRef typ;
 
-	v_srcvar = LLVMGetNamedFunction(llvm_types_module, varname);
+	v_srcvar = LLVMGetNamedFunction(context->llvm_types_module, varname);
 	if (!v_srcvar)
 		elog(ERROR, "function %s not in llvmjit_types.c", varname);
 
@@ -458,22 +529,22 @@ llvm_pg_var_func_type(const char *varname)
  * the module that's currently being worked on.
  */
 LLVMValueRef
-llvm_pg_func(LLVMModuleRef mod, const char *funcname)
+llvm_pg_func(LLVMJitContext *context /*LLVMModuleRef mod*/, const char *funcname)
 {
 	LLVMValueRef v_srcfn;
 	LLVMValueRef v_fn;
 
 	/* don't repeatedly add function */
-	v_fn = LLVMGetNamedFunction(mod, funcname);
+	v_fn = LLVMGetNamedFunction(context->module, funcname);
 	if (v_fn)
 		return v_fn;
 
-	v_srcfn = LLVMGetNamedFunction(llvm_types_module, funcname);
+	v_srcfn = LLVMGetNamedFunction(context->llvm_types_module ? context->llvm_types_module : llvm_types_module, funcname);
 
 	if (!v_srcfn)
 		elog(ERROR, "function %s not in llvmjit_types.c", funcname);
 
-	v_fn = LLVMAddFunction(mod,
+	v_fn = LLVMAddFunction(context->module,
 						   funcname,
 						   LLVMGetFunctionType(v_srcfn));
 	llvm_copy_attributes(v_srcfn, v_fn);
@@ -537,7 +608,8 @@ LLVMValueRef
 llvm_function_reference(LLVMJitContext *context,
 						LLVMBuilderRef builder,
 						LLVMModuleRef mod,
-						FunctionCallInfo fcinfo)
+						FunctionCallInfo fcinfo,
+						LLVMValueRef v_fcinfo)
 {
 	char	   *modname;
 	char	   *basename;
@@ -570,17 +642,22 @@ llvm_function_reference(LLVMJitContext *context,
 							fcinfo->flinfo->fn_oid);
 		v_fn = LLVMGetNamedGlobal(mod, funcname);
 		if (v_fn != 0)
-			return l_load(builder, TypePGFunction, v_fn, "");
-
-		v_fn_addr = l_ptr_const(fcinfo->flinfo->fn_addr, TypePGFunction);
-
-		v_fn = LLVMAddGlobal(mod, TypePGFunction, funcname);
+			return l_load(builder, context->jit_types->TypePGFunction, v_fn, "");
+
+		v_fn_addr = l_ptr_const(fcinfo->flinfo->fn_addr, context->jit_types->TypePGFunction, context->jit_types->TypeSizeT);
+		///tmp = l_ptr_const_step(d.hashdatum.iresult, l_ptr(g->StructNullableDatum));
+		///tmp = l_struct_gep(b, g->StructNullableDatum, tmp, FIELDNO_NULLABLE_DATUM_DATUM, "");
+		/// params[1] =  ///l_ptr_const(fcinfo->args, l_ptr(LLVMInt8TypeInContext(lc)));
+		///			l_load_member_value_by_offset(b, lc , v_fcinfo, l_ptr(LLVMInt8TypeInContext(lc)), offsetof(FunctionCallInfoBaseData, args));
+		////v_fn_addr = l_load_member_value_by_offset(builder, lc , v_fcinfo, l_ptr(LLVMInt8TypeInContext(lc)), offsetof(FunctionCallInfoBaseData, flinfo));
+		////v_fn_addr = l_load_member_value_by_offset(builder, lc , v_fn_addr, context->jit_types->TypePGFunction, offsetof(FmgrInfo, fn_addr));
+		v_fn = LLVMAddGlobal(mod, context->jit_types->TypePGFunction, funcname);
 		LLVMSetInitializer(v_fn, v_fn_addr);
 		LLVMSetGlobalConstant(v_fn, true);
 		LLVMSetLinkage(v_fn, LLVMPrivateLinkage);
 		LLVMSetUnnamedAddr(v_fn, true);
 
-		return l_load(builder, TypePGFunction, v_fn, "");
+		return l_load(builder, context->jit_types->TypePGFunction, v_fn, "");
 	}
 
 	/* check if function already has been added */
@@ -588,7 +665,7 @@ llvm_function_reference(LLVMJitContext *context,
 	if (v_fn != 0)
 		return v_fn;
 
-	v_fn = LLVMAddFunction(mod, funcname, LLVMGetFunctionType(AttributeTemplate));
+	v_fn = LLVMAddFunction(mod, funcname, LLVMGetFunctionType(context->jit_types->AttributeTemplate));
 
 	return v_fn;
 }
@@ -980,12 +1057,10 @@ llvm_set_target(void)
 
 /*
  * Load required information, types, function signatures from llvmjit_types.c
- * and make them available in global variables.
- *
- * Those global variables are then used while emitting code.
+ * and save it in LLVMJitTypes struct.
  */
 static void
-llvm_create_types(void)
+llvm_create_types_context(LLVMJitTypes *jit_types_struct, LLVMModuleRef *llvm_types_module, LLVMContextRef llvm_context)
 {
 	char		path[MAXPGPATH];
 	LLVMMemoryBufferRef buf;
@@ -1001,39 +1076,56 @@ llvm_create_types(void)
 	}
 
 	/* eagerly load contents, going to need it all */
-	if (LLVMParseBitcodeInContext2(llvm_context, buf, &llvm_types_module))
+	if (LLVMParseBitcodeInContext2(llvm_context, buf, llvm_types_module))
 	{
 		elog(ERROR, "LLVMParseBitcodeInContext2 of %s failed", path);
 	}
 	LLVMDisposeMemoryBuffer(buf);
 
-	TypeSizeT = llvm_pg_var_type("TypeSizeT");
-	TypeParamBool = load_return_type(llvm_types_module, "FunctionReturningBool");
-	TypeStorageBool = llvm_pg_var_type("TypeStorageBool");
-	TypePGFunction = llvm_pg_var_type("TypePGFunction");
-	StructNullableDatum = llvm_pg_var_type("StructNullableDatum");
-	StructExprContext = llvm_pg_var_type("StructExprContext");
-	StructExprEvalStep = llvm_pg_var_type("StructExprEvalStep");
-	StructExprState = llvm_pg_var_type("StructExprState");
-	StructFunctionCallInfoData = llvm_pg_var_type("StructFunctionCallInfoData");
-	StructMemoryContextData = llvm_pg_var_type("StructMemoryContextData");
-	StructTupleTableSlot = llvm_pg_var_type("StructTupleTableSlot");
-	StructHeapTupleTableSlot = llvm_pg_var_type("StructHeapTupleTableSlot");
-	StructMinimalTupleTableSlot = llvm_pg_var_type("StructMinimalTupleTableSlot");
-	StructHeapTupleData = llvm_pg_var_type("StructHeapTupleData");
-	StructHeapTupleHeaderData = llvm_pg_var_type("StructHeapTupleHeaderData");
-	StructTupleDescData = llvm_pg_var_type("StructTupleDescData");
-	StructAggState = llvm_pg_var_type("StructAggState");
-	StructAggStatePerGroupData = llvm_pg_var_type("StructAggStatePerGroupData");
-	StructAggStatePerTransData = llvm_pg_var_type("StructAggStatePerTransData");
-	StructPlanState = llvm_pg_var_type("StructPlanState");
-	StructMinimalTupleData = llvm_pg_var_type("StructMinimalTupleData");
-
-	AttributeTemplate = LLVMGetNamedFunction(llvm_types_module, "AttributeTemplate");
-	ExecEvalSubroutineTemplate = LLVMGetNamedFunction(llvm_types_module, "ExecEvalSubroutineTemplate");
-	ExecEvalBoolSubroutineTemplate = LLVMGetNamedFunction(llvm_types_module, "ExecEvalBoolSubroutineTemplate");
+	jit_types_struct->TypeSizeT = llvm_pg_var_type(*llvm_types_module, "TypeSizeT");
+	jit_types_struct->TypeParamBool = load_return_type(*llvm_types_module, "FunctionReturningBool");
+	jit_types_struct->TypeStorageBool = llvm_pg_var_type(*llvm_types_module, "TypeStorageBool");
+	jit_types_struct->TypePGFunction = llvm_pg_var_type(*llvm_types_module, "TypePGFunction");
+	jit_types_struct->StructNullableDatum = llvm_pg_var_type(*llvm_types_module, "StructNullableDatum");
+	jit_types_struct->StructExprContext = llvm_pg_var_type(*llvm_types_module, "StructExprContext");
+	jit_types_struct->StructExprEvalStep = llvm_pg_var_type(*llvm_types_module, "StructExprEvalStep");
+	jit_types_struct->StructExprState = llvm_pg_var_type(*llvm_types_module, "StructExprState");
+	jit_types_struct->StructFunctionCallInfoData = llvm_pg_var_type(*llvm_types_module, "StructFunctionCallInfoData");
+	jit_types_struct->StructMemoryContextData = llvm_pg_var_type(*llvm_types_module, "StructMemoryContextData");
+	jit_types_struct->StructTupleTableSlot = llvm_pg_var_type(*llvm_types_module, "StructTupleTableSlot");
+	jit_types_struct->StructHeapTupleTableSlot = llvm_pg_var_type(*llvm_types_module, "StructHeapTupleTableSlot");
+	jit_types_struct->StructMinimalTupleTableSlot = llvm_pg_var_type(*llvm_types_module, "StructMinimalTupleTableSlot");
+	jit_types_struct->StructHeapTupleData = llvm_pg_var_type(*llvm_types_module, "StructHeapTupleData");
+	jit_types_struct->StructHeapTupleHeaderData = llvm_pg_var_type(*llvm_types_module, "StructHeapTupleHeaderData");
+	jit_types_struct->StructTupleDescData = llvm_pg_var_type(*llvm_types_module, "StructTupleDescData");
+	jit_types_struct->StructAggState = llvm_pg_var_type(*llvm_types_module, "StructAggState");
+	jit_types_struct->StructAggStatePerGroupData = llvm_pg_var_type(*llvm_types_module, "StructAggStatePerGroupData");
+	jit_types_struct->StructAggStatePerTransData = llvm_pg_var_type(*llvm_types_module, "StructAggStatePerTransData");
+	jit_types_struct->StructPlanState = llvm_pg_var_type(*llvm_types_module, "StructPlanState");
+	jit_types_struct->StructMinimalTupleData = llvm_pg_var_type(*llvm_types_module, "StructMinimalTupleData");
+	jit_types_struct->StructWindowFuncExprState = llvm_pg_var_type(*llvm_types_module, "StructWindowFuncExprState");
+
+	jit_types_struct->AttributeTemplate = LLVMGetNamedFunction(*llvm_types_module, "AttributeTemplate");
+	jit_types_struct->ExecEvalSubroutineTemplate = LLVMGetNamedFunction(*llvm_types_module, "ExecEvalSubroutineTemplate");
+	jit_types_struct->ExecEvalBoolSubroutineTemplate = LLVMGetNamedFunction(*llvm_types_module, "ExecEvalBoolSubroutineTemplate");
+	{
+		char *error = NULL;
+		LLVMVerifyModule(*llvm_types_module, LLVMAbortProcessAction, &error);
+		LLVMDisposeMessage(error);
+	}
 }
 
+/*
+ * Load required information, types, function signatures from llvmjit_types.c
+ * and make them available in global variables.
+ *
+ * Those global variables are then used while emitting code.
+ */
+static void
+llvm_create_types(void)
+{
+	llvm_create_types_context(&llvm_jit_types_struct, &llvm_types_module, llvm_context);
+}
 /*
  * Split a symbol into module / function parts.  If the function is in the
  * main binary (or an external library) *modname will be NULL.
diff --git a/src/backend/jit/llvm/llvmjit_deform.c b/src/backend/jit/llvm/llvmjit_deform.c
index 5d169c7a40b..789b7d478bb 100644
--- a/src/backend/jit/llvm/llvmjit_deform.c
+++ b/src/backend/jit/llvm/llvmjit_deform.c
@@ -78,6 +78,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 	LLVMValueRef v_hoff;
 
 	LLVMValueRef v_hasnulls;
+	LLVMJitTypes	*g;
 
 	/* last column (0 indexed) guaranteed to exist */
 	int			guaranteed_column_number = -1;
@@ -101,6 +102,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 
 	mod = llvm_mutable_module(context);
 	lc = LLVMGetModuleContext(mod);
+	g = context->jit_types;
 
 	funcname = llvm_expand_funcname(context, "deform");
 
@@ -133,7 +135,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 	{
 		LLVMTypeRef param_types[1];
 
-		param_types[0] = l_ptr(StructTupleTableSlot);
+		param_types[0] = l_ptr(g->StructTupleTableSlot);
 
 		deform_sig = LLVMFunctionType(LLVMVoidTypeInContext(lc),
 									  param_types, lengthof(param_types), 0);
@@ -141,7 +143,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 	v_deform_fn = LLVMAddFunction(mod, funcname, deform_sig);
 	LLVMSetLinkage(v_deform_fn, LLVMInternalLinkage);
 	LLVMSetParamAlignment(LLVMGetParam(v_deform_fn, 0), MAXIMUM_ALIGNOF);
-	llvm_copy_attributes(AttributeTemplate, v_deform_fn);
+	llvm_copy_attributes(g->AttributeTemplate, v_deform_fn);
 
 	b_entry =
 		LLVMAppendBasicBlockInContext(lc, v_deform_fn, "entry");
@@ -168,18 +170,18 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 	LLVMPositionBuilderAtEnd(b, b_entry);
 
 	/* perform allocas first, llvm only converts those to registers */
-	v_offp = LLVMBuildAlloca(b, TypeSizeT, "v_offp");
+	v_offp = LLVMBuildAlloca(b, g->TypeSizeT, "v_offp");
 
 	v_slot = LLVMGetParam(v_deform_fn, 0);
 
 	v_tts_values =
-		l_load_struct_gep(b, StructTupleTableSlot, v_slot, FIELDNO_TUPLETABLESLOT_VALUES,
+		l_load_struct_gep(b, g->StructTupleTableSlot, v_slot, FIELDNO_TUPLETABLESLOT_VALUES,
 						  "tts_values");
 	v_tts_nulls =
-		l_load_struct_gep(b, StructTupleTableSlot, v_slot, FIELDNO_TUPLETABLESLOT_ISNULL,
+		l_load_struct_gep(b, g->StructTupleTableSlot, v_slot, FIELDNO_TUPLETABLESLOT_ISNULL,
 						  "tts_ISNULL");
-	v_flagsp = l_struct_gep(b, StructTupleTableSlot, v_slot, FIELDNO_TUPLETABLESLOT_FLAGS, "");
-	v_nvalidp = l_struct_gep(b, StructTupleTableSlot, v_slot, FIELDNO_TUPLETABLESLOT_NVALID, "");
+	v_flagsp = l_struct_gep(b, g->StructTupleTableSlot, v_slot, FIELDNO_TUPLETABLESLOT_FLAGS, "");
+	v_nvalidp = l_struct_gep(b, g->StructTupleTableSlot, v_slot, FIELDNO_TUPLETABLESLOT_NVALID, "");
 
 	if (ops == &TTSOpsHeapTuple || ops == &TTSOpsBufferHeapTuple)
 	{
@@ -188,11 +190,11 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 		v_heapslot =
 			LLVMBuildBitCast(b,
 							 v_slot,
-							 l_ptr(StructHeapTupleTableSlot),
+							 l_ptr(g->StructHeapTupleTableSlot),
 							 "heapslot");
-		v_slotoffp = l_struct_gep(b, StructHeapTupleTableSlot, v_heapslot, FIELDNO_HEAPTUPLETABLESLOT_OFF, "");
+		v_slotoffp = l_struct_gep(b, g->StructHeapTupleTableSlot, v_heapslot, FIELDNO_HEAPTUPLETABLESLOT_OFF, "");
 		v_tupleheaderp =
-			l_load_struct_gep(b, StructHeapTupleTableSlot, v_heapslot, FIELDNO_HEAPTUPLETABLESLOT_TUPLE,
+			l_load_struct_gep(b, g->StructHeapTupleTableSlot, v_heapslot, FIELDNO_HEAPTUPLETABLESLOT_TUPLE,
 							  "tupleheader");
 	}
 	else if (ops == &TTSOpsMinimalTuple)
@@ -202,15 +204,15 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 		v_minimalslot =
 			LLVMBuildBitCast(b,
 							 v_slot,
-							 l_ptr(StructMinimalTupleTableSlot),
+							 l_ptr(g->StructMinimalTupleTableSlot),
 							 "minimalslot");
 		v_slotoffp = l_struct_gep(b,
-								  StructMinimalTupleTableSlot,
+								  g->StructMinimalTupleTableSlot,
 								  v_minimalslot,
 								  FIELDNO_MINIMALTUPLETABLESLOT_OFF, "");
 		v_tupleheaderp =
 			l_load_struct_gep(b,
-							  StructMinimalTupleTableSlot,
+							  g->StructMinimalTupleTableSlot,
 							  v_minimalslot,
 							  FIELDNO_MINIMALTUPLETABLESLOT_TUPLE,
 							  "tupleheader");
@@ -223,14 +225,14 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 
 	v_tuplep =
 		l_load_struct_gep(b,
-						  StructHeapTupleData,
+						  g->StructHeapTupleData,
 						  v_tupleheaderp,
 						  FIELDNO_HEAPTUPLEDATA_DATA,
 						  "tuple");
 	v_bits =
 		LLVMBuildBitCast(b,
 						 l_struct_gep(b,
-									  StructHeapTupleHeaderData,
+									  g->StructHeapTupleHeaderData,
 									  v_tuplep,
 									  FIELDNO_HEAPTUPLEHEADERDATA_BITS,
 									  ""),
@@ -238,13 +240,13 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 						 "t_bits");
 	v_infomask1 =
 		l_load_struct_gep(b,
-						  StructHeapTupleHeaderData,
+						  g->StructHeapTupleHeaderData,
 						  v_tuplep,
 						  FIELDNO_HEAPTUPLEHEADERDATA_INFOMASK,
 						  "infomask1");
 	v_infomask2 =
 		l_load_struct_gep(b,
-						  StructHeapTupleHeaderData,
+						  g->StructHeapTupleHeaderData,
 						  v_tuplep, FIELDNO_HEAPTUPLEHEADERDATA_INFOMASK2,
 						  "infomask2");
 
@@ -270,7 +272,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 	v_hoff =
 		LLVMBuildZExt(b,
 					  l_load_struct_gep(b,
-										StructHeapTupleHeaderData,
+										g->StructHeapTupleHeaderData,
 										v_tuplep,
 										FIELDNO_HEAPTUPLEHEADERDATA_HOFF,
 										""),
@@ -293,7 +295,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 		LLVMValueRef v_off_start;
 
 		v_off_start = l_load(b, LLVMInt32TypeInContext(lc), v_slotoffp, "v_slot_off");
-		v_off_start = LLVMBuildZExt(b, v_off_start, TypeSizeT, "");
+		v_off_start = LLVMBuildZExt(b, v_off_start, g->TypeSizeT, "");
 		LLVMBuildStore(b, v_off_start, v_offp);
 	}
 
@@ -349,7 +351,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 		v_params[0] = v_slot;
 		v_params[1] = LLVMBuildZExt(b, v_maxatt, LLVMInt32TypeInContext(lc), "");
 		v_params[2] = l_int32_const(lc, natts);
-		f = llvm_pg_func(mod, "slot_getmissingattrs");
+		f = llvm_pg_func(context, "slot_getmissingattrs");
 		l_call(b,
 			   LLVMGetFunctionType(f), f,
 			   v_params, lengthof(v_params), "");
@@ -409,7 +411,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 		 */
 		if (attnum == 0)
 		{
-			LLVMBuildStore(b, l_sizet_const(0), v_offp);
+			LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_offp);
 		}
 
 		/*
@@ -479,8 +481,8 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 						   l_gep(b, LLVMInt8TypeInContext(lc), v_tts_nulls, &l_attno, 1, ""));
 			/* store zero datum */
 			LLVMBuildStore(b,
-						   l_sizet_const(0),
-						   l_gep(b, TypeSizeT, v_tts_values, &l_attno, 1, ""));
+						   LLVMConstInt(g->TypeSizeT, 0, false),
+						   l_gep(b, g->TypeSizeT, v_tts_values, &l_attno, 1, ""));
 
 			LLVMBuildBr(b, b_next);
 			attguaranteedalign = false;
@@ -524,7 +526,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 				/* don't know if short varlena or not */
 				attguaranteedalign = false;
 
-				v_off = l_load(b, TypeSizeT, v_offp, "");
+				v_off = l_load(b, g->TypeSizeT, v_offp, "");
 
 				v_possible_padbyte =
 					l_load_gep1(b, LLVMInt8TypeInContext(lc), v_tupdata_base, v_off, "padbyte");
@@ -546,16 +548,16 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 			/* translation of alignment code (cf TYPEALIGN()) */
 			{
 				LLVMValueRef v_off_aligned;
-				LLVMValueRef v_off = l_load(b, TypeSizeT, v_offp, "");
+				LLVMValueRef v_off = l_load(b, g->TypeSizeT, v_offp, "");
 
 				/* ((ALIGNVAL) - 1) */
-				LLVMValueRef v_alignval = l_sizet_const(alignto - 1);
+				LLVMValueRef v_alignval = LLVMConstInt(g->TypeSizeT, alignto - 1, false);
 
 				/* ((uintptr_t) (LEN) + ((ALIGNVAL) - 1)) */
 				LLVMValueRef v_lh = LLVMBuildAdd(b, v_off, v_alignval, "");
 
 				/* ~((uintptr_t) ((ALIGNVAL) - 1)) */
-				LLVMValueRef v_rh = l_sizet_const(~(alignto - 1));
+				LLVMValueRef v_rh = LLVMConstInt(g->TypeSizeT, ~(alignto - 1), false);
 
 				v_off_aligned = LLVMBuildAnd(b, v_lh, v_rh, "aligned_offset");
 
@@ -594,7 +596,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 		if (attguaranteedalign)
 		{
 			Assert(known_alignment >= 0);
-			LLVMBuildStore(b, l_sizet_const(known_alignment), v_offp);
+			LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, known_alignment, false), v_offp);
 		}
 
 		/* compute what following columns are aligned to */
@@ -635,18 +637,18 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 
 		/* compute address to load data from */
 		{
-			LLVMValueRef v_off = l_load(b, TypeSizeT, v_offp, "");
+			LLVMValueRef v_off = l_load(b, g->TypeSizeT, v_offp, "");
 
 			v_attdatap =
 				l_gep(b, LLVMInt8TypeInContext(lc), v_tupdata_base, &v_off, 1, "");
 		}
 
 		/* compute address to store value at */
-		v_resultp = l_gep(b, TypeSizeT, v_tts_values, &l_attno, 1, "");
+		v_resultp = l_gep(b, g->TypeSizeT, v_tts_values, &l_attno, 1, "");
 
 		/* store null-byte (false) */
 		LLVMBuildStore(b, l_int8_const(lc, 0),
-					   l_gep(b, TypeStorageBool, v_tts_nulls, &l_attno, 1, ""));
+					   l_gep(b, g->TypeStorageBool, v_tts_nulls, &l_attno, 1, ""));
 
 		/*
 		 * Store datum. For byval: datums copy the value, extend to Datum's
@@ -661,7 +663,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 			v_tmp_loaddata =
 				LLVMBuildPointerCast(b, v_attdatap, vartypep, "");
 			v_tmp_loaddata = l_load(b, vartype, v_tmp_loaddata, "attr_byval");
-			v_tmp_loaddata = LLVMBuildZExt(b, v_tmp_loaddata, TypeSizeT, "");
+			v_tmp_loaddata = LLVMBuildZExt(b, v_tmp_loaddata, g->TypeSizeT, "");
 
 			LLVMBuildStore(b, v_tmp_loaddata, v_resultp);
 		}
@@ -673,7 +675,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 			v_tmp_loaddata =
 				LLVMBuildPtrToInt(b,
 								  v_attdatap,
-								  TypeSizeT,
+								  g->TypeSizeT,
 								  "attr_ptr");
 			LLVMBuildStore(b, v_tmp_loaddata, v_resultp);
 		}
@@ -681,13 +683,13 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 		/* increment data pointer */
 		if (att->attlen > 0)
 		{
-			v_incby = l_sizet_const(att->attlen);
+			v_incby = LLVMConstInt(g->TypeSizeT, att->attlen, false);
 		}
 		else if (att->attlen == -1)
 		{
 			v_incby = l_call(b,
-							 llvm_pg_var_func_type("varsize_any"),
-							 llvm_pg_func(mod, "varsize_any"),
+							 llvm_pg_var_func_type(context, "varsize_any"),
+							 llvm_pg_func(context, "varsize_any"),
 							 &v_attdatap, 1,
 							 "varsize_any");
 			l_callsite_ro(v_incby);
@@ -696,14 +698,14 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 		else if (att->attlen == -2)
 		{
 			v_incby = l_call(b,
-							 llvm_pg_var_func_type("strlen"),
-							 llvm_pg_func(mod, "strlen"),
+							 llvm_pg_var_func_type(context, "strlen"),
+							 llvm_pg_func(context, "strlen"),
 							 &v_attdatap, 1, "strlen");
 
 			l_callsite_ro(v_incby);
 
 			/* add 1 for NUL byte */
-			v_incby = LLVMBuildAdd(b, v_incby, l_sizet_const(1), "");
+			v_incby = LLVMBuildAdd(b, v_incby, LLVMConstInt(g->TypeSizeT, 1, false), "");
 		}
 		else
 		{
@@ -714,11 +716,11 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 		if (attguaranteedalign)
 		{
 			Assert(known_alignment >= 0);
-			LLVMBuildStore(b, l_sizet_const(known_alignment), v_offp);
+			LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, known_alignment, false), v_offp);
 		}
 		else
 		{
-			LLVMValueRef v_off = l_load(b, TypeSizeT, v_offp, "");
+			LLVMValueRef v_off = l_load(b, g->TypeSizeT, v_offp, "");
 
 			v_off = LLVMBuildAdd(b, v_off, v_incby, "increment_offset");
 			LLVMBuildStore(b, v_off, v_offp);
@@ -744,7 +746,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
 	LLVMPositionBuilderAtEnd(b, b_out);
 
 	{
-		LLVMValueRef v_off = l_load(b, TypeSizeT, v_offp, "");
+		LLVMValueRef v_off = l_load(b, g->TypeSizeT, v_offp, "");
 		LLVMValueRef v_flags;
 
 		LLVMBuildStore(b, l_int16_const(lc, natts), v_nvalidp);
diff --git a/src/backend/jit/llvm/llvmjit_expr.c b/src/backend/jit/llvm/llvmjit_expr.c
index f0f5c3bd49f..6380cd5b060 100644
--- a/src/backend/jit/llvm/llvmjit_expr.c
+++ b/src/backend/jit/llvm/llvmjit_expr.c
@@ -17,6 +17,7 @@
 
 #include <llvm-c/Core.h>
 #include <llvm-c/Target.h>
+#include <llvm-c/Analysis.h>
 
 #include "access/htup_details.h"
 #include "access/nbtree.h"
@@ -54,19 +55,25 @@ typedef struct CompiledExprState
 
 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 BuildV1Call(LLVMJitContext *context, LLVMBuilderRef b,
+///								LLVMModuleRef mod, FunctionCallInfo fcinfo,
+///								LLVMValueRef *v_fcinfo_isnull);
+static LLVMValueRef BuildV1CallLLVM(LLVMJitContext *context, LLVMBuilderRef b,
+			LLVMModuleRef mod, FunctionCallInfo fcinfo,
+			LLVMValueRef v_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 build_EvalXFuncIntLLVM(LLVMBuilderRef b, LLVMJitContext *context, const char *funcname,
+				   LLVMValueRef v_state, LLVMValueRef v_op,
+				   int nargs, LLVMValueRef *v_args);
 static LLVMValueRef create_LifetimeEnd(LLVMModuleRef mod);
 
 /* macro making it easier to call ExecEval* functions */
-#define build_EvalXFunc(b, mod, funcname, v_state, op, ...) \
-	build_EvalXFuncInt(b, mod, funcname, v_state, op, \
+#define build_EvalXFunc(b, context, funcname, v_state, op, ...) \
+	build_EvalXFuncIntLLVM(b, context, funcname, v_state, op, \
 					   lengthof(((LLVMValueRef[]){__VA_ARGS__})), \
 					   ((LLVMValueRef[]){__VA_ARGS__}))
 
@@ -84,6 +91,7 @@ llvm_compile_expr(ExprState *state)
 
 	LLVMBuilderRef b;
 	LLVMModuleRef mod;
+	LLVMModuleRef typesmod;
 	LLVMContextRef lc;
 	LLVMValueRef eval_fn;
 	LLVMBasicBlockRef entry;
@@ -93,6 +101,7 @@ llvm_compile_expr(ExprState *state)
 	LLVMValueRef v_state;
 	LLVMValueRef v_econtext;
 	LLVMValueRef v_parent;
+	LLVMValueRef v_steps;
 
 	/* returnvalue */
 	LLVMValueRef v_isnullp;
@@ -132,6 +141,8 @@ llvm_compile_expr(ExprState *state)
 	instr_time	endtime;
 	instr_time	deform_endtime;
 
+	LLVMJitTypes	*g;
+
 	llvm_enter_fatal_on_oom();
 
 	/*
@@ -141,29 +152,89 @@ llvm_compile_expr(ExprState *state)
 	Assert(parent);
 
 	/* get or create JIT context */
-	if (parent->state->es_jit)
-		context = (LLVMJitContext *) parent->state->es_jit;
-	else
+	if (parent->state->es_plannedstmt->jit_context == NULL || !jit_cached)
 	{
-		context = llvm_create_context(parent->state->es_jit_flags);
-		parent->state->es_jit = &context->base;
+		if (parent->state->es_jit)
+			context = (LLVMJitContext *) parent->state->es_jit;
+		else
+		{
+			context = llvm_create_context(parent->state->es_jit_flags);
+			parent->state->es_jit = &context->base;
+		}
+		mod = llvm_mutable_module(context);
+		funcname = llvm_expand_funcname(context, "evalexpr");
+
+		g = context->jit_types;
 	}
+	else
+	{
+		Expr *expr = state->expr;
+
+		if (!expr)
+		{
+			llvm_leave_fatal_on_oom();
+			return false;
+		}
+
+		if (parent->state->es_plannedstmt->jit_context == CACHED_JITCONTEXT_EMPTY)
+		{
+			context = llvm_create_cached_context(parent->state->es_jit_flags);
+			context->plan_mem_context =
+					GetMemoryChunkContext(parent->state->es_plannedstmt);
+			parent->state->es_plannedstmt->jit_context =
+					(JitContext*)context;
+		}
+		else
+		{
+			context = (LLVMJitContext*)parent->state->es_plannedstmt->jit_context;
+		}
+		if (context->plan_mem_context != GetMemoryChunkContext(expr))
+		{
+			llvm_leave_fatal_on_oom();
+			return false;
+		}
+
+		g = context->jit_types;
 
+		if (!context->compiled)
+		{
+			mod = llvm_mutable_module(context);
+			funcname = llvm_expand_funcname_name(context, "evalexpr", (Size)expr);
+			///elog(NOTICE,"Compile %s counter %d, context=%zx, expr=%zx, memcontext=%zx, memcontext plan=%zx",
+			///funcname, context->counter, (Size)context,(Size)expr,(Size)GetMemoryChunkContext(expr),
+			///(Size)GetMemoryChunkContext(parent->state->es_plannedstmt));
+		}
+		else
+		{
+			ExprStateEvalFunc func;
+
+
+			funcname = llvm_expand_funcname_name(context, "evalexpr", (Size)expr);
+			func = (ExprStateEvalFunc) llvm_get_function(context,funcname);
+			///elog(NOTICE,"1 Look for Compiled  context=%zx, expr=%zx, func=%zx, memcontext=%zx",
+			///(Size)context,(Size)expr,(Size)func,(Size)GetMemoryChunkContext(expr));
+			llvm_leave_fatal_on_oom();
+			Assert(func);
+			/* remove indirection via this function for future calls */
+			state->evalfunc = func;
+			pfree(funcname);
+			return true;
+		}
+	}
 	INSTR_TIME_SET_CURRENT(starttime);
 
-	mod = llvm_mutable_module(context);
 	lc = LLVMGetModuleContext(mod);
+	typesmod = context->llvm_types_module;
 
 	b = LLVMCreateBuilderInContext(lc);
 
-	funcname = llvm_expand_funcname(context, "evalexpr");
 
 	/* create function */
 	eval_fn = LLVMAddFunction(mod, funcname,
-							  llvm_pg_var_func_type("ExecInterpExprStillValid"));
+							  llvm_pg_var_func_type(context, "ExecInterpExprStillValid"));
 	LLVMSetLinkage(eval_fn, LLVMExternalLinkage);
 	LLVMSetVisibility(eval_fn, LLVMDefaultVisibility);
-	llvm_copy_attributes(AttributeTemplate, eval_fn);
+	llvm_copy_attributes(g->AttributeTemplate, eval_fn);
 
 	entry = LLVMAppendBasicBlockInContext(lc, eval_fn, "entry");
 
@@ -175,123 +246,128 @@ llvm_compile_expr(ExprState *state)
 	LLVMPositionBuilderAtEnd(b, entry);
 
 	v_tmpvaluep = l_struct_gep(b,
-							   StructExprState,
+							   g->StructExprState,
 							   v_state,
 							   FIELDNO_EXPRSTATE_RESVALUE,
 							   "v.state.resvalue");
 	v_tmpisnullp = l_struct_gep(b,
-								StructExprState,
+								g->StructExprState,
 								v_state,
 								FIELDNO_EXPRSTATE_RESNULL,
 								"v.state.resnull");
 	v_parent = l_load_struct_gep(b,
-								 StructExprState,
+								 g->StructExprState,
 								 v_state,
 								 FIELDNO_EXPRSTATE_PARENT,
 								 "v.state.parent");
+	v_steps = l_load_struct_gep(b,
+								g->StructExprState,
+								v_state,
+								FIELDNO_EXPRSTATE_STEPS,
+								"v_state_steps");
 
 	/* build global slots */
 	v_scanslot = l_load_struct_gep(b,
-								   StructExprContext,
+								   g->StructExprContext,
 								   v_econtext,
 								   FIELDNO_EXPRCONTEXT_SCANTUPLE,
 								   "v_scanslot");
 	v_innerslot = l_load_struct_gep(b,
-									StructExprContext,
+									g->StructExprContext,
 									v_econtext,
 									FIELDNO_EXPRCONTEXT_INNERTUPLE,
 									"v_innerslot");
 	v_outerslot = l_load_struct_gep(b,
-									StructExprContext,
+									g->StructExprContext,
 									v_econtext,
 									FIELDNO_EXPRCONTEXT_OUTERTUPLE,
 									"v_outerslot");
 	v_oldslot = l_load_struct_gep(b,
-								  StructExprContext,
+								  g->StructExprContext,
 								  v_econtext,
 								  FIELDNO_EXPRCONTEXT_OLDTUPLE,
 								  "v_oldslot");
 	v_newslot = l_load_struct_gep(b,
-								  StructExprContext,
+								  g->StructExprContext,
 								  v_econtext,
 								  FIELDNO_EXPRCONTEXT_NEWTUPLE,
 								  "v_newslot");
 	v_resultslot = l_load_struct_gep(b,
-									 StructExprState,
+									 g->StructExprState,
 									 v_state,
 									 FIELDNO_EXPRSTATE_RESULTSLOT,
 									 "v_resultslot");
 
 	/* build global values/isnull pointers */
 	v_scanvalues = l_load_struct_gep(b,
-									 StructTupleTableSlot,
+									 g->StructTupleTableSlot,
 									 v_scanslot,
 									 FIELDNO_TUPLETABLESLOT_VALUES,
 									 "v_scanvalues");
 	v_scannulls = l_load_struct_gep(b,
-									StructTupleTableSlot,
+									g->StructTupleTableSlot,
 									v_scanslot,
 									FIELDNO_TUPLETABLESLOT_ISNULL,
 									"v_scannulls");
 	v_innervalues = l_load_struct_gep(b,
-									  StructTupleTableSlot,
+									  g->StructTupleTableSlot,
 									  v_innerslot,
 									  FIELDNO_TUPLETABLESLOT_VALUES,
 									  "v_innervalues");
 	v_innernulls = l_load_struct_gep(b,
-									 StructTupleTableSlot,
+									 g->StructTupleTableSlot,
 									 v_innerslot,
 									 FIELDNO_TUPLETABLESLOT_ISNULL,
 									 "v_innernulls");
 	v_outervalues = l_load_struct_gep(b,
-									  StructTupleTableSlot,
+									  g->StructTupleTableSlot,
 									  v_outerslot,
 									  FIELDNO_TUPLETABLESLOT_VALUES,
 									  "v_outervalues");
 	v_outernulls = l_load_struct_gep(b,
-									 StructTupleTableSlot,
+									 g->StructTupleTableSlot,
 									 v_outerslot,
 									 FIELDNO_TUPLETABLESLOT_ISNULL,
 									 "v_outernulls");
 	v_oldvalues = l_load_struct_gep(b,
-									StructTupleTableSlot,
+									g->StructTupleTableSlot,
 									v_oldslot,
 									FIELDNO_TUPLETABLESLOT_VALUES,
 									"v_oldvalues");
 	v_oldnulls = l_load_struct_gep(b,
-								   StructTupleTableSlot,
+								   g->StructTupleTableSlot,
 								   v_oldslot,
 								   FIELDNO_TUPLETABLESLOT_ISNULL,
 								   "v_oldnulls");
 	v_newvalues = l_load_struct_gep(b,
-									StructTupleTableSlot,
+									g->StructTupleTableSlot,
 									v_newslot,
 									FIELDNO_TUPLETABLESLOT_VALUES,
 									"v_newvalues");
 	v_newnulls = l_load_struct_gep(b,
-								   StructTupleTableSlot,
+								   g->StructTupleTableSlot,
 								   v_newslot,
 								   FIELDNO_TUPLETABLESLOT_ISNULL,
 								   "v_newnulls");
 	v_resultvalues = l_load_struct_gep(b,
-									   StructTupleTableSlot,
+									   g->StructTupleTableSlot,
 									   v_resultslot,
 									   FIELDNO_TUPLETABLESLOT_VALUES,
 									   "v_resultvalues");
 	v_resultnulls = l_load_struct_gep(b,
-									  StructTupleTableSlot,
+									  g->StructTupleTableSlot,
 									  v_resultslot,
 									  FIELDNO_TUPLETABLESLOT_ISNULL,
 									  "v_resultnulls");
 
 	/* aggvalues/aggnulls */
 	v_aggvalues = l_load_struct_gep(b,
-									StructExprContext,
+									g->StructExprContext,
 									v_econtext,
 									FIELDNO_EXPRCONTEXT_AGGVALUES,
 									"v.econtext.aggvalues");
 	v_aggnulls = l_load_struct_gep(b,
-								   StructExprContext,
+								   g->StructExprContext,
 								   v_econtext,
 								   FIELDNO_EXPRCONTEXT_AGGNULLS,
 								   "v.econtext.aggnulls");
@@ -308,16 +384,22 @@ llvm_compile_expr(ExprState *state)
 	{
 		ExprEvalStep *op;
 		ExprEvalOp	opcode;
+		LLVMValueRef v_op;
+		LLVMValueRef v_opno;
 		LLVMValueRef v_resvaluep;
 		LLVMValueRef v_resnullp;
 
+
 		LLVMPositionBuilderAtEnd(b, opblocks[opno]);
 
 		op = &state->steps[opno];
 		opcode = ExecEvalStepOp(state, op);
-
-		v_resvaluep = l_ptr_const(op->resvalue, l_ptr(TypeSizeT));
-		v_resnullp = l_ptr_const(op->resnull, l_ptr(TypeStorageBool));
+		v_opno = l_int32_const(lc, opno);
+		v_op = l_gep(b, g->StructExprEvalStep, v_steps, &v_opno, 1, "v_op_step");
+		///v_resvaluep = l_ptr_const(op->resvalue, l_ptr(TypeSizeT));
+		///v_resnullp = l_ptr_const(op->resnull, l_ptr(g->TypeStorageBool));
+		v_resvaluep = l_load_struct_gep( b, g->StructExprEvalStep, v_op, FIELDNO_EXPREVALSTEP_RESVALUE, "v_resvaluep");
+		v_resnullp = l_load_struct_gep( b, g->StructExprEvalStep, v_op, FIELDNO_EXPREVALSTEP_RESNULL, "v_resnullp");
 
 		switch (opcode)
 		{
@@ -326,8 +408,8 @@ llvm_compile_expr(ExprState *state)
 					LLVMValueRef v_tmpisnull;
 					LLVMValueRef v_tmpvalue;
 
-					v_tmpvalue = l_load(b, TypeSizeT, v_tmpvaluep, "");
-					v_tmpisnull = l_load(b, TypeStorageBool, v_tmpisnullp, "");
+					v_tmpvalue = l_load(b, g->TypeSizeT, v_tmpvaluep, "");
+					v_tmpisnull = l_load(b, g->TypeStorageBool, v_tmpisnullp, "");
 
 					LLVMBuildStore(b, v_tmpisnull, v_isnullp);
 
@@ -377,7 +459,7 @@ llvm_compile_expr(ExprState *state)
 					 */
 					v_nvalid =
 						l_load_struct_gep(b,
-										  StructTupleTableSlot,
+										  g->StructTupleTableSlot,
 										  v_slot,
 										  FIELDNO_TUPLETABLESLOT_NVALID,
 										  "");
@@ -426,8 +508,8 @@ llvm_compile_expr(ExprState *state)
 						params[1] = l_int32_const(lc, op->d.fetch.last_var);
 
 						l_call(b,
-							   llvm_pg_var_func_type("slot_getsomeattrs_int"),
-							   llvm_pg_func(mod, "slot_getsomeattrs_int"),
+							   llvm_pg_var_func_type(context, "slot_getsomeattrs_int"),
+							   llvm_pg_func(context, "slot_getsomeattrs_int"),
 							   params, lengthof(params), "");
 					}
 
@@ -474,8 +556,8 @@ llvm_compile_expr(ExprState *state)
 					}
 
 					v_attnum = l_int32_const(lc, op->d.var.attnum);
-					value = l_load_gep1(b, TypeSizeT, v_values, v_attnum, "");
-					isnull = l_load_gep1(b, TypeStorageBool, v_nulls, v_attnum, "");
+					value = l_load_gep1(b, g->TypeSizeT, v_values, v_attnum, "");
+					isnull = l_load_gep1(b, g->TypeStorageBool, v_nulls, v_attnum, "");
 					LLVMBuildStore(b, value, v_resvaluep);
 					LLVMBuildStore(b, isnull, v_resnullp);
 
@@ -502,16 +584,16 @@ llvm_compile_expr(ExprState *state)
 					else
 						v_slot = v_newslot;
 
-					build_EvalXFunc(b, mod, "ExecEvalSysVar",
-									v_state, op, v_econtext, v_slot);
+					build_EvalXFunc(b, context, "ExecEvalSysVar",
+									v_state, v_op, v_econtext, v_slot);
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
 					break;
 				}
 
 			case EEOP_WHOLEROW:
-				build_EvalXFunc(b, mod, "ExecEvalWholeRowVar",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalWholeRowVar",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -558,17 +640,17 @@ llvm_compile_expr(ExprState *state)
 
 					/* load data */
 					v_attnum = l_int32_const(lc, op->d.assign_var.attnum);
-					v_value = l_load_gep1(b, TypeSizeT, v_values, v_attnum, "");
-					v_isnull = l_load_gep1(b, TypeStorageBool, v_nulls, v_attnum, "");
+					v_value = l_load_gep1(b, g->TypeSizeT, v_values, v_attnum, "");
+					v_isnull = l_load_gep1(b, g->TypeStorageBool, v_nulls, v_attnum, "");
 
 					/* compute addresses of targets */
 					v_resultnum = l_int32_const(lc, op->d.assign_var.resultnum);
 					v_rvaluep = l_gep(b,
-									  TypeSizeT,
+									  g->TypeSizeT,
 									  v_resultvalues,
 									  &v_resultnum, 1, "");
 					v_risnullp = l_gep(b,
-									   TypeStorageBool,
+									   g->TypeStorageBool,
 									   v_resultnulls,
 									   &v_resultnum, 1, "");
 
@@ -591,15 +673,15 @@ llvm_compile_expr(ExprState *state)
 					size_t		resultnum = op->d.assign_tmp.resultnum;
 
 					/* load data */
-					v_value = l_load(b, TypeSizeT, v_tmpvaluep, "");
-					v_isnull = l_load(b, TypeStorageBool, v_tmpisnullp, "");
+					v_value = l_load(b, g->TypeSizeT, v_tmpvaluep, "");
+					v_isnull = l_load(b, g->TypeStorageBool, v_tmpisnullp, "");
 
 					/* compute addresses of targets */
 					v_resultnum = l_int32_const(lc, resultnum);
 					v_rvaluep =
-						l_gep(b, TypeSizeT, v_resultvalues, &v_resultnum, 1, "");
+						l_gep(b, g->TypeSizeT, v_resultvalues, &v_resultnum, 1, "");
 					v_risnullp =
-						l_gep(b, TypeStorageBool, v_resultnulls, &v_resultnum, 1, "");
+						l_gep(b, g->TypeStorageBool, v_resultnulls, &v_resultnum, 1, "");
 
 					/* store nullness */
 					LLVMBuildStore(b, v_isnull, v_risnullp);
@@ -616,7 +698,7 @@ llvm_compile_expr(ExprState *state)
 						/* check if value is NULL */
 						LLVMBuildCondBr(b,
 										LLVMBuildICmp(b, LLVMIntEQ, v_isnull,
-													  l_sbool_const(0), ""),
+													  LLVMConstInt(g->TypeStorageBool, (int)(0), false), ""),
 										b_notnull, opblocks[opno + 1]);
 
 						/* if value is not null, convert to RO datum */
@@ -624,8 +706,8 @@ llvm_compile_expr(ExprState *state)
 						v_params[0] = v_value;
 						v_value =
 							l_call(b,
-								   llvm_pg_var_func_type("MakeExpandedObjectReadOnlyInternal"),
-								   llvm_pg_func(mod, "MakeExpandedObjectReadOnlyInternal"),
+								   llvm_pg_var_func_type(context, "MakeExpandedObjectReadOnlyInternal"),
+								   llvm_pg_func(context, "MakeExpandedObjectReadOnlyInternal"),
 								   v_params, lengthof(v_params), "");
 
 						/*
@@ -646,8 +728,8 @@ llvm_compile_expr(ExprState *state)
 					LLVMValueRef v_constvalue,
 								v_constnull;
 
-					v_constvalue = l_sizet_const(op->d.constval.value);
-					v_constnull = l_sbool_const(op->d.constval.isnull);
+					v_constvalue = LLVMConstInt(g->TypeSizeT, op->d.constval.value, false);
+					v_constnull = LLVMConstInt(g->TypeStorageBool, (int)(op->d.constval.isnull), false);
 
 					LLVMBuildStore(b, v_constvalue, v_resvaluep);
 					LLVMBuildStore(b, v_constnull, v_resnullp);
@@ -662,12 +744,12 @@ llvm_compile_expr(ExprState *state)
 					FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
 					LLVMValueRef v_fcinfo_isnull;
 					LLVMValueRef v_retval;
+					LLVMValueRef v_fcinfo;
 
 					if (opcode == EEOP_FUNCEXPR_STRICT)
 					{
 						LLVMBasicBlockRef b_nonull;
 						LLVMBasicBlockRef *b_checkargnulls;
-						LLVMValueRef v_fcinfo;
 
 						/*
 						 * Block for the actual function call, if args are
@@ -680,14 +762,18 @@ llvm_compile_expr(ExprState *state)
 						if (op->d.func.nargs == 0)
 							elog(ERROR, "argumentless strict functions are pointless");
 
+						///v_fcinfo =
+						///	l_ptr_const(fcinfo, l_ptr(g->StructFunctionCallInfoData));
 						v_fcinfo =
-							l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
+							///l_struct_member_ptr_by_offset(b,lc, v_op, offsetof(ExprEvalStep ,d.func.fcinfo_data ));
+							l_load_member_value_by_offset(b,lc, v_op,
+								l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep ,d.func.fcinfo_data ));
 
 						/*
 						 * set resnull to true, if the function is actually
 						 * called, it'll be reset
 						 */
-						LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(1), false), v_resnullp);
 
 						/* create blocks for checking args, one for each */
 						b_checkargnulls =
@@ -718,11 +804,11 @@ llvm_compile_expr(ExprState *state)
 								b_argnotnull = b_checkargnulls[argno + 1];
 
 							/* and finally load & check NULLness of arg */
-							v_argisnull = l_funcnull(b, v_fcinfo, argno);
+							v_argisnull = l_funcnull(b, v_fcinfo, argno, g);
 							LLVMBuildCondBr(b,
 											LLVMBuildICmp(b, LLVMIntEQ,
 														  v_argisnull,
-														  l_sbool_const(1),
+														  LLVMConstInt(g->TypeStorageBool, (int)(1), false),
 														  ""),
 											opblocks[opno + 1],
 											b_argnotnull);
@@ -730,8 +816,13 @@ llvm_compile_expr(ExprState *state)
 
 						LLVMPositionBuilderAtEnd(b, b_nonull);
 					}
+					else
+					{
+						v_fcinfo = l_load_member_value_by_offset(b,lc, v_op,
+								l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep ,d.func.fcinfo_data ));
+					}
 
-					v_retval = BuildV1Call(context, b, mod, fcinfo,
+					v_retval = BuildV1CallLLVM(context, b, mod, fcinfo, v_fcinfo,
 										   &v_fcinfo_isnull);
 					LLVMBuildStore(b, v_retval, v_resvaluep);
 					LLVMBuildStore(b, v_fcinfo_isnull, v_resnullp);
@@ -741,15 +832,15 @@ llvm_compile_expr(ExprState *state)
 				}
 
 			case EEOP_FUNCEXPR_FUSAGE:
-				build_EvalXFunc(b, mod, "ExecEvalFuncExprFusage",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalFuncExprFusage",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 
 			case EEOP_FUNCEXPR_STRICT_FUSAGE:
-				build_EvalXFunc(b, mod, "ExecEvalFuncExprStrictFusage",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalFuncExprStrictFusage",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -783,26 +874,28 @@ llvm_compile_expr(ExprState *state)
 					b_boolcont = l_bb_before_v(opblocks[opno + 1],
 											   "b.%d.boolcont", opno);
 
-					v_boolanynullp = l_ptr_const(op->d.boolexpr.anynull,
-												 l_ptr(TypeStorageBool));
+					v_boolanynullp = ///l_ptr_const(op->d.boolexpr.anynull,
+									///			 l_ptr(g->TypeStorageBool));
+									l_load_member_value_by_offset(b,lc, v_op,
+								l_ptr(g->TypeStorageBool), offsetof(ExprEvalStep ,d.boolexpr.anynull ));
 
 					if (opcode == EEOP_BOOL_AND_STEP_FIRST)
-						LLVMBuildStore(b, l_sbool_const(0), v_boolanynullp);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_boolanynullp);
 
-					v_boolnull = l_load(b, TypeStorageBool, v_resnullp, "");
-					v_boolvalue = l_load(b, TypeSizeT, v_resvaluep, "");
+					v_boolnull = l_load(b, g->TypeStorageBool, v_resnullp, "");
+					v_boolvalue = l_load(b, g->TypeSizeT, v_resvaluep, "");
 
 					/* check if current input is NULL */
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_boolnull,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									b_boolisnull,
 									b_boolcheckfalse);
 
 					/* build block that sets anynull */
 					LLVMPositionBuilderAtEnd(b, b_boolisnull);
 					/* set boolanynull to true */
-					LLVMBuildStore(b, l_sbool_const(1), v_boolanynullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(1), false), v_boolanynullp);
 					/* and jump to next block */
 					LLVMBuildBr(b, b_boolcont);
 
@@ -810,7 +903,7 @@ llvm_compile_expr(ExprState *state)
 					LLVMPositionBuilderAtEnd(b, b_boolcheckfalse);
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_boolvalue,
-												  l_sizet_const(0), ""),
+												  LLVMConstInt(g->TypeSizeT, 0, false), ""),
 									b_boolisfalse,
 									b_boolcont);
 
@@ -826,19 +919,19 @@ llvm_compile_expr(ExprState *state)
 					/* Build block that continues if bool is TRUE. */
 					LLVMPositionBuilderAtEnd(b, b_boolcont);
 
-					v_boolanynull = l_load(b, TypeStorageBool, v_boolanynullp, "");
+					v_boolanynull = l_load(b, g->TypeStorageBool, v_boolanynullp, "");
 
 					/* set value to NULL if any previous values were NULL */
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_boolanynull,
-												  l_sbool_const(0), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(0), false), ""),
 									opblocks[opno + 1], b_boolisanynull);
 
 					LLVMPositionBuilderAtEnd(b, b_boolisanynull);
 					/* set resnull to true */
-					LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(1), false), v_resnullp);
 					/* reset resvalue */
-					LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_resvaluep);
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
 					break;
@@ -875,24 +968,26 @@ llvm_compile_expr(ExprState *state)
 					b_boolcont = l_bb_before_v(opblocks[opno + 1],
 											   "b.%d.boolcont", opno);
 
-					v_boolanynullp = l_ptr_const(op->d.boolexpr.anynull,
-												 l_ptr(TypeStorageBool));
+					v_boolanynullp = ///l_ptr_const(op->d.boolexpr.anynull,
+									///			 l_ptr(g->TypeStorageBool));
+									 l_ptr_const_step(d.boolexpr.anynull,
+												 l_ptr(g->TypeStorageBool));
 
 					if (opcode == EEOP_BOOL_OR_STEP_FIRST)
-						LLVMBuildStore(b, l_sbool_const(0), v_boolanynullp);
-					v_boolnull = l_load(b, TypeStorageBool, v_resnullp, "");
-					v_boolvalue = l_load(b, TypeSizeT, v_resvaluep, "");
+						LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_boolanynullp);
+					v_boolnull = l_load(b, g->TypeStorageBool, v_resnullp, "");
+					v_boolvalue = l_load(b, g->TypeSizeT, v_resvaluep, "");
 
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_boolnull,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									b_boolisnull,
 									b_boolchecktrue);
 
 					/* build block that sets anynull */
 					LLVMPositionBuilderAtEnd(b, b_boolisnull);
 					/* set boolanynull to true */
-					LLVMBuildStore(b, l_sbool_const(1), v_boolanynullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(1), false), v_boolanynullp);
 					/* and jump to next block */
 					LLVMBuildBr(b, b_boolcont);
 
@@ -900,7 +995,7 @@ llvm_compile_expr(ExprState *state)
 					LLVMPositionBuilderAtEnd(b, b_boolchecktrue);
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_boolvalue,
-												  l_sizet_const(1), ""),
+												  LLVMConstInt(g->TypeSizeT, 1, false), ""),
 									b_boolistrue,
 									b_boolcont);
 
@@ -916,19 +1011,19 @@ llvm_compile_expr(ExprState *state)
 					/* build block that continues if bool is FALSE */
 					LLVMPositionBuilderAtEnd(b, b_boolcont);
 
-					v_boolanynull = l_load(b, TypeStorageBool, v_boolanynullp, "");
+					v_boolanynull = l_load(b, g->TypeStorageBool, v_boolanynullp, "");
 
 					/* set value to NULL if any previous values were NULL */
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_boolanynull,
-												  l_sbool_const(0), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(0), false), ""),
 									opblocks[opno + 1], b_boolisanynull);
 
 					LLVMPositionBuilderAtEnd(b, b_boolisanynull);
 					/* set resnull to true */
-					LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(1), false), v_resnullp);
 					/* reset resvalue */
-					LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_resvaluep);
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
 					break;
@@ -940,13 +1035,13 @@ llvm_compile_expr(ExprState *state)
 					LLVMValueRef v_negbool;
 
 					/* compute !boolvalue */
-					v_boolvalue = l_load(b, TypeSizeT, v_resvaluep, "");
+					v_boolvalue = l_load(b, g->TypeSizeT, v_resvaluep, "");
 					v_negbool = LLVMBuildZExt(b,
 											  LLVMBuildICmp(b, LLVMIntEQ,
 															v_boolvalue,
-															l_sizet_const(0),
+															LLVMConstInt(g->TypeSizeT, 0, false),
 															""),
-											  TypeSizeT, "");
+											  g->TypeSizeT, "");
 
 					/*
 					 * Store it back in resvalue.  We can ignore resnull here;
@@ -969,15 +1064,15 @@ llvm_compile_expr(ExprState *state)
 					b_qualfail = l_bb_before_v(opblocks[opno + 1],
 											   "op.%d.qualfail", opno);
 
-					v_resvalue = l_load(b, TypeSizeT, v_resvaluep, "");
-					v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
+					v_resvalue = l_load(b, g->TypeSizeT, v_resvaluep, "");
+					v_resnull = l_load(b, g->TypeStorageBool, v_resnullp, "");
 
 					v_nullorfalse =
 						LLVMBuildOr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									LLVMBuildICmp(b, LLVMIntEQ, v_resvalue,
-												  l_sizet_const(0), ""),
+												  LLVMConstInt(g->TypeSizeT, 0, false), ""),
 									"");
 
 					LLVMBuildCondBr(b,
@@ -988,9 +1083,9 @@ llvm_compile_expr(ExprState *state)
 					/* build block handling NULL or false */
 					LLVMPositionBuilderAtEnd(b, b_qualfail);
 					/* set resnull to false */
-					LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_resnullp);
 					/* set resvalue to false */
-					LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_resvaluep);
 					/* and jump out */
 					LLVMBuildBr(b, opblocks[op->d.qualexpr.jumpdone]);
 					break;
@@ -1008,11 +1103,11 @@ llvm_compile_expr(ExprState *state)
 
 					/* Transfer control if current result is null */
 
-					v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
+					v_resnull = l_load(b, g->TypeStorageBool, v_resnullp, "");
 
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									opblocks[op->d.jump.jumpdone],
 									opblocks[opno + 1]);
 					break;
@@ -1024,11 +1119,11 @@ llvm_compile_expr(ExprState *state)
 
 					/* Transfer control if current result is non-null */
 
-					v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
+					v_resnull = l_load(b, g->TypeStorageBool, v_resnullp, "");
 
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
-												  l_sbool_const(0), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(0), false), ""),
 									opblocks[op->d.jump.jumpdone],
 									opblocks[opno + 1]);
 					break;
@@ -1043,15 +1138,15 @@ llvm_compile_expr(ExprState *state)
 
 					/* Transfer control if current result is null or false */
 
-					v_resvalue = l_load(b, TypeSizeT, v_resvaluep, "");
-					v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
+					v_resvalue = l_load(b, g->TypeSizeT, v_resvaluep, "");
+					v_resnull = l_load(b, g->TypeStorageBool, v_resnullp, "");
 
 					v_nullorfalse =
 						LLVMBuildOr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									LLVMBuildICmp(b, LLVMIntEQ, v_resvalue,
-												  l_sizet_const(0), ""),
+												  LLVMConstInt(g->TypeSizeT, 0, false), ""),
 									"");
 
 					LLVMBuildCondBr(b,
@@ -1063,18 +1158,18 @@ llvm_compile_expr(ExprState *state)
 
 			case EEOP_NULLTEST_ISNULL:
 				{
-					LLVMValueRef v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
+					LLVMValueRef v_resnull = l_load(b, g->TypeStorageBool, v_resnullp, "");
 					LLVMValueRef v_resvalue;
 
 					v_resvalue =
 						LLVMBuildSelect(b,
 										LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
-													  l_sbool_const(1), ""),
-										l_sizet_const(1),
-										l_sizet_const(0),
+													  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
+										LLVMConstInt(g->TypeSizeT, 1, false),
+										LLVMConstInt(g->TypeSizeT, 0, false),
 										"");
 					LLVMBuildStore(b, v_resvalue, v_resvaluep);
-					LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_resnullp);
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
 					break;
@@ -1082,32 +1177,32 @@ llvm_compile_expr(ExprState *state)
 
 			case EEOP_NULLTEST_ISNOTNULL:
 				{
-					LLVMValueRef v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
+					LLVMValueRef v_resnull = l_load(b, g->TypeStorageBool, v_resnullp, "");
 					LLVMValueRef v_resvalue;
 
 					v_resvalue =
 						LLVMBuildSelect(b,
 										LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
-													  l_sbool_const(1), ""),
-										l_sizet_const(0),
-										l_sizet_const(1),
+													  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
+										LLVMConstInt(g->TypeSizeT, 0, false),
+										LLVMConstInt(g->TypeSizeT, 1, false),
 										"");
 					LLVMBuildStore(b, v_resvalue, v_resvaluep);
-					LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_resnullp);
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
 					break;
 				}
 
 			case EEOP_NULLTEST_ROWISNULL:
-				build_EvalXFunc(b, mod, "ExecEvalRowNull",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalRowNull",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_NULLTEST_ROWISNOTNULL:
-				build_EvalXFunc(b, mod, "ExecEvalRowNotNull",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalRowNotNull",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -1118,7 +1213,7 @@ llvm_compile_expr(ExprState *state)
 				{
 					LLVMBasicBlockRef b_isnull,
 								b_notnull;
-					LLVMValueRef v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
+					LLVMValueRef v_resnull = l_load(b, g->TypeStorageBool, v_resnullp, "");
 
 					b_isnull = l_bb_before_v(opblocks[opno + 1],
 											 "op.%d.isnull", opno);
@@ -1128,23 +1223,23 @@ llvm_compile_expr(ExprState *state)
 					/* check if value is NULL */
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									b_isnull, b_notnull);
 
 					/* if value is NULL, return false */
 					LLVMPositionBuilderAtEnd(b, b_isnull);
 
 					/* result is not null */
-					LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_resnullp);
 
 					if (opcode == EEOP_BOOLTEST_IS_TRUE ||
 						opcode == EEOP_BOOLTEST_IS_FALSE)
 					{
-						LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_resvaluep);
 					}
 					else
 					{
-						LLVMBuildStore(b, l_sizet_const(1), v_resvaluep);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 1, false), v_resvaluep);
 					}
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
@@ -1162,14 +1257,14 @@ llvm_compile_expr(ExprState *state)
 					else
 					{
 						LLVMValueRef v_value =
-							l_load(b, TypeSizeT, v_resvaluep, "");
+							l_load(b, g->TypeSizeT, v_resvaluep, "");
 
 						v_value = LLVMBuildZExt(b,
 												LLVMBuildICmp(b, LLVMIntEQ,
 															  v_value,
-															  l_sizet_const(0),
+															  LLVMConstInt(g->TypeSizeT, 0, false),
 															  ""),
-												TypeSizeT, "");
+												g->TypeSizeT, "");
 						LLVMBuildStore(b, v_value, v_resvaluep);
 					}
 					LLVMBuildBr(b, opblocks[opno + 1]);
@@ -1177,14 +1272,14 @@ llvm_compile_expr(ExprState *state)
 				}
 
 			case EEOP_PARAM_EXEC:
-				build_EvalXFunc(b, mod, "ExecEvalParamExec",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalParamExec",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_PARAM_EXTERN:
-				build_EvalXFunc(b, mod, "ExecEvalParamExtern",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalParamExtern",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -1193,14 +1288,17 @@ llvm_compile_expr(ExprState *state)
 					LLVMValueRef v_func;
 					LLVMValueRef v_params[3];
 
-					v_func = l_ptr_const(op->d.cparam.paramfunc,
-										 llvm_pg_var_type("TypeExecEvalSubroutine"));
+					v_func = ///l_ptr_const(op->d.cparam.paramfunc,
+							///			 llvm_pg_var_type("TypeExecEvalSubroutine"));
+							l_ptr_const_step(d.cparam.paramfunc,
+										 llvm_pg_var_type(typesmod, "TypeExecEvalSubroutine"));
 
 					v_params[0] = v_state;
-					v_params[1] = l_ptr_const(op, l_ptr(StructExprEvalStep));
+					v_params[1] = ///l_ptr_const(op, l_ptr(g->StructExprEvalStep));
+								v_op;
 					v_params[2] = v_econtext;
 					l_call(b,
-						   LLVMGetFunctionType(ExecEvalSubroutineTemplate),
+						   LLVMGetFunctionType(g->ExecEvalSubroutineTemplate),
 						   v_func,
 						   v_params, lengthof(v_params), "");
 
@@ -1209,8 +1307,8 @@ llvm_compile_expr(ExprState *state)
 				}
 
 			case EEOP_PARAM_SET:
-				build_EvalXFunc(b, mod, "ExecEvalParamSet",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalParamSet",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -1221,21 +1319,23 @@ llvm_compile_expr(ExprState *state)
 					LLVMValueRef v_params[3];
 					LLVMValueRef v_ret;
 
-					v_func = l_ptr_const(op->d.sbsref_subscript.subscriptfunc,
-										 llvm_pg_var_type("TypeExecEvalBoolSubroutine"));
+					v_func = ///l_ptr_const(op->d.sbsref_subscript.subscriptfunc,
+								///		 llvm_pg_var_type("TypeExecEvalBoolSubroutine"));
+								l_ptr_const_step(d.sbsref_subscript.subscriptfunc,
+										 llvm_pg_var_type(typesmod, "TypeExecEvalBoolSubroutine"));
 
 					v_params[0] = v_state;
-					v_params[1] = l_ptr_const(op, l_ptr(StructExprEvalStep));
+					v_params[1] = v_op; /// l_ptr_const(op, l_ptr(g->StructExprEvalStep));
 					v_params[2] = v_econtext;
 					v_ret = l_call(b,
-								   LLVMGetFunctionType(ExecEvalBoolSubroutineTemplate),
+								   LLVMGetFunctionType(g->ExecEvalBoolSubroutineTemplate),
 								   v_func,
 								   v_params, lengthof(v_params), "");
-					v_ret = LLVMBuildZExt(b, v_ret, TypeStorageBool, "");
+					v_ret = LLVMBuildZExt(b, v_ret, g->TypeStorageBool, "");
 
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_ret,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									opblocks[opno + 1],
 									opblocks[jumpdone]);
 					break;
@@ -1248,14 +1348,16 @@ llvm_compile_expr(ExprState *state)
 					LLVMValueRef v_func;
 					LLVMValueRef v_params[3];
 
-					v_func = l_ptr_const(op->d.sbsref.subscriptfunc,
-										 llvm_pg_var_type("TypeExecEvalSubroutine"));
+					v_func = ///l_ptr_const(op->d.sbsref.subscriptfunc,
+							///			 llvm_pg_var_type("TypeExecEvalSubroutine"));
+							l_ptr_const_step(d.sbsref.subscriptfunc,
+										 llvm_pg_var_type(typesmod, "TypeExecEvalSubroutine"));
 
 					v_params[0] = v_state;
-					v_params[1] = l_ptr_const(op, l_ptr(StructExprEvalStep));
+					v_params[1] = v_op; ///l_ptr_const(op, l_ptr(g->StructExprEvalStep));
 					v_params[2] = v_econtext;
 					l_call(b,
-						   LLVMGetFunctionType(ExecEvalSubroutineTemplate),
+						   LLVMGetFunctionType(g->ExecEvalSubroutineTemplate),
 						   v_func,
 						   v_params, lengthof(v_params), "");
 
@@ -1270,13 +1372,17 @@ llvm_compile_expr(ExprState *state)
 					LLVMValueRef v_casenullp,
 								v_casenull;
 
-					v_casevaluep = l_ptr_const(op->d.casetest.value,
-											   l_ptr(TypeSizeT));
-					v_casenullp = l_ptr_const(op->d.casetest.isnull,
-											  l_ptr(TypeStorageBool));
-
-					v_casevalue = l_load(b, TypeSizeT, v_casevaluep, "");
-					v_casenull = l_load(b, TypeStorageBool, v_casenullp, "");
+					v_casevaluep = ///l_ptr_const(op->d.casetest.value,
+									///		   l_ptr(TypeSizeT));
+									l_ptr_const_step(d.casetest.value,
+											   l_ptr(g->TypeSizeT));
+					v_casenullp = ///l_ptr_const(op->d.casetest.isnull,
+								///			  l_ptr(g->TypeStorageBool));
+								l_ptr_const_step(d.casetest.isnull,
+											  l_ptr(g->TypeStorageBool));
+
+					v_casevalue = l_load(b, g->TypeSizeT, v_casevaluep, "");
+					v_casenull = l_load(b, g->TypeStorageBool, v_casenullp, "");
 					LLVMBuildStore(b, v_casevalue, v_resvaluep);
 					LLVMBuildStore(b, v_casenull, v_resnullp);
 
@@ -1291,12 +1397,12 @@ llvm_compile_expr(ExprState *state)
 
 					v_casevalue =
 						l_load_struct_gep(b,
-										  StructExprContext,
+										  g->StructExprContext,
 										  v_econtext,
 										  FIELDNO_EXPRCONTEXT_CASEDATUM, "");
 					v_casenull =
 						l_load_struct_gep(b,
-										  StructExprContext,
+										  g->StructExprContext,
 										  v_econtext,
 										  FIELDNO_EXPRCONTEXT_CASENULL, "");
 					LLVMBuildStore(b, v_casevalue, v_resvaluep);
@@ -1319,10 +1425,12 @@ llvm_compile_expr(ExprState *state)
 					b_notnull = l_bb_before_v(opblocks[opno + 1],
 											  "op.%d.readonly.notnull", opno);
 
-					v_nullp = l_ptr_const(op->d.make_readonly.isnull,
-										  l_ptr(TypeStorageBool));
+					v_nullp = ///l_ptr_const(op->d.make_readonly.isnull,
+								///		  l_ptr(g->TypeStorageBool));
+							l_ptr_const_step(d.make_readonly.isnull,
+										  l_ptr(g->TypeStorageBool));
 
-					v_null = l_load(b, TypeStorageBool, v_nullp, "");
+					v_null = l_load(b, g->TypeStorageBool, v_nullp, "");
 
 					/* store null isnull value in result */
 					LLVMBuildStore(b, v_null, v_resnullp);
@@ -1330,22 +1438,24 @@ llvm_compile_expr(ExprState *state)
 					/* check if value is NULL */
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_null,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									opblocks[opno + 1], b_notnull);
 
 					/* if value is not null, convert to RO datum */
 					LLVMPositionBuilderAtEnd(b, b_notnull);
 
-					v_valuep = l_ptr_const(op->d.make_readonly.value,
-										   l_ptr(TypeSizeT));
+					v_valuep = ///l_ptr_const(op->d.make_readonly.value,
+								///		   l_ptr(TypeSizeT));
+								l_ptr_const_step(d.make_readonly.value,
+										   l_ptr(g->TypeSizeT));
 
-					v_value = l_load(b, TypeSizeT, v_valuep, "");
+					v_value = l_load(b, g->TypeSizeT, v_valuep, "");
 
 					v_params[0] = v_value;
 					v_ret =
 						l_call(b,
-							   llvm_pg_var_func_type("MakeExpandedObjectReadOnlyInternal"),
-							   llvm_pg_func(mod, "MakeExpandedObjectReadOnlyInternal"),
+							   llvm_pg_var_func_type(context, "MakeExpandedObjectReadOnlyInternal"),
+							   llvm_pg_func(context, "MakeExpandedObjectReadOnlyInternal"),
 							   v_params, lengthof(v_params), "");
 					LLVMBuildStore(b, v_ret, v_resvaluep);
 
@@ -1386,40 +1496,43 @@ llvm_compile_expr(ExprState *state)
 					b_inputcall = l_bb_before_v(opblocks[opno + 1],
 												"op.%d.inputcall", opno);
 
-					v_fn_out = llvm_function_reference(context, b, mod, fcinfo_out);
-					v_fn_in = llvm_function_reference(context, b, mod, fcinfo_in);
-					v_fcinfo_out = l_ptr_const(fcinfo_out, l_ptr(StructFunctionCallInfoData));
-					v_fcinfo_in = l_ptr_const(fcinfo_in, l_ptr(StructFunctionCallInfoData));
-
+					v_fcinfo_out = l_load_member_value_by_offset(b,lc, v_op,
+								l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep ,d.iocoerce.fcinfo_data_out ));
+					v_fcinfo_in = l_load_member_value_by_offset(b,lc, v_op,
+								l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep ,d.iocoerce.fcinfo_data_in ));
+					v_fn_out = llvm_function_reference(context, b, mod, fcinfo_out, v_fcinfo_out);
+					v_fn_in = llvm_function_reference(context, b, mod, fcinfo_in, v_fcinfo_in);
+					///v_fcinfo_out = l_ptr_const(fcinfo_out, l_ptr(g->StructFunctionCallInfoData));
+					///v_fcinfo_in = l_ptr_const(fcinfo_in, l_ptr(g->StructFunctionCallInfoData));
 					v_fcinfo_in_isnullp =
 						l_struct_gep(b,
-									 StructFunctionCallInfoData,
+									 g->StructFunctionCallInfoData,
 									 v_fcinfo_in,
 									 FIELDNO_FUNCTIONCALLINFODATA_ISNULL,
 									 "v_fcinfo_in_isnull");
 
 					/* output functions are not called on nulls */
-					v_resnull = l_load(b, TypeStorageBool, v_resnullp, "");
+					v_resnull = l_load(b, g->TypeStorageBool, v_resnullp, "");
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									b_skipoutput,
 									b_calloutput);
 
 					LLVMPositionBuilderAtEnd(b, b_skipoutput);
-					v_output_skip = l_sizet_const(0);
+					v_output_skip = LLVMConstInt(g->TypeSizeT, 0, false);
 					LLVMBuildBr(b, b_input);
 
 					LLVMPositionBuilderAtEnd(b, b_calloutput);
-					v_resvalue = l_load(b, TypeSizeT, v_resvaluep, "");
+					v_resvalue = l_load(b, g->TypeSizeT, v_resvaluep, "");
 
 					/* set arg[0] */
 					LLVMBuildStore(b,
 								   v_resvalue,
-								   l_funcvaluep(b, v_fcinfo_out, 0));
+								   l_funcvaluep(b, v_fcinfo_out, 0, g));
 					LLVMBuildStore(b,
-								   l_sbool_const(0),
-								   l_funcnullp(b, v_fcinfo_out, 0));
+								   LLVMConstInt(g->TypeStorageBool, (int)(0), false),
+								   l_funcnullp(b, v_fcinfo_out, 0, g));
 					/* and call output function (can never return NULL) */
 					v_output = l_call(b,
 									  LLVMGetFunctionType(v_fn_out),
@@ -1441,7 +1554,7 @@ llvm_compile_expr(ExprState *state)
 						incoming_values[1] = v_output;
 						incoming_blocks[1] = b_calloutput;
 
-						v_output = LLVMBuildPhi(b, TypeSizeT, "output");
+						v_output = LLVMBuildPhi(b, g->TypeSizeT, "output");
 						LLVMAddIncoming(v_output,
 										incoming_values, incoming_blocks,
 										lengthof(incoming_blocks));
@@ -1455,7 +1568,7 @@ llvm_compile_expr(ExprState *state)
 					{
 						LLVMBuildCondBr(b,
 										LLVMBuildICmp(b, LLVMIntEQ, v_output,
-													  l_sizet_const(0), ""),
+													  LLVMConstInt(g->TypeSizeT, 0, false), ""),
 										opblocks[opno + 1],
 										b_inputcall);
 					}
@@ -1468,15 +1581,15 @@ llvm_compile_expr(ExprState *state)
 					/* set arguments */
 					/* arg0: output */
 					LLVMBuildStore(b, v_output,
-								   l_funcvaluep(b, v_fcinfo_in, 0));
+								   l_funcvaluep(b, v_fcinfo_in, 0, g));
 					LLVMBuildStore(b, v_resnull,
-								   l_funcnullp(b, v_fcinfo_in, 0));
+								   l_funcnullp(b, v_fcinfo_in, 0, g));
 
 					/* arg1: ioparam: preset in execExpr.c */
 					/* arg2: typmod: preset in execExpr.c  */
 
 					/* reset fcinfo_in->isnull */
-					LLVMBuildStore(b, l_sbool_const(0), v_fcinfo_in_isnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_fcinfo_in_isnullp);
 					/* and call function */
 					v_retval = l_call(b,
 									  LLVMGetFunctionType(v_fn_in),
@@ -1490,8 +1603,8 @@ llvm_compile_expr(ExprState *state)
 				}
 
 			case EEOP_IOCOERCE_SAFE:
-				build_EvalXFunc(b, mod, "ExecEvalCoerceViaIOSafe",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalCoerceViaIOSafe",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -1523,15 +1636,17 @@ llvm_compile_expr(ExprState *state)
 					b_bothargnull = l_bb_before_v(opblocks[opno + 1], "op.%d.bothargnull", opno);
 					b_anyargnull = l_bb_before_v(opblocks[opno + 1], "op.%d.anyargnull", opno);
 
-					v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
+					v_fcinfo = /// l_ptr_const(fcinfo, l_ptr(g->StructFunctionCallInfoData));
+														l_load_member_value_by_offset(b,lc, v_op,
+								l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep ,d.func.fcinfo_data ));
 
 					/* load args[0|1].isnull for both arguments */
-					v_argnull0 = l_funcnull(b, v_fcinfo, 0);
+					v_argnull0 = l_funcnull(b, v_fcinfo, 0, g);
 					v_argisnull0 = LLVMBuildICmp(b, LLVMIntEQ, v_argnull0,
-												 l_sbool_const(1), "");
-					v_argnull1 = l_funcnull(b, v_fcinfo, 1);
+												 LLVMConstInt(g->TypeStorageBool, (int)(1), false), "");
+					v_argnull1 = l_funcnull(b, v_fcinfo, 1, g);
 					v_argisnull1 = LLVMBuildICmp(b, LLVMIntEQ, v_argnull1,
-												 l_sbool_const(1), "");
+												 LLVMConstInt(g->TypeStorageBool, (int)(1), false), "");
 
 					v_anyargisnull = LLVMBuildOr(b, v_argisnull0, v_argisnull1, "");
 					v_bothargisnull = LLVMBuildAnd(b, v_argisnull0, v_argisnull1, "");
@@ -1554,27 +1669,27 @@ llvm_compile_expr(ExprState *state)
 
 					/* Both NULL? Then is not distinct... */
 					LLVMPositionBuilderAtEnd(b, b_bothargnull);
-					LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_resnullp);
 					if (opcode == EEOP_NOT_DISTINCT)
-						LLVMBuildStore(b, l_sizet_const(1), v_resvaluep);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 1, false), v_resvaluep);
 					else
-						LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_resvaluep);
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
 
 					/* Only one is NULL? Then is distinct... */
 					LLVMPositionBuilderAtEnd(b, b_anyargnull);
-					LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_resnullp);
 					if (opcode == EEOP_NOT_DISTINCT)
-						LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_resvaluep);
 					else
-						LLVMBuildStore(b, l_sizet_const(1), v_resvaluep);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 1, false), v_resvaluep);
 					LLVMBuildBr(b, opblocks[opno + 1]);
 
 					/* neither argument is null: compare */
 					LLVMPositionBuilderAtEnd(b, b_noargnull);
 
-					v_result = BuildV1Call(context, b, mod, fcinfo,
+					v_result = BuildV1CallLLVM(context, b, mod, fcinfo, v_fcinfo,
 										   &v_fcinfo_isnull);
 
 					if (opcode == EEOP_DISTINCT)
@@ -1584,8 +1699,8 @@ llvm_compile_expr(ExprState *state)
 							LLVMBuildZExt(b,
 										  LLVMBuildICmp(b, LLVMIntEQ,
 														v_result,
-														l_sizet_const(0), ""),
-										  TypeSizeT, "");
+														LLVMConstInt(g->TypeSizeT, 0, false), ""),
+										  g->TypeSizeT, "");
 					}
 
 					LLVMBuildStore(b, v_fcinfo_isnull, v_resnullp);
@@ -1618,21 +1733,23 @@ llvm_compile_expr(ExprState *state)
 					b_argsequal = l_bb_before_v(opblocks[opno + 1],
 												"b.%d.argsequal", opno);
 
-					v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
+					v_fcinfo = /// l_ptr_const(fcinfo, l_ptr(g->StructFunctionCallInfoData));
+								l_load_member_value_by_offset(b,lc, v_op,
+								l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep ,d.func.fcinfo_data));
 
 					/* save original arg[0] */
-					v_arg0 = l_funcvalue(b, v_fcinfo, 0);
+					v_arg0 = l_funcvalue(b, v_fcinfo, 0, g);
 
 					/* if either argument is NULL they can't be equal */
-					v_argnull0 = l_funcnull(b, v_fcinfo, 0);
-					v_argnull1 = l_funcnull(b, v_fcinfo, 1);
+					v_argnull0 = l_funcnull(b, v_fcinfo, 0, g);
+					v_argnull1 = l_funcnull(b, v_fcinfo, 1, g);
 
 					v_anyargisnull =
 						LLVMBuildOr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_argnull0,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									LLVMBuildICmp(b, LLVMIntEQ, v_argnull1,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									"");
 
 					LLVMBuildCondBr(b, v_anyargisnull, b_hasnull, b_nonull);
@@ -1662,14 +1779,14 @@ llvm_compile_expr(ExprState *state)
 						v_params[0] = v_arg0;
 						v_arg0_ro =
 							l_call(b,
-								   llvm_pg_var_func_type("MakeExpandedObjectReadOnlyInternal"),
-								   llvm_pg_func(mod, "MakeExpandedObjectReadOnlyInternal"),
+								   llvm_pg_var_func_type(context, "MakeExpandedObjectReadOnlyInternal"),
+								   llvm_pg_func(context, "MakeExpandedObjectReadOnlyInternal"),
 								   v_params, lengthof(v_params), "");
 						LLVMBuildStore(b, v_arg0_ro,
-									   l_funcvaluep(b, v_fcinfo, 0));
+									   l_funcvaluep(b, v_fcinfo, 0, g));
 					}
 
-					v_retval = BuildV1Call(context, b, mod, fcinfo, &v_fcinfo_isnull);
+					v_retval = BuildV1CallLLVM(context, b, mod, fcinfo, v_fcinfo, &v_fcinfo_isnull);
 
 					/*
 					 * If result not null and arguments are equal return null,
@@ -1679,39 +1796,39 @@ llvm_compile_expr(ExprState *state)
 					v_argsequal = LLVMBuildAnd(b,
 											   LLVMBuildICmp(b, LLVMIntEQ,
 															 v_fcinfo_isnull,
-															 l_sbool_const(0),
+															 LLVMConstInt(g->TypeStorageBool, (int)(0), false),
 															 ""),
 											   LLVMBuildICmp(b, LLVMIntEQ,
 															 v_retval,
-															 l_sizet_const(1),
+															 LLVMConstInt(g->TypeSizeT, 1, false),
 															 ""),
 											   "");
 					LLVMBuildCondBr(b, v_argsequal, b_argsequal, b_hasnull);
 
 					/* build block setting result to NULL, if args are equal */
 					LLVMPositionBuilderAtEnd(b, b_argsequal);
-					LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
-					LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(1), false), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_resvaluep);
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
 					break;
 				}
 
 			case EEOP_SQLVALUEFUNCTION:
-				build_EvalXFunc(b, mod, "ExecEvalSQLValueFunction",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalSQLValueFunction",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_CURRENTOFEXPR:
-				build_EvalXFunc(b, mod, "ExecEvalCurrentOfExpr",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalCurrentOfExpr",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_NEXTVALUEEXPR:
-				build_EvalXFunc(b, mod, "ExecEvalNextValueExpr",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalNextValueExpr",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -1730,11 +1847,11 @@ llvm_compile_expr(ExprState *state)
 					 * OLD/NEW row doesn't exist, skip that and return NULL.
 					 */
 					v_flagsp = l_struct_gep(b,
-											StructExprState,
+											g->StructExprState,
 											v_state,
 											FIELDNO_EXPRSTATE_FLAGS,
 											"v.state.flags");
-					v_flags = l_load(b, TypeStorageBool, v_flagsp, "");
+					v_flags = l_load(b, g->TypeStorageBool, v_flagsp, "");
 
 					v_nullflag = l_int8_const(lc, op->d.returningexpr.nullflag);
 
@@ -1742,33 +1859,33 @@ llvm_compile_expr(ExprState *state)
 									LLVMBuildICmp(b, LLVMIntEQ,
 												  LLVMBuildAnd(b, v_flags,
 															   v_nullflag, ""),
-												  l_sbool_const(0), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(0), false), ""),
 									opblocks[opno + 1], b_isnull);
 
 					LLVMPositionBuilderAtEnd(b, b_isnull);
 
-					LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
-					LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_resvaluep);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(1), false), v_resnullp);
 
 					LLVMBuildBr(b, opblocks[op->d.returningexpr.jumpdone]);
 					break;
 				}
 
 			case EEOP_ARRAYEXPR:
-				build_EvalXFunc(b, mod, "ExecEvalArrayExpr",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalArrayExpr",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_ARRAYCOERCE:
-				build_EvalXFunc(b, mod, "ExecEvalArrayCoerce",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalArrayCoerce",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_ROW:
-				build_EvalXFunc(b, mod, "ExecEvalRow",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalRow",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -1779,6 +1896,7 @@ llvm_compile_expr(ExprState *state)
 					LLVMBasicBlockRef b_null;
 					LLVMBasicBlockRef b_compare;
 					LLVMBasicBlockRef b_compare_result;
+					LLVMValueRef v_fcinfo;
 
 					LLVMValueRef v_retval;
 
@@ -1790,34 +1908,34 @@ llvm_compile_expr(ExprState *state)
 						l_bb_before_v(opblocks[opno + 1],
 									  "op.%d.row-compare-result",
 									  opno);
-
+					v_fcinfo = l_load_member_value_by_offset(b, lc, v_op,
+								l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep ,d.rowcompare_step.fcinfo_data));
 					/*
 					 * If function is strict, and either arg is null, we're
 					 * done.
 					 */
 					if (op->d.rowcompare_step.finfo->fn_strict)
 					{
-						LLVMValueRef v_fcinfo;
 						LLVMValueRef v_argnull0;
 						LLVMValueRef v_argnull1;
 						LLVMValueRef v_anyargisnull;
 
-						v_fcinfo = l_ptr_const(fcinfo,
-											   l_ptr(StructFunctionCallInfoData));
+						///v_fcinfo = l_ptr_const(fcinfo,
+						///					   l_ptr(g->StructFunctionCallInfoData));
 
-						v_argnull0 = l_funcnull(b, v_fcinfo, 0);
-						v_argnull1 = l_funcnull(b, v_fcinfo, 1);
+						v_argnull0 = l_funcnull(b, v_fcinfo, 0, g);
+						v_argnull1 = l_funcnull(b, v_fcinfo, 1, g);
 
 						v_anyargisnull =
 							LLVMBuildOr(b,
 										LLVMBuildICmp(b,
 													  LLVMIntEQ,
 													  v_argnull0,
-													  l_sbool_const(1),
+													  LLVMConstInt(g->TypeStorageBool, (int)(1), false),
 													  ""),
 										LLVMBuildICmp(b, LLVMIntEQ,
 													  v_argnull1,
-													  l_sbool_const(1), ""),
+													  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 										"");
 
 						LLVMBuildCondBr(b, v_anyargisnull, b_null, b_compare);
@@ -1831,7 +1949,7 @@ llvm_compile_expr(ExprState *state)
 					LLVMPositionBuilderAtEnd(b, b_compare);
 
 					/* call function */
-					v_retval = BuildV1Call(context, b, mod, fcinfo,
+					v_retval = BuildV1CallLLVM(context, b, mod, fcinfo, v_fcinfo,
 										   &v_fcinfo_isnull);
 					LLVMBuildStore(b, v_retval, v_resvaluep);
 
@@ -1840,7 +1958,7 @@ llvm_compile_expr(ExprState *state)
 									LLVMBuildICmp(b,
 												  LLVMIntEQ,
 												  v_fcinfo_isnull,
-												  l_sbool_const(0),
+												  LLVMConstInt(g->TypeStorageBool, (int)(0), false),
 												  ""),
 									b_compare_result,
 									b_null);
@@ -1853,7 +1971,7 @@ llvm_compile_expr(ExprState *state)
 									LLVMBuildICmp(b,
 												  LLVMIntEQ,
 												  v_retval,
-												  l_sizet_const(0), ""),
+												  LLVMConstInt(g->TypeSizeT, 0, false), ""),
 									opblocks[opno + 1],
 									opblocks[op->d.rowcompare_step.jumpdone]);
 
@@ -1862,7 +1980,7 @@ llvm_compile_expr(ExprState *state)
 					 * result.
 					 */
 					LLVMPositionBuilderAtEnd(b, b_null);
-					LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(1), false), v_resnullp);
 					LLVMBuildBr(b, opblocks[op->d.rowcompare_step.jumpnull]);
 
 					break;
@@ -1883,7 +2001,7 @@ llvm_compile_expr(ExprState *state)
 					 */
 					v_cmpresult =
 						LLVMBuildTrunc(b,
-									   l_load(b, TypeSizeT, v_resvaluep, ""),
+									   l_load(b, g->TypeSizeT, v_resvaluep, ""),
 									   LLVMInt32TypeInContext(lc), "");
 
 					switch (cmptype)
@@ -1912,9 +2030,9 @@ llvm_compile_expr(ExprState *state)
 											 v_cmpresult,
 											 l_int32_const(lc, 0),
 											 "");
-					v_result = LLVMBuildZExt(b, v_result, TypeSizeT, "");
+					v_result = LLVMBuildZExt(b, v_result, g->TypeSizeT, "");
 
-					LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_resnullp);
 					LLVMBuildStore(b, v_result, v_resvaluep);
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
@@ -1922,26 +2040,26 @@ llvm_compile_expr(ExprState *state)
 				}
 
 			case EEOP_MINMAX:
-				build_EvalXFunc(b, mod, "ExecEvalMinMax",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalMinMax",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_FIELDSELECT:
-				build_EvalXFunc(b, mod, "ExecEvalFieldSelect",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalFieldSelect",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_FIELDSTORE_DEFORM:
-				build_EvalXFunc(b, mod, "ExecEvalFieldStoreDeForm",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalFieldStoreDeForm",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_FIELDSTORE_FORM:
-				build_EvalXFunc(b, mod, "ExecEvalFieldStoreForm",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalFieldStoreForm",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -1952,13 +2070,13 @@ llvm_compile_expr(ExprState *state)
 					LLVMValueRef v_casenullp,
 								v_casenull;
 
-					v_casevaluep = l_ptr_const(op->d.casetest.value,
-											   l_ptr(TypeSizeT));
-					v_casenullp = l_ptr_const(op->d.casetest.isnull,
-											  l_ptr(TypeStorageBool));
+					v_casevaluep = l_ptr_const_step(d.casetest.value,
+											   l_ptr(g->TypeSizeT));
+					v_casenullp = l_ptr_const_step(d.casetest.isnull,
+											  l_ptr(g->TypeStorageBool));
 
-					v_casevalue = l_load(b, TypeSizeT, v_casevaluep, "");
-					v_casenull = l_load(b, TypeStorageBool, v_casenullp, "");
+					v_casevalue = l_load(b, g->TypeSizeT, v_casevaluep, "");
+					v_casenull = l_load(b, g->TypeStorageBool, v_casenullp, "");
 					LLVMBuildStore(b, v_casevalue, v_resvaluep);
 					LLVMBuildStore(b, v_casenull, v_resnullp);
 
@@ -1973,13 +2091,13 @@ llvm_compile_expr(ExprState *state)
 
 					v_casevalue =
 						l_load_struct_gep(b,
-										  StructExprContext,
+										  g->StructExprContext,
 										  v_econtext,
 										  FIELDNO_EXPRCONTEXT_DOMAINDATUM,
 										  "");
 					v_casenull =
 						l_load_struct_gep(b,
-										  StructExprContext,
+										  g->StructExprContext,
 										  v_econtext,
 										  FIELDNO_EXPRCONTEXT_DOMAINNULL,
 										  "");
@@ -1991,14 +2109,14 @@ llvm_compile_expr(ExprState *state)
 				}
 
 			case EEOP_DOMAIN_NOTNULL:
-				build_EvalXFunc(b, mod, "ExecEvalConstraintNotNull",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalConstraintNotNull",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_DOMAIN_CHECK:
-				build_EvalXFunc(b, mod, "ExecEvalConstraintCheck",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalConstraintCheck",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -2006,10 +2124,10 @@ llvm_compile_expr(ExprState *state)
 				{
 					LLVMValueRef v_initvalue;
 
-					v_initvalue = l_sizet_const(op->d.hashdatum_initvalue.init_value);
+					v_initvalue = LLVMConstInt(g->TypeSizeT, op->d.hashdatum_initvalue.init_value, false);
 
 					LLVMBuildStore(b, v_initvalue, v_resvaluep);
-					LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_resnullp);
 					LLVMBuildBr(b, opblocks[opno + 1]);
 					break;
 				}
@@ -2044,25 +2162,31 @@ llvm_compile_expr(ExprState *state)
 						LLVMValueRef v_tmp2;
 						LLVMValueRef tmp;
 
-						tmp = l_ptr_const(&op->d.hashdatum.iresult->value,
-										  l_ptr(TypeSizeT));
+						///tmp = l_ptr_const(&op->d.hashdatum.iresult->value,
+						///				  l_ptr(TypeSizeT));
+						tmp = l_ptr_const_step(d.hashdatum.iresult, l_ptr(g->StructNullableDatum));
+						tmp = l_struct_gep(b, g->StructNullableDatum, tmp,
+												  FIELDNO_NULLABLE_DATUM_DATUM,
+												  "");
+
+						///l_ptr(TypeSizeT));
 
 						/*
 						 * Fetch the previously hashed value from where the
 						 * previous hash operation stored it.
 						 */
-						v_prevhash = l_load(b, TypeSizeT, tmp, "prevhash");
+						v_prevhash = l_load(b, g->TypeSizeT, tmp, "prevhash");
 
 						/*
 						 * Rotate bits left by 1 bit.  Be careful not to
 						 * overflow uint32 when working with size_t.
 						 */
-						v_tmp1 = LLVMBuildShl(b, v_prevhash, l_sizet_const(1),
+						v_tmp1 = LLVMBuildShl(b, v_prevhash, LLVMConstInt(g->TypeSizeT, 1, false),
 											  "");
 						v_tmp1 = LLVMBuildAnd(b, v_tmp1,
-											  l_sizet_const(0xffffffff), "");
+											  LLVMConstInt(g->TypeSizeT, 0xffffffff, false), "");
 						v_tmp2 = LLVMBuildLShr(b, v_prevhash,
-											   l_sizet_const(31), "");
+											   LLVMConstInt(g->TypeSizeT, 31, false), "");
 						v_prevhash = LLVMBuildOr(b, v_tmp1, v_tmp2,
 												 "rotatedhash");
 					}
@@ -2079,8 +2203,10 @@ llvm_compile_expr(ExprState *state)
 					if (fcinfo->nargs != 1)
 						elog(ERROR, "incorrect number of function arguments");
 
-					v_fcinfo = l_ptr_const(fcinfo,
-										   l_ptr(StructFunctionCallInfoData));
+					v_fcinfo = ///l_ptr_const(fcinfo,
+								///		   l_ptr(g->StructFunctionCallInfoData));
+								l_load_member_value_by_offset(b, lc, v_op,
+								l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep, d.hashdatum.fcinfo_data));
 
 					b_checkargnull = l_bb_before_v(b_ifnotnull,
 												   "b.%d.isnull.0", opno);
@@ -2104,8 +2230,8 @@ llvm_compile_expr(ExprState *state)
 						 * In strict node, NULL inputs result in NULL.  Save
 						 * the NULL result and goto jumpdone.
 						 */
-						LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
-						LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(1), false), v_resnullp);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_resvaluep);
 						LLVMBuildBr(b, opblocks[op->d.hashdatum.jumpdone]);
 					}
 					else
@@ -2117,7 +2243,7 @@ llvm_compile_expr(ExprState *state)
 						LLVMPositionBuilderAtEnd(b, b_ifnullblock);
 
 
-						LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
+						LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_resnullp);
 
 						if (opcode == EEOP_HASHDATUM_NEXT32)
 						{
@@ -2137,7 +2263,7 @@ llvm_compile_expr(ExprState *state)
 							 * Store a zero Datum when the Datum to hash is
 							 * NULL
 							 */
-							LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
+							LLVMBuildStore(b, LLVMConstInt(g->TypeSizeT, 0, false), v_resvaluep);
 						}
 
 						LLVMBuildBr(b, opblocks[opno + 1]);
@@ -2146,12 +2272,12 @@ llvm_compile_expr(ExprState *state)
 					LLVMPositionBuilderAtEnd(b, b_checkargnull);
 
 					/* emit code to check if the input parameter is NULL */
-					v_argisnull = l_funcnull(b, v_fcinfo, 0);
+					v_argisnull = l_funcnull(b, v_fcinfo, 0, g);
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b,
 												  LLVMIntEQ,
 												  v_argisnull,
-												  l_sbool_const(1),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false),
 												  ""),
 									b_ifnullblock,
 									b_ifnotnull);
@@ -2169,31 +2295,34 @@ llvm_compile_expr(ExprState *state)
 						LLVMValueRef v_tmp2;
 						LLVMValueRef tmp;
 
-						tmp = l_ptr_const(&op->d.hashdatum.iresult->value,
-										  l_ptr(TypeSizeT));
-
+						///tmp = l_ptr_const(&op->d.hashdatum.iresult->value,
+						///				  l_ptr(TypeSizeT));
+						tmp = l_ptr_const_step(d.hashdatum.iresult, l_ptr(g->StructNullableDatum));
+						tmp = l_struct_gep(b, g->StructNullableDatum, tmp,
+												  FIELDNO_NULLABLE_DATUM_DATUM,
+												  "");
 						/*
 						 * Fetch the previously hashed value from where the
 						 * previous hash operation stored it.
 						 */
-						v_prevhash = l_load(b, TypeSizeT, tmp, "prevhash");
+						v_prevhash = l_load(b, g->TypeSizeT, tmp, "prevhash");
 
 						/*
 						 * Rotate bits left by 1 bit.  Be careful not to
 						 * overflow uint32 when working with size_t.
 						 */
-						v_tmp1 = LLVMBuildShl(b, v_prevhash, l_sizet_const(1),
+						v_tmp1 = LLVMBuildShl(b, v_prevhash, LLVMConstInt(g->TypeSizeT, 1, false),
 											  "");
 						v_tmp1 = LLVMBuildAnd(b, v_tmp1,
-											  l_sizet_const(0xffffffff), "");
+											  LLVMConstInt(g->TypeSizeT, 0xffffffff, false), "");
 						v_tmp2 = LLVMBuildLShr(b, v_prevhash,
-											   l_sizet_const(31), "");
+											   LLVMConstInt(g->TypeSizeT, 31, false), "");
 						v_prevhash = LLVMBuildOr(b, v_tmp1, v_tmp2,
 												 "rotatedhash");
 					}
 
 					/* call the hash function */
-					v_retval = BuildV1Call(context, b, mod, fcinfo,
+					v_retval = BuildV1CallLLVM(context, b, mod, fcinfo, v_fcinfo,
 										   &v_fcinfo_isnull);
 
 					/*
@@ -2206,45 +2335,45 @@ llvm_compile_expr(ExprState *state)
 												"xorhash");
 
 					LLVMBuildStore(b, v_retval, v_resvaluep);
-					LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
+					LLVMBuildStore(b, LLVMConstInt(g->TypeStorageBool, (int)(0), false), v_resnullp);
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
 					break;
 				}
 
 			case EEOP_CONVERT_ROWTYPE:
-				build_EvalXFunc(b, mod, "ExecEvalConvertRowtype",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalConvertRowtype",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_SCALARARRAYOP:
-				build_EvalXFunc(b, mod, "ExecEvalScalarArrayOp",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalScalarArrayOp",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_HASHED_SCALARARRAYOP:
-				build_EvalXFunc(b, mod, "ExecEvalHashedScalarArrayOp",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalHashedScalarArrayOp",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_XMLEXPR:
-				build_EvalXFunc(b, mod, "ExecEvalXmlExpr",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalXmlExpr",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_JSON_CONSTRUCTOR:
-				build_EvalXFunc(b, mod, "ExecEvalJsonConstructor",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalJsonConstructor",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_IS_JSON:
-				build_EvalXFunc(b, mod, "ExecEvalJsonIsPredicate",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalJsonIsPredicate",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -2257,8 +2386,8 @@ llvm_compile_expr(ExprState *state)
 					 * Call ExecEvalJsonExprPath().  It returns the address of
 					 * the step to perform next.
 					 */
-					v_ret = build_EvalXFunc(b, mod, "ExecEvalJsonExprPath",
-											v_state, op, v_econtext);
+					v_ret = build_EvalXFunc(b, context, "ExecEvalJsonExprPath",
+											v_state, v_op, v_econtext);
 
 					/*
 					 * Build a switch to map the return value (v_ret above),
@@ -2343,15 +2472,15 @@ llvm_compile_expr(ExprState *state)
 				}
 
 			case EEOP_JSONEXPR_COERCION:
-				build_EvalXFunc(b, mod, "ExecEvalJsonCoercion",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalJsonCoercion",
+								v_state, v_op, v_econtext);
 
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_JSONEXPR_COERCION_FINISH:
-				build_EvalXFunc(b, mod, "ExecEvalJsonCoercionFinish",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalJsonCoercionFinish",
+								v_state, v_op);
 
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
@@ -2365,8 +2494,8 @@ llvm_compile_expr(ExprState *state)
 					v_aggno = l_int32_const(lc, op->d.aggref.aggno);
 
 					/* load agg value / null */
-					value = l_load_gep1(b, TypeSizeT, v_aggvalues, v_aggno, "aggvalue");
-					isnull = l_load_gep1(b, TypeStorageBool, v_aggnulls, v_aggno, "aggnull");
+					value = l_load_gep1(b, g->TypeSizeT, v_aggvalues, v_aggno, "aggvalue");
+					isnull = l_load_gep1(b, g->TypeStorageBool, v_aggnulls, v_aggno, "aggnull");
 
 					/* and store result */
 					LLVMBuildStore(b, value, v_resvaluep);
@@ -2377,14 +2506,14 @@ llvm_compile_expr(ExprState *state)
 				}
 
 			case EEOP_GROUPING_FUNC:
-				build_EvalXFunc(b, mod, "ExecEvalGroupingFunc",
-								v_state, op);
+				build_EvalXFunc(b, context, "ExecEvalGroupingFunc",
+								v_state, v_op);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_WINDOW_FUNC:
 				{
-					WindowFuncExprState *wfunc = op->d.window_func.wfstate;
+					///WindowFuncExprState *wfunc = op->d.window_func.wfstate;
 					LLVMValueRef v_wfuncnop;
 					LLVMValueRef v_wfuncno;
 					LLVMValueRef value,
@@ -2395,14 +2524,17 @@ llvm_compile_expr(ExprState *state)
 					 * up in ExecInitWindowAgg() after initializing the
 					 * expression). So load it from memory each time round.
 					 */
-					v_wfuncnop = l_ptr_const(&wfunc->wfuncno,
-											 l_ptr(LLVMInt32TypeInContext(lc)));
+					v_wfuncnop = ///l_ptr_const(&wfunc->wfuncno,
+								///			 l_ptr(LLVMInt32TypeInContext(lc)));
+								l_ptr_const_step(d.window_func.wfstate, l_ptr(g->StructWindowFuncExprState));
+					v_wfuncnop = l_struct_member_ptr_by_offset(b, lc, v_wfuncnop, offsetof(WindowFuncExprState, wfuncno) );
+
 					v_wfuncno = l_load(b, LLVMInt32TypeInContext(lc), v_wfuncnop, "v_wfuncno");
 
 					/* load window func value / null */
-					value = l_load_gep1(b, TypeSizeT, v_aggvalues, v_wfuncno,
+					value = l_load_gep1(b, g->TypeSizeT, v_aggvalues, v_wfuncno,
 										"windowvalue");
-					isnull = l_load_gep1(b, TypeStorageBool, v_aggnulls, v_wfuncno,
+					isnull = l_load_gep1(b, g->TypeStorageBool, v_aggnulls, v_wfuncno,
 										 "windownull");
 
 					LLVMBuildStore(b, value, v_resvaluep);
@@ -2413,62 +2545,74 @@ llvm_compile_expr(ExprState *state)
 				}
 
 			case EEOP_MERGE_SUPPORT_FUNC:
-				build_EvalXFunc(b, mod, "ExecEvalMergeSupportFunc",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalMergeSupportFunc",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_SUBPLAN:
-				build_EvalXFunc(b, mod, "ExecEvalSubPlan",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalSubPlan",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_AGG_STRICT_DESERIALIZE:
 			case EEOP_AGG_DESERIALIZE:
 				{
-					AggState   *aggstate;
+					///AggState   *aggstate;
 					FunctionCallInfo fcinfo = op->d.agg_deserialize.fcinfo_data;
 
 					LLVMValueRef v_retval;
 					LLVMValueRef v_fcinfo_isnull;
 					LLVMValueRef v_tmpcontext;
 					LLVMValueRef v_oldcontext;
+					LLVMValueRef v_fcinfo;
 
 					if (opcode == EEOP_AGG_STRICT_DESERIALIZE)
 					{
-						LLVMValueRef v_fcinfo;
 						LLVMValueRef v_argnull0;
 						LLVMBasicBlockRef b_deserialize;
 
 						b_deserialize = l_bb_before_v(opblocks[opno + 1],
 													  "op.%d.deserialize", opno);
 
-						v_fcinfo = l_ptr_const(fcinfo,
-											   l_ptr(StructFunctionCallInfoData));
-						v_argnull0 = l_funcnull(b, v_fcinfo, 0);
+						v_fcinfo = ///l_ptr_const(fcinfo,
+									///		   l_ptr(g->StructFunctionCallInfoData));
+									l_load_member_value_by_offset(b, lc, v_op,
+									l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep, d.agg_deserialize.fcinfo_data));
+						v_argnull0 = l_funcnull(b, v_fcinfo, 0, g);
 
 						LLVMBuildCondBr(b,
 										LLVMBuildICmp(b,
 													  LLVMIntEQ,
 													  v_argnull0,
-													  l_sbool_const(1),
+													  LLVMConstInt(g->TypeStorageBool, (int)(1), false),
 													  ""),
 										opblocks[op->d.agg_deserialize.jumpnull],
 										b_deserialize);
 						LLVMPositionBuilderAtEnd(b, b_deserialize);
 					}
+					else
+					{
+						v_fcinfo = l_load_member_value_by_offset(b, lc, v_op,
+									l_ptr(g->StructFunctionCallInfoData), offsetof(ExprEvalStep, d.agg_deserialize.fcinfo_data));
+					}
 
-					aggstate = castNode(AggState, state->parent);
+					///aggstate = castNode(AggState, state->parent);
 					fcinfo = op->d.agg_deserialize.fcinfo_data;
 
-					v_tmpcontext =
-						l_ptr_const(aggstate->tmpcontext->ecxt_per_tuple_memory,
-									l_ptr(StructMemoryContextData));
-					v_oldcontext = l_mcxt_switch(mod, b, v_tmpcontext);
-					v_retval = BuildV1Call(context, b, mod, fcinfo,
+					///v_tmpcontext =
+						///l_ptr_const(aggstate->tmpcontext->ecxt_per_tuple_memory,
+						///			l_ptr(g->StructMemoryContextData));
+					///	l_load_struct_gep(b, StructExprState, v_state, FIELDNO_EXPRSTATE_PARENT,"");
+					v_tmpcontext = l_load_struct_gep(b, g->StructExprState, v_state, FIELDNO_EXPRSTATE_PARENT,"");
+					v_tmpcontext = l_load_struct_gep(b, g->StructAggState, v_tmpcontext, FIELDNO_AGGSTATE_TMPCONTEXT,"");
+					v_tmpcontext = l_load_struct_gep(b, g->StructExprContext, v_tmpcontext, FIELDNO_EXPRCONTEXT_PERTUPLEMEMORY,"");
+
+					v_oldcontext = l_mcxt_switch(mod, b, v_tmpcontext, g);
+					v_retval = BuildV1CallLLVM(context, b, mod, fcinfo, v_fcinfo,
 										   &v_fcinfo_isnull);
-					l_mcxt_switch(mod, b, v_oldcontext);
+					l_mcxt_switch(mod, b, v_oldcontext, g);
 
 					LLVMBuildStore(b, v_retval, v_resvaluep);
 					LLVMBuildStore(b, v_fcinfo_isnull, v_resnullp);
@@ -2481,8 +2625,8 @@ llvm_compile_expr(ExprState *state)
 			case EEOP_AGG_STRICT_INPUT_CHECK_NULLS:
 				{
 					int			nargs = op->d.agg_strict_input_check.nargs;
-					NullableDatum *args = op->d.agg_strict_input_check.args;
-					bool	   *nulls = op->d.agg_strict_input_check.nulls;
+					///NullableDatum *args = op->d.agg_strict_input_check.args;
+					///bool	   *nulls = op->d.agg_strict_input_check.nulls;
 					int			jumpnull;
 
 					LLVMValueRef v_argsp;
@@ -2492,8 +2636,10 @@ llvm_compile_expr(ExprState *state)
 					Assert(nargs > 0);
 
 					jumpnull = op->d.agg_strict_input_check.jumpnull;
-					v_argsp = l_ptr_const(args, l_ptr(StructNullableDatum));
-					v_nullsp = l_ptr_const(nulls, l_ptr(TypeStorageBool));
+					v_argsp = ///l_ptr_const(args, l_ptr(g->StructNullableDatum));
+							l_ptr_const_step(d.agg_strict_input_check.args, l_ptr(g->StructNullableDatum));
+					v_nullsp = ///l_ptr_const(nulls, l_ptr(g->TypeStorageBool));
+							l_ptr_const_step(d.agg_strict_input_check.nulls, l_ptr(g->TypeStorageBool));
 
 					/* create blocks for checking args */
 					b_checknulls = palloc(sizeof(LLVMBasicBlockRef *) * nargs);
@@ -2522,14 +2668,14 @@ llvm_compile_expr(ExprState *state)
 							b_argnotnull = b_checknulls[argno + 1];
 
 						if (opcode == EEOP_AGG_STRICT_INPUT_CHECK_NULLS)
-							v_argisnull = l_load_gep1(b, TypeStorageBool, v_nullsp, v_argno, "");
+							v_argisnull = l_load_gep1(b, g->TypeStorageBool, v_nullsp, v_argno, "");
 						else
 						{
 							LLVMValueRef v_argn;
 
-							v_argn = l_gep(b, StructNullableDatum, v_argsp, &v_argno, 1, "");
+							v_argn = l_gep(b, g->StructNullableDatum, v_argsp, &v_argno, 1, "");
 							v_argisnull =
-								l_load_struct_gep(b, StructNullableDatum, v_argn,
+								l_load_struct_gep(b, g->StructNullableDatum, v_argn,
 												  FIELDNO_NULLABLE_DATUM_ISNULL,
 												  "");
 						}
@@ -2538,7 +2684,7 @@ llvm_compile_expr(ExprState *state)
 										LLVMBuildICmp(b,
 													  LLVMIntEQ,
 													  v_argisnull,
-													  l_sbool_const(1), ""),
+													  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 										opblocks[jumpnull],
 										b_argnotnull);
 					}
@@ -2561,23 +2707,23 @@ llvm_compile_expr(ExprState *state)
 					 * [op->d.agg_plain_pergroup_nullcheck.setoff];
 					 */
 					v_aggstatep = LLVMBuildBitCast(b, v_parent,
-												   l_ptr(StructAggState), "");
+												   l_ptr(g->StructAggState), "");
 
 					v_allpergroupsp = l_load_struct_gep(b,
-														StructAggState,
+														g->StructAggState,
 														v_aggstatep,
 														FIELDNO_AGGSTATE_ALL_PERGROUPS,
 														"aggstate.all_pergroups");
 
 					v_setoff = l_int32_const(lc, op->d.agg_plain_pergroup_nullcheck.setoff);
 
-					v_pergroup_allaggs = l_load_gep1(b, l_ptr(StructAggStatePerGroupData),
+					v_pergroup_allaggs = l_load_gep1(b, l_ptr(g->StructAggStatePerGroupData),
 													 v_allpergroupsp, v_setoff, "");
 
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ,
-												  LLVMBuildPtrToInt(b, v_pergroup_allaggs, TypeSizeT, ""),
-												  l_sizet_const(0), ""),
+												  LLVMBuildPtrToInt(b, v_pergroup_allaggs, g->TypeSizeT, ""),
+												  LLVMConstInt(g->TypeSizeT, 0, false), ""),
 									opblocks[jumpnull],
 									opblocks[opno + 1]);
 					break;
@@ -2590,7 +2736,7 @@ llvm_compile_expr(ExprState *state)
 			case EEOP_AGG_PLAIN_TRANS_STRICT_BYREF:
 			case EEOP_AGG_PLAIN_TRANS_BYREF:
 				{
-					AggState   *aggstate;
+					///AggState   *aggstate;
 					AggStatePerTrans pertrans;
 					FunctionCallInfo fcinfo;
 
@@ -2620,23 +2766,24 @@ llvm_compile_expr(ExprState *state)
 					LLVMValueRef v_tmpcontext;
 					LLVMValueRef v_oldcontext;
 
-					aggstate = castNode(AggState, state->parent);
+					///aggstate = castNode(AggState, state->parent);
 					pertrans = op->d.agg_trans.pertrans;
 
 					fcinfo = pertrans->transfn_fcinfo;
 
 					v_aggstatep =
-						LLVMBuildBitCast(b, v_parent, l_ptr(StructAggState), "");
-					v_pertransp = l_ptr_const(pertrans,
-											  l_ptr(StructAggStatePerTransData));
-
+						LLVMBuildBitCast(b, v_parent, l_ptr(g->StructAggState), "");
+					v_pertransp = ///l_ptr_const(pertrans,
+									///			  l_ptr(g->StructAggStatePerTransData));
+									l_ptr_const_step(d.agg_trans.pertrans,
+												  l_ptr(g->StructAggStatePerTransData));
 					/*
 					 * pergroup = &aggstate->all_pergroups
 					 * [op->d.agg_trans.setoff] [op->d.agg_trans.transno];
 					 */
 					v_allpergroupsp =
 						l_load_struct_gep(b,
-										  StructAggState,
+										  g->StructAggState,
 										  v_aggstatep,
 										  FIELDNO_AGGSTATE_ALL_PERGROUPS,
 										  "aggstate.all_pergroups");
@@ -2644,8 +2791,8 @@ llvm_compile_expr(ExprState *state)
 					v_transno = l_int32_const(lc, op->d.agg_trans.transno);
 					v_pergroupp =
 						l_gep(b,
-							  StructAggStatePerGroupData,
-							  l_load_gep1(b, l_ptr(StructAggStatePerGroupData),
+							  g->StructAggStatePerGroupData,
+							  l_load_gep1(b, l_ptr(g->StructAggStatePerGroupData),
 										  v_allpergroupsp, v_setoff, ""),
 							  &v_transno, 1, "");
 
@@ -2659,7 +2806,7 @@ llvm_compile_expr(ExprState *state)
 
 						v_notransvalue =
 							l_load_struct_gep(b,
-											  StructAggStatePerGroupData,
+											  g->StructAggStatePerGroupData,
 											  v_pergroupp,
 											  FIELDNO_AGGSTATEPERGROUPDATA_NOTRANSVALUE,
 											  "notransvalue");
@@ -2671,7 +2818,7 @@ llvm_compile_expr(ExprState *state)
 
 						LLVMBuildCondBr(b,
 										LLVMBuildICmp(b, LLVMIntEQ, v_notransvalue,
-													  l_sbool_const(1), ""),
+													  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 										b_init,
 										b_no_init);
 
@@ -2681,8 +2828,8 @@ llvm_compile_expr(ExprState *state)
 
 							LLVMPositionBuilderAtEnd(b, b_init);
 
-							v_aggcontext = l_ptr_const(op->d.agg_trans.aggcontext,
-													   l_ptr(StructExprContext));
+							v_aggcontext = l_ptr_const_step(d.agg_trans.aggcontext,
+													   l_ptr(g->StructExprContext));
 
 							params[0] = v_aggstatep;
 							params[1] = v_pertransp;
@@ -2690,8 +2837,8 @@ llvm_compile_expr(ExprState *state)
 							params[3] = v_aggcontext;
 
 							l_call(b,
-								   llvm_pg_var_func_type("ExecAggInitGroup"),
-								   llvm_pg_func(mod, "ExecAggInitGroup"),
+								   llvm_pg_var_func_type(context, "ExecAggInitGroup"),
+								   llvm_pg_func(context, "ExecAggInitGroup"),
 								   params, lengthof(params),
 								   "");
 
@@ -2713,14 +2860,14 @@ llvm_compile_expr(ExprState *state)
 													 "op.%d.strictpass", opno);
 						v_transnull =
 							l_load_struct_gep(b,
-											  StructAggStatePerGroupData,
+											  g->StructAggStatePerGroupData,
 											  v_pergroupp,
 											  FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL,
 											  "transnull");
 
 						LLVMBuildCondBr(b,
 										LLVMBuildICmp(b, LLVMIntEQ, v_transnull,
-													  l_sbool_const(1), ""),
+													  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 										opblocks[opno + 1],
 										b_strictpass);
 
@@ -2728,26 +2875,32 @@ llvm_compile_expr(ExprState *state)
 					}
 
 
-					v_fcinfo = l_ptr_const(fcinfo,
-										   l_ptr(StructFunctionCallInfoData));
-					v_aggcontext = l_ptr_const(op->d.agg_trans.aggcontext,
-											   l_ptr(StructExprContext));
+					v_fcinfo = ///l_ptr_const(fcinfo,
+								///		   l_ptr(g->StructFunctionCallInfoData));
+								l_load_member_value_by_offset(b, lc, v_op,
+									l_ptr(g->StructAggStatePerTransData), offsetof(ExprEvalStep, d.agg_trans.pertrans));
+					v_fcinfo = ///l_ptr_const(fcinfo,
+								///		   l_ptr(g->StructFunctionCallInfoData));
+								l_load_member_value_by_offset(b, lc, v_fcinfo,
+									l_ptr(g->StructFunctionCallInfoData), offsetof(AggStatePerTransData, transfn_fcinfo));
+					v_aggcontext = l_ptr_const_step(d.agg_trans.aggcontext,
+											   l_ptr(g->StructExprContext));
 
 					v_current_setp =
 						l_struct_gep(b,
-									 StructAggState,
+									 g->StructAggState,
 									 v_aggstatep,
 									 FIELDNO_AGGSTATE_CURRENT_SET,
 									 "aggstate.current_set");
 					v_curaggcontext =
 						l_struct_gep(b,
-									 StructAggState,
+									 g->StructAggState,
 									 v_aggstatep,
 									 FIELDNO_AGGSTATE_CURAGGCONTEXT,
 									 "aggstate.curaggcontext");
 					v_current_pertransp =
 						l_struct_gep(b,
-									 StructAggState,
+									 g->StructAggState,
 									 v_aggstatep,
 									 FIELDNO_AGGSTATE_CURPERTRANS,
 									 "aggstate.curpertrans");
@@ -2759,36 +2912,40 @@ llvm_compile_expr(ExprState *state)
 					LLVMBuildStore(b, v_pertransp, v_current_pertransp);
 
 					/* invoke transition function in per-tuple context */
-					v_tmpcontext =
-						l_ptr_const(aggstate->tmpcontext->ecxt_per_tuple_memory,
-									l_ptr(StructMemoryContextData));
-					v_oldcontext = l_mcxt_switch(mod, b, v_tmpcontext);
+					///v_tmpcontext =
+					///	l_ptr_const(aggstate->tmpcontext->ecxt_per_tuple_memory,
+					///				l_ptr(g->StructMemoryContextData));
+					v_tmpcontext = l_load_struct_gep(b, g->StructExprState, v_state, FIELDNO_EXPRSTATE_PARENT,"");
+					v_tmpcontext = l_load_struct_gep(b, g->StructAggState, v_tmpcontext, FIELDNO_AGGSTATE_TMPCONTEXT,"");
+					v_tmpcontext = l_load_struct_gep(b, g->StructExprContext, v_tmpcontext, FIELDNO_EXPRCONTEXT_PERTUPLEMEMORY,"");
+
+					v_oldcontext = l_mcxt_switch(mod, b, v_tmpcontext, g);
 
 					/* store transvalue in fcinfo->args[0] */
 					v_transvaluep =
 						l_struct_gep(b,
-									 StructAggStatePerGroupData,
+									 g->StructAggStatePerGroupData,
 									 v_pergroupp,
 									 FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUE,
 									 "transvalue");
 					v_transnullp =
 						l_struct_gep(b,
-									 StructAggStatePerGroupData,
+									 g->StructAggStatePerGroupData,
 									 v_pergroupp,
 									 FIELDNO_AGGSTATEPERGROUPDATA_TRANSVALUEISNULL,
 									 "transnullp");
 					LLVMBuildStore(b,
 								   l_load(b,
-										  TypeSizeT,
+										  g->TypeSizeT,
 										  v_transvaluep,
 										  "transvalue"),
-								   l_funcvaluep(b, v_fcinfo, 0));
+								   l_funcvaluep(b, v_fcinfo, 0, g));
 					LLVMBuildStore(b,
-								   l_load(b, TypeStorageBool, v_transnullp, "transnull"),
-								   l_funcnullp(b, v_fcinfo, 0));
+								   l_load(b, g->TypeStorageBool, v_transnullp, "transnull"),
+								   l_funcnullp(b, v_fcinfo, 0, g));
 
 					/* and invoke transition function */
-					v_retval = BuildV1Call(context, b, mod, fcinfo,
+					v_retval = BuildV1CallLLVM(context, b, mod, fcinfo, v_fcinfo,
 										   &v_fcinfo_isnull);
 
 					/*
@@ -2817,8 +2974,8 @@ llvm_compile_expr(ExprState *state)
 						b_nocall = l_bb_before_v(opblocks[opno + 1],
 												 "op.%d.transnocall", opno);
 
-						v_transvalue = l_load(b, TypeSizeT, v_transvaluep, "");
-						v_transnull = l_load(b, TypeStorageBool, v_transnullp, "");
+						v_transvalue = l_load(b, g->TypeSizeT, v_transvaluep, "");
+						v_transnull = l_load(b, g->TypeStorageBool, v_transnullp, "");
 
 						/*
 						 * DatumGetPointer(newVal) !=
@@ -2837,12 +2994,12 @@ llvm_compile_expr(ExprState *state)
 						params[1] = v_pertransp;
 						params[2] = v_retval;
 						params[3] = LLVMBuildTrunc(b, v_fcinfo_isnull,
-												   TypeParamBool, "");
+												   g->TypeParamBool, "");
 						params[4] = v_transvalue;
 						params[5] = LLVMBuildTrunc(b, v_transnull,
-												   TypeParamBool, "");
+												   g->TypeParamBool, "");
 
-						v_fn = llvm_pg_func(mod, "ExecAggCopyTransValue");
+						v_fn = llvm_pg_func(context, "ExecAggCopyTransValue");
 						v_newval =
 							l_call(b,
 								   LLVMGetFunctionType(v_fn),
@@ -2854,7 +3011,7 @@ llvm_compile_expr(ExprState *state)
 						LLVMBuildStore(b, v_newval, v_transvaluep);
 						LLVMBuildStore(b, v_fcinfo_isnull, v_transnullp);
 
-						l_mcxt_switch(mod, b, v_oldcontext);
+						l_mcxt_switch(mod, b, v_oldcontext, g);
 						LLVMBuildBr(b, opblocks[opno + 1]);
 
 						/* returned datum passed datum, no need to reparent */
@@ -2865,7 +3022,7 @@ llvm_compile_expr(ExprState *state)
 					LLVMBuildStore(b, v_retval, v_transvaluep);
 					LLVMBuildStore(b, v_fcinfo_isnull, v_transnullp);
 
-					l_mcxt_switch(mod, b, v_oldcontext);
+					l_mcxt_switch(mod, b, v_oldcontext, g);
 
 					LLVMBuildBr(b, opblocks[opno + 1]);
 					break;
@@ -2873,23 +3030,25 @@ llvm_compile_expr(ExprState *state)
 
 			case EEOP_AGG_PRESORTED_DISTINCT_SINGLE:
 				{
-					AggState   *aggstate = castNode(AggState, state->parent);
-					AggStatePerTrans pertrans = op->d.agg_presorted_distinctcheck.pertrans;
+					///AggState   *aggstate = castNode(AggState, state->parent);
+					///AggStatePerTrans pertrans = op->d.agg_presorted_distinctcheck.pertrans;
 					int			jumpdistinct = op->d.agg_presorted_distinctcheck.jumpdistinct;
 
-					LLVMValueRef v_fn = llvm_pg_func(mod, "ExecEvalPreOrderedDistinctSingle");
+					LLVMValueRef v_fn = llvm_pg_func(context, "ExecEvalPreOrderedDistinctSingle");
 					LLVMValueRef v_args[2];
 					LLVMValueRef v_ret;
 
-					v_args[0] = l_ptr_const(aggstate, l_ptr(StructAggState));
-					v_args[1] = l_ptr_const(pertrans, l_ptr(StructAggStatePerTransData));
+					///v_args[0] = l_ptr_const(aggstate, l_ptr(g->StructAggState));
+					v_args[0] = v_parent;
+					/// v_args[1] = l_ptr_const(pertrans, l_ptr(g->StructAggStatePerTransData));
+					v_args[1] = l_ptr_const_step(d.agg_presorted_distinctcheck.pertrans, l_ptr(g->StructAggStatePerTransData));
 
 					v_ret = l_call(b, LLVMGetFunctionType(v_fn), v_fn, v_args, 2, "");
-					v_ret = LLVMBuildZExt(b, v_ret, TypeStorageBool, "");
+					v_ret = LLVMBuildZExt(b, v_ret, g->TypeStorageBool, "");
 
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_ret,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									opblocks[opno + 1],
 									opblocks[jumpdistinct]);
 					break;
@@ -2897,37 +3056,39 @@ llvm_compile_expr(ExprState *state)
 
 			case EEOP_AGG_PRESORTED_DISTINCT_MULTI:
 				{
-					AggState   *aggstate = castNode(AggState, state->parent);
-					AggStatePerTrans pertrans = op->d.agg_presorted_distinctcheck.pertrans;
+					///AggState   *aggstate = castNode(AggState, state->parent);
+					///AggStatePerTrans pertrans = op->d.agg_presorted_distinctcheck.pertrans;
 					int			jumpdistinct = op->d.agg_presorted_distinctcheck.jumpdistinct;
 
-					LLVMValueRef v_fn = llvm_pg_func(mod, "ExecEvalPreOrderedDistinctMulti");
+					LLVMValueRef v_fn = llvm_pg_func(context, "ExecEvalPreOrderedDistinctMulti");
 					LLVMValueRef v_args[2];
 					LLVMValueRef v_ret;
 
-					v_args[0] = l_ptr_const(aggstate, l_ptr(StructAggState));
-					v_args[1] = l_ptr_const(pertrans, l_ptr(StructAggStatePerTransData));
+					///v_args[0] = l_ptr_const(aggstate, l_ptr(g->StructAggState));
+					v_args[0] = v_parent;
+					///v_args[1] = l_ptr_const(pertrans, l_ptr(g->StructAggStatePerTransData));
+					v_args[1] = l_ptr_const_step(d.agg_presorted_distinctcheck.pertrans, l_ptr(g->StructAggStatePerTransData));
 
 					v_ret = l_call(b, LLVMGetFunctionType(v_fn), v_fn, v_args, 2, "");
-					v_ret = LLVMBuildZExt(b, v_ret, TypeStorageBool, "");
+					v_ret = LLVMBuildZExt(b, v_ret, g->TypeStorageBool, "");
 
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntEQ, v_ret,
-												  l_sbool_const(1), ""),
+												  LLVMConstInt(g->TypeStorageBool, (int)(1), false), ""),
 									opblocks[opno + 1],
 									opblocks[jumpdistinct]);
 					break;
 				}
 
 			case EEOP_AGG_ORDERED_TRANS_DATUM:
-				build_EvalXFunc(b, mod, "ExecEvalAggOrderedTransDatum",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalAggOrderedTransDatum",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
 			case EEOP_AGG_ORDERED_TRANS_TUPLE:
-				build_EvalXFunc(b, mod, "ExecEvalAggOrderedTransTuple",
-								v_state, op, v_econtext);
+				build_EvalXFunc(b, context, "ExecEvalAggOrderedTransTuple",
+								v_state, v_op, v_econtext);
 				LLVMBuildBr(b, opblocks[opno + 1]);
 				break;
 
@@ -2955,7 +3116,12 @@ llvm_compile_expr(ExprState *state)
 		state->evalfunc = ExecRunCompiledExpr;
 		state->evalfunc_private = cstate;
 	}
-
+	{
+		char *error = NULL;
+		///LLVMDumpModule(context->module);
+		LLVMVerifyModule(context->module, LLVMAbortProcessAction, &error);
+		LLVMDisposeMessage(error);
+	}
 	llvm_leave_fatal_on_oom();
 
 	INSTR_TIME_SET_CURRENT(endtime);
@@ -2994,32 +3160,31 @@ ExecRunCompiledExpr(ExprState *state, ExprContext *econtext, bool *isNull)
 }
 
 static LLVMValueRef
-BuildV1Call(LLVMJitContext *context, LLVMBuilderRef b,
-			LLVMModuleRef mod, FunctionCallInfo fcinfo,
-			LLVMValueRef *v_fcinfo_isnull)
+BuildV1CallLLVM(LLVMJitContext *context, LLVMBuilderRef b,
+			LLVMModuleRef mod, FunctionCallInfo fcinfo2,
+			LLVMValueRef v_fcinfo, LLVMValueRef *v_fcinfo_isnull)
 {
 	LLVMContextRef lc;
 	LLVMValueRef v_fn;
 	LLVMValueRef v_fcinfo_isnullp;
 	LLVMValueRef v_retval;
-	LLVMValueRef v_fcinfo;
 
 	lc = LLVMGetModuleContext(mod);
 
-	v_fn = llvm_function_reference(context, b, mod, fcinfo);
+	v_fn = llvm_function_reference(context, b, mod, fcinfo2, v_fcinfo);
 
-	v_fcinfo = l_ptr_const(fcinfo, l_ptr(StructFunctionCallInfoData));
+	///v_fcinfo = l_ptr_const(fcinfo, l_ptr(g->StructFunctionCallInfoData));
 	v_fcinfo_isnullp = l_struct_gep(b,
-									StructFunctionCallInfoData,
+									context->jit_types->StructFunctionCallInfoData,
 									v_fcinfo,
 									FIELDNO_FUNCTIONCALLINFODATA_ISNULL,
 									"v_fcinfo_isnull");
-	LLVMBuildStore(b, l_sbool_const(0), v_fcinfo_isnullp);
+	LLVMBuildStore(b, LLVMConstInt(context->jit_types->TypeStorageBool, (int)(0), false), v_fcinfo_isnullp);
 
-	v_retval = l_call(b, LLVMGetFunctionType(AttributeTemplate), v_fn, &v_fcinfo, 1, "funccall");
+	v_retval = l_call(b, LLVMGetFunctionType(context->jit_types->AttributeTemplate), v_fn, &v_fcinfo, 1, "funccall");
 
 	if (v_fcinfo_isnull)
-		*v_fcinfo_isnull = l_load(b, TypeStorageBool, v_fcinfo_isnullp, "");
+		*v_fcinfo_isnull = l_load(b, context->jit_types->TypeStorageBool, v_fcinfo_isnullp, "");
 
 	/*
 	 * Add lifetime-end annotation, signaling that writes to memory don't have
@@ -3028,13 +3193,15 @@ BuildV1Call(LLVMJitContext *context, LLVMBuilderRef b,
 	{
 		LLVMValueRef v_lifetime = create_LifetimeEnd(mod);
 		LLVMValueRef params[2];
-
-		params[0] = l_int64_const(lc, sizeof(NullableDatum) * fcinfo->nargs);
-		params[1] = l_ptr_const(fcinfo->args, l_ptr(LLVMInt8TypeInContext(lc)));
+		/* TODO check fcinfo2->nargs is const or is changed from call to call */
+		params[0] = l_int64_const(lc, sizeof(NullableDatum) * fcinfo2->nargs);
+		params[1] =  ///l_ptr_const(fcinfo->args, l_ptr(LLVMInt8TypeInContext(lc)));
+					l_load_member_value_by_offset(b, lc , v_fcinfo, l_ptr(LLVMInt8TypeInContext(lc)), offsetof(FunctionCallInfoBaseData, args) );
 		l_call(b, LLVMGetFunctionType(v_lifetime), v_lifetime, params, lengthof(params), "");
 
-		params[0] = l_int64_const(lc, sizeof(fcinfo->isnull));
-		params[1] = l_ptr_const(&fcinfo->isnull, l_ptr(LLVMInt8TypeInContext(lc)));
+		params[0] = l_int64_const(lc, sizeof(fcinfo2->isnull));
+		params[1] = /// l_ptr_const(&fcinfo->isnull, l_ptr(LLVMInt8TypeInContext(lc)));
+					l_struct_member_ptr_by_offset(b, lc, v_fcinfo, offsetof(FunctionCallInfoBaseData, isnull));
 		l_call(b, LLVMGetFunctionType(v_lifetime), v_lifetime, params, lengthof(params), "");
 	}
 
@@ -3045,11 +3212,11 @@ BuildV1Call(LLVMJitContext *context, LLVMBuilderRef b,
  * Implement an expression step by calling the function funcname.
  */
 static LLVMValueRef
-build_EvalXFuncInt(LLVMBuilderRef b, LLVMModuleRef mod, const char *funcname,
-				   LLVMValueRef v_state, ExprEvalStep *op,
+build_EvalXFuncIntLLVM(LLVMBuilderRef b, LLVMJitContext *context, const char *funcname,
+				   LLVMValueRef v_state, LLVMValueRef v_op,
 				   int nargs, LLVMValueRef *v_args)
 {
-	LLVMValueRef v_fn = llvm_pg_func(mod, funcname);
+	LLVMValueRef v_fn = llvm_pg_func(context, funcname);
 	LLVMValueRef *params;
 	int			argno = 0;
 	LLVMValueRef v_ret;
@@ -3062,7 +3229,7 @@ build_EvalXFuncInt(LLVMBuilderRef b, LLVMModuleRef mod, const char *funcname,
 	params = palloc(sizeof(LLVMValueRef) * (2 + nargs));
 
 	params[argno++] = v_state;
-	params[argno++] = l_ptr_const(op, l_ptr(StructExprEvalStep));
+	params[argno++] = v_op;
 
 	for (int i = 0; i < nargs; i++)
 		params[argno++] = v_args[i];
diff --git a/src/backend/jit/llvm/llvmjit_types.c b/src/backend/jit/llvm/llvmjit_types.c
index dbe0282e98f..f39ddfc30a6 100644
--- a/src/backend/jit/llvm/llvmjit_types.c
+++ b/src/backend/jit/llvm/llvmjit_types.c
@@ -69,6 +69,7 @@ MinimalTupleTableSlot StructMinimalTupleTableSlot;
 TupleDescData StructTupleDescData;
 PlanState	StructPlanState;
 MinimalTupleData StructMinimalTupleData;
+WindowFuncExprState StructWindowFuncExprState;
 
 
 /*
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 45915767825..9bb8ae0e076 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -61,6 +61,9 @@
 #define COPY_LOCATION_FIELD(fldname) \
 	(newnode->fldname = from->fldname)
 
+/* Copy a saved jit context */
+#define COPY_JITCONTEXT_FIELD(fldname) \
+	(newnode->fldname = from->fldname)
 
 #include "copyfuncs.funcs.c"
 
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index f2598a1b69a..6cd16db0a0d 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -84,6 +84,12 @@
 #define COMPARE_COERCIONFORM_FIELD(fldname) \
 	((void) 0)
 
+/* Compare a saved jit context */
+#define COMPARE_JITCONTEXT_FIELD(fldname) \
+	do { \
+		if (a->fldname != b->fldname) \
+			return false; \
+	} while (0)
 
 #include "equalfuncs.funcs.c"
 
diff --git a/src/backend/nodes/gen_node_support.pl b/src/backend/nodes/gen_node_support.pl
index 1a657f7e0ae..37c8cdf5ca6 100644
--- a/src/backend/nodes/gen_node_support.pl
+++ b/src/backend/nodes/gen_node_support.pl
@@ -865,6 +865,14 @@ _equal${n}(const $n *a, const $n *b)
 			print $cff "\tCOPY_SCALAR_FIELD($f);\n" unless $copy_ignore;
 			print $eff "\tCOMPARE_SCALAR_FIELD($f);\n" unless $equal_ignore;
 		}
+		elsif ($t eq 'struct JitContext*')
+		{
+			# Fields of these types are required to be a pointer to a
+			# static struct.  So we don't copy the struct itself,
+			# just reference the original one.
+			print $cff "\tCOPY_SCALAR_FIELD($f);\n" unless $copy_ignore;
+			print $eff "\tCOMPARE_SCALAR_FIELD($f);\n" unless $equal_ignore;
+		}
 		else
 		{
 			die
@@ -1214,6 +1222,11 @@ _read${n}(void)
 	}
 ! unless $no_read;
 		}
+		elsif ($t eq 'struct JitContext*')
+		{
+			print $off "\tWRITE_JITCONTEXT_FIELD($f);\n";
+			print $rff "\tREAD_JITCONTEXT_FIELD($f);\n" unless $no_read;
+		}
 		else
 		{
 			die
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index bb9bdd67192..9c772a00197 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -93,6 +93,10 @@ static void outDouble(StringInfo str, double d);
 #define WRITE_LOCATION_FIELD(fldname) \
 	appendStringInfo(str, " :" CppAsString(fldname) " %d", write_location_fields ? node->fldname : -1)
 
+/* Write a parse jit context field (actually same as INT case) */
+#define WRITE_JITCONTEXT_FIELD(fldname) \
+	appendStringInfo(str, " :" CppAsString(fldname) " %d", 0)
+
 /* Write a Node field */
 #define WRITE_NODE_FIELD(fldname) \
 	(appendStringInfoString(str, " :" CppAsString(fldname) " "), \
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index 64d3a09f765..a2fca4b2370 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -131,6 +131,12 @@
 	local_node->fldname = -1	/* set field to "unknown" */
 #endif
 
+/* Read a parse jit context field*/
+#define READ_JITCONTEXT_FIELD(fldname) \
+	token = pg_strtok(&length);		/* skip :fldname */ \
+	token = pg_strtok(&length);		/* get field value */ \
+	local_node->fldname = 0 		/* set field to "not cached" */
+
 /* Read a Node field */
 #define READ_NODE_FIELD(fldname) \
 	token = pg_strtok(&length);		/* skip :fldname */ \
diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c
index 55db8f53705..c0dfc65f7cb 100644
--- a/src/backend/utils/cache/plancache.c
+++ b/src/backend/utils/cache/plancache.c
@@ -72,6 +72,7 @@
 #include "utils/rls.h"
 #include "utils/snapmgr.h"
 #include "utils/syscache.h"
+#include "jit/jit.h"
 
 
 /*
@@ -1015,6 +1016,10 @@ BuildCachedPlan(CachedPlanSource *plansource, List *qlist,
 			is_transient = true;
 		if (plannedstmt->dependsOnRole)
 			plan->dependsOnRole = true;
+		if (!plansource->is_oneshot && !plannedstmt->jit_context)
+		{
+			plannedstmt->jit_context = CACHED_JITCONTEXT_EMPTY;
+		}
 	}
 	if (is_transient)
 	{
@@ -1305,7 +1310,23 @@ ReleaseCachedPlan(CachedPlan *plan, ResourceOwner owner)
 
 		/* One-shot plans do not own their context, so we can't free them */
 		if (!plan->is_oneshot)
+		{
+#ifdef USE_LLVM
+			/* release cached jit contexts */
+			ListCell   *lc;
+			foreach(lc, plan->stmt_list)
+			{
+				PlannedStmt *plannedstmt = lfirst_node(PlannedStmt, lc);
+
+				if (plannedstmt->jit_context &&
+					plannedstmt->jit_context != CACHED_JITCONTEXT_EMPTY)
+				{
+					jit_release_context(plannedstmt->jit_context); /* todo fix to correct pointer to jit context (.jit)*/
+				}
+			}
+#endif
 			MemoryContextDelete(plan->context);
+		}
 	}
 }
 
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index cce73314609..4d16ac3ff04 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -2003,6 +2003,18 @@ struct config_bool ConfigureNamesBool[] =
 		NULL, NULL, NULL
 	},
 
+	{
+		{"jit_cached", PGC_USERSET, QUERY_TUNING_OTHER,
+			gettext_noop("Allow JIT compilation to store in a plan cache."),
+			NULL,
+			GUC_EXPLAIN
+		},
+		&jit_cached,
+		false,
+		NULL, NULL, NULL
+	},
+
+
 	{
 		{"jit_debugging_support", PGC_SU_BACKEND, DEVELOPER_OPTIONS,
 			gettext_noop("Register JIT-compiled functions with debugger."),
diff --git a/src/include/executor/execExpr.h b/src/include/executor/execExpr.h
index 191d8fe34de..34a741cfe69 100644
--- a/src/include/executor/execExpr.h
+++ b/src/include/executor/execExpr.h
@@ -301,7 +301,9 @@ typedef struct ExprEvalStep
 	intptr_t	opcode;
 
 	/* where to store the result of this step */
+#define FIELDNO_EXPREVALSTEP_RESVALUE	1
 	Datum	   *resvalue;
+#define FIELDNO_EXPREVALSTEP_RESNULL	2
 	bool	   *resnull;
 
 	/*
diff --git a/src/include/jit/jit.h b/src/include/jit/jit.h
index 33cb36c5d2e..ca8dc047c7f 100644
--- a/src/include/jit/jit.h
+++ b/src/include/jit/jit.h
@@ -81,6 +81,7 @@ struct JitProviderCallbacks
 
 /* GUCs */
 extern PGDLLIMPORT bool jit_enabled;
+extern PGDLLIMPORT bool jit_cached;
 extern PGDLLIMPORT char *jit_provider;
 extern PGDLLIMPORT bool jit_debugging_support;
 extern PGDLLIMPORT bool jit_dump_bitcode;
diff --git a/src/include/jit/llvmjit.h b/src/include/jit/llvmjit.h
index 5038cf33e3f..b562c68d064 100644
--- a/src/include/jit/llvmjit.h
+++ b/src/include/jit/llvmjit.h
@@ -40,6 +40,38 @@ extern "C"
 #include "jit/jit.h"
 #include "nodes/pg_list.h"
 
+/* type and struct definitions */
+typedef struct LLVMJitTypes
+{
+	LLVMTypeRef TypeParamBool;
+	LLVMTypeRef TypePGFunction;
+	LLVMTypeRef TypeSizeT;
+	LLVMTypeRef TypeStorageBool;
+
+	LLVMTypeRef StructNullableDatum;
+	LLVMTypeRef StructTupleDescData;
+	LLVMTypeRef StructHeapTupleData;
+	LLVMTypeRef StructHeapTupleHeaderData;
+	LLVMTypeRef StructMinimalTupleData;
+	LLVMTypeRef StructTupleTableSlot;
+	LLVMTypeRef StructHeapTupleTableSlot;
+	LLVMTypeRef StructMinimalTupleTableSlot;
+	LLVMTypeRef StructMemoryContextData;
+	LLVMTypeRef StructFunctionCallInfoData;
+	LLVMTypeRef StructExprContext;
+	LLVMTypeRef StructExprEvalStep;
+	LLVMTypeRef StructExprState;
+	LLVMTypeRef StructAggState;
+	LLVMTypeRef StructAggStatePerTransData;
+	LLVMTypeRef StructAggStatePerGroupData;
+	LLVMTypeRef StructPlanState;
+	LLVMTypeRef StructWindowFuncExprState;
+
+	LLVMValueRef AttributeTemplate;
+	LLVMValueRef ExecEvalBoolSubroutineTemplate;
+	LLVMValueRef ExecEvalSubroutineTemplate;
+} LLVMJitTypes;
+
 typedef struct LLVMJitContext
 {
 	JitContext	base;
@@ -60,6 +92,12 @@ typedef struct LLVMJitContext
 	/* current, "open for write", module */
 	LLVMModuleRef module;
 
+	/* types module in llvm_context or NULL */
+	LLVMModuleRef llvm_types_module;
+
+	/* types defined in types module */
+	LLVMJitTypes *jit_types;
+
 	/* is there any pending code that needs to be emitted */
 	bool		compiled;
 
@@ -68,36 +106,12 @@ typedef struct LLVMJitContext
 
 	/* list of handles for code emitted via Orc */
 	List	   *handles;
-} LLVMJitContext;
 
-/* type and struct definitions */
-extern PGDLLIMPORT LLVMTypeRef TypeParamBool;
-extern PGDLLIMPORT LLVMTypeRef TypePGFunction;
-extern PGDLLIMPORT LLVMTypeRef TypeSizeT;
-extern PGDLLIMPORT LLVMTypeRef TypeStorageBool;
-
-extern PGDLLIMPORT LLVMTypeRef StructNullableDatum;
-extern PGDLLIMPORT LLVMTypeRef StructTupleDescData;
-extern PGDLLIMPORT LLVMTypeRef StructHeapTupleData;
-extern PGDLLIMPORT LLVMTypeRef StructHeapTupleHeaderData;
-extern PGDLLIMPORT LLVMTypeRef StructMinimalTupleData;
-extern PGDLLIMPORT LLVMTypeRef StructTupleTableSlot;
-extern PGDLLIMPORT LLVMTypeRef StructHeapTupleTableSlot;
-extern PGDLLIMPORT LLVMTypeRef StructMinimalTupleTableSlot;
-extern PGDLLIMPORT LLVMTypeRef StructMemoryContextData;
-extern PGDLLIMPORT LLVMTypeRef StructFunctionCallInfoData;
-extern PGDLLIMPORT LLVMTypeRef StructExprContext;
-extern PGDLLIMPORT LLVMTypeRef StructExprEvalStep;
-extern PGDLLIMPORT LLVMTypeRef StructExprState;
-extern PGDLLIMPORT LLVMTypeRef StructAggState;
-extern PGDLLIMPORT LLVMTypeRef StructAggStatePerTransData;
-extern PGDLLIMPORT LLVMTypeRef StructAggStatePerGroupData;
-extern PGDLLIMPORT LLVMTypeRef StructPlanState;
-
-extern PGDLLIMPORT LLVMValueRef AttributeTemplate;
-extern PGDLLIMPORT LLVMValueRef ExecEvalBoolSubroutineTemplate;
-extern PGDLLIMPORT LLVMValueRef ExecEvalSubroutineTemplate;
+	/* cached plan memory context */
+	MemoryContext	plan_mem_context;
+} LLVMJitContext;
 
+extern PGDLLIMPORT LLVMJitTypes llvm_jit_types_struct;
 
 extern void llvm_enter_fatal_on_oom(void);
 extern void llvm_leave_fatal_on_oom(void);
@@ -106,18 +120,21 @@ extern void llvm_reset_after_error(void);
 extern void llvm_assert_in_fatal_section(void);
 
 extern LLVMJitContext *llvm_create_context(int jitFlags);
+extern LLVMJitContext *llvm_create_cached_context(int jitFlags);
 extern LLVMModuleRef llvm_mutable_module(LLVMJitContext *context);
-extern char *llvm_expand_funcname(LLVMJitContext *context, const char *basename);
+extern char * llvm_expand_funcname_name(struct LLVMJitContext *context, const char *basename, Size counter);
+extern char * llvm_expand_funcname(struct LLVMJitContext *context, const char *basename);
 extern void *llvm_get_function(LLVMJitContext *context, const char *funcname);
 extern void llvm_split_symbol_name(const char *name, char **modname, char **funcname);
-extern LLVMTypeRef llvm_pg_var_type(const char *varname);
-extern LLVMTypeRef llvm_pg_var_func_type(const char *varname);
-extern LLVMValueRef llvm_pg_func(LLVMModuleRef mod, const char *funcname);
+extern LLVMTypeRef llvm_pg_var_type(LLVMModuleRef llvm_types_module, const char *varname);
+extern LLVMTypeRef llvm_pg_var_func_type(LLVMJitContext *context, const char *varname);
+extern LLVMValueRef llvm_pg_func(LLVMJitContext *context /*LLVMModuleRef mod*/, const char *funcname);
 extern void llvm_copy_attributes(LLVMValueRef from, LLVMValueRef to);
 extern LLVMValueRef llvm_function_reference(LLVMJitContext *context,
 						LLVMBuilderRef builder,
 						LLVMModuleRef mod,
-						FunctionCallInfo fcinfo);
+						FunctionCallInfo fcinfo,
+						LLVMValueRef v_fcinfo);
 
 extern void llvm_inline_reset_caches(void);
 extern void llvm_inline(LLVMModuleRef mod);
diff --git a/src/include/jit/llvmjit_emit.h b/src/include/jit/llvmjit_emit.h
index df5a9fc8500..643a824622a 100644
--- a/src/include/jit/llvmjit_emit.h
+++ b/src/include/jit/llvmjit_emit.h
@@ -25,7 +25,7 @@
  * Emit a non-LLVM pointer as an LLVM constant.
  */
 static inline LLVMValueRef
-l_ptr_const(void *ptr, LLVMTypeRef type)
+l_ptr_const(void *ptr, LLVMTypeRef type, LLVMTypeRef TypeSizeT)
 {
 	LLVMValueRef c = LLVMConstInt(TypeSizeT, (uintptr_t) ptr, false);
 
@@ -77,33 +77,6 @@ l_int64_const(LLVMContextRef lc, int64 i)
 	return LLVMConstInt(LLVMInt64TypeInContext(lc), i, false);
 }
 
-/*
- * Emit constant integer.
- */
-static inline LLVMValueRef
-l_sizet_const(size_t i)
-{
-	return LLVMConstInt(TypeSizeT, i, false);
-}
-
-/*
- * Emit constant boolean, as used for storage (e.g. global vars, structs).
- */
-static inline LLVMValueRef
-l_sbool_const(bool i)
-{
-	return LLVMConstInt(TypeStorageBool, (int) i, false);
-}
-
-/*
- * Emit constant boolean, as used for parameters (e.g. function parameters).
- */
-static inline LLVMValueRef
-l_pbool_const(bool i)
-{
-	return LLVMConstInt(TypeParamBool, (int) i, false);
-}
-
 static inline LLVMValueRef
 l_struct_gep(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, int32 idx, const char *name)
 {
@@ -149,6 +122,31 @@ l_load_gep1(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, LLVMValueRef idx, c
 	return l_load(b, t, l_gep(b, t, v, &idx, 1, ""), name);
 }
 
+/*
+ * Load value of a structure using offset of member in structure.
+ * b - builder
+ * v - value of sturcture
+ * dest - the type of the structure member
+ * offset - the offset of the structure member in the structure v
+ */
+static inline LLVMValueRef
+l_load_member_value_by_offset(LLVMBuilderRef b, LLVMContextRef lc, LLVMValueRef v, LLVMTypeRef dest, int offset)
+{
+    LLVMValueRef offsets = l_int32_const(lc, offset);
+    LLVMValueRef member_address = l_gep(b,(LLVMInt8TypeInContext(lc)), v, &offsets, 1, "member_address");
+    return l_load(b, dest, member_address, "member_value");
+}
+
+#define l_ptr_const_step(m,t) l_load_member_value_by_offset(b,lc, v_op, t, offsetof(ExprEvalStep ,m))
+
+static inline LLVMValueRef
+l_struct_member_ptr_by_offset(LLVMBuilderRef b, LLVMContextRef lc, LLVMValueRef v, /* LLVMTypeRef dest, */ int offset)
+{
+    LLVMValueRef offsets = l_int32_const(lc, offset);
+    LLVMValueRef member_address = l_gep(b,(LLVMInt8TypeInContext(lc)), v, &offsets, 1, "member_address");
+    return member_address;
+}
+
 /* separate, because pg_attribute_printf(2, 3) can't appear in definition */
 static inline LLVMBasicBlockRef l_bb_before_v(LLVMBasicBlockRef r, const char *fmt,...) pg_attribute_printf(2, 3);
 
@@ -232,15 +230,15 @@ l_callsite_alwaysinline(LLVMValueRef f)
  * Emit code to switch memory context.
  */
 static inline LLVMValueRef
-l_mcxt_switch(LLVMModuleRef mod, LLVMBuilderRef b, LLVMValueRef nc)
+l_mcxt_switch(LLVMModuleRef mod, LLVMBuilderRef b, LLVMValueRef nc, LLVMJitTypes *g)
 {
 	const char *cmc = "CurrentMemoryContext";
 	LLVMValueRef cur;
 	LLVMValueRef ret;
 
 	if (!(cur = LLVMGetNamedGlobal(mod, cmc)))
-		cur = LLVMAddGlobal(mod, l_ptr(StructMemoryContextData), cmc);
-	ret = l_load(b, l_ptr(StructMemoryContextData), cur, cmc);
+		cur = LLVMAddGlobal(mod, l_ptr(g->StructMemoryContextData), cmc);
+	ret = l_load(b, l_ptr(g->StructMemoryContextData), cur, cmc);
 	LLVMBuildStore(b, nc, cur);
 
 	return ret;
@@ -250,23 +248,23 @@ l_mcxt_switch(LLVMModuleRef mod, LLVMBuilderRef b, LLVMValueRef nc)
  * Return pointer to the argno'th argument nullness.
  */
 static inline LLVMValueRef
-l_funcnullp(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
+l_funcnullp(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno, LLVMJitTypes *g)
 {
 	LLVMValueRef v_args;
 	LLVMValueRef v_argn;
 
 	v_args = l_struct_gep(b,
-						  StructFunctionCallInfoData,
+						  g->StructFunctionCallInfoData,
 						  v_fcinfo,
 						  FIELDNO_FUNCTIONCALLINFODATA_ARGS,
 						  "");
 	v_argn = l_struct_gep(b,
-						  LLVMArrayType(StructNullableDatum, 0),
+						  LLVMArrayType(g->StructNullableDatum, 0),
 						  v_args,
 						  argno,
 						  "");
 	return l_struct_gep(b,
-						StructNullableDatum,
+						g->StructNullableDatum,
 						v_argn,
 						FIELDNO_NULLABLE_DATUM_ISNULL,
 						"");
@@ -276,23 +274,23 @@ l_funcnullp(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
  * Return pointer to the argno'th argument datum.
  */
 static inline LLVMValueRef
-l_funcvaluep(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
+l_funcvaluep(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno, LLVMJitTypes *g)
 {
 	LLVMValueRef v_args;
 	LLVMValueRef v_argn;
 
 	v_args = l_struct_gep(b,
-						  StructFunctionCallInfoData,
+						  g->StructFunctionCallInfoData,
 						  v_fcinfo,
 						  FIELDNO_FUNCTIONCALLINFODATA_ARGS,
 						  "");
 	v_argn = l_struct_gep(b,
-						  LLVMArrayType(StructNullableDatum, 0),
+						  LLVMArrayType(g->StructNullableDatum, 0),
 						  v_args,
 						  argno,
 						  "");
 	return l_struct_gep(b,
-						StructNullableDatum,
+						g->StructNullableDatum,
 						v_argn,
 						FIELDNO_NULLABLE_DATUM_DATUM,
 						"");
@@ -302,18 +300,18 @@ l_funcvaluep(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
  * Return argno'th argument nullness.
  */
 static inline LLVMValueRef
-l_funcnull(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
+l_funcnull(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno, LLVMJitTypes *g)
 {
-	return l_load(b, TypeStorageBool, l_funcnullp(b, v_fcinfo, argno), "");
+	return l_load(b, g->TypeStorageBool, l_funcnullp(b, v_fcinfo, argno, g), "");
 }
 
 /*
  * Return argno'th argument datum.
  */
 static inline LLVMValueRef
-l_funcvalue(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
+l_funcvalue(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno, LLVMJitTypes *g)
 {
-	return l_load(b, TypeSizeT, l_funcvaluep(b, v_fcinfo, argno), "");
+	return l_load(b, g->TypeSizeT, l_funcvaluep(b, v_fcinfo, argno, g), "");
 }
 
 #endif							/* USE_LLVM */
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 2625d7e8222..608baa9c9dd 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -108,6 +108,7 @@ typedef struct ExprState
 	/*
 	 * Instructions to compute expression's return value.
 	 */
+#define FIELDNO_EXPRSTATE_STEPS	5
 	struct ExprEvalStep *steps;
 
 	/*
@@ -272,6 +273,7 @@ typedef struct ExprContext
 
 	/* Memory contexts for expression evaluation --- see notes above */
 	MemoryContext ecxt_per_query_memory;
+#define FIELDNO_EXPRCONTEXT_PERTUPLEMEMORY 5
 	MemoryContext ecxt_per_tuple_memory;
 
 	/* Values to substitute for Param nodes in expression */
@@ -2537,6 +2539,7 @@ typedef struct AggState
 	AggStatePerTrans pertrans;	/* per-Trans state information */
 	ExprContext *hashcontext;	/* econtexts for long-lived data (hashtable) */
 	ExprContext **aggcontexts;	/* econtexts for long-lived data (per GS) */
+#define FIELDNO_AGGSTATE_TMPCONTEXT 13
 	ExprContext *tmpcontext;	/* econtext for input expressions */
 #define FIELDNO_AGGSTATE_CURAGGCONTEXT 14
 	ExprContext *curaggcontext; /* currently active aggcontext */
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index bf1f25c0dba..0347c23133f 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -22,7 +22,8 @@
 #include "nodes/lockoptions.h"
 #include "nodes/primnodes.h"
 
-
+struct JitContext;
+#define CACHED_JITCONTEXT_EMPTY ((struct JitContext*)(-1))
 /* ----------------------------------------------------------------
  *						node definitions
  * ----------------------------------------------------------------
@@ -133,6 +134,8 @@ typedef struct PlannedStmt
 	ParseLoc	stmt_location;
 	/* length in bytes; 0 means "rest of string" */
 	ParseLoc	stmt_len;
+	/* context of save jit-module */
+	struct JitContext	*jit_context;
 } PlannedStmt;
 
 /* macro for fetching the Plan associated with a SubPlan node */
-- 
2.39.5 (Apple Git-154)

#4Matheus Alcantara
matheusssilv97@gmail.com
In reply to: Vladlen Popolitov (#3)
Re: PoC. The saving of the compiled jit-code in the plan cache

Hi,

I've spent some time learning more about jit in the last few weeks and I
think that this patch could be very useful, thanks for working on this!
I'm new on this subject but I would like to share some thoughts about
it.

1. Changes in jit-code generation.

a) the load of the absolute address (as const) changed to the load of this
address from a struct member:

If I understood correctly, this change is required to avoid making the
jit code points to a memory address that was reallocated (making it
invalid)? If that's the case, would be possible to split this change
into a separated patch? It would help a lot to review.

It's not clear to me what's the difference between jit_context being set
to NULL or CACHED_JITCONTEXT_EMPTY and how it changes from NULL to
CACHED_JITCONTEXT_EMPTY. I think some code comments will help on this,
specially on llvm_compile_expr around if/else blocks.

Updated patch rebased to the current master. Also I resolved the problems
with the lookup of the compiled expressions.
Cached jit compiles only expressions from cached plan - they are
recognized by memory context - if Expr is not NULL and belong to the same
memory context as cached plan, this expression is compiled to the function
with expression address in the name (expression address casted to Size
type).
All other expression (generated later than plan, f.e. expressions in
aggregates, hash join, hash aggregates) are not compiled and are executed
by standard expression interpreter.

What's stopping us from going back to the current code generation
without caching on these scenarios? I'm a bit concerned for never jit
compile these kind of expressions and have some kind of performance
issue.

What's the relation of this exec time generated expressions (hash join,
hash agg) problem with the function name lookup issue? It's seems
different problems to me but I may be missing something.

If these problems is not fully correlated I think that it would be
better to have some kind of hash map or use the number of the call to
connect expressions with functions (as you did on v4) to lookup the
cached compiled function. IMHO it sounds a bit strange to me to add the
function pointer on the function name and have this memory context
validation.

I've also executed make check-world and it seems that
test_misc/003_check_guc is falling:

[11:29:42.995](1.153s) not ok 1 - no parameters missing from
postgresql.conf.sample
[11:29:42.995](0.000s) # Failed test 'no parameters missing from
postgresql.conf.sample'
# at src/test/modules/test_misc/t/003_check_guc.pl line 85.
[11:29:42.995](0.000s) # got: '1'
# expected: '0'
[11:29:42.995](0.000s) ok 2 - no parameters missing from guc_tables.c
[11:29:42.995](0.000s) ok 3 - no parameters marked as NOT_IN_SAMPLE in
postgresql.conf.sample
found GUC jit_cached in guc_tables.c, missing from postgresql.conf.sample

--
Matheus Alcantara

#5Vladlen Popolitov
v.popolitov@postgrespro.ru
In reply to: Matheus Alcantara (#4)
Re: PoC. The saving of the compiled jit-code in the plan cache

Matheus Alcantara писал(а) 2025-03-07 05:02:

Hi!

Thank for interest to the patch.

1. Changes in jit-code generation.

a) the load of the absolute address (as const) changed to the load of
this
address from a struct member:

If I understood correctly, this change is required to avoid making the
jit code points to a memory address that was reallocated (making it
invalid)? If that's the case, would be possible to split this change
into a separated patch? It would help a lot to review.

Yes, you correct. In this patch the value of the pointers initialised
every time, when code called for new structure, to reffer to new
address.
I did not put it into separate patch, because now I see all changes
in the system are interconnected and require to change many files.
It is hard to maintain, at least now.

Also I did it to check the possibility to implement it and check, is it
really better. During implementation I understood, that the design must
be changed and clarified, it looks dirty now.

It's not clear to me what's the difference between jit_context being
set
to NULL or CACHED_JITCONTEXT_EMPTY and how it changes from NULL to
CACHED_JITCONTEXT_EMPTY. I think some code comments will help on this,
specially on llvm_compile_expr around if/else blocks.

When llvm_compile_expr is called, I need to know, is it compilation for
cache or usual compilation. I use jit_context for this. It is always
initialised by NULL in palloc0(). If plan is saved to cache,
jit_context assigned CACHED_JITCONTEXT_EMPTY - it means, jit also must
me saved in cache, but not saved yet.

Updated patch rebased to the current master. Also I resolved the
problems
with the lookup of the compiled expressions.
Cached jit compiles only expressions from cached plan - they are
recognized by memory context - if Expr is not NULL and belong to the
same
memory context as cached plan, this expression is compiled to the
function
with expression address in the name (expression address casted to Size
type).
All other expression (generated later than plan, f.e. expressions in
aggregates, hash join, hash aggregates) are not compiled and are
executed
by standard expression interpreter.

What's stopping us from going back to the current code generation
without caching on these scenarios? I'm a bit concerned for never jit
compile these kind of expressions and have some kind of performance
issue.

I thought about this. The reason to store the jit in cache - avoid
compiling every time when query is executed. If we anyway compile
the code even for 1 function, we lose benefits of cached jit code.
We can choose the standard jit compilation for other functions.

What's the relation of this exec time generated expressions (hash join,
hash agg) problem with the function name lookup issue? It's seems
different problems to me but I may be missing something.

This question and next question are correlated.

If these problems is not fully correlated I think that it would be
better to have some kind of hash map or use the number of the call to
connect expressions with functions (as you did on v4) to lookup the
cached compiled function. IMHO it sounds a bit strange to me to add the
function pointer on the function name and have this memory context
validation.

This function lookup the biggest challenge in this patch, I see
it correct.
In current implementation: the function is generated for expression,
the name of the function is saved in the ExprState,
then function is compiled (when first expression is executed),
then the function is called,
lookup by saved address is done to find compiled code,
the compiled code address is saved in ExprState as new execution code,
the compiled code is called.

In cached implementation when expression is called the next time,
we need to find the link among the expression and the compiled code.
I tried to find reliable way to connect them, and see now only one
version - make compilation only for expressions saved with the plan -
they have the same address across the time and the same memory context
as the saved plan. Expressions generated during execution like
aggregate expression and Hash join expression are allocated in
query execution context and always have different addresses, and I did
not find any way to connect them with cached plan. The have "expr"
member, but it can be NULL, T_List or T_Expr (or anything, what
Custom node can assign to it).
Function name with expression address now looks as reliable way to find
compiled function, though not elegant. Standard implementation just
stores
generated name, uses it and pfree() it.

I've also executed make check-world and it seems that
test_misc/003_check_guc is falling:

[11:29:42.995](1.153s) not ok 1 - no parameters missing from
postgresql.conf.sample
[11:29:42.995](0.000s) # Failed test 'no parameters missing from
postgresql.conf.sample'
# at src/test/modules/test_misc/t/003_check_guc.pl line 85.
[11:29:42.995](0.000s) # got: '1'
# expected: '0'
[11:29:42.995](0.000s) ok 2 - no parameters missing from guc_tables.c
[11:29:42.995](0.000s) ok 3 - no parameters marked as NOT_IN_SAMPLE in
postgresql.conf.sample
found GUC jit_cached in guc_tables.c, missing from
postgresql.conf.sample

I tested in with make check and make installcheck . In v8 I found bugs,
but
not published fix yet.

--
Best regards,

Vladlen Popolitov.

#6Matheus Alcantara
matheusssilv97@gmail.com
In reply to: Vladlen Popolitov (#5)
Re: PoC. The saving of the compiled jit-code in the plan cache

On Fri, Mar 7, 2025 at 7:43 AM Vladlen Popolitov
<v.popolitov@postgrespro.ru> wrote:

Updated patch rebased to the current master. Also I resolved the
problems
with the lookup of the compiled expressions.
Cached jit compiles only expressions from cached plan - they are
recognized by memory context - if Expr is not NULL and belong to the
same
memory context as cached plan, this expression is compiled to the
function
with expression address in the name (expression address casted to Size
type).
All other expression (generated later than plan, f.e. expressions in
aggregates, hash join, hash aggregates) are not compiled and are
executed
by standard expression interpreter.

What's stopping us from going back to the current code generation
without caching on these scenarios? I'm a bit concerned for never jit
compile these kind of expressions and have some kind of performance
issue.

I thought about this. The reason to store the jit in cache - avoid
compiling every time when query is executed. If we anyway compile
the code even for 1 function, we lose benefits of cached jit code.
We can choose the standard jit compilation for other functions.

I don't think that I get your point here - Why we would lose the
benefits? I think that I may not be clear with my question; My point
was, why we can't jit compile, without caching, these expressions that
are generated later on the plan? Like aggregates, hash join, as you
mention. I think that we may have scenarios that jit compile is worth
even if we will not cache the compiled code. I understand the limitation
of runtime generated ExprState being allocated in another memory
context, but why can't we follow the same path as we have today for
these scenarios?

What's the relation of this exec time generated expressions (hash join,
hash agg) problem with the function name lookup issue? It's seems
different problems to me but I may be missing something.

This question and next question are correlated.

If these problems is not fully correlated I think that it would be
better to have some kind of hash map or use the number of the call to
connect expressions with functions (as you did on v4) to lookup the
cached compiled function. IMHO it sounds a bit strange to me to add the
function pointer on the function name and have this memory context
validation.

This function lookup the biggest challenge in this patch, I see
it correct.
In current implementation: the function is generated for expression,
the name of the function is saved in the ExprState,
then function is compiled (when first expression is executed),
then the function is called,
lookup by saved address is done to find compiled code,
the compiled code address is saved in ExprState as new execution code,
the compiled code is called.

In cached implementation when expression is called the next time,
we need to find the link among the expression and the compiled code.
I tried to find reliable way to connect them, and see now only one
version - make compilation only for expressions saved with the plan -
they have the same address across the time and the same memory context
as the saved plan. Expressions generated during execution like
aggregate expression and Hash join expression are allocated in
query execution context and always have different addresses, and I did
not find any way to connect them with cached plan. The have "expr"
member, but it can be NULL, T_List or T_Expr (or anything, what
Custom node can assign to it).
Function name with expression address now looks as reliable way to find
compiled function, though not elegant. Standard implementation just
stores
generated name, uses it and pfree() it.

Yeah, I see that this sounds a bit complicated. I'm wondering if this
logic of checking if the expr is already cached or not could be
implemented in another function or layer (maybe jit_compile_expr?). I
think that llvm_compile_expr is already complicated enough and it should
only care about emitting code, so we could have another layer that check
if the expr is already compiled or not and only call llvm_compile_expr
if it's not compiled yet, WYT?

I've also executed make check-world and it seems that
test_misc/003_check_guc is falling:

[11:29:42.995](1.153s) not ok 1 - no parameters missing from
postgresql.conf.sample
[11:29:42.995](0.000s) # Failed test 'no parameters missing from
postgresql.conf.sample'
# at src/test/modules/test_misc/t/003_check_guc.pl line 85.
[11:29:42.995](0.000s) # got: '1'
# expected: '0'
[11:29:42.995](0.000s) ok 2 - no parameters missing from guc_tables.c
[11:29:42.995](0.000s) ok 3 - no parameters marked as NOT_IN_SAMPLE in
postgresql.conf.sample
found GUC jit_cached in guc_tables.c, missing from
postgresql.conf.sample

I tested in with make check and make installcheck . In v8 I found bugs,
but not published fix yet.

Do you have any intent to work on a new version for this?

--
Matheus Alcantara

#7Vladlen Popolitov
v.popolitov@postgrespro.ru
In reply to: Matheus Alcantara (#6)
Re: PoC. The saving of the compiled jit-code in the plan cache

Matheus Alcantara писал(а) 2025-03-18 21:56:

On Fri, Mar 7, 2025 at 7:43 AM Vladlen Popolitov
<v.popolitov@postgrespro.ru> wrote:

Updated patch rebased to the current master. Also I resolved the
problems
with the lookup of the compiled expressions.
Cached jit compiles only expressions from cached plan - they are
recognized by memory context - if Expr is not NULL and belong to the
same
memory context as cached plan, this expression is compiled to the
function
with expression address in the name (expression address casted to Size
type).
All other expression (generated later than plan, f.e. expressions in
aggregates, hash join, hash aggregates) are not compiled and are
executed
by standard expression interpreter.

What's stopping us from going back to the current code generation
without caching on these scenarios? I'm a bit concerned for never jit
compile these kind of expressions and have some kind of performance
issue.

I thought about this. The reason to store the jit in cache - avoid
compiling every time when query is executed. If we anyway compile
the code even for 1 function, we lose benefits of cached jit code.
We can choose the standard jit compilation for other functions.

I don't think that I get your point here - Why we would lose the
benefits? I think that I may not be clear with my question; My point
was, why we can't jit compile, without caching, these expressions that
are generated later on the plan? Like aggregates, hash join, as you
mention. I think that we may have scenarios that jit compile is worth
even if we will not cache the compiled code. I understand the
limitation
of runtime generated ExprState being allocated in another memory
context, but why can't we follow the same path as we have today for
these scenarios?

Yes, I understood. It is possible to make compilation of the newly
created expressions. I tried to avoid additional compilation and chose
the implementation without compilation.

What's the relation of this exec time generated expressions (hash join,
hash agg) problem with the function name lookup issue? It's seems
different problems to me but I may be missing something.

This question and next question are correlated.

If these problems is not fully correlated I think that it would be
better to have some kind of hash map or use the number of the call to
connect expressions with functions (as you did on v4) to lookup the
cached compiled function. IMHO it sounds a bit strange to me to add the
function pointer on the function name and have this memory context
validation.

This function lookup the biggest challenge in this patch, I see
it correct.
In current implementation: the function is generated for expression,
the name of the function is saved in the ExprState,
then function is compiled (when first expression is executed),
then the function is called,
lookup by saved address is done to find compiled code,
the compiled code address is saved in ExprState as new execution code,
the compiled code is called.

In cached implementation when expression is called the next time,
we need to find the link among the expression and the compiled code.
I tried to find reliable way to connect them, and see now only one
version - make compilation only for expressions saved with the plan -
they have the same address across the time and the same memory context
as the saved plan. Expressions generated during execution like
aggregate expression and Hash join expression are allocated in
query execution context and always have different addresses, and I did
not find any way to connect them with cached plan. The have "expr"
member, but it can be NULL, T_List or T_Expr (or anything, what
Custom node can assign to it).
Function name with expression address now looks as reliable way to
find
compiled function, though not elegant. Standard implementation just
stores
generated name, uses it and pfree() it.

Yeah, I see that this sounds a bit complicated. I'm wondering if this
logic of checking if the expr is already cached or not could be
implemented in another function or layer (maybe jit_compile_expr?). I
think that llvm_compile_expr is already complicated enough and it
should
only care about emitting code, so we could have another layer that
check
if the expr is already compiled or not and only call llvm_compile_expr
if it's not compiled yet, WYT?

I agree, it requires cleaning of the code. I am going to do it on the
next
step.

I've also executed make check-world and it seems that
test_misc/003_check_guc is falling:

[11:29:42.995](1.153s) not ok 1 - no parameters missing from
postgresql.conf.sample
[11:29:42.995](0.000s) # Failed test 'no parameters missing from
postgresql.conf.sample'
# at src/test/modules/test_misc/t/003_check_guc.pl line 85.
[11:29:42.995](0.000s) # got: '1'
# expected: '0'
[11:29:42.995](0.000s) ok 2 - no parameters missing from guc_tables.c
[11:29:42.995](0.000s) ok 3 - no parameters marked as NOT_IN_SAMPLE in
postgresql.conf.sample
found GUC jit_cached in guc_tables.c, missing from
postgresql.conf.sample

I tested in with make check and make installcheck . In v8 I found
bugs,
but not published fix yet.

Do you have any intent to work on a new version for this?

I am preparing the new version. I got comments with bugs and memory
leaks,
I am fixing and testing the code.

I run TPC-H benchmark and found the degradation of performance with
jit_cached (and with regular jit also in some queries). As I see,
parallel execution of the query creates a parallel worker, that starts,
gets the plan, compile all expressions again. Even if query has cached
jit code, all parallel workers compile code again.
By the way, it is possible to send to the worker compiled jit code
together with plan (shared memory is used), but again arise the problem,
how to find the link between expression addresses in parallel worker
address space and jit code in shared memory.

--
Best regards,

Vladlen Popolitov.