| //===-- 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; | |
| } |