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-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// 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/GlobalISel/IRTranslator.h"
24#include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
25#include "llvm/CodeGen/GlobalISel/Legalizer.h"
26#include "llvm/CodeGen/GlobalISel/RegBankSelect.h"
27#include "llvm/CodeGen/MIRParser/MIParser.h"
28#include "llvm/CodeGen/Passes.h"
29#include "llvm/CodeGen/RegAllocRegistry.h"
30#include "llvm/CodeGen/TargetPassConfig.h"
31#include "llvm/IR/Function.h"
32#include "llvm/InitializePasses.h"
33#include "llvm/MC/TargetRegistry.h"
34#include "llvm/Support/Compiler.h"
35#include "llvm/Target/TargetOptions.h"
36#include "llvm/Transforms/Scalar.h"
37#include "llvm/Transforms/Utils.h"
38#include <optional>
39using namespace llvm;
40
41#define DEBUG_TYPE "wasm"
42
43// A command-line option to keep implicit locals
44// for the purpose of testing with lit/llc ONLY.
45// This produces output which is not valid WebAssembly, and is not supported
46// by assemblers/disassemblers and other MC based tools.
47cl::opt<bool> WebAssembly::WasmDisableExplicitLocals(
48 "wasm-disable-explicit-locals", cl::Hidden,
49 cl::desc("WebAssembly: output implicit locals in"
50 " instruction output for test purposes only."),
51 cl::init(Val: false));
52
53// Exception handling & setjmp-longjmp handling related options.
54
55// Emscripten's asm.js-style setjmp/longjmp handling
56cl::opt<bool> WebAssembly::WasmEnableEmSjLj(
57 "enable-emscripten-sjlj",
58 cl::desc("WebAssembly Emscripten-style setjmp/longjmp handling"),
59 cl::init(Val: false));
60// setjmp/longjmp handling using wasm EH instructions
61cl::opt<bool> WebAssembly::WasmEnableSjLj(
62 "wasm-enable-sjlj", cl::desc("WebAssembly setjmp/longjmp handling"));
63// If true, use the legacy Wasm EH proposal:
64// https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/legacy/Exceptions.md
65// And if false, use the standardized Wasm EH proposal:
66// https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/Exceptions.md
67// Currently set to true by default because not all major web browsers turn on
68// the new standard proposal by default, but will later change to false.
69cl::opt<bool> WebAssembly::WasmUseLegacyEH(
70 "wasm-use-legacy-eh", cl::desc("WebAssembly exception handling (legacy)"),
71 cl::init(Val: true));
72
73extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
74LLVMInitializeWebAssemblyTarget() {
75 // Register the target.
76 RegisterTargetMachine<WebAssemblyTargetMachine> X(
77 getTheWebAssemblyTarget32());
78 RegisterTargetMachine<WebAssemblyTargetMachine> Y(
79 getTheWebAssemblyTarget64());
80
81 // Register backend passes
82 auto &PR = *PassRegistry::getPassRegistry();
83 initializeGlobalISel(PR);
84 initializeWebAssemblyPreLegalizerCombinerLegacyPass(PR);
85 initializeWebAssemblyPostLegalizerCombinerLegacyPass(PR);
86 initializeWebAssemblyAddMissingPrototypesLegacyPass(PR);
87 initializeWebAssemblyLowerEmscriptenEHSjLjLegacyPass(PR);
88 initializeLowerGlobalDtorsLegacyPassPass(PR);
89 initializeWebAssemblyFixFunctionBitcastsLegacyPass(PR);
90 initializeWebAssemblyOptimizeReturnedLegacyPass(PR);
91 initializeWebAssemblyRefTypeMem2LocalLegacyPass(PR);
92 initializeWebAssemblyArgumentMoveLegacyPass(PR);
93 initializeWebAssemblyAsmPrinterPass(PR);
94 initializeWebAssemblySetP2AlignOperandsLegacyPass(PR);
95 initializeWebAssemblyReplacePhysRegsLegacyPass(PR);
96 initializeWebAssemblyOptimizeLiveIntervalsLegacyPass(PR);
97 initializeWebAssemblyMemIntrinsicResultsLegacyPass(PR);
98 initializeWebAssemblyRegStackifyLegacyPass(PR);
99 initializeWebAssemblyRegColoringLegacyPass(PR);
100 initializeWebAssemblyNullifyDebugValueListsLegacyPass(PR);
101 initializeWebAssemblyFixIrreducibleControlFlowLegacyPass(PR);
102 initializeWebAssemblyLateEHPrepareLegacyPass(PR);
103 initializeWebAssemblyExceptionInfoWrapperPassPass(PR);
104 initializeWebAssemblyCFGSortLegacyPass(PR);
105 initializeWebAssemblyCFGStackifyLegacyPass(PR);
106 initializeWebAssemblyExplicitLocalsLegacyPass(PR);
107 initializeWebAssemblyLowerBrUnlessLegacyPass(PR);
108 initializeWebAssemblyRegNumberingLegacyPass(PR);
109 initializeWebAssemblyDebugFixupLegacyPass(PR);
110 initializeWebAssemblyPeepholeLegacyPass(PR);
111 initializeWebAssemblyMCLowerPreLegacyPass(PR);
112 initializeWebAssemblyFixBrTableDefaultsLegacyPass(PR);
113 initializeWebAssemblyDAGToDAGISelLegacyPass(PR);
114}
115
116//===----------------------------------------------------------------------===//
117// WebAssembly Lowering public interface.
118//===----------------------------------------------------------------------===//
119
120static Reloc::Model getEffectiveRelocModel(std::optional<Reloc::Model> RM) {
121 // Default to static relocation model. This should always be more optimal
122 // than PIC since the static linker can determine all global addresses and
123 // assume direct function calls.
124 return RM.value_or(u: Reloc::Static);
125}
126
127using WebAssembly::WasmDisableExplicitLocals;
128using WebAssembly::WasmEnableEmSjLj;
129using WebAssembly::WasmEnableSjLj;
130
131static void basicCheckForEHAndSjLj(TargetMachine *TM) {
132
133 bool EnableEmEH = TM->Options.ExceptionModel == ExceptionHandling::Emscripten;
134
135 // You can't enable two modes of SjLj at the same time
136 if (WasmEnableEmSjLj && WasmEnableSjLj)
137 report_fatal_error(
138 reason: "-enable-emscripten-sjlj not allowed with -wasm-enable-sjlj");
139 // You can't mix Emscripten EH with Wasm SjLj.
140 if (EnableEmEH && WasmEnableSjLj)
141 report_fatal_error(
142 reason: "-exception-model=emscripten not allowed with -wasm-enable-sjlj");
143
144 if (TM->Options.ExceptionModel == ExceptionHandling::Default) {
145 // FIXME: This flag should be removed in favor of directly using the
146 // generically configured ExceptionsType.
147 if (WebAssembly::WasmEnableSjLj)
148 TM->Options.ExceptionModel = ExceptionHandling::Wasm;
149 }
150
151 // Basic Correctness checking related to -exception-model
152 if (TM->Options.ExceptionModel != ExceptionHandling::Default &&
153 TM->Options.ExceptionModel != ExceptionHandling::None &&
154 TM->Options.ExceptionModel != ExceptionHandling::Wasm &&
155 TM->Options.ExceptionModel != ExceptionHandling::Emscripten)
156 report_fatal_error(
157 reason: "-exception-model should be either 'none', 'wasm', or 'emscripten'");
158 if (WasmEnableSjLj && TM->Options.ExceptionModel != ExceptionHandling::Wasm)
159 report_fatal_error(
160 reason: "-wasm-enable-sjlj only allowed with -exception-model=wasm");
161
162 // Currently it is allowed to mix Wasm EH with Emscripten SjLj as an interim
163 // measure, but some code will error out at compile time in this combination.
164 // See WebAssemblyLowerEmscriptenEHSjLj pass for details.
165}
166
167/// Create an WebAssembly architecture model.
168///
169WebAssemblyTargetMachine::WebAssemblyTargetMachine(
170 const Target &T, const Triple &TT, StringRef CPU, StringRef FS,
171 const TargetOptions &Options, std::optional<Reloc::Model> RM,
172 std::optional<CodeModel::Model> CM, CodeGenOptLevel OL, bool JIT)
173 : CodeGenTargetMachineImpl(T, TT, CPU, FS, Options,
174 getEffectiveRelocModel(RM),
175 getEffectiveCodeModel(CM, Default: CodeModel::Large), OL),
176 TLOF(new WebAssemblyTargetObjectFile()) {
177 // WebAssembly type-checks instructions, but a noreturn function with a return
178 // type that doesn't match the context will cause a check failure. So we lower
179 // LLVM 'unreachable' to ISD::TRAP and then lower that to WebAssembly's
180 // 'unreachable' instructions which is meant for that case. Formerly, we also
181 // needed to add checks to SP failure emission in the instruction selection
182 // backends, but this has since been tied to TrapUnreachable and is no longer
183 // necessary.
184 this->Options.TrapUnreachable = true;
185 this->Options.NoTrapAfterNoreturn = false;
186
187 // WebAssembly treats each function as an independent unit. Force
188 // -ffunction-sections, effectively, so that we can emit them independently.
189 this->Options.FunctionSections = true;
190 this->Options.DataSections = true;
191 this->Options.UniqueSectionNames = true;
192
193 basicCheckForEHAndSjLj(TM: this);
194 initAsmInfo();
195
196 // WebAssembly does not run RegAllocFast; tied operands must be lowered by
197 // TwoAddressInstructionPass.
198 setEnableTiedFastRegAlloc(false);
199
200 LLT::setUseExtended(true);
201
202 // Note that we don't use setRequiresStructuredCFG(true). It disables
203 // optimizations than we're ok with, and want, such as critical edge
204 // splitting and tail merging.
205}
206
207WebAssemblyTargetMachine::~WebAssemblyTargetMachine() = default; // anchor.
208
209const WebAssemblySubtarget *
210WebAssemblyTargetMachine::getSubtargetImpl(StringRef CPU, StringRef FS,
211 StringRef ABIName) const {
212 auto &I = SubtargetMap[CPU.str() + FS.str() + ABIName.str()];
213 if (!I) {
214 I = std::make_unique<WebAssemblySubtarget>(args: TargetTriple, args&: CPU, args&: FS, args: *this,
215 args&: ABIName);
216 }
217 return I.get();
218}
219
220const WebAssemblySubtarget *
221WebAssemblyTargetMachine::getSubtargetImpl(const Function &F) const {
222 Attribute CPUAttr = F.getFnAttribute(Kind: "target-cpu");
223 Attribute FSAttr = F.getFnAttribute(Kind: "target-features");
224
225 StringRef CPU = CPUAttr.isValid() ? CPUAttr.getValueAsString() : TargetCPU;
226 StringRef FS = FSAttr.isValid() ? FSAttr.getValueAsString() : TargetFS;
227
228 return getSubtargetImpl(CPU, FS, ABIName: getTargetABIName(M: *F.getParent()));
229}
230
231namespace {
232
233/// WebAssembly Code Generator Pass Configuration Options.
234class WebAssemblyPassConfig final : public TargetPassConfig {
235public:
236 WebAssemblyPassConfig(WebAssemblyTargetMachine &TM, PassManagerBase &PM)
237 : TargetPassConfig(TM, PM) {}
238
239 WebAssemblyTargetMachine &getWebAssemblyTargetMachine() const {
240 return getTM<WebAssemblyTargetMachine>();
241 }
242
243 FunctionPass *createTargetRegisterAllocator(bool) override;
244
245 void addIRPasses() override;
246 void addISelPrepare() override;
247 bool addInstSelector() override;
248 void addOptimizedRegAlloc() override;
249 void addPostRegAlloc() override;
250 bool addGCPasses() override { return false; }
251 void addPreEmitPass() override;
252 bool addPreISel() override;
253
254 // No reg alloc
255 bool addRegAssignAndRewriteFast() override { return false; }
256
257 // No reg alloc
258 bool addRegAssignAndRewriteOptimized() override { return false; }
259
260 bool addIRTranslator() override;
261 void addPreLegalizeMachineIR() override;
262 bool addLegalizeMachineIR() override;
263 void addPreRegBankSelect() override;
264 bool addRegBankSelect() override;
265 bool addGlobalInstructionSelect() override;
266};
267} // end anonymous namespace
268
269MachineFunctionInfo *WebAssemblyTargetMachine::createMachineFunctionInfo(
270 BumpPtrAllocator &Allocator, const Function &F,
271 const TargetSubtargetInfo *STI) const {
272 return WebAssemblyFunctionInfo::create<WebAssemblyFunctionInfo>(Allocator, F,
273 STI);
274}
275
276TargetTransformInfo
277WebAssemblyTargetMachine::getTargetTransformInfo(const Function &F) const {
278 return TargetTransformInfo(std::make_unique<WebAssemblyTTIImpl>(args: this, args: F));
279}
280
281TargetPassConfig *
282WebAssemblyTargetMachine::createPassConfig(PassManagerBase &PM) {
283 return new WebAssemblyPassConfig(*this, PM);
284}
285
286FunctionPass *WebAssemblyPassConfig::createTargetRegisterAllocator(bool) {
287 return nullptr; // No reg alloc
288}
289
290//===----------------------------------------------------------------------===//
291// The following functions are called from lib/CodeGen/Passes.cpp to modify
292// the CodeGen pass sequence.
293//===----------------------------------------------------------------------===//
294
295void WebAssemblyPassConfig::addIRPasses() {
296 // Add signatures to prototype-less function declarations
297 addPass(P: createWebAssemblyAddMissingPrototypesLegacyPass());
298
299 // Lower .llvm.global_dtors into .llvm.global_ctors with __cxa_atexit calls.
300 addPass(P: createLowerGlobalDtorsLegacyPass());
301
302 // Fix function bitcasts, as WebAssembly requires caller and callee signatures
303 // to match.
304 addPass(P: createWebAssemblyFixFunctionBitcastsLegacyPass());
305
306 // Optimize "returned" function attributes.
307 if (getOptLevel() != CodeGenOptLevel::None)
308 addPass(P: createWebAssemblyOptimizeReturnedLegacyPass());
309
310 // If exception handling is not enabled and setjmp/longjmp handling is
311 // enabled, we lower invokes into calls and delete unreachable landingpad
312 // blocks. Lowering invokes when there is no EH support is done in
313 // TargetPassConfig::addPassesToHandleExceptions, but that runs after these IR
314 // passes and Emscripten SjLj handling expects all invokes to be lowered
315 // before.
316 bool EnableEmEH = TM->Options.ExceptionModel == ExceptionHandling::Emscripten;
317 bool EnableWasmEH = TM->Options.ExceptionModel == ExceptionHandling::Wasm;
318 if (!EnableEmEH && !EnableWasmEH) {
319 addPass(P: createLowerInvokePass());
320 // The lower invoke pass may create unreachable code. Remove it in order not
321 // to process dead blocks in setjmp/longjmp handling.
322 addPass(P: createUnreachableBlockEliminationPass());
323 }
324
325 // Handle exceptions and setjmp/longjmp if enabled. Unlike Wasm EH preparation
326 // done in WasmEHPrepare pass, Wasm SjLj preparation shares libraries and
327 // transformation algorithms with Emscripten SjLj, so we run
328 // LowerEmscriptenEHSjLj pass also when Wasm SjLj is enabled.
329 if (EnableEmEH || WasmEnableEmSjLj || WasmEnableSjLj)
330 addPass(P: createWebAssemblyLowerEmscriptenEHSjLjLegacyPass(EnableEmEH));
331
332 // Expand indirectbr instructions to switches.
333 addPass(P: createIndirectBrExpandPass(OptLevel: getOptLevel()));
334
335 // Try to expand `vecreduce_{and, or}` into `{any, all}_true`.
336 addPass(P: createWebAssemblyReduceToAnyAllTrueLegacyPass(
337 TM&: getWebAssemblyTargetMachine()));
338
339 TargetPassConfig::addIRPasses();
340}
341
342void WebAssemblyPassConfig::addISelPrepare() {
343 if (TM->Options.ExceptionModel == ExceptionHandling::Wasm)
344 addPass(P: createWasmEHPass());
345
346 // We need to move reference type allocas to WASM_ADDRESS_SPACE_VAR so that
347 // loads and stores are promoted to local.gets/local.sets.
348 addPass(P: createWebAssemblyRefTypeMem2LocalLegacyPass());
349 // Lower atomics and TLS if necessary
350 addPass(P: createWebAssemblyCoalesceFeaturesAndStripAtomicsLegacyPass(
351 TM&: getWebAssemblyTargetMachine()));
352
353 // This is a no-op if atomics are not used in the module
354 addPass(P: createAtomicExpandLegacyPass());
355
356 TargetPassConfig::addISelPrepare();
357}
358
359bool WebAssemblyPassConfig::addInstSelector() {
360 (void)TargetPassConfig::addInstSelector();
361 addPass(P: createWebAssemblyISelDagLegacyPass(TM&: getWebAssemblyTargetMachine(),
362 OptLevel: getOptLevel()));
363 // Run the argument-move pass immediately after the ScheduleDAG scheduler
364 // so that we can fix up the ARGUMENT instructions before anything else
365 // sees them in the wrong place.
366 addPass(P: createWebAssemblyArgumentMoveLegacyPass());
367 // Set the p2align operands. This information is present during ISel, however
368 // it's inconvenient to collect. Collect it now, and update the immediate
369 // operands.
370 addPass(P: createWebAssemblySetP2AlignOperandsLegacyPass());
371
372 // Eliminate range checks and add default targets to br_table instructions.
373 addPass(P: createWebAssemblyFixBrTableDefaultsLegacyPass());
374
375 // unreachable is terminator, non-terminator instruction after it is not
376 // allowed.
377 addPass(P: createWebAssemblyCleanCodeAfterTrapLegacyPass());
378
379 return false;
380}
381
382void WebAssemblyPassConfig::addOptimizedRegAlloc() {
383 // Currently RegisterCoalesce degrades wasm debug info quality by a
384 // significant margin. As a quick fix, disable this for -O1, which is often
385 // used for debugging large applications. Disabling this increases code size
386 // of Emscripten core benchmarks by ~5%, which is acceptable for -O1, which is
387 // usually not used for production builds.
388 // TODO Investigate why RegisterCoalesce degrades debug info quality and fix
389 // it properly
390 if (getOptLevel() == CodeGenOptLevel::Less)
391 disablePass(PassID: &RegisterCoalescerID);
392 TargetPassConfig::addOptimizedRegAlloc();
393}
394
395void WebAssemblyPassConfig::addPostRegAlloc() {
396 // TODO: The following CodeGen passes don't currently support code containing
397 // virtual registers. Consider removing their restrictions and re-enabling
398 // them.
399
400 // These functions all require the NoVRegs property.
401 disablePass(PassID: &MachineLateInstrsCleanupID);
402 disablePass(PassID: &MachineCopyPropagationID);
403 disablePass(PassID: &PostRAMachineSinkingID);
404 disablePass(PassID: &PostRASchedulerID);
405 disablePass(PassID: &FuncletLayoutID);
406 disablePass(PassID: &StackMapLivenessID);
407 disablePass(PassID: &PatchableFunctionID);
408 disablePass(PassID: &ShrinkWrapID);
409 disablePass(PassID: &RemoveLoadsIntoFakeUsesID);
410
411 // This pass hurts code size for wasm because it can generate irreducible
412 // control flow.
413 disablePass(PassID: &MachineBlockPlacementID);
414
415 TargetPassConfig::addPostRegAlloc();
416}
417
418void WebAssemblyPassConfig::addPreEmitPass() {
419 TargetPassConfig::addPreEmitPass();
420
421 // Nullify DBG_VALUE_LISTs that we cannot handle.
422 addPass(P: createWebAssemblyNullifyDebugValueListsLegacyPass());
423
424 // Remove any unreachable blocks that may be left floating around.
425 // Rare, but possible. Needed for WebAssemblyFixIrreducibleControlFlow.
426 addPass(PassID: &UnreachableMachineBlockElimID);
427
428 // Eliminate multiple-entry loops.
429 addPass(P: createWebAssemblyFixIrreducibleControlFlowLegacyPass());
430
431 // Do various transformations for exception handling.
432 // Every CFG-changing optimizations should come before this.
433 if (TM->Options.ExceptionModel == ExceptionHandling::Wasm)
434 addPass(P: createWebAssemblyLateEHPrepareLegacyPass());
435
436 // Now that we have a prologue and epilogue and all frame indices are
437 // rewritten, eliminate SP and FP. This allows them to be stackified,
438 // colored, and numbered with the rest of the registers.
439 addPass(P: createWebAssemblyReplacePhysRegsLegacyPass());
440
441 // Preparations and optimizations related to register stackification.
442 if (getOptLevel() != CodeGenOptLevel::None) {
443 // Depend on LiveIntervals and perform some optimizations on it.
444 addPass(P: createWebAssemblyOptimizeLiveIntervalsLegacyPass());
445
446 // Prepare memory intrinsic calls for register stackifying.
447 addPass(P: createWebAssemblyMemIntrinsicResultsLegacyPass());
448 }
449
450 // Mark registers as representing wasm's value stack. This is a key
451 // code-compression technique in WebAssembly. We run this pass (and
452 // MemIntrinsicResults above) very late, so that it sees as much code as
453 // possible, including code emitted by PEI and expanded by late tail
454 // duplication.
455 addPass(P: createWebAssemblyRegStackifyLegacyPass(OptLevel: getOptLevel()));
456
457 if (getOptLevel() != CodeGenOptLevel::None) {
458 // Run the register coloring pass to reduce the total number of registers.
459 // This runs after stackification so that it doesn't consider registers
460 // that become stackified.
461 addPass(P: createWebAssemblyRegColoringLegacyPass());
462 }
463
464 // Sort the blocks of the CFG into topological order, a prerequisite for
465 // BLOCK and LOOP markers.
466 addPass(P: createWebAssemblyCFGSortLegacyPass());
467
468 // Insert BLOCK and LOOP markers.
469 addPass(P: createWebAssemblyCFGStackifyLegacyPass());
470
471 // Insert explicit local.get and local.set operators.
472 if (!WasmDisableExplicitLocals)
473 addPass(P: createWebAssemblyExplicitLocalsLegacyPass());
474
475 // Lower br_unless into br_if.
476 addPass(P: createWebAssemblyLowerBrUnlessLegacyPass());
477
478 // Perform the very last peephole optimizations on the code.
479 if (getOptLevel() != CodeGenOptLevel::None)
480 addPass(P: createWebAssemblyPeepholeLegacyPass());
481
482 // Create a mapping from LLVM CodeGen virtual registers to wasm registers.
483 addPass(P: createWebAssemblyRegNumberingLegacyPass());
484
485 // Fix debug_values whose defs have been stackified.
486 if (!WasmDisableExplicitLocals)
487 addPass(P: createWebAssemblyDebugFixupLegacyPass());
488
489 // Collect information to prepare for MC lowering / asm printing.
490 addPass(P: createWebAssemblyMCLowerPreLegacyPass());
491}
492
493bool WebAssemblyPassConfig::addPreISel() {
494 TargetPassConfig::addPreISel();
495 return false;
496}
497
498bool WebAssemblyPassConfig::addIRTranslator() {
499 addPass(P: new IRTranslatorLegacy());
500 return false;
501}
502
503void WebAssemblyPassConfig::addPreLegalizeMachineIR() {
504 if (getOptLevel() != CodeGenOptLevel::None) {
505 addPass(P: createWebAssemblyPreLegalizerCombinerLegacyPass());
506 }
507}
508bool WebAssemblyPassConfig::addLegalizeMachineIR() {
509 addPass(P: new LegalizerLegacy());
510 return false;
511}
512
513void WebAssemblyPassConfig::addPreRegBankSelect() {
514 if (getOptLevel() != CodeGenOptLevel::None) {
515 addPass(P: createWebAssemblyPostLegalizerCombinerLegacyPass());
516 }
517}
518
519bool WebAssemblyPassConfig::addRegBankSelect() {
520 addPass(P: new RegBankSelectLegacy());
521 return false;
522}
523
524bool WebAssemblyPassConfig::addGlobalInstructionSelect() {
525 addPass(P: new InstructionSelectLegacy(getOptLevel()));
526
527 // We insert only if ISelDAG won't insert these at a later point.
528 if (isGlobalISelAbortEnabled()) {
529 addPass(P: createWebAssemblyArgumentMoveLegacyPass());
530 addPass(P: createWebAssemblySetP2AlignOperandsLegacyPass());
531 addPass(P: createWebAssemblyFixBrTableDefaultsLegacyPass());
532 addPass(P: createWebAssemblyCleanCodeAfterTrapLegacyPass());
533 }
534
535 return false;
536}
537
538yaml::MachineFunctionInfo *
539WebAssemblyTargetMachine::createDefaultFuncInfoYAML() const {
540 return new yaml::WebAssemblyFunctionInfo();
541}
542
543yaml::MachineFunctionInfo *WebAssemblyTargetMachine::convertFuncInfoToYAML(
544 const MachineFunction &MF) const {
545 const auto *MFI = MF.getInfo<WebAssemblyFunctionInfo>();
546 return new yaml::WebAssemblyFunctionInfo(MF, *MFI);
547}
548
549bool WebAssemblyTargetMachine::parseMachineFunctionInfo(
550 const yaml::MachineFunctionInfo &MFI, PerFunctionMIParsingState &PFS,
551 SMDiagnostic &Error, SMRange &SourceRange) const {
552 const auto &YamlMFI = static_cast<const yaml::WebAssemblyFunctionInfo &>(MFI);
553 MachineFunction &MF = PFS.MF;
554 MF.getInfo<WebAssemblyFunctionInfo>()->initializeBaseYamlFields(MF, YamlMFI);
555 return false;
556}
557