jit: Reference function pointer types via llvmjit_types.c.
authorAndres Freund <[email protected]>
Mon, 7 Dec 2020 21:16:55 +0000 (13:16 -0800)
committerAndres Freund <[email protected]>
Wed, 9 Dec 2020 00:55:20 +0000 (16:55 -0800)
It is error prone (see 5da871bfa1b) 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 <[email protected]>
Reviewed-By: Tom Lane <[email protected]>
Discussion: https://postgr.es/m/20201207212142[email protected]

src/backend/jit/llvm/llvmjit.c
src/backend/jit/llvm/llvmjit_expr.c
src/backend/jit/llvm/llvmjit_types.c
src/include/jit/llvmjit.h

index 40a439326c6fb2ee3faefc87a29650ec82e48109..9c4fc75f6567a535a173b392b1fcd0c9cd5c5184 100644 (file)
@@ -367,6 +367,47 @@ llvm_get_function(LLVMJitContext *context, const char *funcname)
    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
  * to the module if necessary.
@@ -889,26 +930,6 @@ llvm_shutdown(int code, Datum arg)
 #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 */
 static LLVMTypeRef
 load_return_type(LLVMModuleRef mod, const char *name)
@@ -970,24 +991,24 @@ llvm_create_types(void)
    llvm_triple = pstrdup(LLVMGetTarget(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");
-   TypeStorageBool = load_type(llvm_types_module, "TypeStorageBool");
-   TypePGFunction = load_type(llvm_types_module, "TypePGFunction");
-   StructNullableDatum = load_type(llvm_types_module, "StructNullableDatum");
-   StructExprContext = load_type(llvm_types_module, "StructExprContext");
-   StructExprEvalStep = load_type(llvm_types_module, "StructExprEvalStep");
-   StructExprState = load_type(llvm_types_module, "StructExprState");
-   StructFunctionCallInfoData = load_type(llvm_types_module, "StructFunctionCallInfoData");
-   StructMemoryContextData = load_type(llvm_types_module, "StructMemoryContextData");
-   StructTupleTableSlot = load_type(llvm_types_module, "StructTupleTableSlot");
-   StructHeapTupleTableSlot = load_type(llvm_types_module, "StructHeapTupleTableSlot");
-   StructMinimalTupleTableSlot = load_type(llvm_types_module, "StructMinimalTupleTableSlot");
-   StructHeapTupleData = load_type(llvm_types_module, "StructHeapTupleData");
-   StructTupleDescData = load_type(llvm_types_module, "StructTupleDescData");
-   StructAggState = load_type(llvm_types_module, "StructAggState");
-   StructAggStatePerGroupData = load_type(llvm_types_module, "StructAggStatePerGroupData");
-   StructAggStatePerTransData = load_type(llvm_types_module, "StructAggStatePerTransData");
+   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");
+   StructTupleDescData = llvm_pg_var_type("StructTupleDescData");
+   StructAggState = llvm_pg_var_type("StructAggState");
+   StructAggStatePerGroupData = llvm_pg_var_type("StructAggStatePerGroupData");
+   StructAggStatePerTransData = llvm_pg_var_type("StructAggStatePerTransData");
 
    AttributeTemplate = LLVMGetNamedFunction(llvm_types_module, "AttributeTemplate");
 }
index da5e3a2c1d03c56c6894dbf77111e245bdf688fd..e0d53c0d0a21d0d464bf73e4bcf65cadb53e060a 100644 (file)
@@ -84,7 +84,6 @@ llvm_compile_expr(ExprState *state)
 
    LLVMBuilderRef b;
    LLVMModuleRef mod;
-   LLVMTypeRef eval_sig;
    LLVMValueRef eval_fn;
    LLVMBasicBlockRef entry;
    LLVMBasicBlockRef *opblocks;
@@ -149,19 +148,9 @@ llvm_compile_expr(ExprState *state)
 
    funcname = llvm_expand_funcname(context, "evalexpr");
 
-   /* Create the signature and function */
-   {
-       LLVMTypeRef param_types[3];
-
-       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);
+   /* create function */
+   eval_fn = LLVMAddFunction(mod, funcname,
+                             llvm_pg_var_func_type("TypeExprStateEvalFunc"));
    LLVMSetLinkage(eval_fn, LLVMExternalLinkage);
    LLVMSetVisibility(eval_fn, LLVMDefaultVisibility);
    llvm_copy_attributes(AttributeTemplate, eval_fn);
@@ -1086,24 +1075,16 @@ llvm_compile_expr(ExprState *state)
 
            case EEOP_PARAM_CALLBACK:
                {
-                   LLVMTypeRef param_types[3];
-                   LLVMValueRef v_params[3];
                    LLVMTypeRef v_functype;
                    LLVMValueRef v_func;
+                   LLVMValueRef v_params[3];
 
-                   param_types[0] = l_ptr(StructExprState);
-                   param_types[1] = l_ptr(TypeSizeT);
-                   param_types[2] = l_ptr(StructExprContext);
-
-                   v_functype = LLVMFunctionType(LLVMVoidType(),
-                                                 param_types,
-                                                 lengthof(param_types),
-                                                 false);
+                   v_functype = llvm_pg_var_func_type("TypeExecEvalSubroutine");
                    v_func = l_ptr_const(op->d.cparam.paramfunc,
-                                        l_ptr(v_functype));
+                                        LLVMPointerType(v_functype, 0));
 
                    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;
                    LLVMBuildCall(b,
                                  v_func,
index 1ed3cafa2f23bf81ca804e8c14815eb7d5cd7c4a..e1b23d3052407c410b25302736a2740f6a32fd8a 100644 (file)
@@ -48,6 +48,8 @@
 PGFunction TypePGFunction;
 size_t     TypeSizeT;
 bool       TypeStorageBool;
+ExprStateEvalFunc TypeExprStateEvalFunc;
+ExecEvalSubroutine TypeExecEvalSubroutine;
 
 NullableDatum StructNullableDatum;
 AggState   StructAggState;
index 325409acd5c57d28e1333407b1508464480a0bb7..1c89075eaffe4757cffcd312f4598ef55953b81f 100644 (file)
@@ -92,6 +92,8 @@ extern LLVMModuleRef llvm_mutable_module(LLVMJitContext *context);
 extern char *llvm_expand_funcname(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 void llvm_copy_attributes(LLVMValueRef from, LLVMValueRef to);
 extern LLVMValueRef llvm_function_reference(LLVMJitContext *context,