brintos

brintos / llvm-project-archived public Read only

0
0
Text · 26.0 KiB · 621640c Raw
682 lines · cpp
1//===- WebAssemblyTargetMachine.cpp - Define TargetMachine 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-exception6//7//===----------------------------------------------------------------------===//8///9/// \file10/// This file defines the WebAssembly-specific subclass of TargetMachine.11///12//===----------------------------------------------------------------------===//13 14#include "WebAssemblyTargetMachine.h"15#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"16#include "TargetInfo/WebAssemblyTargetInfo.h"17#include "WebAssembly.h"18#include "WebAssemblyISelLowering.h"19#include "WebAssemblyMachineFunctionInfo.h"20#include "WebAssemblyTargetObjectFile.h"21#include "WebAssemblyTargetTransformInfo.h"22#include "WebAssemblyUtilities.h"23#include "llvm/CodeGen/MIRParser/MIParser.h"24#include "llvm/CodeGen/Passes.h"25#include "llvm/CodeGen/RegAllocRegistry.h"26#include "llvm/CodeGen/TargetPassConfig.h"27#include "llvm/IR/Function.h"28#include "llvm/InitializePasses.h"29#include "llvm/MC/TargetRegistry.h"30#include "llvm/Support/Compiler.h"31#include "llvm/Target/TargetOptions.h"32#include "llvm/Transforms/Scalar.h"33#include "llvm/Transforms/Scalar/LowerAtomicPass.h"34#include "llvm/Transforms/Utils.h"35#include <optional>36using namespace llvm;37 38#define DEBUG_TYPE "wasm"39 40// A command-line option to keep implicit locals41// for the purpose of testing with lit/llc ONLY.42// This produces output which is not valid WebAssembly, and is not supported43// by assemblers/disassemblers and other MC based tools.44static cl::opt<bool> WasmDisableExplicitLocals(45    "wasm-disable-explicit-locals", cl::Hidden,46    cl::desc("WebAssembly: output implicit locals in"47             " instruction output for test purposes only."),48    cl::init(false));49 50static cl::opt<bool> WasmDisableFixIrreducibleControlFlowPass(51    "wasm-disable-fix-irreducible-control-flow-pass", cl::Hidden,52    cl::desc("webassembly: disables the fix "53             " irreducible control flow optimization pass"),54    cl::init(false));55 56// Exception handling & setjmp-longjmp handling related options.57 58// Emscripten's asm.js-style exception handling59cl::opt<bool> WebAssembly::WasmEnableEmEH(60    "enable-emscripten-cxx-exceptions",61    cl::desc("WebAssembly Emscripten-style exception handling"),62    cl::init(false));63// Emscripten's asm.js-style setjmp/longjmp handling64cl::opt<bool> WebAssembly::WasmEnableEmSjLj(65    "enable-emscripten-sjlj",66    cl::desc("WebAssembly Emscripten-style setjmp/longjmp handling"),67    cl::init(false));68// Exception handling using wasm EH instructions69cl::opt<bool>70    WebAssembly::WasmEnableEH("wasm-enable-eh",71                              cl::desc("WebAssembly exception handling"));72// setjmp/longjmp handling using wasm EH instrutions73cl::opt<bool> WebAssembly::WasmEnableSjLj(74    "wasm-enable-sjlj", cl::desc("WebAssembly setjmp/longjmp handling"));75// If true, use the legacy Wasm EH proposal:76// https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/legacy/Exceptions.md77// And if false, use the standardized Wasm EH proposal:78// https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/Exceptions.md79// Currently set to true by default because not all major web browsers turn on80// the new standard proposal by default, but will later change to false.81cl::opt<bool> WebAssembly::WasmUseLegacyEH(82    "wasm-use-legacy-eh", cl::desc("WebAssembly exception handling (legacy)"),83    cl::init(true));84 85extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void86LLVMInitializeWebAssemblyTarget() {87  // Register the target.88  RegisterTargetMachine<WebAssemblyTargetMachine> X(89      getTheWebAssemblyTarget32());90  RegisterTargetMachine<WebAssemblyTargetMachine> Y(91      getTheWebAssemblyTarget64());92 93  // Register backend passes94  auto &PR = *PassRegistry::getPassRegistry();95  initializeWebAssemblyAddMissingPrototypesPass(PR);96  initializeWebAssemblyLowerEmscriptenEHSjLjPass(PR);97  initializeLowerGlobalDtorsLegacyPassPass(PR);98  initializeFixFunctionBitcastsPass(PR);99  initializeOptimizeReturnedPass(PR);100  initializeWebAssemblyRefTypeMem2LocalPass(PR);101  initializeWebAssemblyArgumentMovePass(PR);102  initializeWebAssemblyAsmPrinterPass(PR);103  initializeWebAssemblySetP2AlignOperandsPass(PR);104  initializeWebAssemblyReplacePhysRegsPass(PR);105  initializeWebAssemblyOptimizeLiveIntervalsPass(PR);106  initializeWebAssemblyMemIntrinsicResultsPass(PR);107  initializeWebAssemblyRegStackifyPass(PR);108  initializeWebAssemblyRegColoringPass(PR);109  initializeWebAssemblyNullifyDebugValueListsPass(PR);110  initializeWebAssemblyFixIrreducibleControlFlowPass(PR);111  initializeWebAssemblyLateEHPreparePass(PR);112  initializeWebAssemblyExceptionInfoPass(PR);113  initializeWebAssemblyCFGSortPass(PR);114  initializeWebAssemblyCFGStackifyPass(PR);115  initializeWebAssemblyExplicitLocalsPass(PR);116  initializeWebAssemblyLowerBrUnlessPass(PR);117  initializeWebAssemblyRegNumberingPass(PR);118  initializeWebAssemblyDebugFixupPass(PR);119  initializeWebAssemblyPeepholePass(PR);120  initializeWebAssemblyMCLowerPrePassPass(PR);121  initializeWebAssemblyLowerRefTypesIntPtrConvPass(PR);122  initializeWebAssemblyFixBrTableDefaultsPass(PR);123  initializeWebAssemblyDAGToDAGISelLegacyPass(PR);124}125 126//===----------------------------------------------------------------------===//127// WebAssembly Lowering public interface.128//===----------------------------------------------------------------------===//129 130static Reloc::Model getEffectiveRelocModel(std::optional<Reloc::Model> RM) {131  // Default to static relocation model.  This should always be more optimial132  // than PIC since the static linker can determine all global addresses and133  // assume direct function calls.134  return RM.value_or(Reloc::Static);135}136 137using WebAssembly::WasmEnableEH;138using WebAssembly::WasmEnableEmEH;139using WebAssembly::WasmEnableEmSjLj;140using WebAssembly::WasmEnableSjLj;141 142static void basicCheckForEHAndSjLj(TargetMachine *TM) {143 144  // You can't enable two modes of EH at the same time145  if (WasmEnableEmEH && WasmEnableEH)146    report_fatal_error(147        "-enable-emscripten-cxx-exceptions not allowed with -wasm-enable-eh");148  // You can't enable two modes of SjLj at the same time149  if (WasmEnableEmSjLj && WasmEnableSjLj)150    report_fatal_error(151        "-enable-emscripten-sjlj not allowed with -wasm-enable-sjlj");152  // You can't mix Emscripten EH with Wasm SjLj.153  if (WasmEnableEmEH && WasmEnableSjLj)154    report_fatal_error(155        "-enable-emscripten-cxx-exceptions not allowed with -wasm-enable-sjlj");156 157  if (TM->Options.ExceptionModel == ExceptionHandling::None) {158    // FIXME: These flags should be removed in favor of directly using the159    // generically configured ExceptionsType160    if (WebAssembly::WasmEnableEH || WebAssembly::WasmEnableSjLj)161      TM->Options.ExceptionModel = ExceptionHandling::Wasm;162  }163 164  // Basic Correctness checking related to -exception-model165  if (TM->Options.ExceptionModel != ExceptionHandling::None &&166      TM->Options.ExceptionModel != ExceptionHandling::Wasm)167    report_fatal_error("-exception-model should be either 'none' or 'wasm'");168  if (WasmEnableEmEH && TM->Options.ExceptionModel == ExceptionHandling::Wasm)169    report_fatal_error("-exception-model=wasm not allowed with "170                       "-enable-emscripten-cxx-exceptions");171  if (WasmEnableEH && TM->Options.ExceptionModel != ExceptionHandling::Wasm)172    report_fatal_error(173        "-wasm-enable-eh only allowed with -exception-model=wasm");174  if (WasmEnableSjLj && TM->Options.ExceptionModel != ExceptionHandling::Wasm)175    report_fatal_error(176        "-wasm-enable-sjlj only allowed with -exception-model=wasm");177  if ((!WasmEnableEH && !WasmEnableSjLj) &&178      TM->Options.ExceptionModel == ExceptionHandling::Wasm)179    report_fatal_error(180        "-exception-model=wasm only allowed with at least one of "181        "-wasm-enable-eh or -wasm-enable-sjlj");182 183  // Currently it is allowed to mix Wasm EH with Emscripten SjLj as an interim184  // measure, but some code will error out at compile time in this combination.185  // See WebAssemblyLowerEmscriptenEHSjLj pass for details.186}187 188/// Create an WebAssembly architecture model.189///190WebAssemblyTargetMachine::WebAssemblyTargetMachine(191    const Target &T, const Triple &TT, StringRef CPU, StringRef FS,192    const TargetOptions &Options, std::optional<Reloc::Model> RM,193    std::optional<CodeModel::Model> CM, CodeGenOptLevel OL, bool JIT)194    : CodeGenTargetMachineImpl(T, TT.computeDataLayout(), TT, CPU, FS, Options,195                               getEffectiveRelocModel(RM),196                               getEffectiveCodeModel(CM, CodeModel::Large), OL),197      TLOF(new WebAssemblyTargetObjectFile()),198      UsesMultivalueABI(Options.MCOptions.getABIName() == "experimental-mv") {199  // WebAssembly type-checks instructions, but a noreturn function with a return200  // type that doesn't match the context will cause a check failure. So we lower201  // LLVM 'unreachable' to ISD::TRAP and then lower that to WebAssembly's202  // 'unreachable' instructions which is meant for that case. Formerly, we also203  // needed to add checks to SP failure emission in the instruction selection204  // backends, but this has since been tied to TrapUnreachable and is no longer205  // necessary.206  this->Options.TrapUnreachable = true;207  this->Options.NoTrapAfterNoreturn = false;208 209  // WebAssembly treats each function as an independent unit. Force210  // -ffunction-sections, effectively, so that we can emit them independently.211  this->Options.FunctionSections = true;212  this->Options.DataSections = true;213  this->Options.UniqueSectionNames = true;214 215  initAsmInfo();216  basicCheckForEHAndSjLj(this);217  // Note that we don't use setRequiresStructuredCFG(true). It disables218  // optimizations than we're ok with, and want, such as critical edge219  // splitting and tail merging.220}221 222WebAssemblyTargetMachine::~WebAssemblyTargetMachine() = default; // anchor.223 224const WebAssemblySubtarget *WebAssemblyTargetMachine::getSubtargetImpl() const {225  return getSubtargetImpl(std::string(getTargetCPU()),226                          std::string(getTargetFeatureString()));227}228 229const WebAssemblySubtarget *230WebAssemblyTargetMachine::getSubtargetImpl(std::string CPU,231                                           std::string FS) const {232  auto &I = SubtargetMap[CPU + FS];233  if (!I) {234    I = std::make_unique<WebAssemblySubtarget>(TargetTriple, CPU, FS, *this);235  }236  return I.get();237}238 239const WebAssemblySubtarget *240WebAssemblyTargetMachine::getSubtargetImpl(const Function &F) const {241  Attribute CPUAttr = F.getFnAttribute("target-cpu");242  Attribute FSAttr = F.getFnAttribute("target-features");243 244  std::string CPU =245      CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;246  std::string FS =247      FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;248 249  // This needs to be done before we create a new subtarget since any250  // creation will depend on the TM and the code generation flags on the251  // function that reside in TargetOptions.252  resetTargetOptions(F);253 254  return getSubtargetImpl(CPU, FS);255}256 257namespace {258 259class CoalesceFeaturesAndStripAtomics final : public ModulePass {260  // Take the union of all features used in the module and use it for each261  // function individually, since having multiple feature sets in one module262  // currently does not make sense for WebAssembly. If atomics are not enabled,263  // also strip atomic operations and thread local storage.264  static char ID;265  WebAssemblyTargetMachine *WasmTM;266 267public:268  CoalesceFeaturesAndStripAtomics(WebAssemblyTargetMachine *WasmTM)269      : ModulePass(ID), WasmTM(WasmTM) {}270 271  bool runOnModule(Module &M) override {272    FeatureBitset Features = coalesceFeatures(M);273 274    std::string FeatureStr = getFeatureString(Features);275    WasmTM->setTargetFeatureString(FeatureStr);276    for (auto &F : M)277      replaceFeatures(F, FeatureStr);278 279    bool StrippedAtomics = false;280    bool StrippedTLS = false;281 282    if (!Features[WebAssembly::FeatureAtomics]) {283      StrippedAtomics = stripAtomics(M);284      StrippedTLS = stripThreadLocals(M);285    } else if (!Features[WebAssembly::FeatureBulkMemory]) {286      StrippedTLS |= stripThreadLocals(M);287    }288 289    if (StrippedAtomics && !StrippedTLS)290      stripThreadLocals(M);291    else if (StrippedTLS && !StrippedAtomics)292      stripAtomics(M);293 294    recordFeatures(M, Features, StrippedAtomics || StrippedTLS);295 296    // Conservatively assume we have made some change297    return true;298  }299 300private:301  FeatureBitset coalesceFeatures(const Module &M) {302    // Union the features of all defined functions. Start with an empty set, so303    // that if a feature is disabled in every function, we'll compute it as304    // disabled. If any function lacks a target-features attribute, it'll305    // default to the target CPU from the `TargetMachine`.306    FeatureBitset Features;307    bool AnyDefinedFuncs = false;308    for (auto &F : M) {309      if (F.isDeclaration())310        continue;311 312      Features |= WasmTM->getSubtargetImpl(F)->getFeatureBits();313      AnyDefinedFuncs = true;314    }315 316    // If we have no defined functions, use the target CPU from the317    // `TargetMachine`.318    if (!AnyDefinedFuncs) {319      Features =320          WasmTM321              ->getSubtargetImpl(std::string(WasmTM->getTargetCPU()),322                                 std::string(WasmTM->getTargetFeatureString()))323              ->getFeatureBits();324    }325 326    return Features;327  }328 329  static std::string getFeatureString(const FeatureBitset &Features) {330    std::string Ret;331    for (const SubtargetFeatureKV &KV : WebAssemblyFeatureKV) {332      if (Features[KV.Value])333        Ret += (StringRef("+") + KV.Key + ",").str();334      else335        Ret += (StringRef("-") + KV.Key + ",").str();336    }337    return Ret;338  }339 340  void replaceFeatures(Function &F, const std::string &Features) {341    F.removeFnAttr("target-features");342    F.removeFnAttr("target-cpu");343    F.addFnAttr("target-features", Features);344  }345 346  bool stripAtomics(Module &M) {347    // Detect whether any atomics will be lowered, since there is no way to tell348    // whether the LowerAtomic pass lowers e.g. stores.349    bool Stripped = false;350    for (auto &F : M) {351      for (auto &B : F) {352        for (auto &I : B) {353          if (I.isAtomic()) {354            Stripped = true;355            goto done;356          }357        }358      }359    }360 361  done:362    if (!Stripped)363      return false;364 365    LowerAtomicPass Lowerer;366    FunctionAnalysisManager FAM;367    for (auto &F : M)368      Lowerer.run(F, FAM);369 370    return true;371  }372 373  bool stripThreadLocals(Module &M) {374    bool Stripped = false;375    for (auto &GV : M.globals()) {376      if (GV.isThreadLocal()) {377        // replace `@llvm.threadlocal.address.pX(GV)` with `GV`.378        for (Use &U : make_early_inc_range(GV.uses())) {379          if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(U.getUser())) {380            if (II->getIntrinsicID() == Intrinsic::threadlocal_address &&381                II->getArgOperand(0) == &GV) {382              II->replaceAllUsesWith(&GV);383              II->eraseFromParent();384            }385          }386        }387 388        Stripped = true;389        GV.setThreadLocal(false);390      }391    }392    return Stripped;393  }394 395  void recordFeatures(Module &M, const FeatureBitset &Features, bool Stripped) {396    for (const SubtargetFeatureKV &KV : WebAssemblyFeatureKV) {397      if (Features[KV.Value]) {398        // Mark features as used399        std::string MDKey = (StringRef("wasm-feature-") + KV.Key).str();400        M.addModuleFlag(Module::ModFlagBehavior::Error, MDKey,401                        wasm::WASM_FEATURE_PREFIX_USED);402      }403    }404    // Code compiled without atomics or bulk-memory may have had its atomics or405    // thread-local data lowered to nonatomic operations or non-thread-local406    // data. In that case, we mark the pseudo-feature "shared-mem" as disallowed407    // to tell the linker that it would be unsafe to allow this code ot be used408    // in a module with shared memory.409    if (Stripped) {410      M.addModuleFlag(Module::ModFlagBehavior::Error, "wasm-feature-shared-mem",411                      wasm::WASM_FEATURE_PREFIX_DISALLOWED);412    }413  }414};415char CoalesceFeaturesAndStripAtomics::ID = 0;416 417/// WebAssembly Code Generator Pass Configuration Options.418class WebAssemblyPassConfig final : public TargetPassConfig {419public:420  WebAssemblyPassConfig(WebAssemblyTargetMachine &TM, PassManagerBase &PM)421      : TargetPassConfig(TM, PM) {}422 423  WebAssemblyTargetMachine &getWebAssemblyTargetMachine() const {424    return getTM<WebAssemblyTargetMachine>();425  }426 427  FunctionPass *createTargetRegisterAllocator(bool) override;428 429  void addIRPasses() override;430  void addISelPrepare() override;431  bool addInstSelector() override;432  void addOptimizedRegAlloc() override;433  void addPostRegAlloc() override;434  bool addGCPasses() override { return false; }435  void addPreEmitPass() override;436  bool addPreISel() override;437 438  // No reg alloc439  bool addRegAssignAndRewriteFast() override { return false; }440 441  // No reg alloc442  bool addRegAssignAndRewriteOptimized() override { return false; }443};444} // end anonymous namespace445 446MachineFunctionInfo *WebAssemblyTargetMachine::createMachineFunctionInfo(447    BumpPtrAllocator &Allocator, const Function &F,448    const TargetSubtargetInfo *STI) const {449  return WebAssemblyFunctionInfo::create<WebAssemblyFunctionInfo>(Allocator, F,450                                                                  STI);451}452 453TargetTransformInfo454WebAssemblyTargetMachine::getTargetTransformInfo(const Function &F) const {455  return TargetTransformInfo(std::make_unique<WebAssemblyTTIImpl>(this, F));456}457 458TargetPassConfig *459WebAssemblyTargetMachine::createPassConfig(PassManagerBase &PM) {460  return new WebAssemblyPassConfig(*this, PM);461}462 463FunctionPass *WebAssemblyPassConfig::createTargetRegisterAllocator(bool) {464  return nullptr; // No reg alloc465}466 467//===----------------------------------------------------------------------===//468// The following functions are called from lib/CodeGen/Passes.cpp to modify469// the CodeGen pass sequence.470//===----------------------------------------------------------------------===//471 472void WebAssemblyPassConfig::addIRPasses() {473  // Add signatures to prototype-less function declarations474  addPass(createWebAssemblyAddMissingPrototypes());475 476  // Lower .llvm.global_dtors into .llvm.global_ctors with __cxa_atexit calls.477  addPass(createLowerGlobalDtorsLegacyPass());478 479  // Fix function bitcasts, as WebAssembly requires caller and callee signatures480  // to match.481  addPass(createWebAssemblyFixFunctionBitcasts());482 483  // Optimize "returned" function attributes.484  if (getOptLevel() != CodeGenOptLevel::None)485    addPass(createWebAssemblyOptimizeReturned());486 487  // If exception handling is not enabled and setjmp/longjmp handling is488  // enabled, we lower invokes into calls and delete unreachable landingpad489  // blocks. Lowering invokes when there is no EH support is done in490  // TargetPassConfig::addPassesToHandleExceptions, but that runs after these IR491  // passes and Emscripten SjLj handling expects all invokes to be lowered492  // before.493  if (!WasmEnableEmEH && !WasmEnableEH) {494    addPass(createLowerInvokePass());495    // The lower invoke pass may create unreachable code. Remove it in order not496    // to process dead blocks in setjmp/longjmp handling.497    addPass(createUnreachableBlockEliminationPass());498  }499 500  // Handle exceptions and setjmp/longjmp if enabled. Unlike Wasm EH preparation501  // done in WasmEHPrepare pass, Wasm SjLj preparation shares libraries and502  // transformation algorithms with Emscripten SjLj, so we run503  // LowerEmscriptenEHSjLj pass also when Wasm SjLj is enabled.504  if (WasmEnableEmEH || WasmEnableEmSjLj || WasmEnableSjLj)505    addPass(createWebAssemblyLowerEmscriptenEHSjLj());506 507  // Expand indirectbr instructions to switches.508  addPass(createIndirectBrExpandPass());509 510  TargetPassConfig::addIRPasses();511}512 513void WebAssemblyPassConfig::addISelPrepare() {514  // We need to move reference type allocas to WASM_ADDRESS_SPACE_VAR so that515  // loads and stores are promoted to local.gets/local.sets.516  addPass(createWebAssemblyRefTypeMem2Local());517  // Lower atomics and TLS if necessary518  addPass(new CoalesceFeaturesAndStripAtomics(&getWebAssemblyTargetMachine()));519 520  // This is a no-op if atomics are not used in the module521  addPass(createAtomicExpandLegacyPass());522 523  TargetPassConfig::addISelPrepare();524}525 526bool WebAssemblyPassConfig::addInstSelector() {527  (void)TargetPassConfig::addInstSelector();528  addPass(529      createWebAssemblyISelDag(getWebAssemblyTargetMachine(), getOptLevel()));530  // Run the argument-move pass immediately after the ScheduleDAG scheduler531  // so that we can fix up the ARGUMENT instructions before anything else532  // sees them in the wrong place.533  addPass(createWebAssemblyArgumentMove());534  // Set the p2align operands. This information is present during ISel, however535  // it's inconvenient to collect. Collect it now, and update the immediate536  // operands.537  addPass(createWebAssemblySetP2AlignOperands());538 539  // Eliminate range checks and add default targets to br_table instructions.540  addPass(createWebAssemblyFixBrTableDefaults());541 542  // unreachable is terminator, non-terminator instruction after it is not543  // allowed.544  addPass(createWebAssemblyCleanCodeAfterTrap());545 546  return false;547}548 549void WebAssemblyPassConfig::addOptimizedRegAlloc() {550  // Currently RegisterCoalesce degrades wasm debug info quality by a551  // significant margin. As a quick fix, disable this for -O1, which is often552  // used for debugging large applications. Disabling this increases code size553  // of Emscripten core benchmarks by ~5%, which is acceptable for -O1, which is554  // usually not used for production builds.555  // TODO Investigate why RegisterCoalesce degrades debug info quality and fix556  // it properly557  if (getOptLevel() == CodeGenOptLevel::Less)558    disablePass(&RegisterCoalescerID);559  TargetPassConfig::addOptimizedRegAlloc();560}561 562void WebAssemblyPassConfig::addPostRegAlloc() {563  // TODO: The following CodeGen passes don't currently support code containing564  // virtual registers. Consider removing their restrictions and re-enabling565  // them.566 567  // These functions all require the NoVRegs property.568  disablePass(&MachineLateInstrsCleanupID);569  disablePass(&MachineCopyPropagationID);570  disablePass(&PostRAMachineSinkingID);571  disablePass(&PostRASchedulerID);572  disablePass(&FuncletLayoutID);573  disablePass(&StackMapLivenessID);574  disablePass(&PatchableFunctionID);575  disablePass(&ShrinkWrapID);576  disablePass(&RemoveLoadsIntoFakeUsesID);577 578  // This pass hurts code size for wasm because it can generate irreducible579  // control flow.580  disablePass(&MachineBlockPlacementID);581 582  TargetPassConfig::addPostRegAlloc();583}584 585void WebAssemblyPassConfig::addPreEmitPass() {586  TargetPassConfig::addPreEmitPass();587 588  // Nullify DBG_VALUE_LISTs that we cannot handle.589  addPass(createWebAssemblyNullifyDebugValueLists());590 591  // Eliminate multiple-entry loops.592  if (!WasmDisableFixIrreducibleControlFlowPass)593    addPass(createWebAssemblyFixIrreducibleControlFlow());594 595  // Do various transformations for exception handling.596  // Every CFG-changing optimizations should come before this.597  if (TM->Options.ExceptionModel == ExceptionHandling::Wasm)598    addPass(createWebAssemblyLateEHPrepare());599 600  // Now that we have a prologue and epilogue and all frame indices are601  // rewritten, eliminate SP and FP. This allows them to be stackified,602  // colored, and numbered with the rest of the registers.603  addPass(createWebAssemblyReplacePhysRegs());604 605  // Preparations and optimizations related to register stackification.606  if (getOptLevel() != CodeGenOptLevel::None) {607    // Depend on LiveIntervals and perform some optimizations on it.608    addPass(createWebAssemblyOptimizeLiveIntervals());609 610    // Prepare memory intrinsic calls for register stackifying.611    addPass(createWebAssemblyMemIntrinsicResults());612  }613 614  // Mark registers as representing wasm's value stack. This is a key615  // code-compression technique in WebAssembly. We run this pass (and616  // MemIntrinsicResults above) very late, so that it sees as much code as617  // possible, including code emitted by PEI and expanded by late tail618  // duplication.619  addPass(createWebAssemblyRegStackify(getOptLevel()));620 621  if (getOptLevel() != CodeGenOptLevel::None) {622    // Run the register coloring pass to reduce the total number of registers.623    // This runs after stackification so that it doesn't consider registers624    // that become stackified.625    addPass(createWebAssemblyRegColoring());626  }627 628  // Sort the blocks of the CFG into topological order, a prerequisite for629  // BLOCK and LOOP markers.630  addPass(createWebAssemblyCFGSort());631 632  // Insert BLOCK and LOOP markers.633  addPass(createWebAssemblyCFGStackify());634 635  // Insert explicit local.get and local.set operators.636  if (!WasmDisableExplicitLocals)637    addPass(createWebAssemblyExplicitLocals());638 639  // Lower br_unless into br_if.640  addPass(createWebAssemblyLowerBrUnless());641 642  // Perform the very last peephole optimizations on the code.643  if (getOptLevel() != CodeGenOptLevel::None)644    addPass(createWebAssemblyPeephole());645 646  // Create a mapping from LLVM CodeGen virtual registers to wasm registers.647  addPass(createWebAssemblyRegNumbering());648 649  // Fix debug_values whose defs have been stackified.650  if (!WasmDisableExplicitLocals)651    addPass(createWebAssemblyDebugFixup());652 653  // Collect information to prepare for MC lowering / asm printing.654  addPass(createWebAssemblyMCLowerPrePass());655}656 657bool WebAssemblyPassConfig::addPreISel() {658  TargetPassConfig::addPreISel();659  addPass(createWebAssemblyLowerRefTypesIntPtrConv());660  return false;661}662 663yaml::MachineFunctionInfo *664WebAssemblyTargetMachine::createDefaultFuncInfoYAML() const {665  return new yaml::WebAssemblyFunctionInfo();666}667 668yaml::MachineFunctionInfo *WebAssemblyTargetMachine::convertFuncInfoToYAML(669    const MachineFunction &MF) const {670  const auto *MFI = MF.getInfo<WebAssemblyFunctionInfo>();671  return new yaml::WebAssemblyFunctionInfo(MF, *MFI);672}673 674bool WebAssemblyTargetMachine::parseMachineFunctionInfo(675    const yaml::MachineFunctionInfo &MFI, PerFunctionMIParsingState &PFS,676    SMDiagnostic &Error, SMRange &SourceRange) const {677  const auto &YamlMFI = static_cast<const yaml::WebAssemblyFunctionInfo &>(MFI);678  MachineFunction &MF = PFS.MF;679  MF.getInfo<WebAssemblyFunctionInfo>()->initializeBaseYamlFields(MF, YamlMFI);680  return false;681}682