diff options
Diffstat (limited to 'flowgraph')
-rw-r--r-- | flowgraph/graph.cpp | 60 | ||||
-rw-r--r-- | flowgraph/graph.h | 22 | ||||
-rw-r--r-- | flowgraph/node.cpp | 8 | ||||
-rw-r--r-- | flowgraph/node.h | 16 | ||||
-rw-r--r-- | flowgraph/scope.cpp | 28 | ||||
-rw-r--r-- | flowgraph/scope.h | 29 | ||||
-rw-r--r-- | flowgraph/storage.cpp | 9 | ||||
-rw-r--r-- | flowgraph/storage.h | 16 |
8 files changed, 168 insertions, 20 deletions
diff --git a/flowgraph/graph.cpp b/flowgraph/graph.cpp index e8b6b5e..6398c68 100644 --- a/flowgraph/graph.cpp +++ b/flowgraph/graph.cpp @@ -1 +1,61 @@ #include "graph.h" + +#include "minicc.h" +#include "node.h" + +#include <string> + +using namespace std::string_literals; + +FlowGraph::Graph::Graph() +{ +} + +FlowGraph::Graph::Graph(const std::deque<std::shared_ptr<Node>>& nodes): std::deque<std::shared_ptr<Node>>(nodes) +{ + auto createLocalScope {std::make_shared<FlowGraph::CreateScopeOp>()}; + this->push_front(createLocalScope); + + auto destroyLocalScope {std::make_shared<FlowGraph::DestroyScopeOp>(createLocalScope->scope())}; + this->push_back(destroyLocalScope); +} + +FlowGraph::Graph::~Graph() +{ +} + +// Assume first node of graph to be CreateScopeOp +FlowGraph::LocalScope& FlowGraph::Graph::scope() const +{ + if (this->empty()) + throw std::runtime_error("ICE: FlowGraph expected to be non-empty!"); + + auto& front_deref {*front()}; + + if (typeid(front_deref) != typeid(FlowGraph::CreateScopeOp)) + throw std::runtime_error("ICE: Bad type of first graph element: "s + demangle(typeid(front_deref))); + + FlowGraph::CreateScopeOp& createScope {dynamic_cast<FlowGraph::CreateScopeOp&>(front_deref)}; + + return createScope.scope(); +} + +void FlowGraph::Graph::append(const FlowGraph::Graph& other) +{ + this->insert(this->end() - 1, other.begin() + 1, other.end() - 1); + + this->scope().append(other.scope()); +} + +void FlowGraph::Graph::append(std::shared_ptr<Node> node) +{ + this->insert(this->end() - 1, node); +} + +std::shared_ptr<FlowGraph::Node> FlowGraph::Graph::lastOp() const +{ + if (size() >= 3) + return *(end() - 2); + + throw std::runtime_error("ICE: No last operation found in graph"); +} diff --git a/flowgraph/graph.h b/flowgraph/graph.h index 265a3bd..15c6aef 100644 --- a/flowgraph/graph.h +++ b/flowgraph/graph.h @@ -2,18 +2,32 @@ #include "node.h" +#include <deque> #include <exception> #include <memory> -#include <string> #include <stdexcept> -#include <vector> namespace FlowGraph { - class Graph: public std::vector<std::shared_ptr<Node>> + class Graph: public std::deque<std::shared_ptr<Node>> { public: - Graph() {} + Graph(); + Graph(const std::deque<std::shared_ptr<Node>>& nodes); + Graph(const Graph& other) = default; + ~Graph(); + + Graph& operator= (const Graph&) = default; + + // returns the outermost scope inside this graph + LocalScope& scope() const; + + // append other graph by joining the respective outermost scopes + void append(const Graph& other); + + void append(std::shared_ptr<Node> node); + + std::shared_ptr<Node> lastOp() const; }; } diff --git a/flowgraph/node.cpp b/flowgraph/node.cpp index 9b68d74..e0912dc 100644 --- a/flowgraph/node.cpp +++ b/flowgraph/node.cpp @@ -6,6 +6,14 @@ using namespace FlowGraph; +FlowGraph::Data& Node::destination() +{ + if (mOperands.size() < 1) + throw std::runtime_error("ICE: No destination operand available"); + + return mOperands[0]; +} + // 4 byte for now Data FlowGraph::MakeConstantInt(int i) { diff --git a/flowgraph/node.h b/flowgraph/node.h index 77395f0..5ea194d 100644 --- a/flowgraph/node.h +++ b/flowgraph/node.h @@ -19,8 +19,11 @@ namespace FlowGraph { public: Node(){} Node(std::vector<Data> operands): mOperands(operands) {} - std::vector<Data>& operands() { return mOperands; } virtual ~Node() {}; // force class to be polymorphic (e.g. in a container) + + std::vector<Data>& operands() { return mOperands; } + Data& destination(); // best-effort return of result/destination; else throw + private: std::vector<Data> mOperands; }; @@ -115,7 +118,6 @@ namespace FlowGraph { Increment, Decrement, Negate, - Store // just take Data as-is to store it at destination }; class UnaryOperation: public Node @@ -130,6 +132,16 @@ namespace FlowGraph { UnaryOperationType m_type; }; + // Just take a value e.g. Immediate and store it for later use. + // Should be optimized out later. + class DataNode: public Node + { + public: + DataNode(Data& value): + Node(std::vector<Data>({value})) + {} + }; + enum class BinaryOperationType: int { Add, diff --git a/flowgraph/scope.cpp b/flowgraph/scope.cpp new file mode 100644 index 0000000..6c2e30c --- /dev/null +++ b/flowgraph/scope.cpp @@ -0,0 +1,28 @@ +#include "scope.h" + +#include "storage.h" + +void FlowGraph::LocalScope::push_back(std::shared_ptr<Data> data) +{ + m_variables.push_back(data); +} + +void FlowGraph::LocalScope::append(const FlowGraph::LocalScope& other) +{ + m_variables.insert(m_variables.end(), other.m_variables.begin(), other.m_variables.end()); +} + +index_t FlowGraph::LocalScope::indexOfStorage(const TemporaryStorage& storage) const +{ + for (index_t i = 0; i < m_variables.size(); i++) { + FlowGraph::Storage& i_storage {*(m_variables[i]->storage())}; + + if (typeid(i_storage) == typeid(FlowGraph::TemporaryStorage)) { + FlowGraph::TemporaryStorage& temporaryStorage{dynamic_cast<FlowGraph::TemporaryStorage&>(i_storage)}; + if (&temporaryStorage == &storage) // compare addresses + return i; + } + } + + throw std::runtime_error("ICE: Storage not found"); +} diff --git a/flowgraph/scope.h b/flowgraph/scope.h new file mode 100644 index 0000000..50003f4 --- /dev/null +++ b/flowgraph/scope.h @@ -0,0 +1,29 @@ +#pragma once + +#include "data.h" + +#include "minicc.h" + +#include <cstddef> +#include <memory> +#include <vector> + +namespace FlowGraph { + + class TemporaryStorage; ///< Forward declaration + + // Provide a context for local temporaries name generation + class LocalScope + { + public: + LocalScope() = default; + + void push_back(std::shared_ptr<Data> data); + void append(const LocalScope& other); + index_t indexOfStorage(const TemporaryStorage& storage) const; + + private: + std::vector<std::shared_ptr<Data>> m_variables; + }; + +} diff --git a/flowgraph/storage.cpp b/flowgraph/storage.cpp index f78a65d..7e502de 100644 --- a/flowgraph/storage.cpp +++ b/flowgraph/storage.cpp @@ -3,6 +3,11 @@ using namespace std::string_literals; FlowGraph::TemporaryStorage::TemporaryStorage(LocalScope& scope): - m_name("__local_"s + std::to_string(scope.getNewIndex())) -{} + m_scope(scope) +{ +} +std::string FlowGraph::TemporaryStorage::name() const +{ + return "__local_"s + std::to_string(m_scope.indexOfStorage(*this)); +} diff --git a/flowgraph/storage.h b/flowgraph/storage.h index fd3c085..7f648b0 100644 --- a/flowgraph/storage.h +++ b/flowgraph/storage.h @@ -2,6 +2,7 @@ #pragma once #include "data.h" +#include "scope.h" #include <cstdint> #include <string> @@ -37,16 +38,7 @@ namespace FlowGraph { std::string m_name; }; - // Provide a context for local temporaries name generation - class LocalScope - { - public: - LocalScope() = default; - size_t getNewIndex() { return m_index++; } - private: - size_t m_index{ 0 }; - }; - + // named values class LocalStorage : public Storage { public: @@ -62,9 +54,9 @@ namespace FlowGraph { { public: TemporaryStorage(LocalScope& scope); - const std::string& name() const { return m_name; } + std::string name() const; private: - std::string m_name; + LocalScope& m_scope; }; // dereferenced pointer |