Adapt expression JIT to stdbool.h introduction.

The LLVM JIT provider uses clang to synchronize types between normal C
code and runtime generated code. Clang represents stdbool.h style
booleans in return values & parameters differently from booleans
stored in variables.

Thus the expression compilation code from 2a0faed9d needs to be
adapted to 9a95a77d9. Instead of hardcoding i8 as the type for
booleans (which already was wrong on some edge case platforms!), use
postgres' notion of a boolean as used for storage and for parameters.

Per buildfarm animal xenodermus.

Author: Andres Freund
This commit is contained in:
Andres Freund 2018-03-22 22:15:51 -07:00
parent fdb78948d8
commit 2111a48a0c
5 changed files with 132 additions and 64 deletions

View File

@ -46,6 +46,8 @@ typedef struct LLVMJitHandle
/* types & functions commonly needed for JITing */ /* types & functions commonly needed for JITing */
LLVMTypeRef TypeSizeT; LLVMTypeRef TypeSizeT;
LLVMTypeRef TypeParamBool;
LLVMTypeRef TypeStorageBool;
LLVMTypeRef TypePGFunction; LLVMTypeRef TypePGFunction;
LLVMTypeRef StructHeapTupleFieldsField3; LLVMTypeRef StructHeapTupleFieldsField3;
LLVMTypeRef StructHeapTupleFields; LLVMTypeRef StructHeapTupleFields;
@ -682,7 +684,7 @@ llvm_shutdown(int code, Datum arg)
} }
} }
/* helper for llvm_create_types */ /* helper for llvm_create_types, returning a global var's type */
static LLVMTypeRef static LLVMTypeRef
load_type(LLVMModuleRef mod, const char *name) load_type(LLVMModuleRef mod, const char *name)
{ {
@ -702,6 +704,31 @@ load_type(LLVMModuleRef mod, const char *name)
return typ; return typ;
} }
/* helper for llvm_create_types, returning a function's return type */
static LLVMTypeRef
load_return_type(LLVMModuleRef mod, const char *name)
{
LLVMValueRef value;
LLVMTypeRef typ;
/* this'll return a *pointer* to the function */
value = LLVMGetNamedFunction(mod, name);
if (!value)
elog(ERROR, "function %s is unknown", name);
/* get type of function pointer */
typ = LLVMTypeOf(value);
Assert(typ != NULL);
/* dereference pointer */
typ = LLVMGetElementType(typ);
Assert(typ != NULL);
/* and look at return type */
typ = LLVMGetReturnType(typ);
Assert(typ != NULL);
return typ;
}
/* /*
* Load required information, types, function signatures from llvmjit_types.c * Load required information, types, function signatures from llvmjit_types.c
* and make them available in global variables. * and make them available in global variables.
@ -740,6 +767,8 @@ llvm_create_types(void)
llvm_layout = pstrdup(LLVMGetDataLayoutStr(mod)); llvm_layout = pstrdup(LLVMGetDataLayoutStr(mod));
TypeSizeT = load_type(mod, "TypeSizeT"); TypeSizeT = load_type(mod, "TypeSizeT");
TypeParamBool = load_return_type(mod, "FunctionReturningBool");
TypeStorageBool = load_type(mod, "TypeStorageBool");
TypePGFunction = load_type(mod, "TypePGFunction"); TypePGFunction = load_type(mod, "TypePGFunction");
StructExprContext = load_type(mod, "StructExprContext"); StructExprContext = load_type(mod, "StructExprContext");
StructExprEvalStep = load_type(mod, "StructExprEvalStep"); StructExprEvalStep = load_type(mod, "StructExprEvalStep");

View File

@ -152,7 +152,7 @@ llvm_compile_expr(ExprState *state)
param_types[0] = l_ptr(StructExprState); /* state */ param_types[0] = l_ptr(StructExprState); /* state */
param_types[1] = l_ptr(StructExprContext); /* econtext */ param_types[1] = l_ptr(StructExprContext); /* econtext */
param_types[2] = l_ptr(LLVMInt8Type()); /* isnull */ param_types[2] = l_ptr(TypeParamBool); /* isnull */
eval_sig = LLVMFunctionType(TypeSizeT, eval_sig = LLVMFunctionType(TypeSizeT,
param_types, lengthof(param_types), param_types, lengthof(param_types),
@ -248,7 +248,7 @@ llvm_compile_expr(ExprState *state)
opcode = ExecEvalStepOp(state, op); opcode = ExecEvalStepOp(state, op);
v_resvaluep = l_ptr_const(op->resvalue, l_ptr(TypeSizeT)); v_resvaluep = l_ptr_const(op->resvalue, l_ptr(TypeSizeT));
v_resnullp = l_ptr_const(op->resnull, l_ptr(LLVMInt8Type())); v_resnullp = l_ptr_const(op->resnull, l_ptr(TypeStorageBool));
switch (opcode) switch (opcode)
{ {
@ -259,6 +259,8 @@ llvm_compile_expr(ExprState *state)
v_tmpvalue = LLVMBuildLoad(b, v_tmpvaluep, ""); v_tmpvalue = LLVMBuildLoad(b, v_tmpvaluep, "");
v_tmpisnull = LLVMBuildLoad(b, v_tmpisnullp, ""); v_tmpisnull = LLVMBuildLoad(b, v_tmpisnullp, "");
v_tmpisnull =
LLVMBuildTrunc(b, v_tmpisnull, TypeParamBool, "");
LLVMBuildStore(b, v_tmpisnull, v_isnullp); LLVMBuildStore(b, v_tmpisnull, v_isnullp);
@ -521,7 +523,7 @@ llvm_compile_expr(ExprState *state)
/* check if value is NULL */ /* check if value is NULL */
LLVMBuildCondBr(b, LLVMBuildCondBr(b,
LLVMBuildICmp(b, LLVMIntEQ, v_isnull, LLVMBuildICmp(b, LLVMIntEQ, v_isnull,
l_int8_const(0), ""), l_sbool_const(0), ""),
b_notnull, opblocks[i + 1]); b_notnull, opblocks[i + 1]);
/* if value is not null, convert to RO datum */ /* if value is not null, convert to RO datum */
@ -545,7 +547,7 @@ llvm_compile_expr(ExprState *state)
v_constnull; v_constnull;
v_constvalue = l_sizet_const(op->d.constval.value); v_constvalue = l_sizet_const(op->d.constval.value);
v_constnull = l_int8_const(op->d.constval.isnull); v_constnull = l_sbool_const(op->d.constval.isnull);
LLVMBuildStore(b, v_constvalue, v_resvaluep); LLVMBuildStore(b, v_constvalue, v_resvaluep);
LLVMBuildStore(b, v_constnull, v_resnullp); LLVMBuildStore(b, v_constnull, v_resnullp);
@ -587,7 +589,7 @@ llvm_compile_expr(ExprState *state)
* set resnull to true, if the function is actually * set resnull to true, if the function is actually
* called, it'll be reset * called, it'll be reset
*/ */
LLVMBuildStore(b, l_int8_const(1), v_resnullp); LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
/* create blocks for checking args, one for each */ /* create blocks for checking args, one for each */
b_checkargnulls = b_checkargnulls =
@ -619,7 +621,7 @@ llvm_compile_expr(ExprState *state)
LLVMBuildCondBr(b, LLVMBuildCondBr(b,
LLVMBuildICmp(b, LLVMIntEQ, LLVMBuildICmp(b, LLVMIntEQ,
v_argisnull, v_argisnull,
l_int8_const(1), l_sbool_const(1),
""), ""),
opblocks[i + 1], opblocks[i + 1],
b_argnotnull); b_argnotnull);
@ -661,8 +663,8 @@ llvm_compile_expr(ExprState *state)
LLVMValueRef v_boolanynullp; LLVMValueRef v_boolanynullp;
v_boolanynullp = l_ptr_const(op->d.boolexpr.anynull, v_boolanynullp = l_ptr_const(op->d.boolexpr.anynull,
l_ptr(LLVMInt8Type())); l_ptr(TypeStorageBool));
LLVMBuildStore(b, l_int8_const(0), v_boolanynullp); LLVMBuildStore(b, l_sbool_const(0), v_boolanynullp);
/* intentionally fall through */ /* intentionally fall through */
} }
@ -697,7 +699,7 @@ llvm_compile_expr(ExprState *state)
"b.%d.boolcont", i); "b.%d.boolcont", i);
v_boolanynullp = l_ptr_const(op->d.boolexpr.anynull, v_boolanynullp = l_ptr_const(op->d.boolexpr.anynull,
l_ptr(LLVMInt8Type())); l_ptr(TypeStorageBool));
v_boolnull = LLVMBuildLoad(b, v_resnullp, ""); v_boolnull = LLVMBuildLoad(b, v_resnullp, "");
v_boolvalue = LLVMBuildLoad(b, v_resvaluep, ""); v_boolvalue = LLVMBuildLoad(b, v_resvaluep, "");
@ -710,14 +712,14 @@ llvm_compile_expr(ExprState *state)
/* check if current input is NULL */ /* check if current input is NULL */
LLVMBuildCondBr(b, LLVMBuildCondBr(b,
LLVMBuildICmp(b, LLVMIntEQ, v_boolnull, LLVMBuildICmp(b, LLVMIntEQ, v_boolnull,
l_int8_const(1), ""), l_sbool_const(1), ""),
b_boolisnull, b_boolisnull,
b_boolcheckfalse); b_boolcheckfalse);
/* build block that sets anynull */ /* build block that sets anynull */
LLVMPositionBuilderAtEnd(b, b_boolisnull); LLVMPositionBuilderAtEnd(b, b_boolisnull);
/* set boolanynull to true */ /* set boolanynull to true */
LLVMBuildStore(b, l_int8_const(1), v_boolanynullp); LLVMBuildStore(b, l_sbool_const(1), v_boolanynullp);
/* and jump to next block */ /* and jump to next block */
LLVMBuildBr(b, b_boolcont); LLVMBuildBr(b, b_boolcont);
@ -746,12 +748,12 @@ llvm_compile_expr(ExprState *state)
/* set value to NULL if any previous values were NULL */ /* set value to NULL if any previous values were NULL */
LLVMBuildCondBr(b, LLVMBuildCondBr(b,
LLVMBuildICmp(b, LLVMIntEQ, v_boolanynull, LLVMBuildICmp(b, LLVMIntEQ, v_boolanynull,
l_int8_const(0), ""), l_sbool_const(0), ""),
opblocks[i + 1], b_boolisanynull); opblocks[i + 1], b_boolisanynull);
LLVMPositionBuilderAtEnd(b, b_boolisanynull); LLVMPositionBuilderAtEnd(b, b_boolisanynull);
/* set resnull to true */ /* set resnull to true */
LLVMBuildStore(b, l_int8_const(1), v_resnullp); LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
/* reset resvalue */ /* reset resvalue */
LLVMBuildStore(b, l_sizet_const(0), v_resvaluep); LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
@ -763,8 +765,8 @@ llvm_compile_expr(ExprState *state)
LLVMValueRef v_boolanynullp; LLVMValueRef v_boolanynullp;
v_boolanynullp = l_ptr_const(op->d.boolexpr.anynull, v_boolanynullp = l_ptr_const(op->d.boolexpr.anynull,
l_ptr(LLVMInt8Type())); l_ptr(TypeStorageBool));
LLVMBuildStore(b, l_int8_const(0), v_boolanynullp); LLVMBuildStore(b, l_sbool_const(0), v_boolanynullp);
/* intentionally fall through */ /* intentionally fall through */
} }
@ -800,7 +802,7 @@ llvm_compile_expr(ExprState *state)
"b.%d.boolcont", i); "b.%d.boolcont", i);
v_boolanynullp = l_ptr_const(op->d.boolexpr.anynull, v_boolanynullp = l_ptr_const(op->d.boolexpr.anynull,
l_ptr(LLVMInt8Type())); l_ptr(TypeStorageBool));
v_boolnull = LLVMBuildLoad(b, v_resnullp, ""); v_boolnull = LLVMBuildLoad(b, v_resnullp, "");
v_boolvalue = LLVMBuildLoad(b, v_resvaluep, ""); v_boolvalue = LLVMBuildLoad(b, v_resvaluep, "");
@ -812,14 +814,14 @@ llvm_compile_expr(ExprState *state)
LLVMBuildCondBr(b, LLVMBuildCondBr(b,
LLVMBuildICmp(b, LLVMIntEQ, v_boolnull, LLVMBuildICmp(b, LLVMIntEQ, v_boolnull,
l_int8_const(1), ""), l_sbool_const(1), ""),
b_boolisnull, b_boolisnull,
b_boolchecktrue); b_boolchecktrue);
/* build block that sets anynull */ /* build block that sets anynull */
LLVMPositionBuilderAtEnd(b, b_boolisnull); LLVMPositionBuilderAtEnd(b, b_boolisnull);
/* set boolanynull to true */ /* set boolanynull to true */
LLVMBuildStore(b, l_int8_const(1), v_boolanynullp); LLVMBuildStore(b, l_sbool_const(1), v_boolanynullp);
/* and jump to next block */ /* and jump to next block */
LLVMBuildBr(b, b_boolcont); LLVMBuildBr(b, b_boolcont);
@ -848,12 +850,12 @@ llvm_compile_expr(ExprState *state)
/* set value to NULL if any previous values were NULL */ /* set value to NULL if any previous values were NULL */
LLVMBuildCondBr(b, LLVMBuildCondBr(b,
LLVMBuildICmp(b, LLVMIntEQ, v_boolanynull, LLVMBuildICmp(b, LLVMIntEQ, v_boolanynull,
l_int8_const(0), ""), l_sbool_const(0), ""),
opblocks[i + 1], b_boolisanynull); opblocks[i + 1], b_boolisanynull);
LLVMPositionBuilderAtEnd(b, b_boolisanynull); LLVMPositionBuilderAtEnd(b, b_boolisanynull);
/* set resnull to true */ /* set resnull to true */
LLVMBuildStore(b, l_int8_const(1), v_resnullp); LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
/* reset resvalue */ /* reset resvalue */
LLVMBuildStore(b, l_sizet_const(0), v_resvaluep); LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
@ -901,7 +903,7 @@ llvm_compile_expr(ExprState *state)
v_nullorfalse = v_nullorfalse =
LLVMBuildOr(b, LLVMBuildOr(b,
LLVMBuildICmp(b, LLVMIntEQ, v_resnull, LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
l_int8_const(1), ""), l_sbool_const(1), ""),
LLVMBuildICmp(b, LLVMIntEQ, v_resvalue, LLVMBuildICmp(b, LLVMIntEQ, v_resvalue,
l_sizet_const(0), ""), l_sizet_const(0), ""),
""); "");
@ -914,7 +916,7 @@ llvm_compile_expr(ExprState *state)
/* build block handling NULL or false */ /* build block handling NULL or false */
LLVMPositionBuilderAtEnd(b, b_qualfail); LLVMPositionBuilderAtEnd(b, b_qualfail);
/* set resnull to false */ /* set resnull to false */
LLVMBuildStore(b, l_int8_const(0), v_resnullp); LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
/* set resvalue to false */ /* set resvalue to false */
LLVMBuildStore(b, l_sizet_const(0), v_resvaluep); LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
/* and jump out */ /* and jump out */
@ -938,7 +940,7 @@ llvm_compile_expr(ExprState *state)
LLVMBuildCondBr(b, LLVMBuildCondBr(b,
LLVMBuildICmp(b, LLVMIntEQ, v_resnull, LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
l_int8_const(1), ""), l_sbool_const(1), ""),
opblocks[op->d.jump.jumpdone], opblocks[op->d.jump.jumpdone],
opblocks[i + 1]); opblocks[i + 1]);
break; break;
@ -954,7 +956,7 @@ llvm_compile_expr(ExprState *state)
LLVMBuildCondBr(b, LLVMBuildCondBr(b,
LLVMBuildICmp(b, LLVMIntEQ, v_resnull, LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
l_int8_const(0), ""), l_sbool_const(0), ""),
opblocks[op->d.jump.jumpdone], opblocks[op->d.jump.jumpdone],
opblocks[i + 1]); opblocks[i + 1]);
break; break;
@ -975,7 +977,7 @@ llvm_compile_expr(ExprState *state)
v_nullorfalse = v_nullorfalse =
LLVMBuildOr(b, LLVMBuildOr(b,
LLVMBuildICmp(b, LLVMIntEQ, v_resnull, LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
l_int8_const(1), ""), l_sbool_const(1), ""),
LLVMBuildICmp(b, LLVMIntEQ, v_resvalue, LLVMBuildICmp(b, LLVMIntEQ, v_resvalue,
l_sizet_const(0), ""), l_sizet_const(0), ""),
""); "");
@ -995,12 +997,12 @@ llvm_compile_expr(ExprState *state)
v_resvalue = v_resvalue =
LLVMBuildSelect(b, LLVMBuildSelect(b,
LLVMBuildICmp(b, LLVMIntEQ, v_resnull, LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
l_int8_const(1), ""), l_sbool_const(1), ""),
l_sizet_const(1), l_sizet_const(1),
l_sizet_const(0), l_sizet_const(0),
""); "");
LLVMBuildStore(b, v_resvalue, v_resvaluep); LLVMBuildStore(b, v_resvalue, v_resvaluep);
LLVMBuildStore(b, l_int8_const(0), v_resnullp); LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
LLVMBuildBr(b, opblocks[i + 1]); LLVMBuildBr(b, opblocks[i + 1]);
break; break;
@ -1014,12 +1016,12 @@ llvm_compile_expr(ExprState *state)
v_resvalue = v_resvalue =
LLVMBuildSelect(b, LLVMBuildSelect(b,
LLVMBuildICmp(b, LLVMIntEQ, v_resnull, LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
l_int8_const(1), ""), l_sbool_const(1), ""),
l_sizet_const(0), l_sizet_const(0),
l_sizet_const(1), l_sizet_const(1),
""); "");
LLVMBuildStore(b, v_resvalue, v_resvaluep); LLVMBuildStore(b, v_resvalue, v_resvaluep);
LLVMBuildStore(b, l_int8_const(0), v_resnullp); LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
LLVMBuildBr(b, opblocks[i + 1]); LLVMBuildBr(b, opblocks[i + 1]);
break; break;
@ -1054,14 +1056,14 @@ llvm_compile_expr(ExprState *state)
/* check if value is NULL */ /* check if value is NULL */
LLVMBuildCondBr(b, LLVMBuildCondBr(b,
LLVMBuildICmp(b, LLVMIntEQ, v_resnull, LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
l_int8_const(1), ""), l_sbool_const(1), ""),
b_isnull, b_notnull); b_isnull, b_notnull);
/* if value is NULL, return false */ /* if value is NULL, return false */
LLVMPositionBuilderAtEnd(b, b_isnull); LLVMPositionBuilderAtEnd(b, b_isnull);
/* result is not null */ /* result is not null */
LLVMBuildStore(b, l_int8_const(0), v_resnullp); LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
if (opcode == EEOP_BOOLTEST_IS_TRUE || if (opcode == EEOP_BOOLTEST_IS_TRUE ||
opcode == EEOP_BOOLTEST_IS_FALSE) opcode == EEOP_BOOLTEST_IS_FALSE)
@ -1179,7 +1181,7 @@ llvm_compile_expr(ExprState *state)
v_casevaluep = l_ptr_const(op->d.casetest.value, v_casevaluep = l_ptr_const(op->d.casetest.value,
l_ptr(TypeSizeT)); l_ptr(TypeSizeT));
v_casenullp = l_ptr_const(op->d.casetest.isnull, v_casenullp = l_ptr_const(op->d.casetest.isnull,
l_ptr(LLVMInt8Type())); l_ptr(TypeStorageBool));
v_casevaluenull = v_casevaluenull =
LLVMBuildICmp(b, LLVMIntEQ, LLVMBuildICmp(b, LLVMIntEQ,
@ -1225,7 +1227,7 @@ llvm_compile_expr(ExprState *state)
"op.%d.readonly.notnull", i); "op.%d.readonly.notnull", i);
v_nullp = l_ptr_const(op->d.make_readonly.isnull, v_nullp = l_ptr_const(op->d.make_readonly.isnull,
l_ptr(LLVMInt8Type())); l_ptr(TypeStorageBool));
v_null = LLVMBuildLoad(b, v_nullp, ""); v_null = LLVMBuildLoad(b, v_nullp, "");
@ -1235,7 +1237,7 @@ llvm_compile_expr(ExprState *state)
/* check if value is NULL */ /* check if value is NULL */
LLVMBuildCondBr(b, LLVMBuildCondBr(b,
LLVMBuildICmp(b, LLVMIntEQ, v_null, LLVMBuildICmp(b, LLVMIntEQ, v_null,
l_int8_const(1), ""), l_sbool_const(1), ""),
opblocks[i + 1], b_notnull); opblocks[i + 1], b_notnull);
/* if value is not null, convert to RO datum */ /* if value is not null, convert to RO datum */
@ -1324,7 +1326,7 @@ llvm_compile_expr(ExprState *state)
v_resnull = LLVMBuildLoad(b, v_resnullp, ""); v_resnull = LLVMBuildLoad(b, v_resnullp, "");
LLVMBuildCondBr(b, LLVMBuildCondBr(b,
LLVMBuildICmp(b, LLVMIntEQ, v_resnull, LLVMBuildICmp(b, LLVMIntEQ, v_resnull,
l_int8_const(1), ""), l_sbool_const(1), ""),
b_skipoutput, b_skipoutput,
b_calloutput); b_calloutput);
@ -1340,7 +1342,7 @@ llvm_compile_expr(ExprState *state)
v_resvalue, v_resvalue,
LLVMBuildStructGEP(b, v_out_argp, 0, "")); LLVMBuildStructGEP(b, v_out_argp, 0, ""));
LLVMBuildStore(b, LLVMBuildStore(b,
l_int8_const(0), l_sbool_const(0),
LLVMBuildStructGEP(b, v_out_argnullp, LLVMBuildStructGEP(b, v_out_argnullp,
0, "")); 0, ""));
/* and call output function (can never return NULL) */ /* and call output function (can never return NULL) */
@ -1397,7 +1399,7 @@ llvm_compile_expr(ExprState *state)
/* arg2: typmod: preset in execExpr.c */ /* arg2: typmod: preset in execExpr.c */
/* reset fcinfo_in->isnull */ /* reset fcinfo_in->isnull */
LLVMBuildStore(b, l_int8_const(0), v_fcinfo_in_isnullp); LLVMBuildStore(b, l_sbool_const(0), v_fcinfo_in_isnullp);
/* and call function */ /* and call function */
v_retval = LLVMBuildCall(b, v_fn_addr_in, &v_fcinfo_in, 1, v_retval = LLVMBuildCall(b, v_fn_addr_in, &v_fcinfo_in, 1,
"funccall_iocoerce_in"); "funccall_iocoerce_in");
@ -1448,11 +1450,11 @@ llvm_compile_expr(ExprState *state)
/* load argnull[0|1] for both arguments */ /* load argnull[0|1] for both arguments */
v_argnull0 = l_load_struct_gep(b, v_argnullp, 0, ""); v_argnull0 = l_load_struct_gep(b, v_argnullp, 0, "");
v_argisnull0 = LLVMBuildICmp(b, LLVMIntEQ, v_argnull0, v_argisnull0 = LLVMBuildICmp(b, LLVMIntEQ, v_argnull0,
l_int8_const(1), ""); l_sbool_const(1), "");
v_argnull1 = l_load_struct_gep(b, v_argnullp, 1, ""); v_argnull1 = l_load_struct_gep(b, v_argnullp, 1, "");
v_argisnull1 = LLVMBuildICmp(b, LLVMIntEQ, v_argnull1, v_argisnull1 = LLVMBuildICmp(b, LLVMIntEQ, v_argnull1,
l_int8_const(1), ""); l_sbool_const(1), "");
v_anyargisnull = LLVMBuildOr(b, v_argisnull0, v_argisnull1, ""); v_anyargisnull = LLVMBuildOr(b, v_argisnull0, v_argisnull1, "");
v_bothargisnull = LLVMBuildAnd(b, v_argisnull0, v_argisnull1, ""); v_bothargisnull = LLVMBuildAnd(b, v_argisnull0, v_argisnull1, "");
@ -1475,7 +1477,7 @@ llvm_compile_expr(ExprState *state)
/* Both NULL? Then is not distinct... */ /* Both NULL? Then is not distinct... */
LLVMPositionBuilderAtEnd(b, b_bothargnull); LLVMPositionBuilderAtEnd(b, b_bothargnull);
LLVMBuildStore(b, l_int8_const(0), v_resnullp); LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
if (opcode == EEOP_NOT_DISTINCT) if (opcode == EEOP_NOT_DISTINCT)
LLVMBuildStore(b, l_sizet_const(1), v_resvaluep); LLVMBuildStore(b, l_sizet_const(1), v_resvaluep);
else else
@ -1485,7 +1487,7 @@ llvm_compile_expr(ExprState *state)
/* Only one is NULL? Then is distinct... */ /* Only one is NULL? Then is distinct... */
LLVMPositionBuilderAtEnd(b, b_anyargnull); LLVMPositionBuilderAtEnd(b, b_anyargnull);
LLVMBuildStore(b, l_int8_const(0), v_resnullp); LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
if (opcode == EEOP_NOT_DISTINCT) if (opcode == EEOP_NOT_DISTINCT)
LLVMBuildStore(b, l_sizet_const(0), v_resvaluep); LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
else else
@ -1562,9 +1564,9 @@ llvm_compile_expr(ExprState *state)
v_anyargisnull = v_anyargisnull =
LLVMBuildOr(b, LLVMBuildOr(b,
LLVMBuildICmp(b, LLVMIntEQ, v_argnull0, LLVMBuildICmp(b, LLVMIntEQ, v_argnull0,
l_int8_const(1), ""), l_sbool_const(1), ""),
LLVMBuildICmp(b, LLVMIntEQ, v_argnull1, LLVMBuildICmp(b, LLVMIntEQ, v_argnull1,
l_int8_const(1), ""), l_sbool_const(1), ""),
""); "");
LLVMBuildCondBr(b, v_anyargisnull, b_hasnull, b_nonull); LLVMBuildCondBr(b, v_anyargisnull, b_hasnull, b_nonull);
@ -1589,7 +1591,7 @@ llvm_compile_expr(ExprState *state)
v_argsequal = LLVMBuildAnd(b, v_argsequal = LLVMBuildAnd(b,
LLVMBuildICmp(b, LLVMIntEQ, LLVMBuildICmp(b, LLVMIntEQ,
v_fcinfo_isnull, v_fcinfo_isnull,
l_int8_const(0), l_sbool_const(0),
""), ""),
LLVMBuildICmp(b, LLVMIntEQ, LLVMBuildICmp(b, LLVMIntEQ,
v_retval, v_retval,
@ -1600,7 +1602,7 @@ llvm_compile_expr(ExprState *state)
/* build block setting result to NULL, if args are equal */ /* build block setting result to NULL, if args are equal */
LLVMPositionBuilderAtEnd(b, b_argsequal); LLVMPositionBuilderAtEnd(b, b_argsequal);
LLVMBuildStore(b, l_int8_const(1), v_resnullp); LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
LLVMBuildStore(b, l_sizet_const(0), v_resvaluep); LLVMBuildStore(b, l_sizet_const(0), v_resvaluep);
LLVMBuildStore(b, v_retval, v_resvaluep); LLVMBuildStore(b, v_retval, v_resvaluep);
@ -1691,11 +1693,11 @@ llvm_compile_expr(ExprState *state)
LLVMBuildICmp(b, LLVMBuildICmp(b,
LLVMIntEQ, LLVMIntEQ,
v_argnull0, v_argnull0,
l_int8_const(1), l_sbool_const(1),
""), ""),
LLVMBuildICmp(b, LLVMIntEQ, LLVMBuildICmp(b, LLVMIntEQ,
v_argnull1, v_argnull1,
l_int8_const(1), ""), l_sbool_const(1), ""),
""); "");
LLVMBuildCondBr(b, v_anyargisnull, b_null, b_compare); LLVMBuildCondBr(b, v_anyargisnull, b_null, b_compare);
@ -1718,7 +1720,7 @@ llvm_compile_expr(ExprState *state)
LLVMBuildICmp(b, LLVMBuildICmp(b,
LLVMIntEQ, LLVMIntEQ,
v_fcinfo_isnull, v_fcinfo_isnull,
l_int8_const(0), l_sbool_const(0),
""), ""),
b_compare_result, b_compare_result,
b_null); b_null);
@ -1740,7 +1742,7 @@ llvm_compile_expr(ExprState *state)
* result. * result.
*/ */
LLVMPositionBuilderAtEnd(b, b_null); LLVMPositionBuilderAtEnd(b, b_null);
LLVMBuildStore(b, l_int8_const(1), v_resnullp); LLVMBuildStore(b, l_sbool_const(1), v_resnullp);
LLVMBuildBr(b, opblocks[op->d.rowcompare_step.jumpnull]); LLVMBuildBr(b, opblocks[op->d.rowcompare_step.jumpnull]);
break; break;
@ -1792,7 +1794,7 @@ llvm_compile_expr(ExprState *state)
""); "");
v_result = LLVMBuildZExt(b, v_result, TypeSizeT, ""); v_result = LLVMBuildZExt(b, v_result, TypeSizeT, "");
LLVMBuildStore(b, l_int8_const(0), v_resnullp); LLVMBuildStore(b, l_sbool_const(0), v_resnullp);
LLVMBuildStore(b, v_result, v_resvaluep); LLVMBuildStore(b, v_result, v_resvaluep);
LLVMBuildBr(b, opblocks[i + 1]); LLVMBuildBr(b, opblocks[i + 1]);
@ -1836,10 +1838,11 @@ llvm_compile_expr(ExprState *state)
v_params[1] = l_ptr_const(op, l_ptr(StructExprEvalStep)); v_params[1] = l_ptr_const(op, l_ptr(StructExprEvalStep));
v_ret = LLVMBuildCall(b, v_fn, v_ret = LLVMBuildCall(b, v_fn,
v_params, lengthof(v_params), ""); v_params, lengthof(v_params), "");
v_ret = LLVMBuildZExt(b, v_ret, TypeStorageBool, "");
LLVMBuildCondBr(b, LLVMBuildCondBr(b,
LLVMBuildICmp(b, LLVMIntEQ, v_ret, LLVMBuildICmp(b, LLVMIntEQ, v_ret,
l_int8_const(1), ""), l_sbool_const(1), ""),
opblocks[i + 1], opblocks[i + 1],
opblocks[jumpdone]); opblocks[jumpdone]);
break; break;
@ -1863,7 +1866,7 @@ llvm_compile_expr(ExprState *state)
v_casevaluep = l_ptr_const(op->d.casetest.value, v_casevaluep = l_ptr_const(op->d.casetest.value,
l_ptr(TypeSizeT)); l_ptr(TypeSizeT));
v_casenullp = l_ptr_const(op->d.casetest.isnull, v_casenullp = l_ptr_const(op->d.casetest.isnull,
l_ptr(LLVMInt8Type())); l_ptr(TypeStorageBool));
v_casevaluenull = v_casevaluenull =
LLVMBuildICmp(b, LLVMIntEQ, LLVMBuildICmp(b, LLVMIntEQ,
@ -2032,7 +2035,7 @@ llvm_compile_expr(ExprState *state)
LLVMBuildICmp(b, LLVMBuildICmp(b,
LLVMIntEQ, LLVMIntEQ,
v_argnull0, v_argnull0,
l_int8_const(1), l_sbool_const(1),
""), ""),
opblocks[op->d.agg_deserialize.jumpnull], opblocks[op->d.agg_deserialize.jumpnull],
b_deserialize); b_deserialize);
@ -2080,7 +2083,7 @@ llvm_compile_expr(ExprState *state)
LLVMBasicBlockRef *b_checknulls; LLVMBasicBlockRef *b_checknulls;
jumpnull = op->d.agg_strict_input_check.jumpnull; jumpnull = op->d.agg_strict_input_check.jumpnull;
v_nullp = l_ptr_const(nulls, l_ptr(LLVMInt8Type())); v_nullp = l_ptr_const(nulls, l_ptr(TypeStorageBool));
/* create blocks for checking args */ /* create blocks for checking args */
b_checknulls = palloc(sizeof(LLVMBasicBlockRef *) * nargs); b_checknulls = palloc(sizeof(LLVMBasicBlockRef *) * nargs);
@ -2114,7 +2117,7 @@ llvm_compile_expr(ExprState *state)
LLVMBuildICmp(b, LLVMBuildICmp(b,
LLVMIntEQ, LLVMIntEQ,
v_argisnull, v_argisnull,
l_int8_const(1), ""), l_sbool_const(1), ""),
opblocks[jumpnull], opblocks[jumpnull],
b_argnotnull); b_argnotnull);
} }
@ -2175,7 +2178,7 @@ llvm_compile_expr(ExprState *state)
LLVMBuildCondBr(b, LLVMBuildCondBr(b,
LLVMBuildICmp(b, LLVMIntEQ, v_notransvalue, LLVMBuildICmp(b, LLVMIntEQ, v_notransvalue,
l_int8_const(1), ""), l_sbool_const(1), ""),
b_init, b_init,
opblocks[i + 1]); opblocks[i + 1]);
@ -2240,7 +2243,7 @@ llvm_compile_expr(ExprState *state)
LLVMBuildCondBr(b, LLVMBuildCondBr(b,
LLVMBuildICmp(b, LLVMIntEQ, v_transnull, LLVMBuildICmp(b, LLVMIntEQ, v_transnull,
l_int8_const(1), ""), l_sbool_const(1), ""),
opblocks[jumpnull], opblocks[jumpnull],
opblocks[i + 1]); opblocks[i + 1]);
@ -2417,9 +2420,11 @@ llvm_compile_expr(ExprState *state)
params[0] = v_aggstatep; params[0] = v_aggstatep;
params[1] = v_pertransp; params[1] = v_pertransp;
params[2] = v_retval; params[2] = v_retval;
params[3] = v_fcinfo_isnull; params[3] = LLVMBuildTrunc(b, v_fcinfo_isnull,
TypeParamBool, "");
params[4] = v_transvalue; params[4] = v_transvalue;
params[5] = v_transnull; params[5] = LLVMBuildTrunc(b, v_transnull,
TypeParamBool, "");
v_fn = llvm_get_decl(mod, FuncExecAggTransReparent); v_fn = llvm_get_decl(mod, FuncExecAggTransReparent);
v_newval = v_newval =
@ -2536,8 +2541,7 @@ BuildV1Call(LLVMJitContext *context, LLVMBuilderRef b,
v_fcinfo_isnullp = LLVMBuildStructGEP(b, v_fcinfo, v_fcinfo_isnullp = LLVMBuildStructGEP(b, v_fcinfo,
FIELDNO_FUNCTIONCALLINFODATA_ISNULL, FIELDNO_FUNCTIONCALLINFODATA_ISNULL,
"v_fcinfo_isnull"); "v_fcinfo_isnull");
LLVMBuildStore(b, l_int8_const(0), LLVMBuildStore(b, l_sbool_const(0), v_fcinfo_isnullp);
v_fcinfo_isnullp);
v_retval = LLVMBuildCall(b, v_fn, &v_fcinfo, 1, "funccall"); v_retval = LLVMBuildCall(b, v_fn, &v_fcinfo, 1, "funccall");

View File

@ -45,8 +45,9 @@
* clang/LLVM will omit them. As this file will never be linked into * clang/LLVM will omit them. As this file will never be linked into
* anything, that's harmless. * anything, that's harmless.
*/ */
size_t TypeSizeT;
PGFunction TypePGFunction; PGFunction TypePGFunction;
size_t TypeSizeT;
bool TypeStorageBool;
AggState StructAggState; AggState StructAggState;
AggStatePerGroupData StructAggStatePerGroupData; AggStatePerGroupData StructAggStatePerGroupData;
@ -73,6 +74,19 @@ AttributeTemplate(PG_FUNCTION_ARGS)
PG_RETURN_NULL(); PG_RETURN_NULL();
} }
/*
* Clang represents stdbool.h style booleans that are returned by functions
* differently (as i1) than stored ones (as i8). Therefore we do not just need
* TypeBool (above), but also a way to determine the width of a returned
* integer. This allows us to keep compatible with non-stdbool using
* architectures.
*/
extern bool FunctionReturningBool(void);
bool
FunctionReturningBool(void)
{
return false;
}
/* /*
* To force signatures of functions used during JITing to be present, * To force signatures of functions used during JITing to be present,

View File

@ -56,8 +56,11 @@ typedef struct LLVMJitContext
/* type and struct definitions */ /* type and struct definitions */
extern LLVMTypeRef TypeSizeT; extern LLVMTypeRef TypeParamBool;
extern LLVMTypeRef TypePGFunction; extern LLVMTypeRef TypePGFunction;
extern LLVMTypeRef TypeSizeT;
extern LLVMTypeRef TypeStorageBool;
extern LLVMTypeRef StructtupleDesc; extern LLVMTypeRef StructtupleDesc;
extern LLVMTypeRef StructHeapTupleData; extern LLVMTypeRef StructHeapTupleData;
extern LLVMTypeRef StructTupleTableSlot; extern LLVMTypeRef StructTupleTableSlot;

View File

@ -78,6 +78,24 @@ l_sizet_const(size_t i)
return LLVMConstInt(TypeSizeT, i, false); return LLVMConstInt(TypeSizeT, i, false);
} }
/*
* Emit constant boolean, as used for storage (e.g. global vars, structs).
*/
static inline LLVMValueRef
l_sbool_const(bool i)
{
return LLVMConstInt(TypeStorageBool, (int) i, false);
}
/*
* Emit constant boolean, as used for parameters (e.g. function parameters).
*/
static inline LLVMValueRef
l_pbool_const(bool i)
{
return LLVMConstInt(TypeParamBool, (int) i, false);
}
/* /*
* Load a pointer member idx from a struct. * Load a pointer member idx from a struct.
*/ */