LLiHengsync code
de223dd1创建于 2022年3月4日历史提交
/*
 * Copyright (c) 2020 Huawei Technologies Co.,Ltd.
 *
 * openGauss is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *
 *          http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 * ---------------------------------------------------------------------------------------
 * 
 * vecexprcodegen.h
 *        Declarations of code generation for vecexpression funtions.
 *
 * For each expression, first decide if this expression can be LLVM optimized
 * or not according to the detail information. The expression functions
 * accomplished here have the same functionality as the ones defined in
 * vecexpression.h, though more constraints are used. 
 * 
 * IDENTIFICATION
 *        src/include/codegen/vecexprcodegen.h
 *
 * ---------------------------------------------------------------------------------------
 */
#ifndef LLVM_VECEXPRESSION_H
#define LLVM_VECEXPRESSION_H
#include "optimizer/clauses.h"
#include "nodes/execnodes.h"
#include "codegen/gscodegen.h"

namespace dorado {
#ifdef ENABLE_LLVM_COMPILE
/*
 * @Description	: Arguments used for Vectorized Expression CodeGen Engine.
 */
typedef struct {
    ExprState* exprstate;            /* Expression information used to
                                        generate IR function */
    PlanState* parent;               /* The parent planstate information */
    GsCodeGen::LlvmBuilder* builder; /* LLVM builder in upper level */
    llvm::Value** llvm_args;         /* LLVM parameters*/
} ExprCodeGenArgs;

/*
 * @Description : Parameters needed to pass to the original c-function.
 */
typedef struct {
    int nargs;              /* number of args */
    llvm::Value** args;     /* values of parameters with length nargs */
    llvm::Value** argnulls; /* flags of parameters with length nargs */
} LLVMFuncCallInfo;

typedef llvm::Value* (*VectorExprCodeGen)(ExprCodeGenArgs* args);

/*
 * LlvmExecQual class implements specific optimization by using LLVM.
 */
class VecExprCodeGen : public BaseObject {
public:
    /*
     * @Brief       : Check whether state could be  legal or not.
     * @Description : Check is the current state->expr could be codegened
     *				  or not.
     * @in state	: exprstate, the node to be checked.
     * @return		: return true is state could be codegened.
     */
    static bool ExprJittable(ExprState* state);

    /*
     * The following functions are codegen functions and their guardian function:
     * Since each expression has its own restricts, we should consider them
     * independently. For each expression, we have one guardian function and
     * one codegen function.
     */

    /*
     * @Brief		: Check if the whole qual list can be codegened or not.
     * @Description : Check if the qual list can be codegened or not. The qual
     *				  list can be joinqual, hashjoin_clauses and so on.
     * @in qual		: the expr node list need to be checked.
     * @return 		: return true if the whole qual can be codegened.
     */
    static bool QualJittable(List* qual);

    /*
     * @Brief		: Code generation for ExecEvalQual.
     * @Description : Since ExprState stored the plan-tree information, ExprContext
     *				  stored the actual data information during execution. We need
     *				  to separate these two parameters in 'InitNode' and 'ExecNode'
     *                status. So during expression processes, we should pass through
     *				  'Expr' as parameter in 'InitNode' and pass through 'econtext'
     *                as LLVM parameter in 'ExecNode'.
     * @in qual		: the expr node list need to be codegened.
     * @in parent	: the whole planstate of the expr node.
     * @return 		: ScalarVector result of the qual list in LLVM assemble.
     * @notes       : firstly, econtext is passed when qual is needed; secondly, for
     *				  each LLVM function in ExecVecQual, the interface is
     *				  LLVM_Expr_Func(ExprCodeGenArgs);
     */
    static llvm::Function* QualCodeGen(List* qual, PlanState* parent, bool isReset = true);

    /*
     * @Description	: Check if the scalararrayop expr can be codegened or not.
     * @in state	: ExprState of ScalarArrayOpExpr.
     * @return		: return true if scalararrayop expr can be codegened.
     */
    static bool ScalarArrayJittable(ExprState* state);

