|  | //===-- SparcFrameInfo.h - Define TargetFrameInfo for Sparc -----*- C++ -*-===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file was developed by the LLVM research group and is distributed under | 
|  | // the University of Illinois Open Source License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | // Interface to stack frame layout info for the UltraSPARC. | 
|  | // Starting offsets for each area of the stack frame are aligned at | 
|  | // a multiple of getStackFrameSizeAlignment(). | 
|  | // | 
|  | //---------------------------------------------------------------------------- | 
|  |  | 
|  | #ifndef SPARC_FRAMEINFO_H | 
|  | #define SPARC_FRAMEINFO_H | 
|  |  | 
|  | #include "llvm/Target/TargetFrameInfo.h" | 
|  | #include "llvm/Target/TargetMachine.h" | 
|  | #include "llvm/Target/TargetRegInfo.h" | 
|  |  | 
|  | namespace llvm { | 
|  |  | 
|  | class SparcFrameInfo: public TargetFrameInfo { | 
|  | const TargetMachine ⌖ | 
|  | public: | 
|  | SparcFrameInfo(const TargetMachine &TM) | 
|  | : TargetFrameInfo(StackGrowsDown, StackFrameSizeAlignment, 0), target(TM) {} | 
|  |  | 
|  | 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. | 
|  | // | 
|  | int getFirstIncomingArgOffset(MachineFunction& mcInfo, bool& growUp) const { | 
|  | growUp = true;                         // arguments area grows upwards | 
|  | return FirstIncomingArgOffsetFromFP; | 
|  | } | 
|  | int getFirstOutgoingArgOffset(MachineFunction& mcInfo, bool& growUp) const { | 
|  | growUp = true;                         // arguments area grows upwards | 
|  | return FirstOutgoingArgOffsetFromSP; | 
|  | } | 
|  | int getFirstOptionalOutgoingArgOffset(MachineFunction& mcInfo, | 
|  | bool& growUp) const { | 
|  | growUp = true;                         // arguments area grows upwards | 
|  | return FirstOptionalOutgoingArgOffsetFromSP; | 
|  | } | 
|  |  | 
|  | int getFirstAutomaticVarOffset(MachineFunction& mcInfo, bool& growUp) const; | 
|  | int getRegSpillAreaOffset(MachineFunction& mcInfo, bool& growUp) const; | 
|  | int getTmpAreaOffset(MachineFunction& mcInfo, bool& growUp) const; | 
|  | int getDynamicAreaOffset(MachineFunction& mcInfo, bool& growUp) const; | 
|  |  | 
|  | // | 
|  | // These methods specify the base register used for each stack area | 
|  | // (generally FP or SP) | 
|  | // | 
|  | virtual int getIncomingArgBaseRegNum() const { | 
|  | return (int) target.getRegInfo().getFramePointer(); | 
|  | } | 
|  | virtual int getOutgoingArgBaseRegNum() const { | 
|  | return (int) target.getRegInfo().getStackPointer(); | 
|  | } | 
|  | virtual int getOptionalOutgoingArgBaseRegNum() const { | 
|  | return (int) target.getRegInfo().getStackPointer(); | 
|  | } | 
|  | virtual int getAutomaticVarBaseRegNum() const { | 
|  | return (int) target.getRegInfo().getFramePointer(); | 
|  | } | 
|  | virtual int getRegSpillAreaBaseRegNum() const { | 
|  | return (int) target.getRegInfo().getFramePointer(); | 
|  | } | 
|  | virtual int getDynamicAreaBaseRegNum() const { | 
|  | return (int) target.getRegInfo().getStackPointer(); | 
|  | } | 
|  |  | 
|  | virtual int getIncomingArgOffset(MachineFunction& mcInfo, | 
|  | unsigned argNum) const { | 
|  | assert(argsOnStackHaveFixedSize()); | 
|  |  | 
|  | unsigned relativeOffset = argNum * getSizeOfEachArgOnStack(); | 
|  | bool growUp;                          // do args grow up or down | 
|  | int firstArg = getFirstIncomingArgOffset(mcInfo, growUp); | 
|  | return growUp ? firstArg + relativeOffset : firstArg - relativeOffset; | 
|  | } | 
|  |  | 
|  | virtual int getOutgoingArgOffset(MachineFunction& mcInfo, | 
|  | unsigned argNum) const { | 
|  | assert(argsOnStackHaveFixedSize()); | 
|  | //assert(((int) argNum - this->getNumFixedOutgoingArgs()) | 
|  | //     <= (int) mcInfo.getInfo()->getMaxOptionalNumArgs()); | 
|  |  | 
|  | unsigned relativeOffset = argNum * getSizeOfEachArgOnStack(); | 
|  | bool growUp;                          // do args grow up or down | 
|  | int firstArg = getFirstOutgoingArgOffset(mcInfo, growUp); | 
|  | return growUp ? firstArg + relativeOffset : firstArg - relativeOffset; | 
|  | } | 
|  |  | 
|  | 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 assumptions 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 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; | 
|  | }; | 
|  |  | 
|  | } // End llvm namespace | 
|  |  | 
|  | #endif |