21 #include "gen-cpp/Exprs_types.h"
26 using namespace impala_udf;
31 SlotRef::SlotRef(
const TExprNode& node)
34 null_indicator_offset_(0, 0),
35 slot_id_(node.slot_ref.slot_id) {
40 :
Expr(desc->type(), true),
42 null_indicator_offset_(0, 0),
43 slot_id_(desc->id()) {
50 null_indicator_offset_(0, 0),
51 slot_id_(desc->id()) {
59 null_indicator_offset_(0, -1),
69 if (slot_desc == NULL) {
72 error <<
"couldn't resolve slot descriptor " <<
slot_id_;
73 LOG(INFO) << error.str();
74 return Status(error.str());
78 error <<
"reference to non-materialized slot " <<
slot_id_;
79 return Status(error.str());
85 LOG(INFO) <<
"invalid idx: " << slot_desc->
DebugString()
89 error <<
"invalid tuple_idx";
90 return Status(error.str());
106 out <<
"SlotRef(slot_id=" <<
slot_id_
158 return Status(
"Codegen for Char not supported.");
175 const int64_t TUPLE_NULLABLE_MASK = 1L << 63;
177 DCHECK_EQ(unique_slot_id & TUPLE_NULLABLE_MASK, 0);
180 if (ir_compute_fn_ != NULL) {
185 LLVMContext& context = codegen->
context();
188 Value* row_ptr = args[1];
191 Value* null_byte_offset =
199 BasicBlock* entry_block = BasicBlock::Create(context,
"entry", *fn);
200 BasicBlock* check_slot_null_indicator_block = NULL;
202 check_slot_null_indicator_block =
203 BasicBlock::Create(context,
"check_slot_null", *fn);
205 BasicBlock* get_slot_block = BasicBlock::Create(context,
"get_slot", *fn);
206 BasicBlock* ret_block = BasicBlock::Create(context,
"ret", *fn);
210 Value* cast_row_ptr = builder.CreateBitCast(
211 row_ptr, PointerType::get(codegen->
ptr_type(), 0),
"cast_row_ptr");
212 Value* tuple_addr = builder.CreateGEP(cast_row_ptr, tuple_offset,
"tuple_addr");
214 Value* tuple_ptr = builder.CreateLoad(tuple_addr,
"tuple_ptr");
218 Value* tuple_is_null = builder.CreateIsNull(tuple_ptr,
"tuple_is_null");
221 builder.CreateCondBr(tuple_is_null, ret_block, get_slot_block);
223 builder.CreateCondBr(tuple_is_null, ret_block, check_slot_null_indicator_block);
227 builder.CreateBr(get_slot_block);
229 builder.CreateBr(check_slot_null_indicator_block);
234 if (check_slot_null_indicator_block != NULL) {
235 builder.SetInsertPoint(check_slot_null_indicator_block);
236 Value* null_addr = builder.CreateGEP(tuple_ptr, null_byte_offset,
"null_ptr");
237 Value* null_val = builder.CreateLoad(null_addr,
"null_byte");
238 Value* slot_null_mask = builder.CreateAnd(null_val, null_mask,
"null_byte_set");
239 Value* is_slot_null = builder.CreateICmpNE(slot_null_mask, zero,
"slot_is_null");
240 builder.CreateCondBr(is_slot_null, ret_block, get_slot_block);
244 builder.SetInsertPoint(get_slot_block);
245 Value* slot_ptr = builder.CreateGEP(tuple_ptr, slot_offset,
"slot_addr");
246 Value* val_ptr = builder.CreateBitCast(slot_ptr, codegen->
GetPtrType(
type_),
"val_ptr");
251 Value* time_of_day = NULL;
254 Value* ptr_ptr = builder.CreateStructGEP(val_ptr, 0,
"ptr_ptr");
255 ptr = builder.CreateLoad(ptr_ptr,
"ptr");
256 Value* len_ptr = builder.CreateStructGEP(val_ptr, 1,
"len_ptr");
257 len = builder.CreateLoad(len_ptr,
"len");
259 Value* time_of_day_ptr = builder.CreateStructGEP(val_ptr, 0,
"time_of_day_ptr");
261 Value* time_of_day_cast =
263 time_of_day = builder.CreateLoad(time_of_day_cast,
"time_of_day");
264 Value* date_ptr = builder.CreateStructGEP(val_ptr, 1,
"date_ptr");
267 date = builder.CreateLoad(date_cast,
"date");
270 val = builder.CreateLoad(val_ptr,
"val");
272 builder.CreateBr(ret_block);
275 builder.SetInsertPoint(ret_block);
276 PHINode* is_null_phi = builder.CreatePHI(codegen->
tinyint_type(), 2,
"is_null_phi");
278 if (check_slot_null_indicator_block != NULL) {
279 is_null_phi->addIncoming(one, check_slot_null_indicator_block);
281 is_null_phi->addIncoming(zero, get_slot_block);
287 if (
type().IsVarLen()) {
290 PHINode* ptr_phi = builder.CreatePHI(ptr->getType(), 2,
"ptr_phi");
291 Value* null = Constant::getNullValue(ptr->getType());
293 ptr_phi->addIncoming(null, entry_block);
295 if (check_slot_null_indicator_block != NULL) {
296 ptr_phi->addIncoming(null, check_slot_null_indicator_block);
298 ptr_phi->addIncoming(ptr, get_slot_block);
300 PHINode* len_phi = builder.CreatePHI(len->getType(), 2,
"len_phi");
301 null = ConstantInt::get(len->getType(), 0);
303 len_phi->addIncoming(null, entry_block);
305 if (check_slot_null_indicator_block != NULL) {
306 len_phi->addIncoming(null, check_slot_null_indicator_block);
308 len_phi->addIncoming(len, get_slot_block);
315 builder.CreateRet(result.
value());
317 DCHECK(time_of_day != NULL);
318 DCHECK(date != NULL);
319 PHINode* time_of_day_phi =
320 builder.CreatePHI(time_of_day->getType(), 2,
"time_of_day_phi");
321 Value* null = ConstantInt::get(time_of_day->getType(), 0);
323 time_of_day_phi->addIncoming(null, entry_block);
325 if (check_slot_null_indicator_block != NULL) {
326 time_of_day_phi->addIncoming(null, check_slot_null_indicator_block);
328 time_of_day_phi->addIncoming(time_of_day, get_slot_block);
330 PHINode* date_phi = builder.CreatePHI(date->getType(), 2,
"date_phi");
331 null = ConstantInt::get(date->getType(), 0);
333 date_phi->addIncoming(null, entry_block);
335 if (check_slot_null_indicator_block != NULL) {
336 date_phi->addIncoming(null, check_slot_null_indicator_block);
338 date_phi->addIncoming(date, get_slot_block);
345 builder.CreateRet(result.
value());
348 PHINode* val_phi = builder.CreatePHI(val->getType(), 2,
"val_phi");
349 Value* null = Constant::getNullValue(val->getType());
351 val_phi->addIncoming(null, entry_block);
353 if (check_slot_null_indicator_block != NULL) {
354 val_phi->addIncoming(null, check_slot_null_indicator_block);
356 val_phi->addIncoming(val, get_slot_block);
362 builder.CreateRet(result.
value());
367 ir_compute_fn_ = *fn;
426 result.
ptr =
reinterpret_cast<uint8_t*
>(
459 return DecimalVal::null();
virtual impala_udf::BooleanVal GetBooleanVal(ExprContext *context, TupleRow *)
llvm::Function * ir_compute_fn_
Cached codegened compute function. Exprs should set this in GetCodegendComputeFn().
std::string DebugString() const
virtual impala_udf::SmallIntVal GetSmallIntVal(ExprContext *context, TupleRow *)
llvm::PointerType * GetPtrType(llvm::Type *type)
Return a pointer type to 'type'.
Tuple * GetTuple(int tuple_idx)
void SetLen(llvm::Value *len)
virtual Status GetCodegendComputeFn(RuntimeState *state, llvm::Function **fn)
virtual impala_udf::TimestampVal GetTimestampVal(ExprContext *context, TupleRow *)
A tuple with 0 materialised slots is represented as NULL.
void SetIsNull(llvm::Value *is_null)
Sets the 'is_null' field of the *Val.
virtual impala_udf::IntVal GetIntVal(ExprContext *context, TupleRow *)
virtual impala_udf::FloatVal GetFloatVal(ExprContext *context, TupleRow *)
#define RETURN_IF_ERROR(stmt)
some generally useful macros
virtual impala_udf::TinyIntVal GetTinyIntVal(ExprContext *context, TupleRow *)
void SetVal(llvm::Value *val)
void * GetSlot(int offset)
This object has a compatible storage format with boost::ptime.
const NullIndicatorOffset & null_indicator_offset() const
void SetDate(llvm::Value *date)
Setters for TimestampVals.
TupleDescriptor * GetTupleDescriptor(TupleId id) const
bool TupleIsNullable(int tuple_idx) const
Return true if the Tuple of the given Tuple index is nullable.
static CodegenAnyVal GetNonNullVal(LlvmCodeGen *codegen, LlvmCodeGen::LlvmBuilder *builder, const ColumnType &type, const char *name="")
static const int INVALID_IDX
virtual impala_udf::StringVal GetStringVal(ExprContext *context, TupleRow *)
bool IsNull(const NullIndicatorOffset &offset) const
void ToTimestampVal(impala_udf::TimestampVal *tv) const
LLVM code generator. This is the top level object to generate jitted code.
virtual impala_udf::DoubleVal GetDoubleVal(ExprContext *context, TupleRow *)
llvm::Function * CreateIrFunctionPrototype(LlvmCodeGen *codegen, const std::string &name, llvm::Value *(*args)[2])
bool IsStringType() const
void RegisterExprFn(int64_t id, llvm::Function *function)
NullIndicatorOffset null_indicator_offset_
void SetPtr(llvm::Value *ptr)
Setters for StringVals.
void SetTimeOfDay(llvm::Value *time_of_day)
int GetByteSize() const
Returns the byte size of this type. Returns 0 for variable length types.
int len
Only set if type == TYPE_CHAR or type == TYPE_VARCHAR.
std::string DebugString() const
This is the superclass of all expr evaluation nodes.
SlotRef(const TExprNode &node)
const DescriptorTbl & desc_tbl() const
int GetTupleIdx(TupleId id) const
Returns INVALID_IDX if id not part of this row.
const RowDescriptor & row_desc() const
llvm::Type * tinyint_type()
const ColumnType & type() const
llvm::Value * value()
Returns the current type-lowered value.
SlotDescriptor * GetSlotDescriptor(SlotId id) const
virtual int GetSlotIds(std::vector< SlotId > *slot_ids) const
static char * CharSlotToPtr(void *slot, const ColumnType &type)
virtual impala_udf::BigIntVal GetBigIntVal(ExprContext *context, TupleRow *)
llvm::Type * GetType(const ColumnType &type)
Returns llvm type for the column type.
uint8_t offset[7 *64-sizeof(uint64_t)]
std::string DebugString() const
Status GetCodegen(LlvmCodeGen **codegen, bool initialize=true)
const ColumnType type_
analysis is done, types are fixed at this point
llvm::Function * GetRegisteredExprFn(int64_t id)
Returns a registered expr function for id or NULL if it does not exist.
llvm::Function * FinalizeFunction(llvm::Function *function)
bool is_materialized() const
virtual Status Prepare(RuntimeState *state, const RowDescriptor &row_desc, ExprContext *context)
std::vector< Expr * > children_
virtual impala_udf::DecimalVal GetDecimalVal(ExprContext *context, TupleRow *)
void ToStringVal(impala_udf::StringVal *sv) const
virtual std::string DebugString() const
llvm::LLVMContext & context()
virtual std::string DebugString() const
int GetNumChildren() const
llvm::PointerType * ptr_type()