1285163Sdim//===- WebAssemblyTargetMachine.cpp - Define TargetMachine for WebAssembly -==//
2285163Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6285163Sdim//
7285163Sdim//===----------------------------------------------------------------------===//
8285163Sdim///
9285163Sdim/// \file
10341825Sdim/// This file defines the WebAssembly-specific subclass of TargetMachine.
11285163Sdim///
12285163Sdim//===----------------------------------------------------------------------===//
13285163Sdim
14321369Sdim#include "WebAssemblyTargetMachine.h"
15321369Sdim#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
16353358Sdim#include "TargetInfo/WebAssemblyTargetInfo.h"
17285163Sdim#include "WebAssembly.h"
18353358Sdim#include "WebAssemblyMachineFunctionInfo.h"
19285163Sdim#include "WebAssemblyTargetObjectFile.h"
20285163Sdim#include "WebAssemblyTargetTransformInfo.h"
21353358Sdim#include "llvm/CodeGen/MIRParser/MIParser.h"
22285163Sdim#include "llvm/CodeGen/MachineFunctionPass.h"
23285163Sdim#include "llvm/CodeGen/Passes.h"
24285163Sdim#include "llvm/CodeGen/RegAllocRegistry.h"
25309124Sdim#include "llvm/CodeGen/TargetPassConfig.h"
26285163Sdim#include "llvm/IR/Function.h"
27285163Sdim#include "llvm/Support/TargetRegistry.h"
28285163Sdim#include "llvm/Target/TargetOptions.h"
29285163Sdim#include "llvm/Transforms/Scalar.h"
30353358Sdim#include "llvm/Transforms/Scalar/LowerAtomic.h"
31341825Sdim#include "llvm/Transforms/Utils.h"
32285163Sdimusing namespace llvm;
33285163Sdim
34285163Sdim#define DEBUG_TYPE "wasm"
35285163Sdim
36314564Sdim// Emscripten's asm.js-style exception handling
37314564Sdimstatic cl::opt<bool> EnableEmException(
38314564Sdim    "enable-emscripten-cxx-exceptions",
39314564Sdim    cl::desc("WebAssembly Emscripten-style exception handling"),
40314564Sdim    cl::init(false));
41314564Sdim
42314564Sdim// Emscripten's asm.js-style setjmp/longjmp handling
43314564Sdimstatic cl::opt<bool> EnableEmSjLj(
44314564Sdim    "enable-emscripten-sjlj",
45314564Sdim    cl::desc("WebAssembly Emscripten-style setjmp/longjmp handling"),
46314564Sdim    cl::init(false));
47314564Sdim
48360784Sdimextern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeWebAssemblyTarget() {
49285163Sdim  // Register the target.
50314564Sdim  RegisterTargetMachine<WebAssemblyTargetMachine> X(
51314564Sdim      getTheWebAssemblyTarget32());
52314564Sdim  RegisterTargetMachine<WebAssemblyTargetMachine> Y(
53314564Sdim      getTheWebAssemblyTarget64());
54314564Sdim
55341825Sdim  // Register backend passes
56341825Sdim  auto &PR = *PassRegistry::getPassRegistry();
57341825Sdim  initializeWebAssemblyAddMissingPrototypesPass(PR);
58341825Sdim  initializeWebAssemblyLowerEmscriptenEHSjLjPass(PR);
59341825Sdim  initializeLowerGlobalDtorsPass(PR);
60341825Sdim  initializeFixFunctionBitcastsPass(PR);
61341825Sdim  initializeOptimizeReturnedPass(PR);
62341825Sdim  initializeWebAssemblyArgumentMovePass(PR);
63341825Sdim  initializeWebAssemblySetP2AlignOperandsPass(PR);
64341825Sdim  initializeWebAssemblyReplacePhysRegsPass(PR);
65341825Sdim  initializeWebAssemblyPrepareForLiveIntervalsPass(PR);
66341825Sdim  initializeWebAssemblyOptimizeLiveIntervalsPass(PR);
67344779Sdim  initializeWebAssemblyMemIntrinsicResultsPass(PR);
68341825Sdim  initializeWebAssemblyRegStackifyPass(PR);
69341825Sdim  initializeWebAssemblyRegColoringPass(PR);
70341825Sdim  initializeWebAssemblyFixIrreducibleControlFlowPass(PR);
71341825Sdim  initializeWebAssemblyLateEHPreparePass(PR);
72341825Sdim  initializeWebAssemblyExceptionInfoPass(PR);
73341825Sdim  initializeWebAssemblyCFGSortPass(PR);
74341825Sdim  initializeWebAssemblyCFGStackifyPass(PR);
75353358Sdim  initializeWebAssemblyExplicitLocalsPass(PR);
76341825Sdim  initializeWebAssemblyLowerBrUnlessPass(PR);
77341825Sdim  initializeWebAssemblyRegNumberingPass(PR);
78341825Sdim  initializeWebAssemblyPeepholePass(PR);
79341825Sdim  initializeWebAssemblyCallIndirectFixupPass(PR);
80285163Sdim}
81285163Sdim
82285163Sdim//===----------------------------------------------------------------------===//
83285163Sdim// WebAssembly Lowering public interface.
84285163Sdim//===----------------------------------------------------------------------===//
85285163Sdim
86353358Sdimstatic Reloc::Model getEffectiveRelocModel(Optional<Reloc::Model> RM,
87353358Sdim                                           const Triple &TT) {
88344779Sdim  if (!RM.hasValue()) {
89344779Sdim    // Default to static relocation model.  This should always be more optimial
90344779Sdim    // than PIC since the static linker can determine all global addresses and
91344779Sdim    // assume direct function calls.
92344779Sdim    return Reloc::Static;
93344779Sdim  }
94353358Sdim
95353358Sdim  if (!TT.isOSEmscripten()) {
96353358Sdim    // Relocation modes other than static are currently implemented in a way
97353358Sdim    // that only works for Emscripten, so disable them if we aren't targeting
98353358Sdim    // Emscripten.
99353358Sdim    return Reloc::Static;
100353358Sdim  }
101353358Sdim
102309124Sdim  return *RM;
103309124Sdim}
104309124Sdim
105285163Sdim/// Create an WebAssembly architecture model.
106285163Sdim///
107285163SdimWebAssemblyTargetMachine::WebAssemblyTargetMachine(
108285163Sdim    const Target &T, const Triple &TT, StringRef CPU, StringRef FS,
109309124Sdim    const TargetOptions &Options, Optional<Reloc::Model> RM,
110327952Sdim    Optional<CodeModel::Model> CM, CodeGenOpt::Level OL, bool JIT)
111296417Sdim    : LLVMTargetMachine(T,
112296417Sdim                        TT.isArch64Bit() ? "e-m:e-p:64:64-i64:64-n32:64-S128"
113296417Sdim                                         : "e-m:e-p:32:32-i64:64-n32:64-S128",
114353358Sdim                        TT, CPU, FS, Options, getEffectiveRelocModel(RM, TT),
115344779Sdim                        getEffectiveCodeModel(CM, CodeModel::Large), OL),
116341825Sdim      TLOF(new WebAssemblyTargetObjectFile()) {
117314564Sdim  // WebAssembly type-checks instructions, but a noreturn function with a return
118296417Sdim  // type that doesn't match the context will cause a check failure. So we lower
119296417Sdim  // LLVM 'unreachable' to ISD::TRAP and then lower that to WebAssembly's
120314564Sdim  // 'unreachable' instructions which is meant for that case.
121296417Sdim  this->Options.TrapUnreachable = true;
122296417Sdim
123321369Sdim  // WebAssembly treats each function as an independent unit. Force
124321369Sdim  // -ffunction-sections, effectively, so that we can emit them independently.
125341825Sdim  this->Options.FunctionSections = true;
126341825Sdim  this->Options.DataSections = true;
127341825Sdim  this->Options.UniqueSectionNames = true;
128321369Sdim
129285163Sdim  initAsmInfo();
130285163Sdim
131309124Sdim  // Note that we don't use setRequiresStructuredCFG(true). It disables
132309124Sdim  // optimizations than we're ok with, and want, such as critical edge
133309124Sdim  // splitting and tail merging.
134285163Sdim}
135285163Sdim
136353358SdimWebAssemblyTargetMachine::~WebAssemblyTargetMachine() = default; // anchor.
137285163Sdim
138285163Sdimconst WebAssemblySubtarget *
139353358SdimWebAssemblyTargetMachine::getSubtargetImpl(std::string CPU,
140353358Sdim                                           std::string FS) const {
141353358Sdim  auto &I = SubtargetMap[CPU + FS];
142353358Sdim  if (!I) {
143360784Sdim    I = std::make_unique<WebAssemblySubtarget>(TargetTriple, CPU, FS, *this);
144353358Sdim  }
145353358Sdim  return I.get();
146353358Sdim}
147353358Sdim
148353358Sdimconst WebAssemblySubtarget *
149285163SdimWebAssemblyTargetMachine::getSubtargetImpl(const Function &F) const {
150285163Sdim  Attribute CPUAttr = F.getFnAttribute("target-cpu");
151285163Sdim  Attribute FSAttr = F.getFnAttribute("target-features");
152285163Sdim
153285163Sdim  std::string CPU = !CPUAttr.hasAttribute(Attribute::None)
154285163Sdim                        ? CPUAttr.getValueAsString().str()
155285163Sdim                        : TargetCPU;
156285163Sdim  std::string FS = !FSAttr.hasAttribute(Attribute::None)
157285163Sdim                       ? FSAttr.getValueAsString().str()
158285163Sdim                       : TargetFS;
159285163Sdim
160353358Sdim  // This needs to be done before we create a new subtarget since any
161353358Sdim  // creation will depend on the TM and the code generation flags on the
162353358Sdim  // function that reside in TargetOptions.
163353358Sdim  resetTargetOptions(F);
164353358Sdim
165353358Sdim  return getSubtargetImpl(CPU, FS);
166285163Sdim}
167285163Sdim
168285163Sdimnamespace {
169353358Sdim
170353358Sdimclass CoalesceFeaturesAndStripAtomics final : public ModulePass {
171353358Sdim  // Take the union of all features used in the module and use it for each
172353358Sdim  // function individually, since having multiple feature sets in one module
173353358Sdim  // currently does not make sense for WebAssembly. If atomics are not enabled,
174353358Sdim  // also strip atomic operations and thread local storage.
175341825Sdim  static char ID;
176353358Sdim  WebAssemblyTargetMachine *WasmTM;
177341825Sdim
178344779Sdimpublic:
179353358Sdim  CoalesceFeaturesAndStripAtomics(WebAssemblyTargetMachine *WasmTM)
180353358Sdim      : ModulePass(ID), WasmTM(WasmTM) {}
181353358Sdim
182341825Sdim  bool runOnModule(Module &M) override {
183353358Sdim    FeatureBitset Features = coalesceFeatures(M);
184353358Sdim
185353358Sdim    std::string FeatureStr = getFeatureString(Features);
186353358Sdim    for (auto &F : M)
187353358Sdim      replaceFeatures(F, FeatureStr);
188353358Sdim
189353358Sdim    bool StrippedAtomics = false;
190353358Sdim    bool StrippedTLS = false;
191353358Sdim
192353358Sdim    if (!Features[WebAssembly::FeatureAtomics])
193353358Sdim      StrippedAtomics = stripAtomics(M);
194353358Sdim
195353358Sdim    if (!Features[WebAssembly::FeatureBulkMemory])
196353358Sdim      StrippedTLS = stripThreadLocals(M);
197353358Sdim
198353358Sdim    if (StrippedAtomics && !StrippedTLS)
199353358Sdim      stripThreadLocals(M);
200353358Sdim    else if (StrippedTLS && !StrippedAtomics)
201353358Sdim      stripAtomics(M);
202353358Sdim
203353358Sdim    recordFeatures(M, Features, StrippedAtomics || StrippedTLS);
204353358Sdim
205353358Sdim    // Conservatively assume we have made some change
206341825Sdim    return true;
207341825Sdim  }
208353358Sdim
209353358Sdimprivate:
210353358Sdim  FeatureBitset coalesceFeatures(const Module &M) {
211353358Sdim    FeatureBitset Features =
212353358Sdim        WasmTM
213353358Sdim            ->getSubtargetImpl(WasmTM->getTargetCPU(),
214353358Sdim                               WasmTM->getTargetFeatureString())
215353358Sdim            ->getFeatureBits();
216353358Sdim    for (auto &F : M)
217353358Sdim      Features |= WasmTM->getSubtargetImpl(F)->getFeatureBits();
218353358Sdim    return Features;
219353358Sdim  }
220353358Sdim
221353358Sdim  std::string getFeatureString(const FeatureBitset &Features) {
222353358Sdim    std::string Ret;
223353358Sdim    for (const SubtargetFeatureKV &KV : WebAssemblyFeatureKV) {
224353358Sdim      if (Features[KV.Value])
225353358Sdim        Ret += (StringRef("+") + KV.Key + ",").str();
226353358Sdim    }
227353358Sdim    return Ret;
228353358Sdim  }
229353358Sdim
230353358Sdim  void replaceFeatures(Function &F, const std::string &Features) {
231353358Sdim    F.removeFnAttr("target-features");
232353358Sdim    F.removeFnAttr("target-cpu");
233353358Sdim    F.addFnAttr("target-features", Features);
234353358Sdim  }
235353358Sdim
236353358Sdim  bool stripAtomics(Module &M) {
237353358Sdim    // Detect whether any atomics will be lowered, since there is no way to tell
238353358Sdim    // whether the LowerAtomic pass lowers e.g. stores.
239353358Sdim    bool Stripped = false;
240353358Sdim    for (auto &F : M) {
241353358Sdim      for (auto &B : F) {
242353358Sdim        for (auto &I : B) {
243353358Sdim          if (I.isAtomic()) {
244353358Sdim            Stripped = true;
245353358Sdim            goto done;
246353358Sdim          }
247353358Sdim        }
248353358Sdim      }
249353358Sdim    }
250353358Sdim
251353358Sdim  done:
252353358Sdim    if (!Stripped)
253353358Sdim      return false;
254353358Sdim
255353358Sdim    LowerAtomicPass Lowerer;
256353358Sdim    FunctionAnalysisManager FAM;
257353358Sdim    for (auto &F : M)
258353358Sdim      Lowerer.run(F, FAM);
259353358Sdim
260353358Sdim    return true;
261353358Sdim  }
262353358Sdim
263353358Sdim  bool stripThreadLocals(Module &M) {
264353358Sdim    bool Stripped = false;
265353358Sdim    for (auto &GV : M.globals()) {
266353358Sdim      if (GV.getThreadLocalMode() !=
267353358Sdim          GlobalValue::ThreadLocalMode::NotThreadLocal) {
268353358Sdim        Stripped = true;
269353358Sdim        GV.setThreadLocalMode(GlobalValue::ThreadLocalMode::NotThreadLocal);
270353358Sdim      }
271353358Sdim    }
272353358Sdim    return Stripped;
273353358Sdim  }
274353358Sdim
275353358Sdim  void recordFeatures(Module &M, const FeatureBitset &Features, bool Stripped) {
276353358Sdim    for (const SubtargetFeatureKV &KV : WebAssemblyFeatureKV) {
277353358Sdim      std::string MDKey = (StringRef("wasm-feature-") + KV.Key).str();
278353358Sdim      if (KV.Value == WebAssembly::FeatureAtomics && Stripped) {
279353358Sdim        // "atomics" is special: code compiled without atomics may have had its
280353358Sdim        // atomics lowered to nonatomic operations. In that case, atomics is
281353358Sdim        // disallowed to prevent unsafe linking with atomics-enabled objects.
282353358Sdim        assert(!Features[WebAssembly::FeatureAtomics] ||
283353358Sdim               !Features[WebAssembly::FeatureBulkMemory]);
284353358Sdim        M.addModuleFlag(Module::ModFlagBehavior::Error, MDKey,
285353358Sdim                        wasm::WASM_FEATURE_PREFIX_DISALLOWED);
286353358Sdim      } else if (Features[KV.Value]) {
287353358Sdim        // Otherwise features are marked Used or not mentioned
288353358Sdim        M.addModuleFlag(Module::ModFlagBehavior::Error, MDKey,
289353358Sdim                        wasm::WASM_FEATURE_PREFIX_USED);
290353358Sdim      }
291353358Sdim    }
292353358Sdim  }
293341825Sdim};
294353358Sdimchar CoalesceFeaturesAndStripAtomics::ID = 0;
295341825Sdim
296285163Sdim/// WebAssembly Code Generator Pass Configuration Options.
297285163Sdimclass WebAssemblyPassConfig final : public TargetPassConfig {
298285163Sdimpublic:
299321369Sdim  WebAssemblyPassConfig(WebAssemblyTargetMachine &TM, PassManagerBase &PM)
300285163Sdim      : TargetPassConfig(TM, PM) {}
301285163Sdim
302285163Sdim  WebAssemblyTargetMachine &getWebAssemblyTargetMachine() const {
303285163Sdim    return getTM<WebAssemblyTargetMachine>();
304285163Sdim  }
305285163Sdim
306285163Sdim  FunctionPass *createTargetRegisterAllocator(bool) override;
307285163Sdim
308285163Sdim  void addIRPasses() override;
309285163Sdim  bool addInstSelector() override;
310285163Sdim  void addPostRegAlloc() override;
311309124Sdim  bool addGCPasses() override { return false; }
312285163Sdim  void addPreEmitPass() override;
313353358Sdim
314353358Sdim  // No reg alloc
315353358Sdim  bool addRegAssignmentFast() override { return false; }
316353358Sdim
317353358Sdim  // No reg alloc
318353358Sdim  bool addRegAssignmentOptimized() override { return false; }
319285163Sdim};
320285163Sdim} // end anonymous namespace
321285163Sdim
322327952SdimTargetTransformInfo
323327952SdimWebAssemblyTargetMachine::getTargetTransformInfo(const Function &F) {
324327952Sdim  return TargetTransformInfo(WebAssemblyTTIImpl(this, F));
325285163Sdim}
326285163Sdim
327285163SdimTargetPassConfig *
328285163SdimWebAssemblyTargetMachine::createPassConfig(PassManagerBase &PM) {
329321369Sdim  return new WebAssemblyPassConfig(*this, PM);
330285163Sdim}
331285163Sdim
332285163SdimFunctionPass *WebAssemblyPassConfig::createTargetRegisterAllocator(bool) {
333285163Sdim  return nullptr; // No reg alloc
334285163Sdim}
335285163Sdim
336285163Sdim//===----------------------------------------------------------------------===//
337285163Sdim// The following functions are called from lib/CodeGen/Passes.cpp to modify
338285163Sdim// the CodeGen pass sequence.
339285163Sdim//===----------------------------------------------------------------------===//
340285163Sdim
341285163Sdimvoid WebAssemblyPassConfig::addIRPasses() {
342353358Sdim  // Runs LowerAtomicPass if necessary
343353358Sdim  addPass(new CoalesceFeaturesAndStripAtomics(&getWebAssemblyTargetMachine()));
344285163Sdim
345353358Sdim  // This is a no-op if atomics are not used in the module
346353358Sdim  addPass(createAtomicExpandPass());
347353358Sdim
348341825Sdim  // Add signatures to prototype-less function declarations
349341825Sdim  addPass(createWebAssemblyAddMissingPrototypes());
350341825Sdim
351327952Sdim  // Lower .llvm.global_dtors into .llvm_global_ctors with __cxa_atexit calls.
352327952Sdim  addPass(createWebAssemblyLowerGlobalDtors());
353327952Sdim
354314564Sdim  // Fix function bitcasts, as WebAssembly requires caller and callee signatures
355314564Sdim  // to match.
356314564Sdim  addPass(createWebAssemblyFixFunctionBitcasts());
357314564Sdim
358296417Sdim  // Optimize "returned" function attributes.
359309124Sdim  if (getOptLevel() != CodeGenOpt::None)
360309124Sdim    addPass(createWebAssemblyOptimizeReturned());
361296417Sdim
362314564Sdim  // If exception handling is not enabled and setjmp/longjmp handling is
363314564Sdim  // enabled, we lower invokes into calls and delete unreachable landingpad
364314564Sdim  // blocks. Lowering invokes when there is no EH support is done in
365314564Sdim  // TargetPassConfig::addPassesToHandleExceptions, but this runs after this
366314564Sdim  // function and SjLj handling expects all invokes to be lowered before.
367341825Sdim  if (!EnableEmException &&
368341825Sdim      TM->Options.ExceptionModel == ExceptionHandling::None) {
369314564Sdim    addPass(createLowerInvokePass());
370314564Sdim    // The lower invoke pass may create unreachable code. Remove it in order not
371314564Sdim    // to process dead blocks in setjmp/longjmp handling.
372314564Sdim    addPass(createUnreachableBlockEliminationPass());
373314564Sdim  }
374314564Sdim
375314564Sdim  // Handle exceptions and setjmp/longjmp if enabled.
376314564Sdim  if (EnableEmException || EnableEmSjLj)
377314564Sdim    addPass(createWebAssemblyLowerEmscriptenEHSjLj(EnableEmException,
378314564Sdim                                                   EnableEmSjLj));
379314564Sdim
380353358Sdim  // Expand indirectbr instructions to switches.
381353358Sdim  addPass(createIndirectBrExpandPass());
382353358Sdim
383285163Sdim  TargetPassConfig::addIRPasses();
384285163Sdim}
385285163Sdim
386285163Sdimbool WebAssemblyPassConfig::addInstSelector() {
387296417Sdim  (void)TargetPassConfig::addInstSelector();
388285163Sdim  addPass(
389285163Sdim      createWebAssemblyISelDag(getWebAssemblyTargetMachine(), getOptLevel()));
390296417Sdim  // Run the argument-move pass immediately after the ScheduleDAG scheduler
391296417Sdim  // so that we can fix up the ARGUMENT instructions before anything else
392296417Sdim  // sees them in the wrong place.
393296417Sdim  addPass(createWebAssemblyArgumentMove());
394309124Sdim  // Set the p2align operands. This information is present during ISel, however
395309124Sdim  // it's inconvenient to collect. Collect it now, and update the immediate
396309124Sdim  // operands.
397309124Sdim  addPass(createWebAssemblySetP2AlignOperands());
398285163Sdim  return false;
399285163Sdim}
400285163Sdim
401296417Sdimvoid WebAssemblyPassConfig::addPostRegAlloc() {
402296417Sdim  // TODO: The following CodeGen passes don't currently support code containing
403296417Sdim  // virtual registers. Consider removing their restrictions and re-enabling
404296417Sdim  // them.
405285163Sdim
406314564Sdim  // These functions all require the NoVRegs property.
407309124Sdim  disablePass(&MachineCopyPropagationID);
408341825Sdim  disablePass(&PostRAMachineSinkingID);
409309124Sdim  disablePass(&PostRASchedulerID);
410309124Sdim  disablePass(&FuncletLayoutID);
411309124Sdim  disablePass(&StackMapLivenessID);
412309124Sdim  disablePass(&LiveDebugValuesID);
413309124Sdim  disablePass(&PatchableFunctionID);
414341825Sdim  disablePass(&ShrinkWrapID);
415296417Sdim
416353358Sdim  // This pass hurts code size for wasm because it can generate irreducible
417353358Sdim  // control flow.
418353358Sdim  disablePass(&MachineBlockPlacementID);
419353358Sdim
420296417Sdim  TargetPassConfig::addPostRegAlloc();
421296417Sdim}
422296417Sdim
423296417Sdimvoid WebAssemblyPassConfig::addPreEmitPass() {
424296417Sdim  TargetPassConfig::addPreEmitPass();
425296417Sdim
426314564Sdim  // Rewrite pseudo call_indirect instructions as real instructions.
427314564Sdim  // This needs to run before register stackification, because we change the
428314564Sdim  // order of the arguments.
429314564Sdim  addPass(createWebAssemblyCallIndirectFixup());
430314564Sdim
431344779Sdim  // Eliminate multiple-entry loops.
432344779Sdim  addPass(createWebAssemblyFixIrreducibleControlFlow());
433344779Sdim
434344779Sdim  // Do various transformations for exception handling.
435353358Sdim  // Every CFG-changing optimizations should come before this.
436344779Sdim  addPass(createWebAssemblyLateEHPrepare());
437344779Sdim
438353358Sdim  // Now that we have a prologue and epilogue and all frame indices are
439353358Sdim  // rewritten, eliminate SP and FP. This allows them to be stackified,
440353358Sdim  // colored, and numbered with the rest of the registers.
441353358Sdim  addPass(createWebAssemblyReplacePhysRegs());
442353358Sdim
443353358Sdim  // Preparations and optimizations related to register stackification.
444309124Sdim  if (getOptLevel() != CodeGenOpt::None) {
445309124Sdim    // LiveIntervals isn't commonly run this late. Re-establish preconditions.
446309124Sdim    addPass(createWebAssemblyPrepareForLiveIntervals());
447309124Sdim
448309124Sdim    // Depend on LiveIntervals and perform some optimizations on it.
449309124Sdim    addPass(createWebAssemblyOptimizeLiveIntervals());
450309124Sdim
451344779Sdim    // Prepare memory intrinsic calls for register stackifying.
452344779Sdim    addPass(createWebAssemblyMemIntrinsicResults());
453309124Sdim
454314564Sdim    // Mark registers as representing wasm's value stack. This is a key
455309124Sdim    // code-compression technique in WebAssembly. We run this pass (and
456344779Sdim    // MemIntrinsicResults above) very late, so that it sees as much code as
457344779Sdim    // possible, including code emitted by PEI and expanded by late tail
458344779Sdim    // duplication.
459309124Sdim    addPass(createWebAssemblyRegStackify());
460309124Sdim
461309124Sdim    // Run the register coloring pass to reduce the total number of registers.
462309124Sdim    // This runs after stackification so that it doesn't consider registers
463309124Sdim    // that become stackified.
464309124Sdim    addPass(createWebAssemblyRegColoring());
465309124Sdim  }
466309124Sdim
467321369Sdim  // Sort the blocks of the CFG into topological order, a prerequisite for
468321369Sdim  // BLOCK and LOOP markers.
469321369Sdim  addPass(createWebAssemblyCFGSort());
470309124Sdim
471321369Sdim  // Insert BLOCK and LOOP markers.
472296417Sdim  addPass(createWebAssemblyCFGStackify());
473296417Sdim
474353358Sdim  // Insert explicit local.get and local.set operators.
475353358Sdim  addPass(createWebAssemblyExplicitLocals());
476353358Sdim
477296417Sdim  // Lower br_unless into br_if.
478296417Sdim  addPass(createWebAssemblyLowerBrUnless());
479296417Sdim
480309124Sdim  // Perform the very last peephole optimizations on the code.
481309124Sdim  if (getOptLevel() != CodeGenOpt::None)
482309124Sdim    addPass(createWebAssemblyPeephole());
483309124Sdim
484296417Sdim  // Create a mapping from LLVM CodeGen virtual registers to wasm registers.
485296417Sdim  addPass(createWebAssemblyRegNumbering());
486296417Sdim}
487353358Sdim
488353358Sdimyaml::MachineFunctionInfo *
489353358SdimWebAssemblyTargetMachine::createDefaultFuncInfoYAML() const {
490353358Sdim  return new yaml::WebAssemblyFunctionInfo();
491353358Sdim}
492353358Sdim
493353358Sdimyaml::MachineFunctionInfo *WebAssemblyTargetMachine::convertFuncInfoToYAML(
494353358Sdim    const MachineFunction &MF) const {
495353358Sdim  const auto *MFI = MF.getInfo<WebAssemblyFunctionInfo>();
496353358Sdim  return new yaml::WebAssemblyFunctionInfo(*MFI);
497353358Sdim}
498353358Sdim
499353358Sdimbool WebAssemblyTargetMachine::parseMachineFunctionInfo(
500353358Sdim    const yaml::MachineFunctionInfo &MFI, PerFunctionMIParsingState &PFS,
501353358Sdim    SMDiagnostic &Error, SMRange &SourceRange) const {
502353358Sdim  const auto &YamlMFI =
503353358Sdim      reinterpret_cast<const yaml::WebAssemblyFunctionInfo &>(MFI);
504353358Sdim  MachineFunction &MF = PFS.MF;
505353358Sdim  MF.getInfo<WebAssemblyFunctionInfo>()->initializeBaseYamlFields(YamlMFI);
506353358Sdim  return false;
507353358Sdim}
508