24#include "llvm/IR/IntrinsicsWebAssembly.h" 
   32#define DEBUG_TYPE "wasm-isel" 
   33#define PASS_NAME "WebAssembly Instruction Selection" 
   46  WebAssemblyDAGToDAGISel() = 
delete;
 
   54                         "********** Function: " 
   62  void PreprocessISelDAG() 
override;
 
   66  bool SelectInlineAsmMemoryOperand(
const SDValue &
Op,
 
   68                                    std::vector<SDValue> &OutOps) 
override;
 
   74#include "WebAssemblyGenDAGISel.inc" 
   79  bool SelectAddrOperands(
MVT AddrType, 
unsigned ConstOpc, 
SDValue Op,
 
   91            ID, std::make_unique<WebAssemblyDAGToDAGISel>(TM, OptLevel)) {}
 
   95char WebAssemblyDAGToDAGISelLegacy::ID;
 
  100void WebAssemblyDAGToDAGISel::PreprocessISelDAG() {
 
 
  118                            ? MF.createExternalSymbolName(
"__cpp_exception")
 
  119                            : MF.createExternalSymbolName(
"__c_longjmp");
 
 
  126  auto toWasmValType = [](
MVT VT) {
 
  127    if (VT == MVT::i32) {
 
  130    if (VT == MVT::i64) {
 
  133    if (VT == MVT::f32) {
 
  136    if (VT == MVT::f64) {
 
  139    if (VT == MVT::externref) {
 
  142    if (VT == MVT::funcref) {
 
  145    if (VT == MVT::exnref) {
 
  148    LLVM_DEBUG(
errs() << 
"Unhandled type for llvm.wasm.ref.test.func: " << VT
 
  152  auto NParams = Params.
size();
 
  153  auto NReturns = Returns.
size();
 
  154  auto BitWidth = (NParams + NReturns + 2) * 64;
 
  161  Sig |= NReturns ^ 0x7ffffff;
 
  162  for (
auto &Return : Returns) {
 
  163    auto V = toWasmValType(Return);
 
  169  for (
auto &Param : Params) {
 
  170    auto V = toWasmValType(Param);
 
 
  177void WebAssemblyDAGToDAGISel::Select(
SDNode *
Node) {
 
  179  if (
Node->isMachineOpcode()) {
 
  185  MVT PtrVT = TLI->getPointerTy(CurDAG->getDataLayout());
 
  186  auto GlobalGetIns = PtrVT == MVT::i64 ? WebAssembly::GLOBAL_GET_I64
 
  187                                        : WebAssembly::GLOBAL_GET_I32;
 
  191  MachineFunction &MF = CurDAG->getMachineFunction();
 
  192  switch (
Node->getOpcode()) {
 
  193  case ISD::ATOMIC_FENCE: {
 
  194    if (!MF.
getSubtarget<WebAssemblySubtarget>().hasAtomics())
 
  197    uint64_t SyncScopeID = 
Node->getConstantOperandVal(2);
 
  198    MachineSDNode *Fence = 
nullptr;
 
  199    switch (SyncScopeID) {
 
  204      Fence = CurDAG->getMachineNode(WebAssembly::COMPILER_FENCE,
 
  213      Fence = CurDAG->getMachineNode(
 
  214          WebAssembly::ATOMIC_FENCE,
 
  217          CurDAG->getTargetConstant(0, 
DL, MVT::i32), 
 
  225    ReplaceNode(Node, Fence);
 
  226    CurDAG->RemoveDeadNode(Node);
 
  231    unsigned IntNo = 
Node->getConstantOperandVal(0);
 
  233    case Intrinsic::wasm_tls_size: {
 
  234      MachineSDNode *TLSSize = CurDAG->getMachineNode(
 
  235          GlobalGetIns, 
DL, PtrVT,
 
  236          CurDAG->getTargetExternalSymbol(
"__tls_size", PtrVT));
 
  237      ReplaceNode(Node, TLSSize);
 
  241    case Intrinsic::wasm_tls_align: {
 
  242      MachineSDNode *TLSAlign = CurDAG->getMachineNode(
 
  243          GlobalGetIns, 
DL, PtrVT,
 
  244          CurDAG->getTargetExternalSymbol(
"__tls_align", PtrVT));
 
  245      ReplaceNode(Node, TLSAlign);
 
  248    case Intrinsic::wasm_ref_test_func: {
 
  251      MachineFunction &MF = CurDAG->getMachineFunction();
 
  255      SDValue TableSym = CurDAG->getMCSymbol(Table, PtrVT);
 
  260        FuncPtr = 
SDValue(CurDAG->getMachineNode(WebAssembly::I32_WRAP_I64, 
DL,
 
  265          SDValue(CurDAG->getMachineNode(WebAssembly::TABLE_GET_FUNCREF, 
DL,
 
  266                                         MVT::funcref, TableSym, FuncPtr),
 
  275      bool IsParam = 
false;
 
  279      for (
unsigned I = 2, 
E = 
Node->getNumOperands(); 
I < 
E; ++
I) {
 
  280        MVT VT = 
Node->getOperand(
I).getValueType().getSimpleVT();
 
  281        if (VT == MVT::Untyped) {
 
  293      auto SigOp = CurDAG->getTargetConstant(
 
  295      MachineSDNode *RefTestNode = CurDAG->getMachineNode(
 
  296          WebAssembly::REF_TEST_FUNCREF, 
DL, MVT::i32, {SigOp, FuncRef});
 
  297      ReplaceNode(Node, RefTestNode);
 
  305    unsigned IntNo = 
Node->getConstantOperandVal(1);
 
  306    const auto &TLI = CurDAG->getTargetLoweringInfo();
 
  307    MVT PtrVT = TLI.getPointerTy(CurDAG->getDataLayout());
 
  309    case Intrinsic::wasm_tls_base: {
 
  310      MachineSDNode *TLSBase = CurDAG->getMachineNode(
 
  311          GlobalGetIns, 
DL, PtrVT, MVT::Other,
 
  312          CurDAG->getTargetExternalSymbol(
"__tls_base", PtrVT),
 
  313          Node->getOperand(0));
 
  314      ReplaceNode(Node, TLSBase);
 
  318    case Intrinsic::wasm_catch: {
 
  319      int Tag = 
Node->getConstantOperandVal(2);
 
  322                                 ? WebAssembly::CATCH_LEGACY
 
  323                                 : WebAssembly::CATCH;
 
  324      MachineSDNode *
Catch =
 
  325          CurDAG->getMachineNode(CatchOpcode, 
DL,
 
  334      ReplaceNode(Node, 
Catch);
 
  342    unsigned IntNo = 
Node->getConstantOperandVal(1);
 
  344    case Intrinsic::wasm_throw: {
 
  345      int Tag = 
Node->getConstantOperandVal(2);
 
  347      MachineSDNode *Throw =
 
  348          CurDAG->getMachineNode(WebAssembly::THROW, 
DL,
 
  355      ReplaceNode(Node, Throw);
 
  358    case Intrinsic::wasm_rethrow: {
 
  361      MachineSDNode *Rethrow = CurDAG->getMachineNode(
 
  362          WebAssembly::RETHROW, 
DL,
 
  365              CurDAG->getConstant(0, 
DL, MVT::i32), 
 
  368      ReplaceNode(Node, Rethrow);
 
  375  case WebAssemblyISD::CALL:
 
  376  case WebAssemblyISD::RET_CALL: {
 
  382    for (
size_t i = 1; i < 
Node->getNumOperands(); ++i) {
 
  390      if (i == 1 && 
Op->getOpcode() == WebAssemblyISD::Wrapper) {
 
  394                  GlobalOp->getGlobal()->stripPointerCastsAndAliases()))
 
  404    Ops.push_back(
Node->getOperand(0));
 
  405    MachineSDNode *CallParams =
 
  406        CurDAG->getMachineNode(WebAssembly::CALL_PARAMS, 
DL, MVT::Glue, 
Ops);
 
  408    unsigned Results = 
Node->getOpcode() == WebAssemblyISD::CALL
 
  409                           ? WebAssembly::CALL_RESULTS
 
  410                           : WebAssembly::RET_CALL_RESULTS;
 
  413    MachineSDNode *CallResults =
 
  414        CurDAG->getMachineNode(
Results, 
DL, 
Node->getVTList(), Link);
 
  415    ReplaceNode(Node, CallResults);
 
  427bool WebAssemblyDAGToDAGISel::SelectInlineAsmMemoryOperand(
 
  429    std::vector<SDValue> &OutOps) {
 
  430  switch (ConstraintID) {
 
  431  case InlineAsm::ConstraintCode::m:
 
  434    OutOps.push_back(
Op);
 
  443bool WebAssemblyDAGToDAGISel::SelectAddrAddOperands(MVT OffsetType, 
SDValue N,
 
  446  assert(
N.getNumOperands() == 2 && 
"Attempting to fold in a non-binary op");
 
  451  if (
N.getOpcode() == 
ISD::ADD && !
N.getNode()->getFlags().hasNoUnsignedWrap())
 
  454  for (
size_t i = 0; i < 2; ++i) {
 
  456    SDValue OtherOp = 
N.getOperand(i == 0 ? 1 : 0);
 
  461          CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(
N), OffsetType);
 
  467    if (!
TM.isPositionIndependent()) {
 
  468      if (
Op.getOpcode() == WebAssemblyISD::Wrapper)
 
  469        Op = 
Op.getOperand(0);
 
  481bool WebAssemblyDAGToDAGISel::SelectAddrOperands(MVT AddrType,
 
  488  if (!
TM.isPositionIndependent()) {
 
  490    if (
Op.getOpcode() == WebAssemblyISD::Wrapper)
 
  491      Op = 
Op.getOperand(0);
 
  496          CurDAG->getMachineNode(ConstOpc, 
DL, AddrType,
 
  497                                 CurDAG->getTargetConstant(0, 
DL, AddrType)),
 
  505      SelectAddrAddOperands(AddrType, 
N, 
Offset, Addr))
 
  514          CurDAG->MaskedValueIsZero(
N->getOperand(0), CN->getAPIntValue());
 
  516      KnownBits Known0 = CurDAG->computeKnownBits(
N->getOperand(0), 0);
 
  517      KnownBits Known1 = CurDAG->computeKnownBits(
N->getOperand(1), 0);
 
  518      OrIsAdd = (~Known0.Zero & ~Known1.Zero) == 0;
 
  521    if (OrIsAdd && SelectAddrAddOperands(AddrType, 
N, 
Offset, Addr))
 
  527    Offset = CurDAG->getTargetConstant(CN->getZExtValue(), 
DL, AddrType);
 
  529        CurDAG->getMachineNode(ConstOpc, 
DL, AddrType,
 
  530                               CurDAG->getTargetConstant(0, 
DL, AddrType)),
 
  536  Offset = CurDAG->getTargetConstant(0, 
DL, AddrType);
 
  543  return SelectAddrOperands(MVT::i32, WebAssembly::CONST_I32, 
Op, 
Offset, Addr);
 
  548  return SelectAddrOperands(MVT::i64, WebAssembly::CONST_I64, 
Op, 
Offset, Addr);
 
  555  return new WebAssemblyDAGToDAGISelLegacy(TM, OptLevel);
 
 
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
 
AMDGPU Register Bank Select
 
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
 
Function Alias Analysis Results
 
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
 
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
 
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
 
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.
 
unsigned getPointerSizeInBits(unsigned AS=0) const
The size in bits of the pointer representation in a given address space.
 
FunctionPass class - This class is used to implement most global optimizations.
 
static MVT getIntegerVT(unsigned BitWidth)
 
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
 
int getObjectIndexEnd() const
Return one past the maximum frame object index.
 
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.
 
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.
 
@ ADD
Simple integer binary arithmetic operators.
 
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
 
@ TargetGlobalAddress
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
 
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
 
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
 
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
 
@ System
Synchronized with respect to all concurrently executing threads.
 
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
 
This is an optimization pass for GlobalISel generic memory operations.
 
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
 
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
 
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.
 
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...
 
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
 
DWARFExpression::Operation Op
 
constexpr unsigned BitWidth
 
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.