    /*
     * @Brief		: Codegen for scalararrayop expression.
     * @Description	: Codegeneration of the ExecEvalVecScalarArrayOp:
     *				  For integer/float/date/timestamp, we use switch
     *				  structure in LLVM, for bpchar/varchar/text, we use
     *				  codegen function.
     * @in args		: arguments of vector expr codegen engine.
     * @return		: return true when tuple satisfies the condition
     * @Notes        : Support ...in (...) and any(array[....]) only.
     */
    static llvm::Value* ScalarArrayCodeGen(ExprCodeGenArgs* args);

    /*
     * @Description : Check if the boolean test expr can be codegened or not.
     * @in state	: ExprState of BooleanTest Expr.
     * @Output		: return true if boolean test expr can be codegened.
     */
    static bool BooleanTestJittable(ExprState* state);

    /*
     * @Brief 		: Codegen for boolean test expression.
     * @Description : Codegeneration of the ExecEvalBooleanTest.
     * @in args		: arguments of vector expr codegen engine.
     * @return		: return the result of Boolean Test Expr.
     */
    static llvm::Value* BooleanTestCodeGen(ExprCodeGenArgs* args);

    /*
     * @Description : Check if the null test expr can be codegened or not.
     *
     * @in state	: NullTest ExprState.
     * @return      : return true if nulltest expr can be codegened.
     */
    static bool NullTestJittable(ExprState* state);

    /*
     * @Brief       : Codegen for NullTest expression.
     * @Description : Codegeneration of the ExecEvalNullTest: contains
     *				  IS_NULL, IS_NOT_NULL.
     * @in args		: arguments of vector expr codegen engine.
     * @return 		: return true only if argument is nulll, else return false.
     */
    static llvm::Value* NullTestCodeGen(ExprCodeGenArgs* args);

    /*
     * @Brief       : Check if the oper func can be codegened or not.
     * @Description : Check if the FuncExprState can be codegened or not :
     *				  right now most of the oper expr can be codegened, but
     *				  some of them still have some constraints.
     * @in state	: ExprState representation of FuncExprSate.
     * @return 		: return true if the operation function can be codegened.
     */
    static bool OpJittable(ExprState* state);

    /*
     * @Brief			: Check if the oper func with numeric data can be codegened in special path.
     * @Description	: Check if the Numeric OperExpr can be codegened in a special way:
     *				  the data we considered here are all can be represented in BI64.
     * @in state		: ExprState representation of OperExprSate.
     * @return 		: return true if the operation function can be codegened in fast path.
     */
    static bool NumericOpFastJittable(ExprState* state);

    /*
     * @Brief       : Codegen for vecoper expression.
     * @Description : Codegeneration of the ExecEvalVecOp: Right row
     *				  we only support several cases with data type
     *				  int/float/date/timestamp and text(eq,gt)/bpchar(eq)
     * @in args		: arguments of vector expr codegen engine.
     * @return		: return the result of oper expr in LLVM assemble.
     * @Notes       : Since we have not codegen ExecMakeVecFunctionResult
     *				  as we do in vecexpression.cpp, only seveal cases
     *				  are supported.
     */
    static llvm::Value* OpCodeGen(ExprCodeGenArgs* args);

    /*
     * @Brief       : Codegen for numeric type operation expression.
     * @Description : Codegeneration for numeric operation expression: we make a special
     *			path for data that can be transformed to BI64. While for other cases,
     *			we use normal codegen path(NormalNumericOpCodeGen).
     * @in ptrbuilder	: LLVM Builder associated with the current module.
     * @in estate	: opexprstate associated with current operation.
     * @in funcoid	: function oid of current numeric operation.
     * @in larg	: left argument passed to llvm.
     * @in rarg	: right argument passed to llvm.
     */
    static llvm::Value* FastNumericOpCodeGen(
        GsCodeGen::LlvmBuilder* ptrbuilder, ExprState* estate, llvm::Value* larg, llvm::Value* rarg);
    static llvm::Value* NormalNumericOpCodeGen(
        GsCodeGen::LlvmBuilder* ptrbuilder, Oid funcoid, llvm::Value* larg, llvm::Value* rarg);

