mkql_unwrap.cpp 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. #include "mkql_unwrap.h"
  2. #include <yql/essentials/minikql/computation/mkql_computation_node_codegen.h> // Y_IGNORE
  3. #include <yql/essentials/minikql/mkql_node_cast.h>
  4. #include <yql/essentials/minikql/mkql_node_builder.h>
  5. #include <yql/essentials/public/udf/udf_terminator.h>
  6. #include <yql/essentials/public/udf/udf_type_builder.h>
  7. namespace NKikimr {
  8. namespace NMiniKQL {
  9. namespace {
  10. class TUnwrapWrapper : public TDecoratorCodegeneratorNode<TUnwrapWrapper> {
  11. typedef TDecoratorCodegeneratorNode<TUnwrapWrapper> TBaseComputation;
  12. public:
  13. TUnwrapWrapper(IComputationNode* optional, IComputationNode* message, const NUdf::TSourcePosition& pos)
  14. : TBaseComputation(optional)
  15. , Message(message)
  16. , Pos(pos)
  17. {
  18. }
  19. NUdf::TUnboxedValuePod DoCalculate(TComputationContext& compCtx, const NUdf::TUnboxedValuePod& value) const {
  20. if (value) {
  21. return value.GetOptionalValue();
  22. }
  23. Throw(this, &compCtx);
  24. }
  25. #ifndef MKQL_DISABLE_CODEGEN
  26. Value* DoGenerateGetValue(const TCodegenContext& ctx, Value* value, BasicBlock*& block) const {
  27. auto& context = ctx.Codegen.GetContext();
  28. const auto kill = BasicBlock::Create(context, "kill", ctx.Func);
  29. const auto good = BasicBlock::Create(context, "good", ctx.Func);
  30. BranchInst::Create(kill, good, IsEmpty(value, block, context), block);
  31. block = kill;
  32. const auto doFunc = ConstantInt::get(Type::getInt64Ty(context), GetMethodPtr(&TUnwrapWrapper::Throw));
  33. const auto doFuncArg = ConstantInt::get(Type::getInt64Ty(context), (ui64)this);
  34. const auto doFuncType = FunctionType::get(Type::getVoidTy(context), { Type::getInt64Ty(context), ctx.Ctx->getType() }, false);
  35. const auto doFuncPtr = CastInst::Create(Instruction::IntToPtr, doFunc, PointerType::getUnqual(doFuncType), "thrower", block);
  36. CallInst::Create(doFuncType, doFuncPtr, { doFuncArg, ctx.Ctx }, "", block)->setTailCall();
  37. new UnreachableInst(context, block);
  38. block = good;
  39. return GetOptionalValue(context, value, block);
  40. }
  41. #endif
  42. private:
  43. [[noreturn]] static void Throw(TUnwrapWrapper const* thisPtr, TComputationContext* ctxPtr) {
  44. auto message = thisPtr->Message->GetValue(*ctxPtr);
  45. auto messageStr = message.AsStringRef();
  46. TStringBuilder res;
  47. res << thisPtr->Pos << " Failed to unwrap empty optional";
  48. if (messageStr.Size() > 0) {
  49. res << ":\n\n" << TStringBuf(messageStr) << "\n\n";
  50. }
  51. UdfTerminate(res.data());
  52. }
  53. IComputationNode* const Message;
  54. const NUdf::TSourcePosition Pos;
  55. };
  56. }
  57. IComputationNode* WrapUnwrap(TCallable& callable, const TComputationNodeFactoryContext& ctx) {
  58. MKQL_ENSURE(callable.GetInputsCount() == 5, "Expected 5 args");
  59. const TStringBuf file = AS_VALUE(TDataLiteral, callable.GetInput(2))->AsValue().AsStringRef();
  60. const ui32 row = AS_VALUE(TDataLiteral, callable.GetInput(3))->AsValue().Get<ui32>();
  61. const ui32 column = AS_VALUE(TDataLiteral, callable.GetInput(4))->AsValue().Get<ui32>();
  62. return new TUnwrapWrapper(LocateNode(ctx.NodeLocator, callable, 0), LocateNode(ctx.NodeLocator, callable, 1),
  63. NUdf::TSourcePosition(row, column, file));
  64. }
  65. }
  66. }