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