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