    /*
     * @Brief       : Check if the FuncExpr can be codegened or not.
     * @Description : Check if the FuncExprState can be codegened or not :
     *				  right now most of the func expr can be codegened, but
     *				  some of them still have some constraints.
     * @in state	: ExprState representation of FuncExprSate.
     * @return		: return true if the func can be codegen.
     * @Notes        : We only support C / UTF-8 encoding.
     */
    static bool FuncJittable(ExprState* state);

    /*
     * @Brief       : Codegen for vecfunc expression.
     * @Description : Codegeneration of the ExecEvalVecFunc: Only part of them
     *				  have been codegened, the rest would be used by
     *				  call original C-Function.
     * @in args		: arguments of vector expr codegen engine.
     * @return		: result of ExecEvalFunc in LLVM assemble.
     * @Notes       : We only support C / UTF-8 encoding.
     */
    static llvm::Value* FuncCodeGen(ExprCodeGenArgs* args);

    /*
     * @Brief       : Check if veccase expression can be codegened or not.
     * @Description : Codegeneration of the ExecEvalVecCase: The logic here
     *				  is the same as ExecEvalVecCase. Since operation is only
     *				  partly supported, the exprs in case arg/when expr/default
     *				  expr are the ones supported by OpCodeGen.
     * @in state	: context of CaseExprState
     * @return      : return true if veccase expr can be codegened.
     */
    static bool CaseJittable(ExprState* state);

    /*
     * @Brief        : Codegen for veccase expression.
     * @Description  : Codegeneration of the ExecEvalVecCase: The logic here
     *				  is the same as ExecEvalVecCase. Since operation is only
     *				  partly supported, the exprs in case arg/when expr/default
     *				  expr are the ones supported by OpCodeGen.
     * @in args		: arguments of vector expr codegen engine.
     * @return      : wclause->result or default->result in LLVM assemble.
     */
    static llvm::Value* CaseCodeGen(ExprCodeGenArgs* args);

    /*
     * @Brief       : Check if nullif expression can be codegened or not.
     * @Description : Codegeneration of the ExecEvalVecNullif checking.
     * @in state    : ExprState
     * @return      : return true if nullif expr can be codegened.
     */
    static bool NullIfJittable(ExprState* state);

    /*
     * Brief       : Codegen for nullif expression.
     * Description : NullIfCodeGen is  the codegeneration of the ExecEvalVecNullIf.
     * Input       : ExprCodeGenArgs
     * Output      : when expr1=expr2 return null, else return expr1.
     * Notes       : None.
     */
    static llvm::Value* NullIfCodeGen(ExprCodeGenArgs* args);

    /*
     * @Brief       : Check if and/or/not expr can be codegened or not.
     * @Description : Check if the bool expr can be codegened or not. The
     *				  expr type contatins and, or and not expr. While
     *				  and/or expression and not expression should be
     *				  considered independently.
     * @in state    : the context of bool expr state
     * @return      : return true the expr in state can be codegened.
     */
    static bool BoolJittable(ExprState* state);

    /*
     * @Brief       : Codegen for vector and/or expression.
     * @Description : Codegeneration of the ExecEvalProcessAndOrLogic: The
     *				  logic here is the same as ExecEvalProcessAndOrLogic.
     *				  BoolJittable would check and/or/not expression argument,
     *				  but and/or expression and not expression would be
     *				  considered independently.
     * @in args     : arguments of vector expr codegen engine.
     * @return		: the and/or expr's result in LLVM assemble.
     */
    static llvm::Value* AndOrLogicCodeGen(ExprCodeGenArgs* args);

    /*
     * @Brief 		: Codegen for vector not expression.
     * @Description	: Codegeneration of the ExecEvalVecNot.
     * @in args		: arguments of vector expr codegen engine.
     * @return		: the not expr's result in LLVM assemble.
     */
    static llvm::Value* NotCodeGen(ExprCodeGenArgs* args);

