LLVM 23.0.0git
WebAssemblyISelDAGToDAG.cpp
Go to the documentation of this file.
1//- WebAssemblyISelDAGToDAG.cpp - A dag to dag inst selector for WebAssembly -//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file defines an instruction selector for the WebAssembly target.
11///
12//===----------------------------------------------------------------------===//
13
15#include "WebAssembly.h"
24#include "llvm/IR/Function.h" // To access function attributes.
25#include "llvm/IR/IntrinsicsWebAssembly.h"
27#include "llvm/Support/Debug.h"
30
31using namespace llvm;
32
33#define DEBUG_TYPE "wasm-isel"
34#define PASS_NAME "WebAssembly Instruction Selection"
35
36//===--------------------------------------------------------------------===//
37/// WebAssembly-specific code to select WebAssembly machine instructions for
38/// SelectionDAG operations.
39///
40namespace {
41class WebAssemblyDAGToDAGISel final : public SelectionDAGISel {
42 /// Keep a pointer to the WebAssemblySubtarget around so that we can make the
43 /// right decision when generating code for different targets.
44 const WebAssemblySubtarget *Subtarget;
45
46public:
47 WebAssemblyDAGToDAGISel() = delete;
48
49 WebAssemblyDAGToDAGISel(WebAssemblyTargetMachine &TM,
50 CodeGenOptLevel OptLevel)
51 : SelectionDAGISel(TM, OptLevel), Subtarget(nullptr) {}
52
53 bool runOnMachineFunction(MachineFunction &MF) override {
54 LLVM_DEBUG(dbgs() << "********** ISelDAGToDAG **********\n"
55 "********** Function: "
56 << MF.getName() << '\n');
57
58 Subtarget = &MF.getSubtarget<WebAssemblySubtarget>();
59
61 }
62
63 void PreprocessISelDAG() override;
64
65 void Select(SDNode *Node) override;
66
67 bool SelectInlineAsmMemoryOperand(const SDValue &Op,
68 InlineAsm::ConstraintCode ConstraintID,
69 std::vector<SDValue> &OutOps) override;
70
71 bool SelectAddrOperands32(SDValue Op, SDValue &Offset, SDValue &Addr);
72 bool SelectAddrOperands64(SDValue Op, SDValue &Offset, SDValue &Addr);
73 bool SelectAtomicAddrOperands(SDNode *Op, SDValue N, SDValue &Offset,
74 SDValue &Addr, SDValue &Order, bool Is64);
75 bool SelectAtomicAddrOperands32(SDNode *Op, SDValue N, SDValue &Offset,
76 SDValue &Addr, SDValue &Order);
77 bool SelectAtomicAddrOperands64(SDNode *Op, SDValue N, SDValue &Offset,
78 SDValue &Addr, SDValue &Order);
79
80// Include the pieces autogenerated from the target description.
81#include "WebAssemblyGenDAGISel.inc"
82
83private:
84 // add select functions here...
85
86 bool SelectAddrOperands(MVT AddrType, unsigned ConstOpc, SDValue Op,
87 SDValue &Offset, SDValue &Addr);
88 bool SelectAddrAddOperands(MVT OffsetType, SDValue N, SDValue &Offset,
89 SDValue &Addr);
90};
91
92class WebAssemblyDAGToDAGISelLegacy : public SelectionDAGISelLegacy {
93public:
94 static char ID;
95 explicit WebAssemblyDAGToDAGISelLegacy(WebAssemblyTargetMachine &TM,
96 CodeGenOptLevel OptLevel)
98 ID, std::make_unique<WebAssemblyDAGToDAGISel>(TM, OptLevel)) {}
99};
100} // end anonymous namespace
101
102char WebAssemblyDAGToDAGISelLegacy::ID;
103
104INITIALIZE_PASS(WebAssemblyDAGToDAGISelLegacy, DEBUG_TYPE, PASS_NAME, false,
105 false)
106
107void WebAssemblyDAGToDAGISel::PreprocessISelDAG() {
108 // Stack objects that should be allocated to locals are hoisted to WebAssembly
109 // locals when they are first used. However for those without uses, we hoist
110 // them here. It would be nice if there were some hook to do this when they
111 // are added to the MachineFrameInfo, but that's not the case right now.
112 MachineFrameInfo &FrameInfo = MF->getFrameInfo();
113 for (int Idx = 0; Idx < FrameInfo.getObjectIndexEnd(); Idx++)
115
117}
118
119static SDValue getTagSymNode(int Tag, SelectionDAG *DAG) {
121 auto &MF = DAG->getMachineFunction();
122 const auto &TLI = DAG->getTargetLoweringInfo();
123 MVT PtrVT = TLI.getPointerTy(DAG->getDataLayout());
124 const char *SymName = Tag == WebAssembly::CPP_EXCEPTION
125 ? MF.createExternalSymbolName("__cpp_exception")
126 : MF.createExternalSymbolName("__c_longjmp");
127 return DAG->getTargetExternalSymbol(SymName, PtrVT);
128}
129
131 SmallVector<MVT, 4> &Returns,
132 SmallVector<MVT, 4> &Params) {
133 auto toWasmValType = [](MVT VT) {
134 if (VT == MVT::i32) {
135 return wasm::ValType::I32;
136 }
137 if (VT == MVT::i64) {
138 return wasm::ValType::I64;
139 }
140 if (VT == MVT::f32) {
141 return wasm::ValType::F32;
142 }
143 if (VT == MVT::f64) {
144 return wasm::ValType::F64;
145 }
146 if (VT == MVT::externref) {
148 }
149 if (VT == MVT::funcref) {
151 }
152 if (VT == MVT::exnref) {
154 }
155 LLVM_DEBUG(errs() << "Unhandled type for llvm.wasm.ref.test.func: " << VT
156 << "\n");
157 llvm_unreachable("Unhandled type for llvm.wasm.ref.test.func");
158 };
159 auto NParams = Params.size();
160 auto NReturns = Returns.size();
161 auto BitWidth = (NParams + NReturns + 2) * 64;
162 auto Sig = APInt(BitWidth, 0);
163
164 // Annoying special case: if getSignificantBits() <= 64 then InstrEmitter will
165 // emit an Imm instead of a CImm. It simplifies WebAssemblyMCInstLower if we
166 // always emit a CImm. So xor NParams with 0x7ffffff to ensure
167 // getSignificantBits() > 64
168 Sig |= NReturns ^ 0x7ffffff;
169 for (auto &Return : Returns) {
170 auto V = toWasmValType(Return);
171 Sig <<= 64;
172 Sig |= (int64_t)V;
173 }
174 Sig <<= 64;
175 Sig |= NParams;
176 for (auto &Param : Params) {
177 auto V = toWasmValType(Param);
178 Sig <<= 64;
179 Sig |= (int64_t)V;
180 }
181 return Sig;
182}
183
184static unsigned getWebAssemblyMemoryOrder(AtomicOrdering Ordering) {
185 unsigned OrderVal = wasm::WASM_MEM_ORDER_SEQ_CST;
186 switch (Ordering) {
193 break;
196 break;
197 default:
198 llvm_unreachable("Invalid atomic ordering");
199 }
200 return OrderVal;
201}
202
203void WebAssemblyDAGToDAGISel::Select(SDNode *Node) {
204 // If we have a custom node, we already have selected!
205 if (Node->isMachineOpcode()) {
206 LLVM_DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n");
207 Node->setNodeId(-1);
208 return;
209 }
210
211 MVT PtrVT = TLI->getPointerTy(CurDAG->getDataLayout());
212 auto GlobalGetIns = PtrVT == MVT::i64 ? WebAssembly::GLOBAL_GET_I64
213 : WebAssembly::GLOBAL_GET_I32;
214
215 SDLoc DL(Node);
216 MachineFunction &MF = CurDAG->getMachineFunction();
217 switch (Node->getOpcode()) {
218 case ISD::ATOMIC_FENCE: {
219 if (!MF.getSubtarget<WebAssemblySubtarget>().hasAtomics())
220 break;
221
222 uint64_t SyncScopeID = Node->getConstantOperandVal(2);
223 MachineSDNode *Fence = nullptr;
224 switch (SyncScopeID) {
226 // We lower a single-thread fence to a pseudo compiler barrier instruction
227 // preventing instruction reordering. This will not be emitted in final
228 // binary.
229 Fence = CurDAG->getMachineNode(WebAssembly::COMPILER_FENCE,
230 DL, // debug loc
231 MVT::Other, // outchain type
232 Node->getOperand(0) // inchain
233 );
234 break;
235 case SyncScope::System: {
236 unsigned Order = wasm::WASM_MEM_ORDER_SEQ_CST;
237 if (MF.getSubtarget<WebAssemblySubtarget>().hasRelaxedAtomics()) {
238 auto Ordering =
239 static_cast<AtomicOrdering>(Node->getConstantOperandVal(1));
240 Order = getWebAssemblyMemoryOrder(Ordering);
241 }
242 Fence = CurDAG->getMachineNode(
243 WebAssembly::ATOMIC_FENCE,
244 DL, // debug loc
245 MVT::Other, // outchain type
246 CurDAG->getTargetConstant(Order, DL, MVT::i32), // order
247 Node->getOperand(0) // inchain
248 );
249 break;
250 }
251 default:
252 llvm_unreachable("Unknown scope!");
253 }
254
255 ReplaceNode(Node, Fence);
256 CurDAG->RemoveDeadNode(Node);
257 return;
258 }
259
261 unsigned IntNo = Node->getConstantOperandVal(0);
262 switch (IntNo) {
263 case Intrinsic::wasm_tls_size: {
264 MachineSDNode *TLSSize = CurDAG->getMachineNode(
265 GlobalGetIns, DL, PtrVT,
266 CurDAG->getTargetExternalSymbol("__tls_size", PtrVT));
267 ReplaceNode(Node, TLSSize);
268 return;
269 }
270
271 case Intrinsic::wasm_tls_align: {
272 MachineSDNode *TLSAlign = CurDAG->getMachineNode(
273 GlobalGetIns, DL, PtrVT,
274 CurDAG->getTargetExternalSymbol("__tls_align", PtrVT));
275 ReplaceNode(Node, TLSAlign);
276 return;
277 }
278 case Intrinsic::wasm_ref_test_func: {
279 // First emit the TABLE_GET instruction to convert function pointer ==>
280 // funcref
281 MachineFunction &MF = CurDAG->getMachineFunction();
284 MF.getContext(), Subtarget);
285 SDValue TableSym = CurDAG->getMCSymbol(Table, PtrVT);
286 SDValue FuncPtr = Node->getOperand(1);
287 if (Subtarget->hasAddr64() && FuncPtr.getValueType() == MVT::i64) {
288 // table.get expects an i32 but on 64 bit platforms the function pointer
289 // is an i64. In that case, i32.wrap_i64 to convert.
290 FuncPtr = SDValue(CurDAG->getMachineNode(WebAssembly::I32_WRAP_I64, DL,
291 MVT::i32, FuncPtr),
292 0);
293 }
294 SDValue FuncRef =
295 SDValue(CurDAG->getMachineNode(WebAssembly::TABLE_GET_FUNCREF, DL,
296 MVT::funcref, TableSym, FuncPtr),
297 0);
298
299 // Encode the signature information into the type index placeholder.
300 // This gets decoded and converted into the actual type signature in
301 // WebAssemblyMCInstLower.cpp.
302 SmallVector<MVT, 4> Params;
303 SmallVector<MVT, 4> Returns;
304
305 bool IsParam = false;
306 // Operand 0 is the return register, Operand 1 is the function pointer.
307 // The remaining operands encode the type of the function we are testing
308 // for.
309 for (unsigned I = 2, E = Node->getNumOperands(); I < E; ++I) {
310 MVT VT = Node->getOperand(I).getValueType().getSimpleVT();
311 if (VT == MVT::Untyped) {
312 IsParam = true;
313 continue;
314 }
315 if (IsParam) {
316 Params.push_back(VT);
317 } else {
318 Returns.push_back(VT);
319 }
320 }
321 auto Sig = encodeFunctionSignature(CurDAG, DL, Returns, Params);
322
323 auto SigOp = CurDAG->getTargetConstant(
324 Sig, DL, EVT::getIntegerVT(*CurDAG->getContext(), Sig.getBitWidth()));
325 MachineSDNode *RefTestNode = CurDAG->getMachineNode(
326 WebAssembly::REF_TEST_FUNCREF, DL, MVT::i32, {SigOp, FuncRef});
327 ReplaceNode(Node, RefTestNode);
328 return;
329 }
330 }
331 break;
332 }
333
335 unsigned IntNo = Node->getConstantOperandVal(1);
336 const auto &TLI = CurDAG->getTargetLoweringInfo();
337 MVT PtrVT = TLI.getPointerTy(CurDAG->getDataLayout());
338 switch (IntNo) {
339 case Intrinsic::wasm_tls_base: {
340 MachineSDNode *TLSBase = CurDAG->getMachineNode(
341 GlobalGetIns, DL, PtrVT, MVT::Other,
342 CurDAG->getTargetExternalSymbol("__tls_base", PtrVT),
343 Node->getOperand(0));
344 ReplaceNode(Node, TLSBase);
345 return;
346 }
347
348 case Intrinsic::wasm_catch: {
349 int Tag = Node->getConstantOperandVal(2);
350 SDValue SymNode = getTagSymNode(Tag, CurDAG);
351 unsigned CatchOpcode = WebAssembly::WasmUseLegacyEH
352 ? WebAssembly::CATCH_LEGACY
353 : WebAssembly::CATCH;
354 MachineSDNode *Catch =
355 CurDAG->getMachineNode(CatchOpcode, DL,
356 {
357 PtrVT, // exception pointer
358 MVT::Other // outchain type
359 },
360 {
361 SymNode, // exception symbol
362 Node->getOperand(0) // inchain
363 });
364 ReplaceNode(Node, Catch);
365 return;
366 }
367 }
368 break;
369 }
370
371 case ISD::INTRINSIC_VOID: {
372 unsigned IntNo = Node->getConstantOperandVal(1);
373 switch (IntNo) {
374 case Intrinsic::wasm_throw: {
375 int Tag = Node->getConstantOperandVal(2);
376 SDValue SymNode = getTagSymNode(Tag, CurDAG);
377 MachineSDNode *Throw =
378 CurDAG->getMachineNode(WebAssembly::THROW, DL,
379 MVT::Other, // outchain type
380 {
381 SymNode, // exception symbol
382 Node->getOperand(3), // thrown value
383 Node->getOperand(0) // inchain
384 });
385 ReplaceNode(Node, Throw);
386 return;
387 }
388 case Intrinsic::wasm_rethrow: {
389 // RETHROW's BB argument will be populated in LateEHPrepare. Just use a
390 // '0' as a placeholder for now.
391 MachineSDNode *Rethrow = CurDAG->getMachineNode(
392 WebAssembly::RETHROW, DL,
393 MVT::Other, // outchain type
394 {
395 CurDAG->getConstant(0, DL, MVT::i32), // placeholder
396 Node->getOperand(0) // inchain
397 });
398 ReplaceNode(Node, Rethrow);
399 return;
400 }
401 }
402 break;
403 }
404
407 // CALL has both variable operands and variable results, but ISel only
408 // supports one or the other. Split calls into two nodes glued together, one
409 // for the operands and one for the results. These two nodes will be
410 // recombined in a custom inserter hook into a single MachineInstr.
412 for (size_t i = 1; i < Node->getNumOperands(); ++i) {
413 SDValue Op = Node->getOperand(i);
414 // Remove the wrapper when the call target is a function, an external
415 // symbol (which will be lowered to a library function), or an alias of
416 // a function. If the target is not a function/external symbol, we
417 // shouldn't remove the wrapper, because we cannot call it directly and
418 // instead we want it to be loaded with a CONST instruction and called
419 // with a call_indirect later.
420 if (i == 1 && Op->getOpcode() == WebAssemblyISD::Wrapper) {
421 SDValue NewOp = Op->getOperand(0);
422 if (auto *GlobalOp = dyn_cast<GlobalAddressSDNode>(NewOp.getNode())) {
423 if (isa<Function>(
424 GlobalOp->getGlobal()->stripPointerCastsAndAliases()))
425 Op = NewOp;
426 } else if (isa<ExternalSymbolSDNode>(NewOp.getNode())) {
427 Op = NewOp;
428 }
429 }
430 Ops.push_back(Op);
431 }
432
433 // Add the chain last
434 Ops.push_back(Node->getOperand(0));
435 MachineSDNode *CallParams =
436 CurDAG->getMachineNode(WebAssembly::CALL_PARAMS, DL, MVT::Glue, Ops);
437
438 unsigned Results = Node->getOpcode() == WebAssemblyISD::CALL
439 ? WebAssembly::CALL_RESULTS
440 : WebAssembly::RET_CALL_RESULTS;
441
442 SDValue Link(CallParams, 0);
443 MachineSDNode *CallResults =
444 CurDAG->getMachineNode(Results, DL, Node->getVTList(), Link);
445 ReplaceNode(Node, CallResults);
446 return;
447 }
448
449 default:
450 break;
451 }
452
453 // Select the default instruction.
454 SelectCode(Node);
455}
456
457bool WebAssemblyDAGToDAGISel::SelectInlineAsmMemoryOperand(
458 const SDValue &Op, InlineAsm::ConstraintCode ConstraintID,
459 std::vector<SDValue> &OutOps) {
460 switch (ConstraintID) {
461 case InlineAsm::ConstraintCode::m:
462 // We just support simple memory operands that just have a single address
463 // operand and need no special handling.
464 OutOps.push_back(Op);
465 return false;
466 default:
467 break;
468 }
469
470 return true;
471}
472
473bool WebAssemblyDAGToDAGISel::SelectAddrAddOperands(MVT OffsetType, SDValue N,
475 SDValue &Addr) {
476 assert(N.getNumOperands() == 2 && "Attempting to fold in a non-binary op");
477
478 // WebAssembly constant offsets are performed as unsigned with infinite
479 // precision, so we need to check for NoUnsignedWrap so that we don't fold an
480 // offset for an add that needs wrapping.
481 if (N.getOpcode() == ISD::ADD && !N.getNode()->getFlags().hasNoUnsignedWrap())
482 return false;
483
484 for (size_t i = 0; i < 2; ++i) {
485 SDValue Op = N.getOperand(i);
486 SDValue OtherOp = N.getOperand(i == 0 ? 1 : 0);
487
488 // Folds constants in an add into the offset.
489 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op)) {
490 Offset =
491 CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(N), OffsetType);
492 Addr = OtherOp;
493 return true;
494 }
495
496 // Fold target global addresses into the offset.
497 if (!TM.isPositionIndependent()) {
498 if (Op.getOpcode() == WebAssemblyISD::Wrapper)
499 Op = Op.getOperand(0);
500
501 if (Op.getOpcode() == ISD::TargetGlobalAddress) {
502 Addr = OtherOp;
503 Offset = Op;
504 return true;
505 }
506 }
507 }
508 return false;
509}
510
511bool WebAssemblyDAGToDAGISel::SelectAddrOperands(MVT AddrType,
512 unsigned ConstOpc, SDValue N,
514 SDValue &Addr) {
515 SDLoc DL(N);
516
517 // Fold target global addresses into the offset.
518 if (!TM.isPositionIndependent()) {
519 SDValue Op(N);
520 if (Op.getOpcode() == WebAssemblyISD::Wrapper)
521 Op = Op.getOperand(0);
522
523 if (Op.getOpcode() == ISD::TargetGlobalAddress) {
524 Offset = Op;
525 Addr = SDValue(
526 CurDAG->getMachineNode(ConstOpc, DL, AddrType,
527 CurDAG->getTargetConstant(0, DL, AddrType)),
528 0);
529 return true;
530 }
531 }
532
533 // Fold anything inside an add into the offset.
534 if (N.getOpcode() == ISD::ADD &&
535 SelectAddrAddOperands(AddrType, N, Offset, Addr))
536 return true;
537
538 // Likewise, treat an 'or' node as an 'add' if the or'ed bits are known to be
539 // zero and fold them into the offset too.
540 if (N.getOpcode() == ISD::OR) {
541 bool OrIsAdd;
542 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
543 OrIsAdd =
544 CurDAG->MaskedValueIsZero(N->getOperand(0), CN->getAPIntValue());
545 } else {
546 KnownBits Known0 = CurDAG->computeKnownBits(N->getOperand(0), 0);
547 KnownBits Known1 = CurDAG->computeKnownBits(N->getOperand(1), 0);
548 OrIsAdd = (~Known0.Zero & ~Known1.Zero) == 0;
549 }
550
551 if (OrIsAdd && SelectAddrAddOperands(AddrType, N, Offset, Addr))
552 return true;
553 }
554
555 // Fold constant addresses into the offset.
556 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N)) {
557 Offset = CurDAG->getTargetConstant(CN->getZExtValue(), DL, AddrType);
558 Addr = SDValue(
559 CurDAG->getMachineNode(ConstOpc, DL, AddrType,
560 CurDAG->getTargetConstant(0, DL, AddrType)),
561 0);
562 return true;
563 }
564
565 // Else it's a plain old load/store with no offset.
566 Offset = CurDAG->getTargetConstant(0, DL, AddrType);
567 Addr = N;
568 return true;
569}
570
571bool WebAssemblyDAGToDAGISel::SelectAddrOperands32(SDValue Op, SDValue &Offset,
572 SDValue &Addr) {
573 return SelectAddrOperands(MVT::i32, WebAssembly::CONST_I32, Op, Offset, Addr);
574}
575
576bool WebAssemblyDAGToDAGISel::SelectAddrOperands64(SDValue Op, SDValue &Offset,
577 SDValue &Addr) {
578 return SelectAddrOperands(MVT::i64, WebAssembly::CONST_I64, Op, Offset, Addr);
579}
580
582 while (N) {
583 if (auto *MemNode = dyn_cast<MemSDNode>(N))
584 return MemNode;
585 switch (N->getOpcode()) {
586 case ISD::ZERO_EXTEND:
587 case ISD::SIGN_EXTEND:
588 case ISD::ANY_EXTEND:
590 case ISD::AssertZext:
591 case ISD::AssertSext:
592 case ISD::TRUNCATE:
593 case ISD::BITCAST:
594 case ISD::AND:
595 N = N->getOperand(0).getNode();
596 break;
597 default:
598 return nullptr;
599 }
600 }
601 return nullptr;
602}
603
604bool WebAssemblyDAGToDAGISel::SelectAtomicAddrOperands(SDNode *Op, SDValue N,
606 SDValue &Addr,
607 SDValue &Order,
608 bool Is64) {
609 auto *MemNode = findMemSDNode(Op);
610 if (!MemNode)
611 return false;
612
613 bool Match = Is64 ? SelectAddrOperands64(N, Offset, Addr)
614 : SelectAddrOperands32(N, Offset, Addr);
615 if (!Match)
616 return false;
617
618 auto Ordering = MemNode->getMergedOrdering();
619 unsigned OrderVal = wasm::WASM_MEM_ORDER_SEQ_CST;
620 if (Subtarget->hasRelaxedAtomics())
621 OrderVal = getWebAssemblyMemoryOrder(Ordering);
622 Order = CurDAG->getTargetConstant(OrderVal, SDLoc(Op), MVT::i32);
623 return true;
624}
625
626bool WebAssemblyDAGToDAGISel::SelectAtomicAddrOperands32(SDNode *Op, SDValue N,
628 SDValue &Addr,
629 SDValue &Order) {
630 return SelectAtomicAddrOperands(Op, N, Offset, Addr, Order, /*Is64=*/false);
631}
632
633bool WebAssemblyDAGToDAGISel::SelectAtomicAddrOperands64(SDNode *Op, SDValue N,
635 SDValue &Addr,
636 SDValue &Order) {
637 return SelectAtomicAddrOperands(Op, N, Offset, Addr, Order, /*Is64=*/true);
638}
639
640/// This pass converts a legalized DAG into a WebAssembly-specific DAG, ready
641/// for instruction scheduling.
643 CodeGenOptLevel OptLevel) {
644 return new WebAssemblyDAGToDAGISelLegacy(TM, OptLevel);
645}
return SDValue()
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static MemSDNode * findMemSDNode(SDNode *N)
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis Results
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define DEBUG_TYPE
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define I(x, y, z)
Definition MD5.cpp:57
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
#define LLVM_DEBUG(...)
Definition Debug.h:114
#define PASS_NAME
static unsigned getWebAssemblyMemoryOrder(AtomicOrdering Ordering)
static SDValue getTagSymNode(int Tag, SelectionDAG *DAG)
static APInt encodeFunctionSignature(SelectionDAG *DAG, SDLoc &DL, SmallVector< MVT, 4 > &Returns, SmallVector< MVT, 4 > &Params)
This file defines the interfaces that WebAssembly uses to lower LLVM code into a selection DAG.
This file provides WebAssembly-specific target descriptions.
This file declares the WebAssembly-specific subclass of TargetMachine.
This file contains the declaration of the WebAssembly-specific utility functions.
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end.
Class for arbitrary precision integers.
Definition APInt.h:78
unsigned getPointerSizeInBits(unsigned AS=0) const
The size in bits of the pointer representation in a given address space.
Definition DataLayout.h:494
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
Machine Value Type.
static MVT getIntegerVT(unsigned BitWidth)
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MCContext & getContext() const
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
This is an abstract virtual class for memory operations.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
EVT getValueType() const
Return the ValueType of the referenced return value.
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
virtual void PreprocessISelDAG()
PreprocessISelDAG - This hook allows targets to hack on the graph before instruction selection starts...
virtual bool runOnMachineFunction(MachineFunction &mf)
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
const TargetLowering & getTargetLoweringInfo() const
const DataLayout & getDataLayout() const
MachineFunction & getMachineFunction() const
LLVM_ABI SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned TargetFlags=0)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
static std::optional< unsigned > getLocalForStackObject(MachineFunction &MF, int FrameIndex)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:264
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
Definition ISDOpcodes.h:853
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
Definition ISDOpcodes.h:220
@ ATOMIC_FENCE
OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope) This corresponds to the fence instruction.
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
Definition ISDOpcodes.h:993
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:844
@ TargetGlobalAddress
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
Definition ISDOpcodes.h:185
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
Definition ISDOpcodes.h:850
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition ISDOpcodes.h:888
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:739
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
Definition ISDOpcodes.h:205
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
Definition ISDOpcodes.h:856
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
Definition ISDOpcodes.h:62
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
Definition ISDOpcodes.h:213
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
Definition LLVMContext.h:55
@ System
Synchronized with respect to all concurrently executing threads.
Definition LLVMContext.h:58
MCSymbolWasm * getOrCreateFunctionTableSymbol(MCContext &Ctx, const WebAssemblySubtarget *Subtarget)
Returns the __indirect_function_table, for use in call_indirect and in function bitcasts.
cl::opt< bool > WasmUseLegacyEH
NodeAddr< NodeBase * > Node
Definition RDFGraph.h:381
@ WASM_MEM_ORDER_SEQ_CST
Definition Wasm.h:86
@ WASM_MEM_ORDER_ACQ_REL
Definition Wasm.h:87
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
@ Offset
Definition DWP.cpp:532
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
FunctionPass * createWebAssemblyISelDag(WebAssemblyTargetMachine &TM, CodeGenOptLevel OptLevel)
This pass converts a legalized DAG into a WebAssembly-specific DAG, ready for instruction scheduling.
CodeGenOptLevel
Code generation optimization level.
Definition CodeGen.h:82
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
AtomicOrdering
Atomic ordering for LLVM's memory model.
DWARFExpression::Operation Op
constexpr unsigned BitWidth
#define N
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
Definition ValueTypes.h:61