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// Function names in libc++abi and libunwind
22const char *const WebAssembly::CxaBeginCatchFn = "__cxa_begin_catch";
23const char *const WebAssembly::CxaRethrowFn = "__cxa_rethrow";
24const char *const WebAssembly::StdTerminateFn = "_ZSt9terminatev";
26 "_Unwind_Wasm_CallPersonality";
27
28/// Test whether MI is a child of some other node in an expression tree.
30 const WebAssemblyFunctionInfo &MFI) {
31 if (MI.getNumOperands() == 0)
32 return false;
33 const MachineOperand &MO = MI.getOperand(0);
34 if (!MO.isReg() || MO.isImplicit() || !MO.isDef())
35 return false;
36 Register Reg = MO.getReg();
37 return Reg.isVirtual() && MFI.isVRegStackified(Reg);
38}
39
41 switch (MI.getOpcode()) {
42 case WebAssembly::THROW:
43 case WebAssembly::THROW_S:
44 case WebAssembly::RETHROW:
45 case WebAssembly::RETHROW_S:
46 return true;
47 }
48 if (isCallIndirect(MI.getOpcode()))
49 return true;
50 if (!MI.isCall())
51 return false;
52
53 const MachineOperand &MO = getCalleeOp(MI);
54 assert(MO.isGlobal() || MO.isSymbol());
55
56 if (MO.isSymbol()) {
57 // Some intrinsics are lowered to calls to external symbols, which are then
58 // lowered to calls to library functions. Most of libcalls don't throw, but
59 // we only list some of them here now.
60 // TODO Consider adding 'nounwind' info in TargetLowering::CallLoweringInfo
61 // instead for more accurate info.
62 const char *Name = MO.getSymbolName();
63 if (strcmp(Name, "memcpy") == 0 || strcmp(Name, "memmove") == 0 ||
64 strcmp(Name, "memset") == 0)
65 return false;
66 return true;
67 }
68
69 const auto *F = dyn_cast<Function>(MO.getGlobal());
70 if (!F)
71 return true;
72 if (F->doesNotThrow())
73 return false;
74 // These functions never throw
75 if (F->getName() == CxaBeginCatchFn || F->getName() == PersonalityWrapperFn ||
76 F->getName() == StdTerminateFn)
77 return false;
78
79 // TODO Can we exclude call instructions that are marked as 'nounwind' in the
80 // original LLVm IR? (Even when the callee may throw)
81 return true;
82}
83
85 switch (MI.getOpcode()) {
86 case WebAssembly::CALL:
87 case WebAssembly::CALL_S:
88 case WebAssembly::RET_CALL:
89 case WebAssembly::RET_CALL_S:
90 return MI.getOperand(MI.getNumExplicitDefs());
91 case WebAssembly::CALL_INDIRECT:
92 case WebAssembly::CALL_INDIRECT_S:
93 case WebAssembly::RET_CALL_INDIRECT:
94 case WebAssembly::RET_CALL_INDIRECT_S:
95 return MI.getOperand(MI.getNumExplicitOperands() - 1);
96 default:
97 llvm_unreachable("Not a call instruction");
98 }
99}
100
102 MCContext &Ctx, const WebAssemblySubtarget *Subtarget) {
103 StringRef Name = "__indirect_function_table";
104 MCSymbolWasm *Sym = cast_or_null<MCSymbolWasm>(Ctx.lookupSymbol(Name));
105 if (Sym) {
106 if (!Sym->isFunctionTable())
107 Ctx.reportError(SMLoc(), "symbol is not a wasm funcref table");
108 } else {
109 Sym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(Name));
110 Sym->setFunctionTable();
111 // The default function table is synthesized by the linker.
112 Sym->setUndefined();
113 }
114 // MVP object files can't have symtab entries for tables.
115 if (!(Subtarget && Subtarget->hasReferenceTypes()))
116 Sym->setOmitFromLinkingSection();
117 return Sym;
118}
119
121 MCContext &Ctx, const WebAssemblySubtarget *Subtarget) {
122 StringRef Name = "__funcref_call_table";
123 MCSymbolWasm *Sym = cast_or_null<MCSymbolWasm>(Ctx.lookupSymbol(Name));
124 if (Sym) {
125 if (!Sym->isFunctionTable())
126 Ctx.reportError(SMLoc(), "symbol is not a wasm funcref table");
127 } else {
128 Sym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(Name));
129
130 // Setting Weak ensure only one table is left after linking when multiple
131 // modules define the table.
132 Sym->setWeak(true);
133
134 wasm::WasmLimits Limits = {0, 1, 1};
135 wasm::WasmTableType TableType = {wasm::WASM_TYPE_FUNCREF, Limits};
137 Sym->setTableType(TableType);
138 }
139 // MVP object files can't have symtab entries for tables.
140 if (!(Subtarget && Subtarget->hasReferenceTypes()))
141 Sym->setOmitFromLinkingSection();
142 return Sym;
143}
144
145// Find a catch instruction from an EH pad.
147 assert(EHPad->isEHPad());
148 auto Pos = EHPad->begin();
149 // Skip any label or debug instructions. Also skip 'end' marker instructions
150 // that may exist after marker placement in CFGStackify.
151 while (Pos != EHPad->end() &&
152 (Pos->isLabel() || Pos->isDebugInstr() || isMarker(Pos->getOpcode())))
153 Pos++;
154 if (Pos != EHPad->end() && WebAssembly::isCatch(Pos->getOpcode()))
155 return &*Pos;
156 return nullptr;
157}
158
160 assert(RC != nullptr);
161 switch (RC->getID()) {
162 case WebAssembly::I32RegClassID:
163 return WebAssembly::COPY_I32;
164 case WebAssembly::I64RegClassID:
165 return WebAssembly::COPY_I64;
166 case WebAssembly::F32RegClassID:
167 return WebAssembly::COPY_F32;
168 case WebAssembly::F64RegClassID:
169 return WebAssembly::COPY_F64;
170 case WebAssembly::V128RegClassID:
171 return WebAssembly::COPY_V128;
172 case WebAssembly::FUNCREFRegClassID:
173 return WebAssembly::COPY_FUNCREF;
174 case WebAssembly::EXTERNREFRegClassID:
175 return WebAssembly::COPY_EXTERNREF;
176 default:
177 llvm_unreachable("Unexpected register class");
178 }
179}
std::string Name
Symbol * Sym
Definition: ELF_riscv.cpp:463
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:1049
MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
Definition: MCContext.cpp:201
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.
const char *const PersonalityWrapperFn
bool mayThrow(const MachineInstr &MI)
@ 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