Changeset View
Changeset View
Standalone View
Standalone View
llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
Show First 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM, | ||||
// TODO: add necessary setOperationAction calls later. | // TODO: add necessary setOperationAction calls later. | ||||
setOperationAction(ISD::SHL_PARTS, GRLenVT, Custom); | setOperationAction(ISD::SHL_PARTS, GRLenVT, Custom); | ||||
setOperationAction(ISD::SRA_PARTS, GRLenVT, Custom); | setOperationAction(ISD::SRA_PARTS, GRLenVT, Custom); | ||||
setOperationAction(ISD::SRL_PARTS, GRLenVT, Custom); | setOperationAction(ISD::SRL_PARTS, GRLenVT, Custom); | ||||
setOperationAction(ISD::FP_TO_SINT, GRLenVT, Custom); | setOperationAction(ISD::FP_TO_SINT, GRLenVT, Custom); | ||||
setOperationAction({ISD::GlobalAddress, ISD::ConstantPool}, GRLenVT, Custom); | setOperationAction({ISD::GlobalAddress, ISD::ConstantPool}, GRLenVT, Custom); | ||||
setOperationAction(ISD::DYNAMIC_STACKALLOC, GRLenVT, Expand); | |||||
setOperationAction(ISD::VASTART, MVT::Other, Custom); | |||||
setOperationAction({ISD::VAARG, ISD::VACOPY, ISD::VAEND}, MVT::Other, Expand); | |||||
if (Subtarget.is64Bit()) { | if (Subtarget.is64Bit()) { | ||||
setOperationAction(ISD::SHL, MVT::i32, Custom); | setOperationAction(ISD::SHL, MVT::i32, Custom); | ||||
setOperationAction(ISD::SRA, MVT::i32, Custom); | setOperationAction(ISD::SRA, MVT::i32, Custom); | ||||
setOperationAction(ISD::SRL, MVT::i32, Custom); | setOperationAction(ISD::SRL, MVT::i32, Custom); | ||||
setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); | setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); | ||||
setOperationAction(ISD::BITCAST, MVT::i32, Custom); | setOperationAction(ISD::BITCAST, MVT::i32, Custom); | ||||
if (Subtarget.hasBasicF() && !Subtarget.hasBasicD()) | if (Subtarget.hasBasicF() && !Subtarget.hasBasicD()) | ||||
setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom); | setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom); | ||||
▲ Show 20 Lines • Show All 66 Lines • ▼ Show 20 Lines | SDValue LoongArchTargetLowering::LowerOperation(SDValue Op, | ||||
case ISD::FP_TO_SINT: | case ISD::FP_TO_SINT: | ||||
return lowerFP_TO_SINT(Op, DAG); | return lowerFP_TO_SINT(Op, DAG); | ||||
case ISD::BITCAST: | case ISD::BITCAST: | ||||
return lowerBITCAST(Op, DAG); | return lowerBITCAST(Op, DAG); | ||||
case ISD::FP_TO_UINT: | case ISD::FP_TO_UINT: | ||||
return SDValue(); | return SDValue(); | ||||
case ISD::UINT_TO_FP: | case ISD::UINT_TO_FP: | ||||
return lowerUINT_TO_FP(Op, DAG); | return lowerUINT_TO_FP(Op, DAG); | ||||
case ISD::VASTART: | |||||
return lowerVASTART(Op, DAG); | |||||
} | |||||
} | } | ||||
SDValue LoongArchTargetLowering::lowerVASTART(SDValue Op, | |||||
SelectionDAG &DAG) const { | |||||
MachineFunction &MF = DAG.getMachineFunction(); | |||||
auto *FuncInfo = MF.getInfo<LoongArchMachineFunctionInfo>(); | |||||
SDLoc DL(Op); | |||||
SDValue FI = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), | |||||
getPointerTy(MF.getDataLayout())); | |||||
// vastart just stores the address of the VarArgsFrameIndex slot into the | |||||
// memory location argument. | |||||
const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); | |||||
return DAG.getStore(Op.getOperand(0), DL, FI, Op.getOperand(1), | |||||
MachinePointerInfo(SV)); | |||||
} | } | ||||
SDValue LoongArchTargetLowering::lowerUINT_TO_FP(SDValue Op, | SDValue LoongArchTargetLowering::lowerUINT_TO_FP(SDValue Op, | ||||
SelectionDAG &DAG) const { | SelectionDAG &DAG) const { | ||||
SDLoc DL(Op); | SDLoc DL(Op); | ||||
auto &TLI = DAG.getTargetLoweringInfo(); | auto &TLI = DAG.getTargetLoweringInfo(); | ||||
SDValue Tmp1, Tmp2; | SDValue Tmp1, Tmp2; | ||||
▲ Show 20 Lines • Show All 1,001 Lines • ▼ Show 20 Lines | SDValue LoongArchTargetLowering::LowerFormalArguments( | ||||
switch (CallConv) { | switch (CallConv) { | ||||
default: | default: | ||||
llvm_unreachable("Unsupported calling convention"); | llvm_unreachable("Unsupported calling convention"); | ||||
case CallingConv::C: | case CallingConv::C: | ||||
break; | break; | ||||
} | } | ||||
EVT PtrVT = getPointerTy(DAG.getDataLayout()); | EVT PtrVT = getPointerTy(DAG.getDataLayout()); | ||||
MVT GRLenVT = Subtarget.getGRLenVT(); | |||||
unsigned GRLenInBytes = Subtarget.getGRLen() / 8; | |||||
// Used with varargs to acumulate store chains. | |||||
xen0n: "varargs"? | |||||
std::vector<SDValue> OutChains; | |||||
// Assign locations to all of the incoming arguments. | // Assign locations to all of the incoming arguments. | ||||
SmallVector<CCValAssign> ArgLocs; | SmallVector<CCValAssign> ArgLocs; | ||||
CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); | CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); | ||||
analyzeInputArgs(MF, CCInfo, Ins, /*IsRet=*/false, CC_LoongArch); | analyzeInputArgs(MF, CCInfo, Ins, /*IsRet=*/false, CC_LoongArch); | ||||
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { | for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { | ||||
Show All 21 Lines | if (VA.getLocInfo() == CCValAssign::Indirect) { | ||||
++i; | ++i; | ||||
} | } | ||||
continue; | continue; | ||||
} | } | ||||
InVals.push_back(ArgValue); | InVals.push_back(ArgValue); | ||||
} | } | ||||
if (IsVarArg) { | if (IsVarArg) { | ||||
// TODO: Support vararg. | ArrayRef<MCPhysReg> ArgRegs = makeArrayRef(ArgGPRs); | ||||
report_fatal_error("Not support vararg"); | unsigned Idx = CCInfo.getFirstUnallocated(ArgRegs); | ||||
const TargetRegisterClass *RC = &LoongArch::GPRRegClass; | |||||
MachineFrameInfo &MFI = MF.getFrameInfo(); | |||||
MachineRegisterInfo &RegInfo = MF.getRegInfo(); | |||||
auto *LoongArchFI = MF.getInfo<LoongArchMachineFunctionInfo>(); | |||||
// Offset of the first variable argument from stack pointer, and size of | |||||
// the vararg save area. For now, the varargs save area is either zero or | |||||
// large enough to hold a0-a7. | |||||
int VaArgOffset, VarArgsSaveSize; | |||||
// If all registers are allocated, then all varargs must be passed on the | |||||
// stack and we don't need to save any argregs. | |||||
if (ArgRegs.size() == Idx) { | |||||
VaArgOffset = CCInfo.getNextStackOffset(); | |||||
VarArgsSaveSize = 0; | |||||
} else { | |||||
VarArgsSaveSize = GRLenInBytes * (ArgRegs.size() - Idx); | |||||
VaArgOffset = -VarArgsSaveSize; | |||||
} | |||||
// Record the frame index of the first variable argument | |||||
// which is a value necessary to VASTART. | |||||
int FI = MFI.CreateFixedObject(GRLenInBytes, VaArgOffset, true); | |||||
LoongArchFI->setVarArgsFrameIndex(FI); | |||||
// If saving an odd number of registers then create an extra stack slot to | |||||
// ensure that the frame pointer is 2*GRLen-aligned, which in turn ensures | |||||
// offsets to even-numbered registered remain 2*GRLen-aligned. | |||||
if (Idx % 2) { | |||||
MFI.CreateFixedObject(GRLenInBytes, VaArgOffset - (int)GRLenInBytes, | |||||
true); | |||||
VarArgsSaveSize += GRLenInBytes; | |||||
} | |||||
// Copy the integer registers that may have been used for passing varargs | |||||
// to the vararg save area. | |||||
for (unsigned I = Idx; I < ArgRegs.size(); | |||||
++I, VaArgOffset += GRLenInBytes) { | |||||
const Register Reg = RegInfo.createVirtualRegister(RC); | |||||
RegInfo.addLiveIn(ArgRegs[I], Reg); | |||||
SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, GRLenVT); | |||||
FI = MFI.CreateFixedObject(GRLenInBytes, VaArgOffset, true); | |||||
SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); | |||||
SDValue Store = DAG.getStore(Chain, DL, ArgValue, PtrOff, | |||||
MachinePointerInfo::getFixedStack(MF, FI)); | |||||
cast<StoreSDNode>(Store.getNode()) | |||||
->getMemOperand() | |||||
->setValue((Value *)nullptr); | |||||
OutChains.push_back(Store); | |||||
} | |||||
LoongArchFI->setVarArgsSaveSize(VarArgsSaveSize); | |||||
} | |||||
// All stores are grouped in one node to allow the matching between | |||||
// the size of Ins and InVals. This only happens for vararg functions. | |||||
if (!OutChains.empty()) { | |||||
OutChains.push_back(Chain); | |||||
Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains); | |||||
} | } | ||||
return Chain; | return Chain; | ||||
} | } | ||||
static Align getPrefTypeAlign(EVT VT, SelectionDAG &DAG) { | static Align getPrefTypeAlign(EVT VT, SelectionDAG &DAG) { | ||||
return DAG.getDataLayout().getPrefTypeAlign( | return DAG.getDataLayout().getPrefTypeAlign( | ||||
VT.getTypeForEVT(*DAG.getContext())); | VT.getTypeForEVT(*DAG.getContext())); | ||||
▲ Show 20 Lines • Show All 278 Lines • Show Last 20 Lines |
"varargs"?