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