Permalink
Browse files

llvm function support

  • Loading branch information...
lixupeng authored and apavlo committed Sep 5, 2017
1 parent 5d27bf9 commit 8666f36033f2371760c751b8e6034826f633bb5f
View
@@ -106,6 +106,21 @@ llvm::Value *CodeGen::CallPrintf(const std::string &format,
return CallFunc(printf_fn, printf_args);
}
llvm::Value *CodeGen::CallStrlen(llvm::Value *str) {
auto *strlen_fn = LookupBuiltin("strlen");
if (strlen_fn == nullptr) {
strlen_fn = RegisterBuiltin(
"strlen", llvm::TypeBuilder<int(const char *), false>::get(GetContext()),
reinterpret_cast<void *>(strlen));
}
// Collect all the arguments into a vector
std::vector<llvm::Value *> strlen_args{str};
// Call the function
return CallFunc(strlen_fn, strlen_args);
}
llvm::Value *CodeGen::CallAddWithOverflow(llvm::Value *left, llvm::Value *right,
llvm::Value *&overflow_bit) {
PL_ASSERT(left->getType() == right->getType());
@@ -1,6 +1,7 @@
#include "codegen/expression/function_translator.h"
#include "codegen/type/sql_type.h"
#include "expression/function_expression.h"
#include "codegen/proxy/function_wrapper_proxy.h"
namespace peloton {
namespace codegen {
@@ -13,7 +14,76 @@ FunctionTranslator::FunctionTranslator(
codegen::Value FunctionTranslator::DeriveValue(
CodeGen &codegen, RowBatch::Row &row) const {
const auto &func_expr = GetExpressionAs<expression::FunctionExpression>();
func_expr->
// get the number of arguments
size_t child_num = func_expr.GetChildrenSize();
std::vector<llvm::Value*> args;
// store function pointer
args.push_back(codegen.Const64((int64_t)func_expr.func_ptr_));
// store argument number
args.push_back(codegen.Const32((int32_t) child_num));
// store arguments
for (size_t i = 0; i < child_num; ++i) {
args.push_back(codegen.Const32(
static_cast<int32_t>(func_expr.func_arg_types_[i])));
args.push_back(row.DeriveValue(codegen, *func_expr.GetChild(i))
.GetValue());
}
return CallWrapperFunction(func_expr.GetValueType(), args, codegen);
}
codegen::Value FunctionTranslator::CallWrapperFunction(
peloton::type::TypeId ret_type,
std::vector<llvm::Value*> &args,
CodeGen &codegen) const {
llvm::Function *wrapper = nullptr;
std::vector<llvm::Type *> arg_types{codegen.Int32Type()};
// get the wrapper function with certain return type
switch (ret_type) {
case peloton::type::TypeId::TINYINT:
wrapper = FunctionWrapperProxy::TinyIntWrapper.GetFunction(codegen);
break;
case peloton::type::TypeId::SMALLINT:
wrapper = FunctionWrapperProxy::SmallIntWrapper.GetFunction(codegen);
break;
case peloton::type::TypeId::INTEGER:
wrapper = FunctionWrapperProxy::IntegerWrapper.GetFunction(codegen);
break;
case peloton::type::TypeId::BIGINT:
wrapper = FunctionWrapperProxy::BigIntWrapper.GetFunction(codegen);
break;
case peloton::type::TypeId::DECIMAL:
wrapper = FunctionWrapperProxy::DecimalWrapper.GetFunction(codegen);
break;
case peloton::type::TypeId::DATE:
wrapper = FunctionWrapperProxy::DateWrapper.GetFunction(codegen);
break;
case peloton::type::TypeId::TIMESTAMP:
wrapper = FunctionWrapperProxy::TimestampWrapper.GetFunction(codegen);
break;
case peloton::type::TypeId::VARCHAR:
wrapper = FunctionWrapperProxy::VarcharWrapper.GetFunction(codegen);
break;
default:
break;
}
if (wrapper != nullptr) {
// call the function
llvm::Value *ret_val = codegen.CallFunc(wrapper, args);
// call strlen to get the length of a varchar
llvm::Value *ret_len = nullptr;
if (ret_type == peloton::type::TypeId::VARCHAR) {
ret_len = codegen.CallStrlen(ret_val);
}
return codegen::Value(type::SqlType::LookupType(ret_type), ret_val, ret_len);
}
else {
return codegen::Value(type::SqlType::LookupType(ret_type));
}
}
} // namespace codegen
@@ -0,0 +1,132 @@
#include <stdarg.h>
#include "codegen/function_wrapper.h"
#include "type/value_factory.h"
#include "type/ephemeral_pool.h"
namespace peloton {
namespace codegen {
inline std::vector<peloton::type::Value> GetArguments(
int n_args, va_list &ap) {
std::vector<peloton::type::Value> args;
for (int i = 0; i < n_args; ++i) {
peloton::type::TypeId type_id = peloton::type::TypeId(va_arg(ap, int32_t));
switch (type_id) {
case peloton::type::TypeId::TINYINT:
args.push_back(peloton::type::ValueFactory::GetTinyIntValue(
va_arg(ap, int32_t)
));
break;
case peloton::type::TypeId::SMALLINT:
args.push_back(peloton::type::ValueFactory::GetSmallIntValue(
va_arg(ap, int32_t)
));
break;
case peloton::type::TypeId::INTEGER:
args.push_back(peloton::type::ValueFactory::GetIntegerValue(
va_arg(ap, int32_t)
));
break;
case peloton::type::TypeId::BIGINT:
args.push_back(peloton::type::ValueFactory::GetBigIntValue(
va_arg(ap, int64_t)
));
break;
case peloton::type::TypeId::DECIMAL:
args.push_back(peloton::type::ValueFactory::GetDecimalValue(
va_arg(ap, double)
));
break;
case peloton::type::TypeId::DATE:
args.push_back(peloton::type::ValueFactory::GetDateValue(
va_arg(ap, int32_t)
));
break;
case peloton::type::TypeId::TIMESTAMP:
args.push_back(peloton::type::ValueFactory::GetTimestampValue(
va_arg(ap, int64_t)
));
break;
case peloton::type::TypeId::VARCHAR:
args.push_back(peloton::type::ValueFactory::GetVarcharValue(
va_arg(ap, const char*)
));
break;
default:
args.push_back(peloton::type::ValueFactory::GetNullValueByType(type_id));
break;
}
}
return args;
}
int8_t FunctionWrapper::TinyIntWrapper(int64_t func, int n_args, ...) {
va_list ap;
va_start(ap, n_args);
std::vector<peloton::type::Value> args = GetArguments(n_args, ap);
peloton::type::Value ret = ((BuiltInFuncType)func)(args);
return ret.GetAs<int8_t>();
}
int16_t FunctionWrapper::SmallIntWrapper(int64_t func, int n_args, ...) {
va_list ap;
va_start(ap, n_args);
std::vector<peloton::type::Value> args = GetArguments(n_args, ap);
peloton::type::Value ret = ((BuiltInFuncType)func)(args);
return ret.GetAs<int16_t>();
}
int32_t FunctionWrapper::IntegerWrapper(int64_t func, int n_args, ...) {
va_list ap;
va_start(ap, n_args);
std::vector<peloton::type::Value> args = GetArguments(n_args, ap);
peloton::type::Value ret = ((BuiltInFuncType)func)(args);
return ret.GetAs<int32_t>();
}
int64_t FunctionWrapper::BigIntWrapper(int64_t func, int n_args, ...) {
va_list ap;
va_start(ap, n_args);
std::vector<peloton::type::Value> args = GetArguments(n_args, ap);
peloton::type::Value ret = ((BuiltInFuncType)func)(args);
return ret.GetAs<int64_t>();
}
double FunctionWrapper::DecimalWrapper(int64_t func, int n_args, ...) {
va_list ap;
va_start(ap, n_args);
std::vector<peloton::type::Value> args = GetArguments(n_args, ap);
peloton::type::Value ret = ((BuiltInFuncType)func)(args);
return ret.GetAs<double>();
}
int32_t FunctionWrapper::DateWrapper(int64_t func, int n_args, ...) {
va_list ap;
va_start(ap, n_args);
std::vector<peloton::type::Value> args = GetArguments(n_args, ap);
peloton::type::Value ret = ((BuiltInFuncType)func)(args);
return ret.GetAs<int32_t>();
}
int64_t FunctionWrapper::TimestampWrapper(int64_t func, int n_args, ...) {
va_list ap;
va_start(ap, n_args);
std::vector<peloton::type::Value> args = GetArguments(n_args, ap);
peloton::type::Value ret = ((BuiltInFuncType)func)(args);
return ret.GetAs<int64_t>();
}
const char* FunctionWrapper::VarcharWrapper(int64_t func, int n_args, ...) {
// TODO: put this pool to a proper place
static type::EphemeralPool pool;
va_list ap;
va_start(ap, n_args);
std::vector<peloton::type::Value> args = GetArguments(n_args, ap);
peloton::type::Value ret = ((BuiltInFuncType)func)(args);
char* str = static_cast<char*>(pool.Allocate(ret.GetLength()));
strcpy(str, ret.GetData());
return str;
}
}
}
@@ -0,0 +1,16 @@
#include "codegen/proxy/function_wrapper_proxy.h"
namespace peloton {
namespace codegen {
DEFINE_METHOD(peloton::codegen, FunctionWrapper, TinyIntWrapper);
DEFINE_METHOD(peloton::codegen, FunctionWrapper, SmallIntWrapper);
DEFINE_METHOD(peloton::codegen, FunctionWrapper, IntegerWrapper);
DEFINE_METHOD(peloton::codegen, FunctionWrapper, BigIntWrapper);
DEFINE_METHOD(peloton::codegen, FunctionWrapper, DecimalWrapper);
DEFINE_METHOD(peloton::codegen, FunctionWrapper, DateWrapper);
DEFINE_METHOD(peloton::codegen, FunctionWrapper, TimestampWrapper);
DEFINE_METHOD(peloton::codegen, FunctionWrapper, VarcharWrapper);
} // namespace codegen
} // namespace peloton
@@ -28,13 +28,12 @@
#include "codegen/expression/tuple_value_translator.h"
#include "codegen/expression/function_translator.h"
#include "expression/case_expression.h"
#include "expression/comparison_expression.h"
#include "expression/conjunction_expression.h"
#include "expression/constant_value_expression.h"
#include "expression/operator_expression.h"
#include "expression/tuple_value_expression.h"
#include "expression/aggregate_expression.h"
#include "planner/aggregate_plan.h"
#include "expression/function_expression.h"
#include "planner/delete_plan.h"
#include "planner/hash_join_plan.h"
#include "planner/order_by_plan.h"
@@ -98,6 +98,8 @@ class CodeGen {
llvm::Value *CallPrintf(const std::string &format,
const std::vector<llvm::Value *> &args);
llvm::Value *CallStrlen(llvm::Value *str);
//===--------------------------------------------------------------------===//
// Arithmetic with overflow logic - These methods perform the desired math op,
// on the provided left and right argument and return the result of the op
@@ -1,6 +1,8 @@
#pragma once
#include "codegen/expression/expression_translator.h"
#include "codegen/function_wrapper.h"
#include <unordered_set>
namespace peloton {
@@ -22,6 +24,11 @@ class FunctionTranslator : public ExpressionTranslator {
// Return the result of the function call
codegen::Value DeriveValue(CodeGen &codegen,
RowBatch::Row &row) const override;
private:
codegen::Value CallWrapperFunction(
peloton::type::TypeId ret_type,
std::vector<llvm::Value*> &args,
CodeGen &codegen) const;
};
} // namespace codegen
@@ -0,0 +1,23 @@
#pragma once
#include "type/types.h"
#include "type/value.h"
namespace peloton {
namespace codegen {
class FunctionWrapper {
typedef peloton::type::Value (*BuiltInFuncType)(const std::vector<peloton::type::Value> &);
public:
static int8_t TinyIntWrapper(int64_t func, int n_args, ...);
static int16_t SmallIntWrapper(int64_t func, int n_args, ...);
static int32_t IntegerWrapper(int64_t func, int n_args, ...);
static int64_t BigIntWrapper(int64_t func, int n_args, ...);
static double DecimalWrapper(int64_t func, int n_args, ...);
static int32_t DateWrapper(int64_t func, int n_args, ...);
static int64_t TimestampWrapper(int64_t func, int n_args, ...);
static const char *VarcharWrapper(int64_t func, int n_args, ...);
};
}
}
@@ -0,0 +1,22 @@
#pragma once
#include "codegen/function_wrapper.h"
#include "codegen/proxy/proxy.h"
#include "codegen/proxy/type_builder.h"
namespace peloton {
namespace codegen {
PROXY(FunctionWrapper) {
DECLARE_METHOD(TinyIntWrapper);
DECLARE_METHOD(SmallIntWrapper);
DECLARE_METHOD(IntegerWrapper);
DECLARE_METHOD(BigIntWrapper);
DECLARE_METHOD(DecimalWrapper);
DECLARE_METHOD(DateWrapper);
DECLARE_METHOD(TimestampWrapper);
DECLARE_METHOD(VarcharWrapper);
};
} // namespace codegen
} // namespace peloton
@@ -182,6 +182,11 @@ struct MemFn<R (*)(Args...), T, F> {
static void *Get() { return reinterpret_cast<void *>(F); }
};
template <typename R, typename... Args, typename T, T F>
struct MemFn<R (*)(Args..., ...), T, F> {
static void *Get() { return reinterpret_cast<void *>(F); }
};
} // namespace detail
} // namespace proxy
@@ -103,6 +103,28 @@ struct TypeBuilder<Ret (*)(Args...)> {
}
};
/// Regular C-style functions with variable arguments
template <typename Ret, typename... Args>
struct TypeBuilder<Ret(Args..., ...)> {
static llvm::Type *GetType(CodeGen &codegen) ALWAYS_INLINE {
llvm::Type *ret_type = TypeBuilder<Ret>::GetType(codegen);
std::vector<llvm::Type *> arg_types = {
TypeBuilder<Args>::GetType(codegen)...};
return llvm::FunctionType::get(ret_type, arg_types, true);
}
};
/// C-style function pointer with variable arguments
template <typename Ret, typename... Args>
struct TypeBuilder<Ret (*)(Args..., ...)> {
static llvm::Type *GetType(CodeGen &codegen) ALWAYS_INLINE {
llvm::Type *ret_type = TypeBuilder<Ret>::GetType(codegen);
std::vector<llvm::Type *> arg_types = {
TypeBuilder<Args>::GetType(codegen)...};
return llvm::FunctionType::get(ret_type, arg_types, true)->getPointerTo();
}
};
/// Member functions
template <typename R, typename T, typename... Args>
struct TypeBuilder<R (T::*)(Args...)> {
Oops, something went wrong.

0 comments on commit 8666f36

Please sign in to comment.