| Index: src/IceCfg.h
|
| diff --git a/src/IceCfg.h b/src/IceCfg.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..05e1e3b30ace68b9ccc56b2b85fa8f6ca8cbe7b2
|
| --- /dev/null
|
| +++ b/src/IceCfg.h
|
| @@ -0,0 +1,144 @@
|
| +//===- 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 Cfg 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 Cfg {
|
| +public:
|
| + Cfg(GlobalContext *Ctx);
|
| + ~Cfg();
|
| +
|
| + 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(Type Ty) { ReturnType = Ty; }
|
| +
|
| + // 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 = "");
|
| + SizeT getNumNodes() const { return Nodes.size(); }
|
| + const NodeList &getNodes() const { return Nodes; }
|
| +
|
| + // Manage instruction numbering.
|
| + int newInstNumber() { return NextInstNumber++; }
|
| +
|
| + // Manage Variables.
|
| + Variable *makeVariable(Type Ty, const CfgNode *Node,
|
| + const IceString &Name = "");
|
| + SizeT 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);
|
| + }
|
| +
|
| + // Deallocate data that was allocated via allocate<T>().
|
| + template <typename T> void deallocate(T *Object) {
|
| + Allocator.Deallocate(Object);
|
| + }
|
| +
|
| + // Deallocate data that was allocated via allocateInst<T>().
|
| + template <typename T> void deallocateInst(T *Instr) {
|
| + Allocator.Deallocate(Instr);
|
| + }
|
| +
|
| + // Deallocate data that was allocated via allocateArrayOf<T>().
|
| + template <typename T> void deallocateArrayOf(T *Array) {
|
| + Allocator.Deallocate(Array);
|
| + }
|
| +
|
| +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;
|
| + Type 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;
|
| +
|
| + Cfg(const Cfg &) LLVM_DELETED_FUNCTION;
|
| + Cfg &operator=(const Cfg &) LLVM_DELETED_FUNCTION;
|
| +};
|
| +
|
| +} // end of namespace Ice
|
| +
|
| +#endif // SUBZERO_SRC_ICECFG_H
|
|
|