aboutsummaryrefslogtreecommitdiffstats
path: root/yql/essentials/minikql/computation/mkql_simple_codegen.h
blob: ab8438b1762ee25d785995957794cdf0576f935e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#pragma once

namespace NKikimr {
namespace NMiniKQL {

class TMaybeFetchResult final {
    ui64 Raw;

    explicit TMaybeFetchResult(ui64 raw) : Raw(raw) {}

public:
    /* implicit */ TMaybeFetchResult(EFetchResult res) : TMaybeFetchResult(static_cast<ui64>(static_cast<ui32>(res))) {}


    [[nodiscard]] bool Empty() const {
        return Raw >> ui64(32);
    }

    [[nodiscard]] EFetchResult Get() const {
        Y_ABORT_IF(Empty());
        return static_cast<EFetchResult>(static_cast<ui32>(Raw));
    }

    [[nodiscard]] ui64 RawU64() const {
        return Raw;
    }

    static TMaybeFetchResult None() {
        return TMaybeFetchResult(ui64(1) << ui64(32));
    }

#ifndef MKQL_DISABLE_CODEGEN
    static Type* LLVMType(LLVMContext& context) {
        return Type::getInt64Ty(context);
    }

    static Value* LLVMFromFetchResult(Value *fetchRes, const Twine& name, BasicBlock* block) {
        return new ZExtInst(fetchRes, LLVMType(fetchRes->getContext()), name, block);
    }

    Value* LLVMConst(LLVMContext& context) const {
        return ConstantInt::get(LLVMType(context), RawU64());
    }
#endif
};

#ifndef MKQL_DISABLE_CODEGEN
using TResultCodegenerator = std::function<ICodegeneratorInlineWideNode::TGenerateResult(const TCodegenContext&, BasicBlock*&)>;
#endif

class TSimpleStatefulWideFlowCodegeneratorNodeLLVMBase {
public:
    struct TMethPtrTable {
        uintptr_t ThisPtr;
        uintptr_t InitStateMethPtr;
        uintptr_t PrepareInputMethPtr;
        uintptr_t DoProcessMethPtr;
    };

    TSimpleStatefulWideFlowCodegeneratorNodeLLVMBase(IComputationWideFlowNode* source, ui32 inWidth, ui32 outWidth, TMethPtrTable ptrTable)
        : SourceFlow(source), InWidth(inWidth), OutWidth(outWidth)
        , PtrTable(ptrTable) {}

#ifndef MKQL_DISABLE_CODEGEN
    virtual ICodegeneratorInlineWideNode::TGenerateResult GenFetchProcess(Value* statePtrVal, const TCodegenContext& ctx, const TResultCodegenerator& fetchGenerator, BasicBlock*& block) const {
        Y_UNUSED(statePtrVal);
        Y_UNUSED(ctx);
        Y_UNUSED(fetchGenerator);
        Y_UNUSED(block);
        return {nullptr, {}};
    }

    ICodegeneratorInlineWideNode::TGenerateResult DoGenGetValues(const TCodegenContext& ctx, Value* statePtrVal, BasicBlock*& genToBlock) const;
#endif

protected:
    IComputationWideFlowNode* const SourceFlow;
    const ui32 InWidth, OutWidth;
    const TMethPtrTable PtrTable;
};

template<typename TDerived, typename TState, EValueRepresentation StateKind = EValueRepresentation::Embedded>
class TSimpleStatefulWideFlowCodegeneratorNode
        : public TStatefulWideFlowCodegeneratorNode<TSimpleStatefulWideFlowCodegeneratorNode<TDerived, TState, StateKind>>
        , public TSimpleStatefulWideFlowCodegeneratorNodeLLVMBase {
    using TBase = TStatefulWideFlowCodegeneratorNode<TSimpleStatefulWideFlowCodegeneratorNode>;
    using TLLVMBase = TSimpleStatefulWideFlowCodegeneratorNodeLLVMBase;

protected:
    TSimpleStatefulWideFlowCodegeneratorNode(TComputationMutables& mutables, IComputationWideFlowNode* source, ui32 inWidth, ui32 outWidth)
            : TBase(mutables, source, StateKind)
            , TLLVMBase(source, inWidth, outWidth, {
                .ThisPtr = reinterpret_cast<uintptr_t>(this),
                .InitStateMethPtr = GetMethodPtr(&TDerived::InitState),
                .PrepareInputMethPtr = GetMethodPtr(&TDerived::PrepareInput),
                .DoProcessMethPtr = GetMethodPtr(&TDerived::DoProcess)
            }) {}

#ifndef MKQL_DISABLE_CODEGEN
    ICodegeneratorInlineWideNode::TGenerateResult DoGenGetValues(const TCodegenContext& ctx, Value* statePtrVal, BasicBlock*& genToBlock) const final {
        return TSimpleStatefulWideFlowCodegeneratorNodeLLVMBase::DoGenGetValues(ctx, statePtrVal, genToBlock);
    }
#endif

public:
    EFetchResult DoCalculate(NUdf::TUnboxedValue& state, TComputationContext& ctx, NUdf::TUnboxedValue*const* output) const {
        if (state.IsInvalid()) {
            state = NUdf::TUnboxedValuePod();
            static_cast<const TDerived*>(this)->InitState(state, ctx);
        }
        NUdf::TUnboxedValue *const stub = nullptr;
        if (!output && !OutWidth) {
            output = &stub;
        }
        auto result = TMaybeFetchResult::None();
        while (result.Empty()) {
            NUdf::TUnboxedValue*const* input = static_cast<const TDerived*>(this)->PrepareInput(state, ctx, output);
            TMaybeFetchResult fetchResult = input ? SourceFlow->FetchValues(ctx, input) : TMaybeFetchResult::None();
            result = static_cast<const TDerived*>(this)->DoProcess(state, ctx, fetchResult, output);
        }
        return result.Get();
    }
};

}
}