LLVM 17.0.0git
WebAssemblyUtilities.cpp
Go to the documentation of this file.
1//===-- WebAssemblyUtilities.cpp - WebAssembly Utility Functions ----------===//
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 implements several utility functions for WebAssembly.
11///
12//===----------------------------------------------------------------------===//
13
18#include "llvm/MC/MCContext.h"
19using namespace llvm;
20
21// Exception handling & setjmp-longjmp handling related options. These are
22// defined here to be shared between WebAssembly and its subdirectories.
23
24// Emscripten's asm.js-style exception handling
26 "enable-emscripten-cxx-exceptions",
27 cl::desc("WebAssembly Emscripten-style exception handling"),
28 cl::init(false));
29// Emscripten's asm.js-style setjmp/longjmp handling
31 "enable-emscripten-sjlj",
32 cl::desc("WebAssembly Emscripten-style setjmp/longjmp handling"),
33 cl::init(false));
34// Exception handling using wasm EH instructions
36 WebAssembly::WasmEnableEH("wasm-enable-eh",
37 cl::desc("WebAssembly exception handling"),
38 cl::init(false));
39// setjmp/longjmp handling using wasm EH instrutions
41 WebAssembly::WasmEnableSjLj("wasm-enable-sjlj",
42 cl::desc("WebAssembly setjmp/longjmp handling"),
43 cl::init(false));
44
45// Function names in libc++abi and libunwind
46const char *const WebAssembly::CxaBeginCatchFn = "__cxa_begin_catch";
47const char *const WebAssembly::CxaRethrowFn = "__cxa_rethrow";
48const char *const WebAssembly::StdTerminateFn = "_ZSt9terminatev";
50 "_Unwind_Wasm_CallPersonality";
51
52/// Test whether MI is a child of some other node in an expression tree.
54 const WebAssemblyFunctionInfo &MFI) {
55 if (MI.getNumOperands() == 0)
56 return false;
57 const MachineOperand &MO = MI.getOperand(0);
58 if (!MO.isReg() || MO.isImplicit() || !MO.isDef())
59 return false;
60 Register Reg = MO.getReg();
61 return Reg.isVirtual() && MFI.isVRegStackified(Reg);
62}
63
65 switch (MI.getOpcode()) {
66 case WebAssembly::THROW:
67 case WebAssembly::THROW_S:
68 case WebAssembly::RETHROW:
69 case WebAssembly::RETHROW_S:
70 return true;
71 }
72 if (isCallIndirect(MI.getOpcode()))
73 return true;
74 if (!MI.isCall())
75 return false;
76
77 const MachineOperand &MO = getCalleeOp(MI);
78 assert(MO.isGlobal() || MO.isSymbol());
79
80 if (MO.isSymbol()) {
81 // Some intrinsics are lowered to calls to external symbols, which are then
82 // lowered to calls to library functions. Most of libcalls don't throw, but
83 // we only list some of them here now.
84 // TODO Consider adding 'nounwind' info in TargetLowering::CallLoweringInfo
85 // instead for more accurate info.
86 const char *Name = MO.getSymbolName();
87 if (strcmp(Name, "memcpy") == 0 || strcmp(Name, "memmove") == 0 ||
88 strcmp(Name, "memset") == 0)
89 return false;
90 return true;
91 }
92
93 const auto *F = dyn_cast<Function>(MO.getGlobal());
94 if (!F)
95 return true;
96 if (F->doesNotThrow())
97 return false;
98 // These functions never throw
99 if (F->getName() == CxaBeginCatchFn || F->getName() == PersonalityWrapperFn ||
100 F->getName() == StdTerminateFn)
101 return false;
102
103 // TODO Can we exclude call instructions that are marked as 'nounwind' in the
104 // original LLVm IR? (Even when the callee may throw)
105 return true;
106}
107
109 switch (MI.getOpcode()) {
110 case WebAssembly::CALL:
111 case WebAssembly::CALL_S:
112 case WebAssembly::RET_CALL:
113 case WebAssembly::RET_CALL_S:
114 return MI.getOperand(MI.getNumExplicitDefs());
115 case WebAssembly::CALL_INDIRECT:
116 case WebAssembly::CALL_INDIRECT_S:
117 case WebAssembly::RET_CALL_INDIRECT:
118 case WebAssembly::RET_CALL_INDIRECT_S:
119 return MI.getOperand(MI.getNumExplicitOperands() - 1);
120 default:
121 llvm_unreachable("Not a call instruction");
122 }
123}
124
126 MCContext &Ctx, const WebAssemblySubtarget *Subtarget) {
127 StringRef Name = "__indirect_function_table";
128 MCSymbolWasm *Sym = cast_or_null<MCSymbolWasm>(Ctx.lookupSymbol(Name));
129 if (Sym) {
130 if (!Sym->isFunctionTable())
131 Ctx.reportError(SMLoc(), "symbol is not a wasm funcref table");
132 } else {
133 Sym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(Name));
134 Sym->setFunctionTable();
135 // The default function table is synthesized by the linker.
136 Sym->setUndefined();
137 }
138 // MVP object files can't have symtab entries for tables.
139 if (!(Subtarget && Subtarget->hasReferenceTypes()))
141 return Sym;
142}
143
145 MCContext &Ctx, const WebAssemblySubtarget *Subtarget) {
146 StringRef Name = "__funcref_call_table";
147 MCSymbolWasm *Sym = cast_or_null<MCSymbolWasm>(Ctx.lookupSymbol(Name));
148 if (Sym) {
149 if (!Sym->isFunctionTable())
150 Ctx.reportError(SMLoc(), "symbol is not a wasm funcref table");
151 } else {
152 Sym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(Name));
153
154 // Setting Weak ensure only one table is left after linking when multiple
155 // modules define the table.
156 Sym->setWeak(true);
157
158 wasm::WasmLimits Limits = {0, 1, 1};
159 wasm::WasmTableType TableType = {wasm::WASM_TYPE_FUNCREF, Limits};
161 Sym->setTableType(TableType);
162 }
163 // MVP object files can't have symtab entries for tables.
164 if (!(Subtarget && Subtarget->hasReferenceTypes()))
166 return Sym;
167}
168
169// Find a catch instruction from an EH pad.
171 assert(EHPad->isEHPad());
172 auto Pos = EHPad->begin();
173 // Skip any label or debug instructions. Also skip 'end' marker instructions
174 // that may exist after marker placement in CFGStackify.
175 while (Pos != EHPad->end() &&
176 (Pos->isLabel() || Pos->isDebugInstr() || isMarker(Pos->getOpcode())))
177 Pos++;
178 if (Pos != EHPad->end() && WebAssembly::isCatch(Pos->getOpcode()))
179 return &*Pos;
180 return nullptr;
181}
182
184 assert(RC != nullptr);
185 switch (RC->getID()) {
186 case WebAssembly::I32RegClassID:
187 return WebAssembly::COPY_I32;
188 case WebAssembly::I64RegClassID:
189 return WebAssembly::COPY_I64;
190 case WebAssembly::F32RegClassID:
191 return WebAssembly::COPY_F32;
192 case WebAssembly::F64RegClassID:
193 return WebAssembly::COPY_F64;
194 case WebAssembly::V128RegClassID:
195 return WebAssembly::COPY_V128;
196 case WebAssembly::FUNCREFRegClassID:
197 return WebAssembly::COPY_FUNCREF;
198 case WebAssembly::EXTERNREFRegClassID:
199 return WebAssembly::COPY_EXTERNREF;
200 default:
201 llvm_unreachable("Unexpected register class");
202 }
203}
std::string Name
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition: MD5.cpp:55
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file declares WebAssembly-specific per-machine-function information.
This file contains the declaration of the WebAssembly-specific utility functions.
Context object for machine code objects.
Definition: MCContext.h:76
MCSymbol * lookupSymbol(const Twine &Name) const
Get the symbol for Name, or null.
Definition: MCContext.cpp:359
void reportError(SMLoc L, const Twine &Msg)
Definition: MCContext.cpp:1055
MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
Definition: MCContext.cpp:201
void setTableType(wasm::WasmTableType TT)
Definition: MCSymbolWasm.h:142
bool isFunctionTable() const
Definition: MCSymbolWasm.h:113
void setWeak(bool isWeak)
Definition: MCSymbolWasm.h:75
void setType(wasm::WasmSymbolType type)
Definition: MCSymbolWasm.h:53
void setOmitFromLinkingSection()
Definition: MCSymbolWasm.h:87
void setUndefined()
Mark the symbol as undefined.
Definition: MCSymbol.h:279
bool isEHPad() const
Returns true if the block is a landing pad.
Representation of each machine instruction.
Definition: MachineInstr.h:68
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
bool isImplicit() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isSymbol() const
isSymbol - Tests if this is a MO_ExternalSymbol operand.
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
const char * getSymbolName() const
Register getReg() const
getReg - Returns the register number.
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
Represents a location in source code.
Definition: SMLoc.h:23
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
unsigned getID() const
Return the register class ID number.
This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
const char *const StdTerminateFn
const char *const CxaBeginCatchFn
bool isChild(const MachineInstr &MI, const WebAssemblyFunctionInfo &MFI)
Test whether MI is a child of some other node in an expression tree.
bool isCallIndirect(unsigned Opc)
const char *const CxaRethrowFn
MCSymbolWasm * getOrCreateFunctionTableSymbol(MCContext &Ctx, const WebAssemblySubtarget *Subtarget)
Returns the __indirect_function_table, for use in call_indirect and in function bitcasts.
bool isMarker(unsigned Opc)
unsigned getCopyOpcodeForRegClass(const TargetRegisterClass *RC)
Returns the appropriate copy opcode for the given register class.
const MachineOperand & getCalleeOp(const MachineInstr &MI)
Returns the operand number of a callee, assuming the argument is a call instruction.
MachineInstr * findCatch(MachineBasicBlock *EHPad)
Find a catch instruction from an EH pad.
bool isCatch(unsigned Opc)
MCSymbolWasm * getOrCreateFuncrefCallTableSymbol(MCContext &Ctx, const WebAssemblySubtarget *Subtarget)
Returns the __funcref_call_table, for use in funcref calls when lowered to table.set + call_indirect.
cl::opt< bool > WasmEnableEH
cl::opt< bool > WasmEnableSjLj
const char *const PersonalityWrapperFn
cl::opt< bool > WasmEnableEmEH
cl::opt< bool > WasmEnableEmSjLj
bool mayThrow(const MachineInstr &MI)
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:445
@ WASM_SYMBOL_TYPE_TABLE
Definition: Wasm.h:388
@ WASM_TYPE_FUNCREF
Definition: Wasm.h:266
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18