/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /*! * \file tvm/ir/function.h * \brief Function nodes. */ #ifndef TVM_IR_FUNCTION_H_ #define TVM_IR_FUNCTION_H_ #include #include #include #include #include #include #include namespace tvm { /*! * \brief Possible Calling conventions. * * NOTE: The calling convention also implies * the way we implement the function during lowering. */ enum class CallingConv : int { /*! * \brief Default calling convention. * * - Uses the native calling convention of the target. * - Implementation: specified by the native target. */ kDefault = 0, /*! * \brief ffi::Function that exposes a Cffi::Function signature. * * - Calling by ffi::Function calling convention. * - Implementation: Expose a function with the Cffi::Function signature. */ kCPackedFunc = 1, /*! * \brief Device kernel launch * * - Call by ffi::Function calling convention. * - Implementation: defined by device runtime(e.g. runtime/cuda) */ kDeviceKernelLaunch = 2, }; /*! * \brief Supported linkage types. */ enum class LinkageType : int { /*! * \brief Internal linkage. */ kInternal = 0, /*! * \brief External linkage. - Function with external linkage should have a global symbol attached to it. */ kExternal = 1 }; /*! * \brief Generic attribute names that can be attached to any function. * * \sa tvm::tirx::attr, tvm::relax::attr */ namespace attr { /*! * \brief Indicates the special calling convention. * * Type: IntImm * * \sa tvm::CallingConv */ constexpr const char* kCallingConv = "calling_conv"; /*! * \brief Compilation target of the function. * * Type: Target * * \sa tvm::Target */ constexpr const char* kTarget = "target"; /*! * \brief Global linker symbol of the function in generated code. * * This option forces the code generator to name the * function with the given. * * For example, we could set a global_symbol of a function * early to make sure that we can always refer to it by * the symbol name in the generated DLL. * * We should not set the attribute for local functions, * so that the compiler can freely rename them. * * A unique global symbol will be automatically assigned * to each function in the module before the target code * generation phase. * * Type: String */ constexpr const char* kGlobalSymbol = "global_symbol"; /*! * \brief The function uses s_tir (apache-derived TIR) semantics: * parser fills layout=None, ScriptComplete wraps body in a root SBlock, * and printer emits `s_tir=True` on the decorator. * Default (attr absent or False) is tirx semantics. * * Type: IntImm (bool dtype) */ constexpr const char* kSTir = "s_tir"; /*! * \brief Number of inputs of the Primfunc * * Type: Int */ constexpr const char* kNumInputs = "num_inputs"; } // namespace attr /*! * \brief Base node of all functions. * * We support several variants of functions throughout the stack. * All of the functions share the same type system * to support cross variant calls. * * \sa BaseFunc */ class BaseFuncNode : public ExprNode { public: /*! \brief Additional attributes storing the meta-data */ DictAttrs attrs; /*! * \brief Get a function attribute. * * \param attr_key The attribute key. * \param default_value The default value if the key does not exist, defaults to nullptr. * * \return The result * * \tparam TOBjectRef the expected object type. * \throw Error if the key exists but the value does not match TObjectRef * * \code * * void GetAttrExample(const BaseFunc& f) { * auto value = f->GetAttr("AttrKey", 0); * } * * \endcode */ template ffi::Optional GetAttr(const std::string& attr_key, ffi::Optional default_value = std::nullopt) const { return attrs.GetAttr(attr_key, default_value); } // variant that uses TObjectRef to enable implicit conversion to default value. template ffi::Optional GetAttr(const std::string& attr_key, TObjectRef default_value) const { return GetAttr(attr_key, ffi::Optional(default_value)); } /*! * \brief Check whether the function has an non-zero integer attr. * * This function can be used to check whether an optional * attribute mark(e.g. inline) exists. * * \param attr_key The key to the attribute. * \return The check result. * * \code * * void HasNonzeroAttrExample(const BaseFunc& f) { * if (f->HasNonzeroAttr(attr::kInline)) { * // inline the function. * } * } * * \endcode */ bool HasNonzeroAttr(const std::string& attr_key) const { return attrs.HasNonzeroAttr(attr_key); } /*! * \brief Get the type of the linkage. * * Currently, we only consider external/internal linkage. * This can be extended in the future when necessary. * * \return Linkage type. * * \code * * void Example(const BaseFunc& f) { * if (f->GetLinkageType() == tvm::LinkageType::kExternal) { * // Do not remove a function with external linkage * } * } * * \endcode */ LinkageType GetLinkageType() const { if (GetAttr(attr::kGlobalSymbol)) return LinkageType::kExternal; else return LinkageType::kInternal; } static void RegisterReflection() { namespace refl = tvm::ffi::reflection; refl::ObjectDef().def_ro("attrs", &BaseFuncNode::attrs); } static constexpr const uint32_t _type_child_slots = 2; TVM_FFI_DECLARE_OBJECT_INFO("ir.BaseFunc", BaseFuncNode, ExprNode); }; /*! * \brief Managed reference to BaseFuncNode. * \sa BaseFuncNode */ class BaseFunc : public Expr { public: TVM_FFI_DEFINE_OBJECT_REF_METHODS_NULLABLE(BaseFunc, Expr, BaseFuncNode); }; } // namespace tvm #endif // TVM_IR_FUNCTION_H_