//===-- M68kISelLowering.h - M68k DAG Lowering Interface --------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// /// \file /// This file defines the interfaces that M68k uses to lower LLVM code into a /// selection DAG. /// //===----------------------------------------------------------------------===// #ifndef LLVM_LIB_TARGET_M68K_M68KISELLOWERING_H #define LLVM_LIB_TARGET_M68K_M68KISELLOWERING_H #include "M68k.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/TargetLowering.h" #include "llvm/IR/Function.h" #include namespace llvm { namespace M68kISD { /// M68k Specific DAG nodes enum NodeType { /// Start the numbering from where ISD NodeType finishes. FIRST_NUMBER = ISD::BUILTIN_OP_END, CALL, RET, TAIL_CALL, TC_RETURN, /// M68k compare and logical compare instructions. Subtracts the source /// operand from the destination data register and sets the condition /// codes according to the result. Immediate always goes first. CMP, /// M68k bit-test instructions. BTST, /// M68k Select SELECT, /// M68k SetCC. Operand 0 is condition code, and operand 1 is the CCR /// operand, usually produced by a CMP instruction. SETCC, // Same as SETCC except it's materialized with a subx and the value is all // one's or all zero's. SETCC_CARRY, // R = carry_bit ? ~0 : 0 /// M68k conditional moves. Operand 0 and operand 1 are the two values /// to select from. Operand 2 is the condition code, and operand 3 is the /// flag operand produced by a CMP or TEST instruction. It also writes a /// flag result. CMOV, /// M68k conditional branches. Operand 0 is the chain operand, operand 1 /// is the block to branch if condition is true, operand 2 is the /// condition code, and operand 3 is the flag operand produced by a CMP /// or TEST instruction. BRCOND, // Arithmetic operations with CCR results. ADD, SUB, ADDX, SUBX, SMUL, UMUL, OR, XOR, AND, // GlobalBaseReg, GLOBAL_BASE_REG, /// A wrapper node for TargetConstantPool, /// TargetExternalSymbol, and TargetGlobalAddress. Wrapper, /// Special wrapper used under M68k PIC mode for PC /// relative displacements. WrapperPC, // For allocating variable amounts of stack space when using // segmented stacks. Check if the current stacklet has enough space, and // falls back to heap allocation if not. SEG_ALLOCA, }; } // namespace M68kISD /// Define some predicates that are used for node matching. namespace M68k { /// Determines whether the callee is required to pop its /// own arguments. Callee pop is necessary to support tail calls. bool isCalleePop(CallingConv::ID CallingConv, bool IsVarArg, bool GuaranteeTCO); } // end namespace M68k //===--------------------------------------------------------------------===// // TargetLowering Implementation //===--------------------------------------------------------------------===// class M68kMachineFunctionInfo; class M68kSubtarget; class M68kTargetLowering : public TargetLowering { const M68kSubtarget &Subtarget; const M68kTargetMachine &TM; public: explicit M68kTargetLowering(const M68kTargetMachine &TM, const M68kSubtarget &STI); static const M68kTargetLowering *create(const M68kTargetMachine &TM, const M68kSubtarget &STI); const char *getTargetNodeName(unsigned Opcode) const override; /// Return the value type to use for ISD::SETCC. EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const override; /// EVT is not used in-tree, but is used by out-of-tree target. virtual MVT getScalarShiftAmountTy(const DataLayout &, EVT) const override; /// Provide custom lowering hooks for some operations. SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; /// Return the entry encoding for a jump table in the current function. /// The returned value is a member of the MachineJumpTableInfo::JTEntryKind /// enum. unsigned getJumpTableEncoding() const override; const MCExpr *LowerCustomJumpTableEntry(const MachineJumpTableInfo *MJTI, const MachineBasicBlock *MBB, unsigned uid, MCContext &Ctx) const override; /// Returns relocation base for the given PIC jumptable. SDValue getPICJumpTableRelocBase(SDValue Table, SelectionDAG &DAG) const override; /// This returns the relocation base for the given PIC jumptable, /// the same as getPICJumpTableRelocBase, but as an MCExpr. const MCExpr *getPICJumpTableRelocBaseExpr(const MachineFunction *MF, unsigned JTI, MCContext &Ctx) const override; ConstraintType getConstraintType(StringRef ConstraintStr) const override; std::pair getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override; // Lower operand with C_Immediate and C_Other constraint type void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint, std::vector &Ops, SelectionDAG &DAG) const override; MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const override; CCAssignFn *getCCAssignFn(CallingConv::ID CC, bool Return, bool IsVarArg) const; AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *RMW) const override; /// If a physical register, this returns the register that receives the /// exception address on entry to an EH pad. Register getExceptionPointerRegister(const Constant *PersonalityFn) const override; /// If a physical register, this returns the register that receives the /// exception typeid on entry to a landing pad. Register getExceptionSelectorRegister(const Constant *PersonalityFn) const override; InlineAsm::ConstraintCode getInlineAsmMemConstraint(StringRef ConstraintCode) const override; private: unsigned GetAlignedArgumentStackSize(unsigned StackSize, SelectionDAG &DAG) const; bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override { // In many cases, `GA` doesn't give the correct offset to fold. It's // hard to know if the real offset actually fits into the displacement // of the perspective addressing mode. // Thus, we disable offset folding altogether and leave that to ISel // patterns. return false; } SDValue getReturnAddressFrameIndex(SelectionDAG &DAG) const; /// Emit a load of return address if tail call /// optimization is performed and it is required. SDValue EmitTailCallLoadRetAddr(SelectionDAG &DAG, SDValue &OutRetAddr, SDValue Chain, bool IsTailCall, int FPDiff, const SDLoc &DL) const; /// Emit a store of the return address if tail call /// optimization is performed and it is required (FPDiff!=0). SDValue EmitTailCallStoreRetAddr(SelectionDAG &DAG, MachineFunction &MF, SDValue Chain, SDValue RetAddrFrIdx, EVT PtrVT, unsigned SlotSize, int FPDiff, const SDLoc &DL) const; SDValue LowerMemArgument(SDValue Chain, CallingConv::ID CallConv, const SmallVectorImpl &ArgInfo, const SDLoc &DL, SelectionDAG &DAG, const CCValAssign &VA, MachineFrameInfo &MFI, unsigned ArgIdx) const; SDValue LowerMemOpCallTo(SDValue Chain, SDValue StackPtr, SDValue Arg, const SDLoc &DL, SelectionDAG &DAG, const CCValAssign &VA, ISD::ArgFlagsTy Flags) const; SDValue LowerXALUO(SDValue Op, SelectionDAG &DAG) const; SDValue LowerToBTST(SDValue And, ISD::CondCode CC, const SDLoc &DL, SelectionDAG &DAG) const; SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const; SDValue LowerSETCCCARRY(SDValue Op, SelectionDAG &DAG) const; SDValue LowerSELECT(SDValue Op, SelectionDAG &DAG) const; SDValue LowerBRCOND(SDValue Op, SelectionDAG &DAG) const; SDValue LowerADDC_ADDE_SUBC_SUBE(SDValue Op, SelectionDAG &DAG) const; SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const; SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) const; SDValue LowerExternalSymbol(SDValue Op, SelectionDAG &DAG) const; SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const; SDValue LowerGlobalAddress(const GlobalValue *GV, const SDLoc &DL, int64_t Offset, SelectionDAG &DAG) const; SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const; SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const; SDValue LowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const; SDValue LowerShiftRightParts(SDValue Op, SelectionDAG &DAG, bool IsSRA) const; SDValue LowerATOMICFENCE(SDValue Op, SelectionDAG &DAG) const; SDValue LowerCallResult(SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl &InVals) const; SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const; /// LowerFormalArguments - transform physical registers into virtual /// registers and generate load operations for arguments places on the stack. SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CCID, bool IsVarArg, const SmallVectorImpl &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl &InVals) const override; SDValue LowerCall(CallLoweringInfo &CLI, SmallVectorImpl &InVals) const override; bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg, const SmallVectorImpl &Outs, LLVMContext &Context) const override; /// Lower the result values of a call into the /// appropriate copies out of appropriate physical registers. SDValue LowerReturn(SDValue Chain, CallingConv::ID CCID, bool IsVarArg, const SmallVectorImpl &Outs, const SmallVectorImpl &OutVals, const SDLoc &DL, SelectionDAG &DAG) const override; SDValue LowerExternalSymbolCall(SelectionDAG &DAG, SDLoc loc, llvm::StringRef SymbolName, ArgListTy &&ArgList) const; SDValue getTLSGetAddr(GlobalAddressSDNode *GA, SelectionDAG &DAG, unsigned TargetFlags) const; SDValue getM68kReadTp(SDLoc Loc, SelectionDAG &DAG) const; SDValue LowerTLSGeneralDynamic(GlobalAddressSDNode *GA, SelectionDAG &DAG) const; SDValue LowerTLSLocalDynamic(GlobalAddressSDNode *GA, SelectionDAG &DAG) const; SDValue LowerTLSInitialExec(GlobalAddressSDNode *GA, SelectionDAG &DAG) const; SDValue LowerTLSLocalExec(GlobalAddressSDNode *GA, SelectionDAG &DAG) const; bool decomposeMulByConstant(LLVMContext &Context, EVT VT, SDValue C) const override; MachineBasicBlock *EmitLoweredSelect(MachineInstr &I, MachineBasicBlock *MBB) const; MachineBasicBlock *EmitLoweredSegAlloca(MachineInstr &MI, MachineBasicBlock *BB) const; /// Emit nodes that will be selected as "test Op0,Op0", or something /// equivalent, for use with the given M68k condition code. SDValue EmitTest(SDValue Op0, unsigned M68kCC, const SDLoc &dl, SelectionDAG &DAG) const; /// Emit nodes that will be selected as "cmp Op0,Op1", or something /// equivalent, for use with the given M68k condition code. SDValue EmitCmp(SDValue Op0, SDValue Op1, unsigned M68kCC, const SDLoc &dl, SelectionDAG &DAG) const; /// Check whether the call is eligible for tail call optimization. Targets /// that want to do tail call optimization should implement this function. bool IsEligibleForTailCallOptimization( SDValue Callee, CallingConv::ID CalleeCC, bool IsVarArg, bool IsCalleeStructRet, bool IsCallerStructRet, Type *RetTy, const SmallVectorImpl &Outs, const SmallVectorImpl &OutVals, const SmallVectorImpl &Ins, SelectionDAG &DAG) const; SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override; }; } // namespace llvm #endif // LLVM_LIB_TARGET_M68K_M68KISELLOWERING_H