mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-14 16:33:28 +00:00
* Added lowering hook for external weak global address. It inserts a load
for Darwin. * Added lowering hook for ISD::RET. It inserts CopyToRegs for the return value (or store / fld / copy to ST(0) for floating point value). This eliminate the need to write C++ code to handle RET with variable number of operands. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@24888 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
8de324b59c
commit
b077b842b6
@ -173,22 +173,7 @@ bool X86DAGToDAGISel::MatchAddress(SDOperand N, X86ISelAddressMode &AM) {
|
||||
|
||||
case ISD::GlobalAddress:
|
||||
if (AM.GV == 0) {
|
||||
GlobalValue *GV = cast<GlobalAddressSDNode>(N)->getGlobal();
|
||||
// For Darwin, external and weak symbols are indirect, so we want to load
|
||||
// the value at address GV, not the value of GV itself. This means that
|
||||
// the GlobalAddress must be in the base or index register of the address,
|
||||
// not the GV offset field.
|
||||
if (Subtarget->getIndirectExternAndWeakGlobals() &&
|
||||
(GV->hasWeakLinkage() || GV->isExternal())) {
|
||||
AM.Base.Reg =
|
||||
CurDAG->getTargetNode(X86::MOV32rm, MVT::i32, MVT::Other,
|
||||
CurDAG->getRegister(0, MVT::i32),
|
||||
getI8Imm(1), CurDAG->getRegister(0, MVT::i32),
|
||||
CurDAG->getTargetGlobalAddress(GV, MVT::i32),
|
||||
CurDAG->getEntryNode());
|
||||
} else {
|
||||
AM.GV = GV;
|
||||
}
|
||||
AM.GV = cast<GlobalAddressSDNode>(N)->getGlobal();
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
@ -197,6 +197,68 @@ X86TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
|
||||
return LowerCCCCallTo(Chain, RetTy, isVarArg, isTailCall, Callee, Args, DAG);
|
||||
}
|
||||
|
||||
SDOperand X86TargetLowering::LowerReturnTo(SDOperand Chain, SDOperand Op,
|
||||
SelectionDAG &DAG) {
|
||||
if (!X86DAGIsel)
|
||||
return DAG.getNode(ISD::RET, MVT::Other, Chain, Op);
|
||||
|
||||
SDOperand Copy;
|
||||
MVT::ValueType OpVT = Op.getValueType();
|
||||
switch (OpVT) {
|
||||
default: assert(0 && "Unknown type to return!");
|
||||
case MVT::i32:
|
||||
Copy = DAG.getCopyToReg(Chain, X86::EAX, Op, SDOperand());
|
||||
break;
|
||||
case MVT::i64: {
|
||||
SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op,
|
||||
DAG.getConstant(1, MVT::i32));
|
||||
SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op,
|
||||
DAG.getConstant(0, MVT::i32));
|
||||
Copy = DAG.getCopyToReg(Chain, X86::EAX, Hi, SDOperand());
|
||||
Copy = DAG.getCopyToReg(Copy, X86::EDX, Lo, Copy.getValue(1));
|
||||
break;
|
||||
}
|
||||
case MVT::f32:
|
||||
assert(X86ScalarSSE && "MVT::f32 only legal with scalar sse fp");
|
||||
// Fallthrough intended
|
||||
case MVT::f64:
|
||||
if (!X86ScalarSSE) {
|
||||
std::vector<MVT::ValueType> Tys;
|
||||
Tys.push_back(MVT::Other);
|
||||
Tys.push_back(MVT::Flag);
|
||||
std::vector<SDOperand> Ops;
|
||||
Ops.push_back(Chain);
|
||||
Ops.push_back(Op);
|
||||
Copy = DAG.getNode(X86ISD::FP_SET_RESULT, Tys, Ops);
|
||||
} else {
|
||||
// Spill the value to memory and reload it into top of stack.
|
||||
unsigned Size = MVT::getSizeInBits(OpVT)/8;
|
||||
MachineFunction &MF = DAG.getMachineFunction();
|
||||
int SSFI = MF.getFrameInfo()->CreateStackObject(Size, Size);
|
||||
SDOperand StackSlot = DAG.getFrameIndex(SSFI, getPointerTy());
|
||||
Chain = DAG.getNode(ISD::STORE, MVT::Other, Chain, Op,
|
||||
StackSlot, DAG.getSrcValue(NULL));
|
||||
std::vector<MVT::ValueType> Tys;
|
||||
Tys.push_back(MVT::f64);
|
||||
Tys.push_back(MVT::Other);
|
||||
std::vector<SDOperand> Ops;
|
||||
Ops.push_back(Chain);
|
||||
Ops.push_back(StackSlot);
|
||||
Ops.push_back(DAG.getValueType(OpVT));
|
||||
Copy = DAG.getNode(X86ISD::FLD, Tys, Ops);
|
||||
Tys.clear();
|
||||
Tys.push_back(MVT::Other);
|
||||
Tys.push_back(MVT::Flag);
|
||||
Ops.clear();
|
||||
Ops.push_back(Copy.getValue(1));
|
||||
Ops.push_back(Copy);
|
||||
Copy = DAG.getNode(X86ISD::FP_SET_RESULT, Tys, Ops);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return DAG.getNode(X86ISD::RET_FLAG, MVT::Other, Copy, Copy.getValue(1));
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// C Calling Convention implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -968,6 +1030,20 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
||||
return DAG.getNode(X86ISD::BRCOND, Op.getValueType(),
|
||||
Op.getOperand(0), Op.getOperand(2), CC, Cond);
|
||||
}
|
||||
case ISD::GlobalAddress:
|
||||
GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
|
||||
// For Darwin, external and weak symbols are indirect, so we want to load
|
||||
// the value at address GV, not the value of GV itself. This means that
|
||||
// the GlobalAddress must be in the base or index register of the address,
|
||||
// not the GV offset field.
|
||||
if (getTargetMachine().
|
||||
getSubtarget<X86Subtarget>().getIndirectExternAndWeakGlobals() &&
|
||||
(GV->hasWeakLinkage() || GV->isExternal()))
|
||||
return DAG.getLoad(MVT::i32, DAG.getEntryNode(), Op,
|
||||
DAG.getSrcValue(NULL));
|
||||
else
|
||||
return Op;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -978,6 +1054,8 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
case X86ISD::FP_TO_INT16_IN_MEM: return "X86ISD::FP_TO_INT16_IN_MEM";
|
||||
case X86ISD::FP_TO_INT32_IN_MEM: return "X86ISD::FP_TO_INT32_IN_MEM";
|
||||
case X86ISD::FP_TO_INT64_IN_MEM: return "X86ISD::FP_TO_INT64_IN_MEM";
|
||||
case X86ISD::FLD: return "X86ISD::FLD";
|
||||
case X86ISD::FP_SET_RESULT: return "X86ISD::FP_SET_RESULT";
|
||||
case X86ISD::CALL: return "X86ISD::CALL";
|
||||
case X86ISD::TAILCALL: return "X86ISD::TAILCALL";
|
||||
case X86ISD::RDTSC_DAG: return "X86ISD::RDTSC_DAG";
|
||||
@ -985,5 +1063,6 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
case X86ISD::TEST: return "X86ISD::TEST";
|
||||
case X86ISD::CMOV: return "X86ISD::CMOV";
|
||||
case X86ISD::BRCOND: return "X86ISD::BRCOND";
|
||||
case X86ISD::RET_FLAG: return "X86ISD::RET_FLAG";
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,17 @@ namespace llvm {
|
||||
FP_TO_INT32_IN_MEM,
|
||||
FP_TO_INT64_IN_MEM,
|
||||
|
||||
/// FLD - This instruction implements an extending load to FP stack slots.
|
||||
/// This corresponds to the X86::FLD32m / X86::FLD64m. It takes a chain
|
||||
/// operand, ptr to load from, and a VALUETYPE node indicating the type
|
||||
/// to load.
|
||||
FLD,
|
||||
|
||||
/// FP_SET_RESULT - This corresponds to FpSETRESULT pseudo instrcuction
|
||||
/// which copies the source operand to ST(0). It takes a chain and writes
|
||||
/// a chain and a flag.
|
||||
FP_SET_RESULT,
|
||||
|
||||
/// CALL/TAILCALL - These operations represent an abstract X86 call
|
||||
/// instruction, which includes a bunch of information. In particular the
|
||||
/// operands of these node are:
|
||||
@ -75,6 +86,9 @@ namespace llvm {
|
||||
|
||||
/// X86 conditional branches.
|
||||
BRCOND,
|
||||
|
||||
// Return with a flag operand.
|
||||
RET_FLAG,
|
||||
};
|
||||
}
|
||||
|
||||
@ -113,6 +127,9 @@ namespace llvm {
|
||||
bool isTailCall, SDOperand Callee, ArgListTy &Args,
|
||||
SelectionDAG &DAG);
|
||||
|
||||
virtual SDOperand LowerReturnTo(SDOperand Chain, SDOperand Op,
|
||||
SelectionDAG &DAG);
|
||||
|
||||
virtual SDOperand LowerVAStart(SDOperand Chain, SDOperand VAListP,
|
||||
Value *VAListV, SelectionDAG &DAG);
|
||||
virtual std::pair<SDOperand,SDOperand>
|
||||
|
@ -28,11 +28,25 @@ def SDTX86BrCond : SDTypeProfile<0, 3,
|
||||
[SDTCisVT<0, OtherVT>,
|
||||
SDTCisVT<1, OtherVT>, SDTCisVT<2, FlagVT>]>;
|
||||
|
||||
def X86cmp : SDNode<"X86ISD::CMP" , SDTX86CmpTest, []>;
|
||||
def X86test : SDNode<"X86ISD::TEST", SDTX86CmpTest, []>;
|
||||
def SDTX86RetFlag : SDTypeProfile<0, 1, [SDTCisVT<0, FlagVT>]>;
|
||||
|
||||
def X86cmov : SDNode<"X86ISD::CMOV", SDTX86Cmov, []>;
|
||||
def X86Brcond : SDNode<"X86ISD::BRCOND", SDTX86BrCond, [SDNPHasChain]>;
|
||||
def SDTX86Fld : SDTypeProfile<1, 2, [SDTCisFP<0>,
|
||||
SDTCisPtrTy<1>, SDTCisVT<2, OtherVT>]>;
|
||||
|
||||
def SDTX86FpSet : SDTypeProfile<0, 1, [SDTCisFP<0>]>;
|
||||
|
||||
def X86cmp : SDNode<"X86ISD::CMP" , SDTX86CmpTest, []>;
|
||||
def X86test : SDNode<"X86ISD::TEST", SDTX86CmpTest, []>;
|
||||
|
||||
def X86cmov : SDNode<"X86ISD::CMOV", SDTX86Cmov, []>;
|
||||
def X86Brcond : SDNode<"X86ISD::BRCOND", SDTX86BrCond, [SDNPHasChain]>;
|
||||
|
||||
def X86retflag: SDNode<"X86ISD::RET_FLAG", SDTX86RetFlag, [SDNPHasChain]>;
|
||||
|
||||
def X86fld : SDNode<"X86ISD::FLD", SDTX86Fld, [SDNPHasChain]>;
|
||||
|
||||
def X86fpset : SDNode<"X86ISD::FP_SET_RESULT",
|
||||
SDTX86FpSet, [SDNPHasChain]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// X86 Operand Definitions.
|
||||
@ -274,6 +288,8 @@ let isTerminator = 1, isReturn = 1, isBarrier = 1 in
|
||||
let isTerminator = 1, isReturn = 1, isBarrier = 1 in
|
||||
def RETI : Ii16<0xC2, RawFrm, (ops i16imm:$amt), "ret $amt", []>;
|
||||
|
||||
def : Pat<(X86retflag FLAG), (RET)>;
|
||||
|
||||
// All branches are RawFrm, Void, Branch, and Terminators
|
||||
let isBranch = 1, isTerminator = 1 in
|
||||
class IBr<bits<8> opcode, dag ops, string asm, list<dag> pattern> :
|
||||
@ -2188,10 +2204,21 @@ def FpDIV : FPI<0, Pseudo, TwoArgFP ,
|
||||
(ops RFP:$dst, RFP:$src1, RFP:$src2), "",
|
||||
[]>; // f1 = fdiv f2, f3
|
||||
|
||||
def FpLD32m : FPI<0xD9, MRM0m, ZeroArgFP,
|
||||
(ops RFP:$dst, f32mem:$src),
|
||||
"fld{s} $src",
|
||||
[(set RFP:$dst, (X86fld addr:$src, f32))]>;
|
||||
|
||||
def FpLD64m : FPI<0xDD, MRM0m, ZeroArgFP,
|
||||
(ops RFP:$dst, f64mem:$src),
|
||||
"fld{l} $src",
|
||||
[(set RFP:$dst, (X86fld addr:$src, f64))]>;
|
||||
|
||||
def FpGETRESULT : FPI<0, Pseudo, SpecialFP, (ops RFP:$dst), "", []>,
|
||||
Imp<[ST0], []>; // FPR = ST(0)
|
||||
|
||||
def FpSETRESULT : FPI<0, Pseudo, SpecialFP, (ops RFP:$src), "", []>,
|
||||
def FpSETRESULT : FPI<0, Pseudo, SpecialFP, (ops RFP:$src), "",
|
||||
[(X86fpset RFP:$src)]>,
|
||||
Imp<[], [ST0]>; // ST(0) = FPR
|
||||
|
||||
// FADD reg, mem: Before stackification, these are represented by:
|
||||
|
@ -142,6 +142,11 @@ def RST : RegisterClass<"X86", [f64], 32,
|
||||
}];
|
||||
}
|
||||
|
||||
def FLAGS_REGS : RegisterClass<"X86", [FlagVT], 32, [STATUS]> {
|
||||
// FIXME:
|
||||
// HACKTROCITY: define a flags reg class for things that need to take a flag.
|
||||
// this should really be handled by tablgen.
|
||||
let Namespace = "X86" in
|
||||
def FLAG : Register<"FLAG">;
|
||||
def FLAGS_REGS : RegisterClass<"X86", [FlagVT], 32, [STATUS, FLAG]> {
|
||||
let Size = 32;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user