Initial checkin of Machine Code representation for X86 backend. This will
authorChris Lattner <sabre@nondot.org>
Fri, 25 Oct 2002 23:00:13 +0000 (23:00 +0000)
committerChris Lattner <sabre@nondot.org>
Fri, 25 Oct 2002 23:00:13 +0000 (23:00 +0000)
eventually be merged with the sparc backend.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4286 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/CodeGen/MBasicBlock.h [new file with mode: 0644]
include/llvm/CodeGen/MFunction.h [new file with mode: 0644]
include/llvm/CodeGen/MInstBuilder.h [new file with mode: 0644]
include/llvm/CodeGen/MInstruction.h [new file with mode: 0644]

diff --git a/include/llvm/CodeGen/MBasicBlock.h b/include/llvm/CodeGen/MBasicBlock.h
new file mode 100644 (file)
index 0000000..f846de5
--- /dev/null
@@ -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<MInstruction> InstList;
+  // FIXME: we should maintain a pointer to the function we are embedded into!
+public:
+  MBasicBlock() {}
+
+  // Provide accessors for the MBasicBlock list...
+  typedef iplist<MInstruction> InstListType;
+  typedef InstListType::iterator iterator;
+  typedef InstListType::const_iterator const_iterator;
+  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+  typedef std::reverse_iterator<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>;
+
+  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/include/llvm/CodeGen/MFunction.h b/include/llvm/CodeGen/MFunction.h
new file mode 100644 (file)
index 0000000..683f2df
--- /dev/null
@@ -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 <iosfwd>
+class MInstructionInfo;
+
+class MFunction {
+  iplist<MBasicBlock> 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<MBasicBlock> BasicBlockListType;
+  typedef BasicBlockListType::iterator iterator;
+  typedef BasicBlockListType::const_iterator const_iterator;
+  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+  typedef std::reverse_iterator<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/include/llvm/CodeGen/MInstBuilder.h b/include/llvm/CodeGen/MInstBuilder.h
new file mode 100644 (file)
index 0000000..6b0ba51
--- /dev/null
@@ -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/include/llvm/CodeGen/MInstruction.h b/include/llvm/CodeGen/MInstruction.h
new file mode 100644 (file)
index 0000000..b96a88f
--- /dev/null
@@ -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 <vector>
+template<typename NodeTy> 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<MOperand> 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>;
+
+  MInstruction *getPrev() const { return Prev; }
+  MInstruction *getNext() const { return Next; }
+  void setPrev(MInstruction *P) { Prev = P; }
+  void setNext(MInstruction *N) { Next = N; }
+};
+
+#endif