docc 0.8.3 (0d44999b)
C++ API Reference
Loading...
Searching...
No Matches
switch_expander.h
Go to the documentation of this file.
1#pragma once
2
3#include <memory>
4#include <stdexcept>
5#include <string>
6#include <unordered_map>
7#include <utility>
8#include <vector>
9
12
13namespace sdfg::passes {
14
53 std::vector<std::shared_ptr<const LibNodeExpander>> expanders_;
55 std::unordered_map<std::string, const LibNodeExpander*> by_code_;
57 std::vector<const LibNodeExpander*> fallback_;
58
59public:
66 template<typename... Expanders>
67 explicit SwitchExpander(Expanders... expanders) {
68 expanders_.reserve(sizeof...(Expanders));
69 (register_expander(std::move(expanders)), ...);
70 }
71
73 explicit SwitchExpander(std::vector<std::shared_ptr<const LibNodeExpander>> expanders) {
74 expanders_.reserve(expanders.size());
75 for (auto& expander : expanders) {
76 register_expander(std::move(expander));
77 }
78 }
79
85 void register_expander(std::shared_ptr<const LibNodeExpander> expander) {
86 if (!expander) {
87 return;
88 }
89 if (const auto* code = expander->matched_code()) {
90 register_for_code(*code, std::move(expander));
91 } else {
92 fallback_.push_back(expander.get());
93 expanders_.push_back(std::move(expander));
94 }
95 }
96
104 void register_for_code(const data_flow::LibraryNodeCode& code, std::shared_ptr<const LibNodeExpander> expander) {
105 if (!expander) {
106 return;
107 }
108 auto [it, inserted] = by_code_.emplace(code.value(), expander.get());
109 if (!inserted) {
110 throw std::invalid_argument(
111 "SwitchExpander: more than one expander registered for library node code '" + code.value() + "'"
112 );
113 }
114 expanders_.push_back(std::move(expander));
115 }
116
121 const LibNodeExpander* for_lib_node(const data_flow::LibraryNode& node) const override {
122 if (auto it = by_code_.find(node.code().value()); it != by_code_.end()) {
123 if (const auto* match = it->second->for_lib_node(node)) {
124 return match;
125 }
126 }
127 for (const auto* expander : fallback_) {
128 if (const auto* match = expander->for_lib_node(node)) {
129 return match;
130 }
131 }
132 return nullptr;
133 }
134
144 ) const override {
145 if (const auto* expander = for_lib_node(node); expander && expander != this) {
146 return expander->handle_expand(context, block, node);
147 }
148 return context.unapplicable();
149 }
150};
151
152} // namespace sdfg::passes
std::string value() const
Definition exceptions.h:47
Base class for all library nodes in the dataflow graph.
Definition library_node.h:106
const LibraryNodeCode & code() const
Get the operation code.
Definition lib_node_expander.h:122
Definition lib_node_expander.h:8
ExpandOutcome handle_expand(ExpandContext &context, structured_control_flow::Block &block, data_flow::LibraryNode &node) const override
Delegate expansion to the matching sub-expander.
Definition switch_expander.h:142
void register_for_code(const data_flow::LibraryNodeCode &code, std::shared_ptr< const LibNodeExpander > expander)
Register expander as the handler for library nodes with the given code.
Definition switch_expander.h:104
SwitchExpander(std::vector< std::shared_ptr< const LibNodeExpander > > expanders)
Construct from an already assembled list of expanders.
Definition switch_expander.h:73
SwitchExpander(Expanders... expanders)
Construct from a variadic list of expanders.
Definition switch_expander.h:67
void register_expander(std::shared_ptr< const LibNodeExpander > expander)
Register expander.
Definition switch_expander.h:85
const LibNodeExpander * for_lib_node(const data_flow::LibraryNode &node) const override
Find the expander that applies to node via an O(1) code lookup, with a linear fallback.
Definition switch_expander.h:121
A control flow node representing a basic block with dataflow computations.
Definition block.h:42
Library node definitions for calling functions beyond simple instructions.
StringEnum LibraryNodeCode
Definition library_node.h:65
Definition approximate_math.h:12
Definition lib_node_expander.h:12