mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	jit: Reference function pointer types via llvmjit_types.c.
It is error prone (see 5da871bfa1) and verbose to manually create function
types. Add a helper that can reference a function pointer type via
llvmjit_types.c and and convert existing instances of manual creation.
Author: Andres Freund <andres@anarazel.de>
Reviewed-By: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/20201207212142.wz5tnbk2jsaqzogb@alap3.anarazel.de
			
			
This commit is contained in:
		@@ -367,6 +367,47 @@ llvm_get_function(LLVMJitContext *context, const char *funcname)
 | 
				
			|||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Return type of a variable in llvmjit_types.c. This is useful to keep types
 | 
				
			||||||
 | 
					 * in sync between plain C and JIT related code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					LLVMTypeRef
 | 
				
			||||||
 | 
					llvm_pg_var_type(const char *varname)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						LLVMValueRef v_srcvar;
 | 
				
			||||||
 | 
						LLVMTypeRef typ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* this'll return a *pointer* to the global */
 | 
				
			||||||
 | 
						v_srcvar = LLVMGetNamedGlobal(llvm_types_module, varname);
 | 
				
			||||||
 | 
						if (!v_srcvar)
 | 
				
			||||||
 | 
							elog(ERROR, "variable %s not in llvmjit_types.c", varname);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* look at the contained type */
 | 
				
			||||||
 | 
						typ = LLVMTypeOf(v_srcvar);
 | 
				
			||||||
 | 
						Assert(typ != NULL && LLVMGetTypeKind(typ) == LLVMPointerTypeKind);
 | 
				
			||||||
 | 
						typ = LLVMGetElementType(typ);
 | 
				
			||||||
 | 
						Assert(typ != NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return typ;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Return function type of a variable in llvmjit_types.c. This is useful to
 | 
				
			||||||
 | 
					 * keep function types in sync between C and JITed code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					LLVMTypeRef
 | 
				
			||||||
 | 
					llvm_pg_var_func_type(const char *varname)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						LLVMTypeRef typ = llvm_pg_var_type(varname);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* look at the contained type */
 | 
				
			||||||
 | 
						Assert(LLVMGetTypeKind(typ) == LLVMPointerTypeKind);
 | 
				
			||||||
 | 
						typ = LLVMGetElementType(typ);
 | 
				
			||||||
 | 
						Assert(typ != NULL && LLVMGetTypeKind(typ) == LLVMFunctionTypeKind);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return typ;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Return declaration for a function referenced in llvmjit_types.c, adding it
 | 
					 * Return declaration for a function referenced in llvmjit_types.c, adding it
 | 
				
			||||||
 * to the module if necessary.
 | 
					 * to the module if necessary.
 | 
				
			||||||
@@ -889,26 +930,6 @@ llvm_shutdown(int code, Datum arg)
 | 
				
			|||||||
#endif							/* LLVM_VERSION_MAJOR > 11 */
 | 
					#endif							/* LLVM_VERSION_MAJOR > 11 */
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* helper for llvm_create_types, returning a global var's type */
 | 
					 | 
				
			||||||
static LLVMTypeRef
 | 
					 | 
				
			||||||
load_type(LLVMModuleRef mod, const char *name)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	LLVMValueRef value;
 | 
					 | 
				
			||||||
	LLVMTypeRef typ;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* this'll return a *pointer* to the global */
 | 
					 | 
				
			||||||
	value = LLVMGetNamedGlobal(mod, name);
 | 
					 | 
				
			||||||
	if (!value)
 | 
					 | 
				
			||||||
		elog(ERROR, "type %s is unknown", name);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* therefore look at the contained type and return that */
 | 
					 | 
				
			||||||
	typ = LLVMTypeOf(value);
 | 
					 | 
				
			||||||
	Assert(typ != NULL);
 | 
					 | 
				
			||||||
	typ = LLVMGetElementType(typ);
 | 
					 | 
				
			||||||
	Assert(typ != NULL);
 | 
					 | 
				
			||||||
	return typ;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* helper for llvm_create_types, returning a function's return type */
 | 
					/* helper for llvm_create_types, returning a function's return type */
 | 
				
			||||||
static LLVMTypeRef
 | 
					static LLVMTypeRef
 | 
				
			||||||
load_return_type(LLVMModuleRef mod, const char *name)
 | 
					load_return_type(LLVMModuleRef mod, const char *name)
 | 
				
			||||||
@@ -970,24 +991,24 @@ llvm_create_types(void)
 | 
				
			|||||||
	llvm_triple = pstrdup(LLVMGetTarget(llvm_types_module));
 | 
						llvm_triple = pstrdup(LLVMGetTarget(llvm_types_module));
 | 
				
			||||||
	llvm_layout = pstrdup(LLVMGetDataLayoutStr(llvm_types_module));
 | 
						llvm_layout = pstrdup(LLVMGetDataLayoutStr(llvm_types_module));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	TypeSizeT = load_type(llvm_types_module, "TypeSizeT");
 | 
						TypeSizeT = llvm_pg_var_type("TypeSizeT");
 | 
				
			||||||
	TypeParamBool = load_return_type(llvm_types_module, "FunctionReturningBool");
 | 
						TypeParamBool = load_return_type(llvm_types_module, "FunctionReturningBool");
 | 
				
			||||||
	TypeStorageBool = load_type(llvm_types_module, "TypeStorageBool");
 | 
						TypeStorageBool = llvm_pg_var_type("TypeStorageBool");
 | 
				
			||||||
	TypePGFunction = load_type(llvm_types_module, "TypePGFunction");
 | 
						TypePGFunction = llvm_pg_var_type("TypePGFunction");
 | 
				
			||||||
	StructNullableDatum = load_type(llvm_types_module, "StructNullableDatum");
 | 
						StructNullableDatum = llvm_pg_var_type("StructNullableDatum");
 | 
				
			||||||
	StructExprContext = load_type(llvm_types_module, "StructExprContext");
 | 
						StructExprContext = llvm_pg_var_type("StructExprContext");
 | 
				
			||||||
	StructExprEvalStep = load_type(llvm_types_module, "StructExprEvalStep");
 | 
						StructExprEvalStep = llvm_pg_var_type("StructExprEvalStep");
 | 
				
			||||||
	StructExprState = load_type(llvm_types_module, "StructExprState");
 | 
						StructExprState = llvm_pg_var_type("StructExprState");
 | 
				
			||||||
	StructFunctionCallInfoData = load_type(llvm_types_module, "StructFunctionCallInfoData");
 | 
						StructFunctionCallInfoData = llvm_pg_var_type("StructFunctionCallInfoData");
 | 
				
			||||||
	StructMemoryContextData = load_type(llvm_types_module, "StructMemoryContextData");
 | 
						StructMemoryContextData = llvm_pg_var_type("StructMemoryContextData");
 | 
				
			||||||
	StructTupleTableSlot = load_type(llvm_types_module, "StructTupleTableSlot");
 | 
						StructTupleTableSlot = llvm_pg_var_type("StructTupleTableSlot");
 | 
				
			||||||
	StructHeapTupleTableSlot = load_type(llvm_types_module, "StructHeapTupleTableSlot");
 | 
						StructHeapTupleTableSlot = llvm_pg_var_type("StructHeapTupleTableSlot");
 | 
				
			||||||
	StructMinimalTupleTableSlot = load_type(llvm_types_module, "StructMinimalTupleTableSlot");
 | 
						StructMinimalTupleTableSlot = llvm_pg_var_type("StructMinimalTupleTableSlot");
 | 
				
			||||||
	StructHeapTupleData = load_type(llvm_types_module, "StructHeapTupleData");
 | 
						StructHeapTupleData = llvm_pg_var_type("StructHeapTupleData");
 | 
				
			||||||
	StructTupleDescData = load_type(llvm_types_module, "StructTupleDescData");
 | 
						StructTupleDescData = llvm_pg_var_type("StructTupleDescData");
 | 
				
			||||||
	StructAggState = load_type(llvm_types_module, "StructAggState");
 | 
						StructAggState = llvm_pg_var_type("StructAggState");
 | 
				
			||||||
	StructAggStatePerGroupData = load_type(llvm_types_module, "StructAggStatePerGroupData");
 | 
						StructAggStatePerGroupData = llvm_pg_var_type("StructAggStatePerGroupData");
 | 
				
			||||||
	StructAggStatePerTransData = load_type(llvm_types_module, "StructAggStatePerTransData");
 | 
						StructAggStatePerTransData = llvm_pg_var_type("StructAggStatePerTransData");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	AttributeTemplate = LLVMGetNamedFunction(llvm_types_module, "AttributeTemplate");
 | 
						AttributeTemplate = LLVMGetNamedFunction(llvm_types_module, "AttributeTemplate");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -84,7 +84,6 @@ llvm_compile_expr(ExprState *state)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	LLVMBuilderRef b;
 | 
						LLVMBuilderRef b;
 | 
				
			||||||
	LLVMModuleRef mod;
 | 
						LLVMModuleRef mod;
 | 
				
			||||||
	LLVMTypeRef eval_sig;
 | 
					 | 
				
			||||||
	LLVMValueRef eval_fn;
 | 
						LLVMValueRef eval_fn;
 | 
				
			||||||
	LLVMBasicBlockRef entry;
 | 
						LLVMBasicBlockRef entry;
 | 
				
			||||||
	LLVMBasicBlockRef *opblocks;
 | 
						LLVMBasicBlockRef *opblocks;
 | 
				
			||||||
@@ -149,19 +148,9 @@ llvm_compile_expr(ExprState *state)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	funcname = llvm_expand_funcname(context, "evalexpr");
 | 
						funcname = llvm_expand_funcname(context, "evalexpr");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Create the signature and function */
 | 
						/* create function */
 | 
				
			||||||
	{
 | 
						eval_fn = LLVMAddFunction(mod, funcname,
 | 
				
			||||||
		LLVMTypeRef param_types[3];
 | 
												  llvm_pg_var_func_type("TypeExprStateEvalFunc"));
 | 
				
			||||||
 | 
					 | 
				
			||||||
		param_types[0] = l_ptr(StructExprState);	/* state */
 | 
					 | 
				
			||||||
		param_types[1] = l_ptr(StructExprContext);	/* econtext */
 | 
					 | 
				
			||||||
		param_types[2] = l_ptr(TypeStorageBool);	/* isnull */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		eval_sig = LLVMFunctionType(TypeSizeT,
 | 
					 | 
				
			||||||
									param_types, lengthof(param_types),
 | 
					 | 
				
			||||||
									false);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	eval_fn = LLVMAddFunction(mod, funcname, eval_sig);
 | 
					 | 
				
			||||||
	LLVMSetLinkage(eval_fn, LLVMExternalLinkage);
 | 
						LLVMSetLinkage(eval_fn, LLVMExternalLinkage);
 | 
				
			||||||
	LLVMSetVisibility(eval_fn, LLVMDefaultVisibility);
 | 
						LLVMSetVisibility(eval_fn, LLVMDefaultVisibility);
 | 
				
			||||||
	llvm_copy_attributes(AttributeTemplate, eval_fn);
 | 
						llvm_copy_attributes(AttributeTemplate, eval_fn);
 | 
				
			||||||
@@ -1086,24 +1075,16 @@ llvm_compile_expr(ExprState *state)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			case EEOP_PARAM_CALLBACK:
 | 
								case EEOP_PARAM_CALLBACK:
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					LLVMTypeRef param_types[3];
 | 
					 | 
				
			||||||
					LLVMValueRef v_params[3];
 | 
					 | 
				
			||||||
					LLVMTypeRef v_functype;
 | 
										LLVMTypeRef v_functype;
 | 
				
			||||||
					LLVMValueRef v_func;
 | 
										LLVMValueRef v_func;
 | 
				
			||||||
 | 
										LLVMValueRef v_params[3];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					param_types[0] = l_ptr(StructExprState);
 | 
										v_functype = llvm_pg_var_func_type("TypeExecEvalSubroutine");
 | 
				
			||||||
					param_types[1] = l_ptr(TypeSizeT);
 | 
					 | 
				
			||||||
					param_types[2] = l_ptr(StructExprContext);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					v_functype = LLVMFunctionType(LLVMVoidType(),
 | 
					 | 
				
			||||||
												  param_types,
 | 
					 | 
				
			||||||
												  lengthof(param_types),
 | 
					 | 
				
			||||||
												  false);
 | 
					 | 
				
			||||||
					v_func = l_ptr_const(op->d.cparam.paramfunc,
 | 
										v_func = l_ptr_const(op->d.cparam.paramfunc,
 | 
				
			||||||
										 l_ptr(v_functype));
 | 
															 LLVMPointerType(v_functype, 0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					v_params[0] = v_state;
 | 
										v_params[0] = v_state;
 | 
				
			||||||
					v_params[1] = l_ptr_const(op, l_ptr(TypeSizeT));
 | 
										v_params[1] = l_ptr_const(op, l_ptr(StructExprEvalStep));
 | 
				
			||||||
					v_params[2] = v_econtext;
 | 
										v_params[2] = v_econtext;
 | 
				
			||||||
					LLVMBuildCall(b,
 | 
										LLVMBuildCall(b,
 | 
				
			||||||
								  v_func,
 | 
													  v_func,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -48,6 +48,8 @@
 | 
				
			|||||||
PGFunction	TypePGFunction;
 | 
					PGFunction	TypePGFunction;
 | 
				
			||||||
size_t		TypeSizeT;
 | 
					size_t		TypeSizeT;
 | 
				
			||||||
bool		TypeStorageBool;
 | 
					bool		TypeStorageBool;
 | 
				
			||||||
 | 
					ExprStateEvalFunc TypeExprStateEvalFunc;
 | 
				
			||||||
 | 
					ExecEvalSubroutine TypeExecEvalSubroutine;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
NullableDatum StructNullableDatum;
 | 
					NullableDatum StructNullableDatum;
 | 
				
			||||||
AggState	StructAggState;
 | 
					AggState	StructAggState;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -92,6 +92,8 @@ extern LLVMModuleRef llvm_mutable_module(LLVMJitContext *context);
 | 
				
			|||||||
extern char *llvm_expand_funcname(LLVMJitContext *context, const char *basename);
 | 
					extern char *llvm_expand_funcname(LLVMJitContext *context, const char *basename);
 | 
				
			||||||
extern void *llvm_get_function(LLVMJitContext *context, const char *funcname);
 | 
					extern void *llvm_get_function(LLVMJitContext *context, const char *funcname);
 | 
				
			||||||
extern void llvm_split_symbol_name(const char *name, char **modname, 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 LLVMValueRef llvm_pg_func(LLVMModuleRef mod, const char *funcname);
 | 
				
			||||||
extern void llvm_copy_attributes(LLVMValueRef from, LLVMValueRef to);
 | 
					extern void llvm_copy_attributes(LLVMValueRef from, LLVMValueRef to);
 | 
				
			||||||
extern LLVMValueRef llvm_function_reference(LLVMJitContext *context,
 | 
					extern LLVMValueRef llvm_function_reference(LLVMJitContext *context,
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user