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)

