// Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved. // // Licensed 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. #pragma once #include #include #include "paddle/ir/core/attribute.h" #include "paddle/ir/core/attribute_base.h" #include "paddle/ir/core/dialect_interface.h" #include "paddle/ir/core/enforce.h" #include "paddle/ir/core/ir_context.h" #include "paddle/ir/core/op_base.h" #include "paddle/ir/core/type_base.h" namespace ir { class Operation; class IrPrinter; class IrParser; class DialectInterface; /// /// \brief Dialect can basically be understood as a namespace. In Dialect, we /// can define a series of types, attributes, operations, etc. An instance of /// the dialect object will be loaded into the global IrContext. Specific /// compilers only need to combine existing dialects and add their own /// extensions or customizations. /// class IR_API Dialect { public: Dialect(std::string name, IrContext *context, TypeId id); virtual ~Dialect(); const std::string &name() const { return name_; } IrContext *ir_context() const { return context_; } TypeId id() const { return id_; } /// /// \brief Register all types contained in the template parameter Args. /// To register only one Type, you can use the RegisterType template function. /// template void RegisterTypes() { (void)std::initializer_list{0, (RegisterType(), 0)...}; } template void RegisterType() { ir_context()->RegisterAbstractType(TypeId::get(), AbstractType::get(*this)); TypeManager::RegisterType(ir_context()); } /// /// \brief Register all attributes contained in the template parameter Args. /// To register only one Attribute, you can use the RegisterAttribute template /// function. /// template void RegisterAttributes() { (void)std::initializer_list{0, (RegisterAttribute(), 0)...}; } template void RegisterAttribute() { ir_context()->RegisterAbstractAttribute(TypeId::get(), AbstractAttribute::get(*this)); AttributeManager::RegisterAttribute(ir_context()); } /// /// \brief Register Ops. /// template void RegisterOps() { (void)std::initializer_list{0, (RegisterOp(), 0)...}; } template void RegisterOp() { ir_context()->RegisterOpInfo(this, TypeId::get(), ConcreteOp::name(), ConcreteOp::GetInterfaceMap(), ConcreteOp::GetTraitSet(), ConcreteOp::attributes_num, ConcreteOp::attributes_name, ConcreteOp::VerifyInvariants); } void RegisterOp(const std::string &name, OpInfoImpl *op_info); /// /// \brief Register interface methods. /// DialectInterface *GetRegisteredInterface(TypeId id) { auto it = registered_interfaces_.find(id); return it != registered_interfaces_.end() ? it->second.get() : nullptr; } template InterfaceT *GetRegisteredInterface() { return static_cast( GetRegisteredInterface(TypeId::get())); } /// Register a dialect interface with this dialect instance. void RegisterInterface(std::unique_ptr interface); /// Register a set of dialect interfaces with this dialect instance. template void RegisterInterfaces() { (void)std::initializer_list{ 0, (RegisterInterface(std::make_unique(this)), 0)...}; } template InterfaceT &RegisterInterface(Args &&...args) { InterfaceT *interface = new InterfaceT(this, std::forward(args)...); RegisterInterface(std::unique_ptr(interface)); return *interface; } virtual void PrintType(Type type, std::ostream &os) const { IR_THROW("dialect has no registered type printing hook"); } virtual void PrintAttribute(Attribute attr, std::ostream &os) const { IR_THROW("dialect has no registered attribute printing hook"); } virtual Type ParseType(IrParser &parser) { // NOLINT IR_THROW("dialect has no registered type parsing hook"); } virtual Attribute ParseAttribute(IrParser &parser) { // NOLINT IR_THROW("dialect has no registered attribute parsing hook"); } virtual void PrintOperation(Operation *op, IrPrinter &printer) const; // NOLINT virtual Operation ParseOperation(IrParser &parser) { // NOLINT IR_THROW("dialect has no registered operation parsing hook"); } private: Dialect(const Dialect &) = delete; Dialect &operator=(Dialect &) = delete; std::string name_; IrContext *context_; // not owned TypeId id_; std::unordered_map> registered_interfaces_; }; } // namespace ir