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 = llvm::WebAssembly::getTLSBase(
341 *CurDAG, DL, Subtarget, Node->getOperand(0));
342 ReplaceNode(Node, TLSBase);
343 return;
344 }
345
346 case Intrinsic::wasm_catch: {
347 int Tag = Node->getConstantOperandVal(2);
348 SDValue SymNode = getTagSymNode(Tag, CurDAG);
349 unsigned CatchOpcode = WebAssembly::WasmUseLegacyEH
350 ? WebAssembly::CATCH_LEGACY
351 : WebAssembly::CATCH;
352 MachineSDNode *Catch =
353 CurDAG->getMachineNode(CatchOpcode, DL,
354 {
355 PtrVT, // exception pointer
356 MVT::Other // outchain type
357 },
358 {
359 SymNode, // exception symbol
360 Node->getOperand(0) // inchain
361 });
362 ReplaceNode(Node, Catch);
363 return;
364 }
365 }
366 break;
367 }
368
369 case ISD::INTRINSIC_VOID: {
370 unsigned IntNo = Node->getConstantOperandVal(1);
371 switch (IntNo) {
372 case Intrinsic::wasm_throw: {
373 int Tag = Node->getConstantOperandVal(2);
374 SDValue SymNode = getTagSymNode(Tag, CurDAG);
375 MachineSDNode *Throw =
376 CurDAG->getMachineNode(WebAssembly::THROW, DL,
377 MVT::Other, // outchain type
378 {
379 SymNode, // exception symbol
380 Node->getOperand(3), // thrown value
381 Node->getOperand(0) // inchain
382 });
383 ReplaceNode(Node, Throw);
384 return;
385 }
386 case Intrinsic::wasm_rethrow: {
387 // RETHROW's BB argument will be populated in LateEHPrepare. Just use a
388 // '0' as a placeholder for now.
389 MachineSDNode *Rethrow = CurDAG->getMachineNode(
390 WebAssembly::RETHROW, DL,
391 MVT::Other, // outchain type
392 {
393 CurDAG->getConstant(0, DL, MVT::i32), // placeholder
394 Node->getOperand(0) // inchain
395 });
396 ReplaceNode(Node, Rethrow);
397 return;
398 }
399 }
400 break;
401 }
402
405 // CALL has both variable operands and variable results, but ISel only
406 // supports one or the other. Split calls into two nodes glued together, one
407 // for the operands and one for the results. These two nodes will be
408 // recombined in a custom inserter hook into a single MachineInstr.
410 for (size_t i = 1; i < Node->getNumOperands(); ++i) {
411 SDValue Op = Node->getOperand(i);
412 // Remove the wrapper when the call target is a function, an external
413 // symbol (which will be lowered to a library function), or an alias of
414 // a function. If the target is not a function/external symbol, we
415 // shouldn't remove the wrapper, because we cannot call it directly and
416 // instead we want it to be loaded with a CONST instruction and called
417 // with a call_indirect later.
418 if (i == 1 && Op->getOpcode() == WebAssemblyISD::Wrapper) {
419 SDValue NewOp = Op->getOperand(0);
420 if (auto *GlobalOp = dyn_cast<GlobalAddressSDNode>(NewOp.getNode())) {
421 if (isa<Function>(
422 GlobalOp->getGlobal()->stripPointerCastsAndAliases()))
423 Op = NewOp;
424 } else if (isa<ExternalSymbolSDNode>(NewOp.getNode())) {
425 Op = NewOp;
426 }
427 }
428 Ops.push_back(Op);
429 }
430
431 // Add the chain last
432 Ops.push_back(Node->getOperand(0));
433 MachineSDNode *CallParams =
434 CurDAG->getMachineNode(WebAssembly::CALL_PARAMS, DL, MVT::Glue, Ops);
435
436 unsigned Results = Node->getOpcode() == WebAssemblyISD::CALL
437 ? WebAssembly::CALL_RESULTS
438 : WebAssembly::RET_CALL_RESULTS;
439
440 SDValue Link(CallParams, 0);
441 MachineSDNode *CallResults =
442 CurDAG->getMachineNode(Results, DL, Node->getVTList(), Link);
443 ReplaceNode(Node, CallResults);
444 return;
445 }
446
447 default:
448 break;
449 }
450
451 // Select the default instruction.
452 SelectCode(Node);
453}
454
455bool WebAssemblyDAGToDAGISel::SelectInlineAsmMemoryOperand(
456 const SDValue &Op, InlineAsm::ConstraintCode ConstraintID,
457 std::vector<SDValue> &OutOps) {
458 switch (ConstraintID) {
459 case InlineAsm::ConstraintCode::m:
460 // We just support simple memory operands that just have a single address
461 // operand and need no special handling.
462 OutOps.push_back(Op);
463 return false;
464 default:
465 break;
466 }
467
468 return true;
469}
470
471bool WebAssemblyDAGToDAGISel::SelectAddrAddOperands(MVT OffsetType, SDValue N,
473 SDValue &Addr) {
474 assert(N.getNumOperands() == 2 && "Attempting to fold in a non-binary op");
475
476 // WebAssembly constant offsets are performed as unsigned with infinite
477 // precision, so we need to check for NoUnsignedWrap so that we don't fold an
478 // offset for an add that needs wrapping.
479 if (N.getOpcode() == ISD::ADD && !N.getNode()->getFlags().hasNoUnsignedWrap())
480 return false;
481
482 for (size_t i = 0; i < 2; ++i) {
483 SDValue Op = N.getOperand(i);
484 SDValue OtherOp = N.getOperand(i == 0 ? 1 : 0);
485
486 // Folds constants in an add into the offset.
487 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op)) {
488 Offset =
489 CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(N), OffsetType);
490 Addr = OtherOp;
491 return true;
492 }
493
494 // Fold target global addresses into the offset.
495 if (!TM.isPositionIndependent()) {
496 if (Op.getOpcode() == WebAssemblyISD::Wrapper)
497 Op = Op.getOperand(0);
498
499 if (Op.getOpcode() == ISD::TargetGlobalAddress) {
500 Addr = OtherOp;
501 Offset = Op;
502 return true;
503 }
504 }
505 }
506 return false;
507}
508
509bool WebAssemblyDAGToDAGISel::SelectAddrOperands(MVT AddrType,
510 unsigned ConstOpc, SDValue N,
512 SDValue &Addr) {
513 SDLoc DL(N);
514
515 // Fold target global addresses into the offset.
516 if (!TM.isPositionIndependent()) {
517 SDValue Op(N);
518 if (Op.getOpcode() == WebAssemblyISD::Wrapper)
519 Op = Op.getOperand(0);
520
521 if (Op.getOpcode() == ISD::TargetGlobalAddress) {
522 Offset = Op;
523 Addr = SDValue(
524 CurDAG->getMachineNode(ConstOpc, DL, AddrType,
525 CurDAG->getTargetConstant(0, DL, AddrType)),
526 0);
527 return true;
528 }
529 }
530
531 // Fold anything inside an add into the offset.
532 if (N.getOpcode() == ISD::ADD &&
533 SelectAddrAddOperands(AddrType, N, Offset, Addr))
534 return true;
535
536 // Likewise, treat an 'or' node as an 'add' if the or'ed bits are known to be
537 // zero and fold them into the offset too.
538 if (N.getOpcode() == ISD::OR) {
539 bool OrIsAdd;
540 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
541 OrIsAdd =
542 CurDAG->MaskedValueIsZero(N->getOperand(0), CN->getAPIntValue());
543 } else {
544 KnownBits Known0 = CurDAG->computeKnownBits(N->getOperand(0), 0);
545 KnownBits Known1 = CurDAG->computeKnownBits(N->getOperand(1), 0);
546 OrIsAdd = (~Known0.Zero & ~Known1.Zero) == 0;
547 }
548
549 if (OrIsAdd && SelectAddrAddOperands(AddrType, N, Offset, Addr))
550 return true;
551 }
552
553 // Fold constant addresses into the offset.
554 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N)) {
555 Offset = CurDAG->getTargetConstant(CN->getZExtValue(), DL, AddrType);
556 Addr = SDValue(
557 CurDAG->getMachineNode(ConstOpc, DL, AddrType,
558 CurDAG->getTargetConstant(0, DL, AddrType)),
559 0);
560 return true;
561 }
562
563 // Else it's a plain old load/store with no offset.
564 Offset = CurDAG->getTargetConstant(0, DL, AddrType);
565 Addr = N;
566 return true;
567}
568
569bool WebAssemblyDAGToDAGISel::SelectAddrOperands32(SDValue Op, SDValue &Offset,
570 SDValue &Addr) {
571 return SelectAddrOperands(MVT::i32, WebAssembly::CONST_I32, Op, Offset, Addr);
572}
573
574bool WebAssemblyDAGToDAGISel::SelectAddrOperands64(SDValue Op, SDValue &Offset,
575 SDValue &Addr) {
576 return SelectAddrOperands(MVT::i64, WebAssembly::CONST_I64, Op, Offset, Addr);
577}
578
580 while (N) {
581 if (auto *MemNode = dyn_cast<MemSDNode>(N))
582 return MemNode;
583 switch (N->getOpcode()) {
584 case ISD::ZERO_EXTEND:
585 case ISD::SIGN_EXTEND:
586 case ISD::ANY_EXTEND:
588 case ISD::AssertZext:
589 case ISD::AssertSext:
590 case ISD::TRUNCATE:
591 case ISD::BITCAST:
592 case ISD::AND:
593 N = N->getOperand(0).getNode();
594 break;
595 default:
596 return nullptr;
597 }
598 }
599 return nullptr;
600}
601
602bool WebAssemblyDAGToDAGISel::SelectAtomicAddrOperands(SDNode *Op, SDValue N,
604 SDValue &Addr,
605 SDValue &Order,
606 bool Is64) {
607 auto *MemNode = findMemSDNode(Op);
608 if (!MemNode)
609 return false;
610
611 bool Match = Is64 ? SelectAddrOperands64(N, Offset, Addr)
612 : SelectAddrOperands32(N, Offset, Addr);
613 if (!Match)
614 return false;
615
616 auto Ordering = MemNode->getMergedOrdering();
617 unsigned OrderVal = wasm::WASM_MEM_ORDER_SEQ_CST;
618 if (Subtarget->hasRelaxedAtomics())
619 OrderVal = getWebAssemblyMemoryOrder(Ordering);
620 Order = CurDAG->getTargetConstant(OrderVal, SDLoc(Op), MVT::i32);
621 return true;
622}
623
624bool WebAssemblyDAGToDAGISel::SelectAtomicAddrOperands32(SDNode *Op, SDValue N,
626 SDValue &Addr,
627 SDValue &Order) {
628 return SelectAtomicAddrOperands(Op, N, Offset, Addr, Order, /*Is64=*/false);
629}
630
631bool WebAssemblyDAGToDAGISel::SelectAtomicAddrOperands64(SDNode *Op, SDValue N,
633 SDValue &Addr,
634 SDValue &Order) {
635 return SelectAtomicAddrOperands(Op, N, Offset, Addr, Order, /*Is64=*/true);
636}
637
638/// This pass converts a legalized DAG into a WebAssembly-specific DAG, ready
639/// for instruction scheduling.
641 CodeGenOptLevel OptLevel) {
642 return new WebAssemblyDAGToDAGISelLegacy(TM, OptLevel);
643}
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:119
#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:501
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:857
@ 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:997
@ SIGN_EXTEND
Conversion operators.
Definition ISDOpcodes.h:848
@ 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:854
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
Definition ISDOpcodes.h:892
@ 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:860
@ 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
MachineSDNode * getTLSBase(SelectionDAG &DAG, const SDLoc &DL, const WebAssemblySubtarget *Subtarget, const SDValue Chain=SDValue())
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.
@ Offset
Definition DWP.cpp:558
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:209
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