Chromium Code Reviews| Index: src/IceTargetLowering.h |
| diff --git a/src/IceTargetLowering.h b/src/IceTargetLowering.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..d4dcd5c1830c79fd5434ab0ca45e7d2cfccc761b |
| --- /dev/null |
| +++ b/src/IceTargetLowering.h |
| @@ -0,0 +1,199 @@ |
| +//===- subzero/src/IceTargetLowering.h - Lowering interface -----*- 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 TargetLowering and LoweringContext |
| +// classes. TargetLowering is an abstract class used to drive the |
| +// translation/lowering process. LoweringContext maintains a |
| +// context for lowering each instruction, offering conveniences such |
| +// as iterating over non-deleted instructions. |
| +// |
| +//===----------------------------------------------------------------------===// |
| + |
| +#ifndef SUBZERO_SRC_ICETARGETLOWERING_H |
| +#define SUBZERO_SRC_ICETARGETLOWERING_H |
| + |
| +#include "IceDefs.h" |
| +#include "IceTypes.h" |
| + |
| +#include "IceInst.h" // for the names of the Inst subtypes |
| + |
| +namespace Ice { |
| + |
| +// LoweringContext makes it easy to iterate through non-deleted |
| +// instructions in a node, and insert new (lowered) instructions at |
| +// the current point. Along with the instruction list container and |
| +// associated iterators, it holds the current node, which is needed |
| +// when inserting new instructions in order to track whether variables |
| +// are used as single-block or multi-block. |
| +class LoweringContext { |
| +public: |
| + LoweringContext() : Node(NULL) {} |
|
JF
2014/05/04 23:54:58
Missing dtor.
Jim Stichnoth
2014/05/05 07:03:55
Done.
|
| + void init(CfgNode *Node); |
| + Inst *getNextInst() const { |
| + if (Next == End) |
| + return NULL; |
| + return *Next; |
| + } |
| + CfgNode *getNode() const { return Node; } |
| + bool atEnd() const { return Cur == End; } |
| + InstList::iterator getCur() const { return Cur; } |
| + InstList::iterator getEnd() const { return End; } |
| + void insert(Inst *Inst); |
| + void advanceCur() { Cur = Next; } |
| + void advanceNext() { advance(Next); } |
| + void setInsertPoint(const InstList::iterator &Position) { |
| + Next = Position; |
| + } |
| + |
| +private: |
| + // Node is the argument to Inst::updateVars(). |
| + CfgNode *Node; |
| + // Cur points to the current instruction being considered. It is |
| + // guaranteed to point to a non-deleted instruction, or to be End. |
| + InstList::iterator Cur; |
| + // Next doubles as a pointer to the next valid instruction (if any), |
| + // and the new-instruction insertion point. It is also updated for |
| + // the caller in case the lowering consumes more than one high-level |
| + // instruction. It is guaranteed to point to a non-deleted |
| + // instruction after Cur, or to be End. TODO: Consider separating |
| + // the notion of "next valid instruction" and "new instruction |
| + // insertion point", to avoid confusion when previously-deleted |
| + // instructions come between the two points. |
|
JF
2014/05/04 23:54:58
Can't the deleted instruction be recycled as the i
Jim Stichnoth
2014/05/05 07:03:55
I guess that for debugging codegen, I prefer that
|
| + //public: |
|
JF
2014/05/04 23:54:58
public comment?
Jim Stichnoth
2014/05/05 07:03:55
Whoops, gone now.
|
| + InstList::iterator Next; |
| + // End is a copy of Insts.end(), used if Next needs to be advanced. |
| + InstList::iterator End; |
| + |
| + void skipDeleted(InstList::iterator &I); |
| + void advance(InstList::iterator &I); |
| + LoweringContext(const LoweringContext &) LLVM_DELETED_FUNCTION; |
| + LoweringContext &operator=(const LoweringContext &) LLVM_DELETED_FUNCTION; |
| +}; |
| + |
| +class TargetLowering { |
|
JF
2014/05/04 23:54:58
I think using the CRTP here would be better. The p
Jim Stichnoth
2014/05/05 07:03:55
Good point - I was thinking about CRTP for the tar
Jim Stichnoth
2014/05/17 14:14:32
On further thought, I don't think CRTP is appropri
|
| +public: |
| + static TargetLowering *createLowering(TargetArch Target, Cfg *Func); |
| + void translate() { |
| + switch (Ctx->getOptLevel()) { |
| + case Opt_m1: |
| + translateOm1(); |
| + break; |
| + case Opt_0: |
| + translateO0(); |
| + break; |
| + case Opt_1: |
| + translateO1(); |
| + break; |
| + case Opt_2: |
| + translateO2(); |
| + break; |
| + default: |
| + Func->setError("Target doesn't specify lowering steps."); |
| + break; |
| + } |
| + } |
| + virtual void translateOm1() { |
| + Func->setError("Target doesn't specify Om1 lowering steps."); |
| + } |
| + virtual void translateO0() { |
| + Func->setError("Target doesn't specify O0 lowering steps."); |
| + } |
| + virtual void translateO1() { |
| + Func->setError("Target doesn't specify O1 lowering steps."); |
| + } |
| + virtual void translateO2() { |
| + Func->setError("Target doesn't specify O2 lowering steps."); |
| + } |
| + |
| + // Lowers a single instruction. |
| + void lower(); |
| + |
| + // Returns a variable pre-colored to the specified physical |
| + // register. This is generally used to get very direct access to |
| + // the register such as in the prolog or epilog or for marking |
| + // scratch registers as killed by a call. |
| + virtual Variable *getPhysicalRegister(SizeT RegNum) = 0; |
| + // Returns a printable name for the register. |
| + virtual IceString getRegName(SizeT RegNum, Type Ty) const = 0; |
| + |
| + virtual bool hasFramePointer() const { return false; } |
| + virtual SizeT getFrameOrStackReg() const = 0; |
| + virtual size_t typeWidthInBytesOnStack(Type Ty) = 0; |
| + bool hasComputedFrame() const { return HasComputedFrame; } |
| + int32_t getStackAdjustment() const { return StackAdjustment; } |
| + void updateStackAdjustment(int32_t Offset) { StackAdjustment += Offset; } |
| + void resetStackAdjustment() { StackAdjustment = 0; } |
| + LoweringContext &getContext() { return Context; } |
| + |
| + enum RegSet { |
| + RegSet_None = 0, |
| + RegSet_CallerSave = 1 << 0, |
| + RegSet_CalleeSave = 1 << 1, |
| + RegSet_StackPointer = 1 << 2, |
| + RegSet_FramePointer = 1 << 3, |
| + RegSet_All = ~RegSet_None |
| + }; |
| + typedef uint32_t RegSetMask; |
| + |
| + virtual llvm::SmallBitVector getRegisterSet(RegSetMask Include, |
| + RegSetMask Exclude) const = 0; |
| + virtual const llvm::SmallBitVector &getRegisterSetForType(Type Ty) const = 0; |
| + void regAlloc(); |
| + |
| + virtual void emitVariable(const Variable *Var, const Cfg *Func) const = 0; |
| + |
| + virtual void addProlog(CfgNode *Node) = 0; |
| + virtual void addEpilog(CfgNode *Node) = 0; |
| + |
| + virtual ~TargetLowering() {} |
| + |
| +protected: |
| + TargetLowering(Cfg *Func) |
| + : Func(Func), Ctx(Func->getContext()), HasComputedFrame(false), |
| + StackAdjustment(0) {} |
| + virtual void lowerAlloca(const InstAlloca *Inst) = 0; |
| + virtual void lowerArithmetic(const InstArithmetic *Inst) = 0; |
| + virtual void lowerAssign(const InstAssign *Inst) = 0; |
| + virtual void lowerBr(const InstBr *Inst) = 0; |
| + virtual void lowerCall(const InstCall *Inst) = 0; |
| + virtual void lowerCast(const InstCast *Inst) = 0; |
| + virtual void lowerFcmp(const InstFcmp *Inst) = 0; |
| + virtual void lowerIcmp(const InstIcmp *Inst) = 0; |
| + virtual void lowerLoad(const InstLoad *Inst) = 0; |
| + virtual void lowerPhi(const InstPhi *Inst) = 0; |
| + virtual void lowerRet(const InstRet *Inst) = 0; |
| + virtual void lowerSelect(const InstSelect *Inst) = 0; |
| + virtual void lowerStore(const InstStore *Inst) = 0; |
| + virtual void lowerSwitch(const InstSwitch *Inst) = 0; |
| + virtual void lowerUnreachable(const InstUnreachable *Inst) = 0; |
| + |
| + // This gives the target an opportunity to post-process the lowered |
| + // expansion before returning. The primary intention is to do some |
| + // Register Manager activity as necessary, specifically to eagerly |
| + // allocate registers based on affinity and other factors. The |
| + // simplest lowering does nothing here and leaves it all to a |
| + // subsequent global register allocation pass. |
| + virtual void postLower() {} |
| + |
| + Cfg *Func; |
| + GlobalContext *Ctx; |
| + bool HasComputedFrame; |
| + // StackAdjustment keeps track of the current stack offset from its |
| + // natural location, as arguments are pushed for a function call. |
| + int32_t StackAdjustment; |
| + LoweringContext Context; |
| + |
| +private: |
| + TargetLowering(const TargetLowering &) LLVM_DELETED_FUNCTION; |
| + TargetLowering &operator=(const TargetLowering &) LLVM_DELETED_FUNCTION; |
| +}; |
| + |
| +} // end of namespace Ice |
| + |
| +#endif // SUBZERO_SRC_ICETARGETLOWERING_H |