24 #include "gen-cpp/Exprs_types.h"
40 CaseExpr::CaseExpr(
const TExprNode& node)
42 has_case_expr_(node.case_expr.has_case_expr),
43 has_else_expr_(node.case_expr.has_else_expr) {
75 fn_ctx->
Free(reinterpret_cast<uint8_t*>(case_state));
186 Function* child_fns[num_children];
187 for (
int i = 0; i < num_children; ++i) {
193 LLVMContext& context = codegen->
context();
198 BasicBlock* eval_case_expr_block = NULL;
202 BasicBlock* default_value_block = BasicBlock::Create(
203 context,
has_else_expr() ?
"return_else_expr" :
"return_null",
function);
207 BasicBlock* eval_first_when_expr_block = BasicBlock::Create(
208 context,
"eval_first_when_expr",
function, default_value_block);
209 BasicBlock* current_when_expr_block = eval_first_when_expr_block;
215 eval_case_expr_block = BasicBlock::Create(context,
"eval_case_expr",
216 function, eval_first_when_expr_block);
217 builder.SetInsertPoint(eval_case_expr_block);
219 codegen, &builder,
children()[0]->
type(), child_fns[0], args,
"case_val");
220 builder.CreateCondBr(
221 case_val.
GetIsNull(), default_value_block, eval_first_when_expr_block);
226 const int loop_end = (
has_else_expr()) ? num_children - 1 : num_children;
227 const int last_loop_iter = loop_end - 2;
231 for (
int i = (
has_case_expr()) ? 1 : 0; i < loop_end; i += 2) {
232 BasicBlock* check_when_expr_block = BasicBlock::Create(
233 context,
"check_when_expr_block",
function, default_value_block);
234 BasicBlock* return_then_expr_block =
235 BasicBlock::Create(context,
"return_then_expr",
function, default_value_block);
239 BasicBlock* continue_or_exit_block = NULL;
240 if (i == last_loop_iter) {
241 continue_or_exit_block = default_value_block;
243 continue_or_exit_block = BasicBlock::Create(
244 context,
"eval_next_when_expr",
function, default_value_block);
249 builder.SetInsertPoint(current_when_expr_block);
251 codegen, &builder,
children()[i]->
type(), child_fns[i], args,
"when_val");
252 builder.CreateCondBr(
253 when_val.
GetIsNull(), continue_or_exit_block, check_when_expr_block);
255 builder.SetInsertPoint(check_when_expr_block);
258 Value* is_equal = case_val.
Eq(&when_val);
259 builder.CreateCondBr(is_equal, return_then_expr_block, continue_or_exit_block);
261 builder.CreateCondBr(
262 when_val.
GetVal(), return_then_expr_block, continue_or_exit_block);
265 builder.SetInsertPoint(return_then_expr_block);
269 codegen, &builder, child_fns[i+1], args,
"then_val");
270 builder.CreateRet(then_val);
272 current_when_expr_block = continue_or_exit_block;
275 builder.SetInsertPoint(default_value_block);
278 codegen, &builder, child_fns[num_children - 1], args,
"else_val");
279 builder.CreateRet(else_val);
300 children()[child_idx]->GetSmallIntVal(ctx, row);
303 *
reinterpret_cast<IntVal*
>(dst) =
children()[child_idx]->GetIntVal(ctx, row);
306 *
reinterpret_cast<BigIntVal*
>(dst) =
children()[child_idx]->GetBigIntVal(ctx, row);
309 *
reinterpret_cast<FloatVal*
>(dst) =
children()[child_idx]->GetFloatVal(ctx, row);
312 *
reinterpret_cast<DoubleVal*
>(dst) =
children()[child_idx]->GetDoubleVal(ctx, row);
316 children()[child_idx]->GetTimestampVal(ctx, row);
319 *
reinterpret_cast<StringVal*
>(dst) =
children()[child_idx]->GetStringVal(ctx, row);
325 DCHECK(
false) <<
children()[child_idx]->type();
333 *reinterpret_cast<const BooleanVal*>(v2));
336 *reinterpret_cast<const TinyIntVal*>(v2));
339 *reinterpret_cast<const SmallIntVal*>(v2));
342 *reinterpret_cast<const IntVal*>(v2));
345 *reinterpret_cast<const BigIntVal*>(v2));
348 *reinterpret_cast<const FloatVal*>(v2));
351 *reinterpret_cast<const DoubleVal*>(v2));
354 *reinterpret_cast<const TimestampVal*>(v2));
357 *reinterpret_cast<const StringVal*>(v2));
360 *reinterpret_cast<const DecimalVal*>(v2));
362 DCHECK(
false) <<
type;
367 #define CASE_COMPUTE_FN(THEN_TYPE) \
368 THEN_TYPE CaseExpr::Get##THEN_TYPE(ExprContext* ctx, TupleRow* row) { \
369 FunctionContext* fn_ctx = ctx->fn_context(context_index_); \
370 CaseExprState* state = reinterpret_cast<CaseExprState*>( \
371 fn_ctx->GetFunctionState(FunctionContext::THREAD_LOCAL)); \
372 DCHECK(state->case_val != NULL); \
373 DCHECK(state->when_val != NULL); \
374 int num_children = GetNumChildren(); \
375 if (has_case_expr()) { \
378 GetChildVal(0, ctx, row, state->case_val); \
381 *reinterpret_cast<BooleanVal*>(state->case_val) = BooleanVal(true); \
383 if (state->case_val->is_null) { \
384 if (has_else_expr()) { \
386 return children()[num_children - 1]->Get##THEN_TYPE(ctx, row); \
388 return THEN_TYPE::null(); \
391 int loop_start = has_case_expr() ? 1 : 0; \
392 int loop_end = (has_else_expr()) ? num_children - 1 : num_children; \
393 for (int i = loop_start; i < loop_end; i += 2) { \
394 GetChildVal(i, ctx, row, state->when_val); \
395 if (state->when_val->is_null) continue; \
396 if (AnyValEq(children()[0]->type(), state->case_val, state->when_val)) { \
398 return children()[i + 1]->Get##THEN_TYPE(ctx, row); \
401 if (has_else_expr()) { \
403 return children()[num_children - 1]->Get##THEN_TYPE(ctx, row); \
405 return THEN_TYPE::null(); \
AnyVal * CreateAnyVal(ObjectPool *pool, const ColumnType &type)
Creates the corresponding AnyVal subclass for type. The object is added to the pool.
llvm::Function * ir_compute_fn_
Cached codegened compute function. Exprs should set this in GetCodegendComputeFn().
const std::vector< Expr * > & children() const
static CodegenAnyVal CreateCallWrapped(LlvmCodeGen *cg, LlvmCodeGen::LlvmBuilder *builder, const ColumnType &type, llvm::Function *fn, llvm::ArrayRef< llvm::Value * > args, const char *name="", llvm::Value *result_ptr=NULL)
Same as above but wraps the result in a CodegenAnyVal.
llvm::Value * Eq(CodegenAnyVal *other)
Returns the i1 result of this == other. this and other must be non-null.
static Status Open(const std::vector< ExprContext * > &ctxs, RuntimeState *state)
Convenience function for opening multiple expr trees.
const bool has_case_expr_
static bool Equals(const FunctionContext::TypeDesc *type, const T &x, const T &y)
Templated equality functions. These assume the input values are not NULL.
virtual Status Open(RuntimeState *state, ExprContext *context, FunctionContext::FunctionStateScope scope=FunctionContext::FRAGMENT_LOCAL)
#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.
bool AnyValEq(const ColumnType &type, const AnyVal *v1, const AnyVal *v2)
Return true iff *v1 == *v2. v1 and v2 should both be of the specified type.
#define CASE_COMPUTE_FN(THEN_TYPE)
This object has a compatible storage format with boost::ptime.
virtual Status Prepare(RuntimeState *state, const RowDescriptor &row_desc, ExprContext *context)
static void Close(const std::vector< ExprContext * > &ctxs, RuntimeState *state)
Convenience function for closing multiple expr trees.
void GetChildVal(int child_idx, ExprContext *ctx, TupleRow *row, AnyVal *dst)
const bool has_else_expr_
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])
ObjectPool * obj_pool() const
virtual void Close(RuntimeState *state, ExprContext *context, FunctionContext::FunctionStateScope scope=FunctionContext::FRAGMENT_LOCAL)
Subclasses overriding this function should call Expr::Close().
void * GetFunctionState(FunctionStateScope scope) const
void Free(uint8_t *buffer)
Frees a buffer returned from Allocate() or Reallocate()
This is the superclass of all expr evaluation nodes.
void SetFunctionState(FunctionStateScope scope, void *ptr)
const ColumnType & type() const
uint8_t * Allocate(int byte_size)
llvm::Value * GetVal(const char *name="val")
Status GetCodegen(LlvmCodeGen **codegen, bool initialize=true)
virtual Status GetCodegendComputeFn(RuntimeState *state, llvm::Function **fn)
llvm::Value * GetIsNull(const char *name="is_null")
Gets the 'is_null' field of the *Val.
FunctionContext * fn_context(int i)
llvm::Function * FinalizeFunction(llvm::Function *function)
static Status Prepare(const std::vector< ExprContext * > &ctxs, RuntimeState *state, const RowDescriptor &row_desc, MemTracker *tracker)
static llvm::Value * GetNullVal(LlvmCodeGen *codegen, const ColumnType &type)
std::vector< Expr * > children_
llvm::LLVMContext & context()
virtual std::string DebugString() const
int GetNumChildren() const
virtual std::string DebugString() const
FunctionContext * RegisterFunctionContext(ExprContext *ctx, RuntimeState *state, int varargs_buffer_size=0)