LCOV - code coverage report
Current view: top level - lib/Target/WebAssembly - WebAssemblyISelLowering.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 363 399 91.0 %
Date: 2018-10-20 13:21:21 Functions: 31 32 96.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //=- WebAssemblyISelLowering.cpp - WebAssembly DAG Lowering Implementation -==//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : ///
      10             : /// \file
      11             : /// This file implements the WebAssemblyTargetLowering class.
      12             : ///
      13             : //===----------------------------------------------------------------------===//
      14             : 
      15             : #include "WebAssemblyISelLowering.h"
      16             : #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
      17             : #include "WebAssemblyMachineFunctionInfo.h"
      18             : #include "WebAssemblySubtarget.h"
      19             : #include "WebAssemblyTargetMachine.h"
      20             : #include "llvm/CodeGen/Analysis.h"
      21             : #include "llvm/CodeGen/CallingConvLower.h"
      22             : #include "llvm/CodeGen/MachineInstrBuilder.h"
      23             : #include "llvm/CodeGen/MachineJumpTableInfo.h"
      24             : #include "llvm/CodeGen/MachineRegisterInfo.h"
      25             : #include "llvm/CodeGen/SelectionDAG.h"
      26             : #include "llvm/IR/DiagnosticInfo.h"
      27             : #include "llvm/IR/DiagnosticPrinter.h"
      28             : #include "llvm/IR/Function.h"
      29             : #include "llvm/IR/Intrinsics.h"
      30             : #include "llvm/Support/Debug.h"
      31             : #include "llvm/Support/ErrorHandling.h"
      32             : #include "llvm/Support/raw_ostream.h"
      33             : #include "llvm/Target/TargetOptions.h"
      34             : using namespace llvm;
      35             : 
      36             : #define DEBUG_TYPE "wasm-lower"
      37             : 
      38             : // Emit proposed instructions that may not have been implemented in engines
      39             : cl::opt<bool> EnableUnimplementedWasmSIMDInstrs(
      40             :     "wasm-enable-unimplemented-simd",
      41             :     cl::desc("Emit potentially-unimplemented WebAssembly SIMD instructions"),
      42             :     cl::init(false));
      43             : 
      44         293 : WebAssemblyTargetLowering::WebAssemblyTargetLowering(
      45         293 :     const TargetMachine &TM, const WebAssemblySubtarget &STI)
      46         293 :     : TargetLowering(TM), Subtarget(&STI) {
      47         293 :   auto MVTPtr = Subtarget->hasAddr64() ? MVT::i64 : MVT::i32;
      48             : 
      49             :   // Booleans always contain 0 or 1.
      50             :   setBooleanContents(ZeroOrOneBooleanContent);
      51             :   // WebAssembly does not produce floating-point exceptions on normal floating
      52             :   // point operations.
      53             :   setHasFloatingPointExceptions(false);
      54             :   // We don't know the microarchitecture here, so just reduce register pressure.
      55             :   setSchedulingPreference(Sched::RegPressure);
      56             :   // Tell ISel that we have a stack pointer.
      57         293 :   setStackPointerRegisterToSaveRestore(
      58         293 :       Subtarget->hasAddr64() ? WebAssembly::SP64 : WebAssembly::SP32);
      59             :   // Set up the register classes.
      60             :   addRegisterClass(MVT::i32, &WebAssembly::I32RegClass);
      61             :   addRegisterClass(MVT::i64, &WebAssembly::I64RegClass);
      62             :   addRegisterClass(MVT::f32, &WebAssembly::F32RegClass);
      63             :   addRegisterClass(MVT::f64, &WebAssembly::F64RegClass);
      64         293 :   if (Subtarget->hasSIMD128()) {
      65             :     addRegisterClass(MVT::v16i8, &WebAssembly::V128RegClass);
      66             :     addRegisterClass(MVT::v8i16, &WebAssembly::V128RegClass);
      67             :     addRegisterClass(MVT::v4i32, &WebAssembly::V128RegClass);
      68             :     addRegisterClass(MVT::v4f32, &WebAssembly::V128RegClass);
      69          23 :     if (EnableUnimplementedWasmSIMDInstrs) {
      70             :       addRegisterClass(MVT::v2i64, &WebAssembly::V128RegClass);
      71             :       addRegisterClass(MVT::v2f64, &WebAssembly::V128RegClass);
      72             :     }
      73             :   }
      74             :   // Compute derived properties from the register classes.
      75         586 :   computeRegisterProperties(Subtarget->getRegisterInfo());
      76             : 
      77             :   setOperationAction(ISD::GlobalAddress, MVTPtr, Custom);
      78             :   setOperationAction(ISD::ExternalSymbol, MVTPtr, Custom);
      79             :   setOperationAction(ISD::JumpTable, MVTPtr, Custom);
      80             :   setOperationAction(ISD::BlockAddress, MVTPtr, Custom);
      81             :   setOperationAction(ISD::BRIND, MVT::Other, Custom);
      82             : 
      83             :   // Take the default expansion for va_arg, va_copy, and va_end. There is no
      84             :   // default action for va_start, so we do that custom.
      85             :   setOperationAction(ISD::VASTART, MVT::Other, Custom);
      86             :   setOperationAction(ISD::VAARG, MVT::Other, Expand);
      87             :   setOperationAction(ISD::VACOPY, MVT::Other, Expand);
      88             :   setOperationAction(ISD::VAEND, MVT::Other, Expand);
      89             : 
      90        1465 :   for (auto T : {MVT::f32, MVT::f64, MVT::v4f32, MVT::v2f64}) {
      91             :     // Don't expand the floating-point types to constant pools.
      92        1172 :     setOperationAction(ISD::ConstantFP, T, Legal);
      93             :     // Expand floating-point comparisons.
      94       18752 :     for (auto CC : {ISD::SETO, ISD::SETUO, ISD::SETUEQ, ISD::SETONE,
      95       10548 :                     ISD::SETULT, ISD::SETULE, ISD::SETUGT, ISD::SETUGE})
      96             :       setCondCodeAction(CC, T, Expand);
      97             :     // Expand floating-point library function operators.
      98       14064 :     for (auto Op :
      99        8204 :          {ISD::FSIN, ISD::FCOS, ISD::FSINCOS, ISD::FPOW, ISD::FREM, ISD::FMA})
     100             :       setOperationAction(Op, T, Expand);
     101             :     // Note supported floating-point library function operators that otherwise
     102             :     // default to expand.
     103       11720 :     for (auto Op :
     104        7032 :          {ISD::FCEIL, ISD::FFLOOR, ISD::FTRUNC, ISD::FNEARBYINT, ISD::FRINT})
     105             :       setOperationAction(Op, T, Legal);
     106             :     // Support minnan and maxnan, which otherwise default to expand.
     107             :     setOperationAction(ISD::FMINNAN, T, Legal);
     108             :     setOperationAction(ISD::FMAXNAN, T, Legal);
     109             :     // WebAssembly currently has no builtin f16 support.
     110             :     setOperationAction(ISD::FP16_TO_FP, T, Expand);
     111             :     setOperationAction(ISD::FP_TO_FP16, T, Expand);
     112             :     setLoadExtAction(ISD::EXTLOAD, T, MVT::f16, Expand);
     113             :     setTruncStoreAction(T, MVT::f16, Expand);
     114             :   }
     115             : 
     116         879 :   for (auto T : {MVT::i32, MVT::i64}) {
     117             :     // Expand unavailable integer operations.
     118       16408 :     for (auto Op :
     119             :          {ISD::BSWAP, ISD::SMUL_LOHI, ISD::UMUL_LOHI, ISD::MULHS, ISD::MULHU,
     120             :           ISD::SDIVREM, ISD::UDIVREM, ISD::SHL_PARTS, ISD::SRA_PARTS,
     121        8790 :           ISD::SRL_PARTS, ISD::ADDC, ISD::ADDE, ISD::SUBC, ISD::SUBE}) {
     122             :       setOperationAction(Op, T, Expand);
     123             :     }
     124             :   }
     125             : 
     126             :   // There is no i64x2.mul instruction
     127             :   setOperationAction(ISD::MUL, MVT::v2i64, Expand);
     128             : 
     129             :   // We have custom shuffle lowering to expose the shuffle mask
     130         293 :   if (Subtarget->hasSIMD128()) {
     131         115 :     for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v4f32}) {
     132             :       setOperationAction(ISD::VECTOR_SHUFFLE, T, Custom);
     133             :     }
     134          23 :     if (EnableUnimplementedWasmSIMDInstrs) {
     135             :       setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v2i64, Custom);
     136             :       setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v2f64, Custom);
     137             :     }
     138             :   }
     139             : 
     140             :   // As a special case, these operators use the type to mean the type to
     141             :   // sign-extend from.
     142             :   setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
     143         293 :   if (!Subtarget->hasSignExt()) {
     144        1068 :     for (auto T : {MVT::i8, MVT::i16, MVT::i32})
     145             :       setOperationAction(ISD::SIGN_EXTEND_INREG, T, Expand);
     146             :   }
     147             : 
     148             :   // Dynamic stack allocation: use the default expansion.
     149             :   setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
     150             :   setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
     151             :   setOperationAction(ISD::DYNAMIC_STACKALLOC, MVTPtr, Expand);
     152             : 
     153             :   setOperationAction(ISD::FrameIndex, MVT::i32, Custom);
     154             :   setOperationAction(ISD::CopyToReg, MVT::Other, Custom);
     155             : 
     156             :   // Expand these forms; we pattern-match the forms that we can handle in isel.
     157        1465 :   for (auto T : {MVT::i32, MVT::i64, MVT::f32, MVT::f64})
     158        3516 :     for (auto Op : {ISD::BR_CC, ISD::SELECT_CC})
     159             :       setOperationAction(Op, T, Expand);
     160             : 
     161             :   // We have custom switch handling.
     162             :   setOperationAction(ISD::BR_JT, MVT::Other, Custom);
     163             : 
     164             :   // WebAssembly doesn't have:
     165             :   //  - Floating-point extending loads.
     166             :   //  - Floating-point truncating stores.
     167             :   //  - i1 extending loads.
     168             :   setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f32, Expand);
     169             :   setTruncStoreAction(MVT::f64, MVT::f32, Expand);
     170        2051 :   for (auto T : MVT::integer_valuetypes())
     171        7032 :     for (auto Ext : {ISD::EXTLOAD, ISD::ZEXTLOAD, ISD::SEXTLOAD})
     172             :       setLoadExtAction(Ext, T, MVT::i1, Promote);
     173             : 
     174             :   // Trap lowers to wasm unreachable
     175             :   setOperationAction(ISD::TRAP, MVT::Other, Legal);
     176             : 
     177             :   // Exception handling intrinsics
     178             :   setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
     179             : 
     180             :   setMaxAtomicSizeInBitsSupported(64);
     181         293 : }
     182             : 
     183             : TargetLowering::AtomicExpansionKind
     184         260 : WebAssemblyTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const {
     185             :   // We have wasm instructions for these
     186             :   switch (AI->getOperation()) {
     187             :   case AtomicRMWInst::Add:
     188             :   case AtomicRMWInst::Sub:
     189             :   case AtomicRMWInst::And:
     190             :   case AtomicRMWInst::Or:
     191             :   case AtomicRMWInst::Xor:
     192             :   case AtomicRMWInst::Xchg:
     193             :     return AtomicExpansionKind::None;
     194             :   default:
     195             :     break;
     196             :   }
     197             :   return AtomicExpansionKind::CmpXChg;
     198             : }
     199             : 
     200         478 : FastISel *WebAssemblyTargetLowering::createFastISel(
     201             :     FunctionLoweringInfo &FuncInfo, const TargetLibraryInfo *LibInfo) const {
     202         478 :   return WebAssembly::createFastISel(FuncInfo, LibInfo);
     203             : }
     204             : 
     205         228 : bool WebAssemblyTargetLowering::isOffsetFoldingLegal(
     206             :     const GlobalAddressSDNode * /*GA*/) const {
     207             :   // All offsets can be folded.
     208         228 :   return true;
     209             : }
     210             : 
     211        2011 : MVT WebAssemblyTargetLowering::getScalarShiftAmountTy(const DataLayout & /*DL*/,
     212             :                                                       EVT VT) const {
     213        2011 :   unsigned BitWidth = NextPowerOf2(VT.getSizeInBits() - 1);
     214        2011 :   if (BitWidth > 1 && BitWidth < 8)
     215             :     BitWidth = 8;
     216             : 
     217        2010 :   if (BitWidth > 64) {
     218             :     // The shift will be lowered to a libcall, and compiler-rt libcalls expect
     219             :     // the count to be an i32.
     220             :     BitWidth = 32;
     221             :     assert(BitWidth >= Log2_32_Ceil(VT.getSizeInBits()) &&
     222             :            "32-bit shift counts ought to be enough for anyone");
     223             :   }
     224             : 
     225        2011 :   MVT Result = MVT::getIntegerVT(BitWidth);
     226             :   assert(Result != MVT::INVALID_SIMPLE_VALUE_TYPE &&
     227             :          "Unable to represent scalar shift amount type");
     228        2011 :   return Result;
     229             : }
     230             : 
     231             : // Lower an fp-to-int conversion operator from the LLVM opcode, which has an
     232             : // undefined result on invalid/overflow, to the WebAssembly opcode, which
     233             : // traps on invalid/overflow.
     234          24 : static MachineBasicBlock *LowerFPToInt(MachineInstr &MI, DebugLoc DL,
     235             :                                        MachineBasicBlock *BB,
     236             :                                        const TargetInstrInfo &TII,
     237             :                                        bool IsUnsigned, bool Int64,
     238             :                                        bool Float64, unsigned LoweredOpcode) {
     239          24 :   MachineRegisterInfo &MRI = BB->getParent()->getRegInfo();
     240             : 
     241          24 :   unsigned OutReg = MI.getOperand(0).getReg();
     242          24 :   unsigned InReg = MI.getOperand(1).getReg();
     243             : 
     244          24 :   unsigned Abs = Float64 ? WebAssembly::ABS_F64 : WebAssembly::ABS_F32;
     245          24 :   unsigned FConst = Float64 ? WebAssembly::CONST_F64 : WebAssembly::CONST_F32;
     246          24 :   unsigned LT = Float64 ? WebAssembly::LT_F64 : WebAssembly::LT_F32;
     247          24 :   unsigned GE = Float64 ? WebAssembly::GE_F64 : WebAssembly::GE_F32;
     248          24 :   unsigned IConst = Int64 ? WebAssembly::CONST_I64 : WebAssembly::CONST_I32;
     249             :   unsigned Eqz = WebAssembly::EQZ_I32;
     250             :   unsigned And = WebAssembly::AND_I32;
     251          24 :   int64_t Limit = Int64 ? INT64_MIN : INT32_MIN;
     252          24 :   int64_t Substitute = IsUnsigned ? 0 : Limit;
     253          24 :   double CmpVal = IsUnsigned ? -(double)Limit * 2.0 : -(double)Limit;
     254          24 :   auto &Context = BB->getParent()->getFunction().getContext();
     255          24 :   Type *Ty = Float64 ? Type::getDoubleTy(Context) : Type::getFloatTy(Context);
     256             : 
     257          24 :   const BasicBlock *LLVM_BB = BB->getBasicBlock();
     258          24 :   MachineFunction *F = BB->getParent();
     259          24 :   MachineBasicBlock *TrueMBB = F->CreateMachineBasicBlock(LLVM_BB);
     260          24 :   MachineBasicBlock *FalseMBB = F->CreateMachineBasicBlock(LLVM_BB);
     261          24 :   MachineBasicBlock *DoneMBB = F->CreateMachineBasicBlock(LLVM_BB);
     262             : 
     263          24 :   MachineFunction::iterator It = ++BB->getIterator();
     264             :   F->insert(It, FalseMBB);
     265             :   F->insert(It, TrueMBB);
     266             :   F->insert(It, DoneMBB);
     267             : 
     268             :   // Transfer the remainder of BB and its successor edges to DoneMBB.
     269          24 :   DoneMBB->splice(DoneMBB->begin(), BB,
     270             :                   std::next(MachineBasicBlock::iterator(MI)), BB->end());
     271          24 :   DoneMBB->transferSuccessorsAndUpdatePHIs(BB);
     272             : 
     273          24 :   BB->addSuccessor(TrueMBB);
     274          24 :   BB->addSuccessor(FalseMBB);
     275          24 :   TrueMBB->addSuccessor(DoneMBB);
     276          24 :   FalseMBB->addSuccessor(DoneMBB);
     277             : 
     278             :   unsigned Tmp0, Tmp1, CmpReg, EqzReg, FalseReg, TrueReg;
     279          24 :   Tmp0 = MRI.createVirtualRegister(MRI.getRegClass(InReg));
     280          24 :   Tmp1 = MRI.createVirtualRegister(MRI.getRegClass(InReg));
     281          24 :   CmpReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
     282          24 :   EqzReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
     283          24 :   FalseReg = MRI.createVirtualRegister(MRI.getRegClass(OutReg));
     284          24 :   TrueReg = MRI.createVirtualRegister(MRI.getRegClass(OutReg));
     285             : 
     286          24 :   MI.eraseFromParent();
     287             :   // For signed numbers, we can do a single comparison to determine whether
     288             :   // fabs(x) is within range.
     289          24 :   if (IsUnsigned) {
     290             :     Tmp0 = InReg;
     291             :   } else {
     292          12 :     BuildMI(BB, DL, TII.get(Abs), Tmp0).addReg(InReg);
     293             :   }
     294          24 :   BuildMI(BB, DL, TII.get(FConst), Tmp1)
     295          24 :       .addFPImm(cast<ConstantFP>(ConstantFP::get(Ty, CmpVal)));
     296          24 :   BuildMI(BB, DL, TII.get(LT), CmpReg).addReg(Tmp0).addReg(Tmp1);
     297             : 
     298             :   // For unsigned numbers, we have to do a separate comparison with zero.
     299          24 :   if (IsUnsigned) {
     300          12 :     Tmp1 = MRI.createVirtualRegister(MRI.getRegClass(InReg));
     301             :     unsigned SecondCmpReg =
     302          12 :         MRI.createVirtualRegister(&WebAssembly::I32RegClass);
     303          12 :     unsigned AndReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
     304          12 :     BuildMI(BB, DL, TII.get(FConst), Tmp1)
     305          12 :         .addFPImm(cast<ConstantFP>(ConstantFP::get(Ty, 0.0)));
     306          12 :     BuildMI(BB, DL, TII.get(GE), SecondCmpReg).addReg(Tmp0).addReg(Tmp1);
     307          12 :     BuildMI(BB, DL, TII.get(And), AndReg).addReg(CmpReg).addReg(SecondCmpReg);
     308             :     CmpReg = AndReg;
     309             :   }
     310             : 
     311          24 :   BuildMI(BB, DL, TII.get(Eqz), EqzReg).addReg(CmpReg);
     312             : 
     313             :   // Create the CFG diamond to select between doing the conversion or using
     314             :   // the substitute value.
     315          24 :   BuildMI(BB, DL, TII.get(WebAssembly::BR_IF)).addMBB(TrueMBB).addReg(EqzReg);
     316          24 :   BuildMI(FalseMBB, DL, TII.get(LoweredOpcode), FalseReg).addReg(InReg);
     317          24 :   BuildMI(FalseMBB, DL, TII.get(WebAssembly::BR)).addMBB(DoneMBB);
     318          24 :   BuildMI(TrueMBB, DL, TII.get(IConst), TrueReg).addImm(Substitute);
     319          48 :   BuildMI(*DoneMBB, DoneMBB->begin(), DL, TII.get(TargetOpcode::PHI), OutReg)
     320          24 :       .addReg(FalseReg)
     321             :       .addMBB(FalseMBB)
     322          24 :       .addReg(TrueReg)
     323             :       .addMBB(TrueMBB);
     324             : 
     325          24 :   return DoneMBB;
     326             : }
     327             : 
     328          24 : MachineBasicBlock *WebAssemblyTargetLowering::EmitInstrWithCustomInserter(
     329             :     MachineInstr &MI, MachineBasicBlock *BB) const {
     330          24 :   const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
     331             :   DebugLoc DL = MI.getDebugLoc();
     332             : 
     333          48 :   switch (MI.getOpcode()) {
     334           0 :   default:
     335           0 :     llvm_unreachable("Unexpected instr type to insert");
     336             :   case WebAssembly::FP_TO_SINT_I32_F32:
     337          10 :     return LowerFPToInt(MI, DL, BB, TII, false, false, false,
     338             :                         WebAssembly::I32_TRUNC_S_F32);
     339             :   case WebAssembly::FP_TO_UINT_I32_F32:
     340          10 :     return LowerFPToInt(MI, DL, BB, TII, true, false, false,
     341             :                         WebAssembly::I32_TRUNC_U_F32);
     342             :   case WebAssembly::FP_TO_SINT_I64_F32:
     343           2 :     return LowerFPToInt(MI, DL, BB, TII, false, true, false,
     344             :                         WebAssembly::I64_TRUNC_S_F32);
     345             :   case WebAssembly::FP_TO_UINT_I64_F32:
     346           2 :     return LowerFPToInt(MI, DL, BB, TII, true, true, false,
     347             :                         WebAssembly::I64_TRUNC_U_F32);
     348             :   case WebAssembly::FP_TO_SINT_I32_F64:
     349           2 :     return LowerFPToInt(MI, DL, BB, TII, false, false, true,
     350             :                         WebAssembly::I32_TRUNC_S_F64);
     351             :   case WebAssembly::FP_TO_UINT_I32_F64:
     352           2 :     return LowerFPToInt(MI, DL, BB, TII, true, false, true,
     353             :                         WebAssembly::I32_TRUNC_U_F64);
     354             :   case WebAssembly::FP_TO_SINT_I64_F64:
     355          10 :     return LowerFPToInt(MI, DL, BB, TII, false, true, true,
     356             :                         WebAssembly::I64_TRUNC_S_F64);
     357             :   case WebAssembly::FP_TO_UINT_I64_F64:
     358          10 :     return LowerFPToInt(MI, DL, BB, TII, true, true, true,
     359             :                         WebAssembly::I64_TRUNC_U_F64);
     360             :     llvm_unreachable("Unexpected instruction to emit with custom inserter");
     361             :   }
     362             : }
     363             : 
     364             : const char *
     365           4 : WebAssemblyTargetLowering::getTargetNodeName(unsigned Opcode) const {
     366           4 :   switch (static_cast<WebAssemblyISD::NodeType>(Opcode)) {
     367             :   case WebAssemblyISD::FIRST_NUMBER:
     368             :     break;
     369             : #define HANDLE_NODETYPE(NODE)                                                  \
     370             :   case WebAssemblyISD::NODE:                                                   \
     371             :     return "WebAssemblyISD::" #NODE;
     372             : #include "WebAssemblyISD.def"
     373             : #undef HANDLE_NODETYPE
     374             :   }
     375           0 :   return nullptr;
     376             : }
     377             : 
     378             : std::pair<unsigned, const TargetRegisterClass *>
     379          28 : WebAssemblyTargetLowering::getRegForInlineAsmConstraint(
     380             :     const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const {
     381             :   // First, see if this is a constraint that directly corresponds to a
     382             :   // WebAssembly register class.
     383          28 :   if (Constraint.size() == 1) {
     384          28 :     switch (Constraint[0]) {
     385          14 :     case 'r':
     386             :       assert(VT != MVT::iPTR && "Pointer MVT not expected here");
     387          14 :       if (Subtarget->hasSIMD128() && VT.isVector()) {
     388           0 :         if (VT.getSizeInBits() == 128)
     389           0 :           return std::make_pair(0U, &WebAssembly::V128RegClass);
     390             :       }
     391          28 :       if (VT.isInteger() && !VT.isVector()) {
     392          14 :         if (VT.getSizeInBits() <= 32)
     393          12 :           return std::make_pair(0U, &WebAssembly::I32RegClass);
     394           2 :         if (VT.getSizeInBits() <= 64)
     395           2 :           return std::make_pair(0U, &WebAssembly::I64RegClass);
     396             :       }
     397             :       break;
     398             :     default:
     399             :       break;
     400             :     }
     401             :   }
     402             : 
     403          14 :   return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
     404             : }
     405             : 
     406           3 : bool WebAssemblyTargetLowering::isCheapToSpeculateCttz() const {
     407             :   // Assume ctz is a relatively cheap operation.
     408           3 :   return true;
     409             : }
     410             : 
     411           3 : bool WebAssemblyTargetLowering::isCheapToSpeculateCtlz() const {
     412             :   // Assume clz is a relatively cheap operation.
     413           3 :   return true;
     414             : }
     415             : 
     416        2313 : bool WebAssemblyTargetLowering::isLegalAddressingMode(const DataLayout &DL,
     417             :                                                       const AddrMode &AM,
     418             :                                                       Type *Ty, unsigned AS,
     419             :                                                       Instruction *I) const {
     420             :   // WebAssembly offsets are added as unsigned without wrapping. The
     421             :   // isLegalAddressingMode gives us no way to determine if wrapping could be
     422             :   // happening, so we approximate this by accepting only non-negative offsets.
     423        2313 :   if (AM.BaseOffs < 0)
     424             :     return false;
     425             : 
     426             :   // WebAssembly has no scale register operands.
     427        2235 :   if (AM.Scale != 0)
     428         184 :     return false;
     429             : 
     430             :   // Everything else is legal.
     431             :   return true;
     432             : }
     433             : 
     434          74 : bool WebAssemblyTargetLowering::allowsMisalignedMemoryAccesses(
     435             :     EVT /*VT*/, unsigned /*AddrSpace*/, unsigned /*Align*/, bool *Fast) const {
     436             :   // WebAssembly supports unaligned accesses, though it should be declared
     437             :   // with the p2align attribute on loads and stores which do so, and there
     438             :   // may be a performance impact. We tell LLVM they're "fast" because
     439             :   // for the kinds of things that LLVM uses this for (merging adjacent stores
     440             :   // of constants, etc.), WebAssembly implementations will either want the
     441             :   // unaligned access or they'll split anyway.
     442          74 :   if (Fast)
     443           3 :     *Fast = true;
     444          74 :   return true;
     445             : }
     446             : 
     447          25 : bool WebAssemblyTargetLowering::isIntDivCheap(EVT VT,
     448             :                                               AttributeList Attr) const {
     449             :   // The current thinking is that wasm engines will perform this optimization,
     450             :   // so we can save on code size.
     451          25 :   return true;
     452             : }
     453             : 
     454        1890 : EVT WebAssemblyTargetLowering::getSetCCResultType(const DataLayout &DL,
     455             :                                                   LLVMContext &C,
     456             :                                                   EVT VT) const {
     457        1890 :   if (VT.isVector())
     458         116 :     return VT.changeVectorElementTypeToInteger();
     459             : 
     460        1774 :   return TargetLowering::getSetCCResultType(DL, C, VT);
     461             : }
     462             : 
     463         105 : bool WebAssemblyTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info,
     464             :                                                    const CallInst &I,
     465             :                                                    MachineFunction &MF,
     466             :                                                    unsigned Intrinsic) const {
     467         105 :   switch (Intrinsic) {
     468           8 :   case Intrinsic::wasm_atomic_notify:
     469           8 :     Info.opc = ISD::INTRINSIC_W_CHAIN;
     470           8 :     Info.memVT = MVT::i32;
     471           8 :     Info.ptrVal = I.getArgOperand(0);
     472           8 :     Info.offset = 0;
     473           8 :     Info.align = 4;
     474             :     // atomic.notify instruction does not really load the memory specified with
     475             :     // this argument, but MachineMemOperand should either be load or store, so
     476             :     // we set this to a load.
     477             :     // FIXME Volatile isn't really correct, but currently all LLVM atomic
     478             :     // instructions are treated as volatiles in the backend, so we should be
     479             :     // consistent. The same applies for wasm_atomic_wait intrinsics too.
     480           8 :     Info.flags = MachineMemOperand::MOVolatile | MachineMemOperand::MOLoad;
     481           8 :     return true;
     482           8 :   case Intrinsic::wasm_atomic_wait_i32:
     483           8 :     Info.opc = ISD::INTRINSIC_W_CHAIN;
     484           8 :     Info.memVT = MVT::i32;
     485           8 :     Info.ptrVal = I.getArgOperand(0);
     486           8 :     Info.offset = 0;
     487           8 :     Info.align = 4;
     488           8 :     Info.flags = MachineMemOperand::MOVolatile | MachineMemOperand::MOLoad;
     489           8 :     return true;
     490           6 :   case Intrinsic::wasm_atomic_wait_i64:
     491           6 :     Info.opc = ISD::INTRINSIC_W_CHAIN;
     492           6 :     Info.memVT = MVT::i64;
     493           6 :     Info.ptrVal = I.getArgOperand(0);
     494           6 :     Info.offset = 0;
     495           6 :     Info.align = 8;
     496           6 :     Info.flags = MachineMemOperand::MOVolatile | MachineMemOperand::MOLoad;
     497           6 :     return true;
     498             :   default:
     499             :     return false;
     500             :   }
     501             : }
     502             : 
     503             : //===----------------------------------------------------------------------===//
     504             : // WebAssembly Lowering private implementation.
     505             : //===----------------------------------------------------------------------===//
     506             : 
     507             : //===----------------------------------------------------------------------===//
     508             : // Lowering Code
     509             : //===----------------------------------------------------------------------===//
     510             : 
     511           1 : static void fail(const SDLoc &DL, SelectionDAG &DAG, const char *msg) {
     512           1 :   MachineFunction &MF = DAG.getMachineFunction();
     513           2 :   DAG.getContext()->diagnose(
     514           2 :       DiagnosticInfoUnsupported(MF.getFunction(), msg, DL.getDebugLoc()));
     515           1 : }
     516             : 
     517             : // Test whether the given calling convention is supported.
     518             : static bool CallingConvSupported(CallingConv::ID CallConv) {
     519             :   // We currently support the language-independent target-independent
     520             :   // conventions. We don't yet have a way to annotate calls with properties like
     521             :   // "cold", and we don't have any call-clobbered registers, so these are mostly
     522             :   // all handled the same.
     523        5781 :   return CallConv == CallingConv::C || CallConv == CallingConv::Fast ||
     524           2 :          CallConv == CallingConv::Cold ||
     525           1 :          CallConv == CallingConv::PreserveMost ||
     526        5781 :          CallConv == CallingConv::PreserveAll ||
     527           0 :          CallConv == CallingConv::CXX_FAST_TLS;
     528             : }
     529             : 
     530             : SDValue
     531         520 : WebAssemblyTargetLowering::LowerCall(CallLoweringInfo &CLI,
     532             :                                      SmallVectorImpl<SDValue> &InVals) const {
     533         520 :   SelectionDAG &DAG = CLI.DAG;
     534             :   SDLoc DL = CLI.DL;
     535         520 :   SDValue Chain = CLI.Chain;
     536         520 :   SDValue Callee = CLI.Callee;
     537         520 :   MachineFunction &MF = DAG.getMachineFunction();
     538        1040 :   auto Layout = MF.getDataLayout();
     539             : 
     540         520 :   CallingConv::ID CallConv = CLI.CallConv;
     541             :   if (!CallingConvSupported(CallConv))
     542           0 :     fail(DL, DAG,
     543             :          "WebAssembly doesn't support language-specific or target-specific "
     544             :          "calling conventions yet");
     545         520 :   if (CLI.IsPatchPoint)
     546           0 :     fail(DL, DAG, "WebAssembly doesn't support patch point yet");
     547             : 
     548             :   // WebAssembly doesn't currently support explicit tail calls. If they are
     549             :   // required, fail. Otherwise, just disable them.
     550           1 :   if ((CallConv == CallingConv::Fast && CLI.IsTailCall &&
     551         521 :        MF.getTarget().Options.GuaranteedTailCallOpt) ||
     552             :       (CLI.CS && CLI.CS.isMustTailCall()))
     553           0 :     fail(DL, DAG, "WebAssembly doesn't support tail call yet");
     554         520 :   CLI.IsTailCall = false;
     555             : 
     556             :   SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
     557         520 :   if (Ins.size() > 1)
     558           0 :     fail(DL, DAG, "WebAssembly doesn't support more than 1 returned value yet");
     559             : 
     560             :   SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
     561             :   SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
     562             :   unsigned NumFixedArgs = 0;
     563        1253 :   for (unsigned i = 0; i < Outs.size(); ++i) {
     564             :     const ISD::OutputArg &Out = Outs[i];
     565             :     SDValue &OutVal = OutVals[i];
     566         733 :     if (Out.Flags.isNest())
     567           0 :       fail(DL, DAG, "WebAssembly hasn't implemented nest arguments");
     568         733 :     if (Out.Flags.isInAlloca())
     569           0 :       fail(DL, DAG, "WebAssembly hasn't implemented inalloca arguments");
     570         733 :     if (Out.Flags.isInConsecutiveRegs())
     571           0 :       fail(DL, DAG, "WebAssembly hasn't implemented cons regs arguments");
     572         733 :     if (Out.Flags.isInConsecutiveRegsLast())
     573           0 :       fail(DL, DAG, "WebAssembly hasn't implemented cons regs last arguments");
     574         733 :     if (Out.Flags.isByVal() && Out.Flags.getByValSize() != 0) {
     575           8 :       auto &MFI = MF.getFrameInfo();
     576           8 :       int FI = MFI.CreateStackObject(Out.Flags.getByValSize(),
     577             :                                      Out.Flags.getByValAlign(),
     578             :                                      /*isSS=*/false);
     579             :       SDValue SizeNode =
     580           8 :           DAG.getConstant(Out.Flags.getByValSize(), DL, MVT::i32);
     581           8 :       SDValue FINode = DAG.getFrameIndex(FI, getPointerTy(Layout));
     582           8 :       Chain = DAG.getMemcpy(
     583             :           Chain, DL, FINode, OutVal, SizeNode, Out.Flags.getByValAlign(),
     584             :           /*isVolatile*/ false, /*AlwaysInline=*/false,
     585           8 :           /*isTailCall*/ false, MachinePointerInfo(), MachinePointerInfo());
     586           8 :       OutVal = FINode;
     587             :     }
     588             :     // Count the number of fixed args *after* legalization.
     589         733 :     NumFixedArgs += Out.IsFixed;
     590             :   }
     591             : 
     592         520 :   bool IsVarArg = CLI.IsVarArg;
     593             :   auto PtrVT = getPointerTy(Layout);
     594             : 
     595             :   // Analyze operands of the call, assigning locations to each operand.
     596             :   SmallVector<CCValAssign, 16> ArgLocs;
     597        1040 :   CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
     598             : 
     599         520 :   if (IsVarArg) {
     600             :     // Outgoing non-fixed arguments are placed in a buffer. First
     601             :     // compute their offsets and the total amount of buffer space needed.
     602          13 :     for (SDValue Arg :
     603          24 :          make_range(OutVals.begin() + NumFixedArgs, OutVals.end())) {
     604          13 :       EVT VT = Arg.getValueType();
     605             :       assert(VT != MVT::iPTR && "Legalized args should be concrete");
     606          13 :       Type *Ty = VT.getTypeForEVT(*DAG.getContext());
     607          13 :       unsigned Offset = CCInfo.AllocateStack(Layout.getTypeAllocSize(Ty),
     608             :                                              Layout.getABITypeAlignment(Ty));
     609          13 :       CCInfo.addLoc(CCValAssign::getMem(ArgLocs.size(), VT.getSimpleVT(),
     610             :                                         Offset, VT.getSimpleVT(),
     611          13 :                                         CCValAssign::Full));
     612             :     }
     613             :   }
     614             : 
     615         520 :   unsigned NumBytes = CCInfo.getAlignedCallFrameSize();
     616             : 
     617         520 :   SDValue FINode;
     618         520 :   if (IsVarArg && NumBytes) {
     619             :     // For non-fixed arguments, next emit stores to store the argument values
     620             :     // to the stack buffer at the offsets computed above.
     621           8 :     int FI = MF.getFrameInfo().CreateStackObject(NumBytes,
     622             :                                                  Layout.getStackAlignment(),
     623             :                                                  /*isSS=*/false);
     624             :     unsigned ValNo = 0;
     625             :     SmallVector<SDValue, 8> Chains;
     626          26 :     for (SDValue Arg :
     627          21 :          make_range(OutVals.begin() + NumFixedArgs, OutVals.end())) {
     628             :       assert(ArgLocs[ValNo].getValNo() == ValNo &&
     629             :              "ArgLocs should remain in order and only hold varargs args");
     630          26 :       unsigned Offset = ArgLocs[ValNo++].getLocMemOffset();
     631          13 :       FINode = DAG.getFrameIndex(FI, getPointerTy(Layout));
     632             :       SDValue Add = DAG.getNode(ISD::ADD, DL, PtrVT, FINode,
     633          13 :                                 DAG.getConstant(Offset, DL, PtrVT));
     634          13 :       Chains.push_back(
     635          13 :           DAG.getStore(Chain, DL, Arg, Add,
     636          26 :                        MachinePointerInfo::getFixedStack(MF, FI, Offset), 0));
     637             :     }
     638           8 :     if (!Chains.empty())
     639           8 :       Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chains);
     640         512 :   } else if (IsVarArg) {
     641           3 :     FINode = DAG.getIntPtrConstant(0, DL);
     642             :   }
     643             : 
     644             :   // Compute the operands for the CALLn node.
     645             :   SmallVector<SDValue, 16> Ops;
     646         520 :   Ops.push_back(Chain);
     647         520 :   Ops.push_back(Callee);
     648             : 
     649             :   // Add all fixed arguments. Note that for non-varargs calls, NumFixedArgs
     650             :   // isn't reliable.
     651        1040 :   Ops.append(OutVals.begin(),
     652          11 :              IsVarArg ? OutVals.begin() + NumFixedArgs : OutVals.end());
     653             :   // Add a pointer to the vararg buffer.
     654         520 :   if (IsVarArg)
     655          11 :     Ops.push_back(FINode);
     656             : 
     657             :   SmallVector<EVT, 8> InTys;
     658         730 :   for (const auto &In : Ins) {
     659             :     assert(!In.Flags.isByVal() && "byval is not valid for return values");
     660             :     assert(!In.Flags.isNest() && "nest is not valid for return values");
     661         210 :     if (In.Flags.isInAlloca())
     662           0 :       fail(DL, DAG, "WebAssembly hasn't implemented inalloca return values");
     663         210 :     if (In.Flags.isInConsecutiveRegs())
     664           0 :       fail(DL, DAG, "WebAssembly hasn't implemented cons regs return values");
     665         210 :     if (In.Flags.isInConsecutiveRegsLast())
     666           0 :       fail(DL, DAG,
     667             :            "WebAssembly hasn't implemented cons regs last return values");
     668             :     // Ignore In.getOrigAlign() because all our arguments are passed in
     669             :     // registers.
     670         210 :     InTys.push_back(In.VT);
     671             :   }
     672         520 :   InTys.push_back(MVT::Other);
     673         520 :   SDVTList InTyList = DAG.getVTList(InTys);
     674             :   SDValue Res =
     675         520 :       DAG.getNode(Ins.empty() ? WebAssemblyISD::CALL0 : WebAssemblyISD::CALL1,
     676         730 :                   DL, InTyList, Ops);
     677         520 :   if (Ins.empty()) {
     678         310 :     Chain = Res;
     679             :   } else {
     680         210 :     InVals.push_back(Res);
     681         210 :     Chain = Res.getValue(1);
     682             :   }
     683             : 
     684         520 :   return Chain;
     685             : }
     686             : 
     687        3515 : bool WebAssemblyTargetLowering::CanLowerReturn(
     688             :     CallingConv::ID /*CallConv*/, MachineFunction & /*MF*/, bool /*IsVarArg*/,
     689             :     const SmallVectorImpl<ISD::OutputArg> &Outs,
     690             :     LLVMContext & /*Context*/) const {
     691             :   // WebAssembly can't currently handle returning tuples.
     692        3515 :   return Outs.size() <= 1;
     693             : }
     694             : 
     695        2633 : SDValue WebAssemblyTargetLowering::LowerReturn(
     696             :     SDValue Chain, CallingConv::ID CallConv, bool /*IsVarArg*/,
     697             :     const SmallVectorImpl<ISD::OutputArg> &Outs,
     698             :     const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
     699             :     SelectionDAG &DAG) const {
     700             :   assert(Outs.size() <= 1 && "WebAssembly can only return up to one value");
     701             :   if (!CallingConvSupported(CallConv))
     702           0 :     fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions");
     703             : 
     704             :   SmallVector<SDValue, 4> RetOps(1, Chain);
     705        2633 :   RetOps.append(OutVals.begin(), OutVals.end());
     706        2633 :   Chain = DAG.getNode(WebAssemblyISD::RETURN, DL, MVT::Other, RetOps);
     707             : 
     708             :   // Record the number and types of the return values.
     709        4195 :   for (const ISD::OutputArg &Out : Outs) {
     710             :     assert(!Out.Flags.isByVal() && "byval is not valid for return values");
     711             :     assert(!Out.Flags.isNest() && "nest is not valid for return values");
     712             :     assert(Out.IsFixed && "non-fixed return value is not valid");
     713        1562 :     if (Out.Flags.isInAlloca())
     714           0 :       fail(DL, DAG, "WebAssembly hasn't implemented inalloca results");
     715        1562 :     if (Out.Flags.isInConsecutiveRegs())
     716           0 :       fail(DL, DAG, "WebAssembly hasn't implemented cons regs results");
     717        1562 :     if (Out.Flags.isInConsecutiveRegsLast())
     718           0 :       fail(DL, DAG, "WebAssembly hasn't implemented cons regs last results");
     719             :   }
     720             : 
     721        2633 :   return Chain;
     722             : }
     723             : 
     724        2628 : SDValue WebAssemblyTargetLowering::LowerFormalArguments(
     725             :     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
     726             :     const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
     727             :     SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
     728             :   if (!CallingConvSupported(CallConv))
     729           0 :     fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions");
     730             : 
     731        2628 :   MachineFunction &MF = DAG.getMachineFunction();
     732             :   auto *MFI = MF.getInfo<WebAssemblyFunctionInfo>();
     733             : 
     734             :   // Set up the incoming ARGUMENTS value, which serves to represent the liveness
     735             :   // of the incoming values before they're represented by virtual registers.
     736        2628 :   MF.getRegInfo().addLiveIn(WebAssembly::ARGUMENTS);
     737             : 
     738        9356 :   for (const ISD::InputArg &In : Ins) {
     739        6728 :     if (In.Flags.isInAlloca())
     740           0 :       fail(DL, DAG, "WebAssembly hasn't implemented inalloca arguments");
     741        6728 :     if (In.Flags.isNest())
     742           0 :       fail(DL, DAG, "WebAssembly hasn't implemented nest arguments");
     743        6728 :     if (In.Flags.isInConsecutiveRegs())
     744           0 :       fail(DL, DAG, "WebAssembly hasn't implemented cons regs arguments");
     745        6728 :     if (In.Flags.isInConsecutiveRegsLast())
     746           0 :       fail(DL, DAG, "WebAssembly hasn't implemented cons regs last arguments");
     747             :     // Ignore In.getOrigAlign() because all our arguments are passed in
     748             :     // registers.
     749       13456 :     InVals.push_back(In.Used ? DAG.getNode(WebAssemblyISD::ARGUMENT, DL, In.VT,
     750             :                                            DAG.getTargetConstant(InVals.size(),
     751        6647 :                                                                  DL, MVT::i32))
     752        6809 :                              : DAG.getUNDEF(In.VT));
     753             : 
     754             :     // Record the number and types of arguments.
     755        6728 :     MFI->addParam(In.VT);
     756             :   }
     757             : 
     758             :   // Varargs are copied into a buffer allocated by the caller, and a pointer to
     759             :   // the buffer is passed as an argument.
     760        2628 :   if (IsVarArg) {
     761           6 :     MVT PtrVT = getPointerTy(MF.getDataLayout());
     762             :     unsigned VarargVreg =
     763          12 :         MF.getRegInfo().createVirtualRegister(getRegClassFor(PtrVT));
     764             :     MFI->setVarargBufferVreg(VarargVreg);
     765           6 :     Chain = DAG.getCopyToReg(
     766             :         Chain, DL, VarargVreg,
     767             :         DAG.getNode(WebAssemblyISD::ARGUMENT, DL, PtrVT,
     768           6 :                     DAG.getTargetConstant(Ins.size(), DL, MVT::i32)));
     769           6 :     MFI->addParam(PtrVT);
     770             :   }
     771             : 
     772             :   // Record the number and types of arguments and results.
     773             :   SmallVector<MVT, 4> Params;
     774             :   SmallVector<MVT, 4> Results;
     775        5256 :   ComputeSignatureVTs(MF.getFunction().getFunctionType(), MF.getFunction(),
     776             :                       DAG.getTarget(), Params, Results);
     777        4196 :   for (MVT VT : Results)
     778        1568 :     MFI->addResult(VT);
     779             :   // TODO: Use signatures in WebAssemblyMachineFunctionInfo too and unify
     780             :   // the param logic here with ComputeSignatureVTs
     781             :   assert(MFI->getParams().size() == Params.size() &&
     782             :          std::equal(MFI->getParams().begin(), MFI->getParams().end(),
     783             :                     Params.begin()));
     784             : 
     785        2628 :   return Chain;
     786             : }
     787             : 
     788             : //===----------------------------------------------------------------------===//
     789             : //  Custom lowering hooks.
     790             : //===----------------------------------------------------------------------===//
     791             : 
     792        4950 : SDValue WebAssemblyTargetLowering::LowerOperation(SDValue Op,
     793             :                                                   SelectionDAG &DAG) const {
     794             :   SDLoc DL(Op);
     795        4950 :   switch (Op.getOpcode()) {
     796           0 :   default:
     797           0 :     llvm_unreachable("unimplemented operation lowering");
     798             :     return SDValue();
     799         176 :   case ISD::FrameIndex:
     800         176 :     return LowerFrameIndex(Op, DAG);
     801         746 :   case ISD::GlobalAddress:
     802         746 :     return LowerGlobalAddress(Op, DAG);
     803          57 :   case ISD::ExternalSymbol:
     804          57 :     return LowerExternalSymbol(Op, DAG);
     805           0 :   case ISD::JumpTable:
     806           0 :     return LowerJumpTable(Op, DAG);
     807           2 :   case ISD::BR_JT:
     808           2 :     return LowerBR_JT(Op, DAG);
     809           2 :   case ISD::VASTART:
     810           2 :     return LowerVASTART(Op, DAG);
     811           0 :   case ISD::BlockAddress:
     812             :   case ISD::BRIND:
     813           0 :     fail(DL, DAG, "WebAssembly hasn't implemented computed gotos");
     814           0 :     return SDValue();
     815           1 :   case ISD::RETURNADDR: // Probably nothing meaningful can be returned here.
     816           1 :     fail(DL, DAG, "WebAssembly hasn't implemented __builtin_return_address");
     817           1 :     return SDValue();
     818           4 :   case ISD::FRAMEADDR:
     819           4 :     return LowerFRAMEADDR(Op, DAG);
     820        3828 :   case ISD::CopyToReg:
     821        3828 :     return LowerCopyToReg(Op, DAG);
     822         124 :   case ISD::INTRINSIC_WO_CHAIN:
     823         124 :     return LowerINTRINSIC_WO_CHAIN(Op, DAG);
     824          10 :   case ISD::VECTOR_SHUFFLE:
     825          10 :     return LowerVECTOR_SHUFFLE(Op, DAG);
     826             :   }
     827             : }
     828             : 
     829        3828 : SDValue WebAssemblyTargetLowering::LowerCopyToReg(SDValue Op,
     830             :                                                   SelectionDAG &DAG) const {
     831        3828 :   SDValue Src = Op.getOperand(2);
     832             :   if (isa<FrameIndexSDNode>(Src.getNode())) {
     833             :     // CopyToReg nodes don't support FrameIndex operands. Other targets select
     834             :     // the FI to some LEA-like instruction, but since we don't have that, we
     835             :     // need to insert some kind of instruction that can take an FI operand and
     836             :     // produces a value usable by CopyToReg (i.e. in a vreg). So insert a dummy
     837             :     // copy_local between Op and its FI operand.
     838           2 :     SDValue Chain = Op.getOperand(0);
     839             :     SDLoc DL(Op);
     840           2 :     unsigned Reg = cast<RegisterSDNode>(Op.getOperand(1))->getReg();
     841           2 :     EVT VT = Src.getValueType();
     842           2 :     SDValue Copy(DAG.getMachineNode(VT == MVT::i32 ? WebAssembly::COPY_I32
     843             :                                                    : WebAssembly::COPY_I64,
     844             :                                     DL, VT, Src),
     845             :                  0);
     846           2 :     return Op.getNode()->getNumValues() == 1
     847           1 :                ? DAG.getCopyToReg(Chain, DL, Reg, Copy)
     848             :                : DAG.getCopyToReg(Chain, DL, Reg, Copy,
     849             :                                   Op.getNumOperands() == 4 ? Op.getOperand(3)
     850           2 :                                                            : SDValue());
     851             :   }
     852        3826 :   return SDValue();
     853             : }
     854             : 
     855         176 : SDValue WebAssemblyTargetLowering::LowerFrameIndex(SDValue Op,
     856             :                                                    SelectionDAG &DAG) const {
     857         176 :   int FI = cast<FrameIndexSDNode>(Op)->getIndex();
     858         176 :   return DAG.getTargetFrameIndex(FI, Op.getValueType());
     859             : }
     860             : 
     861           4 : SDValue WebAssemblyTargetLowering::LowerFRAMEADDR(SDValue Op,
     862             :                                                   SelectionDAG &DAG) const {
     863             :   // Non-zero depths are not supported by WebAssembly currently. Use the
     864             :   // legalizer's default expansion, which is to return 0 (what this function is
     865             :   // documented to do).
     866           4 :   if (Op.getConstantOperandVal(0) > 0)
     867           1 :     return SDValue();
     868             : 
     869           3 :   DAG.getMachineFunction().getFrameInfo().setFrameAddressIsTaken(true);
     870           3 :   EVT VT = Op.getValueType();
     871             :   unsigned FP =
     872           6 :       Subtarget->getRegisterInfo()->getFrameRegister(DAG.getMachineFunction());
     873           6 :   return DAG.getCopyFromReg(DAG.getEntryNode(), SDLoc(Op), FP, VT);
     874             : }
     875             : 
     876         746 : SDValue WebAssemblyTargetLowering::LowerGlobalAddress(SDValue Op,
     877             :                                                       SelectionDAG &DAG) const {
     878             :   SDLoc DL(Op);
     879             :   const auto *GA = cast<GlobalAddressSDNode>(Op);
     880         746 :   EVT VT = Op.getValueType();
     881             :   assert(GA->getTargetFlags() == 0 &&
     882             :          "Unexpected target flags on generic GlobalAddressSDNode");
     883         746 :   if (GA->getAddressSpace() != 0)
     884           0 :     fail(DL, DAG, "WebAssembly only expects the 0 address space");
     885             :   return DAG.getNode(
     886             :       WebAssemblyISD::Wrapper, DL, VT,
     887         746 :       DAG.getTargetGlobalAddress(GA->getGlobal(), DL, VT, GA->getOffset()));
     888             : }
     889             : 
     890             : SDValue
     891          57 : WebAssemblyTargetLowering::LowerExternalSymbol(SDValue Op,
     892             :                                                SelectionDAG &DAG) const {
     893             :   SDLoc DL(Op);
     894             :   const auto *ES = cast<ExternalSymbolSDNode>(Op);
     895          57 :   EVT VT = Op.getValueType();
     896             :   assert(ES->getTargetFlags() == 0 &&
     897             :          "Unexpected target flags on generic ExternalSymbolSDNode");
     898             :   // Set the TargetFlags to 0x1 which indicates that this is a "function"
     899             :   // symbol rather than a data symbol. We do this unconditionally even though
     900             :   // we don't know anything about the symbol other than its name, because all
     901             :   // external symbols used in target-independent SelectionDAG code are for
     902             :   // functions.
     903             :   return DAG.getNode(
     904             :       WebAssemblyISD::Wrapper, DL, VT,
     905             :       DAG.getTargetExternalSymbol(ES->getSymbol(), VT,
     906          57 :                                   WebAssemblyII::MO_SYMBOL_FUNCTION));
     907             : }
     908             : 
     909           0 : SDValue WebAssemblyTargetLowering::LowerJumpTable(SDValue Op,
     910             :                                                   SelectionDAG &DAG) const {
     911             :   // There's no need for a Wrapper node because we always incorporate a jump
     912             :   // table operand into a BR_TABLE instruction, rather than ever
     913             :   // materializing it in a register.
     914             :   const JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
     915             :   return DAG.getTargetJumpTable(JT->getIndex(), Op.getValueType(),
     916           0 :                                 JT->getTargetFlags());
     917             : }
     918             : 
     919           2 : SDValue WebAssemblyTargetLowering::LowerBR_JT(SDValue Op,
     920             :                                               SelectionDAG &DAG) const {
     921             :   SDLoc DL(Op);
     922           2 :   SDValue Chain = Op.getOperand(0);
     923             :   const auto *JT = cast<JumpTableSDNode>(Op.getOperand(1));
     924           2 :   SDValue Index = Op.getOperand(2);
     925             :   assert(JT->getTargetFlags() == 0 && "WebAssembly doesn't set target flags");
     926             : 
     927             :   SmallVector<SDValue, 8> Ops;
     928           2 :   Ops.push_back(Chain);
     929           2 :   Ops.push_back(Index);
     930             : 
     931           2 :   MachineJumpTableInfo *MJTI = DAG.getMachineFunction().getJumpTableInfo();
     932           2 :   const auto &MBBs = MJTI->getJumpTables()[JT->getIndex()].MBBs;
     933             : 
     934             :   // Add an operand for each case.
     935          50 :   for (auto MBB : MBBs)
     936          48 :     Ops.push_back(DAG.getBasicBlock(MBB));
     937             : 
     938             :   // TODO: For now, we just pick something arbitrary for a default case for now.
     939             :   // We really want to sniff out the guard and put in the real default case (and
     940             :   // delete the guard).
     941           2 :   Ops.push_back(DAG.getBasicBlock(MBBs[0]));
     942             : 
     943           2 :   return DAG.getNode(WebAssemblyISD::BR_TABLE, DL, MVT::Other, Ops);
     944             : }
     945             : 
     946           2 : SDValue WebAssemblyTargetLowering::LowerVASTART(SDValue Op,
     947             :                                                 SelectionDAG &DAG) const {
     948             :   SDLoc DL(Op);
     949           2 :   EVT PtrVT = getPointerTy(DAG.getMachineFunction().getDataLayout());
     950             : 
     951           2 :   auto *MFI = DAG.getMachineFunction().getInfo<WebAssemblyFunctionInfo>();
     952           2 :   const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
     953             : 
     954             :   SDValue ArgN = DAG.getCopyFromReg(DAG.getEntryNode(), DL,
     955           4 :                                     MFI->getVarargBufferVreg(), PtrVT);
     956             :   return DAG.getStore(Op.getOperand(0), DL, ArgN, Op.getOperand(1),
     957           2 :                       MachinePointerInfo(SV), 0);
     958             : }
     959             : 
     960             : SDValue
     961         124 : WebAssemblyTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
     962             :                                                    SelectionDAG &DAG) const {
     963         248 :   unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
     964             :   SDLoc DL(Op);
     965         124 :   switch (IntNo) {
     966         120 :   default:
     967         120 :     return {}; // Don't custom lower most intrinsics.
     968             : 
     969           4 :   case Intrinsic::wasm_lsda:
     970             :     // TODO For now, just return 0 not to crash
     971           4 :     return DAG.getConstant(0, DL, Op.getValueType());
     972             :   }
     973             : }
     974             : 
     975             : SDValue
     976          10 : WebAssemblyTargetLowering::LowerVECTOR_SHUFFLE(SDValue Op,
     977             :                                                SelectionDAG &DAG) const {
     978             :   SDLoc DL(Op);
     979          10 :   ArrayRef<int> Mask = cast<ShuffleVectorSDNode>(Op.getNode())->getMask();
     980          10 :   MVT VecType = Op.getOperand(0).getSimpleValueType();
     981             :   assert(VecType.is128BitVector() && "Unexpected shuffle vector type");
     982          10 :   size_t LaneBytes = VecType.getVectorElementType().getSizeInBits() / 8;
     983             : 
     984             :   // Space for two vector args and sixteen mask indices
     985          10 :   SDValue Ops[18];
     986             :   size_t OpIdx = 0;
     987          10 :   Ops[OpIdx++] = Op.getOperand(0);
     988          10 :   Ops[OpIdx++] = Op.getOperand(1);
     989             : 
     990             :   // Expand mask indices to byte indices and materialize them as operands
     991          78 :   for (size_t I = 0, Lanes = Mask.size(); I < Lanes; ++I) {
     992         228 :     for (size_t J = 0; J < LaneBytes; ++J) {
     993         160 :       Ops[OpIdx++] =
     994         320 :           DAG.getConstant((uint64_t)Mask[I] * LaneBytes + J, DL, MVT::i32);
     995             :     }
     996             :   }
     997             : 
     998          10 :   return DAG.getNode(WebAssemblyISD::SHUFFLE, DL, MVT::v16i8, Ops);
     999             : }
    1000             : 
    1001             : //===----------------------------------------------------------------------===//
    1002             : //                          WebAssembly Optimization Hooks
    1003             : //===----------------------------------------------------------------------===//

Generated by: LCOV version 1.13