//===----------------------------------------------------------------------===// // Here, we discover the layout of every column that will be accessed. A // column's layout includes three pieces of information: // // 1. The starting memory address (where the first value of the column is) // 2. The stride length // 3. Whether the column is in columnar layout //===----------------------------------------------------------------------===// std::vector<TileGroup::ColumnLayout> TileGroup::GetColumnLayouts( CodeGen &codegen, llvm::Value *tile_group_ptr, llvm::Value *column_layout_infos) const { // Call RuntimeFunctions::GetTileGroupLayout() uint32_t num_cols = schema_.GetColumnCount(); codegen.Call( RuntimeFunctionsProxy::GetTileGroupLayout, {tile_group_ptr, column_layout_infos, codegen.Const32(num_cols)}); // Collect <start, stride, is_columnar> triplets of all columns std::vector<TileGroup::ColumnLayout> layouts; auto *layout_type = ColumnLayoutInfoProxy::GetType(codegen); for (uint32_t col_id = 0; col_id < num_cols; col_id++) { auto *start = codegen->CreateLoad(codegen->CreateConstInBoundsGEP2_32( layout_type, column_layout_infos, col_id, 0)); auto *stride = codegen->CreateLoad(codegen->CreateConstInBoundsGEP2_32( layout_type, column_layout_infos, col_id, 1)); auto *columnar = codegen->CreateLoad(codegen->CreateConstInBoundsGEP2_32( layout_type, column_layout_infos, col_id, 2)); layouts.push_back(ColumnLayout{col_id, start, stride, columnar}); } return layouts; }
codegen::Value Sorter::SorterAccess::LoadRowValue( CodeGen &codegen, Sorter::SorterAccess::Row &row, uint32_t column_index) const { if (row.row_pos_ == nullptr) { auto *addr = codegen->CreateInBoundsGEP(codegen.CharPtrType(), start_pos_, row.row_idx_); row.row_pos_ = codegen->CreateLoad(addr); } const auto &storage_format = sorter_.GetStorageFormat(); UpdateableStorage::NullBitmap null_bitmap(codegen, storage_format, row.row_pos_); return storage_format.GetValue(codegen, row.row_pos_, column_index, null_bitmap); }
// Load a given column for the row with the given TID codegen::Value TileGroup::LoadColumn( CodeGen &codegen, llvm::Value *tid, const TileGroup::ColumnLayout &layout) const { // We're calculating: col[tid] = col_start + (tid * col_stride) llvm::Value *col_address = codegen->CreateInBoundsGEP(codegen.ByteType(), layout.col_start_ptr, codegen->CreateMul(tid, layout.col_stride)); // The value, length and is_null check llvm::Value *val = nullptr, *length = nullptr, *is_null = nullptr; // Column metadata bool is_nullable = schema_.AllowNull(layout.col_id); const auto &column = schema_.GetColumn(layout.col_id); const auto &sql_type = type::SqlType::LookupType(column.GetType()); // Check if it's a string or numeric value if (sql_type.IsVariableLength()) { auto *varlen_type = VarlenProxy::GetType(codegen); auto *varlen_ptr_ptr = codegen->CreateBitCast( col_address, varlen_type->getPointerTo()->getPointerTo()); if (is_nullable) { codegen::Varlen::GetPtrAndLength( codegen, codegen->CreateLoad(varlen_ptr_ptr), val, length, is_null); } else { codegen::Varlen::SafeGetPtrAndLength( codegen, codegen->CreateLoad(varlen_ptr_ptr), val, length); } PL_ASSERT(val != nullptr && length != nullptr); } else { // Get the LLVM type of the column llvm::Type *col_type = nullptr, *col_len_type = nullptr; sql_type.GetTypeForMaterialization(codegen, col_type, col_len_type); PL_ASSERT(col_type != nullptr && col_len_type == nullptr); // val = *(col_type*)col_address; val = codegen->CreateLoad( col_type, codegen->CreateBitCast(col_address, col_type->getPointerTo())); if (is_nullable) { // To check for NULL, we need to perform a comparison between the value we // just read from the table with the NULL value for the column's type. We // need to be careful that the runtime type of both values is not NULL to // bypass the type system's NULL checking logic. if (sql_type.TypeId() == peloton::type::TypeId::BOOLEAN) { is_null = type::Boolean::Instance().CheckNull(codegen, col_address); } else { auto val_tmp = codegen::Value{sql_type, val}; auto null_val = codegen::Value{sql_type, sql_type.GetNullValue(codegen).GetValue()}; auto val_is_null = val_tmp.CompareEq(codegen, null_val); PL_ASSERT(!val_is_null.IsNullable()); is_null = val_is_null.GetValue(); } } } // Names val->setName(column.GetName()); if (length != nullptr) length->setName(column.GetName() + ".len"); if (is_null != nullptr) is_null->setName(column.GetName() + ".null"); // Return the value auto type = type::Type{column.GetType(), is_nullable}; return codegen::Value{type, val, length, is_null}; }
// Pull out the 'start_pos_' instance member from the provided Sorter instance llvm::Value *Sorter::GetStartPosition(CodeGen &codegen, llvm::Value *sorter_ptr) const { auto *sorter_type = SorterProxy::GetType(codegen); return codegen->CreateLoad( codegen->CreateConstInBoundsGEP2_32(sorter_type, sorter_ptr, 0, 0)); }
llvm::Value *Sorter::GetNumberOfStoredTuples(CodeGen &codegen, llvm::Value *sorter_ptr) const { auto *sorter_type = SorterProxy::GetType(codegen); return codegen->CreateLoad( codegen->CreateConstInBoundsGEP2_32(sorter_type, sorter_ptr, 0, 3)); }