Home | History | Annotate | Download | only in WebAssembly
      1 //- WebAssemblyISelDAGToDAG.cpp - A dag to dag inst selector for WebAssembly -//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 ///
     10 /// \file
     11 /// \brief This file defines an instruction selector for the WebAssembly target.
     12 ///
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "WebAssembly.h"
     16 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
     17 #include "WebAssemblyTargetMachine.h"
     18 #include "llvm/CodeGen/SelectionDAGISel.h"
     19 #include "llvm/IR/Function.h" // To access function attributes.
     20 #include "llvm/Support/Debug.h"
     21 #include "llvm/Support/MathExtras.h"
     22 #include "llvm/Support/raw_ostream.h"
     23 using namespace llvm;
     24 
     25 #define DEBUG_TYPE "wasm-isel"
     26 
     27 //===--------------------------------------------------------------------===//
     28 /// WebAssembly-specific code to select WebAssembly machine instructions for
     29 /// SelectionDAG operations.
     30 ///
     31 namespace {
     32 class WebAssemblyDAGToDAGISel final : public SelectionDAGISel {
     33   /// Keep a pointer to the WebAssemblySubtarget around so that we can make the
     34   /// right decision when generating code for different targets.
     35   const WebAssemblySubtarget *Subtarget;
     36 
     37   bool ForCodeSize;
     38 
     39 public:
     40   WebAssemblyDAGToDAGISel(WebAssemblyTargetMachine &tm,
     41                           CodeGenOpt::Level OptLevel)
     42       : SelectionDAGISel(tm, OptLevel), Subtarget(nullptr), ForCodeSize(false) {
     43   }
     44 
     45   const char *getPassName() const override {
     46     return "WebAssembly Instruction Selection";
     47   }
     48 
     49   bool runOnMachineFunction(MachineFunction &MF) override {
     50     ForCodeSize =
     51         MF.getFunction()->hasFnAttribute(Attribute::OptimizeForSize) ||
     52         MF.getFunction()->hasFnAttribute(Attribute::MinSize);
     53     Subtarget = &MF.getSubtarget<WebAssemblySubtarget>();
     54     return SelectionDAGISel::runOnMachineFunction(MF);
     55   }
     56 
     57   void Select(SDNode *Node) override;
     58 
     59   bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
     60                                     std::vector<SDValue> &OutOps) override;
     61 
     62 // Include the pieces autogenerated from the target description.
     63 #include "WebAssemblyGenDAGISel.inc"
     64 
     65 private:
     66   // add select functions here...
     67 };
     68 } // end anonymous namespace
     69 
     70 void WebAssemblyDAGToDAGISel::Select(SDNode *Node) {
     71   // Dump information about the Node being selected.
     72   DEBUG(errs() << "Selecting: ");
     73   DEBUG(Node->dump(CurDAG));
     74   DEBUG(errs() << "\n");
     75 
     76   // If we have a custom node, we already have selected!
     77   if (Node->isMachineOpcode()) {
     78     DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n");
     79     Node->setNodeId(-1);
     80     return;
     81   }
     82 
     83   // Few custom selection stuff.
     84   EVT VT = Node->getValueType(0);
     85 
     86   switch (Node->getOpcode()) {
     87   default:
     88     break;
     89     // If we need WebAssembly-specific selection, it would go here.
     90     (void)VT;
     91   }
     92 
     93   // Select the default instruction.
     94   SelectCode(Node);
     95 }
     96 
     97 bool WebAssemblyDAGToDAGISel::SelectInlineAsmMemoryOperand(
     98     const SDValue &Op, unsigned ConstraintID, std::vector<SDValue> &OutOps) {
     99   switch (ConstraintID) {
    100   case InlineAsm::Constraint_i:
    101   case InlineAsm::Constraint_m:
    102     // We just support simple memory operands that just have a single address
    103     // operand and need no special handling.
    104     OutOps.push_back(Op);
    105     return false;
    106   default:
    107     break;
    108   }
    109 
    110   return true;
    111 }
    112 
    113 /// This pass converts a legalized DAG into a WebAssembly-specific DAG, ready
    114 /// for instruction scheduling.
    115 FunctionPass *llvm::createWebAssemblyISelDag(WebAssemblyTargetMachine &TM,
    116                                              CodeGenOpt::Level OptLevel) {
    117   return new WebAssemblyDAGToDAGISel(TM, OptLevel);
    118 }
    119