mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-15 04:30:12 +00:00
remove Evan's "ugly hack" that sorta attempted to get
x86-64 return conventions correct, but was never enabled. We can now do the "right thing" with multiple return values. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@48635 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
24e0a546b4
commit
920c37afc5
@ -969,11 +969,6 @@ void FPS::handleSpecialFP(MachineBasicBlock::iterator &I) {
|
||||
std::swap(Stack[RegMap[RegOnTop]], Stack[StackTop-1]);
|
||||
break;
|
||||
}
|
||||
case X86::FpGET_ST0_ST1:
|
||||
assert(StackTop == 0 && "Stack should be empty after a call!");
|
||||
pushReg(getFPReg(MI->getOperand(0)));
|
||||
pushReg(getFPReg(MI->getOperand(1)));
|
||||
break;
|
||||
case X86::FpSET_ST0_32:
|
||||
case X86::FpSET_ST0_64:
|
||||
case X86::FpSET_ST0_80:
|
||||
|
@ -1197,26 +1197,6 @@ SDNode *X86DAGToDAGISel::Select(SDOperand N) {
|
||||
}
|
||||
break;
|
||||
|
||||
case X86ISD::FP_GET_ST0_ST1: {
|
||||
SDOperand Chain = N.getOperand(0);
|
||||
SDOperand InFlag = N.getOperand(1);
|
||||
AddToISelQueue(Chain);
|
||||
AddToISelQueue(InFlag);
|
||||
std::vector<MVT::ValueType> Tys;
|
||||
Tys.push_back(MVT::f80);
|
||||
Tys.push_back(MVT::f80);
|
||||
Tys.push_back(MVT::Other);
|
||||
Tys.push_back(MVT::Flag);
|
||||
SDOperand Ops[] = { Chain, InFlag };
|
||||
SDNode *ResNode = CurDAG->getTargetNode(X86::FpGET_ST0_ST1, Tys,
|
||||
Ops, 2);
|
||||
Chain = SDOperand(ResNode, 2);
|
||||
InFlag = SDOperand(ResNode, 3);
|
||||
ReplaceUses(SDOperand(N.Val, 2), Chain);
|
||||
ReplaceUses(SDOperand(N.Val, 3), InFlag);
|
||||
return ResNode;
|
||||
}
|
||||
|
||||
case ISD::ADD: {
|
||||
// Turn ADD X, c to MOV32ri X+c. This cannot be done with tblgen'd
|
||||
// code and is matched first so to prevent it from being turned into
|
||||
|
@ -941,44 +941,6 @@ LowerCallResult(SDOperand Chain, SDOperand InFlag, SDNode *TheCall,
|
||||
&ResultVals[0], ResultVals.size()).Val;
|
||||
}
|
||||
|
||||
/// LowerCallResultToTwo64BitRegs - Lower the result values of an x86-64
|
||||
/// ISD::CALL where the results are known to be in two 64-bit registers,
|
||||
/// e.g. XMM0 and XMM1. This simplify store the two values back to the
|
||||
/// fixed stack slot allocated for StructRet.
|
||||
SDNode *X86TargetLowering::
|
||||
LowerCallResultToTwo64BitRegs(SDOperand Chain, SDOperand InFlag,
|
||||
SDNode *TheCall, unsigned Reg1, unsigned Reg2,
|
||||
MVT::ValueType VT, SelectionDAG &DAG) {
|
||||
SDOperand RetVal1 = DAG.getCopyFromReg(Chain, Reg1, VT, InFlag);
|
||||
Chain = RetVal1.getValue(1);
|
||||
InFlag = RetVal1.getValue(2);
|
||||
SDOperand RetVal2 = DAG.getCopyFromReg(Chain, Reg2, VT, InFlag);
|
||||
Chain = RetVal2.getValue(1);
|
||||
InFlag = RetVal2.getValue(2);
|
||||
SDOperand FIN = TheCall->getOperand(5);
|
||||
Chain = DAG.getStore(Chain, RetVal1, FIN, NULL, 0);
|
||||
FIN = DAG.getNode(ISD::ADD, getPointerTy(), FIN, DAG.getIntPtrConstant(8));
|
||||
Chain = DAG.getStore(Chain, RetVal2, FIN, NULL, 0);
|
||||
return Chain.Val;
|
||||
}
|
||||
|
||||
/// LowerCallResultToTwoX87Regs - Lower the result values of an x86-64 ISD::CALL
|
||||
/// where the results are known to be in ST0 and ST1.
|
||||
SDNode *X86TargetLowering::
|
||||
LowerCallResultToTwoX87Regs(SDOperand Chain, SDOperand InFlag,
|
||||
SDNode *TheCall, SelectionDAG &DAG) {
|
||||
SmallVector<SDOperand, 8> ResultVals;
|
||||
const MVT::ValueType VTs[] = { MVT::f80, MVT::f80, MVT::Other, MVT::Flag };
|
||||
SDVTList Tys = DAG.getVTList(VTs, 4);
|
||||
SDOperand Ops[] = { Chain, InFlag };
|
||||
SDOperand RetVal = DAG.getNode(X86ISD::FP_GET_ST0_ST1, Tys, Ops, 2);
|
||||
Chain = RetVal.getValue(2);
|
||||
SDOperand FIN = TheCall->getOperand(5);
|
||||
Chain = DAG.getStore(Chain, RetVal.getValue(1), FIN, NULL, 0);
|
||||
FIN = DAG.getNode(ISD::ADD, getPointerTy(), FIN, DAG.getIntPtrConstant(16));
|
||||
Chain = DAG.getStore(Chain, RetVal, FIN, NULL, 0);
|
||||
return Chain.Val;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// C & StdCall & Fast Calling Convention implementation
|
||||
@ -1394,63 +1356,6 @@ X86TargetLowering::LowerMemOpCallTo(SDOperand Op, SelectionDAG &DAG,
|
||||
PseudoSourceValue::getStack(), LocMemOffset);
|
||||
}
|
||||
|
||||
/// ClassifyX86_64SRetCallReturn - Classify how to implement a x86-64
|
||||
/// struct return call to the specified function. X86-64 ABI specifies
|
||||
/// some SRet calls are actually returned in registers. Since current
|
||||
/// LLVM cannot represent multi-value calls, they are represent as
|
||||
/// calls where the results are passed in a hidden struct provided by
|
||||
/// the caller. This function examines the type of the struct to
|
||||
/// determine the correct way to implement the call.
|
||||
X86::X86_64SRet
|
||||
X86TargetLowering::ClassifyX86_64SRetCallReturn(const Function *Fn) {
|
||||
// FIXME: Disabled for now.
|
||||
return X86::InMemory;
|
||||
|
||||
const PointerType *PTy = cast<PointerType>(Fn->arg_begin()->getType());
|
||||
const Type *RTy = PTy->getElementType();
|
||||
unsigned Size = getTargetData()->getABITypeSize(RTy);
|
||||
if (Size != 16 && Size != 32)
|
||||
return X86::InMemory;
|
||||
|
||||
if (Size == 32) {
|
||||
const StructType *STy = dyn_cast<StructType>(RTy);
|
||||
if (!STy) return X86::InMemory;
|
||||
if (STy->getNumElements() == 2 &&
|
||||
STy->getElementType(0) == Type::X86_FP80Ty &&
|
||||
STy->getElementType(1) == Type::X86_FP80Ty)
|
||||
return X86::InX87;
|
||||
}
|
||||
|
||||
bool AllFP = true;
|
||||
for (Type::subtype_iterator I = RTy->subtype_begin(), E = RTy->subtype_end();
|
||||
I != E; ++I) {
|
||||
const Type *STy = I->get();
|
||||
if (!STy->isFPOrFPVector()) {
|
||||
AllFP = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (AllFP)
|
||||
return X86::InSSE;
|
||||
return X86::InGPR64;
|
||||
}
|
||||
|
||||
void X86TargetLowering::X86_64AnalyzeSRetCallOperands(SDNode *TheCall,
|
||||
CCAssignFn *Fn,
|
||||
CCState &CCInfo) {
|
||||
unsigned NumOps = (TheCall->getNumOperands() - 5) / 2;
|
||||
for (unsigned i = 1; i != NumOps; ++i) {
|
||||
MVT::ValueType ArgVT = TheCall->getOperand(5+2*i).getValueType();
|
||||
SDOperand FlagOp = TheCall->getOperand(5+2*i+1);
|
||||
unsigned ArgFlags =cast<ConstantSDNode>(FlagOp)->getValue();
|
||||
if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, CCInfo)) {
|
||||
cerr << "Call operand #" << i << " has unhandled type "
|
||||
<< MVT::getValueTypeString(ArgVT) << "\n";
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDOperand X86TargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG) {
|
||||
MachineFunction &MF = DAG.getMachineFunction();
|
||||
@ -1470,24 +1375,7 @@ SDOperand X86TargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG) {
|
||||
// Analyze operands of the call, assigning locations to each operand.
|
||||
SmallVector<CCValAssign, 16> ArgLocs;
|
||||
CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs);
|
||||
CCAssignFn *CCFn = CCAssignFnForNode(Op);
|
||||
|
||||
X86::X86_64SRet SRetMethod = X86::InMemory;
|
||||
if (Is64Bit && IsStructRet)
|
||||
// FIXME: We can't figure out type of the sret structure for indirect
|
||||
// calls. We need to copy more information from CallSite to the ISD::CALL
|
||||
// node.
|
||||
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
|
||||
SRetMethod =
|
||||
ClassifyX86_64SRetCallReturn(dyn_cast<Function>(G->getGlobal()));
|
||||
|
||||
// UGLY HACK! For x86-64, some 128-bit aggregates are returns in a pair of
|
||||
// registers. Unfortunately, llvm does not support i128 yet so we pretend it's
|
||||
// a sret call.
|
||||
if (SRetMethod != X86::InMemory)
|
||||
X86_64AnalyzeSRetCallOperands(Op.Val, CCFn, CCInfo);
|
||||
else
|
||||
CCInfo.AnalyzeCallOperands(Op.Val, CCFn);
|
||||
CCInfo.AnalyzeCallOperands(Op.Val, CCAssignFnForNode(Op));
|
||||
|
||||
// Get a count of how many bytes are to be pushed on the stack.
|
||||
unsigned NumBytes = CCInfo.getNextStackOffset();
|
||||
@ -1798,21 +1686,7 @@ SDOperand X86TargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG) {
|
||||
|
||||
// Handle result values, copying them out of physregs into vregs that we
|
||||
// return.
|
||||
switch (SRetMethod) {
|
||||
default:
|
||||
return SDOperand(LowerCallResult(Chain, InFlag, Op.Val, CC, DAG), Op.ResNo);
|
||||
case X86::InGPR64:
|
||||
return SDOperand(LowerCallResultToTwo64BitRegs(Chain, InFlag, Op.Val,
|
||||
X86::RAX, X86::RDX,
|
||||
MVT::i64, DAG), Op.ResNo);
|
||||
case X86::InSSE:
|
||||
return SDOperand(LowerCallResultToTwo64BitRegs(Chain, InFlag, Op.Val,
|
||||
X86::XMM0, X86::XMM1,
|
||||
MVT::f64, DAG), Op.ResNo);
|
||||
case X86::InX87:
|
||||
return SDOperand(LowerCallResultToTwoX87Regs(Chain, InFlag, Op.Val, DAG),
|
||||
Op.ResNo);
|
||||
}
|
||||
return SDOperand(LowerCallResult(Chain, InFlag, Op.Val, CC, DAG), Op.ResNo);
|
||||
}
|
||||
|
||||
|
||||
@ -5574,7 +5448,6 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
case X86ISD::FP_TO_INT64_IN_MEM: return "X86ISD::FP_TO_INT64_IN_MEM";
|
||||
case X86ISD::FLD: return "X86ISD::FLD";
|
||||
case X86ISD::FST: return "X86ISD::FST";
|
||||
case X86ISD::FP_GET_ST0_ST1: return "X86ISD::FP_GET_ST0_ST1";
|
||||
case X86ISD::CALL: return "X86ISD::CALL";
|
||||
case X86ISD::TAILCALL: return "X86ISD::TAILCALL";
|
||||
case X86ISD::RDTSC_DAG: return "X86ISD::RDTSC_DAG";
|
||||
|
@ -84,10 +84,6 @@ namespace llvm {
|
||||
/// as.
|
||||
FST,
|
||||
|
||||
/// FP_GET_ST0_ST1 - Same as FP_GET_ST0 except it copies two values
|
||||
/// ST(0) and ST(1).
|
||||
FP_GET_ST0_ST1,
|
||||
|
||||
/// CALL/TAILCALL - These operations represent an abstract X86 call
|
||||
/// instruction, which includes a bunch of information. In particular the
|
||||
/// operands of these node are:
|
||||
@ -472,21 +468,9 @@ namespace llvm {
|
||||
bool X86ScalarSSEf32;
|
||||
bool X86ScalarSSEf64;
|
||||
|
||||
X86::X86_64SRet ClassifyX86_64SRetCallReturn(const Function *Fn);
|
||||
|
||||
void X86_64AnalyzeSRetCallOperands(SDNode*, CCAssignFn*, CCState&);
|
||||
|
||||
SDNode *LowerCallResult(SDOperand Chain, SDOperand InFlag, SDNode*TheCall,
|
||||
unsigned CallingConv, SelectionDAG &DAG);
|
||||
|
||||
SDNode *LowerCallResultToTwo64BitRegs(SDOperand Chain, SDOperand InFlag,
|
||||
SDNode *TheCall, unsigned Reg1,
|
||||
unsigned Reg2, MVT::ValueType VT,
|
||||
SelectionDAG &DAG);
|
||||
|
||||
SDNode *LowerCallResultToTwoX87Regs(SDOperand Chain, SDOperand InFlag,
|
||||
SDNode *TheCall, SelectionDAG &DAG);
|
||||
|
||||
SDOperand LowerMemArgument(SDOperand Op, SelectionDAG &DAG,
|
||||
const CCValAssign &VA, MachineFrameInfo *MFI,
|
||||
unsigned CC, SDOperand Root, unsigned i);
|
||||
|
@ -145,10 +145,6 @@ def FpGET_ST1_32 : FpI_<(outs RFP32:$dst), (ins), SpecialFP, []>; // FPR = ST(1)
|
||||
def FpGET_ST1_64 : FpI_<(outs RFP64:$dst), (ins), SpecialFP, []>; // FPR = ST(1)
|
||||
def FpGET_ST1_80 : FpI_<(outs RFP80:$dst), (ins), SpecialFP, []>; // FPR = ST(1)
|
||||
|
||||
def FpGET_ST0_ST1 : FpI_<(outs RFP80:$dst1, RFP80:$dst2), (ins), SpecialFP,
|
||||
[]>; // FPR = ST(0), FPR = ST(1)
|
||||
|
||||
|
||||
let Defs = [ST0] in {
|
||||
def FpSET_ST0_32 : FpI_<(outs), (ins RFP32:$src), SpecialFP, []>; // ST(0) = FPR
|
||||
def FpSET_ST0_64 : FpI_<(outs), (ins RFP64:$src), SpecialFP, []>; // ST(0) = FPR
|
||||
|
Loading…
Reference in New Issue
Block a user