forked from OSchip/llvm-project
Revert r202396, r202397.
These are causing test failures, revert for now. llvm-svn: 202398
This commit is contained in:
parent
e82bf0988e
commit
527aa5052d
|
@ -14,11 +14,7 @@
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
def RetCC_XCore : CallingConv<[
|
def RetCC_XCore : CallingConv<[
|
||||||
// i32 are returned in registers R0, R1, R2, R3
|
// i32 are returned in registers R0, R1, R2, R3
|
||||||
CCIfType<[i32], CCAssignToReg<[R0, R1, R2, R3]>>,
|
CCIfType<[i32], CCAssignToReg<[R0, R1, R2, R3]>>
|
||||||
|
|
||||||
// Integer values get stored in stack slots that are 4 bytes in
|
|
||||||
// size and 4-byte aligned.
|
|
||||||
CCIfType<[i32], CCAssignToStack<4, 4>>
|
|
||||||
]>;
|
]>;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
|
@ -50,7 +50,6 @@ getTargetNodeName(unsigned Opcode) const
|
||||||
case XCoreISD::PCRelativeWrapper : return "XCoreISD::PCRelativeWrapper";
|
case XCoreISD::PCRelativeWrapper : return "XCoreISD::PCRelativeWrapper";
|
||||||
case XCoreISD::DPRelativeWrapper : return "XCoreISD::DPRelativeWrapper";
|
case XCoreISD::DPRelativeWrapper : return "XCoreISD::DPRelativeWrapper";
|
||||||
case XCoreISD::CPRelativeWrapper : return "XCoreISD::CPRelativeWrapper";
|
case XCoreISD::CPRelativeWrapper : return "XCoreISD::CPRelativeWrapper";
|
||||||
case XCoreISD::LDWSP : return "XCoreISD::LDWSP";
|
|
||||||
case XCoreISD::STWSP : return "XCoreISD::STWSP";
|
case XCoreISD::STWSP : return "XCoreISD::STWSP";
|
||||||
case XCoreISD::RETSP : return "XCoreISD::RETSP";
|
case XCoreISD::RETSP : return "XCoreISD::RETSP";
|
||||||
case XCoreISD::LADD : return "XCoreISD::LADD";
|
case XCoreISD::LADD : return "XCoreISD::LADD";
|
||||||
|
@ -1079,52 +1078,6 @@ XCoreTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// LowerCallResult - Lower the result values of a call into the
|
|
||||||
/// appropriate copies out of appropriate physical registers / memory locations.
|
|
||||||
static SDValue
|
|
||||||
LowerCallResult(SDValue Chain, SDValue InFlag,
|
|
||||||
const SmallVectorImpl<CCValAssign> &RVLocs,
|
|
||||||
SDLoc dl, SelectionDAG &DAG,
|
|
||||||
SmallVectorImpl<SDValue> &InVals) {
|
|
||||||
SmallVector<std::pair<int, unsigned>, 4> ResultMemLocs;
|
|
||||||
// Copy results out of physical registers.
|
|
||||||
for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
|
|
||||||
const CCValAssign &VA = RVLocs[i];
|
|
||||||
if (VA.isRegLoc()) {
|
|
||||||
Chain = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), VA.getValVT(),
|
|
||||||
InFlag).getValue(1);
|
|
||||||
InFlag = Chain.getValue(2);
|
|
||||||
InVals.push_back(Chain.getValue(0));
|
|
||||||
} else {
|
|
||||||
assert(VA.isMemLoc());
|
|
||||||
ResultMemLocs.push_back(std::make_pair(VA.getLocMemOffset(),
|
|
||||||
InVals.size()));
|
|
||||||
// Reserve space for this result.
|
|
||||||
InVals.push_back(SDValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy results out of memory.
|
|
||||||
SmallVector<SDValue, 4> MemOpChains;
|
|
||||||
for (unsigned i = 0, e = ResultMemLocs.size(); i != e; ++i) {
|
|
||||||
int offset = ResultMemLocs[i].first;
|
|
||||||
unsigned index = ResultMemLocs[i].second;
|
|
||||||
SDVTList VTs = DAG.getVTList(MVT::i32, MVT::Other);
|
|
||||||
SDValue Ops[] = { Chain, DAG.getConstant(offset / 4, MVT::i32) };
|
|
||||||
SDValue load = DAG.getNode(XCoreISD::LDWSP, dl, VTs, Ops, 2);
|
|
||||||
InVals[index] = load;
|
|
||||||
MemOpChains.push_back(load.getValue(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transform all loads nodes into one single node because
|
|
||||||
// all load nodes are independent of each other.
|
|
||||||
if (!MemOpChains.empty())
|
|
||||||
Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
|
|
||||||
&MemOpChains[0], MemOpChains.size());
|
|
||||||
|
|
||||||
return Chain;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// LowerCCCCallTo - functions arguments are copied from virtual
|
/// LowerCCCCallTo - functions arguments are copied from virtual
|
||||||
/// regs to (physical regs)/(stack frame), CALLSEQ_START and
|
/// regs to (physical regs)/(stack frame), CALLSEQ_START and
|
||||||
/// CALLSEQ_END are emitted.
|
/// CALLSEQ_END are emitted.
|
||||||
|
@ -1150,15 +1103,8 @@ XCoreTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee,
|
||||||
|
|
||||||
CCInfo.AnalyzeCallOperands(Outs, CC_XCore);
|
CCInfo.AnalyzeCallOperands(Outs, CC_XCore);
|
||||||
|
|
||||||
SmallVector<CCValAssign, 16> RVLocs;
|
|
||||||
// Analyze return values to determine the number of bytes of stack required.
|
|
||||||
CCState RetCCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
|
|
||||||
getTargetMachine(), RVLocs, *DAG.getContext());
|
|
||||||
RetCCInfo.AllocateStack(CCInfo.getNextStackOffset(), 4);
|
|
||||||
RetCCInfo.AnalyzeCallResult(Ins, RetCC_XCore);
|
|
||||||
|
|
||||||
// Get a count of how many bytes are to be pushed on the stack.
|
// Get a count of how many bytes are to be pushed on the stack.
|
||||||
unsigned NumBytes = RetCCInfo.getNextStackOffset();
|
unsigned NumBytes = CCInfo.getNextStackOffset();
|
||||||
|
|
||||||
Chain = DAG.getCALLSEQ_START(Chain,DAG.getConstant(NumBytes,
|
Chain = DAG.getCALLSEQ_START(Chain,DAG.getConstant(NumBytes,
|
||||||
getPointerTy(), true), dl);
|
getPointerTy(), true), dl);
|
||||||
|
@ -1256,7 +1202,35 @@ XCoreTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee,
|
||||||
|
|
||||||
// Handle result values, copying them out of physregs into vregs that we
|
// Handle result values, copying them out of physregs into vregs that we
|
||||||
// return.
|
// return.
|
||||||
return LowerCallResult(Chain, InFlag, RVLocs, dl, DAG, InVals);
|
return LowerCallResult(Chain, InFlag, CallConv, isVarArg,
|
||||||
|
Ins, dl, DAG, InVals);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// LowerCallResult - Lower the result values of a call into the
|
||||||
|
/// appropriate copies out of appropriate physical registers.
|
||||||
|
SDValue
|
||||||
|
XCoreTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag,
|
||||||
|
CallingConv::ID CallConv, bool isVarArg,
|
||||||
|
const SmallVectorImpl<ISD::InputArg> &Ins,
|
||||||
|
SDLoc dl, SelectionDAG &DAG,
|
||||||
|
SmallVectorImpl<SDValue> &InVals) const {
|
||||||
|
|
||||||
|
// Assign locations to each value returned by this call.
|
||||||
|
SmallVector<CCValAssign, 16> RVLocs;
|
||||||
|
CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(),
|
||||||
|
getTargetMachine(), RVLocs, *DAG.getContext());
|
||||||
|
|
||||||
|
CCInfo.AnalyzeCallResult(Ins, RetCC_XCore);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
InVals.push_back(Chain.getValue(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Chain;
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -1304,7 +1278,6 @@ XCoreTargetLowering::LowerCCCArguments(SDValue Chain,
|
||||||
MachineFunction &MF = DAG.getMachineFunction();
|
MachineFunction &MF = DAG.getMachineFunction();
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
MachineRegisterInfo &RegInfo = MF.getRegInfo();
|
MachineRegisterInfo &RegInfo = MF.getRegInfo();
|
||||||
XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
|
|
||||||
|
|
||||||
// Assign locations to all of the incoming arguments.
|
// Assign locations to all of the incoming arguments.
|
||||||
SmallVector<CCValAssign, 16> ArgLocs;
|
SmallVector<CCValAssign, 16> ArgLocs;
|
||||||
|
@ -1317,9 +1290,6 @@ XCoreTargetLowering::LowerCCCArguments(SDValue Chain,
|
||||||
|
|
||||||
unsigned LRSaveSize = StackSlotSize;
|
unsigned LRSaveSize = StackSlotSize;
|
||||||
|
|
||||||
if (!isVarArg)
|
|
||||||
XFI->setReturnStackOffset(CCInfo.getNextStackOffset() + LRSaveSize);
|
|
||||||
|
|
||||||
// All getCopyFromReg ops must precede any getMemcpys to prevent the
|
// All getCopyFromReg ops must precede any getMemcpys to prevent the
|
||||||
// scheduler clobbering a register before it has been copied.
|
// scheduler clobbering a register before it has been copied.
|
||||||
// The stages are:
|
// The stages are:
|
||||||
|
@ -1470,11 +1440,7 @@ CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
|
||||||
LLVMContext &Context) const {
|
LLVMContext &Context) const {
|
||||||
SmallVector<CCValAssign, 16> RVLocs;
|
SmallVector<CCValAssign, 16> RVLocs;
|
||||||
CCState CCInfo(CallConv, isVarArg, MF, getTargetMachine(), RVLocs, Context);
|
CCState CCInfo(CallConv, isVarArg, MF, getTargetMachine(), RVLocs, Context);
|
||||||
if (!CCInfo.CheckReturn(Outs, RetCC_XCore))
|
return CCInfo.CheckReturn(Outs, RetCC_XCore);
|
||||||
return false;
|
|
||||||
if (CCInfo.getNextStackOffset() != 0 && isVarArg)
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SDValue
|
SDValue
|
||||||
|
@ -1484,10 +1450,6 @@ XCoreTargetLowering::LowerReturn(SDValue Chain,
|
||||||
const SmallVectorImpl<SDValue> &OutVals,
|
const SmallVectorImpl<SDValue> &OutVals,
|
||||||
SDLoc dl, SelectionDAG &DAG) const {
|
SDLoc dl, SelectionDAG &DAG) const {
|
||||||
|
|
||||||
XCoreFunctionInfo *XFI =
|
|
||||||
DAG.getMachineFunction().getInfo<XCoreFunctionInfo>();
|
|
||||||
MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();
|
|
||||||
|
|
||||||
// CCValAssign - represent the assignment of
|
// CCValAssign - represent the assignment of
|
||||||
// the return value to a location
|
// the return value to a location
|
||||||
SmallVector<CCValAssign, 16> RVLocs;
|
SmallVector<CCValAssign, 16> RVLocs;
|
||||||
|
@ -1497,9 +1459,6 @@ XCoreTargetLowering::LowerReturn(SDValue Chain,
|
||||||
getTargetMachine(), RVLocs, *DAG.getContext());
|
getTargetMachine(), RVLocs, *DAG.getContext());
|
||||||
|
|
||||||
// Analyze return values.
|
// Analyze return values.
|
||||||
if (!isVarArg)
|
|
||||||
CCInfo.AllocateStack(XFI->getReturnStackOffset(), 4);
|
|
||||||
|
|
||||||
CCInfo.AnalyzeReturn(Outs, RetCC_XCore);
|
CCInfo.AnalyzeReturn(Outs, RetCC_XCore);
|
||||||
|
|
||||||
SDValue Flag;
|
SDValue Flag;
|
||||||
|
@ -1508,43 +1467,13 @@ XCoreTargetLowering::LowerReturn(SDValue Chain,
|
||||||
// Return on XCore is always a "retsp 0"
|
// Return on XCore is always a "retsp 0"
|
||||||
RetOps.push_back(DAG.getConstant(0, MVT::i32));
|
RetOps.push_back(DAG.getConstant(0, MVT::i32));
|
||||||
|
|
||||||
SmallVector<SDValue, 4> MemOpChains;
|
// Copy the result values into the output registers.
|
||||||
// Handle return values that must be copied to memory.
|
for (unsigned i = 0; i != RVLocs.size(); ++i) {
|
||||||
for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
|
|
||||||
CCValAssign &VA = RVLocs[i];
|
CCValAssign &VA = RVLocs[i];
|
||||||
if (VA.isRegLoc())
|
assert(VA.isRegLoc() && "Can only return in registers!");
|
||||||
continue;
|
|
||||||
assert(VA.isMemLoc());
|
|
||||||
if (isVarArg) {
|
|
||||||
report_fatal_error("Can't return value from vararg function in memory");
|
|
||||||
}
|
|
||||||
|
|
||||||
int Offset = VA.getLocMemOffset();
|
Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(),
|
||||||
unsigned ObjSize = VA.getLocVT().getSizeInBits() / 8;
|
OutVals[i], Flag);
|
||||||
// Create the frame index object for the memory location.
|
|
||||||
int FI = MFI->CreateFixedObject(ObjSize, Offset, false);
|
|
||||||
|
|
||||||
// Create a SelectionDAG node corresponding to a store
|
|
||||||
// to this memory location.
|
|
||||||
SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
|
|
||||||
MemOpChains.push_back(DAG.getStore(Chain, dl, OutVals[i], FIN,
|
|
||||||
MachinePointerInfo::getFixedStack(FI), false, false,
|
|
||||||
0));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transform all store nodes into one single node because
|
|
||||||
// all stores are independent of each other.
|
|
||||||
if (!MemOpChains.empty())
|
|
||||||
Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
|
|
||||||
&MemOpChains[0], MemOpChains.size());
|
|
||||||
|
|
||||||
// Now handle return values copied to registers.
|
|
||||||
for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
|
|
||||||
CCValAssign &VA = RVLocs[i];
|
|
||||||
if (!VA.isRegLoc())
|
|
||||||
continue;
|
|
||||||
// Copy the result values into the output registers.
|
|
||||||
Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Flag);
|
|
||||||
|
|
||||||
// guarantee that all emitted copies are
|
// guarantee that all emitted copies are
|
||||||
// stuck together, avoiding something bad
|
// stuck together, avoiding something bad
|
||||||
|
|
|
@ -42,9 +42,6 @@ namespace llvm {
|
||||||
// cp relative address
|
// cp relative address
|
||||||
CPRelativeWrapper,
|
CPRelativeWrapper,
|
||||||
|
|
||||||
// Load word from stack
|
|
||||||
LDWSP,
|
|
||||||
|
|
||||||
// Store word to stack
|
// Store word to stack
|
||||||
STWSP,
|
STWSP,
|
||||||
|
|
||||||
|
@ -142,6 +139,11 @@ namespace llvm {
|
||||||
const SmallVectorImpl<ISD::InputArg> &Ins,
|
const SmallVectorImpl<ISD::InputArg> &Ins,
|
||||||
SDLoc dl, SelectionDAG &DAG,
|
SDLoc dl, SelectionDAG &DAG,
|
||||||
SmallVectorImpl<SDValue> &InVals) const;
|
SmallVectorImpl<SDValue> &InVals) const;
|
||||||
|
SDValue LowerCallResult(SDValue Chain, SDValue InFlag,
|
||||||
|
CallingConv::ID CallConv, bool isVarArg,
|
||||||
|
const SmallVectorImpl<ISD::InputArg> &Ins,
|
||||||
|
SDLoc dl, SelectionDAG &DAG,
|
||||||
|
SmallVectorImpl<SDValue> &InVals) const;
|
||||||
SDValue getReturnAddressFrameIndex(SelectionDAG &DAG) const;
|
SDValue getReturnAddressFrameIndex(SelectionDAG &DAG) const;
|
||||||
SDValue getGlobalAddressWrapper(SDValue GA, const GlobalValue *GV,
|
SDValue getGlobalAddressWrapper(SDValue GA, const GlobalValue *GV,
|
||||||
SelectionDAG &DAG) const;
|
SelectionDAG &DAG) const;
|
||||||
|
|
|
@ -68,10 +68,6 @@ def SDT_XCoreStwsp : SDTypeProfile<0, 2, [SDTCisInt<1>]>;
|
||||||
def XCoreStwsp : SDNode<"XCoreISD::STWSP", SDT_XCoreStwsp,
|
def XCoreStwsp : SDNode<"XCoreISD::STWSP", SDT_XCoreStwsp,
|
||||||
[SDNPHasChain, SDNPMayStore]>;
|
[SDNPHasChain, SDNPMayStore]>;
|
||||||
|
|
||||||
def SDT_XCoreLdwsp : SDTypeProfile<1, 1, [SDTCisInt<1>]>;
|
|
||||||
def XCoreLdwsp : SDNode<"XCoreISD::LDWSP", SDT_XCoreLdwsp,
|
|
||||||
[SDNPHasChain, SDNPMayLoad]>;
|
|
||||||
|
|
||||||
// These are target-independent nodes, but have target-specific formats.
|
// These are target-independent nodes, but have target-specific formats.
|
||||||
def SDT_XCoreCallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i32> ]>;
|
def SDT_XCoreCallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i32> ]>;
|
||||||
def SDT_XCoreCallSeqEnd : SDCallSeqEnd<[ SDTCisVT<0, i32>,
|
def SDT_XCoreCallSeqEnd : SDCallSeqEnd<[ SDTCisVT<0, i32>,
|
||||||
|
@ -585,12 +581,10 @@ def STWSP_lru6 : _FLRU6<0b010101, (outs), (ins RRegs:$a, i32imm:$b),
|
||||||
|
|
||||||
let mayLoad=1 in {
|
let mayLoad=1 in {
|
||||||
def LDWSP_ru6 : _FRU6<0b010111, (outs RRegs:$a), (ins i32imm:$b),
|
def LDWSP_ru6 : _FRU6<0b010111, (outs RRegs:$a), (ins i32imm:$b),
|
||||||
"ldw $a, sp[$b]",
|
"ldw $a, sp[$b]", []>;
|
||||||
[(set RRegs:$a, (XCoreLdwsp immU6:$b))]>;
|
|
||||||
|
|
||||||
def LDWSP_lru6 : _FLRU6<0b010111, (outs RRegs:$a), (ins i32imm:$b),
|
def LDWSP_lru6 : _FLRU6<0b010111, (outs RRegs:$a), (ins i32imm:$b),
|
||||||
"ldw $a, sp[$b]",
|
"ldw $a, sp[$b]", []>;
|
||||||
[(set RRegs:$a, (XCoreLdwsp immU16:$b))]>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let neverHasSideEffects = 1 in {
|
let neverHasSideEffects = 1 in {
|
||||||
|
|
|
@ -33,8 +33,6 @@ class XCoreFunctionInfo : public MachineFunctionInfo {
|
||||||
int FPSpillSlot;
|
int FPSpillSlot;
|
||||||
bool EHSpillSlotSet;
|
bool EHSpillSlotSet;
|
||||||
int EHSpillSlot[2];
|
int EHSpillSlot[2];
|
||||||
unsigned ReturnStackOffset;
|
|
||||||
bool ReturnStackOffsetSet;
|
|
||||||
int VarArgsFrameIndex;
|
int VarArgsFrameIndex;
|
||||||
mutable int CachedEStackSize;
|
mutable int CachedEStackSize;
|
||||||
std::vector<std::pair<MCSymbol*, CalleeSavedInfo> > SpillLabels;
|
std::vector<std::pair<MCSymbol*, CalleeSavedInfo> > SpillLabels;
|
||||||
|
@ -44,7 +42,6 @@ public:
|
||||||
LRSpillSlotSet(false),
|
LRSpillSlotSet(false),
|
||||||
FPSpillSlotSet(false),
|
FPSpillSlotSet(false),
|
||||||
EHSpillSlotSet(false),
|
EHSpillSlotSet(false),
|
||||||
ReturnStackOffsetSet(false),
|
|
||||||
VarArgsFrameIndex(0),
|
VarArgsFrameIndex(0),
|
||||||
CachedEStackSize(-1) {}
|
CachedEStackSize(-1) {}
|
||||||
|
|
||||||
|
@ -81,17 +78,6 @@ public:
|
||||||
return EHSpillSlot;
|
return EHSpillSlot;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setReturnStackOffset(unsigned value) {
|
|
||||||
assert(!ReturnStackOffsetSet && "Return stack offset set twice");
|
|
||||||
ReturnStackOffset = value;
|
|
||||||
ReturnStackOffsetSet = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned getReturnStackOffset() const {
|
|
||||||
assert(ReturnStackOffsetSet && "Return stack offset not set");
|
|
||||||
return ReturnStackOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isLargeFrame(const MachineFunction &MF) const;
|
bool isLargeFrame(const MachineFunction &MF) const;
|
||||||
|
|
||||||
std::vector<std::pair<MCSymbol*, CalleeSavedInfo> > &getSpillLabels() {
|
std::vector<std::pair<MCSymbol*, CalleeSavedInfo> > &getSpillLabels() {
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
%0 = type { i32, i32, i32, i32 }
|
%0 = type { i32, i32, i32, i32 }
|
||||||
%1 = type { i32, i32, i32, i32, i32 }
|
%1 = type { i32, i32, i32, i32, i32 }
|
||||||
|
|
||||||
; Structs of 4 words are returned in registers
|
; Structs of 4 words can be returned in registers
|
||||||
define internal %0 @ReturnBigStruct() nounwind readnone {
|
define internal fastcc %0 @ReturnBigStruct() nounwind readnone {
|
||||||
entry:
|
entry:
|
||||||
%0 = insertvalue %0 zeroinitializer, i32 12, 0
|
%0 = insertvalue %0 zeroinitializer, i32 12, 0
|
||||||
%1 = insertvalue %0 %0, i32 24, 1
|
%1 = insertvalue %0 %0, i32 24, 1
|
||||||
|
@ -19,39 +19,8 @@ entry:
|
||||||
; CHECK: ldc r3, 24601
|
; CHECK: ldc r3, 24601
|
||||||
; CHECK: retsp 0
|
; CHECK: retsp 0
|
||||||
|
|
||||||
; Structs of more than 4 words are partially returned in memory so long as the
|
; Structs bigger than 4 words are returned via a hidden hidden sret-parameter
|
||||||
; function is not variadic.
|
define internal fastcc %1 @ReturnBigStruct2() nounwind readnone {
|
||||||
define { i32, i32, i32, i32, i32} @f(i32, i32, i32, i32, i32) nounwind readnone {
|
|
||||||
; CHECK-LABEL: f:
|
|
||||||
; CHECK: ldc [[REGISTER:r[0-9]+]], 5
|
|
||||||
; CHECK-NEXT: stw [[REGISTER]], sp[2]
|
|
||||||
; CHECK-NEXT: retsp 0
|
|
||||||
body:
|
|
||||||
ret { i32, i32, i32, i32, i32} { i32 undef, i32 undef, i32 undef, i32 undef, i32 5}
|
|
||||||
}
|
|
||||||
|
|
||||||
@x = external global i32
|
|
||||||
@y = external global i32
|
|
||||||
|
|
||||||
; Check we call a function returning more than 4 words correctly.
|
|
||||||
define i32 @g() nounwind {
|
|
||||||
; CHECK-LABEL: g:
|
|
||||||
; CHECK: entsp 3
|
|
||||||
; CHECK: ldc [[REGISTER:r[0-9]+]], 0
|
|
||||||
; CHECK: stw [[REGISTER]], sp[1]
|
|
||||||
; CHECK: bl f
|
|
||||||
; CHECK-NEXT: ldw r0, sp[2]
|
|
||||||
; CHECK-NEXT: retsp 3
|
|
||||||
;
|
|
||||||
body:
|
|
||||||
%0 = call { i32, i32, i32, i32, i32 } @f(i32 0, i32 0, i32 0, i32 0, i32 0)
|
|
||||||
%1 = extractvalue { i32, i32, i32, i32, i32 } %0, 4
|
|
||||||
ret i32 %1
|
|
||||||
}
|
|
||||||
|
|
||||||
; Variadic functions return structs bigger than 4 words via a hidden
|
|
||||||
; sret-parameter
|
|
||||||
define internal %1 @ReturnBigStruct2(i32 %dummy, ...) nounwind readnone {
|
|
||||||
entry:
|
entry:
|
||||||
%0 = insertvalue %1 zeroinitializer, i32 12, 0
|
%0 = insertvalue %1 zeroinitializer, i32 12, 0
|
||||||
%1 = insertvalue %1 %0, i32 24, 1
|
%1 = insertvalue %1 %0, i32 24, 1
|
||||||
|
|
Loading…
Reference in New Issue