Skip to content

Commit 15ddc97

Browse files
committed
jit: Support opaque pointers in LLVM 16.
Remove use of LLVMGetElementType() and provide the type of all pointers to LLVMBuildXXX() functions when emitting IR, as required by modern LLVM versions[1]. * For LLVM <= 14, we'll still use the old LLVMBuildXXX() functions. * For LLVM == 15, we'll continue to do the same, explicitly opting out of opaque pointer mode. * For LLVM >= 16, we'll use the new LLVMBuildXXX2() functions that take the extra type argument. The difference is hidden behind some new IR emitting wrapper functions l_load(), l_gep(), l_call() etc. The change is mostly mechanical, except that at each site the correct type had to be provided. In some places we needed to do some extra work to get functions types, including some new wrappers for C++ APIs that are not yet exposed by in LLVM's C API, and some new "example" functions in llvmjit_types.c because it's no longer possible to start from the function pointer type and ask for the function type. Back-patch to 12, because it's a little tricker in 11 and we agreed not to put the latest LLVM support into the upcoming final release of 11. [1] https://llvm.org/docs/OpaquePointers.html Reviewed-by: Dmitry Dolgov <9erthalion6@gmail.com> Reviewed-by: Ronan Dunklau <ronan.dunklau@aiven.io> Reviewed-by: Andres Freund <andres@anarazel.de> Discussion: https://postgr.es/m/CA%2BhUKGKNX_%3Df%2B1C4r06WETKTq0G4Z_7q4L4Fxn5WWpMycDj9Fw%40mail.gmail.com
1 parent 0e32652 commit 15ddc97

File tree

7 files changed

+565
-383
lines changed

7 files changed

+565
-383
lines changed

src/backend/jit/llvm/llvmjit.c

Lines changed: 97 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -89,18 +89,12 @@ LLVMTypeRef StructExprState;
8989
LLVMTypeRef StructAggState;
9090
LLVMTypeRef StructAggStatePerGroupData;
9191
LLVMTypeRef StructAggStatePerTransData;
92+
LLVMTypeRef StructPlanState;
9293

9394
LLVMValueRef AttributeTemplate;
94-
LLVMValueRef FuncStrlen;
95-
LLVMValueRef FuncVarsizeAny;
96-
LLVMValueRef FuncSlotGetsomeattrsInt;
97-
LLVMValueRef FuncSlotGetmissingattrs;
98-
LLVMValueRef FuncMakeExpandedObjectReadOnlyInternal;
99-
LLVMValueRef FuncExecEvalSubscriptingRef;
100-
LLVMValueRef FuncExecEvalSysVar;
101-
LLVMValueRef FuncExecAggTransReparent;
102-
LLVMValueRef FuncExecAggInitGroup;
95+
LLVMValueRef ExecEvalSubroutineTemplate;
10396

97+
LLVMModuleRef llvm_types_module = NULL;
10498

10599
static bool llvm_session_initialized = false;
106100
static size_t llvm_generation = 0;
@@ -382,26 +376,71 @@ llvm_get_function(LLVMJitContext *context, const char *funcname)
382376
}
383377

