2121#include < utility>
2222#include < vector>
2323
24+ #include " arrow/type.h"
2425#include " gandiva/bitmap_accumulator.h"
2526#include " gandiva/decimal_ir.h"
2627#include " gandiva/dex.h"
28+ #include " gandiva/timestamp_ir.h"
2729#include " gandiva/expr_decomposer.h"
2830#include " gandiva/expression.h"
2931#include " gandiva/llvm_types.h"
@@ -384,6 +386,7 @@ Status LLVMGenerator::CodeGenExprValue(DexPtr value_expr, int buffer_count,
384386 Visitor visitor (this , fn, loop_entry, arg_addrs, arg_local_bitmaps, arg_holder_ptrs,
385387 slice_offsets, arg_context_ptr, position_var);
386388 value_expr->Accept (visitor);
389+ ARROW_RETURN_NOT_OK (visitor.status ());
387390 LValuePtr output_value = visitor.result ();
388391
389392 // The "current" block may have changed due to code generation in the visitor.
@@ -813,7 +816,8 @@ void LLVMGenerator::Visitor::Visit(const NonNullableFuncDex& dex) {
813816 auto then_lambda = [&] {
814817 ADD_VISITOR_TRACE (" fn " + function_name +
815818 " can return errors : all args valid, invoke fn" );
816- return BuildFunctionCall (native_function, arrow_return_type, ¶ms);
819+ return BuildFunctionCall (native_function, arrow_return_type, ¶ms,
820+ dex.func_descriptor ());
817821 };
818822
819823 // else block
@@ -831,7 +835,9 @@ void LLVMGenerator::Visitor::Visit(const NonNullableFuncDex& dex) {
831835 result_ = BuildIfElse (is_valid, then_lambda, else_lambda, arrow_return_type);
832836 } else {
833837 // fast path : invoke function without computing validities.
834- result_ = BuildFunctionCall (native_function, arrow_return_type, ¶ms);
838+ result_ = BuildFunctionCall (native_function, arrow_return_type, ¶ms,
839+ dex.func_descriptor ());
840+ if (!status_.ok ()) return ;
835841 }
836842}
837843
@@ -844,7 +850,8 @@ void LLVMGenerator::Visitor::Visit(const NullableNeverFuncDex& dex) {
844850 native_function->NeedsContext ());
845851
846852 auto arrow_return_type = dex.func_descriptor ()->return_type ();
847- result_ = BuildFunctionCall (native_function, arrow_return_type, ¶ms);
853+ result_ = BuildFunctionCall (native_function, arrow_return_type, ¶ms,
854+ dex.func_descriptor ());
848855}
849856
850857void LLVMGenerator::Visitor::Visit (const NullableInternalFuncDex& dex) {
@@ -1084,6 +1091,9 @@ void LLVMGenerator::Visitor::VisitInExpression(const InExprDexBase<Type>& dex) {
10841091 for (auto & pair : dex.args ()) {
10851092 DexPtr value_expr = pair->value_expr ();
10861093 value_expr->Accept (*this );
1094+ if (!status_.ok ()) {
1095+ return ;
1096+ }
10871097 LValue& result_ref = *result ();
10881098 params.push_back (result_ref.data ());
10891099
@@ -1235,6 +1245,9 @@ LValuePtr LLVMGenerator::Visitor::BuildValueAndValidity(const ValueValidityPair&
12351245 // generate code for value
12361246 auto value_expr = pair.value_expr ();
12371247 value_expr->Accept (*this );
1248+ if (!status_.ok ()) {
1249+ return nullptr ;
1250+ }
12381251 auto value = result ()->data ();
12391252 auto length = result ()->length ();
12401253
@@ -1246,12 +1259,44 @@ LValuePtr LLVMGenerator::Visitor::BuildValueAndValidity(const ValueValidityPair&
12461259
12471260LValuePtr LLVMGenerator::Visitor::BuildFunctionCall (const NativeFunction* func,
12481261 DataTypePtr arrow_return_type,
1249- std::vector<llvm::Value*>* params) {
1262+ std::vector<llvm::Value*>* params,
1263+ const FuncDescriptorPtr& descriptor) {
12501264 auto types = generator_->types ();
12511265 auto arrow_return_type_id = arrow_return_type->id ();
12521266 auto llvm_return_type = types->IRType (arrow_return_type_id);
12531267 DecimalIR decimalIR (generator_->engine_ .get ());
12541268
1269+ // Resolve the function name — may remap to a TimestampIR-built variant
1270+ // based on the actual TimeUnit from the expression tree.
1271+ std::string pc_name = func->pc_name ();
1272+ if (descriptor != nullptr ) {
1273+ arrow::TimeUnit::type ts_unit = arrow::TimeUnit::MILLI ;
1274+ bool found_ts = false ;
1275+ for (auto & param : descriptor->params ()) {
1276+ if (param->id () == arrow::Type::TIMESTAMP ) {
1277+ auto unit =
1278+ arrow::internal::checked_cast<const arrow::TimestampType&>(*param).unit ();
1279+ if (!found_ts) {
1280+ ts_unit = unit;
1281+ found_ts = true ;
1282+ } else if (unit != ts_unit) {
1283+ status_ = Status::Invalid (
1284+ " Gandiva cannot compile expression: mixed timestamp units in function '" ,
1285+ pc_name, " '. All timestamp arguments must have the same TimeUnit." );
1286+ return nullptr ;
1287+ }
1288+ }
1289+ }
1290+ if (found_ts && ts_unit != arrow::TimeUnit::MILLI ) {
1291+ std::string suffix = (ts_unit == arrow::TimeUnit::MICRO ) ? " _us" : " _ns" ;
1292+ std::string remapped = pc_name + suffix;
1293+ ARROW_LOG (DEBUG ) << " TimestampIR remap: " << pc_name << " -> " << remapped;
1294+ if (TimestampIR::IsTimestampIRFunction (remapped)) {
1295+ pc_name = remapped;
1296+ }
1297+ }
1298+ }
1299+
12551300 if (arrow_return_type_id == arrow::Type::DECIMAL ) {
12561301 // For decimal fns, the output precision/scale are passed along as parameters.
12571302 //
@@ -1266,7 +1311,7 @@ LValuePtr LLVMGenerator::Visitor::BuildFunctionCall(const NativeFunction* func,
12661311 params->push_back (ret_lvalue->scale ());
12671312
12681313 // Make the function call
1269- auto out = decimalIR.CallDecimalFunction (func-> pc_name () , llvm_return_type, *params);
1314+ auto out = decimalIR.CallDecimalFunction (pc_name, llvm_return_type, *params);
12701315 ret_lvalue->set_data (out);
12711316 return ret_lvalue;
12721317 } else {
@@ -1287,10 +1332,14 @@ LValuePtr LLVMGenerator::Visitor::BuildFunctionCall(const NativeFunction* func,
12871332
12881333 // Make the function call
12891334 llvm::IRBuilder<>* builder = ir_builder ();
1290- auto value =
1291- isDecimalFunction
1292- ? decimalIR.CallDecimalFunction (func->pc_name (), llvm_return_type, *params)
1293- : generator_->AddFunctionCall (func->pc_name (), llvm_return_type, *params);
1335+ llvm::Value* value;
1336+ if (isDecimalFunction) {
1337+ value = decimalIR.CallDecimalFunction (pc_name, llvm_return_type, *params);
1338+ } else if (auto * ir_fn = generator_->engine_ ->module ()->getFunction (pc_name)) {
1339+ value = ir_builder ()->CreateCall (ir_fn, *params);
1340+ } else {
1341+ value = generator_->AddFunctionCall (pc_name, llvm_return_type, *params);
1342+ }
12941343 auto value_len =
12951344 (result_len_ptr == nullptr )
12961345 ? nullptr
0 commit comments