1349cc55cSDimitry Andric //===-- CSKYISelLowering.cpp - CSKY DAG Lowering Implementation ----------===// 2349cc55cSDimitry Andric // 3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6349cc55cSDimitry Andric // 7349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 8349cc55cSDimitry Andric // 9349cc55cSDimitry Andric // This file defines the interfaces that CSKY uses to lower LLVM code into a 10349cc55cSDimitry Andric // selection DAG. 11349cc55cSDimitry Andric // 12349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 13349cc55cSDimitry Andric 14349cc55cSDimitry Andric #ifndef LLVM_LIB_TARGET_CSKY_CSKYISELLOWERING_H 15349cc55cSDimitry Andric #define LLVM_LIB_TARGET_CSKY_CSKYISELLOWERING_H 16349cc55cSDimitry Andric 17349cc55cSDimitry Andric #include "MCTargetDesc/CSKYBaseInfo.h" 18349cc55cSDimitry Andric #include "llvm/CodeGen/CallingConvLower.h" 19349cc55cSDimitry Andric #include "llvm/CodeGen/TargetLowering.h" 20349cc55cSDimitry Andric 21349cc55cSDimitry Andric namespace llvm { 22349cc55cSDimitry Andric class CSKYSubtarget; 23349cc55cSDimitry Andric 24349cc55cSDimitry Andric namespace CSKYISD { 25349cc55cSDimitry Andric enum NodeType : unsigned { 26349cc55cSDimitry Andric FIRST_NUMBER = ISD::BUILTIN_OP_END, 27349cc55cSDimitry Andric NIE, 28349cc55cSDimitry Andric NIR, 29349cc55cSDimitry Andric RET, 3004eeddc0SDimitry Andric CALL, 3104eeddc0SDimitry Andric CALLReg, 3204eeddc0SDimitry Andric TAIL, 3304eeddc0SDimitry Andric TAILReg, 3404eeddc0SDimitry Andric LOAD_ADDR, 3504eeddc0SDimitry Andric // i32, i32 <-- f64 3604eeddc0SDimitry Andric BITCAST_TO_LOHI, 3704eeddc0SDimitry Andric // f64 < -- i32, i32 3804eeddc0SDimitry Andric BITCAST_FROM_LOHI, 39349cc55cSDimitry Andric }; 40349cc55cSDimitry Andric } 41349cc55cSDimitry Andric 42349cc55cSDimitry Andric class CSKYTargetLowering : public TargetLowering { 43349cc55cSDimitry Andric const CSKYSubtarget &Subtarget; 44349cc55cSDimitry Andric 45349cc55cSDimitry Andric public: 46349cc55cSDimitry Andric explicit CSKYTargetLowering(const TargetMachine &TM, 47349cc55cSDimitry Andric const CSKYSubtarget &STI); 48349cc55cSDimitry Andric 4904eeddc0SDimitry Andric SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; 5004eeddc0SDimitry Andric 51349cc55cSDimitry Andric EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, 52349cc55cSDimitry Andric EVT VT) const override; 53349cc55cSDimitry Andric 54349cc55cSDimitry Andric private: 55349cc55cSDimitry Andric SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, 56349cc55cSDimitry Andric bool IsVarArg, 57349cc55cSDimitry Andric const SmallVectorImpl<ISD::InputArg> &Ins, 58349cc55cSDimitry Andric const SDLoc &DL, SelectionDAG &DAG, 59349cc55cSDimitry Andric SmallVectorImpl<SDValue> &InVals) const override; 60349cc55cSDimitry Andric 61349cc55cSDimitry Andric bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, 62349cc55cSDimitry Andric bool IsVarArg, 63349cc55cSDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs, 64349cc55cSDimitry Andric LLVMContext &Context) const override; 65349cc55cSDimitry Andric 66349cc55cSDimitry Andric SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, 67349cc55cSDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs, 68349cc55cSDimitry Andric const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL, 69349cc55cSDimitry Andric SelectionDAG &DAG) const override; 70349cc55cSDimitry Andric 7104eeddc0SDimitry Andric SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, 7204eeddc0SDimitry Andric SmallVectorImpl<SDValue> &InVals) const override; 7304eeddc0SDimitry Andric 74349cc55cSDimitry Andric const char *getTargetNodeName(unsigned Opcode) const override; 75349cc55cSDimitry Andric 7604eeddc0SDimitry Andric /// If a physical register, this returns the register that receives the 7704eeddc0SDimitry Andric /// exception address on entry to an EH pad. 7804eeddc0SDimitry Andric Register 7904eeddc0SDimitry Andric getExceptionPointerRegister(const Constant *PersonalityFn) const override; 8004eeddc0SDimitry Andric 8104eeddc0SDimitry Andric /// If a physical register, this returns the register that receives the 8204eeddc0SDimitry Andric /// exception typeid on entry to a landing pad. 8304eeddc0SDimitry Andric Register 8404eeddc0SDimitry Andric getExceptionSelectorRegister(const Constant *PersonalityFn) const override; 8504eeddc0SDimitry Andric isSelectSupported(SelectSupportKind Kind)8604eeddc0SDimitry Andric bool isSelectSupported(SelectSupportKind Kind) const override { 8704eeddc0SDimitry Andric // CSKY does not support scalar condition selects on vectors. 8804eeddc0SDimitry Andric return (Kind != ScalarCondVectorVal); 8904eeddc0SDimitry Andric } 9004eeddc0SDimitry Andric 9181ad6265SDimitry Andric ConstraintType getConstraintType(StringRef Constraint) const override; 9281ad6265SDimitry Andric 9381ad6265SDimitry Andric std::pair<unsigned, const TargetRegisterClass *> 9481ad6265SDimitry Andric getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, 9581ad6265SDimitry Andric StringRef Constraint, MVT VT) const override; 9681ad6265SDimitry Andric 9704eeddc0SDimitry Andric MachineBasicBlock * 9804eeddc0SDimitry Andric EmitInstrWithCustomInserter(MachineInstr &MI, 9904eeddc0SDimitry Andric MachineBasicBlock *BB) const override; 10004eeddc0SDimitry Andric 10104eeddc0SDimitry Andric SDValue getTargetNode(GlobalAddressSDNode *N, SDLoc DL, EVT Ty, 10204eeddc0SDimitry Andric SelectionDAG &DAG, unsigned Flags) const; 10304eeddc0SDimitry Andric 10404eeddc0SDimitry Andric SDValue getTargetNode(ExternalSymbolSDNode *N, SDLoc DL, EVT Ty, 10504eeddc0SDimitry Andric SelectionDAG &DAG, unsigned Flags) const; 10604eeddc0SDimitry Andric 10704eeddc0SDimitry Andric SDValue getTargetNode(JumpTableSDNode *N, SDLoc DL, EVT Ty, SelectionDAG &DAG, 10804eeddc0SDimitry Andric unsigned Flags) const; 10904eeddc0SDimitry Andric 11004eeddc0SDimitry Andric SDValue getTargetNode(BlockAddressSDNode *N, SDLoc DL, EVT Ty, 11104eeddc0SDimitry Andric SelectionDAG &DAG, unsigned Flags) const; 11204eeddc0SDimitry Andric 113bdd1243dSDimitry Andric SDValue getTargetNode(ConstantPoolSDNode *N, SDLoc DL, EVT Ty, 114bdd1243dSDimitry Andric SelectionDAG &DAG, unsigned Flags) const; 115bdd1243dSDimitry Andric 11604eeddc0SDimitry Andric SDValue getTargetConstantPoolValue(GlobalAddressSDNode *N, EVT Ty, 11704eeddc0SDimitry Andric SelectionDAG &DAG, unsigned Flags) const; 11804eeddc0SDimitry Andric 11904eeddc0SDimitry Andric SDValue getTargetConstantPoolValue(ExternalSymbolSDNode *N, EVT Ty, 12004eeddc0SDimitry Andric SelectionDAG &DAG, unsigned Flags) const; 12104eeddc0SDimitry Andric 12204eeddc0SDimitry Andric SDValue getTargetConstantPoolValue(JumpTableSDNode *N, EVT Ty, 12304eeddc0SDimitry Andric SelectionDAG &DAG, unsigned Flags) const; 12404eeddc0SDimitry Andric 12504eeddc0SDimitry Andric SDValue getTargetConstantPoolValue(BlockAddressSDNode *N, EVT Ty, 12604eeddc0SDimitry Andric SelectionDAG &DAG, unsigned Flags) const; 12704eeddc0SDimitry Andric 128bdd1243dSDimitry Andric SDValue getTargetConstantPoolValue(ConstantPoolSDNode *N, EVT Ty, 129bdd1243dSDimitry Andric SelectionDAG &DAG, unsigned Flags) const; 130bdd1243dSDimitry Andric 13104eeddc0SDimitry Andric template <class NodeTy, bool IsCall = false> 13204eeddc0SDimitry Andric SDValue getAddr(NodeTy *N, SelectionDAG &DAG, bool IsLocal = true) const { 13304eeddc0SDimitry Andric SDLoc DL(N); 13404eeddc0SDimitry Andric EVT Ty = getPointerTy(DAG.getDataLayout()); 13504eeddc0SDimitry Andric 13604eeddc0SDimitry Andric unsigned Flag = CSKYII::MO_None; 13704eeddc0SDimitry Andric bool IsPIC = isPositionIndependent(); 13804eeddc0SDimitry Andric 13904eeddc0SDimitry Andric if (IsPIC) 14004eeddc0SDimitry Andric Flag = IsLocal ? CSKYII::MO_GOTOFF 14104eeddc0SDimitry Andric : IsCall ? CSKYII::MO_PLT32 14204eeddc0SDimitry Andric : CSKYII::MO_GOT32; 14304eeddc0SDimitry Andric 14404eeddc0SDimitry Andric SDValue TCPV = getTargetConstantPoolValue(N, Ty, DAG, Flag); 14504eeddc0SDimitry Andric SDValue TV = getTargetNode(N, DL, Ty, DAG, Flag); 14604eeddc0SDimitry Andric SDValue Addr = DAG.getNode(CSKYISD::LOAD_ADDR, DL, Ty, {TV, TCPV}); 14704eeddc0SDimitry Andric 14804eeddc0SDimitry Andric if (!IsPIC) 14904eeddc0SDimitry Andric return Addr; 15004eeddc0SDimitry Andric 15104eeddc0SDimitry Andric SDValue Result = 15204eeddc0SDimitry Andric DAG.getNode(ISD::ADD, DL, Ty, {DAG.getGLOBAL_OFFSET_TABLE(Ty), Addr}); 15304eeddc0SDimitry Andric if (IsLocal) 15404eeddc0SDimitry Andric return Result; 15504eeddc0SDimitry Andric 15604eeddc0SDimitry Andric return DAG.getLoad(Ty, DL, DAG.getEntryNode(), Result, 15704eeddc0SDimitry Andric MachinePointerInfo::getGOT(DAG.getMachineFunction())); 15804eeddc0SDimitry Andric } 15904eeddc0SDimitry Andric 16004eeddc0SDimitry Andric SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; 16104eeddc0SDimitry Andric SDValue LowerExternalSymbol(SDValue Op, SelectionDAG &DAG) const; 16204eeddc0SDimitry Andric SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const; 16304eeddc0SDimitry Andric SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const; 164bdd1243dSDimitry Andric SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const; 16504eeddc0SDimitry Andric SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) const; 16604eeddc0SDimitry Andric SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const; 16704eeddc0SDimitry Andric SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; 16804eeddc0SDimitry Andric SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const; 16904eeddc0SDimitry Andric 17004eeddc0SDimitry Andric SDValue getStaticTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG, 17104eeddc0SDimitry Andric bool UseGOT) const; 17204eeddc0SDimitry Andric SDValue getDynamicTLSAddr(GlobalAddressSDNode *N, SelectionDAG &DAG) const; 17304eeddc0SDimitry Andric 174349cc55cSDimitry Andric CCAssignFn *CCAssignFnForCall(CallingConv::ID CC, bool IsVarArg) const; 175349cc55cSDimitry Andric CCAssignFn *CCAssignFnForReturn(CallingConv::ID CC, bool IsVarArg) const; 17606c3fb27SDimitry Andric 17706c3fb27SDimitry Andric bool decomposeMulByConstant(LLVMContext &Context, EVT VT, 17806c3fb27SDimitry Andric SDValue C) const override; 179*5f757f3fSDimitry Andric bool isCheapToSpeculateCttz(Type *Ty) const override; 180*5f757f3fSDimitry Andric bool isCheapToSpeculateCtlz(Type *Ty) const override; 181349cc55cSDimitry Andric }; 182349cc55cSDimitry Andric 183349cc55cSDimitry Andric } // namespace llvm 184349cc55cSDimitry Andric 185349cc55cSDimitry Andric #endif // LLVM_LIB_TARGET_CSKY_CSKYISELLOWERING_H 186