1 //===-- WebAssemblyUtilities.cpp - WebAssembly Utility Functions ----------===//
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
7 //===----------------------------------------------------------------------===//
10 /// This file implements several utility functions for WebAssembly.
12 //===----------------------------------------------------------------------===//
14 #include "WebAssemblyUtilities.h"
15 #include "WebAssemblyMachineFunctionInfo.h"
16 #include "llvm/CodeGen/MachineInstr.h"
17 #include "llvm/CodeGen/MachineLoopInfo.h"
20 const char *const WebAssembly::ClangCallTerminateFn
= "__clang_call_terminate";
21 const char *const WebAssembly::CxaBeginCatchFn
= "__cxa_begin_catch";
22 const char *const WebAssembly::CxaRethrowFn
= "__cxa_rethrow";
23 const char *const WebAssembly::StdTerminateFn
= "_ZSt9terminatev";
24 const char *const WebAssembly::PersonalityWrapperFn
=
25 "_Unwind_Wasm_CallPersonality";
27 bool WebAssembly::isArgument(const MachineInstr
&MI
) {
28 switch (MI
.getOpcode()) {
29 case WebAssembly::ARGUMENT_i32
:
30 case WebAssembly::ARGUMENT_i32_S
:
31 case WebAssembly::ARGUMENT_i64
:
32 case WebAssembly::ARGUMENT_i64_S
:
33 case WebAssembly::ARGUMENT_f32
:
34 case WebAssembly::ARGUMENT_f32_S
:
35 case WebAssembly::ARGUMENT_f64
:
36 case WebAssembly::ARGUMENT_f64_S
:
37 case WebAssembly::ARGUMENT_v16i8
:
38 case WebAssembly::ARGUMENT_v16i8_S
:
39 case WebAssembly::ARGUMENT_v8i16
:
40 case WebAssembly::ARGUMENT_v8i16_S
:
41 case WebAssembly::ARGUMENT_v4i32
:
42 case WebAssembly::ARGUMENT_v4i32_S
:
43 case WebAssembly::ARGUMENT_v2i64
:
44 case WebAssembly::ARGUMENT_v2i64_S
:
45 case WebAssembly::ARGUMENT_v4f32
:
46 case WebAssembly::ARGUMENT_v4f32_S
:
47 case WebAssembly::ARGUMENT_v2f64
:
48 case WebAssembly::ARGUMENT_v2f64_S
:
55 bool WebAssembly::isCopy(const MachineInstr
&MI
) {
56 switch (MI
.getOpcode()) {
57 case WebAssembly::COPY_I32
:
58 case WebAssembly::COPY_I32_S
:
59 case WebAssembly::COPY_I64
:
60 case WebAssembly::COPY_I64_S
:
61 case WebAssembly::COPY_F32
:
62 case WebAssembly::COPY_F32_S
:
63 case WebAssembly::COPY_F64
:
64 case WebAssembly::COPY_F64_S
:
65 case WebAssembly::COPY_V128
:
66 case WebAssembly::COPY_V128_S
:
73 bool WebAssembly::isTee(const MachineInstr
&MI
) {
74 switch (MI
.getOpcode()) {
75 case WebAssembly::TEE_I32
:
76 case WebAssembly::TEE_I32_S
:
77 case WebAssembly::TEE_I64
:
78 case WebAssembly::TEE_I64_S
:
79 case WebAssembly::TEE_F32
:
80 case WebAssembly::TEE_F32_S
:
81 case WebAssembly::TEE_F64
:
82 case WebAssembly::TEE_F64_S
:
83 case WebAssembly::TEE_V128
:
84 case WebAssembly::TEE_V128_S
:
91 /// Test whether MI is a child of some other node in an expression tree.
92 bool WebAssembly::isChild(const MachineInstr
&MI
,
93 const WebAssemblyFunctionInfo
&MFI
) {
94 if (MI
.getNumOperands() == 0)
96 const MachineOperand
&MO
= MI
.getOperand(0);
97 if (!MO
.isReg() || MO
.isImplicit() || !MO
.isDef())
99 unsigned Reg
= MO
.getReg();
100 return TargetRegisterInfo::isVirtualRegister(Reg
) &&
101 MFI
.isVRegStackified(Reg
);
104 bool WebAssembly::isCallDirect(const MachineInstr
&MI
) {
105 switch (MI
.getOpcode()) {
106 case WebAssembly::CALL_VOID
:
107 case WebAssembly::CALL_VOID_S
:
108 case WebAssembly::CALL_I32
:
109 case WebAssembly::CALL_I32_S
:
110 case WebAssembly::CALL_I64
:
111 case WebAssembly::CALL_I64_S
:
112 case WebAssembly::CALL_F32
:
113 case WebAssembly::CALL_F32_S
:
114 case WebAssembly::CALL_F64
:
115 case WebAssembly::CALL_F64_S
:
116 case WebAssembly::CALL_v16i8
:
117 case WebAssembly::CALL_v16i8_S
:
118 case WebAssembly::CALL_v8i16
:
119 case WebAssembly::CALL_v8i16_S
:
120 case WebAssembly::CALL_v4i32
:
121 case WebAssembly::CALL_v4i32_S
:
122 case WebAssembly::CALL_v2i64
:
123 case WebAssembly::CALL_v2i64_S
:
124 case WebAssembly::CALL_v4f32
:
125 case WebAssembly::CALL_v4f32_S
:
126 case WebAssembly::CALL_v2f64
:
127 case WebAssembly::CALL_v2f64_S
:
128 case WebAssembly::CALL_EXCEPT_REF
:
129 case WebAssembly::CALL_EXCEPT_REF_S
:
136 bool WebAssembly::isCallIndirect(const MachineInstr
&MI
) {
137 switch (MI
.getOpcode()) {
138 case WebAssembly::CALL_INDIRECT_VOID
:
139 case WebAssembly::CALL_INDIRECT_VOID_S
:
140 case WebAssembly::CALL_INDIRECT_I32
:
141 case WebAssembly::CALL_INDIRECT_I32_S
:
142 case WebAssembly::CALL_INDIRECT_I64
:
143 case WebAssembly::CALL_INDIRECT_I64_S
:
144 case WebAssembly::CALL_INDIRECT_F32
:
145 case WebAssembly::CALL_INDIRECT_F32_S
:
146 case WebAssembly::CALL_INDIRECT_F64
:
147 case WebAssembly::CALL_INDIRECT_F64_S
:
148 case WebAssembly::CALL_INDIRECT_v16i8
:
149 case WebAssembly::CALL_INDIRECT_v16i8_S
:
150 case WebAssembly::CALL_INDIRECT_v8i16
:
151 case WebAssembly::CALL_INDIRECT_v8i16_S
:
152 case WebAssembly::CALL_INDIRECT_v4i32
:
153 case WebAssembly::CALL_INDIRECT_v4i32_S
:
154 case WebAssembly::CALL_INDIRECT_v2i64
:
155 case WebAssembly::CALL_INDIRECT_v2i64_S
:
156 case WebAssembly::CALL_INDIRECT_v4f32
:
157 case WebAssembly::CALL_INDIRECT_v4f32_S
:
158 case WebAssembly::CALL_INDIRECT_v2f64
:
159 case WebAssembly::CALL_INDIRECT_v2f64_S
:
160 case WebAssembly::CALL_INDIRECT_EXCEPT_REF
:
161 case WebAssembly::CALL_INDIRECT_EXCEPT_REF_S
:
168 unsigned WebAssembly::getCalleeOpNo(const MachineInstr
&MI
) {
169 switch (MI
.getOpcode()) {
170 case WebAssembly::CALL_VOID
:
171 case WebAssembly::CALL_VOID_S
:
172 case WebAssembly::CALL_INDIRECT_VOID
:
173 case WebAssembly::CALL_INDIRECT_VOID_S
:
175 case WebAssembly::CALL_I32
:
176 case WebAssembly::CALL_I32_S
:
177 case WebAssembly::CALL_I64
:
178 case WebAssembly::CALL_I64_S
:
179 case WebAssembly::CALL_F32
:
180 case WebAssembly::CALL_F32_S
:
181 case WebAssembly::CALL_F64
:
182 case WebAssembly::CALL_F64_S
:
183 case WebAssembly::CALL_v16i8
:
184 case WebAssembly::CALL_v16i8_S
:
185 case WebAssembly::CALL_v8i16
:
186 case WebAssembly::CALL_v8i16_S
:
187 case WebAssembly::CALL_v4i32
:
188 case WebAssembly::CALL_v4i32_S
:
189 case WebAssembly::CALL_v2i64
:
190 case WebAssembly::CALL_v2i64_S
:
191 case WebAssembly::CALL_v4f32
:
192 case WebAssembly::CALL_v4f32_S
:
193 case WebAssembly::CALL_v2f64
:
194 case WebAssembly::CALL_v2f64_S
:
195 case WebAssembly::CALL_EXCEPT_REF
:
196 case WebAssembly::CALL_EXCEPT_REF_S
:
197 case WebAssembly::CALL_INDIRECT_I32
:
198 case WebAssembly::CALL_INDIRECT_I32_S
:
199 case WebAssembly::CALL_INDIRECT_I64
:
200 case WebAssembly::CALL_INDIRECT_I64_S
:
201 case WebAssembly::CALL_INDIRECT_F32
:
202 case WebAssembly::CALL_INDIRECT_F32_S
:
203 case WebAssembly::CALL_INDIRECT_F64
:
204 case WebAssembly::CALL_INDIRECT_F64_S
:
205 case WebAssembly::CALL_INDIRECT_v16i8
:
206 case WebAssembly::CALL_INDIRECT_v16i8_S
:
207 case WebAssembly::CALL_INDIRECT_v8i16
:
208 case WebAssembly::CALL_INDIRECT_v8i16_S
:
209 case WebAssembly::CALL_INDIRECT_v4i32
:
210 case WebAssembly::CALL_INDIRECT_v4i32_S
:
211 case WebAssembly::CALL_INDIRECT_v2i64
:
212 case WebAssembly::CALL_INDIRECT_v2i64_S
:
213 case WebAssembly::CALL_INDIRECT_v4f32
:
214 case WebAssembly::CALL_INDIRECT_v4f32_S
:
215 case WebAssembly::CALL_INDIRECT_v2f64
:
216 case WebAssembly::CALL_INDIRECT_v2f64_S
:
217 case WebAssembly::CALL_INDIRECT_EXCEPT_REF
:
218 case WebAssembly::CALL_INDIRECT_EXCEPT_REF_S
:
221 llvm_unreachable("Not a call instruction");
225 bool WebAssembly::isMarker(const MachineInstr
&MI
) {
226 switch (MI
.getOpcode()) {
227 case WebAssembly::BLOCK
:
228 case WebAssembly::BLOCK_S
:
229 case WebAssembly::END_BLOCK
:
230 case WebAssembly::END_BLOCK_S
:
231 case WebAssembly::LOOP
:
232 case WebAssembly::LOOP_S
:
233 case WebAssembly::END_LOOP
:
234 case WebAssembly::END_LOOP_S
:
235 case WebAssembly::TRY
:
236 case WebAssembly::TRY_S
:
237 case WebAssembly::END_TRY
:
238 case WebAssembly::END_TRY_S
:
245 bool WebAssembly::mayThrow(const MachineInstr
&MI
) {
246 switch (MI
.getOpcode()) {
247 case WebAssembly::THROW
:
248 case WebAssembly::THROW_S
:
249 case WebAssembly::RETHROW
:
250 case WebAssembly::RETHROW_S
:
253 if (isCallIndirect(MI
))
258 const MachineOperand
&MO
= MI
.getOperand(getCalleeOpNo(MI
));
259 assert(MO
.isGlobal());
260 const auto *F
= dyn_cast
<Function
>(MO
.getGlobal());
263 if (F
->doesNotThrow())
265 // These functions never throw
266 if (F
->getName() == CxaBeginCatchFn
|| F
->getName() == PersonalityWrapperFn
||
267 F
->getName() == ClangCallTerminateFn
|| F
->getName() == StdTerminateFn
)