2017-10-20 05:37:38 +08:00
|
|
|
//===-- RISCVISelLowering.cpp - RISCV 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 defines the interfaces that RISCV uses to lower LLVM code into a
|
|
|
|
// selection DAG.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "RISCVISelLowering.h"
|
|
|
|
#include "RISCV.h"
|
|
|
|
#include "RISCVRegisterInfo.h"
|
|
|
|
#include "RISCVSubtarget.h"
|
|
|
|
#include "RISCVTargetMachine.h"
|
|
|
|
#include "llvm/CodeGen/CallingConvLower.h"
|
|
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
|
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
|
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
|
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
|
|
|
#include "llvm/CodeGen/SelectionDAGISel.h"
|
|
|
|
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
|
|
|
|
#include "llvm/CodeGen/ValueTypes.h"
|
|
|
|
#include "llvm/IR/DiagnosticInfo.h"
|
|
|
|
#include "llvm/IR/DiagnosticPrinter.h"
|
|
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
#define DEBUG_TYPE "riscv-lower"
|
|
|
|
|
|
|
|
RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
|
|
|
|
const RISCVSubtarget &STI)
|
|
|
|
: TargetLowering(TM), Subtarget(STI) {
|
|
|
|
|
|
|
|
MVT XLenVT = Subtarget.getXLenVT();
|
|
|
|
|
|
|
|
// Set up the register classes.
|
|
|
|
addRegisterClass(XLenVT, &RISCV::GPRRegClass);
|
|
|
|
|
|
|
|
// Compute derived properties from the register classes.
|
|
|
|
computeRegisterProperties(STI.getRegisterInfo());
|
|
|
|
|
|
|
|
setStackPointerRegisterToSaveRestore(RISCV::X2);
|
|
|
|
|
2017-11-08 20:20:01 +08:00
|
|
|
for (auto N : {ISD::EXTLOAD, ISD::SEXTLOAD, ISD::ZEXTLOAD})
|
|
|
|
setLoadExtAction(N, XLenVT, MVT::i1, Promote);
|
|
|
|
|
2017-10-20 05:37:38 +08:00
|
|
|
// TODO: add all necessary setOperationAction calls.
|
|
|
|
|
|
|
|
setBooleanContents(ZeroOrOneBooleanContent);
|
|
|
|
|
|
|
|
// Function alignments (log2).
|
|
|
|
setMinFunctionAlignment(3);
|
|
|
|
setPrefFunctionAlignment(3);
|
|
|
|
}
|
|
|
|
|
|
|
|
SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
|
|
|
|
SelectionDAG &DAG) const {
|
|
|
|
switch (Op.getOpcode()) {
|
|
|
|
default:
|
|
|
|
report_fatal_error("unimplemented operand");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Calling Convention Implementation.
|
|
|
|
#include "RISCVGenCallingConv.inc"
|
|
|
|
|
|
|
|
// Transform physical registers into virtual registers.
|
|
|
|
SDValue RISCVTargetLowering::LowerFormalArguments(
|
|
|
|
SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
|
|
|
|
const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
|
|
|
|
SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
|
|
|
|
|
|
|
|
switch (CallConv) {
|
|
|
|
default:
|
|
|
|
report_fatal_error("Unsupported calling convention");
|
|
|
|
case CallingConv::C:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
MachineFunction &MF = DAG.getMachineFunction();
|
|
|
|
MachineRegisterInfo &RegInfo = MF.getRegInfo();
|
|
|
|
MVT XLenVT = Subtarget.getXLenVT();
|
|
|
|
|
|
|
|
if (IsVarArg)
|
|
|
|
report_fatal_error("VarArg not supported");
|
|
|
|
|
|
|
|
// Assign locations to all of the incoming arguments.
|
|
|
|
SmallVector<CCValAssign, 16> ArgLocs;
|
|
|
|
CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
|
|
|
|
CCInfo.AnalyzeFormalArguments(Ins, CC_RISCV32);
|
|
|
|
|
|
|
|
for (auto &VA : ArgLocs) {
|
|
|
|
if (!VA.isRegLoc())
|
|
|
|
report_fatal_error("Defined with too many args");
|
|
|
|
|
|
|
|
// Arguments passed in registers.
|
|
|
|
EVT RegVT = VA.getLocVT();
|
|
|
|
if (RegVT != XLenVT) {
|
|
|
|
DEBUG(dbgs() << "LowerFormalArguments Unhandled argument type: "
|
|
|
|
<< RegVT.getEVTString() << "\n");
|
|
|
|
report_fatal_error("unhandled argument type");
|
|
|
|
}
|
|
|
|
const unsigned VReg =
|
|
|
|
RegInfo.createVirtualRegister(&RISCV::GPRRegClass);
|
|
|
|
RegInfo.addLiveIn(VA.getLocReg(), VReg);
|
|
|
|
SDValue ArgIn = DAG.getCopyFromReg(Chain, DL, VReg, RegVT);
|
|
|
|
|
|
|
|
InVals.push_back(ArgIn);
|
|
|
|
}
|
|
|
|
return Chain;
|
|
|
|
}
|
|
|
|
|
|
|
|
SDValue
|
|
|
|
RISCVTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
|
|
|
|
bool IsVarArg,
|
|
|
|
const SmallVectorImpl<ISD::OutputArg> &Outs,
|
|
|
|
const SmallVectorImpl<SDValue> &OutVals,
|
|
|
|
const SDLoc &DL, SelectionDAG &DAG) const {
|
|
|
|
if (IsVarArg) {
|
|
|
|
report_fatal_error("VarArg not supported");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Stores the assignment of the return value to a location.
|
|
|
|
SmallVector<CCValAssign, 16> RVLocs;
|
|
|
|
|
|
|
|
// Info about the registers and stack slot.
|
|
|
|
CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
|
|
|
|
*DAG.getContext());
|
|
|
|
|
|
|
|
CCInfo.AnalyzeReturn(Outs, RetCC_RISCV32);
|
|
|
|
|
|
|
|
SDValue Flag;
|
|
|
|
SmallVector<SDValue, 4> RetOps(1, Chain);
|
|
|
|
|
|
|
|
// Copy the result values into the output registers.
|
|
|
|
for (unsigned i = 0, e = RVLocs.size(); i < e; ++i) {
|
|
|
|
CCValAssign &VA = RVLocs[i];
|
|
|
|
assert(VA.isRegLoc() && "Can only return in registers!");
|
|
|
|
|
|
|
|
Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVals[i], Flag);
|
|
|
|
|
|
|
|
// Guarantee that all emitted copies are stuck together.
|
|
|
|
Flag = Chain.getValue(1);
|
|
|
|
RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
|
|
|
|
}
|
|
|
|
|
|
|
|
RetOps[0] = Chain; // Update chain.
|
|
|
|
|
|
|
|
// Add the flag if we have it.
|
|
|
|
if (Flag.getNode()) {
|
|
|
|
RetOps.push_back(Flag);
|
|
|
|
}
|
|
|
|
|
|
|
|
return DAG.getNode(RISCVISD::RET_FLAG, DL, MVT::Other, RetOps);
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *RISCVTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
|
|
|
switch ((RISCVISD::NodeType)Opcode) {
|
|
|
|
case RISCVISD::FIRST_NUMBER:
|
|
|
|
break;
|
|
|
|
case RISCVISD::RET_FLAG:
|
|
|
|
return "RISCVISD::RET_FLAG";
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|