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