mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-10-31 09:11:13 +00:00
d71295a684
implementation of a Target{RegInfo, InstrInfo, Machine, etc} now has a separate header and a separate implementation file. This means that instead of a massive SparcInternals.h that forces a recompilation of the whole target whenever a minor detail is changed, you should only recompile a few files. Note that SparcInternals.h is still around; its contents should be minimized. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@10500 91177308-0d34-0410-b5e6-96231b3b80d8
175 lines
7.5 KiB
C++
175 lines
7.5 KiB
C++
//===-- 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
|