mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-26 05:25:47 +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:
@@ -173,22 +173,7 @@ bool X86DAGToDAGISel::MatchAddress(SDOperand N, X86ISelAddressMode &AM) {
|
|||||||
|
|
||||||
case ISD::GlobalAddress:
|
case ISD::GlobalAddress:
|
||||||
if (AM.GV == 0) {
|
if (AM.GV == 0) {
|
||||||
GlobalValue *GV = cast<GlobalAddressSDNode>(N)->getGlobal();
|
AM.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;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@@ -197,6 +197,68 @@ X86TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
|
|||||||
return LowerCCCCallTo(Chain, RetTy, isVarArg, isTailCall, Callee, Args, DAG);
|
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
|
// C Calling Convention implementation
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@@ -968,6 +1030,20 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
|||||||
return DAG.getNode(X86ISD::BRCOND, Op.getValueType(),
|
return DAG.getNode(X86ISD::BRCOND, Op.getValueType(),
|
||||||
Op.getOperand(0), Op.getOperand(2), CC, Cond);
|
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_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_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::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::CALL: return "X86ISD::CALL";
|
||||||
case X86ISD::TAILCALL: return "X86ISD::TAILCALL";
|
case X86ISD::TAILCALL: return "X86ISD::TAILCALL";
|
||||||
case X86ISD::RDTSC_DAG: return "X86ISD::RDTSC_DAG";
|
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::TEST: return "X86ISD::TEST";
|
||||||
case X86ISD::CMOV: return "X86ISD::CMOV";
|
case X86ISD::CMOV: return "X86ISD::CMOV";
|
||||||
case X86ISD::BRCOND: return "X86ISD::BRCOND";
|
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_INT32_IN_MEM,
|
||||||
FP_TO_INT64_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
|
/// CALL/TAILCALL - These operations represent an abstract X86 call
|
||||||
/// instruction, which includes a bunch of information. In particular the
|
/// instruction, which includes a bunch of information. In particular the
|
||||||
/// operands of these node are:
|
/// operands of these node are:
|
||||||
@@ -75,6 +86,9 @@ namespace llvm {
|
|||||||
|
|
||||||
/// X86 conditional branches.
|
/// X86 conditional branches.
|
||||||
BRCOND,
|
BRCOND,
|
||||||
|
|
||||||
|
// Return with a flag operand.
|
||||||
|
RET_FLAG,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,6 +127,9 @@ namespace llvm {
|
|||||||
bool isTailCall, SDOperand Callee, ArgListTy &Args,
|
bool isTailCall, SDOperand Callee, ArgListTy &Args,
|
||||||
SelectionDAG &DAG);
|
SelectionDAG &DAG);
|
||||||
|
|
||||||
|
virtual SDOperand LowerReturnTo(SDOperand Chain, SDOperand Op,
|
||||||
|
SelectionDAG &DAG);
|
||||||
|
|
||||||
virtual SDOperand LowerVAStart(SDOperand Chain, SDOperand VAListP,
|
virtual SDOperand LowerVAStart(SDOperand Chain, SDOperand VAListP,
|
||||||
Value *VAListV, SelectionDAG &DAG);
|
Value *VAListV, SelectionDAG &DAG);
|
||||||
virtual std::pair<SDOperand,SDOperand>
|
virtual std::pair<SDOperand,SDOperand>
|
||||||
|
@@ -28,12 +28,26 @@ def SDTX86BrCond : SDTypeProfile<0, 3,
|
|||||||
[SDTCisVT<0, OtherVT>,
|
[SDTCisVT<0, OtherVT>,
|
||||||
SDTCisVT<1, OtherVT>, SDTCisVT<2, FlagVT>]>;
|
SDTCisVT<1, OtherVT>, SDTCisVT<2, FlagVT>]>;
|
||||||
|
|
||||||
|
def SDTX86RetFlag : SDTypeProfile<0, 1, [SDTCisVT<0, FlagVT>]>;
|
||||||
|
|
||||||
|
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 X86cmp : SDNode<"X86ISD::CMP" , SDTX86CmpTest, []>;
|
||||||
def X86test : SDNode<"X86ISD::TEST", SDTX86CmpTest, []>;
|
def X86test : SDNode<"X86ISD::TEST", SDTX86CmpTest, []>;
|
||||||
|
|
||||||
def X86cmov : SDNode<"X86ISD::CMOV", SDTX86Cmov, []>;
|
def X86cmov : SDNode<"X86ISD::CMOV", SDTX86Cmov, []>;
|
||||||
def X86Brcond : SDNode<"X86ISD::BRCOND", SDTX86BrCond, [SDNPHasChain]>;
|
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.
|
// X86 Operand Definitions.
|
||||||
//
|
//
|
||||||
@@ -274,6 +288,8 @@ let isTerminator = 1, isReturn = 1, isBarrier = 1 in
|
|||||||
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 RETI : Ii16<0xC2, RawFrm, (ops i16imm:$amt), "ret $amt", []>;
|
||||||
|
|
||||||
|
def : Pat<(X86retflag FLAG), (RET)>;
|
||||||
|
|
||||||
// All branches are RawFrm, Void, Branch, and Terminators
|
// All branches are RawFrm, Void, Branch, and Terminators
|
||||||
let isBranch = 1, isTerminator = 1 in
|
let isBranch = 1, isTerminator = 1 in
|
||||||
class IBr<bits<8> opcode, dag ops, string asm, list<dag> pattern> :
|
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), "",
|
(ops RFP:$dst, RFP:$src1, RFP:$src2), "",
|
||||||
[]>; // f1 = fdiv f2, f3
|
[]>; // 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), "", []>,
|
def FpGETRESULT : FPI<0, Pseudo, SpecialFP, (ops RFP:$dst), "", []>,
|
||||||
Imp<[ST0], []>; // FPR = ST(0)
|
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
|
Imp<[], [ST0]>; // ST(0) = FPR
|
||||||
|
|
||||||
// FADD reg, mem: Before stackification, these are represented by:
|
// 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;
|
let Size = 32;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user