384378
/*
385-
* Return declaration for passed function, adding it to the module if
386-
* necessary.
379+
* Return type of a variable in llvmjit_types.c. This is useful to keep types
380+
* in sync between plain C and JIT related code.
381+
*/
382+
LLVMTypeRef
383+
llvm_pg_var_type(const char *varname)
384+
{
385+
LLVMValueRef v_srcvar;
386+
LLVMTypeRef typ;
387+
388+
/* this'll return a *pointer* to the global */
389+
v_srcvar = LLVMGetNamedGlobal(llvm_types_module, varname);
390+
if (!v_srcvar)
391+
elog(ERROR, "variable %s not in llvmjit_types.c", varname);
392+
393+
typ = LLVMGlobalGetValueType(v_srcvar);
394+
395+
return typ;
396+
}
397+
398+
/*
399+
* Return function type of a variable in llvmjit_types.c. This is useful to
400+
* keep function types in sync between C and JITed code.
401+
*/
402+
LLVMTypeRef
403+
llvm_pg_var_func_type(const char *varname)
404+
{
405+
LLVMValueRef v_srcvar;
406+
LLVMTypeRef typ;
407+
408+
v_srcvar = LLVMGetNamedFunction(llvm_types_module, varname);
409+
if (!v_srcvar)
410+
elog(ERROR, "function %s not in llvmjit_types.c", varname);
411+
412+
typ = LLVMGetFunctionType(v_srcvar);
413+
414+
return typ;
415+
}
416+
417+
/*
418+
* Return declaration for a function referenced in llvmjit_types.c, adding it
419+
* to the module if necessary.
387420
*
388-
* This is used to make functions imported by llvm_create_types() known to the
389-
* module that's currently being worked on.
421+
* This is used to make functions discovered via llvm_create_types() known to
422+
* the module that's currently being worked on.
390423
*/
391424
LLVMValueRef
392-
llvm_get_decl(LLVMModuleRef mod, LLVMValueRef v_src)
425+
llvm_pg_func(LLVMModuleRef mod, const char *funcname)
393426
{
427+
LLVMValueRef v_srcfn;
394428
LLVMValueRef v_fn;
395429

396430
/* don't repeatedly add function */
397-
v_fn = LLVMGetNamedFunction(mod, LLVMGetValueName(v_src));
431+
v_fn = LLVMGetNamedFunction(mod, funcname);
398432
if (v_fn)
399433
return v_fn;
400434

435+
v_srcfn = LLVMGetNamedFunction(llvm_types_module, funcname);
436+
437+
if (!v_srcfn)
438+
elog(ERROR, "function %s not in llvmjit_types.c", funcname);
439+
401440
v_fn = LLVMAddFunction(mod,
402-
LLVMGetValueName(v_src),
403-
LLVMGetElementType(LLVMTypeOf(v_src)));
404-
llvm_copy_attributes(v_src, v_fn);
441+
funcname,
442+
LLVMGetFunctionType(v_srcfn));
443+
llvm_copy_attributes(v_srcfn, v_fn);
405444

406445
return v_fn;
407446
}
@@ -496,7 +535,7 @@ llvm_function_reference(LLVMJitContext *context,
496535
fcinfo->flinfo->fn_oid);
497536
v_fn = LLVMGetNamedGlobal(mod, funcname);
498537
if (v_fn != 0)
499-
return LLVMBuildLoad(builder, v_fn, "");
538+
return l_load(builder, TypePGFunction, v_fn, "");
500539

501540
v_fn_addr = l_ptr_const(fcinfo->flinfo->fn_addr, TypePGFunction);
502541

@@ -506,15 +545,15 @@ llvm_function_reference(LLVMJitContext *context,
506545
LLVMSetLinkage(v_fn, LLVMPrivateLinkage);
507546
LLVMSetUnnamedAddr(v_fn, true);
508547

509-
return LLVMBuildLoad(builder, v_fn, "");
548+
return l_load(builder, TypePGFunction, v_fn, "");
510549
}
511550

512551
/* check if function already has been added */
513552
v_fn = LLVMGetNamedFunction(mod, funcname);
514553
if (v_fn != 0)
515554
return v_fn;
516555

517-
v_fn = LLVMAddFunction(mod, funcname, LLVMGetElementType(TypePGFunction));
556+
v_fn = LLVMAddFunction(mod, funcname, LLVMGetFunctionType(AttributeTemplate));
518557

519558
return v_fn;
520559
}
@@ -766,12 +805,15 @@ llvm_session_initialize(void)
766805
LLVMInitializeNativeAsmParser();
767806

768807
/*
769-
* When targeting an LLVM version with opaque pointers enabled by
770-
* default, turn them off for the context we build our code in. We don't
771-
* need to do so for other contexts (e.g. llvm_ts_context). Once the IR is
772-
* generated, it carries the necessary information.
808+
* When targeting LLVM 15, turn off opaque pointers for the context we
809+
* build our code in. We don't need to do so for other contexts (e.g.
810+
* llvm_ts_context). Once the IR is generated, it carries the necessary
811+
* information.
812+
*
813+
* For 16 and above, opaque pointers must be used, and we have special
814+
* code for that.
773815
*/
774-
#if LLVM_VERSION_MAJOR > 14
816+
#if LLVM_VERSION_MAJOR == 15
775817
LLVMContextSetOpaquePointers(LLVMGetGlobalContext(), false);
776818
#endif
777819

