2017-12-07 20:35:02 +08:00
|
|
|
//===-- 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 {
|
2018-01-09 19:15:08 +08:00
|
|
|
// CCValAssign - represent the assignment of
|
|
|
|
// the return value to a location
|
|
|
|
SmallVector<CCValAssign, 16> RVLocs;
|
|
|
|
MachineFunction &MF = DAG.getMachineFunction();
|
2017-12-07 20:35:02 +08:00
|
|
|
|
2018-01-09 19:15:08 +08:00
|
|
|
// 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;
|
2017-12-07 20:35:02 +08:00
|
|
|
SmallVector<SDValue, 4> RetOps(1, Chain);
|
|
|
|
|
2018-01-09 19:15:08 +08:00
|
|
|
// 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);
|
|
|
|
|
2017-12-07 20:35:02 +08:00
|
|
|
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;
|
|
|
|
}
|