11a82d4c0SDimitry Andric //===- WebAssemblyTargetMachine.cpp - Define TargetMachine for WebAssembly -==//
21a82d4c0SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61a82d4c0SDimitry Andric //
71a82d4c0SDimitry Andric //===----------------------------------------------------------------------===//
81a82d4c0SDimitry Andric ///
91a82d4c0SDimitry Andric /// \file
10eb11fae6SDimitry Andric /// This file defines the WebAssembly-specific subclass of TargetMachine.
111a82d4c0SDimitry Andric ///
121a82d4c0SDimitry Andric //===----------------------------------------------------------------------===//
131a82d4c0SDimitry Andric
141a82d4c0SDimitry Andric #include "WebAssemblyTargetMachine.h"
157ab83427SDimitry Andric #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
16e6d15924SDimitry Andric #include "TargetInfo/WebAssemblyTargetInfo.h"
177ab83427SDimitry Andric #include "WebAssembly.h"
187fa27ce4SDimitry Andric #include "WebAssemblyISelLowering.h"
19e6d15924SDimitry Andric #include "WebAssemblyMachineFunctionInfo.h"
201a82d4c0SDimitry Andric #include "WebAssemblyTargetObjectFile.h"
211a82d4c0SDimitry Andric #include "WebAssemblyTargetTransformInfo.h"
22b1c73532SDimitry Andric #include "WebAssemblyUtilities.h"
23e6d15924SDimitry Andric #include "llvm/CodeGen/MIRParser/MIParser.h"
241a82d4c0SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
251a82d4c0SDimitry Andric #include "llvm/CodeGen/Passes.h"
261a82d4c0SDimitry Andric #include "llvm/CodeGen/RegAllocRegistry.h"
2701095a5dSDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h"
281a82d4c0SDimitry Andric #include "llvm/IR/Function.h"
29145449b1SDimitry Andric #include "llvm/InitializePasses.h"
3077fc4c14SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
31c0981da4SDimitry Andric #include "llvm/MC/TargetRegistry.h"
321a82d4c0SDimitry Andric #include "llvm/Target/TargetOptions.h"
331a82d4c0SDimitry Andric #include "llvm/Transforms/Scalar.h"
34145449b1SDimitry Andric #include "llvm/Transforms/Scalar/LowerAtomicPass.h"
35eb11fae6SDimitry Andric #include "llvm/Transforms/Utils.h"
36e3b55780SDimitry Andric #include <optional>
371a82d4c0SDimitry Andric using namespace llvm;
381a82d4c0SDimitry Andric
391a82d4c0SDimitry Andric #define DEBUG_TYPE "wasm"
401a82d4c0SDimitry Andric
41cfca06d7SDimitry Andric // A command-line option to keep implicit locals
42cfca06d7SDimitry Andric // for the purpose of testing with lit/llc ONLY.
43cfca06d7SDimitry Andric // This produces output which is not valid WebAssembly, and is not supported
44cfca06d7SDimitry Andric // by assemblers/disassemblers and other MC based tools.
45cfca06d7SDimitry Andric static cl::opt<bool> WasmDisableExplicitLocals(
46cfca06d7SDimitry Andric "wasm-disable-explicit-locals", cl::Hidden,
47cfca06d7SDimitry Andric cl::desc("WebAssembly: output implicit locals in"
48cfca06d7SDimitry Andric " instruction output for test purposes only."),
49cfca06d7SDimitry Andric cl::init(false));
50cfca06d7SDimitry Andric
51b1c73532SDimitry Andric static cl::opt<bool> WasmDisableFixIrreducibleControlFlowPass(
52b1c73532SDimitry Andric "wasm-disable-fix-irreducible-control-flow-pass", cl::Hidden,
53b1c73532SDimitry Andric cl::desc("webassembly: disables the fix "
54b1c73532SDimitry Andric " irreducible control flow optimization pass"),
55b1c73532SDimitry Andric cl::init(false));
56b1c73532SDimitry Andric
LLVMInitializeWebAssemblyTarget()57706b4fc4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeWebAssemblyTarget() {
581a82d4c0SDimitry Andric // Register the target.
59b915e9e0SDimitry Andric RegisterTargetMachine<WebAssemblyTargetMachine> X(
60b915e9e0SDimitry Andric getTheWebAssemblyTarget32());
61b915e9e0SDimitry Andric RegisterTargetMachine<WebAssemblyTargetMachine> Y(
62b915e9e0SDimitry Andric getTheWebAssemblyTarget64());
63b915e9e0SDimitry Andric
64eb11fae6SDimitry Andric // Register backend passes
65eb11fae6SDimitry Andric auto &PR = *PassRegistry::getPassRegistry();
66eb11fae6SDimitry Andric initializeWebAssemblyAddMissingPrototypesPass(PR);
67eb11fae6SDimitry Andric initializeWebAssemblyLowerEmscriptenEHSjLjPass(PR);
68145449b1SDimitry Andric initializeLowerGlobalDtorsLegacyPassPass(PR);
69eb11fae6SDimitry Andric initializeFixFunctionBitcastsPass(PR);
70eb11fae6SDimitry Andric initializeOptimizeReturnedPass(PR);
71ac9a064cSDimitry Andric initializeWebAssemblyRefTypeMem2LocalPass(PR);
72eb11fae6SDimitry Andric initializeWebAssemblyArgumentMovePass(PR);
73eb11fae6SDimitry Andric initializeWebAssemblySetP2AlignOperandsPass(PR);
74eb11fae6SDimitry Andric initializeWebAssemblyReplacePhysRegsPass(PR);
75eb11fae6SDimitry Andric initializeWebAssemblyOptimizeLiveIntervalsPass(PR);
76d8e91e46SDimitry Andric initializeWebAssemblyMemIntrinsicResultsPass(PR);
77eb11fae6SDimitry Andric initializeWebAssemblyRegStackifyPass(PR);
78eb11fae6SDimitry Andric initializeWebAssemblyRegColoringPass(PR);
79344a3780SDimitry Andric initializeWebAssemblyNullifyDebugValueListsPass(PR);
80eb11fae6SDimitry Andric initializeWebAssemblyFixIrreducibleControlFlowPass(PR);
81eb11fae6SDimitry Andric initializeWebAssemblyLateEHPreparePass(PR);
82eb11fae6SDimitry Andric initializeWebAssemblyExceptionInfoPass(PR);
83eb11fae6SDimitry Andric initializeWebAssemblyCFGSortPass(PR);
84eb11fae6SDimitry Andric initializeWebAssemblyCFGStackifyPass(PR);
85e6d15924SDimitry Andric initializeWebAssemblyExplicitLocalsPass(PR);
86eb11fae6SDimitry Andric initializeWebAssemblyLowerBrUnlessPass(PR);
87eb11fae6SDimitry Andric initializeWebAssemblyRegNumberingPass(PR);
88cfca06d7SDimitry Andric initializeWebAssemblyDebugFixupPass(PR);
89eb11fae6SDimitry Andric initializeWebAssemblyPeepholePass(PR);
90344a3780SDimitry Andric initializeWebAssemblyMCLowerPrePassPass(PR);
91e3b55780SDimitry Andric initializeWebAssemblyLowerRefTypesIntPtrConvPass(PR);
92e3b55780SDimitry Andric initializeWebAssemblyFixBrTableDefaultsPass(PR);
93ac9a064cSDimitry Andric initializeWebAssemblyDAGToDAGISelLegacyPass(PR);
941a82d4c0SDimitry Andric }
951a82d4c0SDimitry Andric
961a82d4c0SDimitry Andric //===----------------------------------------------------------------------===//
971a82d4c0SDimitry Andric // WebAssembly Lowering public interface.
981a82d4c0SDimitry Andric //===----------------------------------------------------------------------===//
991a82d4c0SDimitry Andric
getEffectiveRelocModel(std::optional<Reloc::Model> RM,const Triple & TT)100e3b55780SDimitry Andric static Reloc::Model getEffectiveRelocModel(std::optional<Reloc::Model> RM,
101e6d15924SDimitry Andric const Triple &TT) {
102145449b1SDimitry Andric if (!RM) {
103d8e91e46SDimitry Andric // Default to static relocation model. This should always be more optimial
104d8e91e46SDimitry Andric // than PIC since the static linker can determine all global addresses and
105d8e91e46SDimitry Andric // assume direct function calls.
106d8e91e46SDimitry Andric return Reloc::Static;
107d8e91e46SDimitry Andric }
108e6d15924SDimitry Andric
10901095a5dSDimitry Andric return *RM;
11001095a5dSDimitry Andric }
11101095a5dSDimitry Andric
1121a82d4c0SDimitry Andric /// Create an WebAssembly architecture model.
1131a82d4c0SDimitry Andric ///
WebAssemblyTargetMachine(const Target & T,const Triple & TT,StringRef CPU,StringRef FS,const TargetOptions & Options,std::optional<Reloc::Model> RM,std::optional<CodeModel::Model> CM,CodeGenOptLevel OL,bool JIT)1141a82d4c0SDimitry Andric WebAssemblyTargetMachine::WebAssemblyTargetMachine(
1151a82d4c0SDimitry Andric const Target &T, const Triple &TT, StringRef CPU, StringRef FS,
116e3b55780SDimitry Andric const TargetOptions &Options, std::optional<Reloc::Model> RM,
117b1c73532SDimitry Andric std::optional<CodeModel::Model> CM, CodeGenOptLevel OL, bool JIT)
118344a3780SDimitry Andric : LLVMTargetMachine(
119344a3780SDimitry Andric T,
120344a3780SDimitry Andric TT.isArch64Bit()
121c0981da4SDimitry Andric ? (TT.isOSEmscripten() ? "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-"
122c0981da4SDimitry Andric "f128:64-n32:64-S128-ni:1:10:20"
123c0981da4SDimitry Andric : "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-"
124c0981da4SDimitry Andric "n32:64-S128-ni:1:10:20")
125c0981da4SDimitry Andric : (TT.isOSEmscripten() ? "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-"
126c0981da4SDimitry Andric "f128:64-n32:64-S128-ni:1:10:20"
127c0981da4SDimitry Andric : "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-"
128c0981da4SDimitry Andric "n32:64-S128-ni:1:10:20"),
129e6d15924SDimitry Andric TT, CPU, FS, Options, getEffectiveRelocModel(RM, TT),
130d8e91e46SDimitry Andric getEffectiveCodeModel(CM, CodeModel::Large), OL),
131ac9a064cSDimitry Andric TLOF(new WebAssemblyTargetObjectFile()),
132ac9a064cSDimitry Andric UsesMultivalueABI(Options.MCOptions.getABIName() == "experimental-mv") {
133b915e9e0SDimitry Andric // WebAssembly type-checks instructions, but a noreturn function with a return
134dd58ef01SDimitry Andric // type that doesn't match the context will cause a check failure. So we lower
135dd58ef01SDimitry Andric // LLVM 'unreachable' to ISD::TRAP and then lower that to WebAssembly's
136b915e9e0SDimitry Andric // 'unreachable' instructions which is meant for that case.
137dd58ef01SDimitry Andric this->Options.TrapUnreachable = true;
138b1c73532SDimitry Andric this->Options.NoTrapAfterNoreturn = false;
139dd58ef01SDimitry Andric
14071d5a254SDimitry Andric // WebAssembly treats each function as an independent unit. Force
14171d5a254SDimitry Andric // -ffunction-sections, effectively, so that we can emit them independently.
14271d5a254SDimitry Andric this->Options.FunctionSections = true;
14371d5a254SDimitry Andric this->Options.DataSections = true;
14471d5a254SDimitry Andric this->Options.UniqueSectionNames = true;
14571d5a254SDimitry Andric
1461a82d4c0SDimitry Andric initAsmInfo();
1471a82d4c0SDimitry Andric
14801095a5dSDimitry Andric // Note that we don't use setRequiresStructuredCFG(true). It disables
14901095a5dSDimitry Andric // optimizations than we're ok with, and want, such as critical edge
15001095a5dSDimitry Andric // splitting and tail merging.
1511a82d4c0SDimitry Andric }
1521a82d4c0SDimitry Andric
153e6d15924SDimitry Andric WebAssemblyTargetMachine::~WebAssemblyTargetMachine() = default; // anchor.
154e6d15924SDimitry Andric
getSubtargetImpl() const155b60736ecSDimitry Andric const WebAssemblySubtarget *WebAssemblyTargetMachine::getSubtargetImpl() const {
156b60736ecSDimitry Andric return getSubtargetImpl(std::string(getTargetCPU()),
157b60736ecSDimitry Andric std::string(getTargetFeatureString()));
158b60736ecSDimitry Andric }
159b60736ecSDimitry Andric
160e6d15924SDimitry Andric const WebAssemblySubtarget *
getSubtargetImpl(std::string CPU,std::string FS) const161e6d15924SDimitry Andric WebAssemblyTargetMachine::getSubtargetImpl(std::string CPU,
162e6d15924SDimitry Andric std::string FS) const {
163e6d15924SDimitry Andric auto &I = SubtargetMap[CPU + FS];
164e6d15924SDimitry Andric if (!I) {
1651d5ae102SDimitry Andric I = std::make_unique<WebAssemblySubtarget>(TargetTriple, CPU, FS, *this);
166e6d15924SDimitry Andric }
167e6d15924SDimitry Andric return I.get();
168e6d15924SDimitry Andric }
1691a82d4c0SDimitry Andric
1701a82d4c0SDimitry Andric const WebAssemblySubtarget *
getSubtargetImpl(const Function & F) const1711a82d4c0SDimitry Andric WebAssemblyTargetMachine::getSubtargetImpl(const Function &F) const {
1721a82d4c0SDimitry Andric Attribute CPUAttr = F.getFnAttribute("target-cpu");
1731a82d4c0SDimitry Andric Attribute FSAttr = F.getFnAttribute("target-features");
1741a82d4c0SDimitry Andric
175b60736ecSDimitry Andric std::string CPU =
176b60736ecSDimitry Andric CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;
177b60736ecSDimitry Andric std::string FS =
178b60736ecSDimitry Andric FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;
1791a82d4c0SDimitry Andric
1801a82d4c0SDimitry Andric // This needs to be done before we create a new subtarget since any
1811a82d4c0SDimitry Andric // creation will depend on the TM and the code generation flags on the
1821a82d4c0SDimitry Andric // function that reside in TargetOptions.
1831a82d4c0SDimitry Andric resetTargetOptions(F);
184e6d15924SDimitry Andric
185e6d15924SDimitry Andric return getSubtargetImpl(CPU, FS);
1861a82d4c0SDimitry Andric }
1871a82d4c0SDimitry Andric
1881a82d4c0SDimitry Andric namespace {
189e6d15924SDimitry Andric
190e6d15924SDimitry Andric class CoalesceFeaturesAndStripAtomics final : public ModulePass {
191e6d15924SDimitry Andric // Take the union of all features used in the module and use it for each
192e6d15924SDimitry Andric // function individually, since having multiple feature sets in one module
193e6d15924SDimitry Andric // currently does not make sense for WebAssembly. If atomics are not enabled,
194e6d15924SDimitry Andric // also strip atomic operations and thread local storage.
195eb11fae6SDimitry Andric static char ID;
196e6d15924SDimitry Andric WebAssemblyTargetMachine *WasmTM;
197eb11fae6SDimitry Andric
198eb11fae6SDimitry Andric public:
CoalesceFeaturesAndStripAtomics(WebAssemblyTargetMachine * WasmTM)199e6d15924SDimitry Andric CoalesceFeaturesAndStripAtomics(WebAssemblyTargetMachine *WasmTM)
200e6d15924SDimitry Andric : ModulePass(ID), WasmTM(WasmTM) {}
201e6d15924SDimitry Andric
runOnModule(Module & M)202eb11fae6SDimitry Andric bool runOnModule(Module &M) override {
203e6d15924SDimitry Andric FeatureBitset Features = coalesceFeatures(M);
204e6d15924SDimitry Andric
205efdccd83SDimitry Andric std::string FeatureStr = getFeatureString(Features);
206b60736ecSDimitry Andric WasmTM->setTargetFeatureString(FeatureStr);
207e6d15924SDimitry Andric for (auto &F : M)
208e6d15924SDimitry Andric replaceFeatures(F, FeatureStr);
209e6d15924SDimitry Andric
210e6d15924SDimitry Andric bool StrippedAtomics = false;
211e6d15924SDimitry Andric bool StrippedTLS = false;
212e6d15924SDimitry Andric
213145449b1SDimitry Andric if (!Features[WebAssembly::FeatureAtomics]) {
214e6d15924SDimitry Andric StrippedAtomics = stripAtomics(M);
215e6d15924SDimitry Andric StrippedTLS = stripThreadLocals(M);
216145449b1SDimitry Andric } else if (!Features[WebAssembly::FeatureBulkMemory]) {
217145449b1SDimitry Andric StrippedTLS |= stripThreadLocals(M);
218145449b1SDimitry Andric }
219e6d15924SDimitry Andric
220e6d15924SDimitry Andric if (StrippedAtomics && !StrippedTLS)
221e6d15924SDimitry Andric stripThreadLocals(M);
222e6d15924SDimitry Andric else if (StrippedTLS && !StrippedAtomics)
223e6d15924SDimitry Andric stripAtomics(M);
224e6d15924SDimitry Andric
225e6d15924SDimitry Andric recordFeatures(M, Features, StrippedAtomics || StrippedTLS);
226e6d15924SDimitry Andric
227e6d15924SDimitry Andric // Conservatively assume we have made some change
228eb11fae6SDimitry Andric return true;
229eb11fae6SDimitry Andric }
230e6d15924SDimitry Andric
231e6d15924SDimitry Andric private:
coalesceFeatures(const Module & M)232e6d15924SDimitry Andric FeatureBitset coalesceFeatures(const Module &M) {
233e6d15924SDimitry Andric FeatureBitset Features =
234e6d15924SDimitry Andric WasmTM
235cfca06d7SDimitry Andric ->getSubtargetImpl(std::string(WasmTM->getTargetCPU()),
236cfca06d7SDimitry Andric std::string(WasmTM->getTargetFeatureString()))
237e6d15924SDimitry Andric ->getFeatureBits();
238e6d15924SDimitry Andric for (auto &F : M)
239e6d15924SDimitry Andric Features |= WasmTM->getSubtargetImpl(F)->getFeatureBits();
240e6d15924SDimitry Andric return Features;
241e6d15924SDimitry Andric }
242e6d15924SDimitry Andric
getFeatureString(const FeatureBitset & Features)243efdccd83SDimitry Andric static std::string getFeatureString(const FeatureBitset &Features) {
244e6d15924SDimitry Andric std::string Ret;
245e6d15924SDimitry Andric for (const SubtargetFeatureKV &KV : WebAssemblyFeatureKV) {
246e6d15924SDimitry Andric if (Features[KV.Value])
247e6d15924SDimitry Andric Ret += (StringRef("+") + KV.Key + ",").str();
248efdccd83SDimitry Andric else
249efdccd83SDimitry Andric Ret += (StringRef("-") + KV.Key + ",").str();
250e6d15924SDimitry Andric }
251e6d15924SDimitry Andric return Ret;
252e6d15924SDimitry Andric }
253e6d15924SDimitry Andric
replaceFeatures(Function & F,const std::string & Features)254e6d15924SDimitry Andric void replaceFeatures(Function &F, const std::string &Features) {
255e6d15924SDimitry Andric F.removeFnAttr("target-features");
256e6d15924SDimitry Andric F.removeFnAttr("target-cpu");
257e6d15924SDimitry Andric F.addFnAttr("target-features", Features);
258e6d15924SDimitry Andric }
259e6d15924SDimitry Andric
stripAtomics(Module & M)260e6d15924SDimitry Andric bool stripAtomics(Module &M) {
261e6d15924SDimitry Andric // Detect whether any atomics will be lowered, since there is no way to tell
262e6d15924SDimitry Andric // whether the LowerAtomic pass lowers e.g. stores.
263e6d15924SDimitry Andric bool Stripped = false;
264e6d15924SDimitry Andric for (auto &F : M) {
265e6d15924SDimitry Andric for (auto &B : F) {
266e6d15924SDimitry Andric for (auto &I : B) {
267e6d15924SDimitry Andric if (I.isAtomic()) {
268e6d15924SDimitry Andric Stripped = true;
269e6d15924SDimitry Andric goto done;
270e6d15924SDimitry Andric }
271e6d15924SDimitry Andric }
272e6d15924SDimitry Andric }
273e6d15924SDimitry Andric }
274e6d15924SDimitry Andric
275e6d15924SDimitry Andric done:
276e6d15924SDimitry Andric if (!Stripped)
277e6d15924SDimitry Andric return false;
278e6d15924SDimitry Andric
279e6d15924SDimitry Andric LowerAtomicPass Lowerer;
280e6d15924SDimitry Andric FunctionAnalysisManager FAM;
281e6d15924SDimitry Andric for (auto &F : M)
282e6d15924SDimitry Andric Lowerer.run(F, FAM);
283e6d15924SDimitry Andric
284e6d15924SDimitry Andric return true;
285e6d15924SDimitry Andric }
286e6d15924SDimitry Andric
stripThreadLocals(Module & M)287e6d15924SDimitry Andric bool stripThreadLocals(Module &M) {
288e6d15924SDimitry Andric bool Stripped = false;
289e6d15924SDimitry Andric for (auto &GV : M.globals()) {
290b60736ecSDimitry Andric if (GV.isThreadLocal()) {
291ac9a064cSDimitry Andric // replace `@llvm.threadlocal.address.pX(GV)` with `GV`.
292ac9a064cSDimitry Andric for (Use &U : make_early_inc_range(GV.uses())) {
293ac9a064cSDimitry Andric if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(U.getUser())) {
294ac9a064cSDimitry Andric if (II->getIntrinsicID() == Intrinsic::threadlocal_address &&
295ac9a064cSDimitry Andric II->getArgOperand(0) == &GV) {
296ac9a064cSDimitry Andric II->replaceAllUsesWith(&GV);
297ac9a064cSDimitry Andric II->eraseFromParent();
298ac9a064cSDimitry Andric }
299ac9a064cSDimitry Andric }
300ac9a064cSDimitry Andric }
301ac9a064cSDimitry Andric
302e6d15924SDimitry Andric Stripped = true;
303b60736ecSDimitry Andric GV.setThreadLocal(false);
304e6d15924SDimitry Andric }
305e6d15924SDimitry Andric }
306e6d15924SDimitry Andric return Stripped;
307e6d15924SDimitry Andric }
308e6d15924SDimitry Andric
recordFeatures(Module & M,const FeatureBitset & Features,bool Stripped)309e6d15924SDimitry Andric void recordFeatures(Module &M, const FeatureBitset &Features, bool Stripped) {
310e6d15924SDimitry Andric for (const SubtargetFeatureKV &KV : WebAssemblyFeatureKV) {
311cfca06d7SDimitry Andric if (Features[KV.Value]) {
312cfca06d7SDimitry Andric // Mark features as used
313e6d15924SDimitry Andric std::string MDKey = (StringRef("wasm-feature-") + KV.Key).str();
314e6d15924SDimitry Andric M.addModuleFlag(Module::ModFlagBehavior::Error, MDKey,
315e6d15924SDimitry Andric wasm::WASM_FEATURE_PREFIX_USED);
316e6d15924SDimitry Andric }
317e6d15924SDimitry Andric }
318cfca06d7SDimitry Andric // Code compiled without atomics or bulk-memory may have had its atomics or
319cfca06d7SDimitry Andric // thread-local data lowered to nonatomic operations or non-thread-local
320cfca06d7SDimitry Andric // data. In that case, we mark the pseudo-feature "shared-mem" as disallowed
321cfca06d7SDimitry Andric // to tell the linker that it would be unsafe to allow this code ot be used
322cfca06d7SDimitry Andric // in a module with shared memory.
323cfca06d7SDimitry Andric if (Stripped) {
324cfca06d7SDimitry Andric M.addModuleFlag(Module::ModFlagBehavior::Error, "wasm-feature-shared-mem",
325cfca06d7SDimitry Andric wasm::WASM_FEATURE_PREFIX_DISALLOWED);
326cfca06d7SDimitry Andric }
327e6d15924SDimitry Andric }
328eb11fae6SDimitry Andric };
329e6d15924SDimitry Andric char CoalesceFeaturesAndStripAtomics::ID = 0;
330eb11fae6SDimitry Andric
3311a82d4c0SDimitry Andric /// WebAssembly Code Generator Pass Configuration Options.
3321a82d4c0SDimitry Andric class WebAssemblyPassConfig final : public TargetPassConfig {
3331a82d4c0SDimitry Andric public:
WebAssemblyPassConfig(WebAssemblyTargetMachine & TM,PassManagerBase & PM)334f382538dSDimitry Andric WebAssemblyPassConfig(WebAssemblyTargetMachine &TM, PassManagerBase &PM)
3351a82d4c0SDimitry Andric : TargetPassConfig(TM, PM) {}
3361a82d4c0SDimitry Andric
getWebAssemblyTargetMachine() const3371a82d4c0SDimitry Andric WebAssemblyTargetMachine &getWebAssemblyTargetMachine() const {
3381a82d4c0SDimitry Andric return getTM<WebAssemblyTargetMachine>();
3391a82d4c0SDimitry Andric }
3401a82d4c0SDimitry Andric
3411a82d4c0SDimitry Andric FunctionPass *createTargetRegisterAllocator(bool) override;
3421a82d4c0SDimitry Andric
3431a82d4c0SDimitry Andric void addIRPasses() override;
344145449b1SDimitry Andric void addISelPrepare() override;
3451a82d4c0SDimitry Andric bool addInstSelector() override;
346e3b55780SDimitry Andric void addOptimizedRegAlloc() override;
3471a82d4c0SDimitry Andric void addPostRegAlloc() override;
addGCPasses()34801095a5dSDimitry Andric bool addGCPasses() override { return false; }
3491a82d4c0SDimitry Andric void addPreEmitPass() override;
350c0981da4SDimitry Andric bool addPreISel() override;
351e6d15924SDimitry Andric
352e6d15924SDimitry Andric // No reg alloc
addRegAssignAndRewriteFast()353b60736ecSDimitry Andric bool addRegAssignAndRewriteFast() override { return false; }
354e6d15924SDimitry Andric
355e6d15924SDimitry Andric // No reg alloc
addRegAssignAndRewriteOptimized()356b60736ecSDimitry Andric bool addRegAssignAndRewriteOptimized() override { return false; }
3571a82d4c0SDimitry Andric };
3581a82d4c0SDimitry Andric } // end anonymous namespace
3591a82d4c0SDimitry Andric
createMachineFunctionInfo(BumpPtrAllocator & Allocator,const Function & F,const TargetSubtargetInfo * STI) const360e3b55780SDimitry Andric MachineFunctionInfo *WebAssemblyTargetMachine::createMachineFunctionInfo(
361e3b55780SDimitry Andric BumpPtrAllocator &Allocator, const Function &F,
362e3b55780SDimitry Andric const TargetSubtargetInfo *STI) const {
363e3b55780SDimitry Andric return WebAssemblyFunctionInfo::create<WebAssemblyFunctionInfo>(Allocator, F,
364e3b55780SDimitry Andric STI);
365e3b55780SDimitry Andric }
366e3b55780SDimitry Andric
367c7dac04cSDimitry Andric TargetTransformInfo
getTargetTransformInfo(const Function & F) const368145449b1SDimitry Andric WebAssemblyTargetMachine::getTargetTransformInfo(const Function &F) const {
3691a82d4c0SDimitry Andric return TargetTransformInfo(WebAssemblyTTIImpl(this, F));
3701a82d4c0SDimitry Andric }
3711a82d4c0SDimitry Andric
3721a82d4c0SDimitry Andric TargetPassConfig *
createPassConfig(PassManagerBase & PM)3731a82d4c0SDimitry Andric WebAssemblyTargetMachine::createPassConfig(PassManagerBase &PM) {
374f382538dSDimitry Andric return new WebAssemblyPassConfig(*this, PM);
3751a82d4c0SDimitry Andric }
3761a82d4c0SDimitry Andric
createTargetRegisterAllocator(bool)3771a82d4c0SDimitry Andric FunctionPass *WebAssemblyPassConfig::createTargetRegisterAllocator(bool) {
3781a82d4c0SDimitry Andric return nullptr; // No reg alloc
3791a82d4c0SDimitry Andric }
3801a82d4c0SDimitry Andric
38177fc4c14SDimitry Andric using WebAssembly::WasmEnableEH;
38277fc4c14SDimitry Andric using WebAssembly::WasmEnableEmEH;
38377fc4c14SDimitry Andric using WebAssembly::WasmEnableEmSjLj;
384ac9a064cSDimitry Andric using WebAssembly::WasmEnableExnref;
38577fc4c14SDimitry Andric using WebAssembly::WasmEnableSjLj;
38677fc4c14SDimitry Andric
basicCheckForEHAndSjLj(TargetMachine * TM)38777fc4c14SDimitry Andric static void basicCheckForEHAndSjLj(TargetMachine *TM) {
388ac9a064cSDimitry Andric
389ac9a064cSDimitry Andric // You can't enable two modes of EH at the same time
390ac9a064cSDimitry Andric if (WasmEnableEmEH && WasmEnableEH)
391ac9a064cSDimitry Andric report_fatal_error(
392ac9a064cSDimitry Andric "-enable-emscripten-cxx-exceptions not allowed with -wasm-enable-eh");
393ac9a064cSDimitry Andric // You can't enable two modes of SjLj at the same time
394ac9a064cSDimitry Andric if (WasmEnableEmSjLj && WasmEnableSjLj)
395ac9a064cSDimitry Andric report_fatal_error(
396ac9a064cSDimitry Andric "-enable-emscripten-sjlj not allowed with -wasm-enable-sjlj");
397ac9a064cSDimitry Andric // You can't mix Emscripten EH with Wasm SjLj.
398ac9a064cSDimitry Andric if (WasmEnableEmEH && WasmEnableSjLj)
399ac9a064cSDimitry Andric report_fatal_error(
400ac9a064cSDimitry Andric "-enable-emscripten-cxx-exceptions not allowed with -wasm-enable-sjlj");
401ac9a064cSDimitry Andric if (WasmEnableExnref && !WasmEnableEH)
402ac9a064cSDimitry Andric report_fatal_error(
403ac9a064cSDimitry Andric "-wasm-enable-exnref should be used with -wasm-enable-eh");
404ac9a064cSDimitry Andric
405ac9a064cSDimitry Andric // Here we make sure TargetOptions.ExceptionModel is the same as
40677fc4c14SDimitry Andric // MCAsmInfo.ExceptionsType. Normally these have to be the same, because clang
40777fc4c14SDimitry Andric // stores the exception model info in LangOptions, which is later transferred
40877fc4c14SDimitry Andric // to TargetOptions and MCAsmInfo. But when clang compiles bitcode directly,
40977fc4c14SDimitry Andric // clang's LangOptions is not used and thus the exception model info is not
41077fc4c14SDimitry Andric // correctly transferred to TargetOptions and MCAsmInfo, so we make sure we
411ac9a064cSDimitry Andric // have the correct exception model in WebAssemblyMCAsmInfo constructor. But
412ac9a064cSDimitry Andric // in this case TargetOptions is still not updated, so we make sure they are
413ac9a064cSDimitry Andric // the same.
41477fc4c14SDimitry Andric TM->Options.ExceptionModel = TM->getMCAsmInfo()->getExceptionHandlingType();
41577fc4c14SDimitry Andric
416f65dcba8SDimitry Andric // Basic Correctness checking related to -exception-model
417c0981da4SDimitry Andric if (TM->Options.ExceptionModel != ExceptionHandling::None &&
418c0981da4SDimitry Andric TM->Options.ExceptionModel != ExceptionHandling::Wasm)
419c0981da4SDimitry Andric report_fatal_error("-exception-model should be either 'none' or 'wasm'");
420c0981da4SDimitry Andric if (WasmEnableEmEH && TM->Options.ExceptionModel == ExceptionHandling::Wasm)
421c0981da4SDimitry Andric report_fatal_error("-exception-model=wasm not allowed with "
422c0981da4SDimitry Andric "-enable-emscripten-cxx-exceptions");
423c0981da4SDimitry Andric if (WasmEnableEH && TM->Options.ExceptionModel != ExceptionHandling::Wasm)
424c0981da4SDimitry Andric report_fatal_error(
425c0981da4SDimitry Andric "-wasm-enable-eh only allowed with -exception-model=wasm");
426c0981da4SDimitry Andric if (WasmEnableSjLj && TM->Options.ExceptionModel != ExceptionHandling::Wasm)
427c0981da4SDimitry Andric report_fatal_error(
428c0981da4SDimitry Andric "-wasm-enable-sjlj only allowed with -exception-model=wasm");
429c0981da4SDimitry Andric if ((!WasmEnableEH && !WasmEnableSjLj) &&
430c0981da4SDimitry Andric TM->Options.ExceptionModel == ExceptionHandling::Wasm)
431c0981da4SDimitry Andric report_fatal_error(
432c0981da4SDimitry Andric "-exception-model=wasm only allowed with at least one of "
433ac9a064cSDimitry Andric "-wasm-enable-eh or -wasm-enable-sjlj");
434c0981da4SDimitry Andric
435c0981da4SDimitry Andric // Currently it is allowed to mix Wasm EH with Emscripten SjLj as an interim
436c0981da4SDimitry Andric // measure, but some code will error out at compile time in this combination.
437c0981da4SDimitry Andric // See WebAssemblyLowerEmscriptenEHSjLj pass for details.
438c0981da4SDimitry Andric }
439c0981da4SDimitry Andric
4401a82d4c0SDimitry Andric //===----------------------------------------------------------------------===//
4411a82d4c0SDimitry Andric // The following functions are called from lib/CodeGen/Passes.cpp to modify
4421a82d4c0SDimitry Andric // the CodeGen pass sequence.
4431a82d4c0SDimitry Andric //===----------------------------------------------------------------------===//
4441a82d4c0SDimitry Andric
addIRPasses()4451a82d4c0SDimitry Andric void WebAssemblyPassConfig::addIRPasses() {
446eb11fae6SDimitry Andric // Add signatures to prototype-less function declarations
447eb11fae6SDimitry Andric addPass(createWebAssemblyAddMissingPrototypes());
4481a82d4c0SDimitry Andric
449e3b55780SDimitry Andric // Lower .llvm.global_dtors into .llvm.global_ctors with __cxa_atexit calls.
450145449b1SDimitry Andric addPass(createLowerGlobalDtorsLegacyPass());
451044eb2f6SDimitry Andric
452909545a8SDimitry Andric // Fix function bitcasts, as WebAssembly requires caller and callee signatures
453909545a8SDimitry Andric // to match.
454909545a8SDimitry Andric addPass(createWebAssemblyFixFunctionBitcasts());
455909545a8SDimitry Andric
456dd58ef01SDimitry Andric // Optimize "returned" function attributes.
457b1c73532SDimitry Andric if (getOptLevel() != CodeGenOptLevel::None)
458dd58ef01SDimitry Andric addPass(createWebAssemblyOptimizeReturned());
459dd58ef01SDimitry Andric
460f65dcba8SDimitry Andric basicCheckForEHAndSjLj(TM);
461c0981da4SDimitry Andric
462b915e9e0SDimitry Andric // If exception handling is not enabled and setjmp/longjmp handling is
463b915e9e0SDimitry Andric // enabled, we lower invokes into calls and delete unreachable landingpad
464b915e9e0SDimitry Andric // blocks. Lowering invokes when there is no EH support is done in
465c0981da4SDimitry Andric // TargetPassConfig::addPassesToHandleExceptions, but that runs after these IR
466c0981da4SDimitry Andric // passes and Emscripten SjLj handling expects all invokes to be lowered
467c0981da4SDimitry Andric // before.
468c0981da4SDimitry Andric if (!WasmEnableEmEH && !WasmEnableEH) {
469b915e9e0SDimitry Andric addPass(createLowerInvokePass());
470b915e9e0SDimitry Andric // The lower invoke pass may create unreachable code. Remove it in order not
471b915e9e0SDimitry Andric // to process dead blocks in setjmp/longjmp handling.
472b915e9e0SDimitry Andric addPass(createUnreachableBlockEliminationPass());
473b915e9e0SDimitry Andric }
474b915e9e0SDimitry Andric
475c0981da4SDimitry Andric // Handle exceptions and setjmp/longjmp if enabled. Unlike Wasm EH preparation
476c0981da4SDimitry Andric // done in WasmEHPrepare pass, Wasm SjLj preparation shares libraries and
477c0981da4SDimitry Andric // transformation algorithms with Emscripten SjLj, so we run
478c0981da4SDimitry Andric // LowerEmscriptenEHSjLj pass also when Wasm SjLj is enabled.
479c0981da4SDimitry Andric if (WasmEnableEmEH || WasmEnableEmSjLj || WasmEnableSjLj)
480c0981da4SDimitry Andric addPass(createWebAssemblyLowerEmscriptenEHSjLj());
481b915e9e0SDimitry Andric
482e6d15924SDimitry Andric // Expand indirectbr instructions to switches.
483e6d15924SDimitry Andric addPass(createIndirectBrExpandPass());
484e6d15924SDimitry Andric
4851a82d4c0SDimitry Andric TargetPassConfig::addIRPasses();
4861a82d4c0SDimitry Andric }
4871a82d4c0SDimitry Andric
addISelPrepare()488145449b1SDimitry Andric void WebAssemblyPassConfig::addISelPrepare() {
489ac9a064cSDimitry Andric // We need to move reference type allocas to WASM_ADDRESS_SPACE_VAR so that
490ac9a064cSDimitry Andric // loads and stores are promoted to local.gets/local.sets.
491ac9a064cSDimitry Andric addPass(createWebAssemblyRefTypeMem2Local());
492145449b1SDimitry Andric // Lower atomics and TLS if necessary
493145449b1SDimitry Andric addPass(new CoalesceFeaturesAndStripAtomics(&getWebAssemblyTargetMachine()));
494145449b1SDimitry Andric
495145449b1SDimitry Andric // This is a no-op if atomics are not used in the module
496ac9a064cSDimitry Andric addPass(createAtomicExpandLegacyPass());
497145449b1SDimitry Andric
498145449b1SDimitry Andric TargetPassConfig::addISelPrepare();
499145449b1SDimitry Andric }
500145449b1SDimitry Andric
addInstSelector()5011a82d4c0SDimitry Andric bool WebAssemblyPassConfig::addInstSelector() {
502dd58ef01SDimitry Andric (void)TargetPassConfig::addInstSelector();
5031a82d4c0SDimitry Andric addPass(
5041a82d4c0SDimitry Andric createWebAssemblyISelDag(getWebAssemblyTargetMachine(), getOptLevel()));
505dd58ef01SDimitry Andric // Run the argument-move pass immediately after the ScheduleDAG scheduler
506dd58ef01SDimitry Andric // so that we can fix up the ARGUMENT instructions before anything else
507dd58ef01SDimitry Andric // sees them in the wrong place.
508dd58ef01SDimitry Andric addPass(createWebAssemblyArgumentMove());
50901095a5dSDimitry Andric // Set the p2align operands. This information is present during ISel, however
51001095a5dSDimitry Andric // it's inconvenient to collect. Collect it now, and update the immediate
51101095a5dSDimitry Andric // operands.
51201095a5dSDimitry Andric addPass(createWebAssemblySetP2AlignOperands());
513cfca06d7SDimitry Andric
514cfca06d7SDimitry Andric // Eliminate range checks and add default targets to br_table instructions.
515cfca06d7SDimitry Andric addPass(createWebAssemblyFixBrTableDefaults());
516cfca06d7SDimitry Andric
517ac9a064cSDimitry Andric // unreachable is terminator, non-terminator instruction after it is not
518ac9a064cSDimitry Andric // allowed.
519ac9a064cSDimitry Andric addPass(createWebAssemblyCleanCodeAfterTrap());
520ac9a064cSDimitry Andric
5211a82d4c0SDimitry Andric return false;
5221a82d4c0SDimitry Andric }
5231a82d4c0SDimitry Andric
addOptimizedRegAlloc()524e3b55780SDimitry Andric void WebAssemblyPassConfig::addOptimizedRegAlloc() {
525e3b55780SDimitry Andric // Currently RegisterCoalesce degrades wasm debug info quality by a
526e3b55780SDimitry Andric // significant margin. As a quick fix, disable this for -O1, which is often
527e3b55780SDimitry Andric // used for debugging large applications. Disabling this increases code size
528e3b55780SDimitry Andric // of Emscripten core benchmarks by ~5%, which is acceptable for -O1, which is
529e3b55780SDimitry Andric // usually not used for production builds.
530e3b55780SDimitry Andric // TODO Investigate why RegisterCoalesce degrades debug info quality and fix
531e3b55780SDimitry Andric // it properly
532b1c73532SDimitry Andric if (getOptLevel() == CodeGenOptLevel::Less)
533e3b55780SDimitry Andric disablePass(&RegisterCoalescerID);
534e3b55780SDimitry Andric TargetPassConfig::addOptimizedRegAlloc();
535e3b55780SDimitry Andric }
536e3b55780SDimitry Andric
addPostRegAlloc()537dd58ef01SDimitry Andric void WebAssemblyPassConfig::addPostRegAlloc() {
538dd58ef01SDimitry Andric // TODO: The following CodeGen passes don't currently support code containing
539dd58ef01SDimitry Andric // virtual registers. Consider removing their restrictions and re-enabling
540dd58ef01SDimitry Andric // them.
54101095a5dSDimitry Andric
542b915e9e0SDimitry Andric // These functions all require the NoVRegs property.
543e3b55780SDimitry Andric disablePass(&MachineLateInstrsCleanupID);
544dd58ef01SDimitry Andric disablePass(&MachineCopyPropagationID);
545eb11fae6SDimitry Andric disablePass(&PostRAMachineSinkingID);
54601095a5dSDimitry Andric disablePass(&PostRASchedulerID);
54701095a5dSDimitry Andric disablePass(&FuncletLayoutID);
54801095a5dSDimitry Andric disablePass(&StackMapLivenessID);
54901095a5dSDimitry Andric disablePass(&PatchableFunctionID);
550eb11fae6SDimitry Andric disablePass(&ShrinkWrapID);
551dd58ef01SDimitry Andric
552e6d15924SDimitry Andric // This pass hurts code size for wasm because it can generate irreducible
553e6d15924SDimitry Andric // control flow.
554e6d15924SDimitry Andric disablePass(&MachineBlockPlacementID);
555e6d15924SDimitry Andric
556dd58ef01SDimitry Andric TargetPassConfig::addPostRegAlloc();
557dd58ef01SDimitry Andric }
558dd58ef01SDimitry Andric
addPreEmitPass()559dd58ef01SDimitry Andric void WebAssemblyPassConfig::addPreEmitPass() {
560dd58ef01SDimitry Andric TargetPassConfig::addPreEmitPass();
561dd58ef01SDimitry Andric
562344a3780SDimitry Andric // Nullify DBG_VALUE_LISTs that we cannot handle.
563344a3780SDimitry Andric addPass(createWebAssemblyNullifyDebugValueLists());
564344a3780SDimitry Andric
565d8e91e46SDimitry Andric // Eliminate multiple-entry loops.
566b1c73532SDimitry Andric if (!WasmDisableFixIrreducibleControlFlowPass)
567d8e91e46SDimitry Andric addPass(createWebAssemblyFixIrreducibleControlFlow());
568d8e91e46SDimitry Andric
569d8e91e46SDimitry Andric // Do various transformations for exception handling.
570e6d15924SDimitry Andric // Every CFG-changing optimizations should come before this.
571b60736ecSDimitry Andric if (TM->Options.ExceptionModel == ExceptionHandling::Wasm)
572d8e91e46SDimitry Andric addPass(createWebAssemblyLateEHPrepare());
573d8e91e46SDimitry Andric
574e6d15924SDimitry Andric // Now that we have a prologue and epilogue and all frame indices are
575e6d15924SDimitry Andric // rewritten, eliminate SP and FP. This allows them to be stackified,
576e6d15924SDimitry Andric // colored, and numbered with the rest of the registers.
577e6d15924SDimitry Andric addPass(createWebAssemblyReplacePhysRegs());
578e6d15924SDimitry Andric
579e6d15924SDimitry Andric // Preparations and optimizations related to register stackification.
580b1c73532SDimitry Andric if (getOptLevel() != CodeGenOptLevel::None) {
58101095a5dSDimitry Andric // Depend on LiveIntervals and perform some optimizations on it.
58201095a5dSDimitry Andric addPass(createWebAssemblyOptimizeLiveIntervals());
58301095a5dSDimitry Andric
584d8e91e46SDimitry Andric // Prepare memory intrinsic calls for register stackifying.
585d8e91e46SDimitry Andric addPass(createWebAssemblyMemIntrinsicResults());
58601095a5dSDimitry Andric
587b915e9e0SDimitry Andric // Mark registers as representing wasm's value stack. This is a key
58801095a5dSDimitry Andric // code-compression technique in WebAssembly. We run this pass (and
589d8e91e46SDimitry Andric // MemIntrinsicResults above) very late, so that it sees as much code as
590d8e91e46SDimitry Andric // possible, including code emitted by PEI and expanded by late tail
591d8e91e46SDimitry Andric // duplication.
59201095a5dSDimitry Andric addPass(createWebAssemblyRegStackify());
59301095a5dSDimitry Andric
59401095a5dSDimitry Andric // Run the register coloring pass to reduce the total number of registers.
59501095a5dSDimitry Andric // This runs after stackification so that it doesn't consider registers
59601095a5dSDimitry Andric // that become stackified.
59701095a5dSDimitry Andric addPass(createWebAssemblyRegColoring());
59801095a5dSDimitry Andric }
59901095a5dSDimitry Andric
60071d5a254SDimitry Andric // Sort the blocks of the CFG into topological order, a prerequisite for
60171d5a254SDimitry Andric // BLOCK and LOOP markers.
60271d5a254SDimitry Andric addPass(createWebAssemblyCFGSort());
60301095a5dSDimitry Andric
60471d5a254SDimitry Andric // Insert BLOCK and LOOP markers.
605dd58ef01SDimitry Andric addPass(createWebAssemblyCFGStackify());
606dd58ef01SDimitry Andric
607e6d15924SDimitry Andric // Insert explicit local.get and local.set operators.
608cfca06d7SDimitry Andric if (!WasmDisableExplicitLocals)
609e6d15924SDimitry Andric addPass(createWebAssemblyExplicitLocals());
610e6d15924SDimitry Andric
611dd58ef01SDimitry Andric // Lower br_unless into br_if.
612dd58ef01SDimitry Andric addPass(createWebAssemblyLowerBrUnless());
613dd58ef01SDimitry Andric
61401095a5dSDimitry Andric // Perform the very last peephole optimizations on the code.
615b1c73532SDimitry Andric if (getOptLevel() != CodeGenOptLevel::None)
61601095a5dSDimitry Andric addPass(createWebAssemblyPeephole());
61701095a5dSDimitry Andric
618dd58ef01SDimitry Andric // Create a mapping from LLVM CodeGen virtual registers to wasm registers.
619dd58ef01SDimitry Andric addPass(createWebAssemblyRegNumbering());
620cfca06d7SDimitry Andric
621cfca06d7SDimitry Andric // Fix debug_values whose defs have been stackified.
622cfca06d7SDimitry Andric if (!WasmDisableExplicitLocals)
623cfca06d7SDimitry Andric addPass(createWebAssemblyDebugFixup());
624344a3780SDimitry Andric
625344a3780SDimitry Andric // Collect information to prepare for MC lowering / asm printing.
626344a3780SDimitry Andric addPass(createWebAssemblyMCLowerPrePass());
627dd58ef01SDimitry Andric }
628e6d15924SDimitry Andric
addPreISel()629c0981da4SDimitry Andric bool WebAssemblyPassConfig::addPreISel() {
630c0981da4SDimitry Andric TargetPassConfig::addPreISel();
631c0981da4SDimitry Andric addPass(createWebAssemblyLowerRefTypesIntPtrConv());
632c0981da4SDimitry Andric return false;
633c0981da4SDimitry Andric }
634c0981da4SDimitry Andric
635e6d15924SDimitry Andric yaml::MachineFunctionInfo *
createDefaultFuncInfoYAML() const636e6d15924SDimitry Andric WebAssemblyTargetMachine::createDefaultFuncInfoYAML() const {
637e6d15924SDimitry Andric return new yaml::WebAssemblyFunctionInfo();
638e6d15924SDimitry Andric }
639e6d15924SDimitry Andric
convertFuncInfoToYAML(const MachineFunction & MF) const640e6d15924SDimitry Andric yaml::MachineFunctionInfo *WebAssemblyTargetMachine::convertFuncInfoToYAML(
641e6d15924SDimitry Andric const MachineFunction &MF) const {
642e6d15924SDimitry Andric const auto *MFI = MF.getInfo<WebAssemblyFunctionInfo>();
643e3b55780SDimitry Andric return new yaml::WebAssemblyFunctionInfo(MF, *MFI);
644e6d15924SDimitry Andric }
645e6d15924SDimitry Andric
parseMachineFunctionInfo(const yaml::MachineFunctionInfo & MFI,PerFunctionMIParsingState & PFS,SMDiagnostic & Error,SMRange & SourceRange) const646e6d15924SDimitry Andric bool WebAssemblyTargetMachine::parseMachineFunctionInfo(
647e6d15924SDimitry Andric const yaml::MachineFunctionInfo &MFI, PerFunctionMIParsingState &PFS,
648e6d15924SDimitry Andric SMDiagnostic &Error, SMRange &SourceRange) const {
649145449b1SDimitry Andric const auto &YamlMFI = static_cast<const yaml::WebAssemblyFunctionInfo &>(MFI);
650e6d15924SDimitry Andric MachineFunction &MF = PFS.MF;
651e3b55780SDimitry Andric MF.getInfo<WebAssemblyFunctionInfo>()->initializeBaseYamlFields(MF, YamlMFI);
652e6d15924SDimitry Andric return false;
653e6d15924SDimitry Andric }
654