Index: src/IceCfg.h |
diff --git a/src/IceCfg.h b/src/IceCfg.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..24cc305a96c53a8acb11e208d1aa01a7bb0a5fc2 |
--- /dev/null |
+++ b/src/IceCfg.h |
@@ -0,0 +1,129 @@ |
+//===- subzero/src/IceCfg.h - Control flow graph ----------------*- C++ -*-===// |
+// |
+// The Subzero Code Generator |
+// |
+// This file is distributed under the University of Illinois Open Source |
+// License. See LICENSE.TXT for details. |
+// |
+//===----------------------------------------------------------------------===// |
+// |
+// This file declares the IceCfg class, which represents the control |
+// flow graph and the overall per-function compilation context. |
+// |
+//===----------------------------------------------------------------------===// |
+ |
+#ifndef SUBZERO_SRC_ICECFG_H |
+#define SUBZERO_SRC_ICECFG_H |
+ |
+#include "IceDefs.h" |
+#include "IceTypes.h" |
+#include "IceGlobalContext.h" |
+ |
+#include "llvm/ADT/OwningPtr.h" |
+#include "llvm/Support/Allocator.h" |
+ |
+namespace Ice { |
+ |
+class IceCfg { |
+public: |
+ IceCfg(GlobalContext *Ctx); |
+ ~IceCfg(); |
+ |
+ GlobalContext *getContext() const { return Ctx; } |
+ |
+ // Manage the name and return type of the function being translated. |
+ void setFunctionName(const IceString &Name) { FunctionName = Name; } |
+ IceString getFunctionName() const { return FunctionName; } |
+ void setReturnType(IceType Type) { ReturnType = Type; } |
+ |
+ // Manage the "internal" attribute of the function. |
+ void setInternal(bool Internal) { IsInternalLinkage = Internal; } |
+ bool getInternal() const { return IsInternalLinkage; } |
+ |
+ // Translation error flagging. If support for some construct is |
+ // known to be missing, instead of an assertion failure, setError() |
+ // should be called and the error should be propagated back up. |
+ // This way, we can gracefully fail to translate and let a fallback |
+ // translator handle the function. |
+ void setError(const IceString &Message); |
+ bool hasError() const { return HasError; } |
+ IceString getError() const { return ErrorMessage; } |
+ |
+ // Manage nodes (a.k.a. basic blocks, CfgNodes). |
+ void setEntryNode(CfgNode *EntryNode) { Entry = EntryNode; } |
+ CfgNode *getEntryNode() const { return Entry; } |
+ // Create a node and append it to the end of the linearized list. |
+ CfgNode *makeNode(const IceString &Name = ""); |
+ IceSize_t getNumNodes() const { return Nodes.size(); } |
+ const NodeList &getNodes() const { return Nodes; } |
+ |
+ // Manage instruction numbering. |
+ int newInstNumber() { return NextInstNumber++; } |
+ |
+ // Manage Variables. |
+ Variable *makeVariable(IceType Type, const CfgNode *Node, |
+ const IceString &Name = ""); |
+ IceSize_t getNumVariables() const { return Variables.size(); } |
+ const VarList &getVariables() const { return Variables; } |
+ |
+ // Manage arguments to the function. |
+ void addArg(Variable *Arg); |
+ const VarList &getArgs() const { return Args; } |
+ |
+ // After the CFG is fully constructed, iterate over the nodes and |
+ // compute the predecessor edges, in the form of |
+ // CfgNode::InEdges[]. |
+ void computePredecessors(); |
+ |
+ // Manage the CurrentNode field, which is used for validating the |
+ // Variable::DefNode field during dumping/emitting. |
+ void setCurrentNode(const CfgNode *Node) { CurrentNode = Node; } |
+ const CfgNode *getCurrentNode() const { return CurrentNode; } |
+ |
+ void dump(); |
+ |
+ // Allocate data of type T using the per-Cfg allocator. |
+ template <typename T> T *allocate() { return Allocator.Allocate<T>(); } |
+ |
+ // Allocate an instruction of type T using the per-Cfg instruction allocator. |
+ template <typename T> T *allocateInst() { return Allocator.Allocate<T>(); } |
+ |
+ // Allocate an array of data of type T using the per-Cfg allocator. |
+ template <typename T> T *allocateArrayOf(size_t NumElems) { |
+ return Allocator.Allocate<T>(NumElems); |
+ } |
+ |
+private: |
+ // TODO: for now, everything is allocated from the same allocator. In the |
+ // future we may want to split this to several allocators, for example in |
+ // order to use a "Recycler" to preserve memory. If we keep all allocation |
+ // requests from the Cfg exposed via methods, we can always switch the |
+ // implementation over at a later point. |
+ llvm::BumpPtrAllocator Allocator; |
+ |
+ GlobalContext *Ctx; |
+ IceString FunctionName; |
+ IceType ReturnType; |
+ bool IsInternalLinkage; |
+ bool HasError; |
+ IceString ErrorMessage; |
+ CfgNode *Entry; // entry basic block |
+ NodeList Nodes; // linearized node list; Entry should be first |
+ int NextInstNumber; |
+ VarList Variables; |
+ VarList Args; // subset of Variables, in argument order |
+ |
+ // CurrentNode is maintained during dumping/emitting just for |
+ // validating Variable::DefNode. Normally, a traversal over |
+ // CfgNodes maintains this, but before global operations like |
+ // register allocation, setCurrentNode(NULL) should be called to |
+ // avoid spurious validation failures. |
+ const CfgNode *CurrentNode; |
+ |
+ IceCfg(const IceCfg &) LLVM_DELETED_FUNCTION; |
+ IceCfg &operator=(const IceCfg &) LLVM_DELETED_FUNCTION; |
+}; |
+ |
+} // end of namespace Ice |
+ |
+#endif // SUBZERO_SRC_ICECFG_H |