//===-- Nios2ISelLowering.cpp - Nios2 DAG Lowering Implementation ---------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements the interfaces that Nios2 uses to lower LLVM code into a // selection DAG. // //===----------------------------------------------------------------------===// #include "Nios2ISelLowering.h" #include "Nios2MachineFunction.h" #include "Nios2TargetMachine.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineRegisterInfo.h" using namespace llvm; //===----------------------------------------------------------------------===// // Calling Convention Implementation //===----------------------------------------------------------------------===// #include "Nios2GenCallingConv.inc" SDValue Nios2TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL, SelectionDAG &DAG) const { // CCValAssign - represent the assignment of // the return value to a location SmallVector<CCValAssign, 16> RVLocs; MachineFunction &MF = DAG.getMachineFunction(); // CCState - Info about the registers and stack slot. CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, *DAG.getContext()); // Analyze return values. CCInfo.CheckReturn(Outs, RetCC_Nios2EABI); SDValue Flag; SmallVector<SDValue, 4> RetOps(1, Chain); // Copy the result values into the output registers. for (unsigned i = 0; i != RVLocs.size(); ++i) { SDValue Val = OutVals[i]; CCValAssign &VA = RVLocs[i]; assert(VA.isRegLoc() && "Can only return in registers!"); if (RVLocs[i].getValVT() != RVLocs[i].getLocVT()) Val = DAG.getNode(ISD::BITCAST, DL, RVLocs[i].getLocVT(), Val); Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Val, Flag); // Guarantee that all emitted copies are stuck together with flags. Flag = Chain.getValue(1); RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); } if (Flag.getNode()) RetOps.push_back(Flag); return DAG.getNode(Nios2ISD::Ret, DL, MVT::Other, RetOps); } // addLiveIn - This helper function adds the specified physical register to the // MachineFunction as a live in value. It also creates a corresponding // virtual register for it. static unsigned addLiveIn(MachineFunction &MF, unsigned PReg, const TargetRegisterClass *RC) { unsigned VReg = MF.getRegInfo().createVirtualRegister(RC); MF.getRegInfo().addLiveIn(PReg, VReg); return VReg; } //===----------------------------------------------------------------------===// // Formal Arguments Calling Convention Implementation //===----------------------------------------------------------------------===// // LowerFormalArguments - transform physical registers into virtual registers // and generate load operations for arguments places on the stack. SDValue Nios2TargetLowering::LowerFormalArguments( SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo &MFI = MF.getFrameInfo(); // Assign locations to all of the incoming arguments. SmallVector<CCValAssign, 16> ArgLocs; CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, *DAG.getContext()); CCInfo.AnalyzeFormalArguments(Ins, CC_Nios2); // Used with vargs to acumulate store chains. std::vector<SDValue> OutChains; for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; EVT ValVT = VA.getValVT(); // Arguments stored on registers if (VA.isRegLoc()) { MVT RegVT = VA.getLocVT(); unsigned ArgReg = VA.getLocReg(); const TargetRegisterClass *RC = getRegClassFor(RegVT); // Transform the arguments stored on // physical registers into virtual ones unsigned Reg = addLiveIn(MF, ArgReg, RC); SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, RegVT); // If this is an 8 or 16-bit value, it has been passed promoted // to 32 bits. Insert an assert[sz]ext to capture this, then // truncate to the right size. if (VA.getLocInfo() != CCValAssign::Full) { unsigned Opcode = 0; if (VA.getLocInfo() == CCValAssign::SExt) Opcode = ISD::AssertSext; else if (VA.getLocInfo() == CCValAssign::ZExt) Opcode = ISD::AssertZext; if (Opcode) ArgValue = DAG.getNode(Opcode, DL, RegVT, ArgValue, DAG.getValueType(ValVT)); ArgValue = DAG.getNode(ISD::TRUNCATE, DL, ValVT, ArgValue); } // Handle floating point arguments passed in integer registers. if ((RegVT == MVT::i32 && ValVT == MVT::f32) || (RegVT == MVT::i64 && ValVT == MVT::f64)) ArgValue = DAG.getNode(ISD::BITCAST, DL, ValVT, ArgValue); InVals.push_back(ArgValue); } else { // VA.isRegLoc() MVT LocVT = VA.getLocVT(); // sanity check assert(VA.isMemLoc()); // The stack pointer offset is relative to the caller stack frame. int FI = MFI.CreateFixedObject(ValVT.getSizeInBits() / 8, VA.getLocMemOffset(), true); // Create load nodes to retrieve arguments from the stack SDValue FIN = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); SDValue Load = DAG.getLoad( LocVT, DL, Chain, FIN, MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI)); InVals.push_back(Load); OutChains.push_back(Load.getValue(1)); } } if (!OutChains.empty()) { OutChains.push_back(Chain); Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains); } return Chain; } //===----------------------------------------------------------------------===// // TargetLowering Implementation //===----------------------------------------------------------------------===// Nios2TargetLowering::Nios2TargetLowering(const TargetMachine &TM, const Nios2Subtarget &STI) : TargetLowering(TM), Subtarget(&STI) { addRegisterClass(MVT::i32, &Nios2::CPURegsRegClass); computeRegisterProperties(Subtarget->getRegisterInfo()); } const char *Nios2TargetLowering::getTargetNodeName(unsigned Opcode) const { switch (Opcode) { case Nios2ISD::Hi: return "Nios2ISD::Hi"; case Nios2ISD::Lo: return "Nios2ISD::Lo"; case Nios2ISD::Ret: return "Nios2ISD::Ret"; } return nullptr; }