| //===-- VEISelLowering.cpp - VE DAG Lowering Implementation ---------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file implements the interfaces that VE uses to lower LLVM code into a |
| // selection DAG. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "VEISelLowering.h" |
| #include "VERegisterInfo.h" |
| #include "VETargetMachine.h" |
| #include "llvm/ADT/StringSwitch.h" |
| #include "llvm/CodeGen/CallingConvLower.h" |
| #include "llvm/CodeGen/MachineFrameInfo.h" |
| #include "llvm/CodeGen/MachineFunction.h" |
| #include "llvm/CodeGen/MachineInstrBuilder.h" |
| #include "llvm/CodeGen/MachineModuleInfo.h" |
| #include "llvm/CodeGen/MachineRegisterInfo.h" |
| #include "llvm/CodeGen/SelectionDAG.h" |
| #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" |
| #include "llvm/IR/DerivedTypes.h" |
| #include "llvm/IR/Function.h" |
| #include "llvm/IR/Module.h" |
| #include "llvm/Support/ErrorHandling.h" |
| #include "llvm/Support/KnownBits.h" |
| using namespace llvm; |
| |
| #define DEBUG_TYPE "ve-lower" |
| |
| //===----------------------------------------------------------------------===// |
| // Calling Convention Implementation |
| //===----------------------------------------------------------------------===// |
| |
| #include "VEGenCallingConv.inc" |
| |
| bool VETargetLowering::CanLowerReturn( |
| CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, |
| const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const { |
| assert(!IsVarArg && "TODO implement var args"); |
| assert(Outs.empty() && "TODO implement return values"); |
| return true; // TODO support more than 'ret void' |
| } |
| |
| SDValue |
| VETargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, |
| bool IsVarArg, |
| const SmallVectorImpl<ISD::OutputArg> &Outs, |
| const SmallVectorImpl<SDValue> &OutVals, |
| const SDLoc &DL, SelectionDAG &DAG) const { |
| assert(!IsVarArg && "TODO implement var args"); |
| assert(Outs.empty() && "TODO implement return values"); |
| assert(OutVals.empty() && "TODO implement return values"); |
| |
| SmallVector<SDValue, 4> RetOps(1, Chain); |
| RetOps[0] = Chain; // Update chain. |
| return DAG.getNode(VEISD::RET_FLAG, DL, MVT::Other, RetOps); |
| } |
| |
| SDValue VETargetLowering::LowerFormalArguments( |
| SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, |
| const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL, |
| SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { |
| assert(!IsVarArg && "TODO implement var args"); |
| assert(Ins.empty() && "TODO implement input arguments"); |
| return Chain; |
| } |
| |
| // FIXME? Maybe this could be a TableGen attribute on some registers and |
| // this table could be generated automatically from RegInfo. |
| Register VETargetLowering::getRegisterByName(const char *RegName, LLT VT, |
| const MachineFunction &MF) const { |
| Register Reg = StringSwitch<Register>(RegName) |
| .Case("sp", VE::SX11) // Stack pointer |
| .Case("fp", VE::SX9) // Frame pointer |
| .Case("sl", VE::SX8) // Stack limit |
| .Case("lr", VE::SX10) // Link regsiter |
| .Case("tp", VE::SX14) // Thread pointer |
| .Case("outer", VE::SX12) // Outer regiser |
| .Case("info", VE::SX17) // Info area register |
| .Case("got", VE::SX15) // Global offset table register |
| .Case("plt", VE::SX16) // Procedure linkage table register |
| .Default(0); |
| |
| if (Reg) |
| return Reg; |
| |
| report_fatal_error("Invalid register name global variable"); |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // TargetLowering Implementation |
| //===----------------------------------------------------------------------===// |
| |
| VETargetLowering::VETargetLowering(const TargetMachine &TM, |
| const VESubtarget &STI) |
| : TargetLowering(TM), Subtarget(&STI) { |
| // Instructions which use registers as conditionals examine all the |
| // bits (as does the pseudo SELECT_CC expansion). I don't think it |
| // matters much whether it's ZeroOrOneBooleanContent, or |
| // ZeroOrNegativeOneBooleanContent, so, arbitrarily choose the |
| // former. |
| setBooleanContents(ZeroOrOneBooleanContent); |
| setBooleanVectorContents(ZeroOrOneBooleanContent); |
| |
| // Set up the register classes. |
| addRegisterClass(MVT::i64, &VE::I64RegClass); |
| |
| setStackPointerRegisterToSaveRestore(VE::SX11); |
| |
| // Set function alignment to 16 bytes |
| setMinFunctionAlignment(Align(16)); |
| |
| // VE stores all argument by 8 bytes alignment |
| setMinStackArgumentAlignment(Align(8)); |
| |
| computeRegisterProperties(Subtarget->getRegisterInfo()); |
| } |
| |
| const char *VETargetLowering::getTargetNodeName(unsigned Opcode) const { |
| switch ((VEISD::NodeType)Opcode) { |
| case VEISD::FIRST_NUMBER: |
| break; |
| case VEISD::RET_FLAG: |
| return "VEISD::RET_FLAG"; |
| } |
| return nullptr; |
| } |
| |
| EVT VETargetLowering::getSetCCResultType(const DataLayout &, LLVMContext &, |
| EVT VT) const { |
| return MVT::i64; |
| } |