| //===-- 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; | |
| } |