mkql_simple_codegen.h 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. #pragma once
  2. namespace NKikimr {
  3. namespace NMiniKQL {
  4. class TMaybeFetchResult final {
  5. ui64 Raw;
  6. explicit TMaybeFetchResult(ui64 raw) : Raw(raw) {}
  7. public:
  8. /* implicit */ TMaybeFetchResult(EFetchResult res) : TMaybeFetchResult(static_cast<ui64>(static_cast<ui32>(res))) {}
  9. [[nodiscard]] bool Empty() const {
  10. return Raw >> ui64(32);
  11. }
  12. [[nodiscard]] EFetchResult Get() const {
  13. Y_ABORT_IF(Empty());
  14. return static_cast<EFetchResult>(static_cast<ui32>(Raw));
  15. }
  16. [[nodiscard]] ui64 RawU64() const {
  17. return Raw;
  18. }
  19. static TMaybeFetchResult None() {
  20. return TMaybeFetchResult(ui64(1) << ui64(32));
  21. }
  22. #ifndef MKQL_DISABLE_CODEGEN
  23. static Type* LLVMType(LLVMContext& context) {
  24. return Type::getInt64Ty(context);
  25. }
  26. static Value* LLVMFromFetchResult(Value *fetchRes, const Twine& name, BasicBlock* block) {
  27. return new ZExtInst(fetchRes, LLVMType(fetchRes->getContext()), name, block);
  28. }
  29. Value* LLVMConst(LLVMContext& context) const {
  30. return ConstantInt::get(LLVMType(context), RawU64());
  31. }
  32. #endif
  33. };
  34. #ifndef MKQL_DISABLE_CODEGEN
  35. using TResultCodegenerator = std::function<ICodegeneratorInlineWideNode::TGenerateResult(const TCodegenContext&, BasicBlock*&)>;
  36. #endif
  37. class TSimpleStatefulWideFlowCodegeneratorNodeLLVMBase {
  38. public:
  39. struct TMethPtrTable {
  40. uintptr_t ThisPtr;
  41. uintptr_t InitStateMethPtr;
  42. uintptr_t PrepareInputMethPtr;
  43. uintptr_t DoProcessMethPtr;
  44. };
  45. TSimpleStatefulWideFlowCodegeneratorNodeLLVMBase(IComputationWideFlowNode* source, ui32 inWidth, ui32 outWidth, TMethPtrTable ptrTable)
  46. : SourceFlow(source), InWidth(inWidth), OutWidth(outWidth)
  47. , PtrTable(ptrTable) {}
  48. #ifndef MKQL_DISABLE_CODEGEN
  49. virtual ICodegeneratorInlineWideNode::TGenerateResult GenFetchProcess(Value* statePtrVal, const TCodegenContext& ctx, const TResultCodegenerator& fetchGenerator, BasicBlock*& block) const {
  50. Y_UNUSED(statePtrVal);
  51. Y_UNUSED(ctx);
  52. Y_UNUSED(fetchGenerator);
  53. Y_UNUSED(block);
  54. return {nullptr, {}};
  55. }
  56. ICodegeneratorInlineWideNode::TGenerateResult DoGenGetValues(const TCodegenContext& ctx, Value* statePtrVal, BasicBlock*& genToBlock) const;
  57. #endif
  58. protected:
  59. IComputationWideFlowNode* const SourceFlow;
  60. const ui32 InWidth, OutWidth;
  61. const TMethPtrTable PtrTable;
  62. };
  63. template<typename TDerived, typename TState, EValueRepresentation StateKind = EValueRepresentation::Embedded>
  64. class TSimpleStatefulWideFlowCodegeneratorNode
  65. : public TStatefulWideFlowCodegeneratorNode<TSimpleStatefulWideFlowCodegeneratorNode<TDerived, TState, StateKind>>
  66. , public TSimpleStatefulWideFlowCodegeneratorNodeLLVMBase {
  67. using TBase = TStatefulWideFlowCodegeneratorNode<TSimpleStatefulWideFlowCodegeneratorNode>;
  68. using TLLVMBase = TSimpleStatefulWideFlowCodegeneratorNodeLLVMBase;
  69. protected:
  70. TSimpleStatefulWideFlowCodegeneratorNode(TComputationMutables& mutables, IComputationWideFlowNode* source, ui32 inWidth, ui32 outWidth)
  71. : TBase(mutables, source, StateKind)
  72. , TLLVMBase(source, inWidth, outWidth, {
  73. .ThisPtr = reinterpret_cast<uintptr_t>(this),
  74. .InitStateMethPtr = GetMethodPtr(&TDerived::InitState),
  75. .PrepareInputMethPtr = GetMethodPtr(&TDerived::PrepareInput),
  76. .DoProcessMethPtr = GetMethodPtr(&TDerived::DoProcess)
  77. }) {}
  78. #ifndef MKQL_DISABLE_CODEGEN
  79. ICodegeneratorInlineWideNode::TGenerateResult DoGenGetValues(const TCodegenContext& ctx, Value* statePtrVal, BasicBlock*& genToBlock) const final {
  80. return TSimpleStatefulWideFlowCodegeneratorNodeLLVMBase::DoGenGetValues(ctx, statePtrVal, genToBlock);
  81. }
  82. #endif
  83. public:
  84. EFetchResult DoCalculate(NUdf::TUnboxedValue& state, TComputationContext& ctx, NUdf::TUnboxedValue*const* output) const {
  85. if (state.IsInvalid()) {
  86. state = NUdf::TUnboxedValuePod();
  87. static_cast<const TDerived*>(this)->InitState(state, ctx);
  88. }
  89. NUdf::TUnboxedValue *const stub = nullptr;
  90. if (!output && !OutWidth) {
  91. output = &stub;
  92. }
  93. auto result = TMaybeFetchResult::None();
  94. while (result.Empty()) {
  95. NUdf::TUnboxedValue*const* input = static_cast<const TDerived*>(this)->PrepareInput(state, ctx, output);
  96. TMaybeFetchResult fetchResult = input ? SourceFlow->FetchValues(ctx, input) : TMaybeFetchResult::None();
  97. result = static_cast<const TDerived*>(this)->DoProcess(state, ctx, fetchResult, output);
  98. }
  99. return result.Get();
  100. }
  101. };
  102. }
  103. }