mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-02 18:31:54 +00:00
Some preliminary call lowering
llvm-svn: 75941
This commit is contained in:
parent
f4257ba74e
commit
4fcadd1a7d
@ -185,6 +185,20 @@ void SystemZAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
|
||||
case MachineOperand::MO_MachineBasicBlock:
|
||||
printBasicBlockLabel(MO.getMBB());
|
||||
return;
|
||||
case MachineOperand::MO_GlobalAddress: {
|
||||
std::string Name = Mang->getValueName(MO.getGlobal());
|
||||
assert(MO.getOffset() == 0 && "No offsets allowed!");
|
||||
|
||||
O << Name;
|
||||
|
||||
return;
|
||||
}
|
||||
case MachineOperand::MO_ExternalSymbol: {
|
||||
std::string Name(TAI->getGlobalPrefix());
|
||||
Name += MO.getSymbolName();
|
||||
O << Name;
|
||||
return;
|
||||
}
|
||||
default:
|
||||
assert(0 && "Not implemented yet!");
|
||||
}
|
||||
|
@ -61,6 +61,7 @@ SDValue SystemZTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
|
||||
switch (Op.getOpcode()) {
|
||||
case ISD::FORMAL_ARGUMENTS: return LowerFORMAL_ARGUMENTS(Op, DAG);
|
||||
case ISD::RET: return LowerRET(Op, DAG);
|
||||
case ISD::CALL: return LowerCALL(Op, DAG);
|
||||
default:
|
||||
assert(0 && "unimplemented operand");
|
||||
return SDValue();
|
||||
@ -85,6 +86,18 @@ SDValue SystemZTargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op,
|
||||
}
|
||||
}
|
||||
|
||||
SDValue SystemZTargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
|
||||
CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
|
||||
unsigned CallingConv = TheCall->getCallingConv();
|
||||
switch (CallingConv) {
|
||||
default:
|
||||
assert(0 && "Unsupported calling convention");
|
||||
case CallingConv::Fast:
|
||||
case CallingConv::C:
|
||||
return LowerCCCCallTo(Op, DAG, CallingConv);
|
||||
}
|
||||
}
|
||||
|
||||
/// LowerCCCArguments - transform physical registers into virtual registers and
|
||||
/// generate load operations for arguments places on the stack.
|
||||
// FIXME: struct return stuff
|
||||
@ -167,6 +180,167 @@ SDValue SystemZTargetLowering::LowerCCCArguments(SDValue Op,
|
||||
&ArgValues[0], ArgValues.size()).getValue(Op.getResNo());
|
||||
}
|
||||
|
||||
/// LowerCCCCallTo - functions arguments are copied from virtual regs to
|
||||
/// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted.
|
||||
/// TODO: sret.
|
||||
SDValue SystemZTargetLowering::LowerCCCCallTo(SDValue Op, SelectionDAG &DAG,
|
||||
unsigned CC) {
|
||||
CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
|
||||
SDValue Chain = TheCall->getChain();
|
||||
SDValue Callee = TheCall->getCallee();
|
||||
bool isVarArg = TheCall->isVarArg();
|
||||
DebugLoc dl = Op.getDebugLoc();
|
||||
|
||||
// Analyze operands of the call, assigning locations to each operand.
|
||||
SmallVector<CCValAssign, 16> ArgLocs;
|
||||
CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs);
|
||||
|
||||
CCInfo.AnalyzeCallOperands(TheCall, CC_SystemZ);
|
||||
|
||||
// Get a count of how many bytes are to be pushed on the stack.
|
||||
unsigned NumBytes = CCInfo.getNextStackOffset();
|
||||
|
||||
Chain = DAG.getCALLSEQ_START(Chain ,DAG.getConstant(NumBytes,
|
||||
getPointerTy(), true));
|
||||
|
||||
SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass;
|
||||
SmallVector<SDValue, 12> MemOpChains;
|
||||
SDValue StackPtr;
|
||||
|
||||
// Walk the register/memloc assignments, inserting copies/loads.
|
||||
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
|
||||
CCValAssign &VA = ArgLocs[i];
|
||||
|
||||
// Arguments start after the 5 first operands of ISD::CALL
|
||||
SDValue Arg = TheCall->getArg(i);
|
||||
|
||||
// Promote the value if needed.
|
||||
switch (VA.getLocInfo()) {
|
||||
default: assert(0 && "Unknown loc info!");
|
||||
case CCValAssign::Full: break;
|
||||
case CCValAssign::SExt:
|
||||
Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);
|
||||
break;
|
||||
case CCValAssign::ZExt:
|
||||
Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg);
|
||||
break;
|
||||
case CCValAssign::AExt:
|
||||
Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);
|
||||
break;
|
||||
}
|
||||
|
||||
// Arguments that can be passed on register must be kept at RegsToPass
|
||||
// vector
|
||||
if (VA.isRegLoc()) {
|
||||
RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
|
||||
} else {
|
||||
assert(VA.isMemLoc());
|
||||
|
||||
if (StackPtr.getNode() == 0)
|
||||
StackPtr = DAG.getCopyFromReg(Chain, dl, SystemZ::R15D, getPointerTy());
|
||||
|
||||
SDValue PtrOff = DAG.getNode(ISD::ADD, dl, getPointerTy(),
|
||||
StackPtr,
|
||||
DAG.getIntPtrConstant(VA.getLocMemOffset()));
|
||||
|
||||
|
||||
MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff,
|
||||
PseudoSourceValue::getStack(),
|
||||
VA.getLocMemOffset()));
|
||||
}
|
||||
}
|
||||
|
||||
// Transform all store nodes into one single node because all store nodes are
|
||||
// independent of each other.
|
||||
if (!MemOpChains.empty())
|
||||
Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
|
||||
&MemOpChains[0], MemOpChains.size());
|
||||
|
||||
// Build a sequence of copy-to-reg nodes chained together with token chain and
|
||||
// flag operands which copy the outgoing args into registers. The InFlag in
|
||||
// necessary since all emited instructions must be stuck together.
|
||||
SDValue InFlag;
|
||||
for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
|
||||
Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
|
||||
RegsToPass[i].second, InFlag);
|
||||
InFlag = Chain.getValue(1);
|
||||
}
|
||||
|
||||
// If the callee is a GlobalAddress node (quite common, every direct call is)
|
||||
// turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
|
||||
// Likewise ExternalSymbol -> TargetExternalSymbol.
|
||||
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
|
||||
Callee = DAG.getTargetGlobalAddress(G->getGlobal(), getPointerTy());
|
||||
else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
|
||||
Callee = DAG.getTargetExternalSymbol(E->getSymbol(), getPointerTy());
|
||||
|
||||
// Returns a chain & a flag for retval copy to use.
|
||||
SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
|
||||
SmallVector<SDValue, 8> Ops;
|
||||
Ops.push_back(Chain);
|
||||
Ops.push_back(Callee);
|
||||
|
||||
// Add argument registers to the end of the list so that they are
|
||||
// known live into the call.
|
||||
for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
|
||||
Ops.push_back(DAG.getRegister(RegsToPass[i].first,
|
||||
RegsToPass[i].second.getValueType()));
|
||||
|
||||
if (InFlag.getNode())
|
||||
Ops.push_back(InFlag);
|
||||
|
||||
Chain = DAG.getNode(SystemZISD::CALL, dl, NodeTys, &Ops[0], Ops.size());
|
||||
InFlag = Chain.getValue(1);
|
||||
|
||||
// Create the CALLSEQ_END node.
|
||||
Chain = DAG.getCALLSEQ_END(Chain,
|
||||
DAG.getConstant(NumBytes, getPointerTy(), true),
|
||||
DAG.getConstant(0, getPointerTy(), true),
|
||||
InFlag);
|
||||
InFlag = Chain.getValue(1);
|
||||
|
||||
// Handle result values, copying them out of physregs into vregs that we
|
||||
// return.
|
||||
return SDValue(LowerCallResult(Chain, InFlag, TheCall, CC, DAG),
|
||||
Op.getResNo());
|
||||
}
|
||||
|
||||
/// LowerCallResult - Lower the result values of an ISD::CALL into the
|
||||
/// appropriate copies out of appropriate physical registers. This assumes that
|
||||
/// Chain/InFlag are the input chain/flag to use, and that TheCall is the call
|
||||
/// being lowered. Returns a SDNode with the same number of values as the
|
||||
/// ISD::CALL.
|
||||
SDNode*
|
||||
SystemZTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag,
|
||||
CallSDNode *TheCall,
|
||||
unsigned CallingConv,
|
||||
SelectionDAG &DAG) {
|
||||
bool isVarArg = TheCall->isVarArg();
|
||||
DebugLoc dl = TheCall->getDebugLoc();
|
||||
|
||||
// Assign locations to each value returned by this call.
|
||||
SmallVector<CCValAssign, 16> RVLocs;
|
||||
CCState CCInfo(CallingConv, isVarArg, getTargetMachine(), RVLocs);
|
||||
|
||||
CCInfo.AnalyzeCallResult(TheCall, RetCC_SystemZ);
|
||||
SmallVector<SDValue, 8> ResultVals;
|
||||
|
||||
// Copy all of the result registers out of their specified physreg.
|
||||
for (unsigned i = 0; i != RVLocs.size(); ++i) {
|
||||
Chain = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(),
|
||||
RVLocs[i].getValVT(), InFlag).getValue(1);
|
||||
InFlag = Chain.getValue(2);
|
||||
ResultVals.push_back(Chain.getValue(0));
|
||||
}
|
||||
|
||||
ResultVals.push_back(Chain);
|
||||
|
||||
// Merge everything together with a MERGE_VALUES node.
|
||||
return DAG.getNode(ISD::MERGE_VALUES, dl, TheCall->getVTList(),
|
||||
&ResultVals[0], ResultVals.size()).getNode();
|
||||
}
|
||||
|
||||
|
||||
SDValue SystemZTargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) {
|
||||
// CCValAssign - represent the assignment of the return value to a location
|
||||
SmallVector<CCValAssign, 16> RVLocs;
|
||||
@ -226,6 +400,7 @@ SDValue SystemZTargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) {
|
||||
const char *SystemZTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
switch (Opcode) {
|
||||
case SystemZISD::RET_FLAG: return "SystemZISD::RET_FLAG";
|
||||
case SystemZISD::CALL: return "SystemZISD::CALL";
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,11 @@ namespace llvm {
|
||||
FIRST_NUMBER = ISD::BUILTIN_OP_END,
|
||||
|
||||
/// Return with a flag operand. Operand 0 is the chain operand.
|
||||
RET_FLAG
|
||||
RET_FLAG,
|
||||
|
||||
/// CALL/TAILCALL - These operations represent an abstract call
|
||||
/// instruction, which includes a bunch of information.
|
||||
CALL
|
||||
};
|
||||
}
|
||||
|
||||
@ -45,7 +49,10 @@ namespace llvm {
|
||||
|
||||
SDValue LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG);
|
||||
SDValue LowerRET(SDValue Op, SelectionDAG &DAG);
|
||||
SDValue LowerCALL(SDValue Op, SelectionDAG &DAG);
|
||||
|
||||
SDValue LowerCCCArguments(SDValue Op, SelectionDAG &DAG);
|
||||
SDValue LowerCCCCallTo(SDValue Op, SelectionDAG &DAG, unsigned CC);
|
||||
|
||||
SDNode* LowerCallResult(SDValue Chain, SDValue InFlag,
|
||||
CallSDNode *TheCall,
|
||||
|
@ -117,14 +117,21 @@ bool
|
||||
SystemZInstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MI,
|
||||
const std::vector<CalleeSavedInfo> &CSI) const {
|
||||
return false;
|
||||
if (CSI.empty())
|
||||
return false;
|
||||
|
||||
MachineFunction &MF = *MBB.getParent();
|
||||
SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>();
|
||||
MFI->setCalleeSavedFrameSize(CSI.size() * 8);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
SystemZInstrInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MI,
|
||||
const std::vector<CalleeSavedInfo> &CSI) const {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned
|
||||
|
@ -13,14 +13,34 @@
|
||||
|
||||
include "SystemZInstrFormats.td"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Type Constraints.
|
||||
//===----------------------------------------------------------------------===//
|
||||
class SDTCisI8<int OpNum> : SDTCisVT<OpNum, i8>;
|
||||
class SDTCisI16<int OpNum> : SDTCisVT<OpNum, i16>;
|
||||
class SDTCisI32<int OpNum> : SDTCisVT<OpNum, i32>;
|
||||
class SDTCisI64<int OpNum> : SDTCisVT<OpNum, i64>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Type Profiles.
|
||||
//===----------------------------------------------------------------------===//
|
||||
def SDT_SystemZCall : SDTypeProfile<0, -1, [SDTCisVT<0, iPTR>]>;
|
||||
def SDT_SystemZCallSeqStart : SDCallSeqStart<[SDTCisI64<0>]>;
|
||||
def SDT_SystemZCallSeqEnd : SDCallSeqEnd<[SDTCisI64<0>, SDTCisI64<1>]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// SystemZ Specific Node Definitions.
|
||||
//===----------------------------------------------------------------------===//
|
||||
def SystemZretflag : SDNode<"SystemZISD::RET_FLAG", SDTNone,
|
||||
[SDNPHasChain, SDNPOptInFlag]>;
|
||||
|
||||
let neverHasSideEffects = 1 in
|
||||
def NOP : Pseudo<(outs), (ins), "# no-op", []>;
|
||||
def SystemZcall : SDNode<"SystemZISD::CALL", SDT_SystemZCall,
|
||||
[SDNPHasChain, SDNPOutFlag, SDNPOptInFlag]>;
|
||||
def SystemZcallseq_start :
|
||||
SDNode<"ISD::CALLSEQ_START", SDT_SystemZCallSeqStart,
|
||||
[SDNPHasChain, SDNPOutFlag]>;
|
||||
def SystemZcallseq_end :
|
||||
SDNode<"ISD::CALLSEQ_END", SDT_SystemZCallSeqEnd,
|
||||
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Instruction Pattern Stuff.
|
||||
@ -172,6 +192,23 @@ def laaddr : Operand<i64>,
|
||||
let MIOperandInfo = (ops ADDR64:$base, i64imm:$disp, ADDR64:$index);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Instruction list..
|
||||
|
||||
// ADJCALLSTACKDOWN/UP implicitly use/def SP because they may be expanded into
|
||||
// a stack adjustment and the codegen must know that they may modify the stack
|
||||
// pointer before prolog-epilog rewriting occurs.
|
||||
// Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become
|
||||
// sub / add which can clobber R15D.
|
||||
let Defs = [R15D], Uses = [R15D] in {
|
||||
def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i64imm:$amt),
|
||||
"#ADJCALLSTACKDOWN",
|
||||
[(SystemZcallseq_start timm:$amt)]>;
|
||||
def ADJCALLSTACKUP : Pseudo<(outs), (ins i64imm:$amt1, i64imm:$amt2),
|
||||
"#ADJCALLSTACKUP",
|
||||
[(SystemZcallseq_end timm:$amt1, timm:$amt2)]>;
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Control Flow Instructions...
|
||||
@ -182,6 +219,22 @@ let isReturn = 1, isTerminator = 1, Uses = [R14D] in {
|
||||
def RET : Pseudo<(outs), (ins), "br\t%r14", [(SystemZretflag)]>;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Call Instructions...
|
||||
//
|
||||
|
||||
let isCall = 1 in
|
||||
// All calls clobber the non-callee saved registers. R15 is marked as
|
||||
// a use to prevent stack-pointer assignments that appear immediately
|
||||
// before calls from potentially appearing dead. Uses for argument
|
||||
// registers are added manually.
|
||||
let Defs = [R0D, R1D, R3D, R4D, R5D, R14D, R15D],
|
||||
Uses = [R15D] in {
|
||||
def CALLi : Pseudo<(outs), (ins i64imm:$dst, variable_ops),
|
||||
"brasl\t%r14, $dst", [(SystemZcall imm:$dst)]>;
|
||||
def CALLr : Pseudo<(outs), (ins ADDR64:$dst, variable_ops),
|
||||
"brasl\t%r14, $dst", [(SystemZcall ADDR64:$dst)]>;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Miscellaneous Instructions.
|
||||
@ -193,6 +246,8 @@ def LA64r : Pseudo<(outs GR64:$dst), (ins laaddr:$src),
|
||||
"lay\t{$dst, $src}",
|
||||
[(set GR64:$dst, laaddr:$src)]>;
|
||||
|
||||
let neverHasSideEffects = 1 in
|
||||
def NOP : Pseudo<(outs), (ins), "# no-op", []>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Move Instructions
|
||||
@ -525,3 +580,9 @@ def : Pat<(sext_inreg GR64:$src, i32),
|
||||
def : Pat<(extloadi64i8 rriaddr:$src), (MOVZX64rm8 rriaddr:$src)>;
|
||||
def : Pat<(extloadi64i16 rriaddr:$src), (MOVZX64rm16 rriaddr:$src)>;
|
||||
def : Pat<(extloadi64i32 rriaddr:$src), (MOVZX64rm32 rriaddr:$src)>;
|
||||
|
||||
// calls
|
||||
def : Pat<(SystemZcall (i64 tglobaladdr:$dst)),
|
||||
(CALLi tglobaladdr:$dst)>;
|
||||
def : Pat<(SystemZcall (i64 texternalsym:$dst)),
|
||||
(CALLi texternalsym:$dst)>;
|
||||
|
@ -12,6 +12,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "SystemZ.h"
|
||||
#include "SystemZMachineFunctionInfo.h"
|
||||
#include "SystemZRegisterInfo.h"
|
||||
#include "SystemZSubtarget.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
@ -26,7 +27,7 @@ using namespace llvm;
|
||||
|
||||
SystemZRegisterInfo::SystemZRegisterInfo(SystemZTargetMachine &tm,
|
||||
const TargetInstrInfo &tii)
|
||||
: SystemZGenRegisterInfo(SystemZ::NOP, SystemZ::NOP),
|
||||
: SystemZGenRegisterInfo(SystemZ::ADJCALLSTACKUP, SystemZ::ADJCALLSTACKDOWN),
|
||||
TM(tm), TII(tii) {
|
||||
}
|
||||
|
||||
@ -34,7 +35,7 @@ const unsigned*
|
||||
SystemZRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
|
||||
static const unsigned CalleeSavedRegs[] = {
|
||||
SystemZ::R6D, SystemZ::R7D, SystemZ::R8D, SystemZ::R9D,
|
||||
SystemZ::R10D, SystemZ::R11D, SystemZ::R12D, SystemZ::R13D,
|
||||
SystemZ::R10D, SystemZ::R11D, SystemZ::R12D, SystemZ::R13D, SystemZ::R14D,
|
||||
SystemZ::F1, SystemZ::F3, SystemZ::F5, SystemZ::F7,
|
||||
0
|
||||
};
|
||||
@ -49,6 +50,7 @@ SystemZRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
|
||||
&SystemZ::GR64RegClass, &SystemZ::GR64RegClass,
|
||||
&SystemZ::GR64RegClass, &SystemZ::GR64RegClass,
|
||||
&SystemZ::GR64RegClass, &SystemZ::GR64RegClass,
|
||||
&SystemZ::GR64RegClass,
|
||||
&SystemZ::FP64RegClass, &SystemZ::FP64RegClass,
|
||||
&SystemZ::FP64RegClass, &SystemZ::FP64RegClass, 0
|
||||
};
|
||||
@ -73,18 +75,32 @@ bool SystemZRegisterInfo::hasFP(const MachineFunction &MF) const {
|
||||
return NoFramePointerElim || MFI->hasVarSizedObjects();
|
||||
}
|
||||
|
||||
bool SystemZRegisterInfo::hasReservedCallFrame(MachineFunction &MF) const {
|
||||
return !MF.getFrameInfo()->hasVarSizedObjects();
|
||||
}
|
||||
|
||||
void SystemZRegisterInfo::
|
||||
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I) const {
|
||||
assert(0 && "Not implemented yet!");
|
||||
if (!hasReservedCallFrame(MF)) {
|
||||
assert(0 && "Not implemented yet!");
|
||||
}
|
||||
|
||||
MBB.erase(I);
|
||||
}
|
||||
|
||||
int SystemZRegisterInfo::getFrameIndexOffset(MachineFunction &MF, int FI) const {
|
||||
const TargetFrameInfo &TFI = *MF.getTarget().getFrameInfo();
|
||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
SystemZMachineFunctionInfo *SystemZMFI =
|
||||
MF.getInfo<SystemZMachineFunctionInfo>();
|
||||
int Offset = MFI->getObjectOffset(FI) + MFI->getOffsetAdjustment();
|
||||
uint64_t StackSize = MFI->getStackSize();
|
||||
|
||||
// Fixed objects are really located in the "previous" frame.
|
||||
if (FI < 0)
|
||||
StackSize -= SystemZMFI->getCalleeSavedFrameSize();
|
||||
|
||||
Offset += StackSize - TFI.getOffsetOfLocalArea();
|
||||
|
||||
// Skip the register save area if we generated the stack frame.
|
||||
@ -149,12 +165,17 @@ void SystemZRegisterInfo::emitPrologue(MachineFunction &MF) const {
|
||||
MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB
|
||||
const TargetFrameInfo &TFI = *MF.getTarget().getFrameInfo();
|
||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
SystemZMachineFunctionInfo *SystemZMFI =
|
||||
MF.getInfo<SystemZMachineFunctionInfo>();
|
||||
MachineBasicBlock::iterator MBBI = MBB.begin();
|
||||
DebugLoc DL = (MBBI != MBB.end() ? MBBI->getDebugLoc() :
|
||||
DebugLoc::getUnknownLoc());
|
||||
|
||||
// Get the number of bytes to allocate from the FrameInfo.
|
||||
uint64_t StackSize = MFI->getStackSize();
|
||||
// Note that area for callee-saved stuff is already allocated, thus we need to
|
||||
// 'undo' the stack movement.
|
||||
uint64_t StackSize =
|
||||
MFI->getStackSize() - SystemZMFI->getCalleeSavedFrameSize();
|
||||
|
||||
// FIXME: Skip the callee-saved push instructions.
|
||||
|
||||
@ -184,6 +205,8 @@ void SystemZRegisterInfo::emitEpilogue(MachineFunction &MF,
|
||||
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
const TargetFrameInfo &TFI = *MF.getTarget().getFrameInfo();
|
||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
||||
SystemZMachineFunctionInfo *SystemZMFI =
|
||||
MF.getInfo<SystemZMachineFunctionInfo>();
|
||||
unsigned RetOpcode = MBBI->getOpcode();
|
||||
DebugLoc DL = MBBI->getDebugLoc();
|
||||
|
||||
@ -194,7 +217,10 @@ void SystemZRegisterInfo::emitEpilogue(MachineFunction &MF,
|
||||
}
|
||||
|
||||
// Get the number of bytes to allocate from the FrameInfo
|
||||
uint64_t StackSize = MFI->getStackSize();
|
||||
// Note that area for callee-saved stuff is already allocated, thus we need to
|
||||
// 'undo' the stack movement.
|
||||
uint64_t StackSize =
|
||||
MFI->getStackSize() - SystemZMFI->getCalleeSavedFrameSize();
|
||||
uint64_t NumBytes = StackSize - TFI.getOffsetOfLocalArea();
|
||||
|
||||
// Skip the callee-saved regs load instructions.
|
||||
|
@ -37,6 +37,7 @@ struct SystemZRegisterInfo : public SystemZGenRegisterInfo {
|
||||
|
||||
BitVector getReservedRegs(const MachineFunction &MF) const;
|
||||
|
||||
bool hasReservedCallFrame(MachineFunction &MF) const;
|
||||
bool hasFP(const MachineFunction &MF) const;
|
||||
|
||||
int getFrameIndexOffset(MachineFunction &MF, int FI) const;
|
||||
|
17
test/CodeGen/SystemZ/06-CallViaStack.ll
Normal file
17
test/CodeGen/SystemZ/06-CallViaStack.ll
Normal file
@ -0,0 +1,17 @@
|
||||
; RUN: llvm-as < %s | llc | grep 168 | count 2
|
||||
; RUN: llvm-as < %s | llc | grep 160 | count 3
|
||||
; RUN: llvm-as < %s | llc | grep 328 | count 1
|
||||
|
||||
target datalayout = "E-p:64:64:64-i1:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:128:128"
|
||||
target triple = "s390x-unknown-linux-gnu"
|
||||
|
||||
define i64 @foo(i64 %b, i64 %c, i64 %d, i64 %e, i64 %f, i64 %g) nounwind {
|
||||
entry:
|
||||
%a = alloca i64, align 8 ; <i64*> [#uses=3]
|
||||
store i64 %g, i64* %a
|
||||
call void @bar(i64* %a) nounwind
|
||||
%tmp1 = load i64* %a ; <i64> [#uses=1]
|
||||
ret i64 %tmp1
|
||||
}
|
||||
|
||||
declare void @bar(i64*)
|
12
test/CodeGen/SystemZ/06-SimpleCall.ll
Normal file
12
test/CodeGen/SystemZ/06-SimpleCall.ll
Normal file
@ -0,0 +1,12 @@
|
||||
; RUN: llvm-as < %s | llc
|
||||
|
||||
target datalayout = "E-p:64:64:64-i1:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:128:128"
|
||||
target triple = "s390x-unknown-linux-gnu"
|
||||
|
||||
define void @foo() nounwind {
|
||||
entry:
|
||||
tail call void @bar() nounwind
|
||||
ret void
|
||||
}
|
||||
|
||||
declare void @bar()
|
Loading…
x
Reference in New Issue
Block a user