summaryrefslogtreecommitdiff
path: root/compiler/coco/core/include/coco/IR/Instr.h
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/coco/core/include/coco/IR/Instr.h')
-rw-r--r--compiler/coco/core/include/coco/IR/Instr.h161
1 files changed, 161 insertions, 0 deletions
diff --git a/compiler/coco/core/include/coco/IR/Instr.h b/compiler/coco/core/include/coco/IR/Instr.h
new file mode 100644
index 000000000..fc1cc332d
--- /dev/null
+++ b/compiler/coco/core/include/coco/IR/Instr.h
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. 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.
+ */
+
+#ifndef __COCO_IR_INSTR_H__
+#define __COCO_IR_INSTR_H__
+
+#include "coco/IR/Bag.h"
+#include "coco/IR/Block.forward.h"
+#include "coco/IR/Instr.forward.h"
+#include "coco/IR/InstrIndex.h"
+#include "coco/IR/Entity.h"
+
+#include "coco/ADT/DLinkedList.h"
+
+#include <cassert>
+#include <stdexcept>
+
+namespace coco
+{
+
+#define INSTR(Name) class Name;
+#include "coco/IR/Instr.lst"
+#undef INSTR
+
+using InstrList = coco::DLinkedList<Instr, Block>::Head;
+
+/**
+ * @brief Base interface on explicit computation steps in coco IR
+ *
+ * NOTE Input/output is explicit in Instr, but implicit in Op
+ * NOTE Instr is may (not always) be a combination of multiple NN operations
+ *
+ * One may find a set of supported instructions from "Instrs.h"
+ *
+ * >> How to add a new base instruction in coco IR <<
+ *
+ * To introduce a new instruction (whose name is INS),
+ * 1. Append "INSTR(INS)" to "Instr.lst"
+ * 2. Declare class INS which inherits Instr class in "Instrs.h"
+ * NOTE This class SHOULD be default constructible
+ *
+ */
+class Instr : public coco::DLinkedList<Instr, Block>::Node, public Entity
+{
+public:
+ friend void DLinkedList<Instr, Block>::joined(Block *, Instr *);
+ friend void DLinkedList<Instr, Block>::leaving(Block *, Instr *);
+
+public:
+ Instr() = default;
+
+public:
+ Instr(const Instr &) = delete;
+ Instr(Instr &&) = delete;
+
+public:
+ virtual ~Instr()
+ {
+ if (parent())
+ {
+ // NOTE It is safe to invoke detach here (although "Instr" is not a final class)
+ // as "leaving" hook accesses only the internal of "Instr" class
+ detach();
+ }
+ }
+
+public:
+#define INSTR(Name) \
+ virtual Name *as##Name(void) { return nullptr; } \
+ virtual const Name *as##Name(void) const { return nullptr; }
+#include "coco/IR/Instr.lst"
+#undef INSTR
+
+public:
+ /**
+ * @brief Instr visitor interface
+ *
+ * WARN Use this interface only for coco-internal classes
+ * (to minimize changes upon Instr extension)
+ */
+ template <typename T> struct IVisitor
+ {
+ virtual ~IVisitor() = default;
+
+#define INSTR(Name) virtual T visit(const Name *) = 0;
+#include "coco/IR/Instr.lst"
+#undef INSTR
+ };
+
+ template <typename T> struct Visitor : public IVisitor<T>
+ {
+ virtual ~Visitor() = default;
+
+#define INSTR(Name) \
+ T visit(const Name *) override { throw std::runtime_error{"NYI"}; }
+#include "coco/IR/Instr.lst"
+#undef INSTR
+ };
+
+public:
+ template <typename T> T accept(IVisitor<T> *v) const
+ {
+#define INSTR(Name) \
+ if (auto ins = as##Name()) \
+ { \
+ return v->visit(ins); \
+ }
+#include "coco/IR/Instr.lst"
+#undef INSTR
+ throw std::runtime_error{"unreachable"};
+ }
+
+ template <typename T> T accept(IVisitor<T> &v) const { return accept(&v); }
+ template <typename T> T accept(IVisitor<T> &&v) const { return accept(&v); }
+
+public:
+ const InstrIndex &index(void) const { return _index; }
+
+private:
+ InstrIndex _index;
+};
+
+/**
+ * @brief Return true if a given instruction is of T type
+ *
+ * @note "ins" cannot be a null pointer
+ */
+template <typename T> bool isa(const Instr *ins)
+{
+ assert(ins != nullptr);
+ return dynamic_cast<const T *>(ins) != nullptr;
+}
+
+/**
+ * @brief Cast as a derived instruction
+ *
+ * @note "safe_cast<T>(ins)" returns a null pointer if "ins" is not of T type
+ * @note "safe_cast<T>(ins)" returns a null pointer if "ins" is a null pointer
+ */
+template <typename T> T *safe_cast(Instr *ins)
+{
+ // NOTE dynamic_cast<T *>(nullptr) returns nullptr
+ return dynamic_cast<T *>(ins);
+}
+
+} // namespace coco
+
+#endif // __COCO_IR_INSTR_H__