    /*
     * @Brief       : Check if vecrelabel expr can be codegened or not.
     * @Description : Check if the relabel expr in genericexprstate can be
     *				: codegened or not. Only support the case when arg
     *				: is a var or casetestexpr.
     * @in state    : context of relabel expr.
     * @return		: return true if relabel expr can be codegened.
     */
    static bool RelabelJittable(ExprState* state);

    /*
     * @Brief       : Codegen for vecrelabel expression.
     * @Description : Codegeneration of the ExecEvalVecRelabelType:
     *				  Support the case when arg is a var or casetestexpr.
     * @in args     : arguments of vector expr codegen engine.
     * @return		: result of relabel expr in LLVM assemble
     */
    static llvm::Value* RelabelCodeGen(ExprCodeGenArgs* args);

    /*
     * @Brief       : Check if the var expr can be codegened or not.
     * @Description : Check if the Var in state can be codegened or not,
     *				: only need to consider the var type.
     * @in state    : context of Var Expr State
     * @return      : return true if const expr can be codegened.
     */
    static bool VarJittable(ExprState* state);

    /*
     * @Brief       : Codegen for evalvar expr.
     * @Description : Codegeneration of the ExecEvalVecVar : Get the
     *				  values from econtext->vectorbatch with fixed
     *				  column index and row index(loop_index). Also we
     *				  should restore the null flag.
     * @in args		: arguments of vector expr codegen engine.
     * @out isNull  : null flag of batch->m_arr[varattno-1]
     * @return		: return true if const expr can be codegened.
     */
    static llvm::Value* VarCodeGen(ExprCodeGenArgs* args);

    /*
     * @Brief       : Codegen for vecconst expression.
     * @Description : Check is const expr could be codegened or not.
     * @in state	: const expr state.
     * @return		: return true if const expr can be codegened.
     */
    static bool ConstJittable(ExprState* state);

    /*
     * @Brief       : Codegen for vecconst expression.
     * @Description : Codegeneration of the ExecEvalVecConst
     * @in args		: arguments of vector expr codegen engine.
     * @return		: the value in const expr.
     */
    static llvm::Value* ConstCodeGen(ExprCodeGenArgs* args);

    /*
     * @Brief		: Check if the targetlist could be codegened or not.
     * @Description : Check the jittable of the ExecVecTargetList, which
     *				: evaluates a targetlist with respect to the given
     *				: expression context in LLVM assemble.
     * @in targetlist	: the expr node list need to be checked.
     * @return		: return true if we were able to codegen the list.
     */
    static bool TargetListJittable(List* targetlist);

    /*
     * @Brief       : Codegen for TargetList expression.
     * @Description : Codegeneration of the ExecVecTargetList, which
     *				: evaluates a targetlist with respect to the given
     *				: expression context in LLVM assemble.
     * @in targetlist	: the expr node list need to be codegened.
     * @in parent	: PlanState of the whole targetlist.
     * @return 		: LLVM function of targetlist expr.
     */
    static llvm::Function* TargetListCodeGen(List* targetlist, PlanState* parent);

    /*
     * @Description	: CodeGen routine for Expression.
     * @in args		: arguments of vector expr codegen engine.
     * @return		: the result of current args->exprstate.
     */
    static llvm::Value* CodeGen(ExprCodeGenArgs* args);

    /*
     * @Brief		: CodeGen for general function call.
     * @Description	: For functions we do not codegened, invoke these
     *				  function in LLVM assemble, and reduce the logical
     *				  branches in dealing with arguments and return vals
     *				  by using LLVM optimization.
     * @in ptrbuilder	: LLVM Builder associated with the current module.
     * @in fcache	: The function expr dealed with.
     * @in isNull	: used to record the null flag of the return value.
     * @in lfcinfo	: arguments about fcache.
     *
     */
    static llvm::Value* EvalFuncResultCodeGen(
        GsCodeGen::LlvmBuilder* ptrbuilder, FuncExprState* fcache, llvm::Value* isNull, LLVMFuncCallInfo* lfcinfo);

