LLVM  8.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 /// This file implements the WebAssemblyTargetLowering class.
12 ///
13 //===----------------------------------------------------------------------===//
14 
18 #include "WebAssemblySubtarget.h"
20 #include "llvm/CodeGen/Analysis.h"
26 #include "llvm/IR/DiagnosticInfo.h"
28 #include "llvm/IR/Function.h"
29 #include "llvm/IR/Intrinsics.h"
30 #include "llvm/Support/Debug.h"
34 using namespace llvm;
35 
36 #define DEBUG_TYPE "wasm-lower"
37 
38 // Emit proposed instructions that may not have been implemented in engines
40  "wasm-enable-unimplemented-simd",
41  cl::desc("Emit potentially-unimplemented WebAssembly SIMD instructions"),
42  cl::init(false));
43 
45  const TargetMachine &TM, const WebAssemblySubtarget &STI)
46  : TargetLowering(TM), Subtarget(&STI) {
47  auto MVTPtr = Subtarget->hasAddr64() ? MVT::i64 : MVT::i32;
48 
49  // Booleans always contain 0 or 1.
51  // Except in SIMD vectors
53  // WebAssembly does not produce floating-point exceptions on normal floating
54  // point operations.
56  // We don't know the microarchitecture here, so just reduce register pressure.
58  // Tell ISel that we have a stack pointer.
60  Subtarget->hasAddr64() ? WebAssembly::SP64 : WebAssembly::SP32);
61  // Set up the register classes.
62  addRegisterClass(MVT::i32, &WebAssembly::I32RegClass);
63  addRegisterClass(MVT::i64, &WebAssembly::I64RegClass);
64  addRegisterClass(MVT::f32, &WebAssembly::F32RegClass);
65  addRegisterClass(MVT::f64, &WebAssembly::F64RegClass);
66  if (Subtarget->hasSIMD128()) {
67  addRegisterClass(MVT::v16i8, &WebAssembly::V128RegClass);
68  addRegisterClass(MVT::v8i16, &WebAssembly::V128RegClass);
69  addRegisterClass(MVT::v4i32, &WebAssembly::V128RegClass);
70  addRegisterClass(MVT::v4f32, &WebAssembly::V128RegClass);
72  addRegisterClass(MVT::v2i64, &WebAssembly::V128RegClass);
73  addRegisterClass(MVT::v2f64, &WebAssembly::V128RegClass);
74  }
75  }
76  // Compute derived properties from the register classes.
78 
84 
85  // Take the default expansion for va_arg, va_copy, and va_end. There is no
86  // default action for va_start, so we do that custom.
91 
92  for (auto T : {MVT::f32, MVT::f64, MVT::v4f32, MVT::v2f64}) {
93  // Don't expand the floating-point types to constant pools.
95  // Expand floating-point comparisons.
96  for (auto CC : {ISD::SETO, ISD::SETUO, ISD::SETUEQ, ISD::SETONE,
99  // Expand floating-point library function operators.
100  for (auto Op :
103  // Note supported floating-point library function operators that otherwise
104  // default to expand.
105  for (auto Op :
108  // Support minnan and maxnan, which otherwise default to expand.
111  // WebAssembly currently has no builtin f16 support.
116  }
117 
118  for (auto T : {MVT::i32, MVT::i64}) {
119  // Expand unavailable integer operations.
120  for (auto Op :
125  }
126  }
127 
128  // There is no i64x2.mul instruction
130 
131  // We have custom shuffle lowering to expose the shuffle mask
132  if (Subtarget->hasSIMD128()) {
133  for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v4f32}) {
135  }
139  }
140  }
141 
142  // Custom lowering to avoid having to emit a wrap for 2xi64 constant shifts
143  if (Subtarget->hasSIMD128() && EnableUnimplementedWasmSIMDInstrs)
144  for (auto Op : {ISD::SHL, ISD::SRA, ISD::SRL})
146 
147  // As a special case, these operators use the type to mean the type to
148  // sign-extend from.
150  if (!Subtarget->hasSignExt()) {
151  for (auto T : {MVT::i8, MVT::i16, MVT::i32})
153  }
154  for (auto T : MVT::integer_vector_valuetypes())
156 
157  // Dynamic stack allocation: use the default expansion.
161 
164 
165  // Expand these forms; we pattern-match the forms that we can handle in isel.
166  for (auto T : {MVT::i32, MVT::i64, MVT::f32, MVT::f64})
167  for (auto Op : {ISD::BR_CC, ISD::SELECT_CC})
169 
170  // We have custom switch handling.
172 
173  // WebAssembly doesn't have:
174  // - Floating-point extending loads.
175  // - Floating-point truncating stores.
176  // - i1 extending loads.
179  for (auto T : MVT::integer_valuetypes())
182 
183  // Trap lowers to wasm unreachable
185 
186  // Exception handling intrinsics
188 
190 }
191 
193 WebAssemblyTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const {
194  // We have wasm instructions for these
195  switch (AI->getOperation()) {
196  case AtomicRMWInst::Add:
197  case AtomicRMWInst::Sub:
198  case AtomicRMWInst::And:
199  case AtomicRMWInst::Or:
200  case AtomicRMWInst::Xor:
201  case AtomicRMWInst::Xchg:
203  default:
204  break;
205  }
207 }
208 
209 FastISel *WebAssemblyTargetLowering::createFastISel(
210  FunctionLoweringInfo &FuncInfo, const TargetLibraryInfo *LibInfo) const {
211  return WebAssembly::createFastISel(FuncInfo, LibInfo);
212 }
213 
214 bool WebAssemblyTargetLowering::isOffsetFoldingLegal(
215  const GlobalAddressSDNode * /*GA*/) const {
216  // All offsets can be folded.
217  return true;
218 }
219 
220 MVT WebAssemblyTargetLowering::getScalarShiftAmountTy(const DataLayout & /*DL*/,
221  EVT VT) const {
222  unsigned BitWidth = NextPowerOf2(VT.getSizeInBits() - 1);
223  if (BitWidth > 1 && BitWidth < 8)
224  BitWidth = 8;
225 
226  if (BitWidth > 64) {
227  // The shift will be lowered to a libcall, and compiler-rt libcalls expect
228  // the count to be an i32.
229  BitWidth = 32;
230  assert(BitWidth >= Log2_32_Ceil(VT.getSizeInBits()) &&
231  "32-bit shift counts ought to be enough for anyone");
232  }
233 
234  MVT Result = MVT::getIntegerVT(BitWidth);
236  "Unable to represent scalar shift amount type");
237  return Result;
238 }
239 
240 // Lower an fp-to-int conversion operator from the LLVM opcode, which has an
241 // undefined result on invalid/overflow, to the WebAssembly opcode, which
242 // traps on invalid/overflow.
244  MachineBasicBlock *BB,
245  const TargetInstrInfo &TII,
246  bool IsUnsigned, bool Int64,
247  bool Float64, unsigned LoweredOpcode) {
249 
250  unsigned OutReg = MI.getOperand(0).getReg();
251  unsigned InReg = MI.getOperand(1).getReg();
252 
253  unsigned Abs = Float64 ? WebAssembly::ABS_F64 : WebAssembly::ABS_F32;
254  unsigned FConst = Float64 ? WebAssembly::CONST_F64 : WebAssembly::CONST_F32;
255  unsigned LT = Float64 ? WebAssembly::LT_F64 : WebAssembly::LT_F32;
256  unsigned GE = Float64 ? WebAssembly::GE_F64 : WebAssembly::GE_F32;
257  unsigned IConst = Int64 ? WebAssembly::CONST_I64 : WebAssembly::CONST_I32;
258  unsigned Eqz = WebAssembly::EQZ_I32;
259  unsigned And = WebAssembly::AND_I32;
260  int64_t Limit = Int64 ? INT64_MIN : INT32_MIN;
261  int64_t Substitute = IsUnsigned ? 0 : Limit;
262  double CmpVal = IsUnsigned ? -(double)Limit * 2.0 : -(double)Limit;
263  auto &Context = BB->getParent()->getFunction().getContext();
265 
266  const BasicBlock *LLVM_BB = BB->getBasicBlock();
267  MachineFunction *F = BB->getParent();
268  MachineBasicBlock *TrueMBB = F->CreateMachineBasicBlock(LLVM_BB);
269  MachineBasicBlock *FalseMBB = F->CreateMachineBasicBlock(LLVM_BB);
270  MachineBasicBlock *DoneMBB = F->CreateMachineBasicBlock(LLVM_BB);
271 
273  F->insert(It, FalseMBB);
274  F->insert(It, TrueMBB);
275  F->insert(It, DoneMBB);
276 
277  // Transfer the remainder of BB and its successor edges to DoneMBB.
278  DoneMBB->splice(DoneMBB->begin(), BB,
279  std::next(MachineBasicBlock::iterator(MI)), BB->end());
280  DoneMBB->transferSuccessorsAndUpdatePHIs(BB);
281 
282  BB->addSuccessor(TrueMBB);
283  BB->addSuccessor(FalseMBB);
284  TrueMBB->addSuccessor(DoneMBB);
285  FalseMBB->addSuccessor(DoneMBB);
286 
287  unsigned Tmp0, Tmp1, CmpReg, EqzReg, FalseReg, TrueReg;
288  Tmp0 = MRI.createVirtualRegister(MRI.getRegClass(InReg));
289  Tmp1 = MRI.createVirtualRegister(MRI.getRegClass(InReg));
290  CmpReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
291  EqzReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
292  FalseReg = MRI.createVirtualRegister(MRI.getRegClass(OutReg));
293  TrueReg = MRI.createVirtualRegister(MRI.getRegClass(OutReg));
294 
295  MI.eraseFromParent();
296  // For signed numbers, we can do a single comparison to determine whether
297  // fabs(x) is within range.
298  if (IsUnsigned) {
299  Tmp0 = InReg;
300  } else {
301  BuildMI(BB, DL, TII.get(Abs), Tmp0).addReg(InReg);
302  }
303  BuildMI(BB, DL, TII.get(FConst), Tmp1)
304  .addFPImm(cast<ConstantFP>(ConstantFP::get(Ty, CmpVal)));
305  BuildMI(BB, DL, TII.get(LT), CmpReg).addReg(Tmp0).addReg(Tmp1);
306 
307  // For unsigned numbers, we have to do a separate comparison with zero.
308  if (IsUnsigned) {
309  Tmp1 = MRI.createVirtualRegister(MRI.getRegClass(InReg));
310  unsigned SecondCmpReg =
311  MRI.createVirtualRegister(&WebAssembly::I32RegClass);
312  unsigned AndReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
313  BuildMI(BB, DL, TII.get(FConst), Tmp1)
314  .addFPImm(cast<ConstantFP>(ConstantFP::get(Ty, 0.0)));
315  BuildMI(BB, DL, TII.get(GE), SecondCmpReg).addReg(Tmp0).addReg(Tmp1);
316  BuildMI(BB, DL, TII.get(And), AndReg).addReg(CmpReg).addReg(SecondCmpReg);
317  CmpReg = AndReg;
318  }
319 
320  BuildMI(BB, DL, TII.get(Eqz), EqzReg).addReg(CmpReg);
321 
322  // Create the CFG diamond to select between doing the conversion or using
323  // the substitute value.
324  BuildMI(BB, DL, TII.get(WebAssembly::BR_IF)).addMBB(TrueMBB).addReg(EqzReg);
325  BuildMI(FalseMBB, DL, TII.get(LoweredOpcode), FalseReg).addReg(InReg);
326  BuildMI(FalseMBB, DL, TII.get(WebAssembly::BR)).addMBB(DoneMBB);
327  BuildMI(TrueMBB, DL, TII.get(IConst), TrueReg).addImm(Substitute);
328  BuildMI(*DoneMBB, DoneMBB->begin(), DL, TII.get(TargetOpcode::PHI), OutReg)
329  .addReg(FalseReg)
330  .addMBB(FalseMBB)
331  .addReg(TrueReg)
332  .addMBB(TrueMBB);
333 
334  return DoneMBB;
335 }
336 
337 MachineBasicBlock *WebAssemblyTargetLowering::EmitInstrWithCustomInserter(
338  MachineInstr &MI, MachineBasicBlock *BB) const {
339  const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
340  DebugLoc DL = MI.getDebugLoc();
341 
342  switch (MI.getOpcode()) {
343  default:
344  llvm_unreachable("Unexpected instr type to insert");
345  case WebAssembly::FP_TO_SINT_I32_F32:
346  return LowerFPToInt(MI, DL, BB, TII, false, false, false,
347  WebAssembly::I32_TRUNC_S_F32);
348  case WebAssembly::FP_TO_UINT_I32_F32:
349  return LowerFPToInt(MI, DL, BB, TII, true, false, false,
350  WebAssembly::I32_TRUNC_U_F32);
351  case WebAssembly::FP_TO_SINT_I64_F32:
352  return LowerFPToInt(MI, DL, BB, TII, false, true, false,
353  WebAssembly::I64_TRUNC_S_F32);
354  case WebAssembly::FP_TO_UINT_I64_F32:
355  return LowerFPToInt(MI, DL, BB, TII, true, true, false,
356  WebAssembly::I64_TRUNC_U_F32);
357  case WebAssembly::FP_TO_SINT_I32_F64:
358  return LowerFPToInt(MI, DL, BB, TII, false, false, true,
359  WebAssembly::I32_TRUNC_S_F64);
360  case WebAssembly::FP_TO_UINT_I32_F64:
361  return LowerFPToInt(MI, DL, BB, TII, true, false, true,
362  WebAssembly::I32_TRUNC_U_F64);
363  case WebAssembly::FP_TO_SINT_I64_F64:
364  return LowerFPToInt(MI, DL, BB, TII, false, true, true,
365  WebAssembly::I64_TRUNC_S_F64);
366  case WebAssembly::FP_TO_UINT_I64_F64:
367  return LowerFPToInt(MI, DL, BB, TII, true, true, true,
368  WebAssembly::I64_TRUNC_U_F64);
369  llvm_unreachable("Unexpected instruction to emit with custom inserter");
370  }
371 }
372 
373 const char *
374 WebAssemblyTargetLowering::getTargetNodeName(unsigned Opcode) const {
375  switch (static_cast<WebAssemblyISD::NodeType>(Opcode)) {
377  break;
378 #define HANDLE_NODETYPE(NODE) \
379  case WebAssemblyISD::NODE: \
380  return "WebAssemblyISD::" #NODE;
381 #include "WebAssemblyISD.def"
382 #undef HANDLE_NODETYPE
383  }
384  return nullptr;
385 }
386 
387 std::pair<unsigned, const TargetRegisterClass *>
388 WebAssemblyTargetLowering::getRegForInlineAsmConstraint(
389  const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const {
390  // First, see if this is a constraint that directly corresponds to a
391  // WebAssembly register class.
392  if (Constraint.size() == 1) {
393  switch (Constraint[0]) {
394  case 'r':
395  assert(VT != MVT::iPTR && "Pointer MVT not expected here");
396  if (Subtarget->hasSIMD128() && VT.isVector()) {
397  if (VT.getSizeInBits() == 128)
398  return std::make_pair(0U, &WebAssembly::V128RegClass);
399  }
400  if (VT.isInteger() && !VT.isVector()) {
401  if (VT.getSizeInBits() <= 32)
402  return std::make_pair(0U, &WebAssembly::I32RegClass);
403  if (VT.getSizeInBits() <= 64)
404  return std::make_pair(0U, &WebAssembly::I64RegClass);
405  }
406  break;
407  default:
408  break;
409  }
410  }
411 
412  return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
413 }
414 
415 bool WebAssemblyTargetLowering::isCheapToSpeculateCttz() const {
416  // Assume ctz is a relatively cheap operation.
417  return true;
418 }
419 
420 bool WebAssemblyTargetLowering::isCheapToSpeculateCtlz() const {
421  // Assume clz is a relatively cheap operation.
422  return true;
423 }
424 
425 bool WebAssemblyTargetLowering::isLegalAddressingMode(const DataLayout &DL,
426  const AddrMode &AM,
427  Type *Ty, unsigned AS,
428  Instruction *I) const {
429  // WebAssembly offsets are added as unsigned without wrapping. The
430  // isLegalAddressingMode gives us no way to determine if wrapping could be
431  // happening, so we approximate this by accepting only non-negative offsets.
432  if (AM.BaseOffs < 0)
433  return false;
434 
435  // WebAssembly has no scale register operands.
436  if (AM.Scale != 0)
437  return false;
438 
439  // Everything else is legal.
440  return true;
441 }
442 
443 bool WebAssemblyTargetLowering::allowsMisalignedMemoryAccesses(
444  EVT /*VT*/, unsigned /*AddrSpace*/, unsigned /*Align*/, bool *Fast) const {
445  // WebAssembly supports unaligned accesses, though it should be declared
446  // with the p2align attribute on loads and stores which do so, and there
447  // may be a performance impact. We tell LLVM they're "fast" because
448  // for the kinds of things that LLVM uses this for (merging adjacent stores
449  // of constants, etc.), WebAssembly implementations will either want the
450  // unaligned access or they'll split anyway.
451  if (Fast)
452  *Fast = true;
453  return true;
454 }
455 
456 bool WebAssemblyTargetLowering::isIntDivCheap(EVT VT,
457  AttributeList Attr) const {
458  // The current thinking is that wasm engines will perform this optimization,
459  // so we can save on code size.
460  return true;
461 }
462 
463 EVT WebAssemblyTargetLowering::getSetCCResultType(const DataLayout &DL,
464  LLVMContext &C,
465  EVT VT) const {
466  if (VT.isVector())
468 
469  return TargetLowering::getSetCCResultType(DL, C, VT);
470 }
471 
472 bool WebAssemblyTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info,
473  const CallInst &I,
474  MachineFunction &MF,
475  unsigned Intrinsic) const {
476  switch (Intrinsic) {
477  case Intrinsic::wasm_atomic_notify:
478  Info.opc = ISD::INTRINSIC_W_CHAIN;
479  Info.memVT = MVT::i32;
480  Info.ptrVal = I.getArgOperand(0);
481  Info.offset = 0;
482  Info.align = 4;
483  // atomic.notify instruction does not really load the memory specified with
484  // this argument, but MachineMemOperand should either be load or store, so
485  // we set this to a load.
486  // FIXME Volatile isn't really correct, but currently all LLVM atomic
487  // instructions are treated as volatiles in the backend, so we should be
488  // consistent. The same applies for wasm_atomic_wait intrinsics too.
490  return true;
491  case Intrinsic::wasm_atomic_wait_i32:
492  Info.opc = ISD::INTRINSIC_W_CHAIN;
493  Info.memVT = MVT::i32;
494  Info.ptrVal = I.getArgOperand(0);
495  Info.offset = 0;
496  Info.align = 4;
498  return true;
499  case Intrinsic::wasm_atomic_wait_i64:
500  Info.opc = ISD::INTRINSIC_W_CHAIN;
501  Info.memVT = MVT::i64;
502  Info.ptrVal = I.getArgOperand(0);
503  Info.offset = 0;
504  Info.align = 8;
506  return true;
507  default:
508  return false;
509  }
510 }
511 
512 //===----------------------------------------------------------------------===//
513 // WebAssembly Lowering private implementation.
514 //===----------------------------------------------------------------------===//
515 
516 //===----------------------------------------------------------------------===//
517 // Lowering Code
518 //===----------------------------------------------------------------------===//
519 
520 static void fail(const SDLoc &DL, SelectionDAG &DAG, const char *msg) {
522  DAG.getContext()->diagnose(
524 }
525 
526 // Test whether the given calling convention is supported.
527 static bool CallingConvSupported(CallingConv::ID CallConv) {
528  // We currently support the language-independent target-independent
529  // conventions. We don't yet have a way to annotate calls with properties like
530  // "cold", and we don't have any call-clobbered registers, so these are mostly
531  // all handled the same.
532  return CallConv == CallingConv::C || CallConv == CallingConv::Fast ||
533  CallConv == CallingConv::Cold ||
534  CallConv == CallingConv::PreserveMost ||
535  CallConv == CallingConv::PreserveAll ||
536  CallConv == CallingConv::CXX_FAST_TLS;
537 }
538 
539 SDValue
540 WebAssemblyTargetLowering::LowerCall(CallLoweringInfo &CLI,
541  SmallVectorImpl<SDValue> &InVals) const {
542  SelectionDAG &DAG = CLI.DAG;
543  SDLoc DL = CLI.DL;
544  SDValue Chain = CLI.Chain;
545  SDValue Callee = CLI.Callee;
547  auto Layout = MF.getDataLayout();
548 
549  CallingConv::ID CallConv = CLI.CallConv;
550  if (!CallingConvSupported(CallConv))
551  fail(DL, DAG,
552  "WebAssembly doesn't support language-specific or target-specific "
553  "calling conventions yet");
554  if (CLI.IsPatchPoint)
555  fail(DL, DAG, "WebAssembly doesn't support patch point yet");
556 
557  // WebAssembly doesn't currently support explicit tail calls. If they are
558  // required, fail. Otherwise, just disable them.
559  if ((CallConv == CallingConv::Fast && CLI.IsTailCall &&
561  (CLI.CS && CLI.CS.isMustTailCall()))
562  fail(DL, DAG, "WebAssembly doesn't support tail call yet");
563  CLI.IsTailCall = false;
564 
566  if (Ins.size() > 1)
567  fail(DL, DAG, "WebAssembly doesn't support more than 1 returned value yet");
568 
569  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
570  SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
571  unsigned NumFixedArgs = 0;
572  for (unsigned i = 0; i < Outs.size(); ++i) {
573  const ISD::OutputArg &Out = Outs[i];
574  SDValue &OutVal = OutVals[i];
575  if (Out.Flags.isNest())
576  fail(DL, DAG, "WebAssembly hasn't implemented nest arguments");
577  if (Out.Flags.isInAlloca())
578  fail(DL, DAG, "WebAssembly hasn't implemented inalloca arguments");
579  if (Out.Flags.isInConsecutiveRegs())
580  fail(DL, DAG, "WebAssembly hasn't implemented cons regs arguments");
581  if (Out.Flags.isInConsecutiveRegsLast())
582  fail(DL, DAG, "WebAssembly hasn't implemented cons regs last arguments");
583  if (Out.Flags.isByVal() && Out.Flags.getByValSize() != 0) {
584  auto &MFI = MF.getFrameInfo();
585  int FI = MFI.CreateStackObject(Out.Flags.getByValSize(),
586  Out.Flags.getByValAlign(),
587  /*isSS=*/false);
588  SDValue SizeNode =
589  DAG.getConstant(Out.Flags.getByValSize(), DL, MVT::i32);
590  SDValue FINode = DAG.getFrameIndex(FI, getPointerTy(Layout));
591  Chain = DAG.getMemcpy(
592  Chain, DL, FINode, OutVal, SizeNode, Out.Flags.getByValAlign(),
593  /*isVolatile*/ false, /*AlwaysInline=*/false,
594  /*isTailCall*/ false, MachinePointerInfo(), MachinePointerInfo());
595  OutVal = FINode;
596  }
597  // Count the number of fixed args *after* legalization.
598  NumFixedArgs += Out.IsFixed;
599  }
600 
601  bool IsVarArg = CLI.IsVarArg;
602  auto PtrVT = getPointerTy(Layout);
603 
604  // Analyze operands of the call, assigning locations to each operand.
606  CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
607 
608  if (IsVarArg) {
609  // Outgoing non-fixed arguments are placed in a buffer. First
610  // compute their offsets and the total amount of buffer space needed.
611  for (SDValue Arg :
612  make_range(OutVals.begin() + NumFixedArgs, OutVals.end())) {
613  EVT VT = Arg.getValueType();
614  assert(VT != MVT::iPTR && "Legalized args should be concrete");
615  Type *Ty = VT.getTypeForEVT(*DAG.getContext());
616  unsigned Offset = CCInfo.AllocateStack(Layout.getTypeAllocSize(Ty),
617  Layout.getABITypeAlignment(Ty));
618  CCInfo.addLoc(CCValAssign::getMem(ArgLocs.size(), VT.getSimpleVT(),
619  Offset, VT.getSimpleVT(),
621  }
622  }
623 
624  unsigned NumBytes = CCInfo.getAlignedCallFrameSize();
625 
626  SDValue FINode;
627  if (IsVarArg && NumBytes) {
628  // For non-fixed arguments, next emit stores to store the argument values
629  // to the stack buffer at the offsets computed above.
630  int FI = MF.getFrameInfo().CreateStackObject(NumBytes,
631  Layout.getStackAlignment(),
632  /*isSS=*/false);
633  unsigned ValNo = 0;
635  for (SDValue Arg :
636  make_range(OutVals.begin() + NumFixedArgs, OutVals.end())) {
637  assert(ArgLocs[ValNo].getValNo() == ValNo &&
638  "ArgLocs should remain in order and only hold varargs args");
639  unsigned Offset = ArgLocs[ValNo++].getLocMemOffset();
640  FINode = DAG.getFrameIndex(FI, getPointerTy(Layout));
641  SDValue Add = DAG.getNode(ISD::ADD, DL, PtrVT, FINode,
642  DAG.getConstant(Offset, DL, PtrVT));
643  Chains.push_back(
644  DAG.getStore(Chain, DL, Arg, Add,
645  MachinePointerInfo::getFixedStack(MF, FI, Offset), 0));
646  }
647  if (!Chains.empty())
648  Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chains);
649  } else if (IsVarArg) {
650  FINode = DAG.getIntPtrConstant(0, DL);
651  }
652 
653  // Compute the operands for the CALLn node.
655  Ops.push_back(Chain);
656  Ops.push_back(Callee);
657 
658  // Add all fixed arguments. Note that for non-varargs calls, NumFixedArgs
659  // isn't reliable.
660  Ops.append(OutVals.begin(),
661  IsVarArg ? OutVals.begin() + NumFixedArgs : OutVals.end());
662  // Add a pointer to the vararg buffer.
663  if (IsVarArg)
664  Ops.push_back(FINode);
665 
666  SmallVector<EVT, 8> InTys;
667  for (const auto &In : Ins) {
668  assert(!In.Flags.isByVal() && "byval is not valid for return values");
669  assert(!In.Flags.isNest() && "nest is not valid for return values");
670  if (In.Flags.isInAlloca())
671  fail(DL, DAG, "WebAssembly hasn't implemented inalloca return values");
672  if (In.Flags.isInConsecutiveRegs())
673  fail(DL, DAG, "WebAssembly hasn't implemented cons regs return values");
674  if (In.Flags.isInConsecutiveRegsLast())
675  fail(DL, DAG,
676  "WebAssembly hasn't implemented cons regs last return values");
677  // Ignore In.getOrigAlign() because all our arguments are passed in
678  // registers.
679  InTys.push_back(In.VT);
680  }
681  InTys.push_back(MVT::Other);
682  SDVTList InTyList = DAG.getVTList(InTys);
683  SDValue Res =
684  DAG.getNode(Ins.empty() ? WebAssemblyISD::CALL0 : WebAssemblyISD::CALL1,
685  DL, InTyList, Ops);
686  if (Ins.empty()) {
687  Chain = Res;
688  } else {
689  InVals.push_back(Res);
690  Chain = Res.getValue(1);
691  }
692 
693  return Chain;
694 }
695 
696 bool WebAssemblyTargetLowering::CanLowerReturn(
697  CallingConv::ID /*CallConv*/, MachineFunction & /*MF*/, bool /*IsVarArg*/,
699  LLVMContext & /*Context*/) const {
700  // WebAssembly can't currently handle returning tuples.
701  return Outs.size() <= 1;
702 }
703 
704 SDValue WebAssemblyTargetLowering::LowerReturn(
705  SDValue Chain, CallingConv::ID CallConv, bool /*IsVarArg*/,
707  const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
708  SelectionDAG &DAG) const {
709  assert(Outs.size() <= 1 && "WebAssembly can only return up to one value");
710  if (!CallingConvSupported(CallConv))
711  fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions");
712 
713  SmallVector<SDValue, 4> RetOps(1, Chain);
714  RetOps.append(OutVals.begin(), OutVals.end());
715  Chain = DAG.getNode(WebAssemblyISD::RETURN, DL, MVT::Other, RetOps);
716 
717  // Record the number and types of the return values.
718  for (const ISD::OutputArg &Out : Outs) {
719  assert(!Out.Flags.isByVal() && "byval is not valid for return values");
720  assert(!Out.Flags.isNest() && "nest is not valid for return values");
721  assert(Out.IsFixed && "non-fixed return value is not valid");
722  if (Out.Flags.isInAlloca())
723  fail(DL, DAG, "WebAssembly hasn't implemented inalloca results");
724  if (Out.Flags.isInConsecutiveRegs())
725  fail(DL, DAG, "WebAssembly hasn't implemented cons regs results");
726  if (Out.Flags.isInConsecutiveRegsLast())
727  fail(DL, DAG, "WebAssembly hasn't implemented cons regs last results");
728  }
729 
730  return Chain;
731 }
732 
733 SDValue WebAssemblyTargetLowering::LowerFormalArguments(
734  SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
735  const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
736  SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
737  if (!CallingConvSupported(CallConv))
738  fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions");
739 
741  auto *MFI = MF.getInfo<WebAssemblyFunctionInfo>();
742 
743  // Set up the incoming ARGUMENTS value, which serves to represent the liveness
744  // of the incoming values before they're represented by virtual registers.
745  MF.getRegInfo().addLiveIn(WebAssembly::ARGUMENTS);
746 
747  for (const ISD::InputArg &In : Ins) {
748  if (In.Flags.isInAlloca())
749  fail(DL, DAG, "WebAssembly hasn't implemented inalloca arguments");
750  if (In.Flags.isNest())
751  fail(DL, DAG, "WebAssembly hasn't implemented nest arguments");
752  if (In.Flags.isInConsecutiveRegs())
753  fail(DL, DAG, "WebAssembly hasn't implemented cons regs arguments");
754  if (In.Flags.isInConsecutiveRegsLast())
755  fail(DL, DAG, "WebAssembly hasn't implemented cons regs last arguments");
756  // Ignore In.getOrigAlign() because all our arguments are passed in
757  // registers.
758  InVals.push_back(In.Used ? DAG.getNode(WebAssemblyISD::ARGUMENT, DL, In.VT,
759  DAG.getTargetConstant(InVals.size(),
760  DL, MVT::i32))
761  : DAG.getUNDEF(In.VT));
762 
763  // Record the number and types of arguments.
764  MFI->addParam(In.VT);
765  }
766 
767  // Varargs are copied into a buffer allocated by the caller, and a pointer to
768  // the buffer is passed as an argument.
769  if (IsVarArg) {
770  MVT PtrVT = getPointerTy(MF.getDataLayout());
771  unsigned VarargVreg =
773  MFI->setVarargBufferVreg(VarargVreg);
774  Chain = DAG.getCopyToReg(
775  Chain, DL, VarargVreg,
776  DAG.getNode(WebAssemblyISD::ARGUMENT, DL, PtrVT,
777  DAG.getTargetConstant(Ins.size(), DL, MVT::i32)));
778  MFI->addParam(PtrVT);
779  }
780 
781  // Record the number and types of arguments and results.
782  SmallVector<MVT, 4> Params;
785  DAG.getTarget(), Params, Results);
786  for (MVT VT : Results)
787  MFI->addResult(VT);
788  // TODO: Use signatures in WebAssemblyMachineFunctionInfo too and unify
789  // the param logic here with ComputeSignatureVTs
790  assert(MFI->getParams().size() == Params.size() &&
791  std::equal(MFI->getParams().begin(), MFI->getParams().end(),
792  Params.begin()));
793 
794  return Chain;
795 }
796 
797 //===----------------------------------------------------------------------===//
798 // Custom lowering hooks.
799 //===----------------------------------------------------------------------===//
800 
801 SDValue WebAssemblyTargetLowering::LowerOperation(SDValue Op,
802  SelectionDAG &DAG) const {
803  SDLoc DL(Op);
804  switch (Op.getOpcode()) {
805  default:
806  llvm_unreachable("unimplemented operation lowering");
807  return SDValue();
808  case ISD::FrameIndex:
809  return LowerFrameIndex(Op, DAG);
810  case ISD::GlobalAddress:
811  return LowerGlobalAddress(Op, DAG);
812  case ISD::ExternalSymbol:
813  return LowerExternalSymbol(Op, DAG);
814  case ISD::JumpTable:
815  return LowerJumpTable(Op, DAG);
816  case ISD::BR_JT:
817  return LowerBR_JT(Op, DAG);
818  case ISD::VASTART:
819  return LowerVASTART(Op, DAG);
820  case ISD::BlockAddress:
821  case ISD::BRIND:
822  fail(DL, DAG, "WebAssembly hasn't implemented computed gotos");
823  return SDValue();
824  case ISD::RETURNADDR: // Probably nothing meaningful can be returned here.
825  fail(DL, DAG, "WebAssembly hasn't implemented __builtin_return_address");
826  return SDValue();
827  case ISD::FRAMEADDR:
828  return LowerFRAMEADDR(Op, DAG);
829  case ISD::CopyToReg:
830  return LowerCopyToReg(Op, DAG);
832  return LowerINTRINSIC_WO_CHAIN(Op, DAG);
833  case ISD::VECTOR_SHUFFLE:
834  return LowerVECTOR_SHUFFLE(Op, DAG);
835  case ISD::SHL:
836  case ISD::SRA:
837  case ISD::SRL:
838  return LowerShift(Op, DAG);
839  }
840 }
841 
842 SDValue WebAssemblyTargetLowering::LowerCopyToReg(SDValue Op,
843  SelectionDAG &DAG) const {
844  SDValue Src = Op.getOperand(2);
845  if (isa<FrameIndexSDNode>(Src.getNode())) {
846  // CopyToReg nodes don't support FrameIndex operands. Other targets select
847  // the FI to some LEA-like instruction, but since we don't have that, we
848  // need to insert some kind of instruction that can take an FI operand and
849  // produces a value usable by CopyToReg (i.e. in a vreg). So insert a dummy
850  // copy_local between Op and its FI operand.
851  SDValue Chain = Op.getOperand(0);
852  SDLoc DL(Op);
853  unsigned Reg = cast<RegisterSDNode>(Op.getOperand(1))->getReg();
854  EVT VT = Src.getValueType();
855  SDValue Copy(DAG.getMachineNode(VT == MVT::i32 ? WebAssembly::COPY_I32
856  : WebAssembly::COPY_I64,
857  DL, VT, Src),
858  0);
859  return Op.getNode()->getNumValues() == 1
860  ? DAG.getCopyToReg(Chain, DL, Reg, Copy)
861  : DAG.getCopyToReg(Chain, DL, Reg, Copy,
862  Op.getNumOperands() == 4 ? Op.getOperand(3)
863  : SDValue());
864  }
865  return SDValue();
866 }
867 
868 SDValue WebAssemblyTargetLowering::LowerFrameIndex(SDValue Op,
869  SelectionDAG &DAG) const {
870  int FI = cast<FrameIndexSDNode>(Op)->getIndex();
871  return DAG.getTargetFrameIndex(FI, Op.getValueType());
872 }
873 
874 SDValue WebAssemblyTargetLowering::LowerFRAMEADDR(SDValue Op,
875  SelectionDAG &DAG) const {
876  // Non-zero depths are not supported by WebAssembly currently. Use the
877  // legalizer's default expansion, which is to return 0 (what this function is
878  // documented to do).
879  if (Op.getConstantOperandVal(0) > 0)
880  return SDValue();
881 
883  EVT VT = Op.getValueType();
884  unsigned FP =
886  return DAG.getCopyFromReg(DAG.getEntryNode(), SDLoc(Op), FP, VT);
887 }
888 
889 SDValue WebAssemblyTargetLowering::LowerGlobalAddress(SDValue Op,
890  SelectionDAG &DAG) const {
891  SDLoc DL(Op);
892  const auto *GA = cast<GlobalAddressSDNode>(Op);
893  EVT VT = Op.getValueType();
894  assert(GA->getTargetFlags() == 0 &&
895  "Unexpected target flags on generic GlobalAddressSDNode");
896  if (GA->getAddressSpace() != 0)
897  fail(DL, DAG, "WebAssembly only expects the 0 address space");
898  return DAG.getNode(
899  WebAssemblyISD::Wrapper, DL, VT,
900  DAG.getTargetGlobalAddress(GA->getGlobal(), DL, VT, GA->getOffset()));
901 }
902 
903 SDValue
904 WebAssemblyTargetLowering::LowerExternalSymbol(SDValue Op,
905  SelectionDAG &DAG) const {
906  SDLoc DL(Op);
907  const auto *ES = cast<ExternalSymbolSDNode>(Op);
908  EVT VT = Op.getValueType();
909  assert(ES->getTargetFlags() == 0 &&
910  "Unexpected target flags on generic ExternalSymbolSDNode");
911  // Set the TargetFlags to 0x1 which indicates that this is a "function"
912  // symbol rather than a data symbol. We do this unconditionally even though
913  // we don't know anything about the symbol other than its name, because all
914  // external symbols used in target-independent SelectionDAG code are for
915  // functions.
916  return DAG.getNode(
917  WebAssemblyISD::Wrapper, DL, VT,
918  DAG.getTargetExternalSymbol(ES->getSymbol(), VT,
920 }
921 
922 SDValue WebAssemblyTargetLowering::LowerJumpTable(SDValue Op,
923  SelectionDAG &DAG) const {
924  // There's no need for a Wrapper node because we always incorporate a jump
925  // table operand into a BR_TABLE instruction, rather than ever
926  // materializing it in a register.
927  const JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
928  return DAG.getTargetJumpTable(JT->getIndex(), Op.getValueType(),
929  JT->getTargetFlags());
930 }
931 
932 SDValue WebAssemblyTargetLowering::LowerBR_JT(SDValue Op,
933  SelectionDAG &DAG) const {
934  SDLoc DL(Op);
935  SDValue Chain = Op.getOperand(0);
936  const auto *JT = cast<JumpTableSDNode>(Op.getOperand(1));
937  SDValue Index = Op.getOperand(2);
938  assert(JT->getTargetFlags() == 0 && "WebAssembly doesn't set target flags");
939 
941  Ops.push_back(Chain);
942  Ops.push_back(Index);
943 
945  const auto &MBBs = MJTI->getJumpTables()[JT->getIndex()].MBBs;
946 
947  // Add an operand for each case.
948  for (auto MBB : MBBs)
949  Ops.push_back(DAG.getBasicBlock(MBB));
950 
951  // TODO: For now, we just pick something arbitrary for a default case for now.
952  // We really want to sniff out the guard and put in the real default case (and
953  // delete the guard).
954  Ops.push_back(DAG.getBasicBlock(MBBs[0]));
955 
956  return DAG.getNode(WebAssemblyISD::BR_TABLE, DL, MVT::Other, Ops);
957 }
958 
959 SDValue WebAssemblyTargetLowering::LowerVASTART(SDValue Op,
960  SelectionDAG &DAG) const {
961  SDLoc DL(Op);
963 
965  const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
966 
967  SDValue ArgN = DAG.getCopyFromReg(DAG.getEntryNode(), DL,
968  MFI->getVarargBufferVreg(), PtrVT);
969  return DAG.getStore(Op.getOperand(0), DL, ArgN, Op.getOperand(1),
970  MachinePointerInfo(SV), 0);
971 }
972 
973 SDValue
974 WebAssemblyTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
975  SelectionDAG &DAG) const {
976  unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
977  SDLoc DL(Op);
978  switch (IntNo) {
979  default:
980  return {}; // Don't custom lower most intrinsics.
981 
982  case Intrinsic::wasm_lsda:
983  // TODO For now, just return 0 not to crash
984  return DAG.getConstant(0, DL, Op.getValueType());
985  }
986 }
987 
988 SDValue
989 WebAssemblyTargetLowering::LowerVECTOR_SHUFFLE(SDValue Op,
990  SelectionDAG &DAG) const {
991  SDLoc DL(Op);
992  ArrayRef<int> Mask = cast<ShuffleVectorSDNode>(Op.getNode())->getMask();
994  assert(VecType.is128BitVector() && "Unexpected shuffle vector type");
995  size_t LaneBytes = VecType.getVectorElementType().getSizeInBits() / 8;
996 
997  // Space for two vector args and sixteen mask indices
998  SDValue Ops[18];
999  size_t OpIdx = 0;
1000  Ops[OpIdx++] = Op.getOperand(0);
1001  Ops[OpIdx++] = Op.getOperand(1);
1002 
1003  // Expand mask indices to byte indices and materialize them as operands
1004  for (size_t I = 0, Lanes = Mask.size(); I < Lanes; ++I) {
1005  for (size_t J = 0; J < LaneBytes; ++J) {
1006  // Lower undefs (represented by -1 in mask) to zero
1007  uint64_t ByteIndex =
1008  Mask[I] == -1 ? 0 : (uint64_t)Mask[I] * LaneBytes + J;
1009  Ops[OpIdx++] = DAG.getConstant(ByteIndex, DL, MVT::i32);
1010  }
1011  }
1012 
1013  return DAG.getNode(WebAssemblyISD::SHUFFLE, DL, MVT::v16i8, Ops);
1014 }
1015 
1016 SDValue WebAssemblyTargetLowering::LowerShift(SDValue Op,
1017  SelectionDAG &DAG) const {
1018  SDLoc DL(Op);
1019  auto *ShiftVec = dyn_cast<BuildVectorSDNode>(Op.getOperand(1).getNode());
1020  APInt SplatValue, SplatUndef;
1021  unsigned SplatBitSize;
1022  bool HasAnyUndefs;
1023  if (!ShiftVec || !ShiftVec->isConstantSplat(SplatValue, SplatUndef,
1024  SplatBitSize, HasAnyUndefs))
1025  return Op;
1026  unsigned Opcode;
1027  switch (Op.getOpcode()) {
1028  case ISD::SHL:
1029  Opcode = WebAssemblyISD::VEC_SHL;
1030  break;
1031  case ISD::SRA:
1032  Opcode = WebAssemblyISD::VEC_SHR_S;
1033  break;
1034  case ISD::SRL:
1035  Opcode = WebAssemblyISD::VEC_SHR_U;
1036  break;
1037  default:
1038  llvm_unreachable("unexpected opcode");
1039  return Op;
1040  }
1041  return DAG.getNode(Opcode, DL, Op.getValueType(), Op.getOperand(0),
1042  DAG.getConstant(SplatValue.trunc(32), DL, MVT::i32));
1043 }
1044 
1045 //===----------------------------------------------------------------------===//
1046 // WebAssembly Optimization Hooks
1047 //===----------------------------------------------------------------------===//
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)
uint64_t CallInst * C
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:552
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:111
EVT getValueType() const
Return the ValueType of the referenced return value.
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...
static Type * getDoubleTy(LLVMContext &C)
Definition: Type.cpp:165
const std::vector< MachineJumpTableEntry > & getJumpTables() const
LLVMContext & Context
Diagnostic information for unsupported feature in backend.
const TargetRegisterClass * getRegClass(unsigned Reg) const
Return the register class of the specified virtual register.
BR_CC - Conditional branch.
Definition: ISDOpcodes.h:619
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...
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
Definition: ISDOpcodes.h:351
bool isVector() const
Return true if this is a vector value type.
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:223
static void fail(const SDLoc &DL, SelectionDAG &DAG, const char *msg)
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Definition: MachineInstr.h:383
unsigned getReg() const
getReg - Returns the register number.
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
Definition: StringRef.h:138
void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
STACKRESTORE has two operands, an input chain and a pointer to restore to it returns an output chain...
Definition: ISDOpcodes.h:668
This class represents a function call, abstracting a target machine&#39;s calling convention.
unsigned Reg
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.
void setBooleanVectorContents(BooleanContent Ty)
Specify how the target extends the result of a vector boolean value from a vector of i1 to a wider ty...
Fast - This calling convention attempts to make calls as fast as possible (e.g.
Definition: CallingConv.h:43
virtual const TargetRegisterClass * getRegClassFor(MVT VT) const
Return the register class that should be used for the specified value type.
unsigned const TargetRegisterInfo * TRI
A debug info location.
Definition: DebugLoc.h:34
F(f)
an instruction that atomically reads a memory location, combines it with another value, and then stores the result back.
Definition: Instructions.h:681
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.
AtomicExpansionKind
Enum that specifies what an atomic load/AtomicRMWInst is expanded to, if at all.
int CreateStackObject(uint64_t Size, unsigned Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it...
Select with condition operator - This selects between a true value and a false value (ops #2 and #3) ...
Definition: ISDOpcodes.h:415
void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action)
Indicate that the specified truncating store does not work with the specified type and indicate what ...
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
Definition: ISDOpcodes.h:159
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
Definition: ISDOpcodes.h:210
SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded integer shift operations...
Definition: ISDOpcodes.h:436
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.
const HexagonInstrInfo * TII
static Type * getFloatTy(LLVMContext &C)
Definition: Type.cpp:164
#define INT64_MIN
Definition: DataTypes.h:80
Shift and rotation operations.
Definition: ISDOpcodes.h:390
Type * getTypeForEVT(LLVMContext &Context) const
This method returns an LLVM type corresponding to the specified EVT.
Definition: ValueTypes.cpp:202
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.
BinOp getOperation() const
Definition: Instructions.h:734
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:42
void eraseFromParent()
Unlink &#39;this&#39; from the containing basic block and delete it.
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
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
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:409
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
Definition: SelectionDAG.h:457
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:664
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:395
void computeRegisterProperties(const TargetRegisterInfo *TRI)
Once all of the register classes are added, this allows us to compute derived properties we expose...
SDValue getTargetFrameIndex(int FI, EVT VT)
Definition: SelectionDAG.h:625
const TargetMachine & getTarget() const
Definition: SelectionDAG.h:399
Simple integer binary arithmetic operators.
Definition: ISDOpcodes.h:201
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: APInt.h:33
SDValue getUNDEF(EVT VT)
Return an UNDEF node. UNDEF does not have a useful SDLoc.
Definition: SelectionDAG.h:867
static mvt_range integer_vector_valuetypes()
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
Definition: SelectionDAG.h:573
amdgpu Simplify well known AMD library false Value * Callee
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
Definition: ISDOpcodes.h:151
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *bb=nullptr)
CreateMachineBasicBlock - Allocate a new MachineBasicBlock.
MVT getVectorElementType() const
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
unsigned getByValSize() const
bool IsFixed
IsFixed - Is this a "fixed" value, ie not passed through a vararg "...".
TargetInstrInfo - Interface to description of machine instruction set.
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
The memory access is volatile.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:410
Control flow instructions. These all have token chains.
Definition: ISDOpcodes.h:598
static bool CallingConvSupported(CallingConv::ID CallConv)
unsigned const MachineRegisterInfo * MRI
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.
LLVM Basic Block Representation.
Definition: BasicBlock.h:58
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...
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:149
VAEND, VASTART - VAEND and VASTART have three operands: an input chain, pointer, and a SRCVALUE...
Definition: ISDOpcodes.h:697
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
Definition: SmallVector.h:129
Carry-using nodes for multiple precision addition and subtraction.
Definition: ISDOpcodes.h:232
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...
cl::opt< bool > EnableUnimplementedWasmSIMDInstrs("wasm-enable-unimplemented-simd", cl::desc("Emit potentially-unimplemented WebAssembly SIMD instructions"), cl::init(false))
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:736
unsigned GuaranteedTailCallOpt
GuaranteedTailCallOpt - This flag is enabled when -tailcallopt is specified on the commandline...
self_iterator getIterator()
Definition: ilist_node.h:82
VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE, and the alignment.
Definition: ISDOpcodes.h:688
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
Definition: Function.cpp:194
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:640
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
size_t size() const
Definition: SmallVector.h:53
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:630
TokenFactor - This node takes multiple tokens as input and produces a single token result...
Definition: ISDOpcodes.h:50
static MachineBasicBlock * LowerFPToInt(MachineInstr &MI, DebugLoc DL, MachineBasicBlock *BB, const TargetInstrInfo &TII, bool IsUnsigned, bool Int64, bool Float64, unsigned LoweredOpcode)
This file declares the WebAssembly-specific subclass of TargetSubtarget.
Iterator for intrusive lists based on ilist_node.
CCState - This class holds information needed while lowering arguments and return values...
void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
Definition: SelectionDAG.h:222
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:847
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)
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
Definition: ValueTypes.h:96
Byte Swap and Counting operators.
Definition: ISDOpcodes.h:393
FP16_TO_FP, FP_TO_FP16 - These operators are used to perform promotions and truncation for half-preci...
Definition: ISDOpcodes.h:559
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
C - The default llvm calling convention, compatible with C.
Definition: CallingConv.h:35
static Constant * get(Type *Ty, double V)
This returns a ConstantFP, or a vector containing a splat of a ConstantFP, for the specified value in...
Definition: Constants.cpp:684
SDValue getCopyToReg(SDValue Chain, const SDLoc &dl, unsigned Reg, SDValue N)
Definition: SelectionDAG.h:676
const Function & getFunction() const
Return the LLVM function that this machine code represents.
static mvt_range integer_valuetypes()
unsigned getFrameRegister(const MachineFunction &MF) const override
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition: Function.h:164
void ComputeSignatureVTs(const FunctionType *Ty, const Function &F, const TargetMachine &TM, SmallVectorImpl< MVT > &Params, SmallVectorImpl< MVT > &Results)
Class for arbitrary precision integers.
Definition: APInt.h:70
unsigned getByValAlign() const
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
A "pseudo-class" with methods for operating on BUILD_VECTORs.
AddrMode
ARM Addressing Modes.
Definition: ARMBaseInfo.h:186
FMINNAN/FMAXNAN - NaN-propagating minimum/maximum that also treat -0.0 as less than 0...
Definition: ISDOpcodes.h:574
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:394
const WebAssemblyRegisterInfo * getRegisterInfo() const override
amdgpu Simplify well known AMD library false Value Value * Arg
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
The memory access reads data.
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:607
Representation of each machine instruction.
Definition: MachineInstr.h:64
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:693
This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
Definition: SmallVector.h:133
bool isVector() const
Return true if this is a vector value type.
Definition: ValueTypes.h:151
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB &#39;Other&#39; at the position From, and insert it into this MBB right before &#39;...
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, unsigned Reg, EVT VT)
Definition: SelectionDAG.h:702
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:206
LLVM_NODISCARD bool empty() const
Definition: SmallVector.h:56
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition: ISDOpcodes.h:466
bool isInConsecutiveRegsLast() const
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
Definition: MCInstrInfo.h:45
virtual EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, EVT VT) const
Return the ValueType of the result of SETCC operations.
TargetOptions Options
Definition: TargetMachine.h:97
#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.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:323
static CCValAssign getMem(unsigned ValNo, MVT ValVT, unsigned Offset, MVT LocVT, LocInfo HTP)
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
unsigned getOpcode() const
FSINCOS - Compute both fsin and fcos as a single operation.
Definition: ISDOpcodes.h:577
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.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void insert(iterator MBBI, MachineBasicBlock *MBB)
SDValue getFrameIndex(int FI, EVT VT, bool isTarget=false)
Value * getArgOperand(unsigned i) const
getArgOperand/setArgOperand - Return/set the i-th call argument.
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:286
std::underlying_type< E >::type Mask()
Get a bitmask with 1s in all places up to the high-order bit of E&#39;s largest value.
Definition: BitmaskEnum.h:81
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:59
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
const WebAssemblyInstrInfo * getInstrInfo() const override
unsigned getNumOperands() const
const SDValue & getOperand(unsigned i) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned char TargetFlags=0) const
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:414
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation...
LLVMContext * getContext() const
Definition: SelectionDAG.h:404
unsigned createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned char TargetFlags=0)
Definition: SelectionDAG.h:619
MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing an unsigned/signed value of...
Definition: ISDOpcodes.h:364
BRIND - Indirect branch.
Definition: ISDOpcodes.h:603
DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned to a specified boundary...
Definition: ISDOpcodes.h:592