@@ -921,26 +963,6 @@ llvm_shutdown(int code, Datum arg)
921963
#endif /* LLVM_VERSION_MAJOR > 11 */
922964
}
923965

924-
/* helper for llvm_create_types, returning a global var's type */
925-
static LLVMTypeRef
926-
load_type(LLVMModuleRef mod, const char *name)
927-
{
928-
LLVMValueRef value;
929-
LLVMTypeRef typ;
930-
931-
/* this'll return a *pointer* to the global */
932-
value = LLVMGetNamedGlobal(mod, name);
933-
if (!value)
934-
elog(ERROR, "type %s is unknown", name);
935-
936-
/* therefore look at the contained type and return that */
937-
typ = LLVMTypeOf(value);
938-
Assert(typ != NULL);
939-
typ = LLVMGetElementType(typ);
940-
Assert(typ != NULL);
941-
return typ;
942-
}
943-
944966
/* helper for llvm_create_types, returning a function's return type */
945967
static LLVMTypeRef
946968
load_return_type(LLVMModuleRef mod, const char *name)
@@ -953,15 +975,7 @@ load_return_type(LLVMModuleRef mod, const char *name)
953975
if (!value)
954976
elog(ERROR, "function %s is unknown", name);
955977

956-
/* get type of function pointer */
957-
typ = LLVMTypeOf(value);
958-
Assert(typ != NULL);
959-
/* dereference pointer */
960-
typ = LLVMGetElementType(typ);
961-
Assert(typ != NULL);
962-
/* and look at return type */
963-
typ = LLVMGetReturnType(typ);
964-
Assert(typ != NULL);
978+
typ = LLVMGetFunctionReturnType(value); /* in llvmjit_wrap.cpp */
965979

966980
return typ;
967981
}
@@ -978,7 +992,6 @@ llvm_create_types(void)
978992
char path[MAXPGPATH];
979993
LLVMMemoryBufferRef buf;
980994
char *msg;
981-
LLVMModuleRef mod = NULL;
982995

983996
snprintf(path, MAXPGPATH, "%s/%s", pkglib_path, "llvmjit_types.bc");
984997

@@ -990,7 +1003,7 @@ llvm_create_types(void)
9901003
}
9911004

