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   SDNode *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 SDNode *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 nullptr;
     81   }
     82 
     83   // Few custom selection stuff.
     84   SDNode *ResNode = nullptr;
     85   EVT VT = Node->getValueType(0);
     86 
     87   switch (Node->getOpcode()) {
     88   default:
     89     break;
     90     // If we need WebAssembly-specific selection, it would go here.
     91     (void)VT;
     92   }
     93 
     94   // Select the default instruction.
     95   ResNode = SelectCode(Node);
     96 
     97   DEBUG(errs() << "=> ");
     98   if (ResNode == nullptr || ResNode == Node)
     99     DEBUG(Node->dump(CurDAG));
    100   else
    101     DEBUG(ResNode->dump(CurDAG));
    102   DEBUG(errs() << "\n");
    103 
    104   return ResNode;
    105 }
    106 
    107 bool WebAssemblyDAGToDAGISel::SelectInlineAsmMemoryOperand(
    108     const SDValue &Op, unsigned ConstraintID, std::vector<SDValue> &OutOps) {
    109   switch (ConstraintID) {
    110   case InlineAsm::Constraint_i:
    111   case InlineAsm::Constraint_m:
    112     // We just support simple memory operands that just have a single address
    113     // operand and need no special handling.
    114     OutOps.push_back(Op);
    115     return false;
    116   default:
    117     break;
    118   }
    119 
    120   return true;
    121 }
    122 
    123 /// This pass converts a legalized DAG into a WebAssembly-specific DAG, ready
    124 /// for instruction scheduling.
    125 FunctionPass *llvm::createWebAssemblyISelDag(WebAssemblyTargetMachine &TM,
    126                                              CodeGenOpt::Level OptLevel) {
    127   return new WebAssemblyDAGToDAGISel(TM, OptLevel);
    128 }
    129