mkql_computation_node_codegen.h.txt 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262
  1. #pragma once
  2. #include <yql/essentials/minikql/computation/mkql_computation_node_codegen_common.h>
  3. #ifdef MKQL_DISABLE_CODEGEN
  4. namespace NKikimr {
  5. namespace NMiniKQL {
  6. using NYql::GetMethodPtr;
  7. using NYql::GetMethodPtrIndex;
  8. using NYql::GetMethodIndex;
  9. using TUnboxedImmutableCodegeneratorNode = TUnboxedImmutableComputationNode;
  10. using TExternalCodegeneratorNode = TExternalComputationNode;
  11. using TWideFlowProxyCodegeneratorNode = TWideFlowProxyComputationNode;
  12. template <typename TDerived>
  13. using TDecoratorCodegeneratorNode = TDecoratorComputationNode<TDerived>;
  14. template <typename TDerived>
  15. using TBinaryCodegeneratorNode = TBinaryComputationNode<TDerived>;
  16. template <typename TDerived>
  17. using TMutableCodegeneratorNode = TMutableComputationNode<TDerived>;
  18. template <typename TDerived>
  19. using TMutableCodegeneratorPtrNode = TMutableComputationNode<TDerived>;
  20. template <typename TDerived>
  21. using TMutableCodegeneratorFallbackNode = TMutableComputationNode<TDerived>;
  22. template <typename TDerived>
  23. using TMutableCodegeneratorRootNode = TMutableComputationNode<TDerived>;
  24. template <typename TDerived>
  25. using TCustomValueCodegeneratorNode = TMutableComputationNode<TDerived>;
  26. template <typename TDerived>
  27. using TBothWaysCodegeneratorNode = TMutableComputationNode<TDerived>;
  28. template <typename TDerived>
  29. using TStatelessFlowCodegeneratorNode = TStatelessFlowComputationNode<TDerived>;
  30. template <typename TDerived>
  31. using TStatelessWideFlowCodegeneratorNode = TStatelessWideFlowComputationNode<TDerived>;
  32. template <typename TDerived, bool SerializableState = false>
  33. using TStatefulWideFlowCodegeneratorNode = TStatefulWideFlowComputationNode<TDerived, SerializableState>;
  34. template <typename TDerived>
  35. using TPairStateWideFlowCodegeneratorNode = TPairStateWideFlowComputationNode<TDerived>;
  36. template <typename TDerived>
  37. using TStatelessFlowCodegeneratorRootNode = TStatelessFlowComputationNode<TDerived>;
  38. template <typename TDerived, bool SerializableState = false>
  39. using TStatefulFlowCodegeneratorNode = TStatefulFlowComputationNode<TDerived, SerializableState>;
  40. template <typename TDerived>
  41. using TPairStateFlowCodegeneratorNode = TPairStateFlowComputationNode<TDerived>;
  42. template <typename TDerived>
  43. using TFlowSourceCodegeneratorNode = TFlowSourceComputationNode<TDerived>;
  44. template <typename TDerived>
  45. using TWideFlowSourceCodegeneratorNode = TWideFlowSourceComputationNode<TDerived>;
  46. }
  47. }
  48. #else
  49. #include <llvm/IR/Value.h>
  50. #include <llvm/IR/BasicBlock.h>
  51. #include <llvm/IR/Function.h>
  52. #include <llvm/IR/LLVMContext.h>
  53. #include <llvm/IR/Module.h>
  54. #include <llvm/IR/DerivedTypes.h>
  55. #include <llvm/IR/Instructions.h>
  56. #include <llvm/IR/Constants.h>
  57. #include <llvm/IR/DebugInfoMetadata.h>
  58. #include <llvm/IR/DIBuilder.h>
  59. #if !__clang__ || (__clang_major__ >= 16)
  60. #include <source_location>
  61. #endif
  62. namespace NKikimr {
  63. namespace NMiniKQL {
  64. using NYql::GetMethodPtr;
  65. using NYql::GetMethodPtrIndex;
  66. using NYql::GetMethodIndex;
  67. using namespace llvm;
  68. Type* GetCompContextType(LLVMContext &context);
  69. Type* GetStringRefType(LLVMContext &context);
  70. Type* GetSourcePosType(LLVMContext &context);
  71. class DISubprogramAnnotator;
  72. struct TCodegenContext {
  73. TCodegenContext(NYql::NCodegen::ICodegen& codegen) : Codegen(codegen) {}
  74. NYql::NCodegen::ICodegen& Codegen;
  75. Function* Func = nullptr;
  76. Argument* Ctx = nullptr;
  77. DISubprogramAnnotator* Annotator = nullptr;
  78. bool AlwaysInline = false;
  79. Value* GetFactory() const;
  80. Value* GetStat() const;
  81. Value* GetMutables() const;
  82. Value* GetBuilder() const;
  83. private:
  84. Value * Factory = nullptr;
  85. Value * Stat = nullptr;
  86. Value * Mutables = nullptr;
  87. Value * Builder = nullptr;
  88. };
  89. using TGeneratorPtr = Value* (*)(Value *const * args, const TCodegenContext& ctx, BasicBlock*& block);
  90. class ICodegeneratorRootNode {
  91. public:
  92. virtual ~ICodegeneratorRootNode() {}
  93. virtual void GenerateFunctions(NYql::NCodegen::ICodegen& codegen) = 0;
  94. virtual void FinalizeFunctions(NYql::NCodegen::ICodegen& codegen) = 0;
  95. };
  96. class ICodegeneratorInlineNode {
  97. public:
  98. virtual ~ICodegeneratorInlineNode() {}
  99. virtual Value* CreateGetValue(const TCodegenContext& ctx, BasicBlock*& block) const = 0;
  100. };
  101. class ICodegeneratorInlineWideNode {
  102. public:
  103. virtual ~ICodegeneratorInlineWideNode() {}
  104. using TGettersList = std::vector<std::function<Value*(const TCodegenContext& ctx, BasicBlock*&)>>;
  105. using TGenerateResult = std::pair<Value*, TGettersList>;
  106. virtual TGenerateResult GenGetValues(const TCodegenContext& ctx, BasicBlock*& block) const = 0;
  107. };
  108. class IWideFlowProxyCodegeneratorNode: public ICodegeneratorInlineWideNode
  109. {
  110. public:
  111. using TGenerator = std::function<TGenerateResult(const TCodegenContext&, BasicBlock*&)>;
  112. virtual void SetGenerator(TGenerator&& generator) = 0;
  113. virtual void CreateInvalidate(const TCodegenContext& ctx, BasicBlock*& block) const = 0;
  114. };
  115. class ICodegeneratorExternalNode : public ICodegeneratorInlineNode {
  116. public:
  117. virtual Value* CreateRefValue(const TCodegenContext& ctx, BasicBlock*& block) const = 0;
  118. virtual void CreateSetValue(const TCodegenContext& ctx, BasicBlock*& block, Value* value) const = 0;
  119. virtual Value* CreateSwapValue(const TCodegenContext& ctx, BasicBlock*& block, Value* value) const = 0;
  120. virtual void CreateInvalidate(const TCodegenContext& ctx, BasicBlock*& block) const = 0;
  121. using TValueBuilder = std::function<std::pair<llvm::Value*,llvm::Type*> (const TCodegenContext &)>;
  122. virtual void SetValueBuilder(TValueBuilder valueBuilder) = 0;
  123. using TValueGetterBuilder = std::function<llvm::Function * (const TCodegenContext &)>;
  124. virtual void SetValueGetterBuilder(TValueGetterBuilder valueGetterBuilder) = 0;
  125. };
  126. class ICodegeneratorRunNode {
  127. public:
  128. virtual ~ICodegeneratorRunNode() {}
  129. virtual void CreateRun(const TCodegenContext& ctx, BasicBlock*& block, Value* result, Value* args) const = 0;
  130. };
  131. Value* CallBoxedValueVirtualMethodImpl(uintptr_t methodPtr, Type* returnType, Value* value, NYql::NCodegen::ICodegen& codegen, BasicBlock* block);
  132. template<NUdf::TBoxedValueAccessor::EMethod Method>
  133. Value* CallBoxedValueVirtualMethod(Type* returnType, Value* value, NYql::NCodegen::ICodegen& codegen, BasicBlock* block) {
  134. return CallBoxedValueVirtualMethodImpl(NUdf::TBoxedValueAccessor::GetMethodPtr<Method>(), returnType, value, codegen, block);
  135. }
  136. void CallBoxedValueVirtualMethodImpl(uintptr_t methodPtr, Value* output, Value* value, NYql::NCodegen::ICodegen& codegen, BasicBlock* block);
  137. template<NUdf::TBoxedValueAccessor::EMethod Method>
  138. void CallBoxedValueVirtualMethod(Value* output, Value* value, NYql::NCodegen::ICodegen& codegen, BasicBlock* block) {
  139. CallBoxedValueVirtualMethodImpl(NUdf::TBoxedValueAccessor::GetMethodPtr<Method>(), output, value, codegen, block);
  140. }
  141. void CallBoxedValueVirtualMethodImpl(uintptr_t methodPtr, Value* output, Value* value, NYql::NCodegen::ICodegen& codegen, BasicBlock* block, Value* argument);
  142. template<NUdf::TBoxedValueAccessor::EMethod Method>
  143. void CallBoxedValueVirtualMethod(Value* output, Value* value, NYql::NCodegen::ICodegen& codegen, BasicBlock* block, Value* argument) {
  144. CallBoxedValueVirtualMethodImpl(NUdf::TBoxedValueAccessor::GetMethodPtr<Method>(), output, value, codegen, block, argument);
  145. }
  146. Value* CallBoxedValueVirtualMethodImpl(uintptr_t methodPtr, Type* returnType, Value* value, NYql::NCodegen::ICodegen& codegen, BasicBlock* block, Value* argument);
  147. template<NUdf::TBoxedValueAccessor::EMethod Method>
  148. Value* CallBoxedValueVirtualMethod(Type* returnType, Value* value, NYql::NCodegen::ICodegen& codegen, BasicBlock* block, Value* argument) {
  149. return CallBoxedValueVirtualMethodImpl(NUdf::TBoxedValueAccessor::GetMethodPtr<Method>(), returnType, value, codegen, block, argument);
  150. }
  151. void CallBoxedValueVirtualMethodImpl(uintptr_t methodPtr, Value* output, Value* value, NYql::NCodegen::ICodegen& codegen, BasicBlock* block, Value* arg1, Value* arg2);
  152. template<NUdf::TBoxedValueAccessor::EMethod Method>
  153. void CallBoxedValueVirtualMethod(Value* output, Value* value, NYql::NCodegen::ICodegen& codegen, BasicBlock* block, Value* arg1, Value* arg2) {
  154. CallBoxedValueVirtualMethodImpl(NUdf::TBoxedValueAccessor::GetMethodPtr<Method>(), output, value, codegen, block, arg1, arg2);
  155. }
  156. Value* CallBoxedValueVirtualMethodImpl(uintptr_t methodPtr, Type* returnType, Value* value, NYql::NCodegen::ICodegen& codegen, BasicBlock* block, Value* arg1, Value* arg2);
  157. template<NUdf::TBoxedValueAccessor::EMethod Method>
  158. Value* CallBoxedValueVirtualMethod(Type* returnType, Value* value, NYql::NCodegen::ICodegen& codegen, BasicBlock* block, Value* arg1, Value* arg2) {
  159. return CallBoxedValueVirtualMethodImpl(NUdf::TBoxedValueAccessor::GetMethodPtr<Method>(), returnType, value, codegen, block, arg1, arg2);
  160. }
  161. Value* CallUnaryUnboxedValueFunctionImpl(uintptr_t methodPtr, Type* result, Value* arg, NYql::NCodegen::ICodegen& codegen, BasicBlock* block);
  162. template<typename Method>
  163. Value* CallUnaryUnboxedValueFunction(Method method, Type* result, Value* arg, NYql::NCodegen::ICodegen& codegen, BasicBlock* block) {
  164. return CallUnaryUnboxedValueFunctionImpl(GetMethodPtr(method), result, arg, codegen, block);
  165. }
  166. Value* CallBinaryUnboxedValueFunctionImpl(uintptr_t methodPtr, Type* result, Value* left, Value* right, NYql::NCodegen::ICodegen& codegen, BasicBlock* block);
  167. template<typename Method>
  168. Value* CallBinaryUnboxedValueFunction(Method method, Type* result, Value* left, Value* right, NYql::NCodegen::ICodegen& codegen, BasicBlock* block) {
  169. return CallBinaryUnboxedValueFunctionImpl(GetMethodPtr(method), result, left, right, codegen, block);
  170. }
  171. void AddRefBoxed(Value* value, const TCodegenContext& ctx, BasicBlock*& block);
  172. void UnRefBoxed(Value* value, const TCodegenContext& ctx, BasicBlock*& block);
  173. void CleanupBoxed(Value* value, const TCodegenContext& ctx, BasicBlock*& block);
  174. void SafeUnRefUnboxedOne(Value* pointer, const TCodegenContext& ctx, BasicBlock*& block);
  175. void SafeUnRefUnboxedArray(Value* pointer, ArrayType* arrayType, const TCodegenContext& ctx, BasicBlock*& block);
  176. void ValueAddRef(EValueRepresentation kind, Value* pointer, const TCodegenContext& ctx, BasicBlock*& block);
  177. void ValueUnRef(EValueRepresentation kind, Value* pointer, const TCodegenContext& ctx, BasicBlock*& block);
  178. void ValueCleanup(EValueRepresentation kind, Value* pointer, const TCodegenContext& ctx, BasicBlock*& block);
  179. void ValueRelease(EValueRepresentation kind, Value* pointer, const TCodegenContext& ctx, BasicBlock*& block);
  180. std::pair<Value*, Value*> GetVariantParts(Value* variant, const TCodegenContext& ctx, BasicBlock*& block);
  181. Value* MakeVariant(Value* item, Value* variant, const TCodegenContext& ctx, BasicBlock*& block);
  182. Value* GetNodeValue(IComputationNode* node, const TCodegenContext& ctx, BasicBlock*& block);
  183. void GetNodeValue(Value* value, IComputationNode* node, const TCodegenContext& ctx, BasicBlock*& block);
  184. struct TNoCodegen {};
  185. ICodegeneratorInlineWideNode::TGenerateResult GetNodeValues(IComputationWideFlowNode* node, const TCodegenContext& ctx, BasicBlock*& block);
  186. Function* GenerateCompareFunction(
  187. NYql::NCodegen::ICodegen& codegen,
  188. const TString& name,
  189. IComputationExternalNode* left,
  190. IComputationExternalNode* right,
  191. IComputationNode* compare
  192. );
  193. Function* GenerateEqualsFunction(NYql::NCodegen::ICodegen& codegen, const TString& name, bool isTuple, const TKeyTypes& types);
  194. Function* GenerateHashFunction(NYql::NCodegen::ICodegen& codegen, const TString& name, bool isTuple, const TKeyTypes& types);
  195. Function* GenerateEqualsFunction(NYql::NCodegen::ICodegen& codegen, const TString& name, const TKeyTypes& types);
  196. Function* GenerateHashFunction(NYql::NCodegen::ICodegen& codegen, const TString& name, const TKeyTypes& types);
  197. Function* GenerateCompareFunction(NYql::NCodegen::ICodegen& codegen, const TString& name, const TKeyTypes& types);
  198. class TDecoratorCodegeneratorNodeBase {
  199. protected:
  200. virtual ~TDecoratorCodegeneratorNodeBase() = default;
  201. virtual Value* DoGenerateGetValue(const TCodegenContext& ctx, Value* value, BasicBlock*& block) const = 0;
  202. Value* CreateGetValueImpl(IComputationNode* node, const TCodegenContext& ctx, BasicBlock*& block) const;
  203. };
  204. template <typename TDerived>
  205. class TDecoratorCodegeneratorNode: public TDecoratorComputationNode<TDerived>, public ICodegeneratorInlineNode,
  206. protected TDecoratorCodegeneratorNodeBase
  207. {
  208. using TBase = TDecoratorComputationNode<TDerived>;
  209. protected:
  210. TDecoratorCodegeneratorNode(IComputationNode* node, EValueRepresentation kind)
  211. : TBase(node, kind)
  212. {}
  213. TDecoratorCodegeneratorNode(IComputationNode* node)
  214. : TBase(node)
  215. {}
  216. Value* CreateGetValue(const TCodegenContext& ctx, BasicBlock*& block) const final {
  217. return CreateGetValueImpl(this->Node, ctx, block);
  218. }
  219. };
  220. class TStatelessFlowCodegeneratorNodeBase {
  221. protected:
  222. virtual ~TStatelessFlowCodegeneratorNodeBase() = default;
  223. virtual Value* DoGenerateGetValue(const TCodegenContext& ctx, BasicBlock*& block) const = 0;
  224. Value* CreateGetValueImpl(const IComputationNode* node, const TCodegenContext& ctx, BasicBlock*& block) const;
  225. };
  226. template <typename TDerived>
  227. class TStatelessFlowCodegeneratorNode: public TStatelessFlowComputationNode<TDerived>, public ICodegeneratorInlineNode,
  228. protected TStatelessFlowCodegeneratorNodeBase
  229. {
  230. using TBase = TStatelessFlowComputationNode<TDerived>;
  231. protected:
  232. TStatelessFlowCodegeneratorNode(const IComputationNode* source, EValueRepresentation kind)
  233. : TBase(source, kind)
  234. {}
  235. TStatelessFlowCodegeneratorNode(TComputationMutables& mutables, const IComputationNode* source, EValueRepresentation kind)
  236. : TBase(mutables, source, kind)
  237. {}
  238. Value* CreateGetValue(const TCodegenContext& ctx, BasicBlock*& block) const final {
  239. return CreateGetValueImpl(static_cast<const IComputationNode*>(this), ctx, block);
  240. }
  241. };
  242. class TStatelessWideFlowCodegeneratorNodeBase {
  243. protected:
  244. virtual ~TStatelessWideFlowCodegeneratorNodeBase() = default;
  245. virtual ICodegeneratorInlineWideNode::TGenerateResult DoGenGetValues(const TCodegenContext& ctx, BasicBlock*& block) const = 0;
  246. ICodegeneratorInlineWideNode::TGenerateResult GenGetValuesImpl(const TCodegenContext& ctx, BasicBlock*& block) const;
  247. };
  248. template <typename TDerived>
  249. class TStatelessWideFlowCodegeneratorNode: public TStatelessWideFlowComputationNode<TDerived>, public ICodegeneratorInlineWideNode,
  250. protected TStatelessWideFlowCodegeneratorNodeBase
  251. {
  252. using TBase = TStatelessWideFlowCodegeneratorNode<TDerived>;
  253. protected:
  254. TStatelessWideFlowCodegeneratorNode(const IComputationNode* source)
  255. : TStatelessWideFlowComputationNode<TDerived>(source)
  256. {}
  257. ICodegeneratorInlineWideNode::TGenerateResult GenGetValues(const TCodegenContext& ctx, BasicBlock*& block) const final {
  258. return GenGetValuesImpl(ctx, block);
  259. }
  260. };
  261. class TFlowSourceCodegeneratorNodeBase {
  262. protected:
  263. virtual ~TFlowSourceCodegeneratorNodeBase() = default;
  264. virtual Value* DoGenerateGetValue(const TCodegenContext& ctx, Value* statePtr, BasicBlock*& block) const = 0;
  265. Value* CreateGetValueImpl(const IComputationNode* node, const TCodegenContext& ctx, BasicBlock*& block) const;
  266. };
  267. template <typename TDerived>
  268. class TFlowSourceCodegeneratorNode: public TFlowSourceComputationNode<TDerived>, public ICodegeneratorInlineNode,
  269. protected TFlowSourceCodegeneratorNodeBase
  270. {
  271. using TBase = TFlowSourceComputationNode<TDerived>;
  272. protected:
  273. TFlowSourceCodegeneratorNode(TComputationMutables& mutables, EValueRepresentation kind, EValueRepresentation stateKind)
  274. : TBase(mutables, kind, stateKind)
  275. {}
  276. Value* CreateGetValue(const TCodegenContext& ctx, BasicBlock*& block) const final {
  277. return CreateGetValueImpl(static_cast<const IComputationNode*>(this), ctx, block);
  278. }
  279. };
  280. class TWideFlowSourceCodegeneratorNodeBase {
  281. protected:
  282. virtual ~TWideFlowSourceCodegeneratorNodeBase() = default;
  283. virtual ICodegeneratorInlineWideNode::TGenerateResult DoGenGetValues(const TCodegenContext& ctx, Value* statePtr, BasicBlock*& block) const = 0;
  284. ICodegeneratorInlineWideNode::TGenerateResult GenGetValuesImpl(const IComputationNode* node,
  285. const TCodegenContext& ctx, BasicBlock*& block) const;
  286. };
  287. template <typename TDerived>
  288. class TWideFlowSourceCodegeneratorNode: public TWideFlowSourceComputationNode<TDerived>, public ICodegeneratorInlineWideNode,
  289. protected TWideFlowSourceCodegeneratorNodeBase
  290. {
  291. using TBase = TWideFlowSourceComputationNode<TDerived>;
  292. protected:
  293. TWideFlowSourceCodegeneratorNode(TComputationMutables& mutables,EValueRepresentation stateKind)
  294. : TBase(mutables, stateKind)
  295. {}
  296. TGenerateResult GenGetValues(const TCodegenContext& ctx, BasicBlock*& block) const final {
  297. return GenGetValuesImpl(static_cast<const IComputationNode*>(this), ctx, block);
  298. }
  299. };
  300. class TStatefulFlowCodegeneratorNodeBase {
  301. protected:
  302. virtual ~TStatefulFlowCodegeneratorNodeBase() = default;
  303. virtual Value* DoGenerateGetValue(const TCodegenContext& ctx, Value* statePtr, BasicBlock*& block) const = 0;
  304. Value* CreateGetValueImpl(const IComputationNode* node, const TCodegenContext& ctx, BasicBlock*& block) const;
  305. };
  306. template <typename TDerived, bool SerializableState = false>
  307. class TStatefulFlowCodegeneratorNode: public TStatefulFlowComputationNode<TDerived, SerializableState>, public ICodegeneratorInlineNode,
  308. protected TStatefulFlowCodegeneratorNodeBase
  309. {
  310. using TBase = TStatefulFlowComputationNode<TDerived, SerializableState>;
  311. protected:
  312. TStatefulFlowCodegeneratorNode(TComputationMutables& mutables, const IComputationNode* source, EValueRepresentation kind, EValueRepresentation stateKind = EValueRepresentation::Any)
  313. : TBase(mutables, source, kind, stateKind)
  314. {}
  315. Value* CreateGetValue(const TCodegenContext& ctx, BasicBlock*& block) const final {
  316. return CreateGetValueImpl(static_cast<const IComputationNode*>(this), ctx, block);
  317. }
  318. };
  319. class TStatefulWideFlowCodegeneratorNodeBase {
  320. protected:
  321. virtual ~TStatefulWideFlowCodegeneratorNodeBase() = default;
  322. virtual ICodegeneratorInlineWideNode::TGenerateResult DoGenGetValues(
  323. const TCodegenContext& ctx, Value* statePtr, BasicBlock*& block) const = 0;
  324. ICodegeneratorInlineWideNode::TGenerateResult GenGetValuesImpl(
  325. const IComputationNode* node, const TCodegenContext& ctx, BasicBlock*& block) const;
  326. };
  327. template <typename TDerived, bool SerializableState = false>
  328. class TStatefulWideFlowCodegeneratorNode: public TStatefulWideFlowComputationNode<TDerived, SerializableState>, public ICodegeneratorInlineWideNode,
  329. protected TStatefulWideFlowCodegeneratorNodeBase
  330. {
  331. using TBase = TStatefulWideFlowComputationNode<TDerived, SerializableState>;
  332. protected:
  333. TStatefulWideFlowCodegeneratorNode(TComputationMutables& mutables, const IComputationNode* source, EValueRepresentation stateKind)
  334. : TBase(mutables, source, stateKind)
  335. {}
  336. TStatefulWideFlowCodegeneratorNode(TComputationMutables& mutables, const IComputationNode* source, EValueRepresentation, EValueRepresentation stateKind)
  337. : TBase(mutables, source, stateKind)
  338. {}
  339. TGenerateResult GenGetValues(const TCodegenContext& ctx, BasicBlock*& block) const final {
  340. return GenGetValuesImpl(static_cast<const IComputationNode*>(this), ctx, block);
  341. }
  342. };
  343. class TPairStateWideFlowCodegeneratorNodeBase {
  344. protected:
  345. virtual ~TPairStateWideFlowCodegeneratorNodeBase() = default;
  346. virtual ICodegeneratorInlineWideNode::TGenerateResult DoGenGetValues(const TCodegenContext& ctx,
  347. Value* firstPtr, Value* secondPtr, BasicBlock*& block) const = 0;
  348. ICodegeneratorInlineWideNode::TGenerateResult GenGetValuesImpl(const IComputationNode* node,
  349. const TCodegenContext& ctx, BasicBlock*& block) const;
  350. };
  351. template <typename TDerived>
  352. class TPairStateWideFlowCodegeneratorNode: public TPairStateWideFlowComputationNode<TDerived>, public ICodegeneratorInlineWideNode,
  353. protected TPairStateWideFlowCodegeneratorNodeBase
  354. {
  355. using TBase = TPairStateWideFlowComputationNode<TDerived>;
  356. protected:
  357. TPairStateWideFlowCodegeneratorNode(TComputationMutables& mutables, const IComputationNode* source, EValueRepresentation firstKind, EValueRepresentation secondKind)
  358. : TBase(mutables, source, firstKind, secondKind)
  359. {}
  360. TGenerateResult GenGetValues(const TCodegenContext& ctx, BasicBlock*& block) const final {
  361. return GenGetValuesImpl(static_cast<const IComputationNode*>(this), ctx, block);
  362. }
  363. };
  364. class TPairStateFlowCodegeneratorNodeBase {
  365. protected:
  366. virtual ~TPairStateFlowCodegeneratorNodeBase() = default;
  367. virtual Value* DoGenerateGetValue(const TCodegenContext& ctx, Value* firstPtr, Value* secondPtr, BasicBlock*& block) const = 0;
  368. Value* CreateGetValueImpl(const IComputationNode* node, const TCodegenContext& ctx, BasicBlock*& block) const;
  369. };
  370. template <typename TDerived>
  371. class TPairStateFlowCodegeneratorNode: public TPairStateFlowComputationNode<TDerived>, public ICodegeneratorInlineNode,
  372. protected TPairStateFlowCodegeneratorNodeBase
  373. {
  374. using TBase = TPairStateFlowComputationNode<TDerived>;
  375. protected:
  376. TPairStateFlowCodegeneratorNode(TComputationMutables& mutables, const IComputationNode* source, EValueRepresentation kind, EValueRepresentation firstKind = EValueRepresentation::Any, EValueRepresentation secondKind = EValueRepresentation::Any)
  377. : TBase(mutables, source, kind, firstKind, secondKind)
  378. {}
  379. Value* CreateGetValue(const TCodegenContext& ctx, BasicBlock*& block) const final {
  380. return CreateGetValueImpl(static_cast<const IComputationNode*>(this), ctx, block);
  381. }
  382. };
  383. class TBinaryCodegeneratorNodeBase {
  384. protected:
  385. virtual ~TBinaryCodegeneratorNodeBase() = default;
  386. virtual Value* DoGenerateGetValue(const TCodegenContext& ctx, BasicBlock*& block) const = 0;
  387. Value* CreateGetValueImpl(const IComputationNode* node, const TCodegenContext& ctx, BasicBlock*& block) const;
  388. };
  389. template <typename TDerived>
  390. class TBinaryCodegeneratorNode: public TBinaryComputationNode<TDerived>, public ICodegeneratorInlineNode,
  391. protected TBinaryCodegeneratorNodeBase
  392. {
  393. using TBase = TBinaryComputationNode<TDerived>;
  394. protected:
  395. TBinaryCodegeneratorNode(IComputationNode* left, IComputationNode* right, const EValueRepresentation kind)
  396. : TBase(left, right, kind)
  397. {}
  398. TBinaryCodegeneratorNode(TComputationMutables&, EValueRepresentation kind, IComputationNode* left, IComputationNode* right)
  399. : TBase(left, right, kind)
  400. {}
  401. Value* CreateGetValue(const TCodegenContext& ctx, BasicBlock*& block) const final {
  402. return CreateGetValueImpl(static_cast<const IComputationNode*>(this), ctx, block);
  403. }
  404. };
  405. class TMutableCodegeneratorNodeBase {
  406. protected:
  407. virtual ~TMutableCodegeneratorNodeBase() = default;
  408. Value* CreateGetValueImpl(bool stateless, EValueRepresentation representation, ui32 valueIndex,
  409. const TString& name, const TCodegenContext& ctx, BasicBlock*& block) const;
  410. Function* GenerateInternalGetValue(const TString& name, EValueRepresentation representation, ui32 valueIndex,
  411. NYql::NCodegen::ICodegen& codegen) const;
  412. Value* MakeGetValueBody(EValueRepresentation representation, ui32 valueIndex, const TCodegenContext& ctx, BasicBlock*& block) const;
  413. virtual Value* DoGenerateGetValue(const TCodegenContext& ctx, BasicBlock*& block) const = 0;
  414. };
  415. template <typename TDerived>
  416. class TMutableCodegeneratorNode: public TMutableComputationNode<TDerived>, public ICodegeneratorInlineNode,
  417. protected TMutableCodegeneratorNodeBase
  418. {
  419. using TBase = TMutableComputationNode<TDerived>;
  420. protected:
  421. TString MakeName() const {
  422. TStringStream out;
  423. out << this->DebugString() << "::internal_Get_(" << static_cast<const void*>(this) << ").";
  424. return out.Str();
  425. }
  426. TMutableCodegeneratorNode(TComputationMutables& mutables, EValueRepresentation kind)
  427. : TBase(mutables, kind)
  428. {}
  429. Value* CreateGetValue(const TCodegenContext& ctx, BasicBlock*& block) const final {
  430. return CreateGetValueImpl(*this->Stateless, this->GetRepresentation(), this->ValueIndex, MakeName(), ctx, block);
  431. }
  432. };
  433. class TMutableCodegeneratorPtrNodeBase {
  434. protected:
  435. virtual ~TMutableCodegeneratorPtrNodeBase() = default;
  436. Value* CreateGetValueImpl(bool stateless, EValueRepresentation representation, ui32 valueIndex,
  437. const TString& name, const TCodegenContext& ctx, BasicBlock*& block) const;
  438. Value* MakeGetValueBody(ui32 valueIndex, const TCodegenContext& ctx, BasicBlock*& block) const;
  439. Function* GenerateInternalGetValue(const TString& name, ui32 valueIndex, NYql::NCodegen::ICodegen& codegen) const;
  440. virtual void DoGenerateGetValue(const TCodegenContext& ctx, Value* valuePtr, BasicBlock*& block) const = 0;
  441. };
  442. template <typename TDerived>
  443. class TMutableCodegeneratorPtrNode: public TMutableComputationNode<TDerived>, public ICodegeneratorInlineNode,
  444. protected TMutableCodegeneratorPtrNodeBase
  445. {
  446. using TBase = TMutableComputationNode<TDerived>;
  447. TString MakeName() const {
  448. TStringStream out;
  449. out << this->DebugString() << "::internal_Get_(" << static_cast<const void*>(this) << ").";
  450. return out.Str();
  451. }
  452. protected:
  453. TMutableCodegeneratorPtrNode(TComputationMutables& mutables, EValueRepresentation kind)
  454. : TBase(mutables, kind)
  455. {}
  456. Value* CreateGetValue(const TCodegenContext& ctx, BasicBlock*& block) const final {
  457. return CreateGetValueImpl(*this->Stateless, this->GetRepresentation(), this->ValueIndex, MakeName(), ctx, block);
  458. }
  459. };
  460. class TMutableCodegeneratorFallbackNodeBase {
  461. protected:
  462. Value* DoGenerateGetValueImpl(uintptr_t methodPtr, uintptr_t thisPtr, const TCodegenContext& ctx, BasicBlock*& block) const;
  463. };
  464. template <typename TDerived>
  465. class TMutableCodegeneratorFallbackNode: public TMutableCodegeneratorNode<TDerived>,
  466. protected TMutableCodegeneratorFallbackNodeBase
  467. {
  468. using TBase = TMutableCodegeneratorNode<TDerived>;
  469. protected:
  470. TMutableCodegeneratorFallbackNode(TComputationMutables& mutables, EValueRepresentation kind)
  471. : TBase(mutables, kind)
  472. {}
  473. public:
  474. Value* DoGenerateGetValue(const TCodegenContext& ctx, BasicBlock*& block) const {
  475. static_assert(std::is_same<std::invoke_result_t<decltype(&TDerived::DoCalculate), TDerived, TComputationContext&>, NUdf::TUnboxedValuePod>(), "DoCalculate must return pod!");
  476. return DoGenerateGetValueImpl(GetMethodPtr(&TDerived::DoCalculate), uintptr_t(this), ctx, block);
  477. }
  478. };
  479. class TCodegeneratorRootNodeBase {
  480. protected:
  481. Function* GenerateGetValueImpl(const TString& name, const ICodegeneratorInlineNode* gen,
  482. NYql::NCodegen::ICodegen& codegen);
  483. };
  484. template <typename TDerived, bool PreventReGeneration = false>
  485. class TCodegeneratorRootNode: public TDerived, public ICodegeneratorRootNode,
  486. protected TCodegeneratorRootNodeBase
  487. {
  488. using TBase = TDerived;
  489. public:
  490. NUdf::TUnboxedValue GetValue(TComputationContext& compCtx) const final {
  491. if (compCtx.ExecuteLLVM && GetFunction)
  492. return GetFunction(&compCtx);
  493. return TBase::GetValue(compCtx);
  494. }
  495. protected:
  496. TCodegeneratorRootNode(EValueRepresentation kind)
  497. : TBase(kind)
  498. {}
  499. TCodegeneratorRootNode(const IComputationNode* source, EValueRepresentation kind)
  500. : TBase(source, kind)
  501. {}
  502. TCodegeneratorRootNode(TComputationMutables& mutables, EValueRepresentation kind)
  503. : TBase(mutables, kind)
  504. {}
  505. private:
  506. TString MakeName() const {
  507. TStringStream out;
  508. out << this->DebugString() << "::Get_(" << static_cast<const void*>(this) << ").";
  509. return out.Str();
  510. }
  511. Function* GenerateGetValue(NYql::NCodegen::ICodegen& codegen) {
  512. auto& module = codegen.GetModule();
  513. if constexpr (PreventReGeneration) {
  514. if (const auto& name = TDerived::MakeName(); module.getFunction(name.c_str()))
  515. return nullptr;
  516. }
  517. const auto& name = MakeName();
  518. return GenerateGetValueImpl(name, this, codegen);
  519. }
  520. protected:
  521. void FinalizeFunctions(NYql::NCodegen::ICodegen& codegen) override {
  522. if (GetFunc)
  523. GetFunction = reinterpret_cast<TGetPtr>(codegen.GetPointerToFunction(GetFunc));
  524. }
  525. void GenerateFunctions(NYql::NCodegen::ICodegen& codegen) override {
  526. if (GetFunc = GenerateGetValue(codegen))
  527. codegen.ExportSymbol(GetFunc);
  528. }
  529. private:
  530. using TGetPtr = NUdf::TUnboxedValuePod (*)(TComputationContext* ctx);
  531. Function* GetFunc = nullptr;
  532. TGetPtr GetFunction = nullptr;
  533. };
  534. template <typename TDerived>
  535. using TMutableCodegeneratorRootNode = TCodegeneratorRootNode<TMutableCodegeneratorNode<TDerived>, true>;
  536. template <typename TDerived>
  537. using TStatelessFlowCodegeneratorRootNode = TCodegeneratorRootNode<TStatelessFlowCodegeneratorNode<TDerived>>;
  538. class TUnboxedImmutableCodegeneratorNode: public TUnboxedImmutableComputationNode, public ICodegeneratorInlineNode
  539. {
  540. public:
  541. TUnboxedImmutableCodegeneratorNode(TMemoryUsageInfo* memInfo, NUdf::TUnboxedValue&& value);
  542. private:
  543. Value* CreateGetValue(const TCodegenContext& ctx, BasicBlock*&) const final;
  544. };
  545. class TExternalCodegeneratorNode: public TExternalComputationNode, public ICodegeneratorExternalNode
  546. {
  547. public:
  548. TExternalCodegeneratorNode(TComputationMutables& mutables, EValueRepresentation kind);
  549. protected:
  550. Value* CreateGetValue(const TCodegenContext& ctx, BasicBlock*& block) const final;
  551. Value* CreateRefValue(const TCodegenContext& ctx, BasicBlock*& block) const final;
  552. void CreateSetValue(const TCodegenContext& ctx, BasicBlock*& block, Value* value) const final;
  553. Value* CreateSwapValue(const TCodegenContext& ctx, BasicBlock*& block, Value* value) const final;
  554. void CreateInvalidate(const TCodegenContext& ctx, BasicBlock*& block) const final;
  555. void SetValueBuilder(TValueBuilder valueBuilder) final;
  556. void SetValueGetterBuilder(TValueGetterBuilder valueGetterBuilder) final;
  557. private:
  558. TValueBuilder ValueBuilder;
  559. TValueGetterBuilder ValueGetterBuilder;
  560. };
  561. class TExternalCodegeneratorRootNode: public TExternalCodegeneratorNode, public ICodegeneratorRootNode
  562. {
  563. public:
  564. TExternalCodegeneratorRootNode(TComputationMutables& mutables, EValueRepresentation kind);
  565. private:
  566. NUdf::TUnboxedValue GetValue(TComputationContext& compCtx) const final;
  567. void SetValue(TComputationContext& compCtx, NUdf::TUnboxedValue&& newValue) const final;
  568. TString MakeName(const TString& method) const;
  569. void FinalizeFunctions(NYql::NCodegen::ICodegen& codegen) final;
  570. void GenerateFunctions(NYql::NCodegen::ICodegen& codegen) final;
  571. Function* GenerateGetValue(NYql::NCodegen::ICodegen& codegen);
  572. Function* GenerateSetValue(NYql::NCodegen::ICodegen& codegen);
  573. using TGetPtr = NUdf::TUnboxedValuePod (*)(TComputationContext* ctx);
  574. Function* GetValueFunc = nullptr;
  575. TGetPtr GetFunction = nullptr;
  576. using TSetPtr = void (*)(TComputationContext* ctx, NUdf::TUnboxedValuePod);
  577. Function* SetValueFunc = nullptr;
  578. TSetPtr SetFunction = nullptr;
  579. };
  580. class TWideFlowProxyCodegeneratorNode: public TWideFlowProxyComputationNode, public IWideFlowProxyCodegeneratorNode
  581. {
  582. public:
  583. TWideFlowProxyCodegeneratorNode() = default;
  584. private:
  585. void SetGenerator(TGenerator&& generator) final;
  586. void CreateInvalidate(const TCodegenContext& ctx, BasicBlock*& block) const final;
  587. TGenerateResult GenGetValues(const TCodegenContext& ctx, BasicBlock*& block) const final;
  588. TGenerator Generator;
  589. };
  590. class TCodegenIterator : public TComputationValue<TCodegenIterator> {
  591. public:
  592. using TNextPtr = bool (*)(TComputationContext*, NUdf::TUnboxedValuePod, NUdf::TUnboxedValuePod&);
  593. TCodegenIterator(TMemoryUsageInfo* memInfo, TNextPtr next, TComputationContext* ctx, NUdf::TUnboxedValue&& iterator)
  594. : TComputationValue<TCodegenIterator>(memInfo)
  595. , Ctx(ctx)
  596. , NextFunc(next)
  597. , Iterator(std::move(iterator))
  598. {}
  599. protected:
  600. bool Next(NUdf::TUnboxedValue& value) override {
  601. return NextFunc(Ctx, static_cast<const NUdf::TUnboxedValuePod&>(Iterator), value);
  602. }
  603. TComputationContext* const Ctx;
  604. const TNextPtr NextFunc;
  605. const NUdf::TUnboxedValue Iterator;
  606. };
  607. template <typename TState = NUdf::TUnboxedValue>
  608. class TCodegenStatefulIterator : public TComputationValue<TCodegenStatefulIterator<TState>> {
  609. public:
  610. using TStateType = TState;
  611. using TNextPtr = bool (*)(TComputationContext*, NUdf::TUnboxedValuePod, TStateType&, NUdf::TUnboxedValuePod&);
  612. TCodegenStatefulIterator(TMemoryUsageInfo* memInfo, TNextPtr next, TComputationContext* ctx, NUdf::TUnboxedValue&& iterator, const TStateType& init = TStateType())
  613. : TComputationValue<TCodegenStatefulIterator>(memInfo)
  614. , Ctx(ctx)
  615. , NextFunc(next)
  616. , Iterator(std::move(iterator))
  617. , State(init)
  618. {}
  619. protected:
  620. bool Next(NUdf::TUnboxedValue& value) override {
  621. return NextFunc(Ctx, static_cast<const NUdf::TUnboxedValuePod&>(Iterator), State, value);
  622. }
  623. TComputationContext* const Ctx;
  624. const TNextPtr NextFunc;
  625. const NUdf::TUnboxedValue Iterator;
  626. TStateType State;
  627. };
  628. class TCustomListCodegenValue : public TCustomListValue {
  629. public:
  630. using TIterator = TCodegenIterator;
  631. using TNextPtr = typename TIterator::TNextPtr;
  632. TCustomListCodegenValue(TMemoryUsageInfo* memInfo, TNextPtr next, TComputationContext* ctx, NUdf::TUnboxedValue&& list)
  633. : TCustomListValue(memInfo)
  634. , Ctx(ctx)
  635. , NextFunc(next)
  636. , List(std::move(list))
  637. {}
  638. private:
  639. NUdf::TUnboxedValue GetListIterator() const final {
  640. return NUdf::TUnboxedValuePod(new TIterator(GetMemInfo(), NextFunc, Ctx, List.GetListIterator()));
  641. }
  642. TComputationContext* const Ctx;
  643. const TNextPtr NextFunc;
  644. const NUdf::TUnboxedValue List;
  645. };
  646. template <class TIterator = TCodegenStatefulIterator<>>
  647. class TCustomListCodegenStatefulValueT : public TCustomListValue {
  648. public:
  649. using TStateType = typename TIterator::TStateType;
  650. using TNextPtr = typename TIterator::TNextPtr;
  651. TCustomListCodegenStatefulValueT(TMemoryUsageInfo* memInfo, TNextPtr next, TComputationContext* ctx, NUdf::TUnboxedValue&& list, TStateType&& init = TStateType())
  652. : TCustomListValue(memInfo)
  653. , Ctx(ctx)
  654. , NextFunc(next)
  655. , List(std::move(list))
  656. , Init(std::move(init))
  657. {}
  658. private:
  659. NUdf::TUnboxedValue GetListIterator() const final {
  660. return NUdf::TUnboxedValuePod(new TIterator(GetMemInfo(), NextFunc, Ctx, List.GetListIterator(), Init));
  661. }
  662. TComputationContext* const Ctx;
  663. const TNextPtr NextFunc;
  664. const NUdf::TUnboxedValue List;
  665. const TStateType Init;
  666. };
  667. using TCustomListCodegenStatefulValue = TCustomListCodegenStatefulValueT<>;
  668. class TListCodegenValue : public TComputationValue<TListCodegenValue> {
  669. public:
  670. using TNextPtr = TCodegenIterator::TNextPtr;
  671. TListCodegenValue(TMemoryUsageInfo* memInfo, TNextPtr next, TComputationContext* ctx, NUdf::TUnboxedValue&& list)
  672. : TComputationValue<TListCodegenValue>(memInfo)
  673. , Ctx(ctx)
  674. , NextFunc(next)
  675. , List(std::move(list))
  676. {}
  677. private:
  678. NUdf::TUnboxedValue GetListIterator() const final {
  679. return NUdf::TUnboxedValuePod(new TCodegenIterator(GetMemInfo(), NextFunc, Ctx, List.GetListIterator()));
  680. }
  681. ui64 GetListLength() const final {
  682. return List.GetListLength();
  683. }
  684. bool HasListItems() const final {
  685. return List.HasListItems();
  686. }
  687. bool HasFastListLength() const final {
  688. return List.HasFastListLength();
  689. }
  690. TComputationContext* const Ctx;
  691. const TNextPtr NextFunc;
  692. const NUdf::TUnboxedValue List;
  693. };
  694. class TCodegenIteratorOne : public TComputationValue<TCodegenIteratorOne> {
  695. public:
  696. using TNextPtr = bool (*)(TComputationContext*, NUdf::TUnboxedValuePod, NUdf::TUnboxedValuePod&);
  697. TCodegenIteratorOne(TMemoryUsageInfo* memInfo, TNextPtr nextOne, TNextPtr nextTwo, TComputationContext* ctx, NUdf::TUnboxedValue&& iterator)
  698. : TComputationValue<TCodegenIteratorOne>(memInfo)
  699. , NextFuncOne(nextOne)
  700. , NextFuncTwo(nextTwo)
  701. , Ctx(ctx)
  702. , Iterator(std::move(iterator))
  703. {}
  704. private:
  705. bool Next(NUdf::TUnboxedValue& value) override {
  706. if (FirstCall) {
  707. FirstCall = false;
  708. return NextFuncOne(Ctx, static_cast<const NUdf::TUnboxedValuePod&>(Iterator), value);
  709. } else {
  710. return NextFuncTwo(Ctx, static_cast<const NUdf::TUnboxedValuePod&>(Iterator), value);
  711. }
  712. }
  713. const TNextPtr NextFuncOne;
  714. const TNextPtr NextFuncTwo;
  715. TComputationContext* const Ctx;
  716. const NUdf::TUnboxedValue Iterator;
  717. bool FirstCall = true;
  718. };
  719. class TListCodegenValueOne : public TComputationValue<TListCodegenValueOne> {
  720. public:
  721. using TNextPtr = TCodegenIteratorOne::TNextPtr;
  722. TListCodegenValueOne(TMemoryUsageInfo* memInfo, TNextPtr nextOne, TNextPtr nextTwo, TComputationContext* ctx, NUdf::TUnboxedValue&& list)
  723. : TComputationValue<TListCodegenValueOne>(memInfo)
  724. , NextFuncOne(nextOne)
  725. , NextFuncTwo(nextTwo)
  726. , Ctx(ctx)
  727. , List(std::move(list))
  728. {}
  729. private:
  730. NUdf::TUnboxedValue GetListIterator() const final {
  731. return NUdf::TUnboxedValuePod(new TCodegenIteratorOne(GetMemInfo(), NextFuncOne, NextFuncTwo, Ctx, List.GetListIterator()));
  732. }
  733. ui64 GetListLength() const final {
  734. return List.GetListLength();
  735. }
  736. bool HasListItems() const final {
  737. return List.HasListItems();
  738. }
  739. bool HasFastListLength() const final {
  740. return List.HasFastListLength();
  741. }
  742. const TNextPtr NextFuncOne;
  743. const TNextPtr NextFuncTwo;
  744. TComputationContext* const Ctx;
  745. const NUdf::TUnboxedValue List;
  746. };
  747. class TStreamCodegenValueStateless : public TComputationValue<TStreamCodegenValueStateless> {
  748. public:
  749. using TBase = TComputationValue<TStreamCodegenValueStateless>;
  750. using TFetchPtr = NUdf::EFetchStatus (*)(TComputationContext*, NUdf::TUnboxedValuePod, NUdf::TUnboxedValuePod&);
  751. TStreamCodegenValueStateless(TMemoryUsageInfo* memInfo, TFetchPtr fetch, TComputationContext* ctx, NUdf::TUnboxedValue&& stream)
  752. : TBase(memInfo)
  753. , FetchFunc(fetch)
  754. , Ctx(ctx)
  755. , Stream(std::move(stream))
  756. {}
  757. protected:
  758. ui32 GetTraverseCount() const final {
  759. return 1;
  760. }
  761. NUdf::TUnboxedValue GetTraverseItem(ui32) const final {
  762. return Stream;
  763. }
  764. NUdf::TUnboxedValue Save() const override {
  765. return NUdf::TUnboxedValue::Zero();
  766. }
  767. bool Load2(const NUdf::TUnboxedValue& state) override {
  768. Y_UNUSED(state);
  769. return false;
  770. }
  771. NUdf::EFetchStatus Fetch(NUdf::TUnboxedValue& result) override {
  772. return FetchFunc(Ctx, static_cast<const NUdf::TUnboxedValuePod&>(Stream), result);
  773. }
  774. const TFetchPtr FetchFunc;
  775. TComputationContext* const Ctx;
  776. const NUdf::TUnboxedValue Stream;
  777. };
  778. class TStreamCodegenValueOne : public TComputationValue<TStreamCodegenValueOne> {
  779. public:
  780. using TBase = TComputationValue<TStreamCodegenValueOne>;
  781. using TFetchPtr = NUdf::EFetchStatus (*)(TComputationContext*, NUdf::TUnboxedValuePod, NUdf::TUnboxedValuePod&);
  782. TStreamCodegenValueOne(TMemoryUsageInfo* memInfo, TFetchPtr fetchOne, TFetchPtr fetchTwo, TComputationContext* ctx, NUdf::TUnboxedValue&& stream)
  783. : TBase(memInfo)
  784. , FetchFuncOne(fetchOne)
  785. , FetchFuncTwo(fetchTwo)
  786. , Ctx(ctx)
  787. , Stream(std::move(stream))
  788. {}
  789. private:
  790. NUdf::EFetchStatus Fetch(NUdf::TUnboxedValue& result) final {
  791. if (FirstCall) {
  792. FirstCall = false;
  793. return FetchFuncOne(Ctx, static_cast<const NUdf::TUnboxedValuePod&>(Stream), result);
  794. } else {
  795. return FetchFuncTwo(Ctx, static_cast<const NUdf::TUnboxedValuePod&>(Stream), result);
  796. }
  797. }
  798. const TFetchPtr FetchFuncOne;
  799. const TFetchPtr FetchFuncTwo;
  800. TComputationContext* const Ctx;
  801. const NUdf::TUnboxedValue Stream;
  802. bool FirstCall = true;
  803. };
  804. template <typename TState = NUdf::TUnboxedValue>
  805. class TStreamCodegenStatefulValueT : public TComputationValue<TStreamCodegenStatefulValueT<TState>> {
  806. public:
  807. using TBase = TComputationValue<TStreamCodegenStatefulValueT<TState>>;
  808. using TFetchPtr = NUdf::EFetchStatus (*)(TComputationContext*, NUdf::TUnboxedValuePod, TState&, NUdf::TUnboxedValuePod&);
  809. TStreamCodegenStatefulValueT(TMemoryUsageInfo* memInfo, TFetchPtr fetch, TComputationContext* ctx, NUdf::TUnboxedValue&& stream, TState&& init = TState())
  810. : TBase(memInfo)
  811. , FetchFunc(fetch)
  812. , Ctx(ctx)
  813. , Stream(std::move(stream))
  814. , State(std::move(init))
  815. {}
  816. protected:
  817. NUdf::EFetchStatus Fetch(NUdf::TUnboxedValue& result) override {
  818. return FetchFunc(Ctx, static_cast<const NUdf::TUnboxedValuePod&>(Stream), State, result);
  819. }
  820. const TFetchPtr FetchFunc;
  821. TComputationContext* const Ctx;
  822. const NUdf::TUnboxedValue Stream;
  823. TState State;
  824. };
  825. using TStreamCodegenStatefulValue = TStreamCodegenStatefulValueT<>;
  826. template <class StateType>
  827. class TStreamCodegenSelfStateValue : public StateType {
  828. using TState = StateType;
  829. public:
  830. using TFetchPtr = NUdf::EFetchStatus (*)(TComputationContext*, NUdf::TUnboxedValuePod, TState* state, NUdf::TUnboxedValuePod&);
  831. template <typename...TArgs>
  832. TStreamCodegenSelfStateValue(TMemoryUsageInfo* memInfo, TFetchPtr fetch, TComputationContext* ctx, NUdf::TUnboxedValue&& stream, TArgs&&...args)
  833. : TState(memInfo, std::forward<TArgs>(args)...)
  834. , FetchFunc(fetch)
  835. , Ctx(ctx)
  836. , Stream(std::move(stream))
  837. {}
  838. private:
  839. NUdf::EFetchStatus Fetch(NUdf::TUnboxedValue& result) override {
  840. return FetchFunc(Ctx, static_cast<const NUdf::TUnboxedValuePod&>(Stream), this, result);
  841. }
  842. const TFetchPtr FetchFunc;
  843. TComputationContext* const Ctx;
  844. const NUdf::TUnboxedValue Stream;
  845. };
  846. template <class StateType>
  847. class TStreamCodegenSelfStatePlusValue : public StateType {
  848. using TState = StateType;
  849. public:
  850. using TFetchPtr = NUdf::EFetchStatus (*)(TComputationContext*, NUdf::TUnboxedValuePod, TState* state, NUdf::TUnboxedValuePod&, NUdf::TUnboxedValuePod&);
  851. template <typename...TArgs>
  852. TStreamCodegenSelfStatePlusValue(TMemoryUsageInfo* memInfo, TFetchPtr fetch, TComputationContext* ctx, NUdf::TUnboxedValue&& stream, TArgs&&...args)
  853. : TState(memInfo, std::forward<TArgs>(args)...)
  854. , FetchFunc(fetch)
  855. , Ctx(ctx)
  856. , Stream(std::move(stream))
  857. {}
  858. private:
  859. NUdf::EFetchStatus Fetch(NUdf::TUnboxedValue& result) override {
  860. return FetchFunc(Ctx, static_cast<const NUdf::TUnboxedValuePod&>(Stream), this, State, result);
  861. }
  862. const TFetchPtr FetchFunc;
  863. TComputationContext* const Ctx;
  864. const NUdf::TUnboxedValue Stream;
  865. NUdf::TUnboxedValue State;
  866. };
  867. template <typename TDerived>
  868. class TCustomValueCodegeneratorNode: public TMutableCodegeneratorFallbackNode<TDerived>, public ICodegeneratorRootNode
  869. {
  870. using TBase = TMutableCodegeneratorFallbackNode<TDerived>;
  871. protected:
  872. TCustomValueCodegeneratorNode(TComputationMutables& mutables)
  873. : TBase(mutables, EValueRepresentation::Boxed)
  874. {}
  875. TString MakeName(const TString& method) const {
  876. TStringStream out;
  877. out << this->DebugString() << "::" << method << "_(" << static_cast<const void*>(this) << ").";
  878. return out.Str();
  879. }
  880. };
  881. template <typename TDerived>
  882. class TBothWaysCodegeneratorNode: public TMutableCodegeneratorRootNode<TDerived>
  883. {
  884. using TBase = TMutableCodegeneratorRootNode<TDerived>;
  885. protected:
  886. TBothWaysCodegeneratorNode(TComputationMutables& mutables)
  887. : TBase(mutables, EValueRepresentation::Boxed)
  888. {}
  889. TString MakeName(const TString& method) const {
  890. TStringStream out;
  891. out << this->DebugString() << "::" << method << "_(" << static_cast<const void*>(this) << ").";
  892. return out.Str();
  893. }
  894. };
  895. template<typename T> Type* GetTypeFor(LLVMContext &context);
  896. template<typename T> inline Value* GetterFor(Value* value, LLVMContext &context, BasicBlock* block) {
  897. const auto trunc = CastInst::Create(Instruction::Trunc, value, std::is_same<T, bool>() ? Type::getInt1Ty(context) : IntegerType::get(context, sizeof(T) << 3U), "trunc", block);
  898. if (std::is_integral<T>::value)
  899. return trunc;
  900. return CastInst::Create(Instruction::BitCast, trunc, GetTypeFor<T>(context), "bitcast", block);
  901. }
  902. template<typename T> inline
  903. Value* SetterFor(Value* value, LLVMContext &context, BasicBlock* block) {
  904. if (value->getType()->isFloatingPointTy())
  905. value = CastInst::Create(Instruction::BitCast, value, IntegerType::get(context, sizeof(T) << 3U), "bitcast", block);
  906. const auto type = Type::getInt128Ty(context);
  907. const auto zext = CastInst::Create(Instruction::ZExt, value, type, "zext", block);
  908. const uint64_t init[] = {0ULL, 0x100000000000000ULL}; // Embedded
  909. const auto meta = ConstantInt::get(context, APInt(128, 2, init));
  910. const auto full = BinaryOperator::CreateOr(zext, meta, "or", block);
  911. return full;
  912. }
  913. Value* SetterForInt128(Value* value, BasicBlock* block);
  914. Value* GetterForInt128(Value* value, BasicBlock* block);
  915. Value* GetterForTimezone(LLVMContext& context, Value* value, BasicBlock* block);
  916. template<typename TSrc, typename TDst> inline
  917. Value* StaticCast(Value* value, LLVMContext &context, BasicBlock* block) {
  918. if (std::is_same<TSrc, TDst>())
  919. return value;
  920. if (std::is_integral<TSrc>() == std::is_integral<TDst>()) {
  921. if (std::is_integral<TSrc>()) {
  922. if (sizeof(TSrc) > sizeof(TDst)) {
  923. if (std::is_same<TDst, bool>())
  924. return CmpInst::Create(Instruction::ICmp, ICmpInst::ICMP_NE, value, ConstantInt::get(value->getType(), 0), "test", block);
  925. else
  926. return CastInst::Create(Instruction::Trunc, value, GetTypeFor<TDst>(context), "trunc", block);
  927. } else if ((sizeof(TSrc) < sizeof(TDst))) {
  928. return CastInst::Create(std::is_signed<TSrc>() ? Instruction::SExt : Instruction::ZExt, value, GetTypeFor<TDst>(context), "ext", block);
  929. } else {
  930. return value;
  931. }
  932. } else {
  933. if (sizeof(TSrc) > sizeof(TDst)) {
  934. return CastInst::Create(Instruction::FPTrunc, value, GetTypeFor<TDst>(context), "fptrunc", block);
  935. } else if ((sizeof(TSrc) < sizeof(TDst))) {
  936. return CastInst::Create(Instruction::FPExt, value, GetTypeFor<TDst>(context), "fpext", block);
  937. } else {
  938. return value;
  939. }
  940. }
  941. } else {
  942. constexpr auto instruction = std::is_integral<TSrc>() ?
  943. std::is_signed<TSrc>() ? Instruction::SIToFP : Instruction::UIToFP:
  944. std::is_signed<TDst>() ? Instruction::FPToSI : Instruction::FPToUI;
  945. return CastInst::Create(instruction, value, GetTypeFor<TDst>(context), std::is_integral<TSrc>() ? "int_to_float" : "float_to_int", block);
  946. }
  947. }
  948. Value* GetOptionalValue(LLVMContext& context, Value* value, BasicBlock* block);
  949. Value* MakeOptional(LLVMContext& context, Value* value, BasicBlock* block);
  950. Value* MakeBoolean(Value* boolean, LLVMContext &context, BasicBlock* block);
  951. ConstantInt* GetEmpty(LLVMContext &context);
  952. ConstantInt* GetTrue(LLVMContext &context);
  953. ConstantInt* GetFalse(LLVMContext &context);
  954. ConstantInt* GetDecimalPlusInf(LLVMContext &context);
  955. ConstantInt* GetDecimalMinusInf(LLVMContext &context);
  956. ConstantInt* GetDecimalNan(LLVMContext &context);
  957. ConstantInt* GetDecimalMinusNan(LLVMContext &context);
  958. ConstantInt* GetInvalid(LLVMContext &context);
  959. ConstantInt* GetFinish(LLVMContext &context);
  960. ConstantInt* GetYield(LLVMContext &context);
  961. ConstantInt* GetConstant(ui64 value, LLVMContext &context);
  962. Value* IsExists(Value* value, BasicBlock* block, LLVMContext &context);
  963. Value* IsEmpty(Value* value, BasicBlock* block, LLVMContext &context);
  964. Value* IsInvalid(Value* value, BasicBlock* block, LLVMContext &context);
  965. Value* IsValid(Value* value, BasicBlock* block, LLVMContext &context);
  966. Value* IsFinish(Value* value, BasicBlock* block, LLVMContext &context);
  967. Value* IsYield(Value* value, BasicBlock* block, LLVMContext &context);
  968. Value* IsSpecial(Value* value, BasicBlock* block, LLVMContext &context);
  969. Value* HasValue(Value* value, BasicBlock* block, LLVMContext &context);
  970. Value* GenNewArray(const TCodegenContext& ctx, Value* size, Value* items, BasicBlock* block);
  971. Value* GetMemoryUsed(ui64 limit, const TCodegenContext& ctx, BasicBlock* block);
  972. template <bool TrackRss>
  973. Value* CheckAdjustedMemLimit(ui64 limit, Value* init, const TCodegenContext& ctx, BasicBlock*& block);
  974. #if __clang__ && (__clang_major__ < 16)
  975. class TSrcLocation {
  976. public:
  977. const char* file_name() const;
  978. size_t line() const;
  979. size_t column() const;
  980. static TSrcLocation current();
  981. };
  982. #else
  983. using TSrcLocation = std::source_location;
  984. #endif
  985. class DIScopeAnnotator;
  986. class DISubprogramAnnotator final {
  987. public:
  988. explicit DISubprogramAnnotator(TCodegenContext& ctx, Function* subprogramFunc, const TSrcLocation& location = TSrcLocation::current());
  989. DIFile* MakeDIFile(const TSrcLocation& location);
  990. ~DISubprogramAnnotator();
  991. private:
  992. DISubprogram* MakeDISubprogram(const StringRef& name, const TSrcLocation& location = TSrcLocation::current());
  993. friend DIScopeAnnotator;
  994. TCodegenContext& Ctx;
  995. std::unique_ptr<DIBuilder> DebugBuilder;
  996. DISubprogram* Subprogram;
  997. Function* Func;
  998. };
  999. class DIScopeAnnotator final {
  1000. public:
  1001. explicit DIScopeAnnotator(DISubprogramAnnotator* subprogramAnnotator, const TSrcLocation& location = TSrcLocation::current());
  1002. Instruction* operator()(Instruction* inst, const TSrcLocation& location = TSrcLocation::current()) const;
  1003. private:
  1004. DISubprogramAnnotator* SubprogramAnnotator;
  1005. DIScope* Scope;
  1006. };
  1007. }
  1008. }
  1009. #endif