LCOV - code coverage report
Current view: top level - lib/Target/WebAssembly - WebAssemblyTargetMachine.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 125 125 100.0 %
Date: 2018-10-20 13:21:21 Functions: 14 14 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- WebAssemblyTargetMachine.cpp - Define TargetMachine 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             : /// This file defines the WebAssembly-specific subclass of TargetMachine.
      12             : ///
      13             : //===----------------------------------------------------------------------===//
      14             : 
      15             : #include "WebAssemblyTargetMachine.h"
      16             : #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
      17             : #include "WebAssembly.h"
      18             : #include "WebAssemblyTargetObjectFile.h"
      19             : #include "WebAssemblyTargetTransformInfo.h"
      20             : #include "llvm/CodeGen/MachineFunctionPass.h"
      21             : #include "llvm/CodeGen/Passes.h"
      22             : #include "llvm/CodeGen/RegAllocRegistry.h"
      23             : #include "llvm/CodeGen/TargetPassConfig.h"
      24             : #include "llvm/IR/Function.h"
      25             : #include "llvm/Support/TargetRegistry.h"
      26             : #include "llvm/Target/TargetOptions.h"
      27             : #include "llvm/Transforms/Scalar.h"
      28             : #include "llvm/Transforms/Utils.h"
      29             : using namespace llvm;
      30             : 
      31             : #define DEBUG_TYPE "wasm"
      32             : 
      33             : // Emscripten's asm.js-style exception handling
      34             : static cl::opt<bool> EnableEmException(
      35             :     "enable-emscripten-cxx-exceptions",
      36             :     cl::desc("WebAssembly Emscripten-style exception handling"),
      37             :     cl::init(false));
      38             : 
      39             : // Emscripten's asm.js-style setjmp/longjmp handling
      40             : static cl::opt<bool> EnableEmSjLj(
      41             :     "enable-emscripten-sjlj",
      42             :     cl::desc("WebAssembly Emscripten-style setjmp/longjmp handling"),
      43             :     cl::init(false));
      44             : 
      45      113922 : extern "C" void LLVMInitializeWebAssemblyTarget() {
      46             :   // Register the target.
      47             :   RegisterTargetMachine<WebAssemblyTargetMachine> X(
      48      113922 :       getTheWebAssemblyTarget32());
      49             :   RegisterTargetMachine<WebAssemblyTargetMachine> Y(
      50      113922 :       getTheWebAssemblyTarget64());
      51             : 
      52             :   // Register backend passes
      53      113922 :   auto &PR = *PassRegistry::getPassRegistry();
      54      113922 :   initializeWebAssemblyAddMissingPrototypesPass(PR);
      55      113922 :   initializeWebAssemblyLowerEmscriptenEHSjLjPass(PR);
      56      113922 :   initializeLowerGlobalDtorsPass(PR);
      57      113922 :   initializeFixFunctionBitcastsPass(PR);
      58      113922 :   initializeOptimizeReturnedPass(PR);
      59      113922 :   initializeWebAssemblyArgumentMovePass(PR);
      60      113922 :   initializeWebAssemblySetP2AlignOperandsPass(PR);
      61      113922 :   initializeWebAssemblyEHRestoreStackPointerPass(PR);
      62      113922 :   initializeWebAssemblyReplacePhysRegsPass(PR);
      63      113922 :   initializeWebAssemblyPrepareForLiveIntervalsPass(PR);
      64      113922 :   initializeWebAssemblyOptimizeLiveIntervalsPass(PR);
      65      113922 :   initializeWebAssemblyStoreResultsPass(PR);
      66      113922 :   initializeWebAssemblyRegStackifyPass(PR);
      67      113922 :   initializeWebAssemblyRegColoringPass(PR);
      68      113922 :   initializeWebAssemblyExplicitLocalsPass(PR);
      69      113922 :   initializeWebAssemblyFixIrreducibleControlFlowPass(PR);
      70      113922 :   initializeWebAssemblyLateEHPreparePass(PR);
      71      113922 :   initializeWebAssemblyExceptionInfoPass(PR);
      72      113922 :   initializeWebAssemblyCFGSortPass(PR);
      73      113922 :   initializeWebAssemblyCFGStackifyPass(PR);
      74      113922 :   initializeWebAssemblyLowerBrUnlessPass(PR);
      75      113922 :   initializeWebAssemblyRegNumberingPass(PR);
      76      113922 :   initializeWebAssemblyPeepholePass(PR);
      77      113922 :   initializeWebAssemblyCallIndirectFixupPass(PR);
      78      113922 : }
      79             : 
      80             : //===----------------------------------------------------------------------===//
      81             : // WebAssembly Lowering public interface.
      82             : //===----------------------------------------------------------------------===//
      83             : 
      84             : static Reloc::Model getEffectiveRelocModel(Optional<Reloc::Model> RM) {
      85         352 :   if (!RM.hasValue())
      86             :     return Reloc::PIC_;
      87             :   return *RM;
      88             : }
      89             : 
      90             : /// Create an WebAssembly architecture model.
      91             : ///
      92         352 : WebAssemblyTargetMachine::WebAssemblyTargetMachine(
      93             :     const Target &T, const Triple &TT, StringRef CPU, StringRef FS,
      94             :     const TargetOptions &Options, Optional<Reloc::Model> RM,
      95         352 :     Optional<CodeModel::Model> CM, CodeGenOpt::Level OL, bool JIT)
      96             :     : LLVMTargetMachine(T,
      97         352 :                         TT.isArch64Bit() ? "e-m:e-p:64:64-i64:64-n32:64-S128"
      98             :                                          : "e-m:e-p:32:32-i64:64-n32:64-S128",
      99             :                         TT, CPU, FS, Options, getEffectiveRelocModel(RM),
     100         352 :                         CM ? *CM : CodeModel::Large, OL),
     101        1042 :       TLOF(new WebAssemblyTargetObjectFile()) {
     102             :   // WebAssembly type-checks instructions, but a noreturn function with a return
     103             :   // type that doesn't match the context will cause a check failure. So we lower
     104             :   // LLVM 'unreachable' to ISD::TRAP and then lower that to WebAssembly's
     105             :   // 'unreachable' instructions which is meant for that case.
     106         352 :   this->Options.TrapUnreachable = true;
     107             : 
     108             :   // WebAssembly treats each function as an independent unit. Force
     109             :   // -ffunction-sections, effectively, so that we can emit them independently.
     110         352 :   this->Options.FunctionSections = true;
     111         352 :   this->Options.DataSections = true;
     112         352 :   this->Options.UniqueSectionNames = true;
     113             : 
     114         352 :   initAsmInfo();
     115             : 
     116             :   // Note that we don't use setRequiresStructuredCFG(true). It disables
     117             :   // optimizations than we're ok with, and want, such as critical edge
     118             :   // splitting and tail merging.
     119         352 : }
     120             : 
     121         686 : WebAssemblyTargetMachine::~WebAssemblyTargetMachine() {}
     122             : 
     123             : const WebAssemblySubtarget *
     124       57729 : WebAssemblyTargetMachine::getSubtargetImpl(const Function &F) const {
     125       57729 :   Attribute CPUAttr = F.getFnAttribute("target-cpu");
     126       57729 :   Attribute FSAttr = F.getFnAttribute("target-features");
     127             : 
     128       57729 :   std::string CPU = !CPUAttr.hasAttribute(Attribute::None)
     129         339 :                         ? CPUAttr.getValueAsString().str()
     130       58068 :                         : TargetCPU;
     131       57729 :   std::string FS = !FSAttr.hasAttribute(Attribute::None)
     132       33051 :                        ? FSAttr.getValueAsString().str()
     133       90780 :                        : TargetFS;
     134             : 
     135       80190 :   auto &I = SubtargetMap[CPU + FS];
     136       57729 :   if (!I) {
     137             :     // This needs to be done before we create a new subtarget since any
     138             :     // creation will depend on the TM and the code generation flags on the
     139             :     // function that reside in TargetOptions.
     140         293 :     resetTargetOptions(F);
     141         586 :     I = llvm::make_unique<WebAssemblySubtarget>(TargetTriple, CPU, FS, *this);
     142             :   }
     143       57729 :   return I.get();
     144             : }
     145             : 
     146             : namespace {
     147             : class StripThreadLocal final : public ModulePass {
     148             :   // The default thread model for wasm is single, where thread-local variables
     149             :   // are identical to regular globals and should be treated the same. So this
     150             :   // pass just converts all GlobalVariables to NotThreadLocal
     151             :   static char ID;
     152             : 
     153             : public:
     154          35 :   StripThreadLocal() : ModulePass(ID) {}
     155          35 :   bool runOnModule(Module &M) override {
     156          38 :     for (auto &GV : M.globals())
     157             :       GV.setThreadLocalMode(GlobalValue::ThreadLocalMode::NotThreadLocal);
     158          35 :     return true;
     159             :   }
     160             : };
     161             : char StripThreadLocal::ID = 0;
     162             : 
     163             : /// WebAssembly Code Generator Pass Configuration Options.
     164             : class WebAssemblyPassConfig final : public TargetPassConfig {
     165             : public:
     166             :   WebAssemblyPassConfig(WebAssemblyTargetMachine &TM, PassManagerBase &PM)
     167         323 :       : TargetPassConfig(TM, PM) {}
     168             : 
     169             :   WebAssemblyTargetMachine &getWebAssemblyTargetMachine() const {
     170         305 :     return getTM<WebAssemblyTargetMachine>();
     171             :   }
     172             : 
     173             :   FunctionPass *createTargetRegisterAllocator(bool) override;
     174             : 
     175             :   void addIRPasses() override;
     176             :   bool addInstSelector() override;
     177             :   void addPostRegAlloc() override;
     178         305 :   bool addGCPasses() override { return false; }
     179             :   void addPreEmitPass() override;
     180             : };
     181             : } // end anonymous namespace
     182             : 
     183             : TargetTransformInfo
     184       24631 : WebAssemblyTargetMachine::getTargetTransformInfo(const Function &F) {
     185       24631 :   return TargetTransformInfo(WebAssemblyTTIImpl(this, F));
     186             : }
     187             : 
     188             : TargetPassConfig *
     189         323 : WebAssemblyTargetMachine::createPassConfig(PassManagerBase &PM) {
     190         323 :   return new WebAssemblyPassConfig(*this, PM);
     191             : }
     192             : 
     193         305 : FunctionPass *WebAssemblyPassConfig::createTargetRegisterAllocator(bool) {
     194         305 :   return nullptr; // No reg alloc
     195             : }
     196             : 
     197             : //===----------------------------------------------------------------------===//
     198             : // The following functions are called from lib/CodeGen/Passes.cpp to modify
     199             : // the CodeGen pass sequence.
     200             : //===----------------------------------------------------------------------===//
     201             : 
     202         305 : void WebAssemblyPassConfig::addIRPasses() {
     203         305 :   if (TM->Options.ThreadModel == ThreadModel::Single) {
     204             :     // In "single" mode, atomics get lowered to non-atomics.
     205          35 :     addPass(createLowerAtomicPass());
     206          35 :     addPass(new StripThreadLocal());
     207             :   } else {
     208             :     // Expand some atomic operations. WebAssemblyTargetLowering has hooks which
     209             :     // control specifically what gets lowered.
     210         270 :     addPass(createAtomicExpandPass());
     211             :   }
     212             : 
     213             :   // Add signatures to prototype-less function declarations
     214         305 :   addPass(createWebAssemblyAddMissingPrototypes());
     215             : 
     216             :   // Lower .llvm.global_dtors into .llvm_global_ctors with __cxa_atexit calls.
     217         305 :   addPass(createWebAssemblyLowerGlobalDtors());
     218             : 
     219             :   // Fix function bitcasts, as WebAssembly requires caller and callee signatures
     220             :   // to match.
     221         305 :   addPass(createWebAssemblyFixFunctionBitcasts());
     222             : 
     223             :   // Optimize "returned" function attributes.
     224         305 :   if (getOptLevel() != CodeGenOpt::None)
     225         298 :     addPass(createWebAssemblyOptimizeReturned());
     226             : 
     227             :   // If exception handling is not enabled and setjmp/longjmp handling is
     228             :   // enabled, we lower invokes into calls and delete unreachable landingpad
     229             :   // blocks. Lowering invokes when there is no EH support is done in
     230             :   // TargetPassConfig::addPassesToHandleExceptions, but this runs after this
     231             :   // function and SjLj handling expects all invokes to be lowered before.
     232         305 :   if (!EnableEmException &&
     233         303 :       TM->Options.ExceptionModel == ExceptionHandling::None) {
     234         300 :     addPass(createLowerInvokePass());
     235             :     // The lower invoke pass may create unreachable code. Remove it in order not
     236             :     // to process dead blocks in setjmp/longjmp handling.
     237         300 :     addPass(createUnreachableBlockEliminationPass());
     238             :   }
     239             : 
     240             :   // Handle exceptions and setjmp/longjmp if enabled.
     241         305 :   if (EnableEmException || EnableEmSjLj)
     242           3 :     addPass(createWebAssemblyLowerEmscriptenEHSjLj(EnableEmException,
     243             :                                                    EnableEmSjLj));
     244             : 
     245         305 :   TargetPassConfig::addIRPasses();
     246         305 : }
     247             : 
     248         305 : bool WebAssemblyPassConfig::addInstSelector() {
     249         305 :   (void)TargetPassConfig::addInstSelector();
     250         305 :   addPass(
     251         305 :       createWebAssemblyISelDag(getWebAssemblyTargetMachine(), getOptLevel()));
     252             :   // Run the argument-move pass immediately after the ScheduleDAG scheduler
     253             :   // so that we can fix up the ARGUMENT instructions before anything else
     254             :   // sees them in the wrong place.
     255         305 :   addPass(createWebAssemblyArgumentMove());
     256             :   // Set the p2align operands. This information is present during ISel, however
     257             :   // it's inconvenient to collect. Collect it now, and update the immediate
     258             :   // operands.
     259         305 :   addPass(createWebAssemblySetP2AlignOperands());
     260         305 :   return false;
     261             : }
     262             : 
     263         305 : void WebAssemblyPassConfig::addPostRegAlloc() {
     264             :   // TODO: The following CodeGen passes don't currently support code containing
     265             :   // virtual registers. Consider removing their restrictions and re-enabling
     266             :   // them.
     267             : 
     268             :   // These functions all require the NoVRegs property.
     269         305 :   disablePass(&MachineCopyPropagationID);
     270         305 :   disablePass(&PostRAMachineSinkingID);
     271         305 :   disablePass(&PostRASchedulerID);
     272         305 :   disablePass(&FuncletLayoutID);
     273         305 :   disablePass(&StackMapLivenessID);
     274         305 :   disablePass(&LiveDebugValuesID);
     275         305 :   disablePass(&PatchableFunctionID);
     276         305 :   disablePass(&ShrinkWrapID);
     277             : 
     278             :   TargetPassConfig::addPostRegAlloc();
     279         305 : }
     280             : 
     281         305 : void WebAssemblyPassConfig::addPreEmitPass() {
     282         305 :   TargetPassConfig::addPreEmitPass();
     283             : 
     284             :   // Restore __stack_pointer global after an exception is thrown.
     285         305 :   addPass(createWebAssemblyEHRestoreStackPointer());
     286             : 
     287             :   // Now that we have a prologue and epilogue and all frame indices are
     288             :   // rewritten, eliminate SP and FP. This allows them to be stackified,
     289             :   // colored, and numbered with the rest of the registers.
     290         305 :   addPass(createWebAssemblyReplacePhysRegs());
     291             : 
     292             :   // Rewrite pseudo call_indirect instructions as real instructions.
     293             :   // This needs to run before register stackification, because we change the
     294             :   // order of the arguments.
     295         305 :   addPass(createWebAssemblyCallIndirectFixup());
     296             : 
     297         305 :   if (getOptLevel() != CodeGenOpt::None) {
     298             :     // LiveIntervals isn't commonly run this late. Re-establish preconditions.
     299         298 :     addPass(createWebAssemblyPrepareForLiveIntervals());
     300             : 
     301             :     // Depend on LiveIntervals and perform some optimizations on it.
     302         298 :     addPass(createWebAssemblyOptimizeLiveIntervals());
     303             : 
     304             :     // Prepare store instructions for register stackifying.
     305         298 :     addPass(createWebAssemblyStoreResults());
     306             : 
     307             :     // Mark registers as representing wasm's value stack. This is a key
     308             :     // code-compression technique in WebAssembly. We run this pass (and
     309             :     // StoreResults above) very late, so that it sees as much code as possible,
     310             :     // including code emitted by PEI and expanded by late tail duplication.
     311         298 :     addPass(createWebAssemblyRegStackify());
     312             : 
     313             :     // Run the register coloring pass to reduce the total number of registers.
     314             :     // This runs after stackification so that it doesn't consider registers
     315             :     // that become stackified.
     316         298 :     addPass(createWebAssemblyRegColoring());
     317             :   }
     318             : 
     319             :   // Eliminate multiple-entry loops. Do this before inserting explicit get_local
     320             :   // and set_local operators because we create a new variable that we want
     321             :   // converted into a local.
     322         305 :   addPass(createWebAssemblyFixIrreducibleControlFlow());
     323             : 
     324             :   // Insert explicit get_local and set_local operators.
     325         305 :   addPass(createWebAssemblyExplicitLocals());
     326             : 
     327             :   // Do various transformations for exception handling
     328         305 :   addPass(createWebAssemblyLateEHPrepare());
     329             : 
     330             :   // Sort the blocks of the CFG into topological order, a prerequisite for
     331             :   // BLOCK and LOOP markers.
     332         305 :   addPass(createWebAssemblyCFGSort());
     333             : 
     334             :   // Insert BLOCK and LOOP markers.
     335         305 :   addPass(createWebAssemblyCFGStackify());
     336             : 
     337             :   // Lower br_unless into br_if.
     338         305 :   addPass(createWebAssemblyLowerBrUnless());
     339             : 
     340             :   // Perform the very last peephole optimizations on the code.
     341         305 :   if (getOptLevel() != CodeGenOpt::None)
     342         298 :     addPass(createWebAssemblyPeephole());
     343             : 
     344             :   // Create a mapping from LLVM CodeGen virtual registers to wasm registers.
     345         305 :   addPass(createWebAssemblyRegNumbering());
     346         305 : }

Generated by: LCOV version 1.13