MCPcopy Create free account
hub / github.com/ClickHouse/ClickHouse / compileSortDescription

Function compileSortDescription

src/Interpreters/JIT/compileFunction.cpp:594–763  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

592}
593
594static void compileSortDescription(llvm::Module & module,
595 SortDescription & description,
596 const DataTypes & sort_description_types,
597 const std::string & sort_description_dump)
598{
599 llvm::IRBuilder<> b(module.getContext());
600
601 auto * size_type = b.getIntNTy(sizeof(size_t) * 8);
602
603 auto * column_data_type = buildColumnDataStruct(b);
604
605 std::vector<llvm::Type *> function_argument_types = {size_type, size_type, column_data_type->getPointerTo(), column_data_type->getPointerTo()};
606 auto * comparator_func_declaration = llvm::FunctionType::get(b.getInt8Ty(), function_argument_types, false);
607 auto * comparator_func = llvm::Function::Create(comparator_func_declaration, llvm::Function::ExternalLinkage, sort_description_dump, module);
608 /// The result is read back through an `int8_t (*)(...)` function pointer, so the i8 return
609 /// must obey the C `int8_t` calling convention. This matters only on Darwin/Apple arm64:
610 /// Apple's arm64 ABI makes the *callee* sign-extend sub-word return values and the caller
611 /// relies on it (it emits no `sxtb` after the call). Without `signext` the JIT callee leaves
612 /// the upper bits unset, so e.g. a -1 result is read as 255 and NULL ordering breaks.
613 /// Linux arm64 (AAPCS64) is unaffected because there the *caller* sign-extends the return
614 /// itself (`sxtb w0, w0`); x86-64 is likewise a no-op.
615 comparator_func->addRetAttr(llvm::Attribute::SExt);
616
617 auto * arguments = comparator_func->args().begin();
618 llvm::Value * lhs_index_arg = arguments++;
619 llvm::Value * rhs_index_arg = arguments++;
620 llvm::Value * columns_lhs_arg = arguments++;
621 llvm::Value * columns_rhs_arg = arguments++;
622
623 size_t columns_size = description.size();
624
625 std::vector<std::pair<llvm::BasicBlock *, llvm::Value *>> comparator_steps_and_results;
626 for (size_t i = 0; i < columns_size; ++i)
627 {
628 auto * step = llvm::BasicBlock::Create(b.getContext(), "step_" + std::to_string(i), comparator_func);
629 comparator_steps_and_results.emplace_back(step, nullptr);
630 }
631
632 auto * lhs_equals_rhs_result = llvm::ConstantInt::getSigned(b.getInt8Ty(), 0);
633
634 auto * comparator_join = llvm::BasicBlock::Create(b.getContext(), "comparator_join", comparator_func);
635
636 for (size_t i = 0; i < columns_size; ++i)
637 {
638 b.SetInsertPoint(comparator_steps_and_results[i].first);
639
640 const auto & sort_description = description[i];
641 const auto & column_type = sort_description_types[i];
642 auto nested_column_type = removeNullable(column_type);
643
644 auto dummy_column = column_type->createColumn();
645
646 auto try_load_nullable_value = [&](llvm::Value * value, llvm::Value * nullable_uninitialized, llvm::Value * column_null_data, llvm::Value * index_arg) -> llvm::Value *
647 {
648 if (column_null_data)
649 {
650 auto * is_null_value_pointer = b.CreateInBoundsGEP(b.getInt8Ty(), column_null_data, index_arg);
651 auto * is_null = b.CreateICmpNE(b.CreateLoad(b.getInt8Ty(), is_null_value_pointer), b.getInt8(0));

Callers 1

Calls 15

buildColumnDataStructFunction · 0.85
buildStringRefTypeFunction · 0.85
toNullableTypeFunction · 0.85
buildFixedStringTypeFunction · 0.85
toNativeTypeFunction · 0.85
WhichDataTypeClass · 0.85
isFixedStringMethod · 0.80
getFunction · 0.50
to_stringFunction · 0.50
removeNullableFunction · 0.50
ExceptionClass · 0.50
canBeNativeTypeFunction · 0.50

Tested by

no test coverage detected