17 #include <llvm/ExecutionEngine/ExecutionEngine.h>
18 #include <llvm/PassManager.h>
19 #include <llvm/Transforms/Scalar.h>
20 #include <llvm/Transforms/Utils/BasicBlockUtils.h>
21 #include <llvm/Transforms/Utils/UnrollLoop.h>
22 #include <llvm/Support/InstIterator.h>
23 #include <thrift/protocol/TDebugProtocol.h>
54 #include "gen-cpp/Exprs_types.h"
55 #include "gen-cpp/Data_types.h"
62 #include "gen-cpp/Exprs_types.h"
63 #include "gen-cpp/ImpalaService_types.h"
67 using namespace impala;
68 using namespace impala_udf;
75 istringstream stream(str);
77 return !stream.fail();
81 int varargs_buffer_size) {
83 vector<FunctionContext::TypeDesc> arg_types;
84 for (
int i = 0; i < children_.size(); ++i) {
87 context_index_ = ctx->
Register(state, return_type, arg_types, varargs_buffer_size);
93 is_slotref_(is_slotref),
97 ir_compute_fn_(NULL) {
101 : cache_entry_(NULL),
102 is_slotref_(is_slotref),
106 ir_compute_fn_(NULL) {
107 if (node.__isset.fn)
fn_ = node.fn;
116 for (
int i = 0; i <
children_.size(); ++i) {
117 children_[i]->Close(state, context, scope);
120 if (scope == FunctionContext::FRAGMENT_LOCAL) {
131 if (texpr.nodes.size() == 0) {
138 if (status.
ok() && node_idx + 1 != texpr.nodes.size()) {
140 "Expression tree only partially reconstructed. Not all thrift nodes were used.");
143 LOG(ERROR) <<
"Could not construct expr tree.\n" << status.
GetDetail() <<
"\n"
144 << apache::thrift::ThriftDebugString(texpr);
150 vector<ExprContext*>* ctxs) {
152 for (
int i = 0; i < texprs.size(); ++i) {
155 ctxs->push_back(ctx);
163 if (*node_idx >= nodes.size()) {
164 return Status(
"Failed to reconstruct expression tree from thrift.");
166 int num_children = nodes[*node_idx].num_children;
169 DCHECK(expr != NULL);
170 if (parent != NULL) {
173 DCHECK(root_expr != NULL);
178 for (
int i = 0; i < num_children; i++) {
183 if (*node_idx >= nodes.size()) {
184 return Status(
"Failed to reconstruct expression tree from thrift.");
191 switch (texpr_node.node_type) {
192 case TExprNodeType::BOOL_LITERAL:
193 case TExprNodeType::FLOAT_LITERAL:
194 case TExprNodeType::INT_LITERAL:
195 case TExprNodeType::STRING_LITERAL:
196 case TExprNodeType::DECIMAL_LITERAL:
199 case TExprNodeType::CASE_EXPR:
200 if (!texpr_node.__isset.case_expr) {
201 return Status(
"Case expression not set in thrift node");
205 case TExprNodeType::COMPOUND_PRED:
206 if (texpr_node.fn.name.function_name ==
"and") {
208 }
else if (texpr_node.fn.name.function_name ==
"or") {
211 DCHECK_EQ(texpr_node.fn.name.function_name,
"not");
215 case TExprNodeType::NULL_LITERAL:
218 case TExprNodeType::SLOT_REF:
219 if (!texpr_node.__isset.slot_ref) {
220 return Status(
"Slot reference not set in thrift node");
224 case TExprNodeType::TUPLE_IS_NULL_PRED:
227 case TExprNodeType::FUNCTION_CALL:
228 if (!texpr_node.__isset.fn) {
229 return Status(
"Function not set in thrift node");
233 if (texpr_node.fn.name.function_name ==
"if") {
234 *expr = pool->
Add(
new IfExpr(texpr_node));
235 }
else if (texpr_node.fn.name.function_name ==
"nullif") {
237 }
else if (texpr_node.fn.name.function_name ==
"isnull" ||
238 texpr_node.fn.name.function_name ==
"ifnull" ||
239 texpr_node.fn.name.function_name ==
"nvl") {
241 }
else if (texpr_node.fn.name.function_name ==
"coalesce") {
244 }
else if (texpr_node.fn.binary_type == TFunctionBinaryType::HIVE) {
252 os <<
"Unknown expr node type: " << texpr_node.node_type;
272 int* var_result_begin) {
273 if (exprs.size() == 0) {
274 *var_result_begin = -1;
278 vector<MemLayoutData> data;
279 data.resize(exprs.size());
282 for (
int i = 0; i < exprs.size(); ++i) {
283 data[i].expr_idx = i;
285 data[i].byte_size = 16;
286 data[i].variable_length =
true;
288 data[i].byte_size = exprs[i]->type().GetByteSize();
289 data[i].variable_length =
false;
291 DCHECK_NE(data[i].byte_size, 0);
294 sort(data.begin(), data.end());
297 int max_alignment =
sizeof(int64_t);
298 int current_alignment = data[0].byte_size;
301 offsets->resize(exprs.size());
303 *var_result_begin = -1;
305 for (
int i = 0; i < data.size(); ++i) {
306 DCHECK_GE(data[i].byte_size, current_alignment);
310 !exprs[data[i].expr_idx]->
type().IsVarLen()) {
313 current_alignment = (data[i].byte_size + current_alignment) % max_alignment;
314 }
else if (data[i].byte_size != current_alignment &&
315 current_alignment != max_alignment) {
316 byte_offset += data[i].byte_size - current_alignment;
317 current_alignment = min(data[i].byte_size, max_alignment);
319 (*offsets)[data[i].expr_idx] = byte_offset;
320 if (data[i].variable_length && *var_result_begin == -1) {
321 *var_result_begin = byte_offset;
323 byte_offset += data[i].byte_size;
330 int* var_result_begin) {
332 for (
int i = 0; i < ctxs.size(); ++i) exprs.push_back(ctxs[i]->root());
337 for (
int i = 0; i < ctxs.size(); ++i) {
338 ctxs[i]->Close(state);
344 for (
int i = 0; i < ctxs.size(); ++i) {
353 for (
int i = 0; i <
children_.size(); ++i) {
360 for (
int i = 0; i < ctxs.size(); ++i) {
368 for (
int i = 0; i <
children_.size(); ++i) {
375 vector<ExprContext*>* new_ctxs) {
376 DCHECK(new_ctxs != NULL);
377 DCHECK(new_ctxs->empty());
378 new_ctxs->resize(ctxs.size());
379 for (
int i = 0; i < ctxs.size(); ++i) {
398 for (
int i = 0; i < exprs.size(); ++i) {
399 out << (i == 0 ?
"" :
" ") << exprs[i]->
DebugString();
407 for (
int i = 0; i < ctxs.size(); ++i) exprs.push_back(ctxs[i]->root());
412 for (
int i = 0; i <
children_.size(); ++i) {
420 for (
int i = 0; i <
children_.size(); ++i) {
429 return codegen->
GetFunction(IRFunction::EXPR_GET_BOOLEAN_VAL);
431 return codegen->
GetFunction(IRFunction::EXPR_GET_TINYINT_VAL);
433 return codegen->
GetFunction(IRFunction::EXPR_GET_SMALLINT_VAL);
435 return codegen->
GetFunction(IRFunction::EXPR_GET_INT_VAL);
437 return codegen->
GetFunction(IRFunction::EXPR_GET_BIGINT_VAL);
439 return codegen->
GetFunction(IRFunction::EXPR_GET_FLOAT_VAL);
441 return codegen->
GetFunction(IRFunction::EXPR_GET_DOUBLE_VAL);
445 return codegen->
GetFunction(IRFunction::EXPR_GET_STRING_VAL);
447 return codegen->
GetFunction(IRFunction::EXPR_GET_TIMESTAMP_VAL);
449 return codegen->
GetFunction(IRFunction::EXPR_GET_DECIMAL_VAL);
451 DCHECK(
false) <<
"Invalid type: " << type.
DebugString();
466 DCHECK(
function != NULL);
540 DCHECK(
false) <<
"Type not implemented: " <<
type();
558 BasicBlock* entry_block =
563 Value* compute_fn_args[] = { this_ptr, args[0], args[1] };
565 codegen, &builder, static_getval_fn, compute_fn_args,
"ret");
566 builder.CreateRet(ret);
575 return BooleanVal::null();
579 return TinyIntVal::null();
583 return SmallIntVal::null();
587 return IntVal::null();
591 return BigIntVal::null();
595 return FloatVal::null();
599 return DoubleVal::null();
603 return StringVal::null();
607 return TimestampVal::null();
611 return DecimalVal::null();
static IntVal Year(FunctionContext *context, const TimestampVal &ts_val)
Functions to extract parts of the timestamp, return integers.
If the UDF ran into an error, the FE throws an exception.
llvm::Function * ir_compute_fn_
Cached codegened compute function. Exprs should set this in GetCodegendComputeFn().
static FunctionContext::TypeDesc ColumnTypeToTypeDesc(const ColumnType &type)
static Status CreateTreeFromThrift(ObjectPool *pool, const std::vector< TExprNode > &nodes, Expr *parent, int *node_idx, Expr **root_expr, ExprContext **ctx)
const std::string GetDetail() const
static TinyIntVal NullIfZero(FunctionContext *context, const TinyIntVal &val)
static impala_udf::BooleanVal InIterate(impala_udf::FunctionContext *context, const impala_udf::BooleanVal &val, int num_args, const impala_udf::BooleanVal *args)
Functions for every type.
virtual IntVal GetIntVal(ExprContext *context, TupleRow *)
llvm::PointerType * GetPtrType(llvm::Type *type)
Return a pointer type to 'type'.
virtual TimestampVal GetTimestampVal(ExprContext *context, TupleRow *)
static void InitNull(FunctionContext *, AnyVal *dst)
Initializes dst to NULL.
virtual int GetSlotIds(std::vector< SlotId > *slot_ids) const
virtual SmallIntVal GetSmallIntVal(ExprContext *context, TupleRow *)
static Status Clone(const std::vector< ExprContext * > &ctxs, RuntimeState *state, std::vector< ExprContext * > *new_ctxs)
Expr(const ColumnType &type, bool is_slotref=false)
Utility struct that wraps a variable name and llvm type.
static Status Open(const std::vector< ExprContext * > &ctxs, RuntimeState *state)
Convenience function for opening multiple expr trees.
static BooleanVal CastToBooleanVal(FunctionContext *context, const TinyIntVal &val)
friend class ScalarFnCall
#define RETURN_IF_ERROR(stmt)
some generally useful macros
static llvm::Value * CreateCall(LlvmCodeGen *cg, LlvmCodeGen::LlvmBuilder *builder, llvm::Function *fn, llvm::ArrayRef< llvm::Value * > args, const char *name="", llvm::Value *result_ptr=NULL)
'name' optionally specifies the name of the returned value.
virtual BooleanVal GetBooleanVal(ExprContext *context, TupleRow *)
virtual DoubleVal GetDoubleVal(ExprContext *context, TupleRow *)
static IntVal Precision(FunctionContext *context, const DecimalVal &val)
static impala_udf::BooleanVal Like(impala_udf::FunctionContext *context, const impala_udf::StringVal &val, const impala_udf::StringVal &pattern)
virtual bool IsConstant() const
This object has a compatible storage format with boost::ptime.
virtual StringVal GetStringVal(ExprContext *context, TupleRow *)
virtual DecimalVal GetDecimalVal(ExprContext *context, TupleRow *)
static void Close(const std::vector< ExprContext * > &ctxs, RuntimeState *state)
Convenience function for closing multiple expr trees.
Expr for evaluating and (&&) operators.
boost::scoped_ptr< AnyVal > constant_val_
static DoubleVal Pi(FunctionContext *)
LLVM code generator. This is the top level object to generate jitted code.
llvm::Function * CreateIrFunctionPrototype(LlvmCodeGen *codegen, const std::string &name, llvm::Value *(*args)[2])
std::string DebugString() const
void AddChild(Expr *expr)
static const char * LLVM_CLASS_NAME
llvm::Function * GeneratePrototype(LlvmBuilder *builder=NULL, llvm::Value **params=NULL)
static const char * LLVM_CLASS_NAME
llvm::Value * CastPtrToLlvmPtr(llvm::Type *type, const void *ptr)
void AddArgument(const NamedVariable &var)
Add argument.
static const char * LLVM_CLASS_NAME
virtual AnyVal * GetConstVal(ExprContext *context)
Status GetCodegendComputeFnWrapper(RuntimeState *state, llvm::Function **fn)
static DoubleVal Pi(FunctionContext *context)
static llvm::Type * GetLoweredType(LlvmCodeGen *cg, const ColumnType &type)
llvm::Function * GetFunction(IRFunction::Type)
LibCache::LibCacheEntry * cache_entry_
Cache entry for the library implementing this function.
This is the superclass of all expr evaluation nodes.
virtual FloatVal GetFloatVal(ExprContext *context, TupleRow *)
static LibCache * instance()
static int ComputeResultsLayout(const std::vector< Expr * > &exprs, std::vector< int > *offsets, int *var_result_begin)
This class is thread-safe.
const RowDescriptor & row_desc() const
static DecimalVal CastToDecimalVal(FunctionContext *, const DecimalVal &)
virtual BigIntVal GetBigIntVal(ExprContext *context, TupleRow *)
static IntVal Length(FunctionContext *, const StringVal &str)
static Status CreateExprTree(ObjectPool *pool, const TExpr &texpr, ExprContext **ctx)
TFunction fn_
Function description.
const ColumnType & type() const
Expr for evaluating or (||) operators.
Reference to a single slot of a tuple.
static void InitBuiltinsDummy()
Status GetCodegen(LlvmCodeGen **codegen, bool initialize=true)
virtual TinyIntVal GetTinyIntVal(ExprContext *context, TupleRow *)
static Status CreateExpr(ObjectPool *pool, const TExprNode &texpr_node, Expr **expr)
Create a new Expr based on texpr_node.node_type within 'pool'.
int Register(RuntimeState *state, const FunctionContext::TypeDesc &return_type, const std::vector< FunctionContext::TypeDesc > &arg_types, int varargs_buffer_size=0)
const ColumnType type_
analysis is done, types are fixed at this point
bool operator<(const MemLayoutData &rhs) const
FunctionContext * fn_context(int i)
bool ParseString(const string &str, T *val)
static Status CreateExprTrees(ObjectPool *pool, const std::vector< TExpr > &texprs, std::vector< ExprContext * > *ctxs)
llvm::Function * FinalizeFunction(llvm::Function *function)
static Status Prepare(const std::vector< ExprContext * > &ctxs, RuntimeState *state, const RowDescriptor &row_desc, MemTracker *tracker)
void DecrementUseCount(LibCacheEntry *entry)
See comment in GetSoFunctionPtr().
std::vector< Expr * > children_
static BooleanVal IsNull(FunctionContext *ctx, const T &val)
llvm::Function * GetStaticGetValWrapper(ColumnType type, LlvmCodeGen *codegen)
llvm::LLVMContext & context()
virtual std::string DebugString() const
static BooleanVal Not(FunctionContext *context, const BooleanVal &)
FunctionContext * RegisterFunctionContext(ExprContext *ctx, RuntimeState *state, int varargs_buffer_size=0)
static IntVal Pid(FunctionContext *ctx)
static IntVal Add_IntVal_IntVal(FunctionContext *, const IntVal &, const IntVal &)