9921005
/* eagerly load contents, going to need it all */
993-
if (LLVMParseBitcode2(buf, &mod))
1006+
if (LLVMParseBitcode2(buf, &llvm_types_module))
9941007
{
9951008
elog(ERROR, "LLVMParseBitcode2 of %s failed", path);
9961009
}
@@ -1000,45 +1013,33 @@ llvm_create_types(void)
10001013
* Load triple & layout from clang emitted file so we're guaranteed to be
10011014
* compatible.
10021015
*/
1003-
llvm_triple = pstrdup(LLVMGetTarget(mod));
1004-
llvm_layout = pstrdup(LLVMGetDataLayoutStr(mod));
1005-
1006-
TypeSizeT = load_type(mod, "TypeSizeT");
1007-
TypeParamBool = load_return_type(mod, "FunctionReturningBool");
1008-
TypeStorageBool = load_type(mod, "TypeStorageBool");
1009-
TypePGFunction = load_type(mod, "TypePGFunction");
1010-
StructNullableDatum = load_type(mod, "StructNullableDatum");
1011-
StructExprContext = load_type(mod, "StructExprContext");
1012-
StructExprEvalStep = load_type(mod, "StructExprEvalStep");
1013-
StructExprState = load_type(mod, "StructExprState");
1014-
StructFunctionCallInfoData = load_type(mod, "StructFunctionCallInfoData");
1015-
StructMemoryContextData = load_type(mod, "StructMemoryContextData");
1016-
StructTupleTableSlot = load_type(mod, "StructTupleTableSlot");
1017-
StructHeapTupleTableSlot = load_type(mod, "StructHeapTupleTableSlot");
1018-
StructMinimalTupleTableSlot = load_type(mod, "StructMinimalTupleTableSlot");
1019-
StructHeapTupleData = load_type(mod, "StructHeapTupleData");
1020-
StructTupleDescData = load_type(mod, "StructTupleDescData");
1021-
StructAggState = load_type(mod, "StructAggState");
1022-
StructAggStatePerGroupData = load_type(mod, "StructAggStatePerGroupData");
1023-
StructAggStatePerTransData = load_type(mod, "StructAggStatePerTransData");
1024-
1025-
AttributeTemplate = LLVMGetNamedFunction(mod, "AttributeTemplate");
1026-
FuncStrlen = LLVMGetNamedFunction(mod, "strlen");
1027-
FuncVarsizeAny = LLVMGetNamedFunction(mod, "varsize_any");
1028-
FuncSlotGetsomeattrsInt = LLVMGetNamedFunction(mod, "slot_getsomeattrs_int");
1029-
FuncSlotGetmissingattrs = LLVMGetNamedFunction(mod, "slot_getmissingattrs");
1030-
FuncMakeExpandedObjectReadOnlyInternal = LLVMGetNamedFunction(mod, "MakeExpandedObjectReadOnlyInternal");
1031-
FuncExecEvalSubscriptingRef = LLVMGetNamedFunction(mod, "ExecEvalSubscriptingRef");
1032-
FuncExecEvalSysVar = LLVMGetNamedFunction(mod, "ExecEvalSysVar");
1033-
FuncExecAggTransReparent = LLVMGetNamedFunction(mod, "ExecAggTransReparent");
1034-
FuncExecAggInitGroup = LLVMGetNamedFunction(mod, "ExecAggInitGroup");
1035-
1036-
/*
1037-
* Leave the module alive, otherwise references to function would be
1038-
* dangling.
1039-
*/
1040-
1041-
return;
1016+
llvm_triple = pstrdup(LLVMGetTarget(llvm_types_module));
1017+
llvm_layout = pstrdup(LLVMGetDataLayoutStr(llvm_types_module));
1018+
1019+
TypeSizeT = llvm_pg_var_type("TypeSizeT");
1020+
TypeParamBool = load_return_type(llvm_types_module, "FunctionReturningBool");
1021+
TypeStorageBool = llvm_pg_var_type("TypeStorageBool");
1022+
TypePGFunction = llvm_pg_var_type("TypePGFunction");
1023+
StructNullableDatum = llvm_pg_var_type("StructNullableDatum");
1024+
StructExprContext = llvm_pg_var_type("StructExprContext");
1025+
StructExprEvalStep = llvm_pg_var_type("StructExprEvalStep");
1026+
StructExprState = llvm_pg_var_type("StructExprState");
1027+
StructFunctionCallInfoData = llvm_pg_var_type("StructFunctionCallInfoData");
1028+
StructMemoryContextData = llvm_pg_var_type("StructMemoryContextData");
1029+
StructTupleTableSlot = llvm_pg_var_type("StructTupleTableSlot");
1030+
StructHeapTupleTableSlot = llvm_pg_var_type("StructHeapTupleTableSlot");
1031+
StructMinimalTupleTableSlot = llvm_pg_var_type("StructMinimalTupleTableSlot");
1032+
StructHeapTupleData = llvm_pg_var_type("StructHeapTupleData");
1033+
StructHeapTupleHeaderData = llvm_pg_var_type("StructHeapTupleHeaderData");
1034+
StructTupleDescData = llvm_pg_var_type("StructTupleDescData");
1035+
StructAggState = llvm_pg_var_type("StructAggState");
1036+
StructAggStatePerGroupData = llvm_pg_var_type("StructAggStatePerGroupData");
1037+
StructAggStatePerTransData = llvm_pg_var_type("StructAggStatePerTransData");
1038+
StructPlanState = llvm_pg_var_type("StructPlanState");
1039+
StructMinimalTupleData = llvm_pg_var_type("StructMinimalTupleData");
1040+
1041+
AttributeTemplate = LLVMGetNamedFunction(llvm_types_module, "AttributeTemplate");
1042+
ExecEvalSubroutineTemplate = LLVMGetNamedFunction(llvm_types_module, "ExecEvalSubroutineTemplate");
10421043
}
10431044

10441045
/*

0 commit comments

Comments
 (0)