forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			189 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			189 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C++
		
	
	
	
//===-- 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;
 | 
						|
}
 |