Changeset View
Changeset View
Standalone View
Standalone View
llvm/trunk/lib/Target/RISCV/RISCVISelLowering.cpp
//===-- 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); | |||||
// 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; | |||||
} |