SDValue MSP430TargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const { MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); MFI->setReturnAddressIsTaken(true); if (verifyReturnAddressArgumentIsConstant(Op, DAG)) return SDValue(); unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); SDLoc dl(Op); auto PtrVT = getPointerTy(DAG.getDataLayout()); if (Depth > 0) { SDValue FrameAddr = LowerFRAMEADDR(Op, DAG); SDValue Offset = DAG.getConstant(DAG.getDataLayout().getPointerSize(), dl, MVT::i16); return DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), DAG.getNode(ISD::ADD, dl, PtrVT, FrameAddr, Offset), MachinePointerInfo(), false, false, false, 0); } // Just load the return address. SDValue RetAddrFI = getReturnAddressFrameIndex(DAG); return DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), RetAddrFI, MachinePointerInfo(), false, false, false, 0); }
SDValue NvfcTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); MFI->setFrameAddressIsTaken(true); EVT VT = Op.getValueType(); DebugLoc dl = Op.getDebugLoc(); // FIXME probably not meaningful unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, Nvfc::FP, VT); while (Depth--) FrameAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), FrameAddr, NULL, 0, false, false, 0); return FrameAddr; }
SDValue MipsTargetLowering:: LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) { if (!Subtarget->isMips1()) return Op; MachineFunction &MF = DAG.getMachineFunction(); unsigned CCReg = AddLiveIn(MF, Mips::FCR31, Mips::CCRRegisterClass); SDValue Chain = DAG.getEntryNode(); DebugLoc dl = Op.getDebugLoc(); SDValue Src = Op.getOperand(0); // Set the condition register SDValue CondReg = DAG.getCopyFromReg(Chain, dl, CCReg, MVT::i32); CondReg = DAG.getCopyToReg(Chain, dl, Mips::AT, CondReg); CondReg = DAG.getCopyFromReg(CondReg, dl, Mips::AT, MVT::i32); SDValue Cst = DAG.getConstant(3, MVT::i32); SDValue Or = DAG.getNode(ISD::OR, dl, MVT::i32, CondReg, Cst); Cst = DAG.getConstant(2, MVT::i32); SDValue Xor = DAG.getNode(ISD::XOR, dl, MVT::i32, Or, Cst); SDValue InFlag(0, 0); CondReg = DAG.getCopyToReg(Chain, dl, Mips::FCR31, Xor, InFlag); // Emit the round instruction and bit convert to integer SDValue Trunc = DAG.getNode(MipsISD::FPRound, dl, MVT::f32, Src, CondReg.getValue(1)); SDValue BitCvt = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i32, Trunc); return BitCvt; }
static SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) { MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); MFI->setReturnAddressIsTaken(true); EVT VT = Op.getValueType(); DebugLoc dl = Op.getDebugLoc(); unsigned RetReg = SP::I7; uint64_t depth = Op.getConstantOperandVal(0); SDValue RetAddr; if (depth == 0) RetAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, RetReg, VT); else { // flush first to make sure the windowed registers' values are in stack SDValue Chain = getFLUSHW(Op, DAG); RetAddr = DAG.getCopyFromReg(Chain, dl, SP::I6, VT); for (uint64_t i = 0; i != depth; ++i) { SDValue Ptr = DAG.getNode(ISD::ADD, dl, MVT::i32, RetAddr, DAG.getIntPtrConstant((i == depth-1)?60:56)); RetAddr = DAG.getLoad(MVT::i32, dl, Chain, Ptr, MachinePointerInfo(), false, false, 0); } } return RetAddr; }
SDValue Cpu0TargetLowering:: LowerJumpTable(SDValue Op, SelectionDAG &DAG) const { SDValue HiPart, JTI, JTILo; // FIXME there isn't actually debug info here DebugLoc dl = Op.getDebugLoc(); bool IsPIC = getTargetMachine().getRelocationModel() == Reloc::PIC_; EVT PtrVT = Op.getValueType(); JumpTableSDNode *JT = cast<JumpTableSDNode>(Op); if (!IsPIC) { JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, Cpu0II::MO_ABS); HiPart = DAG.getNode(Cpu0ISD::Hi, dl, PtrVT, JTI); JTILo = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, Cpu0II::MO_ABS); } else {// Emit Load from Global Pointer unsigned GOTFlag = Cpu0II::MO_GOT; unsigned OfstFlag = Cpu0II::MO_ABS; JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, GOTFlag); JTI = DAG.getNode(Cpu0ISD::Wrapper, dl, PtrVT, GetGlobalReg(DAG, PtrVT), JTI); HiPart = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), JTI, MachinePointerInfo(), false, false, false, 0); JTILo = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, OfstFlag); } SDValue Lo = DAG.getNode(Cpu0ISD::Lo, dl, PtrVT, JTILo); return DAG.getNode(ISD::ADD, dl, PtrVT, HiPart, Lo); }
SDValue LanaiTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); MFI->setFrameAddressIsTaken(true); EVT VT = Op.getValueType(); SDLoc DL(Op); SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), DL, Lanai::FP, VT); unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); while (Depth--) { const unsigned Offset = -8; SDValue Ptr = DAG.getNode(ISD::ADD, DL, VT, FrameAddr, DAG.getIntPtrConstant(Offset, DL)); FrameAddr = DAG.getLoad(VT, DL, DAG.getEntryNode(), Ptr, MachinePointerInfo(), false, false, false, 0); } return FrameAddr; }
SDValue Cpu0TargetLowering::getAddrGlobal(SDValue Op, SelectionDAG &DAG, unsigned Flag) const { SDLoc DL = SDLoc(Op); EVT Ty = Op.getValueType(); SDValue Tgt = DAG.getNode(Cpu0ISD::Wrapper, DL, Ty, getGlobalReg(DAG, Ty), getTargetNode(Op, DAG, Flag)); return DAG.getLoad(Ty, DL, DAG.getEntryNode(), Tgt, MachinePointerInfo::getGOT(), false, false, false, 0); }
// Global addresses are stored in the per-function constant pool. SDValue VectorProcTargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const { EVT PtrVT = getPointerTy(); DebugLoc dl = Op.getDebugLoc(); const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); SDValue CPIdx = DAG.getTargetConstantPool(GV, MVT::i32); return DAG.getLoad(MVT::i32, dl, DAG.getEntryNode(), CPIdx, MachinePointerInfo::getConstantPool(), false, false, false, 4); }
SDValue AVM2TargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); MFI->setFrameAddressIsTaken(true); EVT VT = Op.getValueType(); DebugLoc dl = Op.getDebugLoc(); // FIXME probably not meaningful assert((cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() == 0) && "only current frame addr supported"); SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, AVM2::EBP, VT); return FrameAddr; }
SDValue Cpu0TargetLowering::getAddrGlobalLargeGOT(SDValue Op, SelectionDAG &DAG, unsigned HiFlag, unsigned LoFlag) const { SDLoc DL = SDLoc(Op); EVT Ty = Op.getValueType(); SDValue Hi = DAG.getNode(Cpu0ISD::Hi, DL, Ty, getTargetNode(Op, DAG, HiFlag)); Hi = DAG.getNode(ISD::ADD, DL, Ty, Hi, getGlobalReg(DAG, Ty)); SDValue Wrapper = DAG.getNode(Cpu0ISD::Wrapper, DL, Ty, Hi, getTargetNode(Op, DAG, LoFlag)); return DAG.getLoad(Ty, DL, DAG.getEntryNode(), Wrapper, MachinePointerInfo::getGOT(), false, false, false, 0); }
SDValue Cpu0TargetLowering::getAddrLocal(SDValue Op, SelectionDAG &DAG) const { SDLoc DL = SDLoc(Op); EVT Ty = Op.getValueType(); unsigned GOTFlag = Cpu0II::MO_GOT; SDValue GOT = DAG.getNode(Cpu0ISD::Wrapper, DL, Ty, getGlobalReg(DAG, Ty), getTargetNode(Op, DAG, GOTFlag)); SDValue Load = DAG.getLoad(Ty, DL, DAG.getEntryNode(), GOT, MachinePointerInfo::getGOT(), false, false, false, 0); unsigned LoFlag = Cpu0II::MO_ABS_LO; SDValue Lo = DAG.getNode(Cpu0ISD::Lo, DL, Ty, getTargetNode(Op, DAG, LoFlag)); return DAG.getNode(ISD::ADD, DL, Ty, Load, Lo); }
SDValue ARCTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { const ARCRegisterInfo &ARI = *Subtarget.getRegisterInfo(); MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo &MFI = MF.getFrameInfo(); MFI.setFrameAddressIsTaken(true); EVT VT = Op.getValueType(); SDLoc dl(Op); assert(cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() == 0 && "Only support lowering frame addr of current frame."); unsigned FrameReg = ARI.getFrameRegister(MF); return DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT); }
SDValue WebAssemblyTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const { SDLoc DL(Op); EVT PtrVT = getPointerTy(DAG.getMachineFunction().getDataLayout()); auto *MFI = DAG.getMachineFunction().getInfo<WebAssemblyFunctionInfo>(); const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); SDValue ArgN = DAG.getCopyFromReg(DAG.getEntryNode(), DL, MFI->getVarargBufferVreg(), PtrVT); return DAG.getStore(Op.getOperand(0), DL, ArgN, Op.getOperand(1), MachinePointerInfo(SV), false, false, 0); }
SDValue Cpu0TargetLowering:: LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { // check the depth assert((cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() == 0) && "Frame address can only be determined for current frame."); MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); MFI->setFrameAddressIsTaken(true); EVT VT = Op.getValueType(); DebugLoc dl = Op.getDebugLoc(); SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, Cpu0::FP, VT); return FrameAddr; }
SDValue NvfcTargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const { MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); MFI->setReturnAddressIsTaken(true); unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); DebugLoc dl = Op.getDebugLoc(); if (Depth > 0) { SDValue FrameAddr = LowerFRAMEADDR(Op, DAG); SDValue Offset = DAG.getConstant(TD->getPointerSize(), MVT::i32); return DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), DAG.getNode(ISD::ADD, dl, getPointerTy(), FrameAddr, Offset), NULL, 0, false, false, 0); } // Just load the return address. SDValue RetAddrFI = getReturnAddressFrameIndex(DAG); return DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), RetAddrFI, NULL, 0, false, false, 0); }
SDValue LanaiTargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const { MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); MFI->setReturnAddressIsTaken(true); EVT VT = Op.getValueType(); SDLoc DL(Op); unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); if (Depth) { SDValue FrameAddr = LowerFRAMEADDR(Op, DAG); const unsigned Offset = -4; SDValue Ptr = DAG.getNode(ISD::ADD, DL, VT, FrameAddr, DAG.getIntPtrConstant(Offset, DL)); return DAG.getLoad(VT, DL, DAG.getEntryNode(), Ptr, MachinePointerInfo(), false, false, false, 0); } // Return the link register, which contains the return address. // Mark it an implicit live-in. unsigned Reg = MF.addLiveIn(TRI->getRARegister(), getRegClassFor(MVT::i32)); return DAG.getCopyFromReg(DAG.getEntryNode(), DL, Reg, VT); }
SDValue WebAssemblyTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { // Non-zero depths are not supported by WebAssembly currently. Use the // legalizer's default expansion, which is to return 0 (what this function is // documented to do). if (Op.getConstantOperandVal(0) > 0) return SDValue(); DAG.getMachineFunction().getFrameInfo()->setFrameAddressIsTaken(true); EVT VT = Op.getValueType(); unsigned FP = Subtarget->getRegisterInfo()->getFrameRegister(DAG.getMachineFunction()); return DAG.getCopyFromReg(DAG.getEntryNode(), SDLoc(Op), FP, VT); }
SDValue WebAssemblyTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const { SDLoc DL(Op); EVT PtrVT = getPointerTy(DAG.getMachineFunction().getDataLayout()); // The incoming non-fixed arguments are placed on the top of the stack, with // natural alignment, at the point of the call, so the base pointer is just // the current frame pointer. DAG.getMachineFunction().getFrameInfo()->setFrameAddressIsTaken(true); unsigned FP = Subtarget->getRegisterInfo()->getFrameRegister(DAG.getMachineFunction()); SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), DL, FP, PtrVT); const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); return DAG.getStore(Op.getOperand(0), DL, FrameAddr, Op.getOperand(1), MachinePointerInfo(SV), false, false, 0); }
SDValue VectorProcTargetLowering::LowerConstant(SDValue Op, SelectionDAG &DAG) const { DebugLoc dl = Op.getDebugLoc(); EVT PtrVT = Op.getValueType(); ConstantSDNode *C = cast<ConstantSDNode>(Op); if (C->getAPIntValue().abs().ult(0x4000)) { // Don't need to convert to constant pool reference. This will fit in // the immediate field of a single instruction, sign extended (15 bits). return SDValue(); } SDValue CPIdx = DAG.getConstantPool(C->getConstantIntValue(), MVT::i32); return DAG.getLoad(MVT::i32, dl, DAG.getEntryNode(), CPIdx, MachinePointerInfo::getConstantPool(), false, false, false, 4); }
SDValue Cpu0TargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const { // FIXME there isn't actually debug info here DebugLoc dl = Op.getDebugLoc(); const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); if (getTargetMachine().getRelocationModel() != Reloc::PIC_) { SDVTList VTs = DAG.getVTList(MVT::i32); Cpu0TargetObjectFile &TLOF = (Cpu0TargetObjectFile&)getObjFileLowering(); // %gp_rel relocation if (TLOF.IsGlobalInSmallSection(GV, getTargetMachine())) { SDValue GA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0, Cpu0II::MO_GPREL); SDValue GPRelNode = DAG.getNode(Cpu0ISD::GPRel, dl, VTs, &GA, 1); SDValue GOT = DAG.getGLOBAL_OFFSET_TABLE(MVT::i32); return DAG.getNode(ISD::ADD, dl, MVT::i32, GOT, GPRelNode); } // %hi/%lo relocation SDValue GAHi = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0, Cpu0II::MO_ABS_HI); SDValue GALo = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, 0, Cpu0II::MO_ABS_LO); SDValue HiPart = DAG.getNode(Cpu0ISD::Hi, dl, VTs, &GAHi, 1); SDValue Lo = DAG.getNode(Cpu0ISD::Lo, dl, MVT::i32, GALo); return DAG.getNode(ISD::ADD, dl, MVT::i32, HiPart, Lo); } EVT ValTy = Op.getValueType(); bool HasGotOfst = (GV->hasInternalLinkage() || (GV->hasLocalLinkage() && !isa<Function>(GV))); unsigned GotFlag = (HasGotOfst ? Cpu0II::MO_GOT : Cpu0II::MO_GOT16); SDValue GA = DAG.getTargetGlobalAddress(GV, dl, ValTy, 0, GotFlag); GA = DAG.getNode(Cpu0ISD::Wrapper, dl, ValTy, GetGlobalReg(DAG, ValTy), GA); SDValue ResNode = DAG.getLoad(ValTy, dl, DAG.getEntryNode(), GA, MachinePointerInfo(), false, false, false, 0); // On functions and global targets not internal linked only // a load from got/GP is necessary for PIC to work. if (!HasGotOfst) return ResNode; SDValue GALo = DAG.getTargetGlobalAddress(GV, dl, ValTy, 0, Cpu0II::MO_ABS_LO); SDValue Lo = DAG.getNode(Cpu0ISD::Lo, dl, ValTy, GALo); return DAG.getNode(ISD::ADD, dl, ValTy, ResNode, Lo); }
SDValue SparcTargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const { const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); // FIXME there isn't really any debug info here DebugLoc dl = Op.getDebugLoc(); SDValue GA = DAG.getTargetGlobalAddress(GV, MVT::i32); SDValue Hi = DAG.getNode(SPISD::Hi, dl, MVT::i32, GA); SDValue Lo = DAG.getNode(SPISD::Lo, dl, MVT::i32, GA); if (getTargetMachine().getRelocationModel() != Reloc::PIC_) return DAG.getNode(ISD::ADD, dl, MVT::i32, Lo, Hi); SDValue GlobalBase = DAG.getNode(SPISD::GLOBAL_BASE_REG, dl, getPointerTy()); SDValue RelAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, Lo, Hi); SDValue AbsAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, GlobalBase, RelAddr); return DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), AbsAddr, NULL, 0, false, false, 0); }
SDValue SparcTargetLowering::LowerConstantPool(SDValue Op, SelectionDAG &DAG) const { ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op); // FIXME there isn't really any debug info here DebugLoc dl = Op.getDebugLoc(); const Constant *C = N->getConstVal(); SDValue CP = DAG.getTargetConstantPool(C, MVT::i32, N->getAlignment()); SDValue Hi = DAG.getNode(SPISD::Hi, dl, MVT::i32, CP); SDValue Lo = DAG.getNode(SPISD::Lo, dl, MVT::i32, CP); if (getTargetMachine().getRelocationModel() != Reloc::PIC_) return DAG.getNode(ISD::ADD, dl, MVT::i32, Lo, Hi); SDValue GlobalBase = DAG.getNode(SPISD::GLOBAL_BASE_REG, dl, getPointerTy()); SDValue RelAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, Lo, Hi); SDValue AbsAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, GlobalBase, RelAddr); return DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), AbsAddr, NULL, 0, false, false, 0); }
SDValue Cpu0TargetLowering:: LowerConstantPool(SDValue Op, SelectionDAG &DAG) const { SDValue ResNode; ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op); const Constant *C = N->getConstVal(); // FIXME there isn't actually debug info here DebugLoc dl = Op.getDebugLoc(); // gp_rel relocation // FIXME: we should reference the constant pool using small data sections, // but the asm printer currently doesn't support this feature without // hacking it. This feature should come soon so we can uncomment the // stuff below. //if (IsInSmallSection(C->getType())) { // SDValue GPRelNode = DAG.getNode(Cpu0ISD::GPRel, MVT::i32, CP); // SDValue GOT = DAG.getGLOBAL_OFFSET_TABLE(MVT::i32); // ResNode = DAG.getNode(ISD::ADD, MVT::i32, GOT, GPRelNode); if (getTargetMachine().getRelocationModel() != Reloc::PIC_) { SDValue CPHi = DAG.getTargetConstantPool(C, MVT::i32, N->getAlignment(), N->getOffset(), Cpu0II::MO_ABS); SDValue ResNode = DAG.getNode(Cpu0ISD::Hi, dl, MVT::i32, CPHi); } else { EVT ValTy = Op.getValueType(); unsigned GOTFlag = Cpu0II::MO_GOT; unsigned OFSTFlag = Cpu0II::MO_ABS; SDValue CP = DAG.getTargetConstantPool(C, ValTy, N->getAlignment(), N->getOffset(), GOTFlag); CP = DAG.getNode(Cpu0ISD::Wrapper, dl, ValTy, GetGlobalReg(DAG, ValTy), CP); SDValue Load = DAG.getLoad(ValTy, dl, DAG.getEntryNode(), CP, MachinePointerInfo::getConstantPool(), false, false, false, 0); SDValue CPLo = DAG.getTargetConstantPool(C, ValTy, N->getAlignment(), N->getOffset(), OFSTFlag); SDValue Lo = DAG.getNode(Cpu0ISD::Lo, dl, ValTy, CPLo); ResNode = DAG.getNode(ISD::ADD, dl, ValTy, Load, Lo); } return ResNode; }
SDValue Cpu0TargetLowering::LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const { const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress(); // FIXME there isn't actually debug info here DebugLoc dl = Op.getDebugLoc(); if (getTargetMachine().getRelocationModel() != Reloc::PIC_) { return DAG.getBlockAddress(BA, MVT::i32, true, Cpu0II::MO_ABS); } EVT ValTy = Op.getValueType(); unsigned GOTFlag = Cpu0II::MO_GOT; unsigned OFSTFlag = Cpu0II::MO_ABS; SDValue BAGOTOffset = DAG.getBlockAddress(BA, ValTy, true, GOTFlag); BAGOTOffset = DAG.getNode(Cpu0ISD::Wrapper, dl, ValTy, GetGlobalReg(DAG, ValTy), BAGOTOffset); SDValue BALOOffset = DAG.getBlockAddress(BA, ValTy, true, OFSTFlag); SDValue Load = DAG.getLoad(ValTy, dl, DAG.getEntryNode(), BAGOTOffset, MachinePointerInfo(), false, false, false, 0); SDValue Lo = DAG.getNode(Cpu0ISD::Lo, dl, ValTy, BALOOffset); return DAG.getNode(ISD::ADD, dl, ValTy, Load, Lo); }
SDValue SystemZTargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) { DebugLoc dl = Op.getDebugLoc(); const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); int64_t Offset = cast<GlobalAddressSDNode>(Op)->getOffset(); bool IsPic = getTargetMachine().getRelocationModel() == Reloc::PIC_; bool ExtraLoadRequired = Subtarget.GVRequiresExtraLoad(GV, getTargetMachine(), false); SDValue Result; if (!IsPic && !ExtraLoadRequired) { Result = DAG.getTargetGlobalAddress(GV, getPointerTy(), Offset); Offset = 0; } else { unsigned char OpFlags = 0; if (ExtraLoadRequired) OpFlags = SystemZII::MO_GOTENT; Result = DAG.getTargetGlobalAddress(GV, getPointerTy(), 0, OpFlags); } Result = DAG.getNode(SystemZISD::PCRelativeWrapper, dl, getPointerTy(), Result); if (ExtraLoadRequired) Result = DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), Result, PseudoSourceValue::getGOT(), 0, false, false, 0); // If there was a non-zero offset that we didn't fold, create an explicit // addition for it. if (Offset != 0) Result = DAG.getNode(ISD::ADD, dl, getPointerTy(), Result, DAG.getConstant(Offset, getPointerTy())); return Result; }
SDValue MipsTargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) { // FIXME there isn't actually debug info here DebugLoc dl = Op.getDebugLoc(); GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); SDValue GA = DAG.getTargetGlobalAddress(GV, MVT::i32); if (getTargetMachine().getRelocationModel() != Reloc::PIC_) { SDVTList VTs = DAG.getVTList(MVT::i32); MipsTargetObjectFile &TLOF = (MipsTargetObjectFile&)getObjFileLowering(); // %gp_rel relocation if (TLOF.IsGlobalInSmallSection(GV, getTargetMachine())) { SDValue GPRelNode = DAG.getNode(MipsISD::GPRel, dl, VTs, &GA, 1); SDValue GOT = DAG.getGLOBAL_OFFSET_TABLE(MVT::i32); return DAG.getNode(ISD::ADD, dl, MVT::i32, GOT, GPRelNode); } // %hi/%lo relocation SDValue HiPart = DAG.getNode(MipsISD::Hi, dl, VTs, &GA, 1); SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, GA); return DAG.getNode(ISD::ADD, dl, MVT::i32, HiPart, Lo); } else { // Abicall relocations, TODO: make this cleaner. SDValue ResNode = DAG.getLoad(MVT::i32, dl, DAG.getEntryNode(), GA, NULL, 0); // On functions and global targets not internal linked only // a load from got/GP is necessary for PIC to work. if (!GV->hasLocalLinkage() || isa<Function>(GV)) return ResNode; SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, GA); return DAG.getNode(ISD::ADD, dl, MVT::i32, ResNode, Lo); } llvm_unreachable("Dont know how to handle GlobalAddress"); return SDValue(0,0); }
SDValue MipsTargetLowering:: LowerJumpTable(SDValue Op, SelectionDAG &DAG) { SDValue ResNode; SDValue HiPart; // FIXME there isn't actually debug info here DebugLoc dl = Op.getDebugLoc(); EVT PtrVT = Op.getValueType(); JumpTableSDNode *JT = cast<JumpTableSDNode>(Op); SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT); if (getTargetMachine().getRelocationModel() != Reloc::PIC_) { SDVTList VTs = DAG.getVTList(MVT::i32); SDValue Ops[] = { JTI }; HiPart = DAG.getNode(MipsISD::Hi, dl, VTs, Ops, 1); } else // Emit Load from Global Pointer HiPart = DAG.getLoad(MVT::i32, dl, DAG.getEntryNode(), JTI, NULL, 0); SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, JTI); ResNode = DAG.getNode(ISD::ADD, dl, MVT::i32, HiPart, Lo); return ResNode; }
static SDValue PerformDivRemCombine(SDNode *N, SelectionDAG& DAG, TargetLowering::DAGCombinerInfo &DCI, const Cpu0Subtarget* Subtarget) { if (DCI.isBeforeLegalizeOps()) return SDValue(); EVT Ty = N->getValueType(0); unsigned LO = Cpu0::LO; unsigned HI = Cpu0::HI; unsigned opc = N->getOpcode() == ISD::SDIVREM ? Cpu0ISD::DivRem : Cpu0ISD::DivRemU; SDLoc DL(N); SDValue DivRem = DAG.getNode(opc, DL, MVT::Glue, N->getOperand(0), N->getOperand(1)); SDValue InChain = DAG.getEntryNode(); SDValue InGlue = DivRem; // insert MFLO if (N->hasAnyUseOfValue(0)) { SDValue CopyFromLo = DAG.getCopyFromReg(InChain, DL, LO, Ty, InGlue); DAG.ReplaceAllUsesOfValueWith(SDValue(N, 0), CopyFromLo); InChain = CopyFromLo.getValue(1); InGlue = CopyFromLo.getValue(2); } // insert MFHI if (N->hasAnyUseOfValue(1)) { SDValue CopyFromHi = DAG.getCopyFromReg(InChain, DL, HI, Ty, InGlue); DAG.ReplaceAllUsesOfValueWith(SDValue(N, 1), CopyFromHi); } return SDValue(); }
SDValue MSP430TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const { SDValue LHS = Op.getOperand(0); SDValue RHS = Op.getOperand(1); DebugLoc dl = Op.getDebugLoc(); // If we are doing an AND and testing against zero, then the CMP // will not be generated. The AND (or BIT) will generate the condition codes, // but they are different from CMP. // FIXME: since we're doing a post-processing, use a pseudoinstr here, so // lowering & isel wouldn't diverge. bool andCC = false; if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(RHS)) { if (RHSC->isNullValue() && LHS.hasOneUse() && (LHS.getOpcode() == ISD::AND || (LHS.getOpcode() == ISD::TRUNCATE && LHS.getOperand(0).getOpcode() == ISD::AND))) { andCC = true; } } ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get(); SDValue TargetCC; SDValue Flag = EmitCMP(LHS, RHS, TargetCC, CC, dl, DAG); // Get the condition codes directly from the status register, if its easy. // Otherwise a branch will be generated. Note that the AND and BIT // instructions generate different flags than CMP, the carry bit can be used // for NE/EQ. bool Invert = false; bool Shift = false; bool Convert = true; switch (cast<ConstantSDNode>(TargetCC)->getZExtValue()) { default: Convert = false; break; case MSP430CC::COND_HS: // Res = SRW & 1, no processing is required break; case MSP430CC::COND_LO: // Res = ~(SRW & 1) Invert = true; break; case MSP430CC::COND_NE: if (andCC) { // C = ~Z, thus Res = SRW & 1, no processing is required } else { // Res = ~((SRW >> 1) & 1) Shift = true; Invert = true; } break; case MSP430CC::COND_E: Shift = true; // C = ~Z for AND instruction, thus we can put Res = ~(SRW & 1), however, // Res = (SRW >> 1) & 1 is 1 word shorter. break; } EVT VT = Op.getValueType(); SDValue One = DAG.getConstant(1, VT); if (Convert) { SDValue SR = DAG.getCopyFromReg(DAG.getEntryNode(), dl, MSP430::SRW, MVT::i16, Flag); if (Shift) // FIXME: somewhere this is turned into a SRL, lower it MSP specific? SR = DAG.getNode(ISD::SRA, dl, MVT::i16, SR, One); SR = DAG.getNode(ISD::AND, dl, MVT::i16, SR, One); if (Invert) SR = DAG.getNode(ISD::XOR, dl, MVT::i16, SR, One); return SR; } else { SDValue Zero = DAG.getConstant(0, VT); SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Glue); SmallVector<SDValue, 4> Ops; Ops.push_back(One); Ops.push_back(Zero); Ops.push_back(TargetCC); Ops.push_back(Flag); return DAG.getNode(MSP430ISD::SELECT_CC, dl, VTs, &Ops[0], Ops.size()); } }
SDValue Cpu0TargetLowering::LowerCall(SDValue InChain, SDValue Callee, CallingConv::ID CallConv, bool isVarArg, bool doesNotRet, bool &isTailCall, const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, const SmallVectorImpl<ISD::InputArg> &Ins, DebugLoc dl, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { #if 1 // Cpu0 target does not yet support tail call optimization. isTailCall = false; MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); const TargetFrameLowering *TFL = MF.getTarget().getFrameLowering(); bool IsPIC = getTargetMachine().getRelocationModel() == Reloc::PIC_; Cpu0FunctionInfo *Cpu0FI = MF.getInfo<Cpu0FunctionInfo>(); // Analyze operands of the call, assigning locations to each operand. SmallVector<CCValAssign, 16> ArgLocs; CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), getTargetMachine(), ArgLocs, *DAG.getContext()); CCInfo.AnalyzeCallOperands(Outs, CC_Cpu0); // Get a count of how many bytes are to be pushed on the stack. unsigned NextStackOffset = CCInfo.getNextStackOffset(); // Chain is the output chain of the last Load/Store or CopyToReg node. // ByValChain is the output chain of the last Memcpy node created for copying // byval arguments to the stack. SDValue Chain, CallSeqStart, ByValChain; SDValue NextStackOffsetVal = DAG.getIntPtrConstant(NextStackOffset, true); Chain = CallSeqStart = DAG.getCALLSEQ_START(InChain, NextStackOffsetVal); ByValChain = InChain; #if 0 // If this is the first call, create a stack frame object that points to // a location to which .cprestore saves $gp. if (IsO32 && IsPIC && Cpu0FI->globalBaseRegFixed() && !Cpu0FI->getGPFI()) Cpu0FI->setGPFI(MFI->CreateFixedObject(4, 0, true)); #endif // Get the frame index of the stack frame object that points to the location // of dynamically allocated area on the stack. int DynAllocFI = Cpu0FI->getDynAllocFI(); #if 0 // Update size of the maximum argument space. // For O32, a minimum of four words (16 bytes) of argument space is // allocated. if (IsO32) NextStackOffset = std::max(NextStackOffset, (unsigned)16); #endif unsigned MaxCallFrameSize = Cpu0FI->getMaxCallFrameSize(); if (MaxCallFrameSize < NextStackOffset) { Cpu0FI->setMaxCallFrameSize(NextStackOffset); // Set the offsets relative to $sp of the $gp restore slot and dynamically // allocated stack space. These offsets must be aligned to a boundary // determined by the stack alignment of the ABI. unsigned StackAlignment = TFL->getStackAlignment(); NextStackOffset = (NextStackOffset + StackAlignment - 1) / StackAlignment * StackAlignment; if (Cpu0FI->needGPSaveRestore()) MFI->setObjectOffset(Cpu0FI->getGPFI(), NextStackOffset); MFI->setObjectOffset(DynAllocFI, NextStackOffset); } // With EABI is it possible to have 16 args on registers. SmallVector<std::pair<unsigned, SDValue>, 16> RegsToPass; SmallVector<SDValue, 8> MemOpChains; int FirstFI = -MFI->getNumFixedObjects() - 1, LastFI = 0; // Walk the register/memloc assignments, inserting copies/loads. for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { SDValue Arg = OutVals[i]; CCValAssign &VA = ArgLocs[i]; MVT ValVT = VA.getValVT(), LocVT = VA.getLocVT(); ISD::ArgFlagsTy Flags = Outs[i].Flags; // ByVal Arg. if (Flags.isByVal()) { assert(Flags.getByValSize() && "ByVal args of size 0 should have been ignored by front-end."); #if 0 if (IsO32) WriteByValArg(ByValChain, Chain, dl, RegsToPass, MemOpChains, LastFI, MFI, DAG, Arg, VA, Flags, getPointerTy(), Subtarget->isLittle()); #endif #if 0 else PassByValArg64(ByValChain, Chain, dl, RegsToPass, MemOpChains, LastFI, MFI, DAG, Arg, VA, Flags, getPointerTy(), Subtarget->isLittle()); #endif continue; } // Promote the value if needed. switch (VA.getLocInfo()) { default: llvm_unreachable("Unknown loc info!"); case CCValAssign::Full: #if 0 if (VA.isRegLoc()) { if ((ValVT == MVT::f32 && LocVT == MVT::i32) || (ValVT == MVT::f64 && LocVT == MVT::i64)) Arg = DAG.getNode(ISD::BITCAST, dl, LocVT, Arg); else if (ValVT == MVT::f64 && LocVT == MVT::i32) { SDValue Lo = DAG.getNode(Cpu0ISD::ExtractElementF64, dl, MVT::i32, Arg, DAG.getConstant(0, MVT::i32)); SDValue Hi = DAG.getNode(Cpu0ISD::ExtractElementF64, dl, MVT::i32, Arg, DAG.getConstant(1, MVT::i32)); if (!Subtarget->isLittle()) std::swap(Lo, Hi); unsigned LocRegLo = VA.getLocReg(); unsigned LocRegHigh = getNextIntArgReg(LocRegLo); RegsToPass.push_back(std::make_pair(LocRegLo, Lo)); RegsToPass.push_back(std::make_pair(LocRegHigh, Hi)); continue; } } #else assert("CCValAssign::Full:"); // Gamma debug #endif break; case CCValAssign::SExt: Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, LocVT, Arg); break; case CCValAssign::ZExt: Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, LocVT, Arg); break; case CCValAssign::AExt: Arg = DAG.getNode(ISD::ANY_EXTEND, dl, LocVT, Arg); break; } // Arguments that can be passed on register must be kept at // RegsToPass vector if (VA.isRegLoc()) { RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); continue; } // Register can't get to this point... assert(VA.isMemLoc()); // Create the frame index object for this incoming parameter LastFI = MFI->CreateFixedObject(ValVT.getSizeInBits()/8, VA.getLocMemOffset(), true); SDValue PtrOff = DAG.getFrameIndex(LastFI, getPointerTy()); // emit ISD::STORE whichs stores the // parameter value to a stack Location MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo(), false, false, 0)); } // Extend range of indices of frame objects for outgoing arguments that were // created during this function call. Skip this step if no such objects were // created. if (LastFI) Cpu0FI->extendOutArgFIRange(FirstFI, LastFI); // If a memcpy has been created to copy a byval arg to a stack, replace the // chain input of CallSeqStart with ByValChain. if (InChain != ByValChain) DAG.UpdateNodeOperands(CallSeqStart.getNode(), ByValChain, NextStackOffsetVal); // Transform all store nodes into one single node because all store // nodes are independent of each other. if (!MemOpChains.empty()) Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &MemOpChains[0], MemOpChains.size()); // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol // node so that legalize doesn't hack it. unsigned char OpFlag; #if 0 // cpu0 int 32 only bool IsPICCall = (IsN64 || IsPIC); // true if calls are translated to jalr $25 #else bool IsPICCall = IsPIC; // true if calls are translated to jalr $25 #endif bool GlobalOrExternal = false; SDValue CalleeLo; if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) { if (IsPICCall && G->getGlobal()->hasInternalLinkage()) { OpFlag = Cpu0II::MO_GOT; #if 0 unsigned char LoFlag = IsO32 ? Cpu0II::MO_ABS_LO : Cpu0II::MO_GOT_OFST; #else unsigned char LoFlag = Cpu0II::MO_ABS_LO; #endif Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, getPointerTy(), 0, OpFlag); CalleeLo = DAG.getTargetGlobalAddress(G->getGlobal(), dl, getPointerTy(), 0, LoFlag); } else { OpFlag = IsPICCall ? Cpu0II::MO_GOT_CALL : Cpu0II::MO_NO_FLAG; Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, getPointerTy(), 0, OpFlag); } GlobalOrExternal = true; } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) { if (!IsPIC) // static OpFlag = Cpu0II::MO_NO_FLAG; else // O32 & PIC OpFlag = Cpu0II::MO_GOT_CALL; Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy(), OpFlag); GlobalOrExternal = true; } SDValue InFlag; // Create nodes that load address of callee and copy it to T9 if (IsPICCall) { if (GlobalOrExternal) { // Load callee address Callee = DAG.getNode(Cpu0ISD::Wrapper, dl, getPointerTy(), GetGlobalReg(DAG, getPointerTy()), Callee); SDValue LoadValue = DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), Callee, MachinePointerInfo::getGOT(), false, false, false, 0); // Use GOT+LO if callee has internal linkage. if (CalleeLo.getNode()) { SDValue Lo = DAG.getNode(Cpu0ISD::Lo, dl, getPointerTy(), CalleeLo); Callee = DAG.getNode(ISD::ADD, dl, getPointerTy(), LoadValue, Lo); } else Callee = LoadValue; } } // T9 should contain the address of the callee function if // -reloction-model=pic or it is an indirect call. if (IsPICCall || !GlobalOrExternal) { // copy to T9 unsigned T9Reg = Cpu0::T9; Chain = DAG.getCopyToReg(Chain, dl, T9Reg, Callee, SDValue(0, 0)); InFlag = Chain.getValue(1); Callee = DAG.getRegister(T9Reg, getPointerTy()); } // Build a sequence of copy-to-reg nodes chained together with token // chain and flag operands which copy the outgoing args into registers. // The InFlag in necessary since all emitted instructions must be // stuck together. for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, RegsToPass[i].second, InFlag); InFlag = Chain.getValue(1); } // Cpu0JmpLink = #chain, #target_address, #opt_in_flags... // = Chain, Callee, Reg#1, Reg#2, ... // // Returns a chain & a flag for retval copy to use. SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); SmallVector<SDValue, 8> Ops; Ops.push_back(Chain); Ops.push_back(Callee); // Add argument registers to the end of the list so that they are // known live into the call. for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) Ops.push_back(DAG.getRegister(RegsToPass[i].first, RegsToPass[i].second.getValueType())); // Add a register mask operand representing the call-preserved registers. const TargetRegisterInfo *TRI = getTargetMachine().getRegisterInfo(); const uint32_t *Mask = TRI->getCallPreservedMask(CallConv); assert(Mask && "Missing call preserved mask for calling convention"); Ops.push_back(DAG.getRegisterMask(Mask)); if (InFlag.getNode()) Ops.push_back(InFlag); Chain = DAG.getNode(Cpu0ISD::JmpLink, dl, NodeTys, &Ops[0], Ops.size()); InFlag = Chain.getValue(1); // Create the CALLSEQ_END node. Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NextStackOffset, true), DAG.getIntPtrConstant(0, true), InFlag); InFlag = Chain.getValue(1); // Handle result values, copying them out of physregs into vregs that we // return. return LowerCallResult(Chain, InFlag, CallConv, isVarArg, Ins, dl, DAG, InVals); #else return InChain; #endif }