//
//===----------------------------------------------------------------------===//
-#ifndef MipsISELLOWERING_H
-#define MipsISELLOWERING_H
+#ifndef LLVM_LIB_TARGET_MIPS_MIPSISELLOWERING_H
+#define LLVM_LIB_TARGET_MIPS_MIPSISELLOWERING_H
+#include "MCTargetDesc/MipsABIInfo.h"
#include "MCTargetDesc/MipsBaseInfo.h"
#include "Mips.h"
-#include "MipsSubtarget.h"
#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/IR/Function.h"
namespace llvm {
namespace MipsISD {
- enum NodeType {
+ enum NodeType : unsigned {
// Start the numbering from where ISD NodeType finishes.
FIRST_NUMBER = ISD::BUILTIN_OP_END,
// TargetLowering Implementation
//===--------------------------------------------------------------------===//
class MipsFunctionInfo;
+ class MipsSubtarget;
+ class MipsCCState;
class MipsTargetLowering : public TargetLowering {
bool isMicroMips;
public:
- explicit MipsTargetLowering(MipsTargetMachine &TM);
+ explicit MipsTargetLowering(const MipsTargetMachine &TM,
+ const MipsSubtarget &STI);
- static const MipsTargetLowering *create(MipsTargetMachine &TM);
+ static const MipsTargetLowering *create(const MipsTargetMachine &TM,
+ const MipsSubtarget &STI);
/// createFastISel - This method returns a target specific FastISel object,
/// or null if the target does not support "fast" ISel.
}
};
+ void HandleByVal(CCState *, unsigned &, unsigned) const override;
+
+ unsigned getRegisterByName(const char* RegName, EVT VT) const override;
+
protected:
SDValue getGlobalReg(SelectionDAG &DAG, EVT Ty) const;
//
// (add (load (wrapper $gp, %got(sym)), %lo(sym))
template <class NodeTy>
- SDValue getAddrLocal(NodeTy *N, EVT Ty, SelectionDAG &DAG,
+ SDValue getAddrLocal(NodeTy *N, SDLoc DL, EVT Ty, SelectionDAG &DAG,
bool IsN32OrN64) const {
- SDLoc DL(N);
unsigned GOTFlag = IsN32OrN64 ? MipsII::MO_GOT_PAGE : MipsII::MO_GOT;
SDValue GOT = DAG.getNode(MipsISD::Wrapper, DL, Ty, getGlobalReg(DAG, Ty),
getTargetNode(N, Ty, DAG, GOTFlag));
// computing a global symbol's address:
//
// (load (wrapper $gp, %got(sym)))
- template<class NodeTy>
- SDValue getAddrGlobal(NodeTy *N, EVT Ty, SelectionDAG &DAG,
+ template <class NodeTy>
+ SDValue getAddrGlobal(NodeTy *N, SDLoc DL, EVT Ty, SelectionDAG &DAG,
unsigned Flag, SDValue Chain,
const MachinePointerInfo &PtrInfo) const {
- SDLoc DL(N);
SDValue Tgt = DAG.getNode(MipsISD::Wrapper, DL, Ty, getGlobalReg(DAG, Ty),
getTargetNode(N, Ty, DAG, Flag));
return DAG.getLoad(Ty, DL, Chain, Tgt, PtrInfo, false, false, false, 0);
// computing a global symbol's address in large-GOT mode:
//
// (load (wrapper (add %hi(sym), $gp), %lo(sym)))
- template<class NodeTy>
- SDValue getAddrGlobalLargeGOT(NodeTy *N, EVT Ty, SelectionDAG &DAG,
- unsigned HiFlag, unsigned LoFlag,
- SDValue Chain,
+ template <class NodeTy>
+ SDValue getAddrGlobalLargeGOT(NodeTy *N, SDLoc DL, EVT Ty,
+ SelectionDAG &DAG, unsigned HiFlag,
+ unsigned LoFlag, SDValue Chain,
const MachinePointerInfo &PtrInfo) const {
- SDLoc DL(N);
- SDValue Hi = DAG.getNode(MipsISD::Hi, DL, Ty,
- getTargetNode(N, Ty, DAG, HiFlag));
+ SDValue Hi =
+ DAG.getNode(MipsISD::Hi, DL, Ty, getTargetNode(N, Ty, DAG, HiFlag));
Hi = DAG.getNode(ISD::ADD, DL, Ty, Hi, getGlobalReg(DAG, Ty));
SDValue Wrapper = DAG.getNode(MipsISD::Wrapper, DL, Ty, Hi,
getTargetNode(N, Ty, DAG, LoFlag));
// computing a symbol's address in non-PIC mode:
//
// (add %hi(sym), %lo(sym))
- template<class NodeTy>
- SDValue getAddrNonPIC(NodeTy *N, EVT Ty, SelectionDAG &DAG) const {
- SDLoc DL(N);
+ template <class NodeTy>
+ SDValue getAddrNonPIC(NodeTy *N, SDLoc DL, EVT Ty,
+ SelectionDAG &DAG) const {
SDValue Hi = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_HI);
SDValue Lo = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_LO);
return DAG.getNode(ISD::ADD, DL, Ty,
DAG.getNode(MipsISD::Lo, DL, Ty, Lo));
}
+ // This method creates the following nodes, which are necessary for
+ // computing a symbol's address using gp-relative addressing:
+ //
+ // (add $gp, %gp_rel(sym))
+ template <class NodeTy>
+ SDValue getAddrGPRel(NodeTy *N, SDLoc DL, EVT Ty, SelectionDAG &DAG) const {
+ assert(Ty == MVT::i32);
+ SDValue GPRel = getTargetNode(N, Ty, DAG, MipsII::MO_GPREL);
+ return DAG.getNode(ISD::ADD, DL, Ty,
+ DAG.getRegister(Mips::GP, Ty),
+ DAG.getNode(MipsISD::GPRel, DL, DAG.getVTList(Ty),
+ GPRel));
+ }
+
/// This function fills Ops, which is the list of operands that will later
/// be used when a function call node is created. It also generates
/// copyToReg nodes to set up argument registers.
getOpndList(SmallVectorImpl<SDValue> &Ops,
std::deque< std::pair<unsigned, SDValue> > &RegsToPass,
bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage,
- CallLoweringInfo &CLI, SDValue Callee, SDValue Chain) const;
-
- /// ByValArgInfo - Byval argument information.
- struct ByValArgInfo {
- unsigned FirstIdx; // Index of the first register used.
- unsigned NumRegs; // Number of registers used for this argument.
- unsigned Address; // Offset of the stack area used to pass this argument.
-
- ByValArgInfo() : FirstIdx(0), NumRegs(0), Address(0) {}
- };
-
- /// MipsCC - This class provides methods used to analyze formal and call
- /// arguments and inquire about calling convention information.
- class MipsCC {
- public:
- enum SpecialCallingConvType {
- Mips16RetHelperConv, NoSpecialCallingConv
- };
-
- MipsCC(CallingConv::ID CallConv, bool IsO32, bool IsFP64, CCState &Info,
- SpecialCallingConvType SpecialCallingConv = NoSpecialCallingConv);
-
-
- void analyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs,
- bool IsVarArg, bool IsSoftFloat,
- const SDNode *CallNode,
- std::vector<ArgListEntry> &FuncArgs);
- void analyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins,
- bool IsSoftFloat,
- Function::const_arg_iterator FuncArg);
-
- void analyzeCallResult(const SmallVectorImpl<ISD::InputArg> &Ins,
- bool IsSoftFloat, const SDNode *CallNode,
- const Type *RetTy) const;
-
- void analyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs,
- bool IsSoftFloat, const Type *RetTy) const;
-
- const CCState &getCCInfo() const { return CCInfo; }
+ bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee,
+ SDValue Chain) const;
- /// hasByValArg - Returns true if function has byval arguments.
- bool hasByValArg() const { return !ByValArgs.empty(); }
-
- /// regSize - Size (in number of bits) of integer registers.
- unsigned regSize() const { return IsO32 ? 4 : 8; }
-
- /// numIntArgRegs - Number of integer registers available for calls.
- unsigned numIntArgRegs() const;
-
- /// reservedArgArea - The size of the area the caller reserves for
- /// register arguments. This is 16-byte if ABI is O32.
- unsigned reservedArgArea() const;
-
- /// Return pointer to array of integer argument registers.
- const MCPhysReg *intArgRegs() const;
-
- typedef SmallVectorImpl<ByValArgInfo>::const_iterator byval_iterator;
- byval_iterator byval_begin() const { return ByValArgs.begin(); }
- byval_iterator byval_end() const { return ByValArgs.end(); }
-
- private:
- void handleByValArg(unsigned ValNo, MVT ValVT, MVT LocVT,
- CCValAssign::LocInfo LocInfo,
- ISD::ArgFlagsTy ArgFlags);
-
- /// useRegsForByval - Returns true if the calling convention allows the
- /// use of registers to pass byval arguments.
- bool useRegsForByval() const { return CallConv != CallingConv::Fast; }
-
- /// Return the function that analyzes fixed argument list functions.
- llvm::CCAssignFn *fixedArgFn() const;
-
- /// Return the function that analyzes variable argument list functions.
- llvm::CCAssignFn *varArgFn() const;
-
- const MCPhysReg *shadowRegs() const;
-
- void allocateRegs(ByValArgInfo &ByVal, unsigned ByValSize,
- unsigned Align);
-
- /// Return the type of the register which is used to pass an argument or
- /// return a value. This function returns f64 if the argument is an i64
- /// value which has been generated as a result of softening an f128 value.
- /// Otherwise, it just returns VT.
- MVT getRegVT(MVT VT, const Type *OrigTy, const SDNode *CallNode,
- bool IsSoftFloat) const;
-
- template<typename Ty>
- void analyzeReturn(const SmallVectorImpl<Ty> &RetVals, bool IsSoftFloat,
- const SDNode *CallNode, const Type *RetTy) const;
-
- CCState &CCInfo;
- CallingConv::ID CallConv;
- bool IsO32, IsFP64;
- SpecialCallingConvType SpecialCallingConv;
- SmallVector<ByValArgInfo, 2> ByValArgs;
- };
protected:
SDValue lowerLOAD(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerSTORE(SDValue Op, SelectionDAG &DAG) const;
// Subtarget Info
- const MipsSubtarget *Subtarget;
-
- bool hasMips64() const { return Subtarget->hasMips64(); }
- bool isGP64bit() const { return Subtarget->isGP64bit(); }
- bool isO32() const { return Subtarget->isABI_O32(); }
- bool isN32() const { return Subtarget->isABI_N32(); }
- bool isN64() const { return Subtarget->isABI_N64(); }
+ const MipsSubtarget &Subtarget;
+ // Cache the ABI from the TargetMachine, we use it everywhere.
+ const MipsABIInfo &ABI;
private:
// Create a TargetGlobalAddress node.
SDValue getTargetNode(ConstantPoolSDNode *N, EVT Ty, SelectionDAG &DAG,
unsigned Flag) const;
- MipsCC::SpecialCallingConvType getSpecialCallingConv(SDValue Callee) const;
// Lower Operand helpers
SDValue LowerCallResult(SDValue Chain, SDValue InFlag,
CallingConv::ID CallConv, bool isVarArg,
- const SmallVectorImpl<ISD::InputArg> &Ins,
- SDLoc dl, SelectionDAG &DAG,
- SmallVectorImpl<SDValue> &InVals,
- const SDNode *CallNode, const Type *RetTy) const;
+ const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc dl,
+ SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals,
+ TargetLowering::CallLoweringInfo &CLI) const;
// Lower Operand specifics
SDValue lowerBR_JT(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerSETCC(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerVASTART(SDValue Op, SelectionDAG &DAG) const;
+ SDValue lowerVAARG(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerFABS(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
/// isEligibleForTailCallOptimization - Check whether the call is eligible
/// for tail call optimization.
virtual bool
- isEligibleForTailCallOptimization(const MipsCC &MipsCCInfo,
+ isEligibleForTailCallOptimization(const CCState &CCInfo,
unsigned NextStackOffset,
- const MipsFunctionInfo& FI) const = 0;
+ const MipsFunctionInfo &FI) const = 0;
/// copyByValArg - Copy argument registers which were used to pass a byval
/// argument to the stack. Create a stack frame object for the byval
/// argument.
- void copyByValRegs(SDValue Chain, SDLoc DL,
- std::vector<SDValue> &OutChains, SelectionDAG &DAG,
- const ISD::ArgFlagsTy &Flags,
+ void copyByValRegs(SDValue Chain, SDLoc DL, std::vector<SDValue> &OutChains,
+ SelectionDAG &DAG, const ISD::ArgFlagsTy &Flags,
SmallVectorImpl<SDValue> &InVals,
- const Argument *FuncArg,
- const MipsCC &CC, const ByValArgInfo &ByVal) const;
+ const Argument *FuncArg, unsigned FirstReg,
+ unsigned LastReg, const CCValAssign &VA,
+ MipsCCState &State) const;
/// passByValArg - Pass a byval argument in registers or on stack.
void passByValArg(SDValue Chain, SDLoc DL,
- std::deque< std::pair<unsigned, SDValue> > &RegsToPass,
+ std::deque<std::pair<unsigned, SDValue>> &RegsToPass,
SmallVectorImpl<SDValue> &MemOpChains, SDValue StackPtr,
MachineFrameInfo *MFI, SelectionDAG &DAG, SDValue Arg,
- const MipsCC &CC, const ByValArgInfo &ByVal,
- const ISD::ArgFlagsTy &Flags, bool isLittle) const;
+ unsigned FirstReg, unsigned LastReg,
+ const ISD::ArgFlagsTy &Flags, bool isLittle,
+ const CCValAssign &VA) const;
/// writeVarArgRegs - Write variable function arguments passed in registers
/// to the stack. Also create a stack frame object for the first variable
/// argument.
- void writeVarArgRegs(std::vector<SDValue> &OutChains, const MipsCC &CC,
- SDValue Chain, SDLoc DL, SelectionDAG &DAG) const;
+ void writeVarArgRegs(std::vector<SDValue> &OutChains, SDValue Chain,
+ SDLoc DL, SelectionDAG &DAG, CCState &State) const;
SDValue
LowerFormalArguments(SDValue Chain,
const SmallVectorImpl<SDValue> &OutVals,
SDLoc dl, SelectionDAG &DAG) const override;
+ bool shouldSignExtendTypeInLibCall(EVT Type, bool IsSigned) const override;
+
// Inline asm support
ConstraintType
getConstraintType(const std::string &Constraint) const override;
/// This function parses registers that appear in inline-asm constraints.
/// It returns pair (0, 0) on failure.
std::pair<unsigned, const TargetRegisterClass *>
- parseRegForInlineAsmConstraint(const StringRef &C, MVT VT) const;
+ parseRegForInlineAsmConstraint(StringRef C, MVT VT) const;
- std::pair<unsigned, const TargetRegisterClass*>
- getRegForInlineAsmConstraint(const std::string &Constraint,
- MVT VT) const override;
+ std::pair<unsigned, const TargetRegisterClass *>
+ getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
+ const std::string &Constraint,
+ MVT VT) const override;
/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops
/// vector. If it is invalid, don't add anything to Ops. If hasMemory is
std::vector<SDValue> &Ops,
SelectionDAG &DAG) const override;
+ unsigned getInlineAsmMemConstraint(
+ const std::string &ConstraintCode) const override {
+ if (ConstraintCode == "R")
+ return InlineAsm::Constraint_R;
+ else if (ConstraintCode == "ZC")
+ return InlineAsm::Constraint_ZC;
+ return TargetLowering::getInlineAsmMemConstraint(ConstraintCode);
+ }
+
bool isLegalAddressingMode(const AddrMode &AM, Type *Ty) const override;
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;
unsigned getJumpTableEncoding() const override;
+ /// Emit a sign-extension using sll/sra, seb, or seh appropriately.
+ MachineBasicBlock *emitSignExtendToI32InReg(MachineInstr *MI,
+ MachineBasicBlock *BB,
+ unsigned Size, unsigned DstReg,
+ unsigned SrcRec) const;
+
MachineBasicBlock *emitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB,
unsigned Size, unsigned BinOpcode, bool Nand = false) const;
MachineBasicBlock *emitAtomicBinaryPartword(MachineInstr *MI,
MachineBasicBlock *emitAtomicCmpSwapPartword(MachineInstr *MI,
MachineBasicBlock *BB, unsigned Size) const;
MachineBasicBlock *emitSEL_D(MachineInstr *MI, MachineBasicBlock *BB) const;
+ MachineBasicBlock *emitPseudoSELECT(MachineInstr *MI,
+ MachineBasicBlock *BB, bool isFPCmp,
+ unsigned Opc) const;
};
/// Create MipsTargetLowering objects.
- const MipsTargetLowering *createMips16TargetLowering(MipsTargetMachine &TM);
- const MipsTargetLowering *createMipsSETargetLowering(MipsTargetMachine &TM);
+ const MipsTargetLowering *
+ createMips16TargetLowering(const MipsTargetMachine &TM,
+ const MipsSubtarget &STI);
+ const MipsTargetLowering *
+ createMipsSETargetLowering(const MipsTargetMachine &TM,
+ const MipsSubtarget &STI);
namespace Mips {
FastISel *createFastISel(FunctionLoweringInfo &funcInfo,
}
}
-#endif // MipsISELLOWERING_H
+#endif