diff --git a/llvm/include/llvm/CodeGen/MBasicBlock.h b/llvm/include/llvm/CodeGen/MBasicBlock.h new file mode 100644 index 000000000000..f846de588cbe --- /dev/null +++ b/llvm/include/llvm/CodeGen/MBasicBlock.h @@ -0,0 +1,64 @@ +//===-- llvm/CodeGen/MBasicBlock.h - Machine Specific BB rep ----*- C++ -*-===// +// +// This class provides a way to represent a basic block in a machine-specific +// form. A basic block is represented as a list of machine specific +// instructions. +// +//===----------------------------------------------------------------------===// + +#ifndef CODEGEN_MBASICBLOCK_H +#define CODEGEN_MBASICBLOCK_H + +#include "llvm/CodeGen/MInstruction.h" +#include "Support/ilist" + +class MBasicBlock { + MBasicBlock *Prev, *Next; + iplist InstList; + // FIXME: we should maintain a pointer to the function we are embedded into! +public: + MBasicBlock() {} + + // Provide accessors for the MBasicBlock list... + typedef iplist InstListType; + typedef InstListType::iterator iterator; + typedef InstListType::const_iterator const_iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + + //===--------------------------------------------------------------------===// + /// Instruction iterator methods + /// + inline iterator begin() { return InstList.begin(); } + inline const_iterator begin() const { return InstList.begin(); } + inline iterator end () { return InstList.end(); } + inline const_iterator end () const { return InstList.end(); } + + inline reverse_iterator rbegin() { return InstList.rbegin(); } + inline const_reverse_iterator rbegin() const { return InstList.rbegin(); } + inline reverse_iterator rend () { return InstList.rend(); } + inline const_reverse_iterator rend () const { return InstList.rend(); } + + inline unsigned size() const { return InstList.size(); } + inline bool empty() const { return InstList.empty(); } + inline const MInstruction &front() const { return InstList.front(); } + inline MInstruction &front() { return InstList.front(); } + inline const MInstruction &back() const { return InstList.back(); } + inline MInstruction &back() { return InstList.back(); } + + /// getInstList() - Return the underlying instruction list container. You + /// need to access it directly if you want to modify it currently. + /// + const InstListType &getInstList() const { return InstList; } + InstListType &getInstList() { return InstList; } + +private: // Methods used to maintain doubly linked list of blocks... + friend class ilist_traits; + + MBasicBlock *getPrev() const { return Prev; } + MBasicBlock *getNext() const { return Next; } + void setPrev(MBasicBlock *P) { Prev = P; } + void setNext(MBasicBlock *N) { Next = N; } +}; + +#endif diff --git a/llvm/include/llvm/CodeGen/MFunction.h b/llvm/include/llvm/CodeGen/MFunction.h new file mode 100644 index 000000000000..683f2dfbf587 --- /dev/null +++ b/llvm/include/llvm/CodeGen/MFunction.h @@ -0,0 +1,70 @@ +//===-- llvm/CodeGen/MFunction.h - Machine Specific Function ----*- C++ -*-===// +// +// This class provides a way to represent a function in a machine-specific form. +// A function is represented as a list of machine specific blocks along with a +// list of registers that are used to receive arguments for the function. +// +// In the machine specific representation for a function, the function may +// either be in SSA form or in a register based form. When in SSA form, the +// register numbers are indexes into the RegDefMap that the MFunction contains. +// This allows accessing SSA use-def information by using the source register +// number for a use. +// +// After register allocation occurs, all of the register numbers in a function +// refer to real hardware registers and the RegDefMap is cleared. +// +//===----------------------------------------------------------------------===// + +#ifndef CODEGEN_MFUNCTION_H +#define CODEGEN_MFUNCTION_H + +#include "llvm/CodeGen/MBasicBlock.h" +#include +class MInstructionInfo; + +class MFunction { + iplist BasicBlocks; + // FIXME: This should contain a pointer to the LLVM function +public: + + /// print - Provide a way to get a simple debugging dump. This dumps the + /// machine code in a simple "assembly" language that is not really suitable + /// for an assembler, but is useful for debugging. This is completely target + /// independant. + /// + void print(std::ostream &OS, const MInstructionInfo &MII) const; + void dump(const MInstructionInfo &MII) const; + + // Provide accessors for the MBasicBlock list... + typedef iplist BasicBlockListType; + typedef BasicBlockListType::iterator iterator; + typedef BasicBlockListType::const_iterator const_iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + + // Provide accessors for basic blocks... + const BasicBlockListType &getBasicBlockList() const { return BasicBlocks; } + BasicBlockListType &getBasicBlockList() { return BasicBlocks; } + + //===--------------------------------------------------------------------===// + // BasicBlock iterator forwarding functions + // + iterator begin() { return BasicBlocks.begin(); } + const_iterator begin() const { return BasicBlocks.begin(); } + iterator end () { return BasicBlocks.end(); } + const_iterator end () const { return BasicBlocks.end(); } + + reverse_iterator rbegin() { return BasicBlocks.rbegin(); } + const_reverse_iterator rbegin() const { return BasicBlocks.rbegin(); } + reverse_iterator rend () { return BasicBlocks.rend(); } + const_reverse_iterator rend () const { return BasicBlocks.rend(); } + + unsigned size() const { return BasicBlocks.size(); } + bool empty() const { return BasicBlocks.empty(); } + const MBasicBlock &front() const { return BasicBlocks.front(); } + MBasicBlock &front() { return BasicBlocks.front(); } + const MBasicBlock &back() const { return BasicBlocks.back(); } + MBasicBlock &back() { return BasicBlocks.back(); } +}; + +#endif diff --git a/llvm/include/llvm/CodeGen/MInstBuilder.h b/llvm/include/llvm/CodeGen/MInstBuilder.h new file mode 100644 index 000000000000..6b0ba51fff72 --- /dev/null +++ b/llvm/include/llvm/CodeGen/MInstBuilder.h @@ -0,0 +1,51 @@ +//===-- CodeGen/MInstBuilder.h - Simplify creation of MInstcn's -*- C++ -*-===// +// +// This file exposes a function named BuildMInst that is useful for dramatically +// simplifying how MInstruction's are created. Instead of using code like this: +// +// M = new MInstruction(BB, X86::ADDrr32, DestReg); +// M->addOperand(Arg0Reg, MOperand::Register); +// M->addOperand(Arg1Reg, MOperand::Register); +// +// we can now use code like this: +// +// M = BuildMInst(BB, X86::ADDrr8, DestReg).addReg(Arg0Reg).addReg(Arg1Reg); +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MINSTBUILDER_H +#define LLVM_CODEGEN_MINSTBUILDER_H + +#include "llvm/CodeGen/MInstruction.h" + +struct MInstructionBuilder { + MInstruction *MI; + + MInstructionBuilder(MInstruction *mi) : MI(mi) {} + + /// Allow automatic conversion to the machine instruction we are working on. + /// + operator MInstruction*() const { return MI; } + + /// addReg - Add a new register operand... + /// + MInstructionBuilder &addReg(unsigned RegNo) { + MI->addOperand(RegNo, MOperand::Register); + return *this; + } + +}; + +/// BuildMInst - Builder interface. Specify how to create the initial +/// instruction itself. +/// +inline MInstructionBuilder BuildMInst(unsigned Opcode, unsigned DestReg = 0) { + return MInstructionBuilder(new MInstruction(Opcode, DestReg)); +} + +inline MInstructionBuilder BuildMInst(MBasicBlock *BB, unsigned Opcode, + unsigned DestReg = 0) { + return MInstructionBuilder(new MInstruction(BB, Opcode, DestReg)); +} + +#endif diff --git a/llvm/include/llvm/CodeGen/MInstruction.h b/llvm/include/llvm/CodeGen/MInstruction.h new file mode 100644 index 000000000000..b96a88f0796b --- /dev/null +++ b/llvm/include/llvm/CodeGen/MInstruction.h @@ -0,0 +1,150 @@ +//===-- llvm/CodeGen/MInstruction.h - Machine Instruction -------*- C++ -*-===// +// +// This class represents a single machine instruction for the LLVM backend. +// This instruction is represented in a completely generic way to allow all +// backends to share a common representation. MInstructions are embedded into +// MBasicBlocks, and are maintained as a doubly linked list. +// +// Because there are a lot of machine instruction that may be in use at a time +// (being manipulated), we are sure to keep a very compact representation that +// is extremely light-weight. +// +// This class is used to represent an instruction when it is in SSA form as well +// as when it has been register allocated to use physical registers. +// +// FIXME: This should eventually be merged with the MachineInstr class. +// +//===----------------------------------------------------------------------===// + +#ifndef CODEGEN_MINSTRUCTION_H +#define CODEGEN_MINSTRUCTION_H + +#include +template struct ilist_traits; +class MBasicBlock; + +/// MOperand - This class represents a single operand in an instruction. +/// Interpretation of this operand is not really possible without information +/// from the machine instruction that it is embedded into. +/// +class MOperand { + union { + unsigned uVal; + int iVal; + }; +public: + MOperand(unsigned Value) : uVal(Value) {} + MOperand(int Value) : iVal(Value) {} + + /// Interpretation - This enum is used by the MInstruction class to interpret + /// the untyped value field of the operand. + enum Interpretation { + Register, // This is some register number + SignExtImmediate, // This is a sign extended immediate + ZeroExtImmediate, // This is a zero extended immediate + PCRelativeDisp // This is a displacement relative to the PC + // FIXME: We need a symbolic value here, like global variable address + }; + + unsigned getUnsignedValue() const { return uVal; } + unsigned getSignedValue() const { return iVal; } +}; + +/// MInstruction - Represent a single machine instruction in the code generator. +/// This is meant to be a light weight representation that is completely +/// independant of the target machine being code generated for. +/// +class MInstruction { + MInstruction *Prev, *Next; // Doubly linked list of instructions... + + unsigned Opcode; // Opcode of the instruction + unsigned Dest; // Destination register written (or 0 if none) + + std::vector Operands; // Operands of the instruction... + + /// OperandInterpretation - This array specifies how the operands of the + /// instruction are to be interpreted (is it a register?, an immediate + /// constant?, a PC relative displacement?, etc...). Only four values are + /// allowed, so any instruction with more than four operands (should be + /// exceedingly rare, perhaps only PHI nodes) are assumed to have register + /// operands beyond the fourth. + /// + unsigned char OperandInterpretation[4]; +public: + /// MInstruction ctor - Create a new machine instruction, with the specified + /// opcode and destination register. Operands are then added with the + /// addOperand method. + /// + MInstruction(unsigned O = 0, unsigned D = 0) : Opcode(O), Dest(D) {} + + /// MInstruction ctor - Create a new instruction, and append it to the + /// specified basic block. + /// + MInstruction(MBasicBlock *BB, unsigned Opcode = 0, unsigned Dest = 0); + + /// getOpcode - Return the opcode for this machine instruction. The value of + /// the opcode defines how to interpret the operands of the instruction. + /// + unsigned getOpcode() const { return Opcode; } + + /// getDestinationReg - This method returns the register written to by this + /// instruction. If this returns zero, the instruction does not produce a + /// value, because register #0 is always the garbage marker. + /// + unsigned getDestinationReg() const { return Dest; } + + /// setDestinationReg - This method changes the register written to by this + /// instruction. Note that if SSA form is currently active then the SSA table + /// needs to be updated to match this, thus this method shouldn't be used + /// directly. + /// + void setDestinationReg(unsigned R) { Dest = R; } + + /// getNumOperands - Return the number of operands the instruction currently + /// has. + /// + unsigned getNumOperands() const { return Operands.size(); } + + /// getOperandInterpretation - Return the interpretation of operand #Op + /// + MOperand::Interpretation getOperandInterpretation(unsigned Op) const { + if (Op < 4) return (MOperand::Interpretation)OperandInterpretation[Op]; + return MOperand::Register; // Operands >= 4 are all registers + } + + unsigned getRegisterOperand(unsigned Op) const { + assert(getOperandInterpretation(Op) == MOperand::Register && + "Operand isn't a register!"); + return Operands[Op].getUnsignedValue(); + } + int getSignExtOperand(unsigned Op) const { + assert(getOperandInterpretation(Op) == MOperand::SignExtImmediate && + "Operand isn't a sign extended immediate!"); + return Operands[Op].getSignedValue(); + } + unsigned getZeroExtOperand(unsigned Op) const { + assert(getOperandInterpretation(Op) == MOperand::ZeroExtImmediate && + "Operand isn't a zero extended immediate!"); + return Operands[Op].getUnsignedValue(); + } + int getPCRelativeOperand(unsigned Op) const { + assert(getOperandInterpretation(Op) == MOperand::PCRelativeDisp && + "Operand isn't a PC relative displacement!"); + return Operands[Op].getSignedValue(); + } + + /// addOperand - Add a new operand to the instruction with the specified value + /// and interpretation. + /// + void addOperand(unsigned Value, MOperand::Interpretation Ty); + +private: // Methods used to maintain doubly linked list of instructions... + friend class ilist_traits; + + MInstruction *getPrev() const { return Prev; } + MInstruction *getNext() const { return Next; } + void setPrev(MInstruction *P) { Prev = P; } + void setNext(MInstruction *N) { Next = N; } +}; + +#endif