    /*
     * @Brief		: Make sure the ExtractFunc according the datum type.
     * @Description	: Wrap all the Extract Func in LLVM assemble, which could
     *				: easily deal with input argument according the different
     *				: datum type.
     * @in ptrbuilder	: LLVM Builder associated with the current module.
     * @in argtyp	: input argument datum type.type
     * @in data		: input data
     * @return		: the result after extraction.
     */
    static llvm::Value* WrapChooExtFunCodeGen(GsCodeGen::LlvmBuilder* ptrbuilder, Oid argtyp, llvm::Value* argval);
    static llvm::Value* WrapExtFixedTypeCodeGen(GsCodeGen::LlvmBuilder* ptrbuilder, llvm::Value* data);
    static llvm::Value* WrapExtAddrTypeCodeGen(GsCodeGen::LlvmBuilder* ptrbuilder, llvm::Value* data);
    static llvm::Value* WrapExtCStrTypeCodeGen(GsCodeGen::LlvmBuilder* ptrbuilder, llvm::Value* data);
    static llvm::Value* WrapExtVarTypeCodeGen(GsCodeGen::LlvmBuilder* ptrbuilder, llvm::Value* data);

    /*
     * @Brief		: Wrap Datum to Scalar Func according the datum type.
     * @Description	: Wrap all the Convert Func in LLVM assemble.
     * @in ptrbuilder	: LLVM Builder associated with the current module.
     * @in val		: input data argument.
     * @in len		: the argument data len with respect to datum type.
     * @return		: the result after conversation.
     */
    static llvm::Value* WrapDFixLToScalCodeGen(GsCodeGen::LlvmBuilder* ptrbuilder, llvm::Value* val, llvm::Value* len);
    static llvm::Value* WrapDCStrToScalCodeGen(GsCodeGen::LlvmBuilder* ptrbuilder, llvm::Value* val);

    /*
     * @Description : Wrap the c-function : GetVectorBatch, which is used to
     *				  get the vectorbatch during vectargetlist-codegeneration.
     * @in ptrbuilder	: LLVM Builder associated with the current module.
     * @in econtext	: exprcontext in LLVM assemble.
     */
    static llvm::Value* WrapGetVectorBatchCodeGen(GsCodeGen::LlvmBuilder* ptrbuilder, llvm::Value* econtext);

    /*
     * @Brief		: Wrap the Invoke function.
     * @Description	: Codegen the interface, used to call the original
     * 				: C-Function - FunctionCallInvoke, only consider strict
     *				: function, where we do not consider the flag of args.
     * @in ptrbuilder	: LLVM Builder associated with the current module.
     * @in fcinfo	: data with FunctionCallInfo type in LLVM assemble.
     * @in arg		: array of arguments, contain the arguments of fcinfo
     *				: and the flag of the result.
     */
    static llvm::Value* WrapStrictOpFuncCodeGen(
        GsCodeGen::LlvmBuilder* ptrbuilder, llvm::Value* fcinfo, llvm::Value* arg, llvm::Value* isNull);

    /*
     * @Brief		: Wrap the Invoke function.
     * @Description	: Codegen the interface, used to call the original
     * 				: C-Function - FunctionCallInvoke, only consider non-strict
     *				: function.
     * @in ptrbuilder	: LLVM Builder associated with the current module.
     * @in fcinfo	: data with FunctionCallInfo type in LLVM assemble.
     * @in arg		: array of arguments, contain the arguments of fcinfo
     *				: and the flag of the result.
     * @in argnull	: the flag of the input args.
     * @in isNull	: the flag of the result.
     */
    static llvm::Value* WrapNonStrictOpFuncCodeGen(GsCodeGen::LlvmBuilder* ptrbuilder, llvm::Value* fcinfo,
        llvm::Value* arg, llvm::Value* argnull, llvm::Value* isNull);

    /*
     * @Brief		: Wrap the Invoke function.
     * @Description	: Codegen the interface, used to call the original
     * 				: C-Function - MemoryContextSwitchTo.
     * @in ptrbuilder	: LLVM Builder associated with the current module.
     * @in context	: MemoryContext that we want to access.
     */
    static llvm::Value* MemCxtSwitToCodeGen(GsCodeGen::LlvmBuilder* ptrbuilder, llvm::Value* context);
};
#endif
}  // namespace dorado
#endif