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