blob: 7944cd018fdb981063f9601daecc11821a79cae2 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License
#include <llvm/IR/Type.h>
#include "gandiva/engine.h"
#include "gandiva/exported_funcs.h"
namespace {
// calculate the number of arguments for a function signature
size_t GetNumArgs(const gandiva::FunctionSignature& sig,
const gandiva::NativeFunction& func) {
auto num_args = 0;
num_args += func.NeedsContext() ? 1 : 0;
num_args += func.NeedsFunctionHolder() ? 1 : 0;
for (const auto& arg : sig.param_types()) {
num_args += arg->id() == arrow::Type::STRING ? 2 : 1;
}
num_args += sig.ret_type()->id() == arrow::Type::STRING ? 1 : 0;
return num_args;
}
// map from a NativeFunction's signature to the corresponding LLVM signature
arrow::Result<std::pair<std::vector<llvm::Type*>, llvm::Type*>> MapToLLVMSignature(
const gandiva::FunctionSignature& sig, const gandiva::NativeFunction& func,
gandiva::LLVMTypes* types) {
std::vector<llvm::Type*> arg_llvm_types;
arg_llvm_types.reserve(GetNumArgs(sig, func));
if (func.NeedsContext()) {
arg_llvm_types.push_back(types->i64_type());
}
if (func.NeedsFunctionHolder()) {
arg_llvm_types.push_back(types->i64_type());
}
for (const auto& arg : sig.param_types()) {
arg_llvm_types.push_back(types->IRType(arg->id()));
if (arg->id() == arrow::Type::STRING) {
// string type needs an additional length argument
arg_llvm_types.push_back(types->i32_type());
}
}
if (sig.ret_type()->id() == arrow::Type::STRING) {
// for string output, the last arg is the output length
arg_llvm_types.push_back(types->i32_ptr_type());
}
auto ret_llvm_type = types->IRType(sig.ret_type()->id());
return std::make_pair(std::move(arg_llvm_types), ret_llvm_type);
}
} // namespace
namespace gandiva {
Status ExternalCFunctions::AddMappings(Engine* engine) const {
const auto& c_funcs = function_registry_->GetCFunctions();
const auto types = engine->types();
for (auto& [func, func_ptr] : c_funcs) {
for (const auto& sig : func.signatures()) {
ARROW_ASSIGN_OR_RAISE(auto llvm_signature, MapToLLVMSignature(sig, func, types));
auto& [args, ret_llvm_type] = llvm_signature;
engine->AddGlobalMappingForFunc(func.pc_name(), ret_llvm_type, args, func_ptr);
}
}
return Status::OK();
}
} // namespace gandiva