Home | History | Annotate | Download | only in WebAssembly
      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 /// \brief 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/MachineJumpTableInfo.h"
     23 #include "llvm/CodeGen/MachineRegisterInfo.h"
     24 #include "llvm/CodeGen/SelectionDAG.h"
     25 #include "llvm/IR/DiagnosticInfo.h"
     26 #include "llvm/IR/DiagnosticPrinter.h"
     27 #include "llvm/IR/Function.h"
     28 #include "llvm/IR/Intrinsics.h"
     29 #include "llvm/Support/CommandLine.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 namespace {
     39 // Diagnostic information for unimplemented or unsupported feature reporting.
     40 // TODO: This code is copied from BPF and AMDGPU; consider factoring it out
     41 // and sharing code.
     42 class DiagnosticInfoUnsupported final : public DiagnosticInfo {
     43 private:
     44   // Debug location where this diagnostic is triggered.
     45   DebugLoc DLoc;
     46   const Twine &Description;
     47   const Function &Fn;
     48   SDValue Value;
     49 
     50   static int KindID;
     51 
     52   static int getKindID() {
     53     if (KindID == 0)
     54       KindID = llvm::getNextAvailablePluginDiagnosticKind();
     55     return KindID;
     56   }
     57 
     58 public:
     59   DiagnosticInfoUnsupported(SDLoc DLoc, const Function &Fn, const Twine &Desc,
     60                             SDValue Value)
     61       : DiagnosticInfo(getKindID(), DS_Error), DLoc(DLoc.getDebugLoc()),
     62         Description(Desc), Fn(Fn), Value(Value) {}
     63 
     64   void print(DiagnosticPrinter &DP) const override {
     65     std::string Str;
     66     raw_string_ostream OS(Str);
     67 
     68     if (DLoc) {
     69       auto DIL = DLoc.get();
     70       StringRef Filename = DIL->getFilename();
     71       unsigned Line = DIL->getLine();
     72       unsigned Column = DIL->getColumn();
     73       OS << Filename << ':' << Line << ':' << Column << ' ';
     74     }
     75 
     76     OS << "in function " << Fn.getName() << ' ' << *Fn.getFunctionType() << '\n'
     77        << Description;
     78     if (Value)
     79       Value->print(OS);
     80     OS << '\n';
     81     OS.flush();
     82     DP << Str;
     83   }
     84 
     85   static bool classof(const DiagnosticInfo *DI) {
     86     return DI->getKind() == getKindID();
     87   }
     88 };
     89 
     90 int DiagnosticInfoUnsupported::KindID = 0;
     91 } // end anonymous namespace
     92 
     93 WebAssemblyTargetLowering::WebAssemblyTargetLowering(
     94     const TargetMachine &TM, const WebAssemblySubtarget &STI)
     95     : TargetLowering(TM), Subtarget(&STI) {
     96   auto MVTPtr = Subtarget->hasAddr64() ? MVT::i64 : MVT::i32;
     97 
     98   // Booleans always contain 0 or 1.
     99   setBooleanContents(ZeroOrOneBooleanContent);
    100   // WebAssembly does not produce floating-point exceptions on normal floating
    101   // point operations.
    102   setHasFloatingPointExceptions(false);
    103   // We don't know the microarchitecture here, so just reduce register pressure.
    104   setSchedulingPreference(Sched::RegPressure);
    105   // Tell ISel that we have a stack pointer.
    106   setStackPointerRegisterToSaveRestore(
    107       Subtarget->hasAddr64() ? WebAssembly::SP64 : WebAssembly::SP32);
    108   // Set up the register classes.
    109   addRegisterClass(MVT::i32, &WebAssembly::I32RegClass);
    110   addRegisterClass(MVT::i64, &WebAssembly::I64RegClass);
    111   addRegisterClass(MVT::f32, &WebAssembly::F32RegClass);
    112   addRegisterClass(MVT::f64, &WebAssembly::F64RegClass);
    113   // Compute derived properties from the register classes.
    114   computeRegisterProperties(Subtarget->getRegisterInfo());
    115 
    116   setOperationAction(ISD::GlobalAddress, MVTPtr, Custom);
    117   setOperationAction(ISD::ExternalSymbol, MVTPtr, Custom);
    118   setOperationAction(ISD::JumpTable, MVTPtr, Custom);
    119 
    120   // Take the default expansion for va_arg, va_copy, and va_end. There is no
    121   // default action for va_start, so we do that custom.
    122   setOperationAction(ISD::VASTART, MVT::Other, Custom);
    123   setOperationAction(ISD::VAARG, MVT::Other, Expand);
    124   setOperationAction(ISD::VACOPY, MVT::Other, Expand);
    125   setOperationAction(ISD::VAEND, MVT::Other, Expand);
    126 
    127   for (auto T : {MVT::f32, MVT::f64}) {
    128     // Don't expand the floating-point types to constant pools.
    129     setOperationAction(ISD::ConstantFP, T, Legal);
    130     // Expand floating-point comparisons.
    131     for (auto CC : {ISD::SETO, ISD::SETUO, ISD::SETUEQ, ISD::SETONE,
    132                     ISD::SETULT, ISD::SETULE, ISD::SETUGT, ISD::SETUGE})
    133       setCondCodeAction(CC, T, Expand);
    134     // Expand floating-point library function operators.
    135     for (auto Op : {ISD::FSIN, ISD::FCOS, ISD::FSINCOS, ISD::FPOWI, ISD::FPOW,
    136                     ISD::FREM, ISD::FMA})
    137       setOperationAction(Op, T, Expand);
    138     // Note supported floating-point library function operators that otherwise
    139     // default to expand.
    140     for (auto Op :
    141          {ISD::FCEIL, ISD::FFLOOR, ISD::FTRUNC, ISD::FNEARBYINT, ISD::FRINT})
    142       setOperationAction(Op, T, Legal);
    143     // Support minnan and maxnan, which otherwise default to expand.
    144     setOperationAction(ISD::FMINNAN, T, Legal);
    145     setOperationAction(ISD::FMAXNAN, T, Legal);
    146   }
    147 
    148   for (auto T : {MVT::i32, MVT::i64}) {
    149     // Expand unavailable integer operations.
    150     for (auto Op :
    151          {ISD::BSWAP, ISD::ROTL, ISD::ROTR, ISD::SMUL_LOHI, ISD::UMUL_LOHI,
    152           ISD::MULHS, ISD::MULHU, ISD::SDIVREM, ISD::UDIVREM, ISD::SHL_PARTS,
    153           ISD::SRA_PARTS, ISD::SRL_PARTS, ISD::ADDC, ISD::ADDE, ISD::SUBC,
    154           ISD::SUBE}) {
    155       setOperationAction(Op, T, Expand);
    156     }
    157   }
    158 
    159   // As a special case, these operators use the type to mean the type to
    160   // sign-extend from.
    161   for (auto T : {MVT::i1, MVT::i8, MVT::i16, MVT::i32})
    162     setOperationAction(ISD::SIGN_EXTEND_INREG, T, Expand);
    163 
    164   // Dynamic stack allocation: use the default expansion.
    165   setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
    166   setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
    167   setOperationAction(ISD::DYNAMIC_STACKALLOC, MVTPtr, Expand);
    168 
    169   setOperationAction(ISD::FrameIndex, MVT::i32, Custom);
    170 
    171   // Expand these forms; we pattern-match the forms that we can handle in isel.
    172   for (auto T : {MVT::i32, MVT::i64, MVT::f32, MVT::f64})
    173     for (auto Op : {ISD::BR_CC, ISD::SELECT_CC})
    174       setOperationAction(Op, T, Expand);
    175 
    176   // We have custom switch handling.
    177   setOperationAction(ISD::BR_JT, MVT::Other, Custom);
    178 
    179   // WebAssembly doesn't have:
    180   //  - Floating-point extending loads.
    181   //  - Floating-point truncating stores.
    182   //  - i1 extending loads.
    183   setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f32, Expand);
    184   setTruncStoreAction(MVT::f64, MVT::f32, Expand);
    185   for (auto T : MVT::integer_valuetypes())
    186     for (auto Ext : {ISD::EXTLOAD, ISD::ZEXTLOAD, ISD::SEXTLOAD})
    187       setLoadExtAction(Ext, T, MVT::i1, Promote);
    188 
    189   // Trap lowers to wasm unreachable
    190   setOperationAction(ISD::TRAP, MVT::Other, Legal);
    191 }
    192 
    193 FastISel *WebAssemblyTargetLowering::createFastISel(
    194     FunctionLoweringInfo &FuncInfo, const TargetLibraryInfo *LibInfo) const {
    195   return WebAssembly::createFastISel(FuncInfo, LibInfo);
    196 }
    197 
    198 bool WebAssemblyTargetLowering::isOffsetFoldingLegal(
    199     const GlobalAddressSDNode * /*GA*/) const {
    200   // All offsets can be folded.
    201   return true;
    202 }
    203 
    204 MVT WebAssemblyTargetLowering::getScalarShiftAmountTy(const DataLayout & /*DL*/,
    205                                                       EVT VT) const {
    206   unsigned BitWidth = NextPowerOf2(VT.getSizeInBits() - 1);
    207   if (BitWidth > 1 && BitWidth < 8)
    208     BitWidth = 8;
    209 
    210   if (BitWidth > 64) {
    211     BitWidth = 64;
    212     assert(BitWidth >= Log2_32_Ceil(VT.getSizeInBits()) &&
    213            "64-bit shift counts ought to be enough for anyone");
    214   }
    215 
    216   MVT Result = MVT::getIntegerVT(BitWidth);
    217   assert(Result != MVT::INVALID_SIMPLE_VALUE_TYPE &&
    218          "Unable to represent scalar shift amount type");
    219   return Result;
    220 }
    221 
    222 const char *
    223 WebAssemblyTargetLowering::getTargetNodeName(unsigned Opcode) const {
    224   switch (static_cast<WebAssemblyISD::NodeType>(Opcode)) {
    225   case WebAssemblyISD::FIRST_NUMBER:
    226     break;
    227 #define HANDLE_NODETYPE(NODE)                                                  \
    228   case WebAssemblyISD::NODE:                                                   \
    229     return "WebAssemblyISD::" #NODE;
    230 #include "WebAssemblyISD.def"
    231 #undef HANDLE_NODETYPE
    232   }
    233   return nullptr;
    234 }
    235 
    236 std::pair<unsigned, const TargetRegisterClass *>
    237 WebAssemblyTargetLowering::getRegForInlineAsmConstraint(
    238     const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const {
    239   // First, see if this is a constraint that directly corresponds to a
    240   // WebAssembly register class.
    241   if (Constraint.size() == 1) {
    242     switch (Constraint[0]) {
    243     case 'r':
    244       assert(VT != MVT::iPTR && "Pointer MVT not expected here");
    245       if (VT.isInteger() && !VT.isVector()) {
    246         if (VT.getSizeInBits() <= 32)
    247           return std::make_pair(0U, &WebAssembly::I32RegClass);
    248         if (VT.getSizeInBits() <= 64)
    249           return std::make_pair(0U, &WebAssembly::I64RegClass);
    250       }
    251       break;
    252     default:
    253       break;
    254     }
    255   }
    256 
    257   return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
    258 }
    259 
    260 bool WebAssemblyTargetLowering::isCheapToSpeculateCttz() const {
    261   // Assume ctz is a relatively cheap operation.
    262   return true;
    263 }
    264 
    265 bool WebAssemblyTargetLowering::isCheapToSpeculateCtlz() const {
    266   // Assume clz is a relatively cheap operation.
    267   return true;
    268 }
    269 
    270 bool WebAssemblyTargetLowering::isLegalAddressingMode(const DataLayout &DL,
    271                                                       const AddrMode &AM,
    272                                                       Type *Ty,
    273                                                       unsigned AS) const {
    274   // WebAssembly offsets are added as unsigned without wrapping. The
    275   // isLegalAddressingMode gives us no way to determine if wrapping could be
    276   // happening, so we approximate this by accepting only non-negative offsets.
    277   if (AM.BaseOffs < 0)
    278     return false;
    279 
    280   // WebAssembly has no scale register operands.
    281   if (AM.Scale != 0)
    282     return false;
    283 
    284   // Everything else is legal.
    285   return true;
    286 }
    287 
    288 //===----------------------------------------------------------------------===//
    289 // WebAssembly Lowering private implementation.
    290 //===----------------------------------------------------------------------===//
    291 
    292 //===----------------------------------------------------------------------===//
    293 // Lowering Code
    294 //===----------------------------------------------------------------------===//
    295 
    296 static void fail(SDLoc DL, SelectionDAG &DAG, const char *msg) {
    297   MachineFunction &MF = DAG.getMachineFunction();
    298   DAG.getContext()->diagnose(
    299       DiagnosticInfoUnsupported(DL, *MF.getFunction(), msg, SDValue()));
    300 }
    301 
    302 // Test whether the given calling convention is supported.
    303 static bool CallingConvSupported(CallingConv::ID CallConv) {
    304   // We currently support the language-independent target-independent
    305   // conventions. We don't yet have a way to annotate calls with properties like
    306   // "cold", and we don't have any call-clobbered registers, so these are mostly
    307   // all handled the same.
    308   return CallConv == CallingConv::C || CallConv == CallingConv::Fast ||
    309          CallConv == CallingConv::Cold ||
    310          CallConv == CallingConv::PreserveMost ||
    311          CallConv == CallingConv::PreserveAll ||
    312          CallConv == CallingConv::CXX_FAST_TLS;
    313 }
    314 
    315 SDValue
    316 WebAssemblyTargetLowering::LowerCall(CallLoweringInfo &CLI,
    317                                      SmallVectorImpl<SDValue> &InVals) const {
    318   SelectionDAG &DAG = CLI.DAG;
    319   SDLoc DL = CLI.DL;
    320   SDValue Chain = CLI.Chain;
    321   SDValue Callee = CLI.Callee;
    322   MachineFunction &MF = DAG.getMachineFunction();
    323 
    324   CallingConv::ID CallConv = CLI.CallConv;
    325   if (!CallingConvSupported(CallConv))
    326     fail(DL, DAG,
    327          "WebAssembly doesn't support language-specific or target-specific "
    328          "calling conventions yet");
    329   if (CLI.IsPatchPoint)
    330     fail(DL, DAG, "WebAssembly doesn't support patch point yet");
    331 
    332   // WebAssembly doesn't currently support explicit tail calls. If they are
    333   // required, fail. Otherwise, just disable them.
    334   if ((CallConv == CallingConv::Fast && CLI.IsTailCall &&
    335        MF.getTarget().Options.GuaranteedTailCallOpt) ||
    336       (CLI.CS && CLI.CS->isMustTailCall()))
    337     fail(DL, DAG, "WebAssembly doesn't support tail call yet");
    338   CLI.IsTailCall = false;
    339 
    340   SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
    341 
    342   SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
    343   if (Ins.size() > 1)
    344     fail(DL, DAG, "WebAssembly doesn't support more than 1 returned value yet");
    345 
    346   SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
    347   for (const ISD::OutputArg &Out : Outs) {
    348     if (Out.Flags.isByVal())
    349       fail(DL, DAG, "WebAssembly hasn't implemented byval arguments");
    350     if (Out.Flags.isNest())
    351       fail(DL, DAG, "WebAssembly hasn't implemented nest arguments");
    352     if (Out.Flags.isInAlloca())
    353       fail(DL, DAG, "WebAssembly hasn't implemented inalloca arguments");
    354     if (Out.Flags.isInConsecutiveRegs())
    355       fail(DL, DAG, "WebAssembly hasn't implemented cons regs arguments");
    356     if (Out.Flags.isInConsecutiveRegsLast())
    357       fail(DL, DAG, "WebAssembly hasn't implemented cons regs last arguments");
    358   }
    359 
    360   bool IsVarArg = CLI.IsVarArg;
    361   unsigned NumFixedArgs = CLI.NumFixedArgs;
    362   auto PtrVT = getPointerTy(MF.getDataLayout());
    363 
    364   // Analyze operands of the call, assigning locations to each operand.
    365   SmallVector<CCValAssign, 16> ArgLocs;
    366   CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
    367 
    368   if (IsVarArg) {
    369     // Outgoing non-fixed arguments are placed at the top of the stack. First
    370     // compute their offsets and the total amount of argument stack space
    371     // needed.
    372     for (SDValue Arg :
    373          make_range(OutVals.begin() + NumFixedArgs, OutVals.end())) {
    374       EVT VT = Arg.getValueType();
    375       assert(VT != MVT::iPTR && "Legalized args should be concrete");
    376       Type *Ty = VT.getTypeForEVT(*DAG.getContext());
    377       unsigned Offset =
    378           CCInfo.AllocateStack(MF.getDataLayout().getTypeAllocSize(Ty),
    379                                MF.getDataLayout().getABITypeAlignment(Ty));
    380       CCInfo.addLoc(CCValAssign::getMem(ArgLocs.size(), VT.getSimpleVT(),
    381                                         Offset, VT.getSimpleVT(),
    382                                         CCValAssign::Full));
    383     }
    384   }
    385 
    386   unsigned NumBytes = CCInfo.getAlignedCallFrameSize();
    387 
    388   SDValue NB;
    389   if (NumBytes) {
    390     NB = DAG.getConstant(NumBytes, DL, PtrVT, true);
    391     Chain = DAG.getCALLSEQ_START(Chain, NB, DL);
    392   }
    393 
    394   if (IsVarArg) {
    395     // For non-fixed arguments, next emit stores to store the argument values
    396     // to the stack at the offsets computed above.
    397     SDValue SP = DAG.getCopyFromReg(
    398         Chain, DL, getStackPointerRegisterToSaveRestore(), PtrVT);
    399     unsigned ValNo = 0;
    400     SmallVector<SDValue, 8> Chains;
    401     for (SDValue Arg :
    402          make_range(OutVals.begin() + NumFixedArgs, OutVals.end())) {
    403       assert(ArgLocs[ValNo].getValNo() == ValNo &&
    404              "ArgLocs should remain in order and only hold varargs args");
    405       unsigned Offset = ArgLocs[ValNo++].getLocMemOffset();
    406       SDValue Add = DAG.getNode(ISD::ADD, DL, PtrVT, SP,
    407                                 DAG.getConstant(Offset, DL, PtrVT));
    408       Chains.push_back(DAG.getStore(Chain, DL, Arg, Add,
    409                                     MachinePointerInfo::getStack(MF, Offset),
    410                                     false, false, 0));
    411     }
    412     if (!Chains.empty())
    413       Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chains);
    414   }
    415 
    416   // Compute the operands for the CALLn node.
    417   SmallVector<SDValue, 16> Ops;
    418   Ops.push_back(Chain);
    419   Ops.push_back(Callee);
    420 
    421   // Add all fixed arguments. Note that for non-varargs calls, NumFixedArgs
    422   // isn't reliable.
    423   Ops.append(OutVals.begin(),
    424              IsVarArg ? OutVals.begin() + NumFixedArgs : OutVals.end());
    425 
    426   SmallVector<EVT, 8> Tys;
    427   for (const auto &In : Ins) {
    428     assert(!In.Flags.isByVal() && "byval is not valid for return values");
    429     assert(!In.Flags.isNest() && "nest is not valid for return values");
    430     if (In.Flags.isInAlloca())
    431       fail(DL, DAG, "WebAssembly hasn't implemented inalloca return values");
    432     if (In.Flags.isInConsecutiveRegs())
    433       fail(DL, DAG, "WebAssembly hasn't implemented cons regs return values");
    434     if (In.Flags.isInConsecutiveRegsLast())
    435       fail(DL, DAG,
    436            "WebAssembly hasn't implemented cons regs last return values");
    437     // Ignore In.getOrigAlign() because all our arguments are passed in
    438     // registers.
    439     Tys.push_back(In.VT);
    440   }
    441   Tys.push_back(MVT::Other);
    442   SDVTList TyList = DAG.getVTList(Tys);
    443   SDValue Res =
    444       DAG.getNode(Ins.empty() ? WebAssemblyISD::CALL0 : WebAssemblyISD::CALL1,
    445                   DL, TyList, Ops);
    446   if (Ins.empty()) {
    447     Chain = Res;
    448   } else {
    449     InVals.push_back(Res);
    450     Chain = Res.getValue(1);
    451   }
    452 
    453   if (NumBytes) {
    454     SDValue Unused = DAG.getTargetConstant(0, DL, PtrVT);
    455     Chain = DAG.getCALLSEQ_END(Chain, NB, Unused, SDValue(), DL);
    456   }
    457 
    458   return Chain;
    459 }
    460 
    461 bool WebAssemblyTargetLowering::CanLowerReturn(
    462     CallingConv::ID /*CallConv*/, MachineFunction & /*MF*/, bool /*IsVarArg*/,
    463     const SmallVectorImpl<ISD::OutputArg> &Outs,
    464     LLVMContext & /*Context*/) const {
    465   // WebAssembly can't currently handle returning tuples.
    466   return Outs.size() <= 1;
    467 }
    468 
    469 SDValue WebAssemblyTargetLowering::LowerReturn(
    470     SDValue Chain, CallingConv::ID CallConv, bool /*IsVarArg*/,
    471     const SmallVectorImpl<ISD::OutputArg> &Outs,
    472     const SmallVectorImpl<SDValue> &OutVals, SDLoc DL,
    473     SelectionDAG &DAG) const {
    474   assert(Outs.size() <= 1 && "WebAssembly can only return up to one value");
    475   if (!CallingConvSupported(CallConv))
    476     fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions");
    477 
    478   SmallVector<SDValue, 4> RetOps(1, Chain);
    479   RetOps.append(OutVals.begin(), OutVals.end());
    480   Chain = DAG.getNode(WebAssemblyISD::RETURN, DL, MVT::Other, RetOps);
    481 
    482   // Record the number and types of the return values.
    483   for (const ISD::OutputArg &Out : Outs) {
    484     assert(!Out.Flags.isByVal() && "byval is not valid for return values");
    485     assert(!Out.Flags.isNest() && "nest is not valid for return values");
    486     assert(Out.IsFixed && "non-fixed return value is not valid");
    487     if (Out.Flags.isInAlloca())
    488       fail(DL, DAG, "WebAssembly hasn't implemented inalloca results");
    489     if (Out.Flags.isInConsecutiveRegs())
    490       fail(DL, DAG, "WebAssembly hasn't implemented cons regs results");
    491     if (Out.Flags.isInConsecutiveRegsLast())
    492       fail(DL, DAG, "WebAssembly hasn't implemented cons regs last results");
    493   }
    494 
    495   return Chain;
    496 }
    497 
    498 SDValue WebAssemblyTargetLowering::LowerFormalArguments(
    499     SDValue Chain, CallingConv::ID CallConv, bool /*IsVarArg*/,
    500     const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc DL, SelectionDAG &DAG,
    501     SmallVectorImpl<SDValue> &InVals) const {
    502   MachineFunction &MF = DAG.getMachineFunction();
    503 
    504   if (!CallingConvSupported(CallConv))
    505     fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions");
    506 
    507   // Set up the incoming ARGUMENTS value, which serves to represent the liveness
    508   // of the incoming values before they're represented by virtual registers.
    509   MF.getRegInfo().addLiveIn(WebAssembly::ARGUMENTS);
    510 
    511   for (const ISD::InputArg &In : Ins) {
    512     if (In.Flags.isByVal())
    513       fail(DL, DAG, "WebAssembly hasn't implemented byval arguments");
    514     if (In.Flags.isInAlloca())
    515       fail(DL, DAG, "WebAssembly hasn't implemented inalloca arguments");
    516     if (In.Flags.isNest())
    517       fail(DL, DAG, "WebAssembly hasn't implemented nest arguments");
    518     if (In.Flags.isInConsecutiveRegs())
    519       fail(DL, DAG, "WebAssembly hasn't implemented cons regs arguments");
    520     if (In.Flags.isInConsecutiveRegsLast())
    521       fail(DL, DAG, "WebAssembly hasn't implemented cons regs last arguments");
    522     // Ignore In.getOrigAlign() because all our arguments are passed in
    523     // registers.
    524     InVals.push_back(
    525         In.Used
    526             ? DAG.getNode(WebAssemblyISD::ARGUMENT, DL, In.VT,
    527                           DAG.getTargetConstant(InVals.size(), DL, MVT::i32))
    528             : DAG.getUNDEF(In.VT));
    529 
    530     // Record the number and types of arguments.
    531     MF.getInfo<WebAssemblyFunctionInfo>()->addParam(In.VT);
    532   }
    533 
    534   // Incoming varargs arguments are on the stack and will be accessed through
    535   // va_arg, so we don't need to do anything for them here.
    536 
    537   return Chain;
    538 }
    539 
    540 //===----------------------------------------------------------------------===//
    541 //  Custom lowering hooks.
    542 //===----------------------------------------------------------------------===//
    543 
    544 SDValue WebAssemblyTargetLowering::LowerOperation(SDValue Op,
    545                                                   SelectionDAG &DAG) const {
    546   switch (Op.getOpcode()) {
    547   default:
    548     llvm_unreachable("unimplemented operation lowering");
    549     return SDValue();
    550   case ISD::FrameIndex:
    551     return LowerFrameIndex(Op, DAG);
    552   case ISD::GlobalAddress:
    553     return LowerGlobalAddress(Op, DAG);
    554   case ISD::ExternalSymbol:
    555     return LowerExternalSymbol(Op, DAG);
    556   case ISD::JumpTable:
    557     return LowerJumpTable(Op, DAG);
    558   case ISD::BR_JT:
    559     return LowerBR_JT(Op, DAG);
    560   case ISD::VASTART:
    561     return LowerVASTART(Op, DAG);
    562   }
    563 }
    564 
    565 SDValue WebAssemblyTargetLowering::LowerFrameIndex(SDValue Op,
    566                                                    SelectionDAG &DAG) const {
    567   int FI = cast<FrameIndexSDNode>(Op)->getIndex();
    568   return DAG.getTargetFrameIndex(FI, Op.getValueType());
    569 }
    570 
    571 SDValue WebAssemblyTargetLowering::LowerGlobalAddress(SDValue Op,
    572                                                       SelectionDAG &DAG) const {
    573   SDLoc DL(Op);
    574   const auto *GA = cast<GlobalAddressSDNode>(Op);
    575   EVT VT = Op.getValueType();
    576   assert(GA->getTargetFlags() == 0 && "WebAssembly doesn't set target flags");
    577   if (GA->getAddressSpace() != 0)
    578     fail(DL, DAG, "WebAssembly only expects the 0 address space");
    579   return DAG.getNode(
    580       WebAssemblyISD::Wrapper, DL, VT,
    581       DAG.getTargetGlobalAddress(GA->getGlobal(), DL, VT, GA->getOffset()));
    582 }
    583 
    584 SDValue
    585 WebAssemblyTargetLowering::LowerExternalSymbol(SDValue Op,
    586                                                SelectionDAG &DAG) const {
    587   SDLoc DL(Op);
    588   const auto *ES = cast<ExternalSymbolSDNode>(Op);
    589   EVT VT = Op.getValueType();
    590   assert(ES->getTargetFlags() == 0 && "WebAssembly doesn't set target flags");
    591   return DAG.getNode(WebAssemblyISD::Wrapper, DL, VT,
    592                      DAG.getTargetExternalSymbol(ES->getSymbol(), VT));
    593 }
    594 
    595 SDValue WebAssemblyTargetLowering::LowerJumpTable(SDValue Op,
    596                                                   SelectionDAG &DAG) const {
    597   // There's no need for a Wrapper node because we always incorporate a jump
    598   // table operand into a TABLESWITCH instruction, rather than ever
    599   // materializing it in a register.
    600   const JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
    601   return DAG.getTargetJumpTable(JT->getIndex(), Op.getValueType(),
    602                                 JT->getTargetFlags());
    603 }
    604 
    605 SDValue WebAssemblyTargetLowering::LowerBR_JT(SDValue Op,
    606                                               SelectionDAG &DAG) const {
    607   SDLoc DL(Op);
    608   SDValue Chain = Op.getOperand(0);
    609   const auto *JT = cast<JumpTableSDNode>(Op.getOperand(1));
    610   SDValue Index = Op.getOperand(2);
    611   assert(JT->getTargetFlags() == 0 && "WebAssembly doesn't set target flags");
    612 
    613   SmallVector<SDValue, 8> Ops;
    614   Ops.push_back(Chain);
    615   Ops.push_back(Index);
    616 
    617   MachineJumpTableInfo *MJTI = DAG.getMachineFunction().getJumpTableInfo();
    618   const auto &MBBs = MJTI->getJumpTables()[JT->getIndex()].MBBs;
    619 
    620   // TODO: For now, we just pick something arbitrary for a default case for now.
    621   // We really want to sniff out the guard and put in the real default case (and
    622   // delete the guard).
    623   Ops.push_back(DAG.getBasicBlock(MBBs[0]));
    624 
    625   // Add an operand for each case.
    626   for (auto MBB : MBBs)
    627     Ops.push_back(DAG.getBasicBlock(MBB));
    628 
    629   return DAG.getNode(WebAssemblyISD::TABLESWITCH, DL, MVT::Other, Ops);
    630 }
    631 
    632 SDValue WebAssemblyTargetLowering::LowerVASTART(SDValue Op,
    633                                                 SelectionDAG &DAG) const {
    634   SDLoc DL(Op);
    635   EVT PtrVT = getPointerTy(DAG.getMachineFunction().getDataLayout());
    636 
    637   // The incoming non-fixed arguments are placed on the top of the stack, with
    638   // natural alignment, at the point of the call, so the base pointer is just
    639   // the current frame pointer.
    640   DAG.getMachineFunction().getFrameInfo()->setFrameAddressIsTaken(true);
    641   unsigned FP =
    642       Subtarget->getRegisterInfo()->getFrameRegister(DAG.getMachineFunction());
    643   SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), DL, FP, PtrVT);
    644   const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
    645   return DAG.getStore(Op.getOperand(0), DL, FrameAddr, Op.getOperand(1),
    646                       MachinePointerInfo(SV), false, false, 0);
    647 }
    648 
    649 //===----------------------------------------------------------------------===//
    650 //                          WebAssembly Optimization Hooks
    651 //===----------------------------------------------------------------------===//
    652