10b57cec5SDimitry Andric //===- ARCISelLowering.cpp - ARC DAG Lowering Impl --------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements the ARCTargetLowering class. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "ARCISelLowering.h" 140b57cec5SDimitry Andric #include "ARC.h" 150b57cec5SDimitry Andric #include "ARCMachineFunctionInfo.h" 160b57cec5SDimitry Andric #include "ARCSubtarget.h" 170b57cec5SDimitry Andric #include "ARCTargetMachine.h" 180b57cec5SDimitry Andric #include "MCTargetDesc/ARCInfo.h" 190b57cec5SDimitry Andric #include "llvm/CodeGen/CallingConvLower.h" 200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 230b57cec5SDimitry Andric #include "llvm/CodeGen/MachineJumpTableInfo.h" 240b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 250b57cec5SDimitry Andric #include "llvm/CodeGen/ValueTypes.h" 260b57cec5SDimitry Andric #include "llvm/IR/CallingConv.h" 270b57cec5SDimitry Andric #include "llvm/IR/Intrinsics.h" 280b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 290b57cec5SDimitry Andric #include <algorithm> 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric #define DEBUG_TYPE "arc-lower" 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric using namespace llvm; 340b57cec5SDimitry Andric 3506c3fb27SDimitry Andric static SDValue lowerCallResult(SDValue Chain, SDValue InGlue, 360b57cec5SDimitry Andric const SmallVectorImpl<CCValAssign> &RVLocs, 370b57cec5SDimitry Andric SDLoc dl, SelectionDAG &DAG, 380b57cec5SDimitry Andric SmallVectorImpl<SDValue> &InVals); 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric static ARCCC::CondCode ISDCCtoARCCC(ISD::CondCode isdCC) { 410b57cec5SDimitry Andric switch (isdCC) { 420b57cec5SDimitry Andric case ISD::SETUEQ: 430b57cec5SDimitry Andric return ARCCC::EQ; 440b57cec5SDimitry Andric case ISD::SETUGT: 450b57cec5SDimitry Andric return ARCCC::HI; 460b57cec5SDimitry Andric case ISD::SETUGE: 470b57cec5SDimitry Andric return ARCCC::HS; 480b57cec5SDimitry Andric case ISD::SETULT: 490b57cec5SDimitry Andric return ARCCC::LO; 500b57cec5SDimitry Andric case ISD::SETULE: 510b57cec5SDimitry Andric return ARCCC::LS; 520b57cec5SDimitry Andric case ISD::SETUNE: 530b57cec5SDimitry Andric return ARCCC::NE; 540b57cec5SDimitry Andric case ISD::SETEQ: 550b57cec5SDimitry Andric return ARCCC::EQ; 560b57cec5SDimitry Andric case ISD::SETGT: 570b57cec5SDimitry Andric return ARCCC::GT; 580b57cec5SDimitry Andric case ISD::SETGE: 590b57cec5SDimitry Andric return ARCCC::GE; 600b57cec5SDimitry Andric case ISD::SETLT: 610b57cec5SDimitry Andric return ARCCC::LT; 620b57cec5SDimitry Andric case ISD::SETLE: 630b57cec5SDimitry Andric return ARCCC::LE; 640b57cec5SDimitry Andric case ISD::SETNE: 650b57cec5SDimitry Andric return ARCCC::NE; 660b57cec5SDimitry Andric default: 670b57cec5SDimitry Andric llvm_unreachable("Unhandled ISDCC code."); 680b57cec5SDimitry Andric } 690b57cec5SDimitry Andric } 700b57cec5SDimitry Andric 71349cc55cSDimitry Andric void ARCTargetLowering::ReplaceNodeResults(SDNode *N, 72349cc55cSDimitry Andric SmallVectorImpl<SDValue> &Results, 73349cc55cSDimitry Andric SelectionDAG &DAG) const { 74349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << "[ARC-ISEL] ReplaceNodeResults "); 75349cc55cSDimitry Andric LLVM_DEBUG(N->dump(&DAG)); 76349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << "; use_count=" << N->use_size() << "\n"); 77349cc55cSDimitry Andric 78349cc55cSDimitry Andric switch (N->getOpcode()) { 79349cc55cSDimitry Andric case ISD::READCYCLECOUNTER: 80349cc55cSDimitry Andric if (N->getValueType(0) == MVT::i64) { 81349cc55cSDimitry Andric // We read the TIMER0 and zero-extend it to 64-bits as the intrinsic 82349cc55cSDimitry Andric // requires. 83349cc55cSDimitry Andric SDValue V = 84349cc55cSDimitry Andric DAG.getNode(ISD::READCYCLECOUNTER, SDLoc(N), 85349cc55cSDimitry Andric DAG.getVTList(MVT::i32, MVT::Other), N->getOperand(0)); 86349cc55cSDimitry Andric SDValue Op = DAG.getNode(ISD::ZERO_EXTEND, SDLoc(N), MVT::i64, V); 87349cc55cSDimitry Andric Results.push_back(Op); 88349cc55cSDimitry Andric Results.push_back(V.getValue(1)); 89349cc55cSDimitry Andric } 90349cc55cSDimitry Andric break; 91349cc55cSDimitry Andric default: 92349cc55cSDimitry Andric break; 93349cc55cSDimitry Andric } 94349cc55cSDimitry Andric } 95349cc55cSDimitry Andric 960b57cec5SDimitry Andric ARCTargetLowering::ARCTargetLowering(const TargetMachine &TM, 970b57cec5SDimitry Andric const ARCSubtarget &Subtarget) 980b57cec5SDimitry Andric : TargetLowering(TM), Subtarget(Subtarget) { 990b57cec5SDimitry Andric // Set up the register classes. 1000b57cec5SDimitry Andric addRegisterClass(MVT::i32, &ARC::GPR32RegClass); 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric // Compute derived properties from the register classes 1030b57cec5SDimitry Andric computeRegisterProperties(Subtarget.getRegisterInfo()); 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric setStackPointerRegisterToSaveRestore(ARC::SP); 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric setSchedulingPreference(Sched::Source); 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric // Use i32 for setcc operations results (slt, sgt, ...). 1100b57cec5SDimitry Andric setBooleanContents(ZeroOrOneBooleanContent); 1110b57cec5SDimitry Andric setBooleanVectorContents(ZeroOrOneBooleanContent); 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric for (unsigned Opc = 0; Opc < ISD::BUILTIN_OP_END; ++Opc) 1140b57cec5SDimitry Andric setOperationAction(Opc, MVT::i32, Expand); 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric // Operations to get us off of the ground. 1170b57cec5SDimitry Andric // Basic. 1180b57cec5SDimitry Andric setOperationAction(ISD::ADD, MVT::i32, Legal); 1190b57cec5SDimitry Andric setOperationAction(ISD::SUB, MVT::i32, Legal); 1200b57cec5SDimitry Andric setOperationAction(ISD::AND, MVT::i32, Legal); 1210b57cec5SDimitry Andric setOperationAction(ISD::SMAX, MVT::i32, Legal); 1220b57cec5SDimitry Andric setOperationAction(ISD::SMIN, MVT::i32, Legal); 1230b57cec5SDimitry Andric 124349cc55cSDimitry Andric setOperationAction(ISD::ADDC, MVT::i32, Legal); 125349cc55cSDimitry Andric setOperationAction(ISD::ADDE, MVT::i32, Legal); 126349cc55cSDimitry Andric setOperationAction(ISD::SUBC, MVT::i32, Legal); 127349cc55cSDimitry Andric setOperationAction(ISD::SUBE, MVT::i32, Legal); 128349cc55cSDimitry Andric 1290b57cec5SDimitry Andric // Need barrel shifter. 1300b57cec5SDimitry Andric setOperationAction(ISD::SHL, MVT::i32, Legal); 1310b57cec5SDimitry Andric setOperationAction(ISD::SRA, MVT::i32, Legal); 1320b57cec5SDimitry Andric setOperationAction(ISD::SRL, MVT::i32, Legal); 1330b57cec5SDimitry Andric setOperationAction(ISD::ROTR, MVT::i32, Legal); 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric setOperationAction(ISD::Constant, MVT::i32, Legal); 1360b57cec5SDimitry Andric setOperationAction(ISD::UNDEF, MVT::i32, Legal); 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric // Need multiplier 1390b57cec5SDimitry Andric setOperationAction(ISD::MUL, MVT::i32, Legal); 1400b57cec5SDimitry Andric setOperationAction(ISD::MULHS, MVT::i32, Legal); 1410b57cec5SDimitry Andric setOperationAction(ISD::MULHU, MVT::i32, Legal); 1420b57cec5SDimitry Andric setOperationAction(ISD::LOAD, MVT::i32, Legal); 1430b57cec5SDimitry Andric setOperationAction(ISD::STORE, MVT::i32, Legal); 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric setOperationAction(ISD::SELECT_CC, MVT::i32, Custom); 1460b57cec5SDimitry Andric setOperationAction(ISD::BR_CC, MVT::i32, Custom); 1470b57cec5SDimitry Andric setOperationAction(ISD::BRCOND, MVT::Other, Expand); 1480b57cec5SDimitry Andric setOperationAction(ISD::BR_JT, MVT::Other, Expand); 1490b57cec5SDimitry Andric setOperationAction(ISD::JumpTable, MVT::i32, Custom); 1500b57cec5SDimitry Andric 151480093f4SDimitry Andric // Have pseudo instruction for frame addresses. 1520b57cec5SDimitry Andric setOperationAction(ISD::FRAMEADDR, MVT::i32, Legal); 1530b57cec5SDimitry Andric // Custom lower global addresses. 1540b57cec5SDimitry Andric setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric // Expand var-args ops. 1570b57cec5SDimitry Andric setOperationAction(ISD::VASTART, MVT::Other, Custom); 1580b57cec5SDimitry Andric setOperationAction(ISD::VAEND, MVT::Other, Expand); 1590b57cec5SDimitry Andric setOperationAction(ISD::VAARG, MVT::Other, Expand); 1600b57cec5SDimitry Andric setOperationAction(ISD::VACOPY, MVT::Other, Expand); 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric // Other expansions 1630b57cec5SDimitry Andric setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); 1640b57cec5SDimitry Andric setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric // Sign extend inreg 1670b57cec5SDimitry Andric setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Custom); 168349cc55cSDimitry Andric 169349cc55cSDimitry Andric // TODO: Predicate these with `options.hasBitScan() ? Legal : Expand` 170349cc55cSDimitry Andric // when the HasBitScan predicate is available. 171349cc55cSDimitry Andric setOperationAction(ISD::CTLZ, MVT::i32, Legal); 172349cc55cSDimitry Andric setOperationAction(ISD::CTTZ, MVT::i32, Legal); 173349cc55cSDimitry Andric 174349cc55cSDimitry Andric setOperationAction(ISD::READCYCLECOUNTER, MVT::i32, Legal); 175349cc55cSDimitry Andric setOperationAction(ISD::READCYCLECOUNTER, MVT::i64, 176349cc55cSDimitry Andric isTypeLegal(MVT::i64) ? Legal : Custom); 1771db9f3b2SDimitry Andric 1781db9f3b2SDimitry Andric setMaxAtomicSizeInBitsSupported(0); 1790b57cec5SDimitry Andric } 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric const char *ARCTargetLowering::getTargetNodeName(unsigned Opcode) const { 1820b57cec5SDimitry Andric switch (Opcode) { 1830b57cec5SDimitry Andric case ARCISD::BL: 1840b57cec5SDimitry Andric return "ARCISD::BL"; 1850b57cec5SDimitry Andric case ARCISD::CMOV: 1860b57cec5SDimitry Andric return "ARCISD::CMOV"; 1870b57cec5SDimitry Andric case ARCISD::CMP: 1880b57cec5SDimitry Andric return "ARCISD::CMP"; 1890b57cec5SDimitry Andric case ARCISD::BRcc: 1900b57cec5SDimitry Andric return "ARCISD::BRcc"; 1910b57cec5SDimitry Andric case ARCISD::RET: 1920b57cec5SDimitry Andric return "ARCISD::RET"; 1930b57cec5SDimitry Andric case ARCISD::GAWRAPPER: 1940b57cec5SDimitry Andric return "ARCISD::GAWRAPPER"; 1950b57cec5SDimitry Andric } 1960b57cec5SDimitry Andric return nullptr; 1970b57cec5SDimitry Andric } 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 2000b57cec5SDimitry Andric // Misc Lower Operation implementation 2010b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 2020b57cec5SDimitry Andric 2030b57cec5SDimitry Andric SDValue ARCTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const { 2040b57cec5SDimitry Andric SDValue LHS = Op.getOperand(0); 2050b57cec5SDimitry Andric SDValue RHS = Op.getOperand(1); 2060b57cec5SDimitry Andric ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get(); 2070b57cec5SDimitry Andric SDValue TVal = Op.getOperand(2); 2080b57cec5SDimitry Andric SDValue FVal = Op.getOperand(3); 2090b57cec5SDimitry Andric SDLoc dl(Op); 2100b57cec5SDimitry Andric ARCCC::CondCode ArcCC = ISDCCtoARCCC(CC); 2110b57cec5SDimitry Andric assert(LHS.getValueType() == MVT::i32 && "Only know how to SELECT_CC i32"); 2120b57cec5SDimitry Andric SDValue Cmp = DAG.getNode(ARCISD::CMP, dl, MVT::Glue, LHS, RHS); 2130b57cec5SDimitry Andric return DAG.getNode(ARCISD::CMOV, dl, TVal.getValueType(), TVal, FVal, 2140b57cec5SDimitry Andric DAG.getConstant(ArcCC, dl, MVT::i32), Cmp); 2150b57cec5SDimitry Andric } 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric SDValue ARCTargetLowering::LowerSIGN_EXTEND_INREG(SDValue Op, 2180b57cec5SDimitry Andric SelectionDAG &DAG) const { 2190b57cec5SDimitry Andric SDValue Op0 = Op.getOperand(0); 2200b57cec5SDimitry Andric SDLoc dl(Op); 2210b57cec5SDimitry Andric assert(Op.getValueType() == MVT::i32 && 2220b57cec5SDimitry Andric "Unhandled target sign_extend_inreg."); 2230b57cec5SDimitry Andric // These are legal 2240b57cec5SDimitry Andric unsigned Width = cast<VTSDNode>(Op.getOperand(1))->getVT().getSizeInBits(); 2250b57cec5SDimitry Andric if (Width == 16 || Width == 8) 2260b57cec5SDimitry Andric return Op; 2270b57cec5SDimitry Andric if (Width >= 32) { 2280b57cec5SDimitry Andric return {}; 2290b57cec5SDimitry Andric } 2300b57cec5SDimitry Andric SDValue LS = DAG.getNode(ISD::SHL, dl, MVT::i32, Op0, 2310b57cec5SDimitry Andric DAG.getConstant(32 - Width, dl, MVT::i32)); 2320b57cec5SDimitry Andric SDValue SR = DAG.getNode(ISD::SRA, dl, MVT::i32, LS, 2330b57cec5SDimitry Andric DAG.getConstant(32 - Width, dl, MVT::i32)); 2340b57cec5SDimitry Andric return SR; 2350b57cec5SDimitry Andric } 2360b57cec5SDimitry Andric 2370b57cec5SDimitry Andric SDValue ARCTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const { 2380b57cec5SDimitry Andric SDValue Chain = Op.getOperand(0); 2390b57cec5SDimitry Andric ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get(); 2400b57cec5SDimitry Andric SDValue LHS = Op.getOperand(2); 2410b57cec5SDimitry Andric SDValue RHS = Op.getOperand(3); 2420b57cec5SDimitry Andric SDValue Dest = Op.getOperand(4); 2430b57cec5SDimitry Andric SDLoc dl(Op); 2440b57cec5SDimitry Andric ARCCC::CondCode arcCC = ISDCCtoARCCC(CC); 2450b57cec5SDimitry Andric assert(LHS.getValueType() == MVT::i32 && "Only know how to BR_CC i32"); 2460b57cec5SDimitry Andric return DAG.getNode(ARCISD::BRcc, dl, MVT::Other, Chain, Dest, LHS, RHS, 2470b57cec5SDimitry Andric DAG.getConstant(arcCC, dl, MVT::i32)); 2480b57cec5SDimitry Andric } 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric SDValue ARCTargetLowering::LowerJumpTable(SDValue Op, SelectionDAG &DAG) const { 2510b57cec5SDimitry Andric auto *N = cast<JumpTableSDNode>(Op); 2520b57cec5SDimitry Andric SDValue GA = DAG.getTargetJumpTable(N->getIndex(), MVT::i32); 2530b57cec5SDimitry Andric return DAG.getNode(ARCISD::GAWRAPPER, SDLoc(N), MVT::i32, GA); 2540b57cec5SDimitry Andric } 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric #include "ARCGenCallingConv.inc" 2570b57cec5SDimitry Andric 2580b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 2590b57cec5SDimitry Andric // Call Calling Convention Implementation 2600b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 2610b57cec5SDimitry Andric 2620b57cec5SDimitry Andric /// ARC call implementation 2630b57cec5SDimitry Andric SDValue ARCTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, 2640b57cec5SDimitry Andric SmallVectorImpl<SDValue> &InVals) const { 2650b57cec5SDimitry Andric SelectionDAG &DAG = CLI.DAG; 2660b57cec5SDimitry Andric SDLoc &dl = CLI.DL; 2670b57cec5SDimitry Andric SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs; 2680b57cec5SDimitry Andric SmallVectorImpl<SDValue> &OutVals = CLI.OutVals; 2690b57cec5SDimitry Andric SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins; 2700b57cec5SDimitry Andric SDValue Chain = CLI.Chain; 2710b57cec5SDimitry Andric SDValue Callee = CLI.Callee; 2720b57cec5SDimitry Andric CallingConv::ID CallConv = CLI.CallConv; 2730b57cec5SDimitry Andric bool IsVarArg = CLI.IsVarArg; 2740b57cec5SDimitry Andric bool &IsTailCall = CLI.IsTailCall; 2750b57cec5SDimitry Andric 2760b57cec5SDimitry Andric IsTailCall = false; // Do not support tail calls yet. 2770b57cec5SDimitry Andric 2780b57cec5SDimitry Andric SmallVector<CCValAssign, 16> ArgLocs; 2790b57cec5SDimitry Andric CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, 2800b57cec5SDimitry Andric *DAG.getContext()); 2810b57cec5SDimitry Andric 2820b57cec5SDimitry Andric CCInfo.AnalyzeCallOperands(Outs, CC_ARC); 2830b57cec5SDimitry Andric 2840b57cec5SDimitry Andric SmallVector<CCValAssign, 16> RVLocs; 2850b57cec5SDimitry Andric // Analyze return values to determine the number of bytes of stack required. 2860b57cec5SDimitry Andric CCState RetCCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs, 2870b57cec5SDimitry Andric *DAG.getContext()); 28806c3fb27SDimitry Andric RetCCInfo.AllocateStack(CCInfo.getStackSize(), Align(4)); 2890b57cec5SDimitry Andric RetCCInfo.AnalyzeCallResult(Ins, RetCC_ARC); 2900b57cec5SDimitry Andric 2910b57cec5SDimitry Andric // Get a count of how many bytes are to be pushed on the stack. 29206c3fb27SDimitry Andric unsigned NumBytes = RetCCInfo.getStackSize(); 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, dl); 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andric SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass; 2970b57cec5SDimitry Andric SmallVector<SDValue, 12> MemOpChains; 2980b57cec5SDimitry Andric 2990b57cec5SDimitry Andric SDValue StackPtr; 3000b57cec5SDimitry Andric // Walk the register/memloc assignments, inserting copies/loads. 3010b57cec5SDimitry Andric for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 3020b57cec5SDimitry Andric CCValAssign &VA = ArgLocs[i]; 3030b57cec5SDimitry Andric SDValue Arg = OutVals[i]; 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric // Promote the value if needed. 3060b57cec5SDimitry Andric switch (VA.getLocInfo()) { 3070b57cec5SDimitry Andric default: 3080b57cec5SDimitry Andric llvm_unreachable("Unknown loc info!"); 3090b57cec5SDimitry Andric case CCValAssign::Full: 3100b57cec5SDimitry Andric break; 3110b57cec5SDimitry Andric case CCValAssign::SExt: 3120b57cec5SDimitry Andric Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg); 3130b57cec5SDimitry Andric break; 3140b57cec5SDimitry Andric case CCValAssign::ZExt: 3150b57cec5SDimitry Andric Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg); 3160b57cec5SDimitry Andric break; 3170b57cec5SDimitry Andric case CCValAssign::AExt: 3180b57cec5SDimitry Andric Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg); 3190b57cec5SDimitry Andric break; 3200b57cec5SDimitry Andric } 3210b57cec5SDimitry Andric 3220b57cec5SDimitry Andric // Arguments that can be passed on register must be kept at 3230b57cec5SDimitry Andric // RegsToPass vector 3240b57cec5SDimitry Andric if (VA.isRegLoc()) { 3250b57cec5SDimitry Andric RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); 3260b57cec5SDimitry Andric } else { 3270b57cec5SDimitry Andric assert(VA.isMemLoc() && "Must be register or memory argument."); 3280b57cec5SDimitry Andric if (!StackPtr.getNode()) 3290b57cec5SDimitry Andric StackPtr = DAG.getCopyFromReg(Chain, dl, ARC::SP, 3300b57cec5SDimitry Andric getPointerTy(DAG.getDataLayout())); 3310b57cec5SDimitry Andric // Calculate the stack position. 3320b57cec5SDimitry Andric SDValue SOffset = DAG.getIntPtrConstant(VA.getLocMemOffset(), dl); 3330b57cec5SDimitry Andric SDValue PtrOff = DAG.getNode( 3340b57cec5SDimitry Andric ISD::ADD, dl, getPointerTy(DAG.getDataLayout()), StackPtr, SOffset); 3350b57cec5SDimitry Andric 3360b57cec5SDimitry Andric SDValue Store = 3370b57cec5SDimitry Andric DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo()); 3380b57cec5SDimitry Andric MemOpChains.push_back(Store); 3390b57cec5SDimitry Andric IsTailCall = false; 3400b57cec5SDimitry Andric } 3410b57cec5SDimitry Andric } 3420b57cec5SDimitry Andric 3430b57cec5SDimitry Andric // Transform all store nodes into one single node because 3440b57cec5SDimitry Andric // all store nodes are independent of each other. 3450b57cec5SDimitry Andric if (!MemOpChains.empty()) 3460b57cec5SDimitry Andric Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains); 3470b57cec5SDimitry Andric 3480b57cec5SDimitry Andric // Build a sequence of copy-to-reg nodes chained together with token 3490b57cec5SDimitry Andric // chain and flag operands which copy the outgoing args into registers. 35006c3fb27SDimitry Andric // The Glue in necessary since all emitted instructions must be 3510b57cec5SDimitry Andric // stuck together. 3520b57cec5SDimitry Andric SDValue Glue; 3530b57cec5SDimitry Andric for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { 3540b57cec5SDimitry Andric Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, 3550b57cec5SDimitry Andric RegsToPass[i].second, Glue); 3560b57cec5SDimitry Andric Glue = Chain.getValue(1); 3570b57cec5SDimitry Andric } 3580b57cec5SDimitry Andric 3590b57cec5SDimitry Andric // If the callee is a GlobalAddress node (quite common, every direct call is) 3600b57cec5SDimitry Andric // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. 3610b57cec5SDimitry Andric // Likewise ExternalSymbol -> TargetExternalSymbol. 3620b57cec5SDimitry Andric bool IsDirect = true; 3630b57cec5SDimitry Andric if (auto *G = dyn_cast<GlobalAddressSDNode>(Callee)) 3640b57cec5SDimitry Andric Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32); 3650b57cec5SDimitry Andric else if (auto *E = dyn_cast<ExternalSymbolSDNode>(Callee)) 3660b57cec5SDimitry Andric Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32); 3670b57cec5SDimitry Andric else 3680b57cec5SDimitry Andric IsDirect = false; 3690b57cec5SDimitry Andric // Branch + Link = #chain, #target_address, #opt_in_flags... 3700b57cec5SDimitry Andric // = Chain, Callee, Reg#1, Reg#2, ... 3710b57cec5SDimitry Andric // 37206c3fb27SDimitry Andric // Returns a chain & a glue for retval copy to use. 3730b57cec5SDimitry Andric SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); 3740b57cec5SDimitry Andric SmallVector<SDValue, 8> Ops; 3750b57cec5SDimitry Andric Ops.push_back(Chain); 3760b57cec5SDimitry Andric Ops.push_back(Callee); 3770b57cec5SDimitry Andric 3780b57cec5SDimitry Andric for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) 3790b57cec5SDimitry Andric Ops.push_back(DAG.getRegister(RegsToPass[i].first, 3800b57cec5SDimitry Andric RegsToPass[i].second.getValueType())); 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andric // Add a register mask operand representing the call-preserved registers. 3830b57cec5SDimitry Andric const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); 3840b57cec5SDimitry Andric const uint32_t *Mask = 3850b57cec5SDimitry Andric TRI->getCallPreservedMask(DAG.getMachineFunction(), CallConv); 3860b57cec5SDimitry Andric assert(Mask && "Missing call preserved mask for calling convention"); 3870b57cec5SDimitry Andric Ops.push_back(DAG.getRegisterMask(Mask)); 3880b57cec5SDimitry Andric 3890b57cec5SDimitry Andric if (Glue.getNode()) 3900b57cec5SDimitry Andric Ops.push_back(Glue); 3910b57cec5SDimitry Andric 3920b57cec5SDimitry Andric Chain = DAG.getNode(IsDirect ? ARCISD::BL : ARCISD::JL, dl, NodeTys, Ops); 3930b57cec5SDimitry Andric Glue = Chain.getValue(1); 3940b57cec5SDimitry Andric 3950b57cec5SDimitry Andric // Create the CALLSEQ_END node. 396bdd1243dSDimitry Andric Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, Glue, dl); 3970b57cec5SDimitry Andric Glue = Chain.getValue(1); 3980b57cec5SDimitry Andric 3990b57cec5SDimitry Andric // Handle result values, copying them out of physregs into vregs that we 4000b57cec5SDimitry Andric // return. 4010b57cec5SDimitry Andric if (IsTailCall) 4020b57cec5SDimitry Andric return Chain; 4030b57cec5SDimitry Andric return lowerCallResult(Chain, Glue, RVLocs, dl, DAG, InVals); 4040b57cec5SDimitry Andric } 4050b57cec5SDimitry Andric 4060b57cec5SDimitry Andric /// Lower the result values of a call into the appropriate copies out of 4070b57cec5SDimitry Andric /// physical registers / memory locations. 4080b57cec5SDimitry Andric static SDValue lowerCallResult(SDValue Chain, SDValue Glue, 4090b57cec5SDimitry Andric const SmallVectorImpl<CCValAssign> &RVLocs, 4100b57cec5SDimitry Andric SDLoc dl, SelectionDAG &DAG, 4110b57cec5SDimitry Andric SmallVectorImpl<SDValue> &InVals) { 4120b57cec5SDimitry Andric SmallVector<std::pair<int, unsigned>, 4> ResultMemLocs; 4130b57cec5SDimitry Andric // Copy results out of physical registers. 4140b57cec5SDimitry Andric for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) { 4150b57cec5SDimitry Andric const CCValAssign &VA = RVLocs[i]; 4160b57cec5SDimitry Andric if (VA.isRegLoc()) { 4170b57cec5SDimitry Andric SDValue RetValue; 4180b57cec5SDimitry Andric RetValue = 4190b57cec5SDimitry Andric DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), VA.getValVT(), Glue); 4200b57cec5SDimitry Andric Chain = RetValue.getValue(1); 4210b57cec5SDimitry Andric Glue = RetValue.getValue(2); 4220b57cec5SDimitry Andric InVals.push_back(RetValue); 4230b57cec5SDimitry Andric } else { 4240b57cec5SDimitry Andric assert(VA.isMemLoc() && "Must be memory location."); 4250b57cec5SDimitry Andric ResultMemLocs.push_back( 4260b57cec5SDimitry Andric std::make_pair(VA.getLocMemOffset(), InVals.size())); 4270b57cec5SDimitry Andric 4280b57cec5SDimitry Andric // Reserve space for this result. 4290b57cec5SDimitry Andric InVals.push_back(SDValue()); 4300b57cec5SDimitry Andric } 4310b57cec5SDimitry Andric } 4320b57cec5SDimitry Andric 4330b57cec5SDimitry Andric // Copy results out of memory. 4340b57cec5SDimitry Andric SmallVector<SDValue, 4> MemOpChains; 4350b57cec5SDimitry Andric for (unsigned i = 0, e = ResultMemLocs.size(); i != e; ++i) { 4360b57cec5SDimitry Andric int Offset = ResultMemLocs[i].first; 4370b57cec5SDimitry Andric unsigned Index = ResultMemLocs[i].second; 4380b57cec5SDimitry Andric SDValue StackPtr = DAG.getRegister(ARC::SP, MVT::i32); 4390b57cec5SDimitry Andric SDValue SpLoc = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, 4400b57cec5SDimitry Andric DAG.getConstant(Offset, dl, MVT::i32)); 4410b57cec5SDimitry Andric SDValue Load = 4420b57cec5SDimitry Andric DAG.getLoad(MVT::i32, dl, Chain, SpLoc, MachinePointerInfo()); 4430b57cec5SDimitry Andric InVals[Index] = Load; 4440b57cec5SDimitry Andric MemOpChains.push_back(Load.getValue(1)); 4450b57cec5SDimitry Andric } 4460b57cec5SDimitry Andric 4470b57cec5SDimitry Andric // Transform all loads nodes into one single node because 4480b57cec5SDimitry Andric // all load nodes are independent of each other. 4490b57cec5SDimitry Andric if (!MemOpChains.empty()) 4500b57cec5SDimitry Andric Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains); 4510b57cec5SDimitry Andric 4520b57cec5SDimitry Andric return Chain; 4530b57cec5SDimitry Andric } 4540b57cec5SDimitry Andric 4550b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 4560b57cec5SDimitry Andric // Formal Arguments Calling Convention Implementation 4570b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 4580b57cec5SDimitry Andric 4590b57cec5SDimitry Andric namespace { 4600b57cec5SDimitry Andric 4610b57cec5SDimitry Andric struct ArgDataPair { 4620b57cec5SDimitry Andric SDValue SDV; 4630b57cec5SDimitry Andric ISD::ArgFlagsTy Flags; 4640b57cec5SDimitry Andric }; 4650b57cec5SDimitry Andric 4660b57cec5SDimitry Andric } // end anonymous namespace 4670b57cec5SDimitry Andric 4680b57cec5SDimitry Andric /// ARC formal arguments implementation 4690b57cec5SDimitry Andric SDValue ARCTargetLowering::LowerFormalArguments( 4700b57cec5SDimitry Andric SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, 4710b57cec5SDimitry Andric const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl, 4720b57cec5SDimitry Andric SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { 4730b57cec5SDimitry Andric switch (CallConv) { 4740b57cec5SDimitry Andric default: 4750b57cec5SDimitry Andric llvm_unreachable("Unsupported calling convention"); 4760b57cec5SDimitry Andric case CallingConv::C: 4770b57cec5SDimitry Andric case CallingConv::Fast: 4780b57cec5SDimitry Andric return LowerCallArguments(Chain, CallConv, IsVarArg, Ins, dl, DAG, InVals); 4790b57cec5SDimitry Andric } 4800b57cec5SDimitry Andric } 4810b57cec5SDimitry Andric 4820b57cec5SDimitry Andric /// Transform physical registers into virtual registers, and generate load 4830b57cec5SDimitry Andric /// operations for argument places on the stack. 4840b57cec5SDimitry Andric SDValue ARCTargetLowering::LowerCallArguments( 4850b57cec5SDimitry Andric SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, 4860b57cec5SDimitry Andric const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc dl, SelectionDAG &DAG, 4870b57cec5SDimitry Andric SmallVectorImpl<SDValue> &InVals) const { 4880b57cec5SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 4890b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 4900b57cec5SDimitry Andric MachineRegisterInfo &RegInfo = MF.getRegInfo(); 4910b57cec5SDimitry Andric auto *AFI = MF.getInfo<ARCFunctionInfo>(); 4920b57cec5SDimitry Andric 4930b57cec5SDimitry Andric // Assign locations to all of the incoming arguments. 4940b57cec5SDimitry Andric SmallVector<CCValAssign, 16> ArgLocs; 4950b57cec5SDimitry Andric CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, 4960b57cec5SDimitry Andric *DAG.getContext()); 4970b57cec5SDimitry Andric 4980b57cec5SDimitry Andric CCInfo.AnalyzeFormalArguments(Ins, CC_ARC); 4990b57cec5SDimitry Andric 5000b57cec5SDimitry Andric unsigned StackSlotSize = 4; 5010b57cec5SDimitry Andric 5020b57cec5SDimitry Andric if (!IsVarArg) 50306c3fb27SDimitry Andric AFI->setReturnStackOffset(CCInfo.getStackSize()); 5040b57cec5SDimitry Andric 5050b57cec5SDimitry Andric // All getCopyFromReg ops must precede any getMemcpys to prevent the 5060b57cec5SDimitry Andric // scheduler clobbering a register before it has been copied. 5070b57cec5SDimitry Andric // The stages are: 5080b57cec5SDimitry Andric // 1. CopyFromReg (and load) arg & vararg registers. 5090b57cec5SDimitry Andric // 2. Chain CopyFromReg nodes into a TokenFactor. 5100b57cec5SDimitry Andric // 3. Memcpy 'byVal' args & push final InVals. 5110b57cec5SDimitry Andric // 4. Chain mem ops nodes into a TokenFactor. 5120b57cec5SDimitry Andric SmallVector<SDValue, 4> CFRegNode; 5130b57cec5SDimitry Andric SmallVector<ArgDataPair, 4> ArgData; 5140b57cec5SDimitry Andric SmallVector<SDValue, 4> MemOps; 5150b57cec5SDimitry Andric 5160b57cec5SDimitry Andric // 1a. CopyFromReg (and load) arg registers. 5170b57cec5SDimitry Andric for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 5180b57cec5SDimitry Andric CCValAssign &VA = ArgLocs[i]; 5190b57cec5SDimitry Andric SDValue ArgIn; 5200b57cec5SDimitry Andric 5210b57cec5SDimitry Andric if (VA.isRegLoc()) { 5220b57cec5SDimitry Andric // Arguments passed in registers 5230b57cec5SDimitry Andric EVT RegVT = VA.getLocVT(); 5240b57cec5SDimitry Andric switch (RegVT.getSimpleVT().SimpleTy) { 5250b57cec5SDimitry Andric default: { 5260b57cec5SDimitry Andric LLVM_DEBUG(errs() << "LowerFormalArguments Unhandled argument type: " 5270b57cec5SDimitry Andric << (unsigned)RegVT.getSimpleVT().SimpleTy << "\n"); 5280b57cec5SDimitry Andric llvm_unreachable("Unhandled LowerFormalArguments type."); 5290b57cec5SDimitry Andric } 5300b57cec5SDimitry Andric case MVT::i32: 5310b57cec5SDimitry Andric unsigned VReg = RegInfo.createVirtualRegister(&ARC::GPR32RegClass); 5320b57cec5SDimitry Andric RegInfo.addLiveIn(VA.getLocReg(), VReg); 5330b57cec5SDimitry Andric ArgIn = DAG.getCopyFromReg(Chain, dl, VReg, RegVT); 5340b57cec5SDimitry Andric CFRegNode.push_back(ArgIn.getValue(ArgIn->getNumValues() - 1)); 5350b57cec5SDimitry Andric } 5360b57cec5SDimitry Andric } else { 537349cc55cSDimitry Andric // Only arguments passed on the stack should make it here. 5380b57cec5SDimitry Andric assert(VA.isMemLoc()); 5390b57cec5SDimitry Andric // Load the argument to a virtual register 5400b57cec5SDimitry Andric unsigned ObjSize = VA.getLocVT().getStoreSize(); 5410b57cec5SDimitry Andric assert((ObjSize <= StackSlotSize) && "Unhandled argument"); 5420b57cec5SDimitry Andric 5430b57cec5SDimitry Andric // Create the frame index object for this incoming parameter... 5440b57cec5SDimitry Andric int FI = MFI.CreateFixedObject(ObjSize, VA.getLocMemOffset(), true); 5450b57cec5SDimitry Andric 5460b57cec5SDimitry Andric // Create the SelectionDAG nodes corresponding to a load 5470b57cec5SDimitry Andric // from this parameter 5480b57cec5SDimitry Andric SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); 5490b57cec5SDimitry Andric ArgIn = DAG.getLoad(VA.getLocVT(), dl, Chain, FIN, 5500b57cec5SDimitry Andric MachinePointerInfo::getFixedStack(MF, FI)); 5510b57cec5SDimitry Andric } 5520b57cec5SDimitry Andric const ArgDataPair ADP = {ArgIn, Ins[i].Flags}; 5530b57cec5SDimitry Andric ArgData.push_back(ADP); 5540b57cec5SDimitry Andric } 5550b57cec5SDimitry Andric 5560b57cec5SDimitry Andric // 1b. CopyFromReg vararg registers. 5570b57cec5SDimitry Andric if (IsVarArg) { 5580b57cec5SDimitry Andric // Argument registers 5590b57cec5SDimitry Andric static const MCPhysReg ArgRegs[] = {ARC::R0, ARC::R1, ARC::R2, ARC::R3, 5600b57cec5SDimitry Andric ARC::R4, ARC::R5, ARC::R6, ARC::R7}; 5610b57cec5SDimitry Andric auto *AFI = MF.getInfo<ARCFunctionInfo>(); 5620b57cec5SDimitry Andric unsigned FirstVAReg = CCInfo.getFirstUnallocated(ArgRegs); 563bdd1243dSDimitry Andric if (FirstVAReg < std::size(ArgRegs)) { 5640b57cec5SDimitry Andric int Offset = 0; 5650b57cec5SDimitry Andric // Save remaining registers, storing higher register numbers at a higher 5660b57cec5SDimitry Andric // address 567bdd1243dSDimitry Andric // There are (std::size(ArgRegs) - FirstVAReg) registers which 5680b57cec5SDimitry Andric // need to be saved. 569bdd1243dSDimitry Andric int VarFI = MFI.CreateFixedObject((std::size(ArgRegs) - FirstVAReg) * 4, 57006c3fb27SDimitry Andric CCInfo.getStackSize(), true); 5710b57cec5SDimitry Andric AFI->setVarArgsFrameIndex(VarFI); 5720b57cec5SDimitry Andric SDValue FIN = DAG.getFrameIndex(VarFI, MVT::i32); 573bdd1243dSDimitry Andric for (unsigned i = FirstVAReg; i < std::size(ArgRegs); i++) { 5740b57cec5SDimitry Andric // Move argument from phys reg -> virt reg 5750b57cec5SDimitry Andric unsigned VReg = RegInfo.createVirtualRegister(&ARC::GPR32RegClass); 5760b57cec5SDimitry Andric RegInfo.addLiveIn(ArgRegs[i], VReg); 5770b57cec5SDimitry Andric SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32); 5780b57cec5SDimitry Andric CFRegNode.push_back(Val.getValue(Val->getNumValues() - 1)); 5790b57cec5SDimitry Andric SDValue VAObj = DAG.getNode(ISD::ADD, dl, MVT::i32, FIN, 5800b57cec5SDimitry Andric DAG.getConstant(Offset, dl, MVT::i32)); 5810b57cec5SDimitry Andric // Move argument from virt reg -> stack 5820b57cec5SDimitry Andric SDValue Store = 5830b57cec5SDimitry Andric DAG.getStore(Val.getValue(1), dl, Val, VAObj, MachinePointerInfo()); 5840b57cec5SDimitry Andric MemOps.push_back(Store); 5850b57cec5SDimitry Andric Offset += 4; 5860b57cec5SDimitry Andric } 5870b57cec5SDimitry Andric } else { 5880b57cec5SDimitry Andric llvm_unreachable("Too many var args parameters."); 5890b57cec5SDimitry Andric } 5900b57cec5SDimitry Andric } 5910b57cec5SDimitry Andric 5920b57cec5SDimitry Andric // 2. Chain CopyFromReg nodes into a TokenFactor. 5930b57cec5SDimitry Andric if (!CFRegNode.empty()) 5940b57cec5SDimitry Andric Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, CFRegNode); 5950b57cec5SDimitry Andric 5960b57cec5SDimitry Andric // 3. Memcpy 'byVal' args & push final InVals. 5970b57cec5SDimitry Andric // Aggregates passed "byVal" need to be copied by the callee. 5980b57cec5SDimitry Andric // The callee will use a pointer to this copy, rather than the original 5990b57cec5SDimitry Andric // pointer. 6000b57cec5SDimitry Andric for (const auto &ArgDI : ArgData) { 6010b57cec5SDimitry Andric if (ArgDI.Flags.isByVal() && ArgDI.Flags.getByValSize()) { 6020b57cec5SDimitry Andric unsigned Size = ArgDI.Flags.getByValSize(); 6035ffd83dbSDimitry Andric Align Alignment = 6045ffd83dbSDimitry Andric std::max(Align(StackSlotSize), ArgDI.Flags.getNonZeroByValAlign()); 6050b57cec5SDimitry Andric // Create a new object on the stack and copy the pointee into it. 6065ffd83dbSDimitry Andric int FI = MFI.CreateStackObject(Size, Alignment, false); 6070b57cec5SDimitry Andric SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); 6080b57cec5SDimitry Andric InVals.push_back(FIN); 6090b57cec5SDimitry Andric MemOps.push_back(DAG.getMemcpy( 6105ffd83dbSDimitry Andric Chain, dl, FIN, ArgDI.SDV, DAG.getConstant(Size, dl, MVT::i32), 611*0fca6ea1SDimitry Andric Alignment, false, false, /*CI=*/nullptr, false, MachinePointerInfo(), 6125ffd83dbSDimitry Andric MachinePointerInfo())); 6130b57cec5SDimitry Andric } else { 6140b57cec5SDimitry Andric InVals.push_back(ArgDI.SDV); 6150b57cec5SDimitry Andric } 6160b57cec5SDimitry Andric } 6170b57cec5SDimitry Andric 6180b57cec5SDimitry Andric // 4. Chain mem ops nodes into a TokenFactor. 6190b57cec5SDimitry Andric if (!MemOps.empty()) { 6200b57cec5SDimitry Andric MemOps.push_back(Chain); 6210b57cec5SDimitry Andric Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOps); 6220b57cec5SDimitry Andric } 6230b57cec5SDimitry Andric 6240b57cec5SDimitry Andric return Chain; 6250b57cec5SDimitry Andric } 6260b57cec5SDimitry Andric 6270b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 6280b57cec5SDimitry Andric // Return Value Calling Convention Implementation 6290b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 6300b57cec5SDimitry Andric 6310b57cec5SDimitry Andric bool ARCTargetLowering::CanLowerReturn( 6320b57cec5SDimitry Andric CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg, 6330b57cec5SDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const { 6340b57cec5SDimitry Andric SmallVector<CCValAssign, 16> RVLocs; 6350b57cec5SDimitry Andric CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context); 6360b57cec5SDimitry Andric if (!CCInfo.CheckReturn(Outs, RetCC_ARC)) 6370b57cec5SDimitry Andric return false; 63806c3fb27SDimitry Andric if (CCInfo.getStackSize() != 0 && IsVarArg) 6390b57cec5SDimitry Andric return false; 6400b57cec5SDimitry Andric return true; 6410b57cec5SDimitry Andric } 6420b57cec5SDimitry Andric 6430b57cec5SDimitry Andric SDValue 6440b57cec5SDimitry Andric ARCTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, 6450b57cec5SDimitry Andric bool IsVarArg, 6460b57cec5SDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs, 6470b57cec5SDimitry Andric const SmallVectorImpl<SDValue> &OutVals, 6480b57cec5SDimitry Andric const SDLoc &dl, SelectionDAG &DAG) const { 6490b57cec5SDimitry Andric auto *AFI = DAG.getMachineFunction().getInfo<ARCFunctionInfo>(); 6500b57cec5SDimitry Andric MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo(); 6510b57cec5SDimitry Andric 6520b57cec5SDimitry Andric // CCValAssign - represent the assignment of 6530b57cec5SDimitry Andric // the return value to a location 6540b57cec5SDimitry Andric SmallVector<CCValAssign, 16> RVLocs; 6550b57cec5SDimitry Andric 6560b57cec5SDimitry Andric // CCState - Info about the registers and stack slot. 6570b57cec5SDimitry Andric CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs, 6580b57cec5SDimitry Andric *DAG.getContext()); 6590b57cec5SDimitry Andric 6600b57cec5SDimitry Andric // Analyze return values. 6610b57cec5SDimitry Andric if (!IsVarArg) 6625ffd83dbSDimitry Andric CCInfo.AllocateStack(AFI->getReturnStackOffset(), Align(4)); 6630b57cec5SDimitry Andric 6640b57cec5SDimitry Andric CCInfo.AnalyzeReturn(Outs, RetCC_ARC); 6650b57cec5SDimitry Andric 66606c3fb27SDimitry Andric SDValue Glue; 6670b57cec5SDimitry Andric SmallVector<SDValue, 4> RetOps(1, Chain); 6680b57cec5SDimitry Andric SmallVector<SDValue, 4> MemOpChains; 6690b57cec5SDimitry Andric // Handle return values that must be copied to memory. 6700b57cec5SDimitry Andric for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) { 6710b57cec5SDimitry Andric CCValAssign &VA = RVLocs[i]; 6720b57cec5SDimitry Andric if (VA.isRegLoc()) 6730b57cec5SDimitry Andric continue; 6740b57cec5SDimitry Andric assert(VA.isMemLoc()); 6750b57cec5SDimitry Andric if (IsVarArg) { 6760b57cec5SDimitry Andric report_fatal_error("Can't return value from vararg function in memory"); 6770b57cec5SDimitry Andric } 6780b57cec5SDimitry Andric 6790b57cec5SDimitry Andric int Offset = VA.getLocMemOffset(); 6800b57cec5SDimitry Andric unsigned ObjSize = VA.getLocVT().getStoreSize(); 6810b57cec5SDimitry Andric // Create the frame index object for the memory location. 6820b57cec5SDimitry Andric int FI = MFI.CreateFixedObject(ObjSize, Offset, false); 6830b57cec5SDimitry Andric 6840b57cec5SDimitry Andric // Create a SelectionDAG node corresponding to a store 6850b57cec5SDimitry Andric // to this memory location. 6860b57cec5SDimitry Andric SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); 6870b57cec5SDimitry Andric MemOpChains.push_back(DAG.getStore( 6880b57cec5SDimitry Andric Chain, dl, OutVals[i], FIN, 6890b57cec5SDimitry Andric MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI))); 6900b57cec5SDimitry Andric } 6910b57cec5SDimitry Andric 6920b57cec5SDimitry Andric // Transform all store nodes into one single node because 6930b57cec5SDimitry Andric // all stores are independent of each other. 6940b57cec5SDimitry Andric if (!MemOpChains.empty()) 6950b57cec5SDimitry Andric Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains); 6960b57cec5SDimitry Andric 6970b57cec5SDimitry Andric // Now handle return values copied to registers. 6980b57cec5SDimitry Andric for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) { 6990b57cec5SDimitry Andric CCValAssign &VA = RVLocs[i]; 7000b57cec5SDimitry Andric if (!VA.isRegLoc()) 7010b57cec5SDimitry Andric continue; 7020b57cec5SDimitry Andric // Copy the result values into the output registers. 70306c3fb27SDimitry Andric Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Glue); 7040b57cec5SDimitry Andric 7050b57cec5SDimitry Andric // guarantee that all emitted copies are 7060b57cec5SDimitry Andric // stuck together, avoiding something bad 70706c3fb27SDimitry Andric Glue = Chain.getValue(1); 7080b57cec5SDimitry Andric RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); 7090b57cec5SDimitry Andric } 7100b57cec5SDimitry Andric 7110b57cec5SDimitry Andric RetOps[0] = Chain; // Update chain. 7120b57cec5SDimitry Andric 71306c3fb27SDimitry Andric // Add the glue if we have it. 71406c3fb27SDimitry Andric if (Glue.getNode()) 71506c3fb27SDimitry Andric RetOps.push_back(Glue); 7160b57cec5SDimitry Andric 7170b57cec5SDimitry Andric // What to do with the RetOps? 7180b57cec5SDimitry Andric return DAG.getNode(ARCISD::RET, dl, MVT::Other, RetOps); 7190b57cec5SDimitry Andric } 7200b57cec5SDimitry Andric 7210b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 7220b57cec5SDimitry Andric // Target Optimization Hooks 7230b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 7240b57cec5SDimitry Andric 7250b57cec5SDimitry Andric SDValue ARCTargetLowering::PerformDAGCombine(SDNode *N, 7260b57cec5SDimitry Andric DAGCombinerInfo &DCI) const { 7270b57cec5SDimitry Andric return {}; 7280b57cec5SDimitry Andric } 7290b57cec5SDimitry Andric 7300b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 7310b57cec5SDimitry Andric // Addressing mode description hooks 7320b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 7330b57cec5SDimitry Andric 7340b57cec5SDimitry Andric /// Return true if the addressing mode represented by AM is legal for this 7350b57cec5SDimitry Andric /// target, for a load/store of the specified type. 7360b57cec5SDimitry Andric bool ARCTargetLowering::isLegalAddressingMode(const DataLayout &DL, 7370b57cec5SDimitry Andric const AddrMode &AM, Type *Ty, 7380b57cec5SDimitry Andric unsigned AS, 7390b57cec5SDimitry Andric Instruction *I) const { 7400b57cec5SDimitry Andric return AM.Scale == 0; 7410b57cec5SDimitry Andric } 7420b57cec5SDimitry Andric 7430b57cec5SDimitry Andric // Don't emit tail calls for the time being. 7440b57cec5SDimitry Andric bool ARCTargetLowering::mayBeEmittedAsTailCall(const CallInst *CI) const { 7450b57cec5SDimitry Andric return false; 7460b57cec5SDimitry Andric } 7470b57cec5SDimitry Andric 7480b57cec5SDimitry Andric SDValue ARCTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { 7490b57cec5SDimitry Andric const ARCRegisterInfo &ARI = *Subtarget.getRegisterInfo(); 7500b57cec5SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 7510b57cec5SDimitry Andric MachineFrameInfo &MFI = MF.getFrameInfo(); 7520b57cec5SDimitry Andric MFI.setFrameAddressIsTaken(true); 7530b57cec5SDimitry Andric 7540b57cec5SDimitry Andric EVT VT = Op.getValueType(); 7550b57cec5SDimitry Andric SDLoc dl(Op); 756647cbc5dSDimitry Andric assert(Op.getConstantOperandVal(0) == 0 && 7570b57cec5SDimitry Andric "Only support lowering frame addr of current frame."); 7588bcb0991SDimitry Andric Register FrameReg = ARI.getFrameRegister(MF); 7590b57cec5SDimitry Andric return DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT); 7600b57cec5SDimitry Andric } 7610b57cec5SDimitry Andric 7620b57cec5SDimitry Andric SDValue ARCTargetLowering::LowerGlobalAddress(SDValue Op, 7630b57cec5SDimitry Andric SelectionDAG &DAG) const { 7640b57cec5SDimitry Andric const GlobalAddressSDNode *GN = cast<GlobalAddressSDNode>(Op); 7650b57cec5SDimitry Andric const GlobalValue *GV = GN->getGlobal(); 7660b57cec5SDimitry Andric SDLoc dl(GN); 7670b57cec5SDimitry Andric int64_t Offset = GN->getOffset(); 7680b57cec5SDimitry Andric SDValue GA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, Offset); 7690b57cec5SDimitry Andric return DAG.getNode(ARCISD::GAWRAPPER, dl, MVT::i32, GA); 7700b57cec5SDimitry Andric } 7710b57cec5SDimitry Andric 7720b57cec5SDimitry Andric static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) { 7730b57cec5SDimitry Andric MachineFunction &MF = DAG.getMachineFunction(); 7740b57cec5SDimitry Andric auto *FuncInfo = MF.getInfo<ARCFunctionInfo>(); 7750b57cec5SDimitry Andric 7760b57cec5SDimitry Andric // vastart just stores the address of the VarArgsFrameIndex slot into the 7770b57cec5SDimitry Andric // memory location argument. 7780b57cec5SDimitry Andric SDLoc dl(Op); 7790b57cec5SDimitry Andric EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(DAG.getDataLayout()); 7800b57cec5SDimitry Andric SDValue FR = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), PtrVT); 7810b57cec5SDimitry Andric const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); 7820b57cec5SDimitry Andric return DAG.getStore(Op.getOperand(0), dl, FR, Op.getOperand(1), 7830b57cec5SDimitry Andric MachinePointerInfo(SV)); 7840b57cec5SDimitry Andric } 7850b57cec5SDimitry Andric 7860b57cec5SDimitry Andric SDValue ARCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { 7870b57cec5SDimitry Andric switch (Op.getOpcode()) { 7880b57cec5SDimitry Andric case ISD::GlobalAddress: 7890b57cec5SDimitry Andric return LowerGlobalAddress(Op, DAG); 7900b57cec5SDimitry Andric case ISD::FRAMEADDR: 7910b57cec5SDimitry Andric return LowerFRAMEADDR(Op, DAG); 7920b57cec5SDimitry Andric case ISD::SELECT_CC: 7930b57cec5SDimitry Andric return LowerSELECT_CC(Op, DAG); 7940b57cec5SDimitry Andric case ISD::BR_CC: 7950b57cec5SDimitry Andric return LowerBR_CC(Op, DAG); 7960b57cec5SDimitry Andric case ISD::SIGN_EXTEND_INREG: 7970b57cec5SDimitry Andric return LowerSIGN_EXTEND_INREG(Op, DAG); 7980b57cec5SDimitry Andric case ISD::JumpTable: 7990b57cec5SDimitry Andric return LowerJumpTable(Op, DAG); 8000b57cec5SDimitry Andric case ISD::VASTART: 8010b57cec5SDimitry Andric return LowerVASTART(Op, DAG); 802349cc55cSDimitry Andric case ISD::READCYCLECOUNTER: 803349cc55cSDimitry Andric // As of LLVM 3.8, the lowering code insists that we customize it even 804349cc55cSDimitry Andric // though we've declared the i32 version as legal. This is because it only 805349cc55cSDimitry Andric // thinks i64 is the truly supported version. We've already converted the 806349cc55cSDimitry Andric // i64 version to a widened i32. 807349cc55cSDimitry Andric assert(Op.getSimpleValueType() == MVT::i32); 808349cc55cSDimitry Andric return Op; 8090b57cec5SDimitry Andric default: 8100b57cec5SDimitry Andric llvm_unreachable("unimplemented operand"); 8110b57cec5SDimitry Andric } 8120b57cec5SDimitry Andric } 813