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:
Andres Freund 2020-12-07 13:16:55 -08:00
parent 62ee703313
commit df99ddc70b
4 changed files with 69 additions and 63 deletions

View File

@ -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");
} }

View File

@ -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,

View File

@ -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;

View File

@ -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,