mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-11 07:18:44 +00:00
Implement the full V8 ABI for incoming arguments.
llvm-svn: 24825
This commit is contained in:
parent
21ae63ceb9
commit
b82f4641c4
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include "SparcV8.h"
|
#include "SparcV8.h"
|
||||||
#include "SparcV8TargetMachine.h"
|
#include "SparcV8TargetMachine.h"
|
||||||
|
#include "llvm/DerivedTypes.h"
|
||||||
#include "llvm/Function.h"
|
#include "llvm/Function.h"
|
||||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||||
#include "llvm/CodeGen/MachineFunction.h"
|
#include "llvm/CodeGen/MachineFunction.h"
|
||||||
@ -129,56 +130,170 @@ SparcV8TargetLowering::SparcV8TargetLowering(TargetMachine &TM)
|
|||||||
computeRegisterProperties();
|
computeRegisterProperties();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// LowerArguments - V8 uses a very simple ABI, where all values are passed in
|
||||||
|
/// either one or two GPRs, including FP values. TODO: we should pass FP values
|
||||||
|
/// in FP registers for fastcc functions.
|
||||||
std::vector<SDOperand>
|
std::vector<SDOperand>
|
||||||
SparcV8TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
|
SparcV8TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
|
||||||
MachineFunction &MF = DAG.getMachineFunction();
|
MachineFunction &MF = DAG.getMachineFunction();
|
||||||
SSARegMap *RegMap = MF.getSSARegMap();
|
SSARegMap *RegMap = MF.getSSARegMap();
|
||||||
std::vector<SDOperand> ArgValues;
|
std::vector<SDOperand> ArgValues;
|
||||||
|
|
||||||
static const unsigned GPR[] = {
|
static const unsigned ArgRegs[] = {
|
||||||
V8::I0, V8::I1, V8::I2, V8::I3, V8::I4, V8::I5
|
V8::I0, V8::I1, V8::I2, V8::I3, V8::I4, V8::I5
|
||||||
};
|
};
|
||||||
unsigned ArgNo = 0;
|
|
||||||
|
const unsigned *CurArgReg = ArgRegs, *ArgRegEnd = ArgRegs+6;
|
||||||
|
unsigned ArgOffset = 68;
|
||||||
|
|
||||||
|
SDOperand Root = DAG.getRoot();
|
||||||
|
std::vector<SDOperand> OutChains;
|
||||||
|
|
||||||
for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) {
|
for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) {
|
||||||
MVT::ValueType ObjectVT = getValueType(I->getType());
|
MVT::ValueType ObjectVT = getValueType(I->getType());
|
||||||
assert(ArgNo < 6 && "Only args in regs for now");
|
|
||||||
|
|
||||||
switch (ObjectVT) {
|
switch (ObjectVT) {
|
||||||
default: assert(0 && "Unhandled argument type!");
|
default: assert(0 && "Unhandled argument type!");
|
||||||
// TODO: MVT::i64 & FP
|
// TODO: FP
|
||||||
case MVT::i1:
|
case MVT::i1:
|
||||||
case MVT::i8:
|
case MVT::i8:
|
||||||
case MVT::i16:
|
case MVT::i16:
|
||||||
case MVT::i32: {
|
case MVT::i32:
|
||||||
unsigned VReg = RegMap->createVirtualRegister(&V8::IntRegsRegClass);
|
if (I->use_empty()) { // Argument is dead.
|
||||||
MF.addLiveIn(GPR[ArgNo++], VReg);
|
if (CurArgReg < ArgRegEnd) ++CurArgReg;
|
||||||
SDOperand Arg = DAG.getCopyFromReg(DAG.getRoot(), VReg, MVT::i32);
|
ArgValues.push_back(DAG.getNode(ISD::UNDEF, ObjectVT));
|
||||||
DAG.setRoot(Arg.getValue(1));
|
} else if (CurArgReg < ArgRegEnd) { // Lives in an incoming GPR
|
||||||
if (ObjectVT != MVT::i32) {
|
unsigned VReg = RegMap->createVirtualRegister(&V8::IntRegsRegClass);
|
||||||
unsigned AssertOp = I->getType()->isSigned() ? ISD::AssertSext
|
MF.addLiveIn(*CurArgReg++, VReg);
|
||||||
: ISD::AssertZext;
|
SDOperand Arg = DAG.getCopyFromReg(Root, VReg, MVT::i32);
|
||||||
Arg = DAG.getNode(AssertOp, MVT::i32, Arg,
|
if (ObjectVT != MVT::i32) {
|
||||||
DAG.getValueType(ObjectVT));
|
unsigned AssertOp = I->getType()->isSigned() ? ISD::AssertSext
|
||||||
Arg = DAG.getNode(ISD::TRUNCATE, ObjectVT, Arg);
|
: ISD::AssertZext;
|
||||||
|
Arg = DAG.getNode(AssertOp, MVT::i32, Arg,
|
||||||
|
DAG.getValueType(ObjectVT));
|
||||||
|
Arg = DAG.getNode(ISD::TRUNCATE, ObjectVT, Arg);
|
||||||
|
}
|
||||||
|
ArgValues.push_back(Arg);
|
||||||
|
} else {
|
||||||
|
int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset);
|
||||||
|
SDOperand FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
|
||||||
|
SDOperand Load;
|
||||||
|
if (ObjectVT == MVT::i32) {
|
||||||
|
Load = DAG.getLoad(MVT::i32, Root, FIPtr, DAG.getSrcValue(0));
|
||||||
|
} else {
|
||||||
|
unsigned LoadOp =
|
||||||
|
I->getType()->isSigned() ? ISD::SEXTLOAD : ISD::ZEXTLOAD;
|
||||||
|
|
||||||
|
Load = DAG.getExtLoad(LoadOp, MVT::i32, Root, FIPtr,
|
||||||
|
DAG.getSrcValue(0), ObjectVT);
|
||||||
|
}
|
||||||
|
ArgValues.push_back(Load);
|
||||||
}
|
}
|
||||||
ArgValues.push_back(Arg);
|
|
||||||
|
ArgOffset += 4;
|
||||||
break;
|
break;
|
||||||
}
|
case MVT::f32:
|
||||||
case MVT::i64: {
|
if (I->use_empty()) { // Argument is dead.
|
||||||
unsigned VRegHi = RegMap->createVirtualRegister(&V8::IntRegsRegClass);
|
if (CurArgReg < ArgRegEnd) ++CurArgReg;
|
||||||
MF.addLiveIn(GPR[ArgNo++], VRegHi);
|
ArgValues.push_back(DAG.getNode(ISD::UNDEF, ObjectVT));
|
||||||
unsigned VRegLo = RegMap->createVirtualRegister(&V8::IntRegsRegClass);
|
} else if (CurArgReg < ArgRegEnd) { // Lives in an incoming GPR
|
||||||
MF.addLiveIn(GPR[ArgNo++], VRegLo);
|
// FP value is passed in an integer register.
|
||||||
SDOperand ArgLo = DAG.getCopyFromReg(DAG.getRoot(), VRegLo, MVT::i32);
|
unsigned VReg = RegMap->createVirtualRegister(&V8::IntRegsRegClass);
|
||||||
SDOperand ArgHi = DAG.getCopyFromReg(ArgLo.getValue(1), VRegHi, MVT::i32);
|
MF.addLiveIn(*CurArgReg++, VReg);
|
||||||
DAG.setRoot(ArgHi.getValue(1));
|
SDOperand Arg = DAG.getCopyFromReg(Root, VReg, MVT::i32);
|
||||||
ArgValues.push_back(DAG.getNode(ISD::BUILD_PAIR, MVT::i64, ArgLo, ArgHi));
|
|
||||||
|
// We use the stack space that is already reserved for this reg.
|
||||||
|
int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset);
|
||||||
|
SDOperand FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
|
||||||
|
|
||||||
|
SDOperand SV = DAG.getSrcValue(0);
|
||||||
|
SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, Root,
|
||||||
|
Arg, FIPtr, SV);
|
||||||
|
ArgValues.push_back(DAG.getLoad(MVT::f32, Store, FIPtr, SV));
|
||||||
|
}
|
||||||
|
ArgOffset += 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MVT::i64:
|
||||||
|
case MVT::f64:
|
||||||
|
if (I->use_empty()) { // Argument is dead.
|
||||||
|
if (CurArgReg < ArgRegEnd) ++CurArgReg;
|
||||||
|
if (CurArgReg < ArgRegEnd) ++CurArgReg;
|
||||||
|
ArgValues.push_back(DAG.getNode(ISD::UNDEF, ObjectVT));
|
||||||
|
} else if (CurArgReg == ArgRegEnd && ObjectVT == MVT::f64 &&
|
||||||
|
((CurArgReg-ArgRegs) & 1) == 0) {
|
||||||
|
// If this is a double argument and the whole thing lives on the stack,
|
||||||
|
// and the argument is aligned, load the double straight from the stack.
|
||||||
|
// We can't do a load in cases like void foo([6ints], int,double),
|
||||||
|
// because the double wouldn't be aligned!
|
||||||
|
int FrameIdx = MF.getFrameInfo()->CreateFixedObject(8, ArgOffset);
|
||||||
|
SDOperand FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
|
||||||
|
ArgValues.push_back(DAG.getLoad(MVT::f64, Root, FIPtr,
|
||||||
|
DAG.getSrcValue(0)));
|
||||||
|
} else {
|
||||||
|
SDOperand HiVal;
|
||||||
|
if (CurArgReg < ArgRegEnd) { // Lives in an incoming GPR
|
||||||
|
unsigned VRegHi = RegMap->createVirtualRegister(&V8::IntRegsRegClass);
|
||||||
|
MF.addLiveIn(*CurArgReg++, VRegHi);
|
||||||
|
HiVal = DAG.getCopyFromReg(Root, VRegHi, MVT::i32);
|
||||||
|
} else {
|
||||||
|
int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset);
|
||||||
|
SDOperand FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
|
||||||
|
HiVal = DAG.getLoad(MVT::i32, Root, FIPtr, DAG.getSrcValue(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
SDOperand LoVal;
|
||||||
|
if (CurArgReg < ArgRegEnd) { // Lives in an incoming GPR
|
||||||
|
unsigned VRegLo = RegMap->createVirtualRegister(&V8::IntRegsRegClass);
|
||||||
|
MF.addLiveIn(*CurArgReg++, VRegLo);
|
||||||
|
LoVal = DAG.getCopyFromReg(Root, VRegLo, MVT::i32);
|
||||||
|
} else {
|
||||||
|
int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset+4);
|
||||||
|
SDOperand FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
|
||||||
|
LoVal = DAG.getLoad(MVT::i32, Root, FIPtr, DAG.getSrcValue(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compose the two halves together into an i64 unit.
|
||||||
|
SDOperand WholeValue =
|
||||||
|
DAG.getNode(ISD::BUILD_PAIR, MVT::i64, LoVal, HiVal);
|
||||||
|
|
||||||
|
if (ObjectVT == MVT::i64) {
|
||||||
|
// If we are emitting an i64, this is what we want.
|
||||||
|
ArgValues.push_back(WholeValue);
|
||||||
|
} else {
|
||||||
|
assert(ObjectVT == MVT::f64);
|
||||||
|
// Otherwise, emit a store to the stack and reload into FPR.
|
||||||
|
int FrameIdx = MF.getFrameInfo()->CreateStackObject(8, 8);
|
||||||
|
SDOperand FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
|
||||||
|
SDOperand SV = DAG.getSrcValue(0);
|
||||||
|
SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, Root,
|
||||||
|
WholeValue, FIPtr, SV);
|
||||||
|
ArgValues.push_back(DAG.getLoad(MVT::f64, Store, FIPtr, SV));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ArgOffset += 8;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(!F.isVarArg() && "Unimp");
|
// Store remaining ArgRegs to the stack if this is a varargs function.
|
||||||
|
if (F.getFunctionType()->isVarArg()) {
|
||||||
|
for (; CurArgReg != ArgRegEnd; ++CurArgReg) {
|
||||||
|
unsigned VReg = RegMap->createVirtualRegister(&V8::IntRegsRegClass);
|
||||||
|
MF.addLiveIn(*CurArgReg, VReg);
|
||||||
|
SDOperand Arg = DAG.getCopyFromReg(DAG.getRoot(), VReg, MVT::i32);
|
||||||
|
|
||||||
|
int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset);
|
||||||
|
SDOperand FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
|
||||||
|
|
||||||
|
OutChains.push_back(DAG.getNode(ISD::STORE, MVT::Other, DAG.getRoot(),
|
||||||
|
Arg, FIPtr, DAG.getSrcValue(0)));
|
||||||
|
ArgOffset += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!OutChains.empty())
|
||||||
|
DAG.setRoot(DAG.getNode(ISD::TokenFactor, MVT::Other, OutChains));
|
||||||
|
|
||||||
// Finally, inform the code generator which regs we return values in.
|
// Finally, inform the code generator which regs we return values in.
|
||||||
switch (getValueType(F.getReturnType())) {
|
switch (getValueType(F.getReturnType())) {
|
||||||
|
@ -367,7 +367,7 @@ void V8ISel::LoadArgumentsToVirtualRegs (Function *LF) {
|
|||||||
// FIXME: We could avoid storing any args onto the stack that don't
|
// FIXME: We could avoid storing any args onto the stack that don't
|
||||||
// need to be in memory, because they come before the ellipsis in the
|
// need to be in memory, because they come before the ellipsis in the
|
||||||
// parameter list (and thus could never be accessed through va_arg).
|
// parameter list (and thus could never be accessed through va_arg).
|
||||||
if (LF->getFunctionType ()->isVarArg ()) {
|
if (LF->getFunctionType()->isVarArg()) {
|
||||||
for (unsigned i = 0; i < 6; ++i) {
|
for (unsigned i = 0; i < 6; ++i) {
|
||||||
int FI = F->getFrameInfo()->CreateFixedObject(4, ArgOffset);
|
int FI = F->getFrameInfo()->CreateFixedObject(4, ArgOffset);
|
||||||
assert (IAR != IAREnd
|
assert (IAR != IAREnd
|
||||||
|
Loading…
x
Reference in New Issue
Block a user