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