Make sure to escape \'s when they are output
[oota-llvm.git] / lib / Target / SparcV9 / SparcV9Internals.h
index a3dc7c3974211ae1e9415666ea2a69658d15369f..2399a1e68b3971c6873eb6e48845c5f9fa90d040 100644 (file)
@@ -13,6 +13,7 @@
 #include "llvm/Target/MachineFrameInfo.h"
 #include "llvm/Target/MachineCacheInfo.h"
 #include "llvm/Target/MachineRegInfo.h"
+#include "llvm/Target/MachineOptInfo.h"
 #include "llvm/Type.h"
 #include <sys/types.h>
 
@@ -21,8 +22,6 @@ class UltraSparc;
 class PhyRegAlloc;
 class Pass;
 
-Pass *createPrologEpilogCodeInserter(TargetMachine &TM);
-
 // OpCodeMask definitions for the Sparc V9
 // 
 const OpCodeMask       Immed           = 0x00002000; // immed or reg operand?
@@ -88,7 +87,7 @@ struct UltraSparcInstrInfo : public MachineInstrInfo {
 
   //
   // All immediate constants are in position 1 except the
-  // store instructions.
+  // store instructions and SETxx.
   // 
   virtual int getImmedConstantPos(MachineOpCode opCode) const {
     bool ignore;
@@ -96,7 +95,11 @@ struct UltraSparcInstrInfo : public MachineInstrInfo {
       {
         assert(! this->isStore((MachineOpCode) STB - 1)); // 1st  store opcode
         assert(! this->isStore((MachineOpCode) STXFSR+1));// last store opcode
-        return (opCode >= STB && opCode <= STXFSR)? 2 : 1;
+        if (opCode==SETSW || opCode==SETUW || opCode==SETX || opCode==SETHI)
+          return 0;
+        if (opCode >= STB && opCode <= STXFSR)
+          return 2;
+        return 1;
       }
     else
       return -1;
@@ -113,10 +116,22 @@ struct UltraSparcInstrInfo : public MachineInstrInfo {
     return (opCode == FCMPS || opCode == FCMPD || opCode == FCMPQ);
   }
 
+  //-------------------------------------------------------------------------
+  // Queries about representation of LLVM quantities (e.g., constants)
+  //-------------------------------------------------------------------------
+
+  virtual bool ConstantMayNotFitInImmedField(const Constant* CV,
+                                             const Instruction* I) const;
+
   //-------------------------------------------------------------------------
   // Code generation support for creating individual machine instructions
   //-------------------------------------------------------------------------
-  
+
+  // Get certain common op codes for the current target.  This and all the
+  // Create* methods below should be moved to a machine code generation class
+  // 
+  virtual MachineOpCode getNOPOpCode() const { return NOP; }
+
   // Create an instruction sequence to put the constant `val' into
   // the virtual register `dest'.  `val' may be a Constant or a
   // GlobalValue, viz., the constant address of a global variable or function.
@@ -172,13 +187,29 @@ struct UltraSparcInstrInfo : public MachineInstrInfo {
 
   // Create instruction sequence to produce a sign-extended register value
   // from an arbitrary sized value (sized in bits, not bytes).
+  // The generated instructions are appended to `mvec'.
+  // Any temp. registers (TmpInstruction) created are recorded in mcfi.
   // Any stack space required is allocated via mcff.
   // 
   virtual void CreateSignExtensionInstructions(const TargetMachine& target,
                                        Function* F,
-                                       Value* unsignedSrcVal,
-                                       unsigned int srcSizeInBits,
-                                       Value* dest,
+                                       Value* srcVal,
+                                       Value* destVal,
+                                       unsigned int numLowBits,
+                                       std::vector<MachineInstr*>& mvec,
+                                       MachineCodeForInstruction& mcfi) const;
+
+  // Create instruction sequence to produce a zero-extended register value
+  // from an arbitrary sized value (sized in bits, not bytes).
+  // The generated instructions are appended to `mvec'.
+  // Any temp. registers (TmpInstruction) created are recorded in mcfi.
+  // Any stack space required is allocated via mcff.
+  // 
+  virtual void CreateZeroExtensionInstructions(const TargetMachine& target,
+                                       Function* F,
+                                       Value* srcVal,
+                                       Value* destVal,
+                                       unsigned int numLowBits,
                                        std::vector<MachineInstr*>& mvec,
                                        MachineCodeForInstruction& mcfi) const;
 };
@@ -219,10 +250,6 @@ class UltraSparcRegInfo : public MachineRegInfo {
   // order for efficiency.
 
 
-  // reverse pointer to get info about the ultra sparc machine
-  //
-  const UltraSparc *const UltraSparcInfo;
-
   // Number of registers used for passing int args (usually 6: %o0 - %o5)
   //
   unsigned const NumOfIntArgRegs;
@@ -246,8 +273,7 @@ class UltraSparcRegInfo : public MachineRegInfo {
   void suggestReg4RetAddr(MachineInstr *RetMI, 
                          LiveRangeInfo &LRI) const;
 
-  void suggestReg4CallAddr(MachineInstr *CallMI, LiveRangeInfo &LRI,
-                          std::vector<RegClass *> RCList) const;
+  void suggestReg4CallAddr(MachineInstr *CallMI, LiveRangeInfo &LRI) const;
   
   void InitializeOutgoingArg(MachineInstr* CallMI, AddedInstrns *CallAI,
                              PhyRegAlloc &PRA, LiveRange* LR,
@@ -299,13 +325,6 @@ class UltraSparcRegInfo : public MachineRegInfo {
 public:
   UltraSparcRegInfo(const UltraSparc &tgt);
 
-  // To get complete machine information structure using the machine register
-  // information
-  //
-  inline const UltraSparc &getUltraSparcInfo() const { 
-    return *UltraSparcInfo;
-  }
-
   // To find the register class used for a specified Type
   //
   unsigned getRegClassIDOfType(const Type *type,
@@ -353,8 +372,7 @@ public:
                              LiveRangeInfo& LRI) const;
 
   void suggestRegs4CallArgs(MachineInstr *CallMI, 
-                           LiveRangeInfo& LRI,
-                            std::vector<RegClass *> RCL) const; 
+                           LiveRangeInfo& LRI) const; 
 
   void suggestReg4RetValue(MachineInstr *RetMI, 
                            LiveRangeInfo& LRI) const;
@@ -522,13 +540,22 @@ public:
   UltraSparcFrameInfo(const TargetMachine &tgt) : MachineFrameInfo(tgt) {}
   
 public:
+  // These methods provide constant parameters of the frame layout.
+  // 
   int  getStackFrameSizeAlignment() const { return StackFrameSizeAlignment;}
   int  getMinStackFrameSize()       const { return MinStackFrameSize; }
   int  getNumFixedOutgoingArgs()    const { return NumFixedOutgoingArgs; }
   int  getSizeOfEachArgOnStack()    const { return SizeOfEachArgOnStack; }
   bool argsOnStackHaveFixedSize()   const { return true; }
 
-  //
+  // This method adjusts a stack offset to meet alignment rules of target.
+  // The fixed OFFSET (0x7ff) must be subtracted and the result aligned.
+  virtual int  adjustAlignment                  (int unalignedOffset,
+                                                 bool growUp,
+                                                 unsigned int align) const {
+    return unalignedOffset + (growUp? +1:-1)*((unalignedOffset-OFFSET) % align);
+  }
+
   // These methods compute offsets using the frame contents for a
   // particular function.  The frame contents are obtained from the
   // MachineCodeInfoForMethod object for the given function.
@@ -585,15 +612,58 @@ public:
   }
   
 private:
+  /*----------------------------------------------------------------------
+    This diagram shows the stack frame layout used by llc on Sparc V9.
+    Note that only the location of automatic variables, spill area,
+    temporary storage, and dynamically allocated stack area are chosen
+    by us.  The rest conform to the Sparc V9 ABI.
+    All stack addresses are offset by OFFSET = 0x7ff (2047).
+
+    Alignment assumpteions and other invariants:
+    (1) %sp+OFFSET and %fp+OFFSET are always aligned on 16-byte boundary
+    (2) Variables in automatic, spill, temporary, or dynamic regions
+        are aligned according to their size as in all memory accesses.
+    (3) Everything below the dynamically allocated stack area is only used
+        during a call to another function, so it is never needed when
+        the current function is active.  This is why space can be allocated
+        dynamically by incrementing %sp any time within the function.
+    
+    STACK FRAME LAYOUT:
+
+       ...
+       %fp+OFFSET+176      Optional extra incoming arguments# 1..N
+       %fp+OFFSET+168      Incoming argument #6
+       ...                 ...
+       %fp+OFFSET+128      Incoming argument #1
+       ...                 ...
+    ---%fp+OFFSET-0--------Bottom of caller's stack frame--------------------
+       %fp+OFFSET-8        Automatic variables <-- ****TOP OF STACK FRAME****
+                           Spill area
+                           Temporary storage
+       ...
+
+       %sp+OFFSET+176+8N   Bottom of dynamically allocated stack area
+       %sp+OFFSET+168+8N   Optional extra outgoing argument# N
+       ...                 ...
+       %sp+OFFSET+176      Optional extra outgoing argument# 1
+       %sp+OFFSET+168      Outgoing argument #6
+       ...                 ...
+       %sp+OFFSET+128      Outgoing argument #1
+       %sp+OFFSET+120      Save area for %i7
+       ...                 ...
+       %sp+OFFSET+0        Save area for %l0 <-- ****BOTTOM OF STACK FRAME****
+
+   *----------------------------------------------------------------------*/
+
   // All stack addresses must be offset by 0x7ff (2047) on Sparc V9.
   static const int OFFSET                                  = (int) 0x7ff;
   static const int StackFrameSizeAlignment                 =  16;
   static const int MinStackFrameSize                       = 176;
   static const int NumFixedOutgoingArgs                    =   6;
   static const int SizeOfEachArgOnStack                    =   8;
-  static const int StaticAreaOffsetFromFP                  =  0 + OFFSET;
   static const int FirstIncomingArgOffsetFromFP            = 128 + OFFSET;
   static const int FirstOptionalIncomingArgOffsetFromFP    = 176 + OFFSET;
+  static const int StaticAreaOffsetFromFP                  =   0 + OFFSET;
   static const int FirstOutgoingArgOffsetFromSP            = 128 + OFFSET;
   static const int FirstOptionalOutgoingArgOffsetFromSP    = 176 + OFFSET;
 };
@@ -613,6 +683,21 @@ public:
 };
 
 
+//---------------------------------------------------------------------------
+// class UltraSparcOptInfo 
+// 
+// Purpose:
+//   Interface to machine-level optimization routines for the UltraSPARC.
+//---------------------------------------------------------------------------
+
+class UltraSparcOptInfo: public MachineOptInfo {
+public:
+  UltraSparcOptInfo(const TargetMachine &T) : MachineOptInfo(T) {} 
+
+  virtual bool IsUselessCopy    (const MachineInstr* MI) const;
+};
+
+
 //---------------------------------------------------------------------------
 // class UltraSparcMachine 
 // 
@@ -630,25 +715,28 @@ private:
   UltraSparcRegInfo   regInfo;
   UltraSparcFrameInfo frameInfo;
   UltraSparcCacheInfo cacheInfo;
+  UltraSparcOptInfo   optInfo;
 public:
   UltraSparc();
-  
+
   virtual const MachineInstrInfo &getInstrInfo() const { return instrInfo; }
   virtual const MachineSchedInfo &getSchedInfo() const { return schedInfo; }
   virtual const MachineRegInfo   &getRegInfo()   const { return regInfo; }
   virtual const MachineFrameInfo &getFrameInfo() const { return frameInfo; }
   virtual const MachineCacheInfo &getCacheInfo() const { return cacheInfo; }
+  virtual const MachineOptInfo   &getOptInfo()   const { return optInfo; }
 
-  //
-  // addPassesToEmitAssembly - Add passes to the specified pass manager to get
-  // assembly langage code emited.  For sparc, we have to do ...
-  //
-  virtual void addPassesToEmitAssembly(PassManager &PM, std::ostream &Out);
+  // getPrologEpilogCodeInserter - Inserts prolog/epilog code.
+  virtual Pass* getPrologEpilogInsertionPass();
 
-private:
-  Pass *getFunctionAsmPrinterPass(PassManager &PM, std::ostream &Out);
-  Pass *getModuleAsmPrinterPass(PassManager &PM, std::ostream &Out);
-  Pass *getEmitBytecodeToAsmPass(std::ostream &Out);
+  // getFunctionAsmPrinterPass - Writes out machine code for a single function
+  virtual Pass* getFunctionAsmPrinterPass(std::ostream &Out);
+
+  // getModuleAsmPrinterPass - Writes generated machine code to assembly file.
+  virtual Pass* getModuleAsmPrinterPass(std::ostream &Out);
+
+  // getEmitBytecodeToAsmPass - Emits final LLVM bytecode to assembly file.
+  virtual Pass* getEmitBytecodeToAsmPass(std::ostream &Out);
 };
 
 #endif