LLVM  6.0.0svn
WebAssemblyISelLowering.cpp
Go to the documentation of this file.
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 
18 #include "WebAssemblySubtarget.h"
20 #include "llvm/CodeGen/Analysis.h"
25 #include "llvm/IR/DiagnosticInfo.h"
27 #include "llvm/IR/Function.h"
28 #include "llvm/IR/Intrinsics.h"
29 #include "llvm/Support/Debug.h"
33 using namespace llvm;
34 
35 #define DEBUG_TYPE "wasm-lower"
36 
38  const TargetMachine &TM, const WebAssemblySubtarget &STI)
39  : TargetLowering(TM), Subtarget(&STI) {
40  auto MVTPtr = Subtarget->hasAddr64() ? MVT::i64 : MVT::i32;
41 
42  // Booleans always contain 0 or 1.
44  // WebAssembly does not produce floating-point exceptions on normal floating
45  // point operations.
47  // We don't know the microarchitecture here, so just reduce register pressure.
49  // Tell ISel that we have a stack pointer.
51  Subtarget->hasAddr64() ? WebAssembly::SP64 : WebAssembly::SP32);
52  // Set up the register classes.
53  addRegisterClass(MVT::i32, &WebAssembly::I32RegClass);
54  addRegisterClass(MVT::i64, &WebAssembly::I64RegClass);
55  addRegisterClass(MVT::f32, &WebAssembly::F32RegClass);
56  addRegisterClass(MVT::f64, &WebAssembly::F64RegClass);
57  if (Subtarget->hasSIMD128()) {
58  addRegisterClass(MVT::v16i8, &WebAssembly::V128RegClass);
59  addRegisterClass(MVT::v8i16, &WebAssembly::V128RegClass);
60  addRegisterClass(MVT::v4i32, &WebAssembly::V128RegClass);
61  addRegisterClass(MVT::v4f32, &WebAssembly::V128RegClass);
62  }
63  // Compute derived properties from the register classes.
65 
71 
72  // Take the default expansion for va_arg, va_copy, and va_end. There is no
73  // default action for va_start, so we do that custom.
78 
79  for (auto T : {MVT::f32, MVT::f64}) {
80  // Don't expand the floating-point types to constant pools.
82  // Expand floating-point comparisons.
83  for (auto CC : {ISD::SETO, ISD::SETUO, ISD::SETUEQ, ISD::SETONE,
86  // Expand floating-point library function operators.
88  ISD::FMA})
90  // Note supported floating-point library function operators that otherwise
91  // default to expand.
92  for (auto Op :
95  // Support minnan and maxnan, which otherwise default to expand.
98  // WebAssembly currently has no builtin f16 support.
103  }
104 
105  for (auto T : {MVT::i32, MVT::i64}) {
106  // Expand unavailable integer operations.
107  for (auto Op :
111  ISD::SUBE}) {
113  }
114  }
115 
116  // As a special case, these operators use the type to mean the type to
117  // sign-extend from.
119  if (!Subtarget->hasAtomics()) {
120  // The Atomics feature includes signext intructions.
121  for (auto T : {MVT::i8, MVT::i16, MVT::i32})
123  }
124 
125  // Dynamic stack allocation: use the default expansion.
129 
132 
133  // Expand these forms; we pattern-match the forms that we can handle in isel.
134  for (auto T : {MVT::i32, MVT::i64, MVT::f32, MVT::f64})
135  for (auto Op : {ISD::BR_CC, ISD::SELECT_CC})
137 
138  // We have custom switch handling.
140 
141  // WebAssembly doesn't have:
142  // - Floating-point extending loads.
143  // - Floating-point truncating stores.
144  // - i1 extending loads.
147  for (auto T : MVT::integer_valuetypes())
150 
151  // Trap lowers to wasm unreachable
153 
155 }
156 
157 FastISel *WebAssemblyTargetLowering::createFastISel(
158  FunctionLoweringInfo &FuncInfo, const TargetLibraryInfo *LibInfo) const {
159  return WebAssembly::createFastISel(FuncInfo, LibInfo);
160 }
161 
162 bool WebAssemblyTargetLowering::isOffsetFoldingLegal(
163  const GlobalAddressSDNode * /*GA*/) const {
164  // All offsets can be folded.
165  return true;
166 }
167 
168 MVT WebAssemblyTargetLowering::getScalarShiftAmountTy(const DataLayout & /*DL*/,
169  EVT VT) const {
170  unsigned BitWidth = NextPowerOf2(VT.getSizeInBits() - 1);
171  if (BitWidth > 1 && BitWidth < 8) BitWidth = 8;
172 
173  if (BitWidth > 64) {
174  // The shift will be lowered to a libcall, and compiler-rt libcalls expect
175  // the count to be an i32.
176  BitWidth = 32;
177  assert(BitWidth >= Log2_32_Ceil(VT.getSizeInBits()) &&
178  "32-bit shift counts ought to be enough for anyone");
179  }
180 
181  MVT Result = MVT::getIntegerVT(BitWidth);
183  "Unable to represent scalar shift amount type");
184  return Result;
185 }
186 
187 const char *WebAssemblyTargetLowering::getTargetNodeName(
188  unsigned Opcode) const {
189  switch (static_cast<WebAssemblyISD::NodeType>(Opcode)) {
191  break;
192 #define HANDLE_NODETYPE(NODE) \
193  case WebAssemblyISD::NODE: \
194  return "WebAssemblyISD::" #NODE;
195 #include "WebAssemblyISD.def"
196 #undef HANDLE_NODETYPE
197  }
198  return nullptr;
199 }
200 
201 std::pair<unsigned, const TargetRegisterClass *>
202 WebAssemblyTargetLowering::getRegForInlineAsmConstraint(
203  const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const {
204  // First, see if this is a constraint that directly corresponds to a
205  // WebAssembly register class.
206  if (Constraint.size() == 1) {
207  switch (Constraint[0]) {
208  case 'r':
209  assert(VT != MVT::iPTR && "Pointer MVT not expected here");
210  if (Subtarget->hasSIMD128() && VT.isVector()) {
211  if (VT.getSizeInBits() == 128)
212  return std::make_pair(0U, &WebAssembly::V128RegClass);
213  }
214  if (VT.isInteger() && !VT.isVector()) {
215  if (VT.getSizeInBits() <= 32)
216  return std::make_pair(0U, &WebAssembly::I32RegClass);
217  if (VT.getSizeInBits() <= 64)
218  return std::make_pair(0U, &WebAssembly::I64RegClass);
219  }
220  break;
221  default:
222  break;
223  }
224  }
225 
226  return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
227 }
228 
229 bool WebAssemblyTargetLowering::isCheapToSpeculateCttz() const {
230  // Assume ctz is a relatively cheap operation.
231  return true;
232 }
233 
234 bool WebAssemblyTargetLowering::isCheapToSpeculateCtlz() const {
235  // Assume clz is a relatively cheap operation.
236  return true;
237 }
238 
239 bool WebAssemblyTargetLowering::isLegalAddressingMode(const DataLayout &DL,
240  const AddrMode &AM,
241  Type *Ty,
242  unsigned AS,
243  Instruction *I) const {
244  // WebAssembly offsets are added as unsigned without wrapping. The
245  // isLegalAddressingMode gives us no way to determine if wrapping could be
246  // happening, so we approximate this by accepting only non-negative offsets.
247  if (AM.BaseOffs < 0) return false;
248 
249  // WebAssembly has no scale register operands.
250  if (AM.Scale != 0) return false;
251 
252  // Everything else is legal.
253  return true;
254 }
255 
256 bool WebAssemblyTargetLowering::allowsMisalignedMemoryAccesses(
257  EVT /*VT*/, unsigned /*AddrSpace*/, unsigned /*Align*/, bool *Fast) const {
258  // WebAssembly supports unaligned accesses, though it should be declared
259  // with the p2align attribute on loads and stores which do so, and there
260  // may be a performance impact. We tell LLVM they're "fast" because
261  // for the kinds of things that LLVM uses this for (merging adjacent stores
262  // of constants, etc.), WebAssembly implementations will either want the
263  // unaligned access or they'll split anyway.
264  if (Fast) *Fast = true;
265  return true;
266 }
267 
268 bool WebAssemblyTargetLowering::isIntDivCheap(EVT VT,
269  AttributeList Attr) const {
270  // The current thinking is that wasm engines will perform this optimization,
271  // so we can save on code size.
272  return true;
273 }
274 
275 //===----------------------------------------------------------------------===//
276 // WebAssembly Lowering private implementation.
277 //===----------------------------------------------------------------------===//
278 
279 //===----------------------------------------------------------------------===//
280 // Lowering Code
281 //===----------------------------------------------------------------------===//
282 
283 static void fail(const SDLoc &DL, SelectionDAG &DAG, const char *msg) {
285  DAG.getContext()->diagnose(
287 }
288 
289 // Test whether the given calling convention is supported.
290 static bool CallingConvSupported(CallingConv::ID CallConv) {
291  // We currently support the language-independent target-independent
292  // conventions. We don't yet have a way to annotate calls with properties like
293  // "cold", and we don't have any call-clobbered registers, so these are mostly
294  // all handled the same.
295  return CallConv == CallingConv::C || CallConv == CallingConv::Fast ||
296  CallConv == CallingConv::Cold ||
297  CallConv == CallingConv::PreserveMost ||
298  CallConv == CallingConv::PreserveAll ||
299  CallConv == CallingConv::CXX_FAST_TLS;
300 }
301 
302 SDValue WebAssemblyTargetLowering::LowerCall(
303  CallLoweringInfo &CLI, SmallVectorImpl<SDValue> &InVals) const {
304  SelectionDAG &DAG = CLI.DAG;
305  SDLoc DL = CLI.DL;
306  SDValue Chain = CLI.Chain;
307  SDValue Callee = CLI.Callee;
309  auto Layout = MF.getDataLayout();
310 
311  CallingConv::ID CallConv = CLI.CallConv;
312  if (!CallingConvSupported(CallConv))
313  fail(DL, DAG,
314  "WebAssembly doesn't support language-specific or target-specific "
315  "calling conventions yet");
316  if (CLI.IsPatchPoint)
317  fail(DL, DAG, "WebAssembly doesn't support patch point yet");
318 
319  // WebAssembly doesn't currently support explicit tail calls. If they are
320  // required, fail. Otherwise, just disable them.
321  if ((CallConv == CallingConv::Fast && CLI.IsTailCall &&
323  (CLI.CS && CLI.CS.isMustTailCall()))
324  fail(DL, DAG, "WebAssembly doesn't support tail call yet");
325  CLI.IsTailCall = false;
326 
328  if (Ins.size() > 1)
329  fail(DL, DAG, "WebAssembly doesn't support more than 1 returned value yet");
330 
331  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
332  SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
333  for (unsigned i = 0; i < Outs.size(); ++i) {
334  const ISD::OutputArg &Out = Outs[i];
335  SDValue &OutVal = OutVals[i];
336  if (Out.Flags.isNest())
337  fail(DL, DAG, "WebAssembly hasn't implemented nest arguments");
338  if (Out.Flags.isInAlloca())
339  fail(DL, DAG, "WebAssembly hasn't implemented inalloca arguments");
340  if (Out.Flags.isInConsecutiveRegs())
341  fail(DL, DAG, "WebAssembly hasn't implemented cons regs arguments");
342  if (Out.Flags.isInConsecutiveRegsLast())
343  fail(DL, DAG, "WebAssembly hasn't implemented cons regs last arguments");
344  if (Out.Flags.isByVal() && Out.Flags.getByValSize() != 0) {
345  auto &MFI = MF.getFrameInfo();
346  int FI = MFI.CreateStackObject(Out.Flags.getByValSize(),
347  Out.Flags.getByValAlign(),
348  /*isSS=*/false);
349  SDValue SizeNode =
350  DAG.getConstant(Out.Flags.getByValSize(), DL, MVT::i32);
351  SDValue FINode = DAG.getFrameIndex(FI, getPointerTy(Layout));
352  Chain = DAG.getMemcpy(
353  Chain, DL, FINode, OutVal, SizeNode, Out.Flags.getByValAlign(),
354  /*isVolatile*/ false, /*AlwaysInline=*/false,
355  /*isTailCall*/ false, MachinePointerInfo(), MachinePointerInfo());
356  OutVal = FINode;
357  }
358  }
359 
360  bool IsVarArg = CLI.IsVarArg;
361  unsigned NumFixedArgs = CLI.NumFixedArgs;
362 
363  auto PtrVT = getPointerTy(Layout);
364 
365  // Analyze operands of the call, assigning locations to each operand.
367  CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
368 
369  if (IsVarArg) {
370  // Outgoing non-fixed arguments are placed in a buffer. First
371  // compute their offsets and the total amount of buffer space needed.
372  for (SDValue Arg :
373  make_range(OutVals.begin() + NumFixedArgs, OutVals.end())) {
374  EVT VT = Arg.getValueType();
375  assert(VT != MVT::iPTR && "Legalized args should be concrete");
376  Type *Ty = VT.getTypeForEVT(*DAG.getContext());
377  unsigned Offset = CCInfo.AllocateStack(Layout.getTypeAllocSize(Ty),
378  Layout.getABITypeAlignment(Ty));
379  CCInfo.addLoc(CCValAssign::getMem(ArgLocs.size(), VT.getSimpleVT(),
380  Offset, VT.getSimpleVT(),
382  }
383  }
384 
385  unsigned NumBytes = CCInfo.getAlignedCallFrameSize();
386 
387  SDValue FINode;
388  if (IsVarArg && NumBytes) {
389  // For non-fixed arguments, next emit stores to store the argument values
390  // to the stack buffer at the offsets computed above.
391  int FI = MF.getFrameInfo().CreateStackObject(NumBytes,
392  Layout.getStackAlignment(),
393  /*isSS=*/false);
394  unsigned ValNo = 0;
396  for (SDValue Arg :
397  make_range(OutVals.begin() + NumFixedArgs, OutVals.end())) {
398  assert(ArgLocs[ValNo].getValNo() == ValNo &&
399  "ArgLocs should remain in order and only hold varargs args");
400  unsigned Offset = ArgLocs[ValNo++].getLocMemOffset();
401  FINode = DAG.getFrameIndex(FI, getPointerTy(Layout));
402  SDValue Add = DAG.getNode(ISD::ADD, DL, PtrVT, FINode,
403  DAG.getConstant(Offset, DL, PtrVT));
404  Chains.push_back(DAG.getStore(
405  Chain, DL, Arg, Add,
406  MachinePointerInfo::getFixedStack(MF, FI, Offset), 0));
407  }
408  if (!Chains.empty())
409  Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chains);
410  } else if (IsVarArg) {
411  FINode = DAG.getIntPtrConstant(0, DL);
412  }
413 
414  // Compute the operands for the CALLn node.
416  Ops.push_back(Chain);
417  Ops.push_back(Callee);
418 
419  // Add all fixed arguments. Note that for non-varargs calls, NumFixedArgs
420  // isn't reliable.
421  Ops.append(OutVals.begin(),
422  IsVarArg ? OutVals.begin() + NumFixedArgs : OutVals.end());
423  // Add a pointer to the vararg buffer.
424  if (IsVarArg) Ops.push_back(FINode);
425 
426  SmallVector<EVT, 8> InTys;
427  for (const auto &In : Ins) {
428  assert(!In.Flags.isByVal() && "byval is not valid for return values");
429  assert(!In.Flags.isNest() && "nest is not valid for return values");
430  if (In.Flags.isInAlloca())
431  fail(DL, DAG, "WebAssembly hasn't implemented inalloca return values");
432  if (In.Flags.isInConsecutiveRegs())
433  fail(DL, DAG, "WebAssembly hasn't implemented cons regs return values");
434  if (In.Flags.isInConsecutiveRegsLast())
435  fail(DL, DAG,
436  "WebAssembly hasn't implemented cons regs last return values");
437  // Ignore In.getOrigAlign() because all our arguments are passed in
438  // registers.
439  InTys.push_back(In.VT);
440  }
441  InTys.push_back(MVT::Other);
442  SDVTList InTyList = DAG.getVTList(InTys);
443  SDValue Res =
444  DAG.getNode(Ins.empty() ? WebAssemblyISD::CALL0 : WebAssemblyISD::CALL1,
445  DL, InTyList, Ops);
446  if (Ins.empty()) {
447  Chain = Res;
448  } else {
449  InVals.push_back(Res);
450  Chain = Res.getValue(1);
451  }
452 
453  return Chain;
454 }
455 
456 bool WebAssemblyTargetLowering::CanLowerReturn(
457  CallingConv::ID /*CallConv*/, MachineFunction & /*MF*/, bool /*IsVarArg*/,
459  LLVMContext & /*Context*/) const {
460  // WebAssembly can't currently handle returning tuples.
461  return Outs.size() <= 1;
462 }
463 
464 SDValue WebAssemblyTargetLowering::LowerReturn(
465  SDValue Chain, CallingConv::ID CallConv, bool /*IsVarArg*/,
467  const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
468  SelectionDAG &DAG) const {
469  assert(Outs.size() <= 1 && "WebAssembly can only return up to one value");
470  if (!CallingConvSupported(CallConv))
471  fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions");
472 
473  SmallVector<SDValue, 4> RetOps(1, Chain);
474  RetOps.append(OutVals.begin(), OutVals.end());
475  Chain = DAG.getNode(WebAssemblyISD::RETURN, DL, MVT::Other, RetOps);
476 
477  // Record the number and types of the return values.
478  for (const ISD::OutputArg &Out : Outs) {
479  assert(!Out.Flags.isByVal() && "byval is not valid for return values");
480  assert(!Out.Flags.isNest() && "nest is not valid for return values");
481  assert(Out.IsFixed && "non-fixed return value is not valid");
482  if (Out.Flags.isInAlloca())
483  fail(DL, DAG, "WebAssembly hasn't implemented inalloca results");
484  if (Out.Flags.isInConsecutiveRegs())
485  fail(DL, DAG, "WebAssembly hasn't implemented cons regs results");
486  if (Out.Flags.isInConsecutiveRegsLast())
487  fail(DL, DAG, "WebAssembly hasn't implemented cons regs last results");
488  }
489 
490  return Chain;
491 }
492 
493 SDValue WebAssemblyTargetLowering::LowerFormalArguments(
494  SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
495  const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
496  SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
497  if (!CallingConvSupported(CallConv))
498  fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions");
499 
501  auto *MFI = MF.getInfo<WebAssemblyFunctionInfo>();
502 
503  // Set up the incoming ARGUMENTS value, which serves to represent the liveness
504  // of the incoming values before they're represented by virtual registers.
505  MF.getRegInfo().addLiveIn(WebAssembly::ARGUMENTS);
506 
507  for (const ISD::InputArg &In : Ins) {
508  if (In.Flags.isInAlloca())
509  fail(DL, DAG, "WebAssembly hasn't implemented inalloca arguments");
510  if (In.Flags.isNest())
511  fail(DL, DAG, "WebAssembly hasn't implemented nest arguments");
512  if (In.Flags.isInConsecutiveRegs())
513  fail(DL, DAG, "WebAssembly hasn't implemented cons regs arguments");
514  if (In.Flags.isInConsecutiveRegsLast())
515  fail(DL, DAG, "WebAssembly hasn't implemented cons regs last arguments");
516  // Ignore In.getOrigAlign() because all our arguments are passed in
517  // registers.
518  InVals.push_back(
519  In.Used
520  ? DAG.getNode(WebAssemblyISD::ARGUMENT, DL, In.VT,
521  DAG.getTargetConstant(InVals.size(), DL, MVT::i32))
522  : DAG.getUNDEF(In.VT));
523 
524  // Record the number and types of arguments.
525  MFI->addParam(In.VT);
526  }
527 
528  // Varargs are copied into a buffer allocated by the caller, and a pointer to
529  // the buffer is passed as an argument.
530  if (IsVarArg) {
531  MVT PtrVT = getPointerTy(MF.getDataLayout());
532  unsigned VarargVreg =
534  MFI->setVarargBufferVreg(VarargVreg);
535  Chain = DAG.getCopyToReg(
536  Chain, DL, VarargVreg,
537  DAG.getNode(WebAssemblyISD::ARGUMENT, DL, PtrVT,
538  DAG.getTargetConstant(Ins.size(), DL, MVT::i32)));
539  MFI->addParam(PtrVT);
540  }
541 
542  // Record the number and types of results.
543  SmallVector<MVT, 4> Params;
545  ComputeSignatureVTs(*MF.getFunction(), DAG.getTarget(), Params, Results);
546  for (MVT VT : Results)
547  MFI->addResult(VT);
548 
549  return Chain;
550 }
551 
552 //===----------------------------------------------------------------------===//
553 // Custom lowering hooks.
554 //===----------------------------------------------------------------------===//
555 
556 SDValue WebAssemblyTargetLowering::LowerOperation(SDValue Op,
557  SelectionDAG &DAG) const {
558  SDLoc DL(Op);
559  switch (Op.getOpcode()) {
560  default:
561  llvm_unreachable("unimplemented operation lowering");
562  return SDValue();
563  case ISD::FrameIndex:
564  return LowerFrameIndex(Op, DAG);
565  case ISD::GlobalAddress:
566  return LowerGlobalAddress(Op, DAG);
567  case ISD::ExternalSymbol:
568  return LowerExternalSymbol(Op, DAG);
569  case ISD::JumpTable:
570  return LowerJumpTable(Op, DAG);
571  case ISD::BR_JT:
572  return LowerBR_JT(Op, DAG);
573  case ISD::VASTART:
574  return LowerVASTART(Op, DAG);
575  case ISD::BlockAddress:
576  case ISD::BRIND:
577  fail(DL, DAG, "WebAssembly hasn't implemented computed gotos");
578  return SDValue();
579  case ISD::RETURNADDR: // Probably nothing meaningful can be returned here.
580  fail(DL, DAG, "WebAssembly hasn't implemented __builtin_return_address");
581  return SDValue();
582  case ISD::FRAMEADDR:
583  return LowerFRAMEADDR(Op, DAG);
584  case ISD::CopyToReg:
585  return LowerCopyToReg(Op, DAG);
586  }
587 }
588 
589 SDValue WebAssemblyTargetLowering::LowerCopyToReg(SDValue Op,
590  SelectionDAG &DAG) const {
591  SDValue Src = Op.getOperand(2);
592  if (isa<FrameIndexSDNode>(Src.getNode())) {
593  // CopyToReg nodes don't support FrameIndex operands. Other targets select
594  // the FI to some LEA-like instruction, but since we don't have that, we
595  // need to insert some kind of instruction that can take an FI operand and
596  // produces a value usable by CopyToReg (i.e. in a vreg). So insert a dummy
597  // copy_local between Op and its FI operand.
598  SDValue Chain = Op.getOperand(0);
599  SDLoc DL(Op);
600  unsigned Reg = cast<RegisterSDNode>(Op.getOperand(1))->getReg();
601  EVT VT = Src.getValueType();
602  SDValue Copy(
603  DAG.getMachineNode(VT == MVT::i32 ? WebAssembly::COPY_I32
604  : WebAssembly::COPY_I64,
605  DL, VT, Src),
606  0);
607  return Op.getNode()->getNumValues() == 1
608  ? DAG.getCopyToReg(Chain, DL, Reg, Copy)
609  : DAG.getCopyToReg(Chain, DL, Reg, Copy, Op.getNumOperands() == 4
610  ? Op.getOperand(3)
611  : SDValue());
612  }
613  return SDValue();
614 }
615 
616 SDValue WebAssemblyTargetLowering::LowerFrameIndex(SDValue Op,
617  SelectionDAG &DAG) const {
618  int FI = cast<FrameIndexSDNode>(Op)->getIndex();
619  return DAG.getTargetFrameIndex(FI, Op.getValueType());
620 }
621 
622 SDValue WebAssemblyTargetLowering::LowerFRAMEADDR(SDValue Op,
623  SelectionDAG &DAG) const {
624  // Non-zero depths are not supported by WebAssembly currently. Use the
625  // legalizer's default expansion, which is to return 0 (what this function is
626  // documented to do).
627  if (Op.getConstantOperandVal(0) > 0)
628  return SDValue();
629 
631  EVT VT = Op.getValueType();
632  unsigned FP =
634  return DAG.getCopyFromReg(DAG.getEntryNode(), SDLoc(Op), FP, VT);
635 }
636 
637 SDValue WebAssemblyTargetLowering::LowerGlobalAddress(SDValue Op,
638  SelectionDAG &DAG) const {
639  SDLoc DL(Op);
640  const auto *GA = cast<GlobalAddressSDNode>(Op);
641  EVT VT = Op.getValueType();
642  assert(GA->getTargetFlags() == 0 &&
643  "Unexpected target flags on generic GlobalAddressSDNode");
644  if (GA->getAddressSpace() != 0)
645  fail(DL, DAG, "WebAssembly only expects the 0 address space");
646  return DAG.getNode(
647  WebAssemblyISD::Wrapper, DL, VT,
648  DAG.getTargetGlobalAddress(GA->getGlobal(), DL, VT, GA->getOffset()));
649 }
650 
651 SDValue WebAssemblyTargetLowering::LowerExternalSymbol(
652  SDValue Op, SelectionDAG &DAG) const {
653  SDLoc DL(Op);
654  const auto *ES = cast<ExternalSymbolSDNode>(Op);
655  EVT VT = Op.getValueType();
656  assert(ES->getTargetFlags() == 0 &&
657  "Unexpected target flags on generic ExternalSymbolSDNode");
658  // Set the TargetFlags to 0x1 which indicates that this is a "function"
659  // symbol rather than a data symbol. We do this unconditionally even though
660  // we don't know anything about the symbol other than its name, because all
661  // external symbols used in target-independent SelectionDAG code are for
662  // functions.
663  return DAG.getNode(WebAssemblyISD::Wrapper, DL, VT,
664  DAG.getTargetExternalSymbol(ES->getSymbol(), VT,
665  /*TargetFlags=*/0x1));
666 }
667 
668 SDValue WebAssemblyTargetLowering::LowerJumpTable(SDValue Op,
669  SelectionDAG &DAG) const {
670  // There's no need for a Wrapper node because we always incorporate a jump
671  // table operand into a BR_TABLE instruction, rather than ever
672  // materializing it in a register.
673  const JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
674  return DAG.getTargetJumpTable(JT->getIndex(), Op.getValueType(),
675  JT->getTargetFlags());
676 }
677 
678 SDValue WebAssemblyTargetLowering::LowerBR_JT(SDValue Op,
679  SelectionDAG &DAG) const {
680  SDLoc DL(Op);
681  SDValue Chain = Op.getOperand(0);
682  const auto *JT = cast<JumpTableSDNode>(Op.getOperand(1));
683  SDValue Index = Op.getOperand(2);
684  assert(JT->getTargetFlags() == 0 && "WebAssembly doesn't set target flags");
685 
687  Ops.push_back(Chain);
688  Ops.push_back(Index);
689 
691  const auto &MBBs = MJTI->getJumpTables()[JT->getIndex()].MBBs;
692 
693  // Add an operand for each case.
694  for (auto MBB : MBBs) Ops.push_back(DAG.getBasicBlock(MBB));
695 
696  // TODO: For now, we just pick something arbitrary for a default case for now.
697  // We really want to sniff out the guard and put in the real default case (and
698  // delete the guard).
699  Ops.push_back(DAG.getBasicBlock(MBBs[0]));
700 
701  return DAG.getNode(WebAssemblyISD::BR_TABLE, DL, MVT::Other, Ops);
702 }
703 
704 SDValue WebAssemblyTargetLowering::LowerVASTART(SDValue Op,
705  SelectionDAG &DAG) const {
706  SDLoc DL(Op);
708 
710  const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
711 
712  SDValue ArgN = DAG.getCopyFromReg(DAG.getEntryNode(), DL,
713  MFI->getVarargBufferVreg(), PtrVT);
714  return DAG.getStore(Op.getOperand(0), DL, ArgN, Op.getOperand(1),
715  MachinePointerInfo(SV), 0);
716 }
717 
718 //===----------------------------------------------------------------------===//
719 // WebAssembly Optimization Hooks
720 //===----------------------------------------------------------------------===//
SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, unsigned Alignment=0, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
Fast - This calling convention attempts to make calls as fast as possible (e.g.
Definition: CallingConv.h:43
void setFrameAddressIsTaken(bool T)
static MVT getIntegerVT(unsigned BitWidth)
unsigned Log2_32_Ceil(uint32_t Value)
Return the ceil log base 2 of the specified value, 32 if the value is zero.
Definition: MathExtras.h:544
This file defines the interfaces that WebAssembly uses to lower LLVM code into a selection DAG...
A parsed version of the target data layout string in and methods for querying it. ...
Definition: DataLayout.h:109
EVT getValueType() const
Return the ValueType of the referenced return value.
This represents an addressing mode of: BaseGV + BaseOffs + BaseReg + Scale*ScaleReg If BaseGV is null...
bool isInteger() const
Return true if this is an integer or a vector integer type.
void setLoadExtAction(unsigned ExtType, MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified load with extension does not work with the specified type and indicate wh...
const std::vector< MachineJumpTableEntry > & getJumpTables() const
Diagnostic information for unsupported feature in backend.
BR_CC - Conditional branch.
Definition: ISDOpcodes.h:617
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
InputArg - This struct carries flags and type information about a single incoming (formal) argument o...
int CreateStackObject(uint64_t Size, unsigned Alignment, bool isSS, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it...
LLVM_ATTRIBUTE_ALWAYS_INLINE size_type size() const
Definition: SmallVector.h:136
bool isVector() const
Return true if this is a vector value type.
unsigned createVirtualRegister(const TargetRegisterClass *RegClass)
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
void addLiveIn(unsigned Reg, unsigned vreg=0)
addLiveIn - Add the specified register as a live-in.
Carry-setting nodes for multiple precision addition and subtraction.
Definition: ISDOpcodes.h:222
static void fail(const SDLoc &DL, SelectionDAG &DAG, const char *msg)
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
Definition: StringRef.h:138
STACKRESTORE has two operands, an input chain and a pointer to restore to it returns an output chain...
Definition: ISDOpcodes.h:666
void setHasFloatingPointExceptions(bool FPExceptions=true)
Tells the code generator that this target supports floating point exceptions and cares about preservi...
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
Definition: ValueTypes.h:253
SDValue getBasicBlock(MachineBasicBlock *MBB)
Function Alias Analysis Results
virtual std::pair< unsigned, const TargetRegisterClass * > getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const
Given a physical register constraint (e.g.
virtual const TargetRegisterClass * getRegClassFor(MVT VT) const
Return the register class that should be used for the specified value type.
SDNode * getNode() const
get the SDNode which holds the desired result
SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned char TargetFlags=0)
SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition: ISDOpcodes.h:404
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
Definition: ISDOpcodes.h:209
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations...
Definition: ISDOpcodes.h:433
SDValue getIntPtrConstant(uint64_t Val, const SDLoc &DL, bool isTarget=false)
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo)
void setMaxAtomicSizeInBitsSupported(unsigned SizeInBits)
Set the maximum atomic operation size supported by the backend.
Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
Definition: ValueTypes.cpp:205
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s), MachineInstr opcode, and operands.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:42
CopyToReg - This node has three operands: a chain, a register number to set to this value...
Definition: ISDOpcodes.h:170
uint64_t getConstantOperandVal(unsigned i) const
Reg
All possible values of the reg field in the ModR/M byte.
void setCondCodeAction(ISD::CondCode CC, MVT VT, LegalizeAction Action)
Indicate that the specified condition code is or isn&#39;t supported on the target and indicate what to d...
bool isInConsecutiveRegs() const
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
Definition: SelectionDAG.h:446
void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action)
Indicate that the specified operation does not work with the specified type and indicate what to do a...
SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and llvm.returnaddress on the DAG...
Definition: ISDOpcodes.h:73
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
OutputArg - This struct carries flags and a value for a single outgoing (actual) argument or outgoing...
This represents a list of ValueType&#39;s that has been intern&#39;d by a SelectionDAG.
STACKSAVE - STACKSAVE has one operand, an input chain.
Definition: ISDOpcodes.h:662
unsigned getSizeInBits() const
This is a fast-path instruction selection class that generates poor code and doesn&#39;t support illegal ...
Definition: FastISel.h:67
unsigned getSizeInBits() const
Return the size of the specified value type in bits.
Definition: ValueTypes.h:292
This file declares the WebAssembly-specific subclass of TargetMachine.
MachineFunction & getMachineFunction() const
Definition: SelectionDAG.h:385
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose...
C - The default llvm calling convention, compatible with C.
Definition: CallingConv.h:35
SDValue getTargetFrameIndex(int FI, EVT VT)
Definition: SelectionDAG.h:606
const TargetMachine & getTarget() const
Definition: SelectionDAG.h:389
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:200
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
Definition: SelectionDAG.h:830
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
Definition: SelectionDAG.h:558
amdgpu Simplify well known AMD library false Value * Callee
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
unsigned getByValSize() const
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
static bool CallingConvSupported(CallingConv::ID CallConv)
MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
Machine Value Type.
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:46
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:69
void addRegisterClass(MVT VT, const TargetRegisterClass *RC)
Add the specified register class as an available regclass for the specified value type...
void ComputeSignatureVTs(const Function &F, const TargetMachine &TM, SmallVectorImpl< MVT > &Params, SmallVectorImpl< MVT > &Results)
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
VAEND, VASTART - VAEND and VASTART have three operands: an input chain, pointer, and a SRCVALUE...
Definition: ISDOpcodes.h:695
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
Definition: SmallVector.h:116
Carry-using nodes for multiple precision addition and subtraction.
Definition: ISDOpcodes.h:231
This file provides WebAssembly-specific target descriptions.
unsigned char getTargetFlags() const
void setBooleanContents(BooleanContent Ty)
Specify how the target extends the result of integer and floating point boolean values from i1 to a w...
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
TRAP - Trapping instruction.
Definition: ISDOpcodes.h:734
unsigned GuaranteedTailCallOpt
GuaranteedTailCallOpt - This flag is enabled when -tailcallopt is specified on the commandline...
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
Definition: ISDOpcodes.h:686
static unsigned NumFixedArgs
Extended Value Type.
Definition: ValueTypes.h:34
uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
Definition: MathExtras.h:632
const AMDGPUAS & AS
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
This class contains a discriminated union of information about pointers in memory operands...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
WebAssemblyTargetLowering(const TargetMachine &TM, const WebAssemblySubtarget &STI)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
SDValue getTargetJumpTable(int JTI, EVT VT, unsigned char TargetFlags=0)
Definition: SelectionDAG.h:611
TokenFactor - This node takes multiple tokens as input and produces a single token result...
Definition: ISDOpcodes.h:50
This file declares the WebAssembly-specific subclass of TargetSubtarget.
CCState - This class holds information needed while lowering arguments and return values...
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
Definition: SelectionDAG.h:209
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:864
Provides information about what library functions are available for the current target.
const DebugLoc & getDebugLoc() const
SDValue getMemcpy(SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size, unsigned Align, bool isVol, bool AlwaysInline, bool isTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo)
Byte Swap and Counting operators.
Definition: ISDOpcodes.h:382
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
Definition: ISDOpcodes.h:555
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, unsigned Reg, SDValue N)
Definition: SelectionDAG.h:657
static mvt_range integer_valuetypes()
unsigned getFrameRegister(const MachineFunction &MF) const override
unsigned getByValAlign() const
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
FMINNAN/FMAXNAN - Behave identically to FMINNUM/FMAXNUM, except that when a single input is NaN...
Definition: ISDOpcodes.h:572
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:398
const WebAssemblyRegisterInfo * getRegisterInfo() const override
amdgpu Simplify well known AMD library false Value Value * Arg
static MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
BR_JT - Jumptable branch.
Definition: ISDOpcodes.h:605
VACOPY - VACOPY has 5 operands: an input chain, a destination pointer, a source pointer, a SRCVALUE for the destination, and a SRCVALUE for the source.
Definition: ISDOpcodes.h:691
This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
Definition: SmallVector.h:120
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, unsigned Reg, EVT VT)
Definition: SelectionDAG.h:683
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
Definition: ISDOpcodes.h:205
LLVM_NODISCARD bool empty() const
Definition: SmallVector.h:61
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition: ISDOpcodes.h:463
bool isInConsecutiveRegsLast() const
TargetOptions Options
Definition: TargetMachine.h:96
#define I(x, y, z)
Definition: MD5.cpp:58
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
This file declares WebAssembly-specific per-machine-function information.
void setStackPointerRegisterToSaveRestore(unsigned R)
If set to a physical register, this specifies the register that llvm.savestack/llvm.restorestack should save and restore.
static CCValAssign getMem(unsigned ValNo, MVT ValVT, unsigned Offset, MVT LocVT, LocInfo HTP)
unsigned getOpcode() const
FSINCOS - Compute both fsin and fcos as a single operation.
Definition: ISDOpcodes.h:575
SDValue getValue(unsigned R) const
void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
const Function * getFunction() const
getFunction - Return the LLVM function that this machine code represents
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
void setSchedulingPreference(Sched::Preference Pref)
Specify the target scheduling preference.
LLVM Value Representation.
Definition: Value.h:73
FMA - Perform a * b + c with no intermediate rounding step.
Definition: ISDOpcodes.h:277
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:57
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
unsigned getNumOperands() const
const SDValue & getOperand(unsigned i) const
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation...
LLVMContext * getContext() const
Definition: SelectionDAG.h:393
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned char TargetFlags=0)
Definition: SelectionDAG.h:600
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
Definition: ISDOpcodes.h:355
BRIND - Indirect branch.
Definition: ISDOpcodes.h:601
DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned to a specified boundary...
Definition: ISDOpcodes.h:590