Files
wehub-resource-sync 26446540fa
Lint / lint (push) Waiting to run
CI / MacOS (push) Waiting to run
CI / Windows (push) Waiting to run
chore: import upstream snapshot with attribution
2026-07-13 13:36:25 +08:00

367 lines
12 KiB
C++

/*
* 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/module.h
* \brief IRModule that holds the functions and type definitions.
*/
#ifndef TVM_IR_MODULE_H_
#define TVM_IR_MODULE_H_
#include <tvm/ffi/container/array.h>
#include <tvm/ffi/container/map.h>
#include <tvm/ffi/reflection/registry.h>
#include <tvm/ffi/string.h>
#include <tvm/ir/cow.h>
#include <tvm/ir/expr.h>
#include <tvm/ir/function.h>
#include <tvm/ir/global_info.h>
#include <tvm/ir/source_map.h>
#include <tvm/ir/type.h>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
namespace tvm {
class IRModule;
/*!
* \brief IRModule that holds functions and type definitions.
*
* IRModule is the basic unit for all IR transformations across the stack.
*
* Many operations require access to the global IRModule.
* We pass the IRModule by value in a functional style as an explicit argument,
* but we mutate the Module while optimizing programs.
* \sa IRModule
*/
class IRModuleNode : public ffi::Object {
public:
/*! \brief A map from ids to all global functions. */
ffi::Map<GlobalVar, BaseFunc> functions;
/*! \brief The source map for the module. */
SourceMap source_map;
/* \brief Additional attributes storing meta-data about the module. */
DictAttrs attrs;
/*! \brief Globally static object that are referred by the IR itself */
ffi::Map<ffi::String, ffi::Array<GlobalInfo>> global_infos;
/*!
* \brief A map from string names to global variables that
* ensures global uniqueness.
*/
ffi::Map<ffi::String, GlobalVar> global_var_map_;
/*!
* \brief Get a module 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 IRModule& mod) {
* auto value = f->GetAttr<int64_t>("AttrKey", 0);
* }
*
* \endcode
*/
template <typename TObjectRef>
ffi::Optional<TObjectRef> GetAttr(
const std::string& attr_key,
ffi::Optional<TObjectRef> default_value = ffi::Optional<TObjectRef>(std::nullopt)) const {
return attrs.GetAttr(attr_key, default_value);
}
// variant that uses TObjectRef to enable implicit conversion to default value.
template <typename TObjectRef>
ffi::Optional<TObjectRef> GetAttr(const std::string& attr_key, TObjectRef default_value) const {
return GetAttr<TObjectRef>(attr_key, ffi::Optional<TObjectRef>(default_value));
}
/*!
* \brief Get the metadata attributes.
* \returns The additional meta-data attributes
*/
DictAttrs GetAttrs() const { return attrs; }
/*!
* \brief Check whether the module 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 IRModule& mod) {
* if (mod->HasNonzeroAttr(attr::kInline)) {
* // inline the function.
* }
* }
*
* \endcode
*/
bool HasNonzeroAttr(const std::string& attr_key) const { return attrs.HasNonzeroAttr(attr_key); }
IRModuleNode() : source_map() {}
static void RegisterReflection() {
namespace refl = tvm::ffi::reflection;
refl::ObjectDef<IRModuleNode>()
.def_ro("functions", &IRModuleNode::functions)
.def_ro("global_var_map_", &IRModuleNode::global_var_map_)
.def_ro("source_map", &IRModuleNode::source_map)
.def_ro("attrs", &IRModuleNode::attrs)
.def_ro("global_infos", &IRModuleNode::global_infos);
// register custom structural equal and hash.
refl::TypeAttrDef<IRModuleNode>()
.def("__s_equal__", &IRModuleNode::SEqual)
.def("__s_hash__", &IRModuleNode::SHash);
}
TVM_DLL bool SEqual(const IRModuleNode* other,
ffi::TypedFunction<bool(AnyView, AnyView, bool, AnyView)> equal) const;
TVM_DLL int64_t SHash(int64_t init_hash,
ffi::TypedFunction<int64_t(AnyView, int64_t, bool)> hash) const;
/*!
* \brief Add a function to the global environment.
* \param var The var of the global function.
* \param func The function.
* \param update Controls whether you can replace a definition in the
* environment.
*/
TVM_DLL void Add(const GlobalVar& var, const BaseFunc& func, bool update = false);
/*!
* \brief Add a function to the global environment.
* \param var The name of the global function.
* \param func The function.
*
* It does not do type inference as Add does.
*/
TVM_DLL void AddUnchecked(const GlobalVar& var, const BaseFunc& func);
/*!
* \brief Update a function in the global environment.
* \param var The name of the global function to update.
* \param func The new function.
*/
TVM_DLL void Update(const GlobalVar& var, const BaseFunc& func);
/*!
* \brief Update an array of global infos in the global environment.
* \param name The name of the global info.
* \param info The new array of global infos.
*/
TVM_DLL void UpdateGlobalInfo(const ffi::String& name, const ffi::Array<GlobalInfo>& info);
/*!
* \brief Remove a function from the global environment.
* \param var The name of the global function to update.
*/
TVM_DLL void Remove(const GlobalVar& var);
/*!
* \brief Check if the global_var_map_ contains a global variable.
* \param name The variable name.
* \returns true if contains, otherise false.
*/
TVM_DLL bool ContainGlobalVar(const ffi::String& name) const;
/*!
* \brief Lookup a global function by its variable.
* \param str The unique string specifying the global variable.
* \returns The global variable.
*/
TVM_DLL GlobalVar GetGlobalVar(const ffi::String& str) const;
/*!
* \brief Collect all global vars defined in this module, ordered by
* the global variable name.
* \returns An array of global vars
*/
TVM_DLL ffi::Array<GlobalVar> GetGlobalVars() const;
/*!
* \brief Look up a global function by its variable.
* \param var The global var to lookup.
* \returns The function named by the variable argument.
*/
TVM_DLL BaseFunc Lookup(const GlobalVar& var) const;
/*!
* \brief Look up a global function by its string name
* \param name The name of the function.
* \returns The function named by the argument.
*/
TVM_DLL BaseFunc Lookup(const ffi::String& name) const;
/*!
* \brief Update the functions inside this environment by
* functions in another environment.
* \param other The other environment.
*/
TVM_DLL void Update(const IRModule& other);
/*!
* \brief Create a shallow copy of this IRModule.
* \returns The shallow copy of the IRModule.
*/
TVM_DLL IRModule ShallowCopy();
/*!
* \brief The set of imported files.
*/
TVM_DLL std::unordered_set<ffi::String> Imports() const;
static constexpr TVMFFISEqHashKind _type_s_eq_hash_kind = kTVMFFISEqHashKindTreeNode;
TVM_FFI_DECLARE_OBJECT_INFO_FINAL("ir.IRModule", IRModuleNode, ffi::Object);
private:
friend class IRModule;
};
/*!
* \brief Managed reference class to IRModuleNode.
* \sa IRModuleNode
*/
class IRModule : public ffi::ObjectRef {
public:
/*!
* \brief constructor
* \param functions Functions in the module.
* \param map The module source map.
* \param attrs The module meta-data attributes.
* \param global_infos Global infos in the module.
*/
TVM_DLL explicit IRModule(ffi::Map<GlobalVar, BaseFunc> functions, SourceMap map = {},
DictAttrs attrs = DictAttrs(),
ffi::Map<ffi::String, ffi::Array<GlobalInfo>> global_infos = {});
/*! \brief default constructor */
IRModule() : IRModule(ffi::Map<GlobalVar, BaseFunc>({})) {}
/*!
* \brief constructor
* \param n The object pointer.
*/
explicit IRModule(ffi::ObjectPtr<IRModuleNode> n) : ffi::ObjectRef(n) {}
/*!
* \brief constructor with UnsafeInit
*/
explicit IRModule(ffi::UnsafeInit tag) : ffi::ObjectRef(tag) {}
/*! \return mutable pointers to the node. */
IRModuleNode* operator->() const {
auto* ptr = get_mutable();
TVM_FFI_ICHECK(ptr != nullptr);
return static_cast<IRModuleNode*>(ptr);
}
/*!
* \brief As for \p FromExprInContext, but assuming \p expr is bound to 'main' and no
* imports.
*/
TVM_DLL static IRModule FromExpr(const Expr& expr,
const ffi::Map<GlobalVar, BaseFunc>& global_funcs = {});
/*!
* \brief Create a shallow copy of an IRModule.
* \param mod The module to copy.
* \return The copied module.
*/
IRModule ShallowCopyIRModule(IRModule mod);
/*! \brief Declare the container type. */
using ContainerType = IRModuleNode;
// allow copy on write.
TVM_DEFINE_OBJECT_REF_COW_METHOD(IRModuleNode);
};
namespace attr {
// Following are attributes for IRModule only.
/*!
* \brief Name of the module
*
* Type: String
*/
constexpr const char* kModuleName = "mod_name";
/*!
* \brief All the runtime::Modules accumulated during compilation by external codegen. These
* modules must be either directly linked or captured in the final compilation artifact.
*
* Type: ffi::Array<runtime::Module>
*/
constexpr const char* kExternalMods = "external_mods";
/*!
* \brief A prefix for generating C symbols system lib creation.
*
* This prefix guides passes that creates global_symbol for internal functions
* that may have c linkage (e.g. TIR functions and some BYOC functions). It also affects
* the symbol of the fat bin blob during module export.
*
* This attribute is used to avoid symbol conflict when we
* generate and combine multiple system libs that get linked into one.
*
* Rationale: mechanisms like BYOC rely on the common global symbol
* and each external compiler also has its own mechanism of mangling.
* As a result, we cannot rely on other mechanisms on setting a global_symbol and then renaming,
* because the external compiler already agreed on the name.
*
* system_lib_prefix provides a way to hint at the passes to allow names to
* avoid name conflict at the beginning.
*
* Note that users can still directly specify global symbols that may conflict.
* It is up to the downstream toolchain to manage those external-facing functions.
*
* This does not affect non-C linkage functions it is less of an issue because
* they will be embedded into fatbin that in different symbols,
* The system lib loader can pick the right prefix for a given prefix.
*
* Having this attribute implies system lib generation linkage.
*/
constexpr const char* kSystemLibPrefix = "system_lib_prefix";
/*!
* \brief All the named runtime::Tensors accumulated during compilation by external codegen.
* Generally the associated runtime::Module will indicate it requires bindings for these names,
* and during module initialization these bindings will be recovered from a ConstLoaderModule.
*
* Type: ffi::Map<ffi::String, runtime::Tensor>
*/
constexpr const char* kConstNameToConstant = "const_name_to_constant";
} // namespace attr
} // namespace tvm
#endif // TVM_IR_MODULE_H_