#ifndef MIGRAPH_GUARD_MIGRAPHLIB_TARGET_HPP #define MIGRAPH_GUARD_MIGRAPHLIB_TARGET_HPP #include #include #include #include #include #include #include #include #include namespace migraph { #ifdef DOXYGEN /// An interface for a compilation target struct target { /// A unique name used to identify the target std::string name() const; /// The transformation passes to be run /** * @brief The transformation pass to be run during compilation. * @details [long description] * * @param ctx This is the target-dependent context that is created by `get_context` * @return The passes to be ran */ std::vector get_passes(context& ctx) const; /** * @brief Construct a context for the target. * @return The context to be used during compilation and execution. */ context get_context() const; }; #else /* * Type-erased interface for: * * struct target * { * std::string name() const; * std::vector get_passes(context& ctx) const; * context get_context() const; * }; * */ struct target { // Constructors target() = default; template target(PrivateDetailTypeErasedT value) : private_detail_te_handle_mem_var( std::make_shared::type>>( std::forward(value))) { } // Assignment template target& operator=(PrivateDetailTypeErasedT value) { if(private_detail_te_handle_mem_var.unique()) *private_detail_te_handle_mem_var = std::forward(value); else if(!private_detail_te_handle_mem_var) private_detail_te_handle_mem_var = std::make_shared( std::forward(value)); return *this; } // Cast template PrivateDetailTypeErasedT* any_cast() { return private_detail_te_get_handle().type() == typeid(PrivateDetailTypeErasedT) ? std::addressof(static_cast::type>&>( private_detail_te_get_handle()) .private_detail_te_value) : nullptr; } template const typename std::remove_cv::type* any_cast() const { return private_detail_te_get_handle().type() == typeid(PrivateDetailTypeErasedT) ? std::addressof(static_cast::type>&>( private_detail_te_get_handle()) .private_detail_te_value) : nullptr; } const std::type_info& type_id() const { if(private_detail_te_handle_empty()) return typeid(std::nullptr_t); else return private_detail_te_get_handle().type(); } std::string name() const { assert((*this).private_detail_te_handle_mem_var); return (*this).private_detail_te_get_handle().name(); } std::vector get_passes(context& ctx) const { assert((*this).private_detail_te_handle_mem_var); return (*this).private_detail_te_get_handle().get_passes(ctx); } context get_context() const { assert((*this).private_detail_te_handle_mem_var); return (*this).private_detail_te_get_handle().get_context(); } private: struct private_detail_te_handle_base_type { virtual ~private_detail_te_handle_base_type() {} virtual std::shared_ptr clone() const = 0; virtual const std::type_info& type() const = 0; virtual std::string name() const = 0; virtual std::vector get_passes(context& ctx) const = 0; virtual context get_context() const = 0; }; template struct private_detail_te_handle_type : private_detail_te_handle_base_type { template private_detail_te_handle_type( PrivateDetailTypeErasedT value, typename std::enable_if::value>::type* = nullptr) : private_detail_te_value(value) { } template private_detail_te_handle_type( PrivateDetailTypeErasedT value, typename std::enable_if::value, int>::type* = nullptr) noexcept : private_detail_te_value(std::move(value)) { } std::shared_ptr clone() const override { return std::make_shared(private_detail_te_value); } const std::type_info& type() const override { return typeid(private_detail_te_value); } std::string name() const override { return private_detail_te_value.name(); } std::vector get_passes(context& ctx) const override { return private_detail_te_value.get_passes(ctx); } context get_context() const override { return private_detail_te_value.get_context(); } PrivateDetailTypeErasedT private_detail_te_value; }; template struct private_detail_te_handle_type> : private_detail_te_handle_type { private_detail_te_handle_type(std::reference_wrapper ref) : private_detail_te_handle_type(ref.get()) { } }; bool private_detail_te_handle_empty() const { return private_detail_te_handle_mem_var == nullptr; } const private_detail_te_handle_base_type& private_detail_te_get_handle() const { assert(private_detail_te_handle_mem_var != nullptr); return *private_detail_te_handle_mem_var; } private_detail_te_handle_base_type& private_detail_te_get_handle() { assert(private_detail_te_handle_mem_var != nullptr); if(!private_detail_te_handle_mem_var.unique()) private_detail_te_handle_mem_var = private_detail_te_handle_mem_var->clone(); return *private_detail_te_handle_mem_var; } std::shared_ptr private_detail_te_handle_mem_var; }; template inline const ValueType* any_cast(const target* x) { return x->any_cast(); } template inline ValueType* any_cast(target* x) { return x->any_cast(); } template inline ValueType& any_cast(target& x) { auto* y = x.any_cast::type>(); if(y == nullptr) throw std::bad_cast(); return *y; } template inline const ValueType& any_cast(const target& x) { const auto* y = x.any_cast::type>(); if(y == nullptr) throw std::bad_cast(); return *y; } #endif } // namespace migraph #endif