Use PGFuncGeneratorInfo to codegen pg functions

上级 15bc00dc
......@@ -91,19 +91,15 @@ class PGArithFuncGenerator {
* error block.
**/
static bool MulWithOverflow(gpcodegen::GpCodegenUtils* codegen_utils,
llvm::Function* llvm_main_func,
llvm::BasicBlock* llvm_error_block,
const std::vector<llvm::Value*>& llvm_args,
const PGFuncGeneratorInfo& pg_func_info,
llvm::Value** llvm_out_value) {
llvm::Value* llvm_err_msg = codegen_utils->GetConstant(
ArithOpOverFlowErrorMsg<rtype>::OverFlowErrMsg());
return ArithOpWithOverflow(
codegen_utils,
&gpcodegen::GpCodegenUtils::CreateMulOverflow<rtype>,
llvm_main_func,
llvm_error_block,
llvm_err_msg,
llvm_args,
pg_func_info,
llvm_out_value);
}
......@@ -122,20 +118,16 @@ class PGArithFuncGenerator {
* error block.
**/
static bool AddWithOverflow(gpcodegen::GpCodegenUtils* codegen_utils,
llvm::Function* llvm_main_func,
llvm::BasicBlock* llvm_error_block,
const std::vector<llvm::Value*>& llvm_args,
const PGFuncGeneratorInfo& pg_func_info,
llvm::Value** llvm_out_value) {
llvm::Value* llvm_err_msg = codegen_utils->GetConstant(
ArithOpOverFlowErrorMsg<rtype>::OverFlowErrMsg());
return ArithOpWithOverflow(
codegen_utils,
&gpcodegen::GpCodegenUtils::CreateAddOverflow<rtype>,
llvm_main_func,
llvm_error_block,
llvm_err_msg,
llvm_args,
llvm_out_value);
codegen_utils,
&gpcodegen::GpCodegenUtils::CreateAddOverflow<rtype>,
llvm_err_msg,
pg_func_info,
llvm_out_value);
}
/**
* @brief Create LLVM Sub instruction with check for overflow
......@@ -152,28 +144,22 @@ class PGArithFuncGenerator {
* error block.
**/
static bool SubWithOverflow(gpcodegen::GpCodegenUtils* codegen_utils,
llvm::Function* llvm_main_func,
llvm::BasicBlock* llvm_error_block,
const std::vector<llvm::Value*>& llvm_args,
llvm::Value** llvm_out_value) {
const PGFuncGeneratorInfo& pg_func_info,
llvm::Value** llvm_out_value) {
llvm::Value* llvm_err_msg = codegen_utils->GetConstant(
ArithOpOverFlowErrorMsg<rtype>::OverFlowErrMsg());
return ArithOpWithOverflow(
codegen_utils,
&gpcodegen::GpCodegenUtils::CreateSubOverflow<rtype>,
llvm_main_func,
llvm_error_block,
llvm_err_msg,
llvm_args,
llvm_out_value);
codegen_utils,
&gpcodegen::GpCodegenUtils::CreateSubOverflow<rtype>,
llvm_err_msg,
pg_func_info,
llvm_out_value);
}
static bool ArithOpWithOverflow(gpcodegen::GpCodegenUtils* codegen_utils,
CGArithOpFunc codegen_mem_funcptr,
llvm::Function* llvm_main_func,
llvm::BasicBlock* llvm_error_block,
llvm::Value* llvm_error_msg,
const std::vector<llvm::Value*>& llvm_args,
const PGFuncGeneratorInfo& pg_func_info,
llvm::Value** llvm_out_value);
};
......@@ -181,19 +167,18 @@ template <typename rtype, typename Arg0, typename Arg1>
bool PGArithFuncGenerator<rtype, Arg0, Arg1>::ArithOpWithOverflow(
gpcodegen::GpCodegenUtils* codegen_utils,
CGArithOpFunc codegen_mem_funcptr,
llvm::Function* llvm_main_func,
llvm::BasicBlock* llvm_error_block,
llvm::Value* llvm_error_msg,
const std::vector<llvm::Value*>& llvm_args,
const PGFuncGeneratorInfo& pg_func_info,
llvm::Value** llvm_out_value) {
assert(nullptr != llvm_out_value);
assert(nullptr != codegen_mem_funcptr);
assert(nullptr != llvm_error_msg);
// Assumed caller checked vector size and nullptr for codegen_utils
llvm::Value* casted_arg0 =
codegen_utils->CreateCast<rtype, Arg0>(llvm_args[0]);
codegen_utils->CreateCast<rtype, Arg0>(pg_func_info.llvm_args[0]);
llvm::Value* casted_arg1 =
codegen_utils->CreateCast<rtype, Arg1>(llvm_args[1]);
codegen_utils->CreateCast<rtype, Arg1>(pg_func_info.llvm_args[1]);
llvm::Value* llvm_arith_output = (codegen_utils->*codegen_mem_funcptr)(
casted_arg0, casted_arg1);
......@@ -203,9 +188,9 @@ bool PGArithFuncGenerator<rtype, Arg0, Arg1>::ArithOpWithOverflow(
// Check if it is a Integer type
if (std::is_integral<rtype>::value) {
llvm::BasicBlock* llvm_non_overflow_block = codegen_utils->CreateBasicBlock(
"arith_non_overflow_block", llvm_main_func);
"arith_non_overflow_block", pg_func_info.llvm_main_func);
llvm::BasicBlock* llvm_overflow_block = codegen_utils->CreateBasicBlock(
"arith_overflow_block", llvm_main_func);
"arith_overflow_block", pg_func_info.llvm_main_func);
*llvm_out_value = irb->CreateExtractValue(llvm_arith_output, 0);
llvm::Value* llvm_overflow_flag =
......@@ -218,7 +203,7 @@ bool PGArithFuncGenerator<rtype, Arg0, Arg1>::ArithOpWithOverflow(
irb->SetInsertPoint(llvm_overflow_block);
codegen_utils->CreateElog(
ERROR, "%s", llvm_error_msg);
irb->CreateBr(llvm_error_block);
irb->CreateBr(pg_func_info.llvm_error_block);
irb->SetInsertPoint(llvm_non_overflow_block);
} else {
......
......@@ -18,6 +18,7 @@
#include "codegen/utils/codegen_utils.h"
#include "codegen/base_codegen.h"
#include "codegen/pg_func_generator_interface.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Value.h"
......@@ -46,11 +47,10 @@ class PGDateFuncGenerator {
* @return true if generation was successful otherwise return false
*
**/
static bool DateLETimestamp(gpcodegen::GpCodegenUtils* codegen_utils,
llvm::Function* llvm_main_func,
llvm::BasicBlock* llvm_error_block,
const std::vector<llvm::Value*>& llvm_args,
llvm::Value** llvm_out_value);
static bool DateLETimestamp(
gpcodegen::GpCodegenUtils* codegen_utils,
const PGFuncGeneratorInfo& pg_func_info,
llvm::Value** llvm_out_value);
private:
/**
......@@ -67,9 +67,7 @@ class PGDateFuncGenerator {
*/
static llvm::Value* GenerateDate2Timestamp(
GpCodegenUtils* codegen_utils,
llvm::Function* llvm_main_func,
llvm::Value* llvm_arg,
llvm::BasicBlock* llvm_error_block);
const PGFuncGeneratorInfo& pg_func_info);
};
/** @} */
......
......@@ -29,9 +29,7 @@ namespace gpcodegen {
*/
typedef bool (*PGFuncGenerator)(gpcodegen::GpCodegenUtils* codegen_utils,
llvm::Function* llvm_main_func,
llvm::BasicBlock* llvm_error_block,
const std::vector<llvm::Value*>& llvm_args,
const PGFuncGeneratorInfo& pg_func_info,
llvm::Value** llvm_out_value);
......@@ -136,13 +134,13 @@ Arg0, Arg1> {
}
bool GenerateCode(gpcodegen::GpCodegenUtils* codegen_utils,
llvm::Function* llvm_main_func,
llvm::BasicBlock* llvm_error_block,
const std::vector<llvm::Value*>& llvm_args,
const PGFuncGeneratorInfo& pg_func_info,
llvm::Value** llvm_out_value) final {
assert(nullptr != llvm_out_value);
std::vector<llvm::Value*> llvm_preproc_args;
if (!this->PreProcessArgs(codegen_utils, llvm_args, &llvm_preproc_args)) {
if (!this->PreProcessArgs(codegen_utils,
pg_func_info.llvm_args,
&llvm_preproc_args)) {
return false;
}
llvm::IRBuilder<>* irb = codegen_utils->ir_builder();
......@@ -182,20 +180,21 @@ Arg0, Arg1> {
}
bool GenerateCode(gpcodegen::GpCodegenUtils* codegen_utils,
llvm::Function* llvm_main_func,
llvm::BasicBlock* llvm_error_block,
const std::vector<llvm::Value*>& llvm_args,
const PGFuncGeneratorInfo& pg_func_info,
llvm::Value** llvm_out_value) final {
assert(nullptr != codegen_utils &&
nullptr != llvm_out_value);
assert(nullptr != codegen_utils);
assert(nullptr != llvm_out_value);
std::vector<llvm::Value*> llvm_preproc_args;
if (!this->PreProcessArgs(codegen_utils, llvm_args, &llvm_preproc_args)) {
if (!this->PreProcessArgs(codegen_utils,
pg_func_info.llvm_args,
&llvm_preproc_args)) {
return false;
}
PGFuncGeneratorInfo pg_processed_func_info(pg_func_info.llvm_main_func,
pg_func_info.llvm_error_block,
llvm_preproc_args);
this->func_ptr()(codegen_utils,
llvm_main_func,
llvm_error_block,
llvm_preproc_args,
pg_processed_func_info,
llvm_out_value);
return true;
}
......
......@@ -26,6 +26,30 @@ namespace gpcodegen {
* @{
*/
/**
* @brief Object that holds the information needed for generating the builtin
* postgres functions.
*
**/
struct PGFuncGeneratorInfo {
// Convenience members for code generation
llvm::Function* llvm_main_func;
llvm::BasicBlock* llvm_error_block;
// llvm arguments for the function.
// This can be updated while generating the code.
std::vector<llvm::Value*> llvm_args;
PGFuncGeneratorInfo(
llvm::Function* llvm_main_func,
llvm::BasicBlock* llvm_error_block,
const std::vector<llvm::Value*>& llvm_args) :
llvm_main_func(llvm_main_func),
llvm_error_block(llvm_error_block),
llvm_args(llvm_args) {
}
};
/**
* @brief Interface for all code generators.
**/
......@@ -55,9 +79,7 @@ class PGFuncGeneratorInterface {
* @return true when it generated successfully otherwise it return false.
**/
virtual bool GenerateCode(gpcodegen::GpCodegenUtils* codegen_utils,
llvm::Function* llvm_main_func,
llvm::BasicBlock* llvm_error_block,
const std::vector<llvm::Value*>& llvm_args,
const PGFuncGeneratorInfo& pg_gen_info,
llvm::Value** llvm_out_value) = 0;
};
......
......@@ -186,11 +186,12 @@ bool OpExprTreeGenerator::GenerateCode(GpCodegenUtils* codegen_utils,
llvm_arguments.push_back(llvm_arg);
}
llvm::Value* llvm_op_value = nullptr;
bool retval = pg_func_interface->GenerateCode(codegen_utils,
gen_info.llvm_main_func,
PGFuncGeneratorInfo pg_func_info(gen_info.llvm_main_func,
gen_info.llvm_error_block,
llvm_arguments,
&llvm_op_value);
llvm_arguments);
bool retval = pg_func_interface->GenerateCode(codegen_utils,
pg_func_info,
&llvm_op_value);
// convert return type to Datum
*llvm_out_value = codegen_utils->CreateCppTypeToDatumCast(llvm_op_value);
return retval;
......
......@@ -27,21 +27,19 @@ using gpcodegen::PGDateFuncGenerator;
bool PGDateFuncGenerator::DateLETimestamp(
gpcodegen::GpCodegenUtils* codegen_utils,
llvm::Function* llvm_main_func,
llvm::BasicBlock* llvm_error_block,
const std::vector<llvm::Value*>& llvm_args,
const PGFuncGeneratorInfo& pg_func_info,
llvm::Value** llvm_out_value) {
llvm::IRBuilder<>* irb = codegen_utils->ir_builder();
// llvm_args[0] is of date type
llvm::Value* llvm_arg0_Timestamp = GenerateDate2Timestamp(
codegen_utils, llvm_main_func, llvm_args[0], llvm_error_block);
codegen_utils, pg_func_info);
// timestamp_cmp_internal {{{
#ifdef HAVE_INT64_TIMESTAMP
*llvm_out_value =
irb->CreateICmpSLE(llvm_arg0_Timestamp, llvm_args[1]);
irb->CreateICmpSLE(llvm_arg0_Timestamp, pg_func_info.llvm_args[1]);
#else
// TODO(nikos): We do not support NaNs.
elog(DEBUG1, "Timestamp != int_64: NaNs are not supported.");
......@@ -54,11 +52,11 @@ bool PGDateFuncGenerator::DateLETimestamp(
llvm::Value* PGDateFuncGenerator::GenerateDate2Timestamp(
GpCodegenUtils* codegen_utils,
llvm::Function* llvm_main_func,
llvm::Value* llvm_arg,
llvm::BasicBlock* llvm_error_block) {
const PGFuncGeneratorInfo& pg_func_info) {
assert(nullptr != llvm_arg && nullptr != llvm_arg->getType());
assert(pg_func_info.llvm_args.size() > 1);
assert(nullptr != pg_func_info.llvm_args[0]);
assert(nullptr != pg_func_info.llvm_args[0]->getType());
#ifdef HAVE_INT64_TIMESTAMP
......@@ -68,19 +66,22 @@ llvm::Value* PGDateFuncGenerator::GenerateDate2Timestamp(
llvm::Value* llvm_out_value = nullptr;
llvm::Value* llvm_err_msg = codegen_utils->GetConstant(
"date out of range for timestamp");
PGFuncGeneratorInfo pg_timestamp_func_info(
pg_func_info.llvm_main_func,
pg_func_info.llvm_error_block,
{pg_func_info.llvm_args[0], llvm_USECS_PER_DAY});
PGArithFuncGenerator<int64_t, int32_t, int64_t>::ArithOpWithOverflow(
codegen_utils,
&gpcodegen::GpCodegenUtils::CreateMulOverflow<int64_t>,
llvm_main_func,
llvm_error_block,
llvm_err_msg,
{llvm_arg, llvm_USECS_PER_DAY},
pg_timestamp_func_info,
&llvm_out_value);
return llvm_out_value;
#else
llvm::Value* llvm_arg_64 = codegen_utils->CreateCast<int64_t, int32_t>(
llvm_arg);
pg_func_info.llvm_args[0]);
llvm::Value *llvm_SECS_PER_DAY = codegen_utils->
GetConstant<int64_t>(SECS_PER_DAY);
return codegen_utils->ir_builder()->CreateMul(llvm_arg_64, llvm_SECS_PER_DAY);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册