diff --git a/src/backend/codegen/CMakeLists.txt b/src/backend/codegen/CMakeLists.txt index 8bee31a4aef4d955dd31f95c8591e5b6c550049c..2e6e6bae0114c3c65858c0a87380a6b542808923 100644 --- a/src/backend/codegen/CMakeLists.txt +++ b/src/backend/codegen/CMakeLists.txt @@ -171,12 +171,13 @@ set(GPCODEGEN_SRC codegen_interface.cc codegen_manager.cc codegen_wrapper.cc + const_expr_tree_generator.cc exec_variable_list_codegen.cc exec_eval_expr_codegen.cc expr_tree_generator.cc op_expr_tree_generator.cc + pg_date_func_generator.cc var_expr_tree_generator.cc - const_expr_tree_generator.cc ) # Integrate with GPDB build system. diff --git a/src/backend/codegen/const_expr_tree_generator.cc b/src/backend/codegen/const_expr_tree_generator.cc index bd2a93864bb96034d7d9a20d1826339143a6fbbb..97bb48428e158781692cc5bf67450ddd7982ade1 100644 --- a/src/backend/codegen/const_expr_tree_generator.cc +++ b/src/backend/codegen/const_expr_tree_generator.cc @@ -39,7 +39,7 @@ ConstExprTreeGenerator::ConstExprTreeGenerator(ExprState* expr_state) : ExprTreeGenerator(expr_state, ExprTreeNodeType::kConst) { } -bool ConstExprTreeGenerator::GenerateCode(CodegenUtils* codegen_utils, +bool ConstExprTreeGenerator::GenerateCode(GpCodegenUtils* codegen_utils, ExprContext* econtext, llvm::Function* llvm_main_func, llvm::BasicBlock* llvm_error_block, diff --git a/src/backend/codegen/include/codegen/const_expr_tree_generator.h b/src/backend/codegen/include/codegen/const_expr_tree_generator.h index 2b3c47475e3357ef2bef7374e628187c78ce79f9..9ba70fb917e203667896644a2152b3ad9e49a1c6 100644 --- a/src/backend/codegen/include/codegen/const_expr_tree_generator.h +++ b/src/backend/codegen/include/codegen/const_expr_tree_generator.h @@ -32,7 +32,7 @@ class ConstExprTreeGenerator : public ExprTreeGenerator { ExprContext* econtext, std::unique_ptr* expr_tree); - bool GenerateCode(gpcodegen::CodegenUtils* codegen_utils, + bool GenerateCode(gpcodegen::GpCodegenUtils* codegen_utils, ExprContext* econtext, llvm::Function* llvm_main_func, llvm::BasicBlock* llvm_error_block, diff --git a/src/backend/codegen/include/codegen/expr_tree_generator.h b/src/backend/codegen/include/codegen/expr_tree_generator.h index 881b50c79237b4c80bbde79333a0d328bc887424..7155b3c7a930faf83af96e0d21b8823fa6c4356f 100644 --- a/src/backend/codegen/include/codegen/expr_tree_generator.h +++ b/src/backend/codegen/include/codegen/expr_tree_generator.h @@ -18,7 +18,7 @@ #include #include -#include "codegen/utils/codegen_utils.h" +#include "codegen/utils/gp_codegen_utils.h" #include "llvm/IR/Value.h" @@ -71,7 +71,7 @@ class ExprTreeGenerator { * * @return true when it generated successfully otherwise it return false. **/ - virtual bool GenerateCode(gpcodegen::CodegenUtils* codegen_utils, + virtual bool GenerateCode(gpcodegen::GpCodegenUtils* codegen_utils, ExprContext* econtext, llvm::Function* llvm_main_func, llvm::BasicBlock* llvm_error_block, diff --git a/src/backend/codegen/include/codegen/op_expr_tree_generator.h b/src/backend/codegen/include/codegen/op_expr_tree_generator.h index 29154c7369c38278056654d1513dcf30f99d1d7b..cfd4010e16e77c509140d82167682caf1de164b9 100644 --- a/src/backend/codegen/include/codegen/op_expr_tree_generator.h +++ b/src/backend/codegen/include/codegen/op_expr_tree_generator.h @@ -45,7 +45,7 @@ class OpExprTreeGenerator : public ExprTreeGenerator { ExprContext* econtext, std::unique_ptr* expr_tree); - bool GenerateCode(gpcodegen::CodegenUtils* codegen_utils, + bool GenerateCode(gpcodegen::GpCodegenUtils* codegen_utils, ExprContext* econtext, llvm::Function* llvm_main_func, llvm::BasicBlock* llvm_error_block, diff --git a/src/backend/codegen/include/codegen/pg_arith_func_generator.h b/src/backend/codegen/include/codegen/pg_arith_func_generator.h index 3908d70695aa5b2945077ea2ec2f034ab5acedb8..b7118a0e8d4b868239ff648f8047466c8fef626c 100644 --- a/src/backend/codegen/include/codegen/pg_arith_func_generator.h +++ b/src/backend/codegen/include/codegen/pg_arith_func_generator.h @@ -16,7 +16,7 @@ #include #include -#include "codegen/utils/codegen_utils.h" +#include "codegen/utils/gp_codegen_utils.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Value.h" @@ -52,11 +52,11 @@ class PGArithFuncGenerator { * @note If there is overflow, it will do elog::ERROR and then jump to given * error block. **/ - static bool MulWithOverflow(gpcodegen::CodegenUtils* codegen_utils, - llvm::Function* llvm_main_func, - llvm::BasicBlock* llvm_error_block, - const std::vector& llvm_args, - llvm::Value** llvm_out_value); + static bool MulWithOverflow(gpcodegen::GpCodegenUtils* codegen_utils, + llvm::Function* llvm_main_func, + llvm::BasicBlock* llvm_error_block, + const std::vector& llvm_args, + llvm::Value** llvm_out_value); /** * @brief Create LLVM Add instruction with check for overflow @@ -72,7 +72,7 @@ class PGArithFuncGenerator { * @note If there is overflow, it will do elog::ERROR and then jump to given * error block. **/ - static bool AddWithOverflow(gpcodegen::CodegenUtils* codegen_utils, + static bool AddWithOverflow(gpcodegen::GpCodegenUtils* codegen_utils, llvm::Function* llvm_main_func, llvm::BasicBlock* llvm_error_block, const std::vector& llvm_args, @@ -91,16 +91,16 @@ class PGArithFuncGenerator { * @note If there is overflow, it will do elog::ERROR and then jump to given * error block. **/ - static bool SubWithOverflow(gpcodegen::CodegenUtils* codegen_utils, - llvm::Function* llvm_main_func, - llvm::BasicBlock* llvm_error_block, - const std::vector& llvm_args, - llvm::Value** llvm_out_value); + static bool SubWithOverflow(gpcodegen::GpCodegenUtils* codegen_utils, + llvm::Function* llvm_main_func, + llvm::BasicBlock* llvm_error_block, + const std::vector& llvm_args, + llvm::Value** llvm_out_value); }; template bool PGArithFuncGenerator::MulWithOverflow( - gpcodegen::CodegenUtils* codegen_utils, + gpcodegen::GpCodegenUtils* codegen_utils, llvm::Function* llvm_main_func, llvm::BasicBlock* llvm_error_block, const std::vector& llvm_args, @@ -113,29 +113,26 @@ bool PGArithFuncGenerator::MulWithOverflow( llvm::IRBuilder<>* irb = codegen_utils->ir_builder(); - if (!llvm_mul_output->getType()->isDoubleTy()) - { + if (llvm_mul_output->getType()->isIntegerTy()) { llvm::BasicBlock* llvm_non_overflow_block = codegen_utils->CreateBasicBlock( "mul_non_overflow_block", llvm_main_func); llvm::BasicBlock* llvm_overflow_block = codegen_utils->CreateBasicBlock( "mul_overflow_block", llvm_main_func); *llvm_out_value = irb->CreateExtractValue(llvm_mul_output, 0); - llvm::Value* llvm_overflow_flag = irb->CreateExtractValue(llvm_mul_output, 1); + llvm::Value* llvm_overflow_flag = + irb->CreateExtractValue(llvm_mul_output, 1); - irb->CreateCondBr( - irb->CreateICmpEQ(llvm_overflow_flag, - codegen_utils->GetConstant(true)), - llvm_overflow_block, - llvm_non_overflow_block); + irb->CreateCondBr(llvm_overflow_flag, + llvm_overflow_block, + llvm_non_overflow_block); irb->SetInsertPoint(llvm_overflow_block); // TODO(krajaraman): Elog::ERROR after ElogWrapper integrated. irb->CreateBr(llvm_error_block); irb->SetInsertPoint(llvm_non_overflow_block); - } - else { + } else { *llvm_out_value = llvm_mul_output; } @@ -144,7 +141,7 @@ bool PGArithFuncGenerator::MulWithOverflow( template bool PGArithFuncGenerator::AddWithOverflow( - gpcodegen::CodegenUtils* codegen_utils, + gpcodegen::GpCodegenUtils* codegen_utils, llvm::Function* llvm_main_func, llvm::BasicBlock* llvm_error_block, const std::vector& llvm_args, @@ -157,28 +154,25 @@ bool PGArithFuncGenerator::AddWithOverflow( llvm::IRBuilder<>* irb = codegen_utils->ir_builder(); - if (!llvm_add_output->getType()->isDoubleTy()) - { + if (llvm_add_output->getType()->isIntegerTy()) { llvm::BasicBlock* llvm_non_overflow_block = codegen_utils->CreateBasicBlock( "add_non_overflow_block", llvm_main_func); llvm::BasicBlock* llvm_overflow_block = codegen_utils->CreateBasicBlock( "add_overflow_block", llvm_main_func); *llvm_out_value = irb->CreateExtractValue(llvm_add_output, 0); - llvm::Value* llvm_overflow_flag = irb->CreateExtractValue(llvm_add_output, 1); + llvm::Value* llvm_overflow_flag = + irb->CreateExtractValue(llvm_add_output, 1); - irb->CreateCondBr( - irb->CreateICmpEQ(llvm_overflow_flag, - codegen_utils->GetConstant(true)), - llvm_overflow_block, - llvm_non_overflow_block ); + irb->CreateCondBr(llvm_overflow_flag, + llvm_overflow_block, + llvm_non_overflow_block); irb->SetInsertPoint(llvm_overflow_block); - // TODO : krajaraman Elog::ERROR after ElogWrapper integrad. + // TODO(krajaraman) Elog::ERROR after ElogWrapper integrated. irb->CreateBr(llvm_error_block); irb->SetInsertPoint(llvm_non_overflow_block); - } - else { + } else { *llvm_out_value = llvm_add_output; } @@ -187,7 +181,7 @@ bool PGArithFuncGenerator::AddWithOverflow( template bool PGArithFuncGenerator::SubWithOverflow( - gpcodegen::CodegenUtils* codegen_utils, + gpcodegen::GpCodegenUtils* codegen_utils, llvm::Function* llvm_main_func, llvm::BasicBlock* llvm_error_block, const std::vector& llvm_args, @@ -201,29 +195,26 @@ bool PGArithFuncGenerator::SubWithOverflow( llvm::IRBuilder<>* irb = codegen_utils->ir_builder(); // We only support overflow checks for integers for now - if (llvm_sub_output->getType()->isIntegerTy()) - { + if (llvm_sub_output->getType()->isIntegerTy()) { llvm::BasicBlock* llvm_non_overflow_block = codegen_utils->CreateBasicBlock( "sub_non_overflow_block", llvm_main_func); llvm::BasicBlock* llvm_overflow_block = codegen_utils->CreateBasicBlock( "sub_overflow_block", llvm_main_func); *llvm_out_value = irb->CreateExtractValue(llvm_sub_output, 0); - llvm::Value* llvm_overflow_flag = irb->CreateExtractValue(llvm_sub_output, 1); + llvm::Value* llvm_overflow_flag = + irb->CreateExtractValue(llvm_sub_output, 1); - irb->CreateCondBr( - irb->CreateICmpEQ(llvm_overflow_flag, - codegen_utils->GetConstant(true)), - llvm_overflow_block, - llvm_non_overflow_block); + irb->CreateCondBr(llvm_overflow_flag, + llvm_overflow_block, + llvm_non_overflow_block); irb->SetInsertPoint(llvm_overflow_block); // TODO(krajaraman): Elog::ERROR after ElogWrapper integrated. irb->CreateBr(llvm_error_block); irb->SetInsertPoint(llvm_non_overflow_block); - } - else { + } else { *llvm_out_value = llvm_sub_output; } return true; diff --git a/src/backend/codegen/include/codegen/pg_date_func_generator.h b/src/backend/codegen/include/codegen/pg_date_func_generator.h new file mode 100644 index 0000000000000000000000000000000000000000..38a0a032d7040480a46bb33ff0ec60aebb9b843b --- /dev/null +++ b/src/backend/codegen/include/codegen/pg_date_func_generator.h @@ -0,0 +1,78 @@ +//--------------------------------------------------------------------------- +// Greenplum Database +// Copyright (C) 2016 Pivotal Software, Inc. +// +// @filename: +// pg_date_func_generator.h +// +// @doc: +// Base class for date functions to generate code +// +//--------------------------------------------------------------------------- +#ifndef GPCODEGEN_PG_DATE_FUNC_GENERATOR_H_ // NOLINT(build/header_guard) +#define GPCODEGEN_PG_DATE_FUNC_GENERATOR_H_ + +#include +#include +#include + +#include "codegen/utils/codegen_utils.h" +#include "codegen/base_codegen.h" + +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Value.h" + +namespace gpcodegen { + +/** \addtogroup gpcodegen + * @{ + */ + +/** + * @brief Class with Static member function to generate code for date + * operators. + **/ +class PGDateFuncGenerator { + public: + /** + * @brief Create instructions for date_le_timestamp function + * + * @param codegen_utils Utility to easy code generation. + * @param llvm_main_func Current function for which we are generating code + * @param llvm_error_block Basic Block to jump when error happens + * @param llvm_args Vector of llvm arguments for the function + * @param llvm_out_value Store the results of function + * + * @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_args, + llvm::Value** llvm_out_value); + + private: + /** + * @brief Internal routines for promoting date to timestamp and timestamp + * with time zone (see date2timestamp). + * + * @param codegen_utils Utility to easy code generation. + * @param llvm_main_func Current function for which we are generating code + * @param llvm_arg llvm value for the date + * @param llvm_error_block Basic Block to jump when error happens + * + * @note If there is overflow, it will do elog::ERROR and then jump to given + * error block. + */ + static llvm::Value* GenerateDate2Timestamp( + GpCodegenUtils* codegen_utils, + llvm::Function* llvm_main_func, + llvm::Value* llvm_arg, + llvm::BasicBlock* llvm_error_block); +}; + +/** @} */ +} // namespace gpcodegen + +#endif // GPCODEGEN_PG_ARITH_FUNC_GENERATOR_H_ diff --git a/src/backend/codegen/include/codegen/pg_func_generator.h b/src/backend/codegen/include/codegen/pg_func_generator.h index 8dfcc8ae9baee6d98dff92eab8ac9c5e1e99242c..1e89c7cc542ee1ba8f0a986f53c934eb61cdd61a 100644 --- a/src/backend/codegen/include/codegen/pg_func_generator.h +++ b/src/backend/codegen/include/codegen/pg_func_generator.h @@ -17,7 +17,7 @@ #include #include "codegen/pg_func_generator_interface.h" -#include "codegen/utils/codegen_utils.h" +#include "codegen/utils/gp_codegen_utils.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Value.h" @@ -28,7 +28,7 @@ namespace gpcodegen { * @{ */ -typedef bool (*PGFuncGenerator)(gpcodegen::CodegenUtils* codegen_utils, +typedef bool (*PGFuncGenerator)(gpcodegen::GpCodegenUtils* codegen_utils, llvm::Function* llvm_main_func, llvm::BasicBlock* llvm_error_block, const std::vector& llvm_args, @@ -63,7 +63,7 @@ class PGFuncBaseGenerator : public PGFuncGeneratorInterface { * * @return true on successful preprocess otherwise return false. **/ - bool PreProcessArgs(gpcodegen::CodegenUtils* codegen_utils, + bool PreProcessArgs(gpcodegen::GpCodegenUtils* codegen_utils, const std::vector& llvm_in_args, std::vector* llvm_out_args) { assert(nullptr != codegen_utils && @@ -132,7 +132,7 @@ Arg0, Arg1> { mem_func_ptr) { } - bool GenerateCode(gpcodegen::CodegenUtils* codegen_utils, + bool GenerateCode(gpcodegen::GpCodegenUtils* codegen_utils, llvm::Function* llvm_main_func, llvm::BasicBlock* llvm_error_block, const std::vector& llvm_args, @@ -178,7 +178,7 @@ Arg0, Arg1> { func_ptr) { } - bool GenerateCode(gpcodegen::CodegenUtils* codegen_utils, + bool GenerateCode(gpcodegen::GpCodegenUtils* codegen_utils, llvm::Function* llvm_main_func, llvm::BasicBlock* llvm_error_block, const std::vector& llvm_args, diff --git a/src/backend/codegen/include/codegen/pg_func_generator_interface.h b/src/backend/codegen/include/codegen/pg_func_generator_interface.h index f23adbc579daa0e7057bb76e8a60c01b204f31f6..a8f1a66daac12d0326670b30cfabfdc8e169a6a8 100644 --- a/src/backend/codegen/include/codegen/pg_func_generator_interface.h +++ b/src/backend/codegen/include/codegen/pg_func_generator_interface.h @@ -18,7 +18,7 @@ #include "llvm/IR/Value.h" -#include "codegen/utils/codegen_utils.h" +#include "codegen/utils/gp_codegen_utils.h" namespace gpcodegen { @@ -54,7 +54,7 @@ class PGFuncGeneratorInterface { * * @return true when it generated successfully otherwise it return false. **/ - virtual bool GenerateCode(gpcodegen::CodegenUtils* codegen_utils, + virtual bool GenerateCode(gpcodegen::GpCodegenUtils* codegen_utils, llvm::Function* llvm_main_func, llvm::BasicBlock* llvm_error_block, const std::vector& llvm_args, diff --git a/src/backend/codegen/include/codegen/utils/codegen_utils.h b/src/backend/codegen/include/codegen/utils/codegen_utils.h index 2ae02e71264c8a822143754c9a3a9e59f60d2a68..a577596a90fddc562d6dea8dd441efb68914ba0c 100644 --- a/src/backend/codegen/include/codegen/utils/codegen_utils.h +++ b/src/backend/codegen/include/codegen/utils/codegen_utils.h @@ -492,7 +492,7 @@ class CodegenUtils { // Check that the call instruction belongs to a BasicBlock which is part of // a valid function if (!(call_inst && call_inst->getParent() - && call_inst->getParent()->getParent())){ + && call_inst->getParent()->getParent())) { return false; } llvm::InlineFunctionInfo info; @@ -1360,7 +1360,6 @@ class ArithOpMaker { template <> class ArithOpMaker { public: - static llvm::Value* CreateAddOverflow(CodegenUtils* generator, llvm::Value* arg0, llvm::Value* arg1) { @@ -1370,7 +1369,7 @@ class ArithOpMaker { llvm::Value* casted_arg1 = generator->ir_builder()-> CreateBitCast(arg1, generator->GetType()); - // TODO: armenatzoglou Support overflow + // TODO(armenatzoglou) Support overflow return generator->ir_builder()->CreateFAdd(casted_arg0, casted_arg1); } @@ -1383,7 +1382,7 @@ class ArithOpMaker { llvm::Value* casted_arg1 = generator->ir_builder()-> CreateBitCast(arg1, generator->GetType()); - // TODO: armenatzoglou Support overflow + // TODO(armenatzoglou) Support overflow return generator->ir_builder()->CreateFSub(casted_arg0, casted_arg1); } @@ -1396,7 +1395,7 @@ class ArithOpMaker { llvm::Value* casted_arg1 = generator->ir_builder()-> CreateBitCast(arg1, generator->GetType()); - // TODO: armenatzoglou Support overflow + // TODO(armenatzoglou) Support overflow return generator->ir_builder()->CreateFMul(casted_arg0, casted_arg1); } diff --git a/src/backend/codegen/include/codegen/var_expr_tree_generator.h b/src/backend/codegen/include/codegen/var_expr_tree_generator.h index b5bb3d8794fafcc3f7914e1fad399611dd805bb9..3b2ded01972d2b201e37bf13270f6594cdd01d67 100644 --- a/src/backend/codegen/include/codegen/var_expr_tree_generator.h +++ b/src/backend/codegen/include/codegen/var_expr_tree_generator.h @@ -32,7 +32,7 @@ class VarExprTreeGenerator : public ExprTreeGenerator { ExprContext* econtext, std::unique_ptr* expr_tree); - bool GenerateCode(gpcodegen::CodegenUtils* codegen_utils, + bool GenerateCode(gpcodegen::GpCodegenUtils* codegen_utils, ExprContext* econtext, llvm::Function* llvm_main_func, llvm::BasicBlock* llvm_error_block, diff --git a/src/backend/codegen/op_expr_tree_generator.cc b/src/backend/codegen/op_expr_tree_generator.cc index df30f9e2e1340eb41b98534df6a592ec041b004c..65e58d64fdf6e4001a53d1d1d3418fb00471d1ac 100644 --- a/src/backend/codegen/op_expr_tree_generator.cc +++ b/src/backend/codegen/op_expr_tree_generator.cc @@ -14,6 +14,7 @@ #include "codegen/op_expr_tree_generator.h" #include "include/codegen/pg_arith_func_generator.h" +#include "include/codegen/pg_date_func_generator.h" #include "llvm/IR/Value.h" extern "C" { @@ -25,7 +26,7 @@ extern "C" { using gpcodegen::OpExprTreeGenerator; using gpcodegen::ExprTreeGenerator; -using gpcodegen::CodegenUtils; +using gpcodegen::GpCodegenUtils; using gpcodegen::PGFuncGeneratorInterface; using gpcodegen::PGFuncGenerator; using gpcodegen::CodeGenFuncMap; @@ -59,7 +60,6 @@ void OpExprTreeGenerator::InitializeSupportedFunction() { "int4mi", &PGArithFuncGenerator::SubWithOverflow)); - supported_function_[216] = std::unique_ptr( new PGGenericFuncGenerator( 216, @@ -82,6 +82,11 @@ void OpExprTreeGenerator::InitializeSupportedFunction() { new PGIRBuilderFuncGenerator::CreateICmpSLE), int32_t, int32_t>(1088, "date_le", &IRBuilder<>::CreateICmpSLE)); + supported_function_[2339] = std::unique_ptr( + new PGGenericFuncGenerator( + 2339, + "date_le_timestamp", + &PGDateFuncGenerator::DateLETimestamp)); } OpExprTreeGenerator::OpExprTreeGenerator( @@ -125,8 +130,8 @@ bool OpExprTreeGenerator::VerifyAndCreateExprTree( assert(nullptr != argstate); std::unique_ptr arg(nullptr); supported_tree &= ExprTreeGenerator::VerifyAndCreateExprTree(argstate, - econtext, - &arg); + econtext, + &arg); if (!supported_tree) { break; } @@ -141,7 +146,7 @@ bool OpExprTreeGenerator::VerifyAndCreateExprTree( return true; } -bool OpExprTreeGenerator::GenerateCode(CodegenUtils* codegen_utils, +bool OpExprTreeGenerator::GenerateCode(GpCodegenUtils* codegen_utils, ExprContext* econtext, llvm::Function* llvm_main_func, llvm::BasicBlock* llvm_error_block, diff --git a/src/backend/codegen/pg_date_func_generator.cc b/src/backend/codegen/pg_date_func_generator.cc new file mode 100644 index 0000000000000000000000000000000000000000..0811c50cb9a4479f61881f63549ce0ea875c37a7 --- /dev/null +++ b/src/backend/codegen/pg_date_func_generator.cc @@ -0,0 +1,103 @@ +//--------------------------------------------------------------------------- +// Greenplum Database +// Copyright (C) 2016 Pivotal Software, Inc. +// +// @filename: +// pg_date_func_generator.cc +// +// @doc: +// Base class for date functions to generate code +// +//--------------------------------------------------------------------------- + + +#include "codegen/pg_date_func_generator.h" +#include "codegen/utils/gp_codegen_utils.h" + +extern "C" { +#include "postgres.h" +#include "utils/elog.h" +#include "utils/date.h" +#include "utils/timestamp.h" +} + +using gpcodegen::GpCodegenUtils; +using gpcodegen::PGDateFuncGenerator; + +bool PGDateFuncGenerator::DateLETimestamp( + gpcodegen::GpCodegenUtils* codegen_utils, + llvm::Function* llvm_main_func, + llvm::BasicBlock* llvm_error_block, + const std::vector& llvm_args, + llvm::Value** llvm_out_value) { + + llvm::IRBuilder<>* irb = codegen_utils->ir_builder(); + + llvm::Value* llvm_arg0_DateADT = codegen_utils-> + CreateCast(llvm_args[0]); + /* TODO: Use CreateCast*/ + llvm::Value* llvm_arg1_Timestamp = irb->CreateSExt( + llvm_args[1], codegen_utils->GetType()); + + llvm::Value* llvm_arg0_Timestamp = GenerateDate2Timestamp( + codegen_utils, llvm_main_func, llvm_arg0_DateADT, llvm_error_block); + + // timestamp_cmp_internal {{{ +#ifdef HAVE_INT64_TIMESTAMP + *llvm_out_value = irb->CreateICmpSLE(llvm_arg0_Timestamp, llvm_arg1_Timestamp); +#else + // TODO: We do not support NaNs. + elog(DEBUG1,"Timestamp != int_64: NaNs are not supported."); + return false; +#endif + // }}} + + return true; +} + +llvm::Value* PGDateFuncGenerator::GenerateDate2Timestamp( + GpCodegenUtils* codegen_utils, + llvm::Function* llvm_main_func, + llvm::Value* llvm_arg, + llvm::BasicBlock* llvm_error_block) { + + assert(nullptr != llvm_arg && nullptr != llvm_arg->getType()); + llvm::IRBuilder<>* irb = codegen_utils->ir_builder(); + +#ifdef HAVE_INT64_TIMESTAMP + + llvm::BasicBlock* llvm_non_overflow_block = codegen_utils->CreateBasicBlock( + "date_non_overflow_block", llvm_main_func); + llvm::BasicBlock* llvm_overflow_block = codegen_utils->CreateBasicBlock( + "date_overflow_block", llvm_main_func); + + llvm::Value *llvm_USECS_PER_DAY = codegen_utils-> + GetConstant(USECS_PER_DAY); + + /* TODO: Use CreateCast*/ + llvm::Value* llvm_arg_64 = irb->CreateSExt( + llvm_arg, codegen_utils->GetType()); + + llvm::Value* llvm_mul_output = codegen_utils->CreateMulOverflow( + llvm_USECS_PER_DAY, llvm_arg_64); + + llvm::Value* llvm_overflow_flag = irb->CreateExtractValue(llvm_mul_output, 1); + + irb->CreateCondBr(llvm_overflow_flag, llvm_overflow_block, llvm_non_overflow_block); + + irb->SetInsertPoint(llvm_overflow_block); + codegen_utils->CreateElog(ERROR, "date out of range for timestamp"); + irb->CreateBr(llvm_error_block); + + irb->SetInsertPoint(llvm_non_overflow_block); + + return irb->CreateExtractValue(llvm_mul_output, 0); +#else + llvm::Value *llvm_SECS_PER_DAY = codegen_utils-> + GetConstant(SECS_PER_DAY); + /*TODO: Use CreateCast*/ + llvm::Value *llvm_arg_64 = irb->CreateSExt(llvm_arg, + codegen_utils->GetType()); + return irb->CreateMul(llvm_arg_64, llvm_SECS_PER_DAY); +#endif +} diff --git a/src/backend/codegen/var_expr_tree_generator.cc b/src/backend/codegen/var_expr_tree_generator.cc index f70b0e8925553d3cf114e9d88f6a33b338241ffe..162f275f1be5d3e98fe679c01c6de033b3a1b29c 100644 --- a/src/backend/codegen/var_expr_tree_generator.cc +++ b/src/backend/codegen/var_expr_tree_generator.cc @@ -23,7 +23,7 @@ extern "C" { using gpcodegen::VarExprTreeGenerator; using gpcodegen::ExprTreeGenerator; -using gpcodegen::CodegenUtils; +using gpcodegen::GpCodegenUtils; bool VarExprTreeGenerator::VerifyAndCreateExprTree( ExprState* expr_state, @@ -41,7 +41,7 @@ VarExprTreeGenerator::VarExprTreeGenerator(ExprState* expr_state) : ExprTreeGenerator(expr_state, ExprTreeNodeType::kVar) { } -bool VarExprTreeGenerator::GenerateCode(CodegenUtils* codegen_utils, +bool VarExprTreeGenerator::GenerateCode(GpCodegenUtils* codegen_utils, ExprContext* econtext, llvm::Function* llvm_main_func, llvm::BasicBlock* llvm_error_block,