There are four possible cases we may generate: 1. Tuple is non-nullable and slot is non-nullable 2. Tuple is non-nullable and slot is nullable 3. Tuple is nullable and slot is non-nullable (when the aggregate output is the "nullable" side of an outer join). 4. Tuple is nullable and slot is nullable Resulting IR for a bigint slotref: (Note: some of the GEPs that look like no-ops are because certai
| 200 | // TODO: We could generate a typed struct (and not a char*) for Tuple for llvm. We know |
| 201 | // the types from the TupleDesc. It will likely make this code simpler to reason about. |
| 202 | Status SlotRef::GetCodegendComputeFnImpl(LlvmCodeGen* codegen, llvm::Function** fn) { |
| 203 | // SlotRefs are based on the slot_id and tuple_idx. Combine them to make a |
| 204 | // query-wide unique id. We also need to combine whether the tuple is nullable. For |
| 205 | // example, in an outer join the scan node could have the same tuple id and slot id |
| 206 | // as the join node. When the slot is being used in the scan-node, the tuple is |
| 207 | // non-nullable. Used in the join node (and above in the plan tree), it is nullable. |
| 208 | // TODO: can we do something better. |
| 209 | constexpr int64_t TUPLE_NULLABLE_MASK = numeric_limits<int64_t>::min(); |
| 210 | int64_t unique_slot_id = slot_id_ | ((int64_t)tuple_idx_) << 32; |
| 211 | DCHECK_EQ(unique_slot_id & TUPLE_NULLABLE_MASK, 0); |
| 212 | if (tuple_is_nullable_) unique_slot_id |= TUPLE_NULLABLE_MASK; |
| 213 | llvm::Function* ir_compute_fn_ = codegen->GetRegisteredExprFn(unique_slot_id); |
| 214 | if (ir_compute_fn_ != NULL) { |
| 215 | *fn = ir_compute_fn_; |
| 216 | return Status::OK(); |
| 217 | } |
| 218 | |
| 219 | llvm::Value* args[2]; |
| 220 | *fn = CreateIrFunctionPrototype("GetSlotRef", codegen, &args); |
| 221 | llvm::Value* eval_ptr = args[0]; |
| 222 | llvm::Value* row_ptr = args[1]; |
| 223 | |
| 224 | LlvmBuilder builder(codegen->context()); |
| 225 | CodegenAnyVal result_value = CodegenValue(codegen, &builder, *fn, eval_ptr, row_ptr); |
| 226 | builder.CreateRet(result_value.GetLoweredValue()); |
| 227 | |
| 228 | *fn = codegen->FinalizeFunction(*fn); |
| 229 | if (UNLIKELY(*fn == NULL)) return Status(TErrorCode::IR_VERIFY_FAILED, "SlotRef"); |
| 230 | codegen->RegisterExprFn(unique_slot_id, *fn); |
| 231 | return Status::OK(); |
| 232 | } |
| 233 | |
| 234 | // Generates null checking code: null checking may be generated for the tuple and for the |
| 235 | // slot based on 'tuple_is_nullable' and 'slot_is_nullable'. If any one of the checks |
nothing calls this directly
no test coverage detected