LLVM  8.0.1
WebAssemblyUtilities.cpp
Go to the documentation of this file.
1 //===-- WebAssemblyUtilities.cpp - WebAssembly Utility Functions ----------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// This file implements several utility functions for WebAssembly.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #include "WebAssemblyUtilities.h"
19 using namespace llvm;
20 
21 const char *const WebAssembly::ClangCallTerminateFn = "__clang_call_terminate";
22 const char *const WebAssembly::CxaBeginCatchFn = "__cxa_begin_catch";
23 const char *const WebAssembly::CxaRethrowFn = "__cxa_rethrow";
24 const char *const WebAssembly::StdTerminateFn = "_ZSt9terminatev";
26  "_Unwind_Wasm_CallPersonality";
27 
29  switch (MI.getOpcode()) {
30  case WebAssembly::ARGUMENT_i32:
31  case WebAssembly::ARGUMENT_i32_S:
32  case WebAssembly::ARGUMENT_i64:
33  case WebAssembly::ARGUMENT_i64_S:
34  case WebAssembly::ARGUMENT_f32:
35  case WebAssembly::ARGUMENT_f32_S:
36  case WebAssembly::ARGUMENT_f64:
37  case WebAssembly::ARGUMENT_f64_S:
38  case WebAssembly::ARGUMENT_v16i8:
39  case WebAssembly::ARGUMENT_v16i8_S:
40  case WebAssembly::ARGUMENT_v8i16:
41  case WebAssembly::ARGUMENT_v8i16_S:
42  case WebAssembly::ARGUMENT_v4i32:
43  case WebAssembly::ARGUMENT_v4i32_S:
44  case WebAssembly::ARGUMENT_v2i64:
45  case WebAssembly::ARGUMENT_v2i64_S:
46  case WebAssembly::ARGUMENT_v4f32:
47  case WebAssembly::ARGUMENT_v4f32_S:
48  case WebAssembly::ARGUMENT_v2f64:
49  case WebAssembly::ARGUMENT_v2f64_S:
50  return true;
51  default:
52  return false;
53  }
54 }
55 
57  switch (MI.getOpcode()) {
58  case WebAssembly::COPY_I32:
59  case WebAssembly::COPY_I32_S:
60  case WebAssembly::COPY_I64:
61  case WebAssembly::COPY_I64_S:
62  case WebAssembly::COPY_F32:
63  case WebAssembly::COPY_F32_S:
64  case WebAssembly::COPY_F64:
65  case WebAssembly::COPY_F64_S:
66  case WebAssembly::COPY_V128:
67  case WebAssembly::COPY_V128_S:
68  return true;
69  default:
70  return false;
71  }
72 }
73 
75  switch (MI.getOpcode()) {
76  case WebAssembly::TEE_I32:
77  case WebAssembly::TEE_I32_S:
78  case WebAssembly::TEE_I64:
79  case WebAssembly::TEE_I64_S:
80  case WebAssembly::TEE_F32:
81  case WebAssembly::TEE_F32_S:
82  case WebAssembly::TEE_F64:
83  case WebAssembly::TEE_F64_S:
84  case WebAssembly::TEE_V128:
85  case WebAssembly::TEE_V128_S:
86  return true;
87  default:
88  return false;
89  }
90 }
91 
92 /// Test whether MI is a child of some other node in an expression tree.
94  const WebAssemblyFunctionInfo &MFI) {
95  if (MI.getNumOperands() == 0)
96  return false;
97  const MachineOperand &MO = MI.getOperand(0);
98  if (!MO.isReg() || MO.isImplicit() || !MO.isDef())
99  return false;
100  unsigned Reg = MO.getReg();
102  MFI.isVRegStackified(Reg);
103 }
104 
106  switch (MI.getOpcode()) {
107  case WebAssembly::CALL_VOID:
108  case WebAssembly::CALL_VOID_S:
109  case WebAssembly::CALL_I32:
110  case WebAssembly::CALL_I32_S:
111  case WebAssembly::CALL_I64:
112  case WebAssembly::CALL_I64_S:
113  case WebAssembly::CALL_F32:
114  case WebAssembly::CALL_F32_S:
115  case WebAssembly::CALL_F64:
116  case WebAssembly::CALL_F64_S:
117  case WebAssembly::CALL_v16i8:
118  case WebAssembly::CALL_v16i8_S:
119  case WebAssembly::CALL_v8i16:
120  case WebAssembly::CALL_v8i16_S:
121  case WebAssembly::CALL_v4i32:
122  case WebAssembly::CALL_v4i32_S:
123  case WebAssembly::CALL_v2i64:
124  case WebAssembly::CALL_v2i64_S:
125  case WebAssembly::CALL_v4f32:
126  case WebAssembly::CALL_v4f32_S:
127  case WebAssembly::CALL_v2f64:
128  case WebAssembly::CALL_v2f64_S:
129  case WebAssembly::CALL_EXCEPT_REF:
130  case WebAssembly::CALL_EXCEPT_REF_S:
131  return true;
132  default:
133  return false;
134  }
135 }
136 
138  switch (MI.getOpcode()) {
139  case WebAssembly::CALL_INDIRECT_VOID:
140  case WebAssembly::CALL_INDIRECT_VOID_S:
141  case WebAssembly::CALL_INDIRECT_I32:
142  case WebAssembly::CALL_INDIRECT_I32_S:
143  case WebAssembly::CALL_INDIRECT_I64:
144  case WebAssembly::CALL_INDIRECT_I64_S:
145  case WebAssembly::CALL_INDIRECT_F32:
146  case WebAssembly::CALL_INDIRECT_F32_S:
147  case WebAssembly::CALL_INDIRECT_F64:
148  case WebAssembly::CALL_INDIRECT_F64_S:
149  case WebAssembly::CALL_INDIRECT_v16i8:
150  case WebAssembly::CALL_INDIRECT_v16i8_S:
151  case WebAssembly::CALL_INDIRECT_v8i16:
152  case WebAssembly::CALL_INDIRECT_v8i16_S:
153  case WebAssembly::CALL_INDIRECT_v4i32:
154  case WebAssembly::CALL_INDIRECT_v4i32_S:
155  case WebAssembly::CALL_INDIRECT_v2i64:
156  case WebAssembly::CALL_INDIRECT_v2i64_S:
157  case WebAssembly::CALL_INDIRECT_v4f32:
158  case WebAssembly::CALL_INDIRECT_v4f32_S:
159  case WebAssembly::CALL_INDIRECT_v2f64:
160  case WebAssembly::CALL_INDIRECT_v2f64_S:
161  case WebAssembly::CALL_INDIRECT_EXCEPT_REF:
162  case WebAssembly::CALL_INDIRECT_EXCEPT_REF_S:
163  return true;
164  default:
165  return false;
166  }
167 }
168 
170  switch (MI.getOpcode()) {
171  case WebAssembly::CALL_VOID:
172  case WebAssembly::CALL_VOID_S:
173  case WebAssembly::CALL_INDIRECT_VOID:
174  case WebAssembly::CALL_INDIRECT_VOID_S:
175  return 0;
176  case WebAssembly::CALL_I32:
177  case WebAssembly::CALL_I32_S:
178  case WebAssembly::CALL_I64:
179  case WebAssembly::CALL_I64_S:
180  case WebAssembly::CALL_F32:
181  case WebAssembly::CALL_F32_S:
182  case WebAssembly::CALL_F64:
183  case WebAssembly::CALL_F64_S:
184  case WebAssembly::CALL_v16i8:
185  case WebAssembly::CALL_v16i8_S:
186  case WebAssembly::CALL_v8i16:
187  case WebAssembly::CALL_v8i16_S:
188  case WebAssembly::CALL_v4i32:
189  case WebAssembly::CALL_v4i32_S:
190  case WebAssembly::CALL_v2i64:
191  case WebAssembly::CALL_v2i64_S:
192  case WebAssembly::CALL_v4f32:
193  case WebAssembly::CALL_v4f32_S:
194  case WebAssembly::CALL_v2f64:
195  case WebAssembly::CALL_v2f64_S:
196  case WebAssembly::CALL_EXCEPT_REF:
197  case WebAssembly::CALL_EXCEPT_REF_S:
198  case WebAssembly::CALL_INDIRECT_I32:
199  case WebAssembly::CALL_INDIRECT_I32_S:
200  case WebAssembly::CALL_INDIRECT_I64:
201  case WebAssembly::CALL_INDIRECT_I64_S:
202  case WebAssembly::CALL_INDIRECT_F32:
203  case WebAssembly::CALL_INDIRECT_F32_S:
204  case WebAssembly::CALL_INDIRECT_F64:
205  case WebAssembly::CALL_INDIRECT_F64_S:
206  case WebAssembly::CALL_INDIRECT_v16i8:
207  case WebAssembly::CALL_INDIRECT_v16i8_S:
208  case WebAssembly::CALL_INDIRECT_v8i16:
209  case WebAssembly::CALL_INDIRECT_v8i16_S:
210  case WebAssembly::CALL_INDIRECT_v4i32:
211  case WebAssembly::CALL_INDIRECT_v4i32_S:
212  case WebAssembly::CALL_INDIRECT_v2i64:
213  case WebAssembly::CALL_INDIRECT_v2i64_S:
214  case WebAssembly::CALL_INDIRECT_v4f32:
215  case WebAssembly::CALL_INDIRECT_v4f32_S:
216  case WebAssembly::CALL_INDIRECT_v2f64:
217  case WebAssembly::CALL_INDIRECT_v2f64_S:
218  case WebAssembly::CALL_INDIRECT_EXCEPT_REF:
219  case WebAssembly::CALL_INDIRECT_EXCEPT_REF_S:
220  return 1;
221  default:
222  llvm_unreachable("Not a call instruction");
223  }
224 }
225 
227  switch (MI.getOpcode()) {
228  case WebAssembly::BLOCK:
229  case WebAssembly::BLOCK_S:
231  case WebAssembly::END_BLOCK_S:
232  case WebAssembly::LOOP:
233  case WebAssembly::LOOP_S:
234  case WebAssembly::END_LOOP:
235  case WebAssembly::END_LOOP_S:
236  case WebAssembly::TRY:
237  case WebAssembly::TRY_S:
238  case WebAssembly::END_TRY:
239  case WebAssembly::END_TRY_S:
240  return true;
241  default:
242  return false;
243  }
244 }
245 
247  switch (MI.getOpcode()) {
248  case WebAssembly::THROW_I32:
249  case WebAssembly::THROW_I32_S:
250  case WebAssembly::THROW_I64:
251  case WebAssembly::THROW_I64_S:
252  return true;
253  default:
254  return false;
255  }
256 }
257 
259  switch (MI.getOpcode()) {
260  case WebAssembly::RETHROW:
261  case WebAssembly::RETHROW_S:
262  case WebAssembly::RETHROW_TO_CALLER:
263  case WebAssembly::RETHROW_TO_CALLER_S:
264  return true;
265  default:
266  return false;
267  }
268 }
269 
271  switch (MI.getOpcode()) {
272  case WebAssembly::CATCH_I32:
273  case WebAssembly::CATCH_I32_S:
274  case WebAssembly::CATCH_I64:
275  case WebAssembly::CATCH_I64_S:
276  case WebAssembly::CATCH_ALL:
277  case WebAssembly::CATCH_ALL_S:
278  return true;
279  default:
280  return false;
281  }
282 }
283 
285  switch (MI.getOpcode()) {
286  case WebAssembly::THROW_I32:
287  case WebAssembly::THROW_I32_S:
288  case WebAssembly::THROW_I64:
289  case WebAssembly::THROW_I64_S:
290  case WebAssembly::RETHROW:
291  case WebAssembly::RETHROW_S:
292  return true;
293  }
294  if (isCallIndirect(MI))
295  return true;
296  if (!MI.isCall())
297  return false;
298 
299  const MachineOperand &MO = MI.getOperand(getCalleeOpNo(MI));
300  assert(MO.isGlobal());
301  const auto *F = dyn_cast<Function>(MO.getGlobal());
302  if (!F)
303  return true;
304  if (F->doesNotThrow())
305  return false;
306  // These functions never throw
307  if (F->getName() == CxaBeginCatchFn || F->getName() == PersonalityWrapperFn ||
308  F->getName() == ClangCallTerminateFn || F->getName() == StdTerminateFn)
309  return false;
310  return true;
311 }
312 
314  if (!MBB.isEHPad())
315  return false;
316  bool SeenCatch = false;
317  for (auto &MI : MBB) {
318  if (MI.getOpcode() == WebAssembly::CATCH_I32 ||
319  MI.getOpcode() == WebAssembly::CATCH_I64 ||
320  MI.getOpcode() == WebAssembly::CATCH_I32_S ||
321  MI.getOpcode() == WebAssembly::CATCH_I64_S)
322  SeenCatch = true;
323  if (SeenCatch && MI.isCall()) {
324  const MachineOperand &CalleeOp = MI.getOperand(getCalleeOpNo(MI));
325  if (CalleeOp.isGlobal() &&
326  CalleeOp.getGlobal()->getName() == ClangCallTerminateFn)
327  return true;
328  }
329  }
330  return false;
331 }
332 
334  if (!MBB.isEHPad())
335  return false;
336  bool SeenCatchAll = false;
337  for (auto &MI : MBB) {
338  if (MI.getOpcode() == WebAssembly::CATCH_ALL ||
339  MI.getOpcode() == WebAssembly::CATCH_ALL_S)
340  SeenCatchAll = true;
341  if (SeenCatchAll && MI.isCall()) {
342  const MachineOperand &CalleeOp = MI.getOperand(getCalleeOpNo(MI));
343  if (CalleeOp.isGlobal() &&
344  CalleeOp.getGlobal()->getName() == StdTerminateFn)
345  return true;
346  }
347  }
348  return false;
349 }
bool isCall(QueryType Type=AnyInBundle) const
Definition: MachineInstr.h:633
This class represents lattice values for constants.
Definition: AllocatorList.h:24
bool mayThrow(const MachineInstr &MI)
unsigned getReg() const
getReg - Returns the register number.
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
unsigned Reg
F(f)
unsigned getNumOperands() const
Retuns the total number of operands.
Definition: MachineInstr.h:412
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:409
const char *const CxaBeginCatchFn
const char *const StdTerminateFn
bool isThrow(const MachineInstr &MI)
bool isCopy(const MachineInstr &MI)
This file contains the declaration of the WebAssembly-specific utility functions. ...
bool isCallDirect(const MachineInstr &MI)
const GlobalValue * getGlobal() const
const char *const CxaRethrowFn
bool isRethrow(const MachineInstr &MI)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool isTee(const MachineInstr &MI)
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
const char *const ClangCallTerminateFn
bool isArgument(const MachineInstr &MI)
MachineOperand class - Representation of each machine instruction operand.
bool isCatchTerminatePad(const MachineBasicBlock &MBB)
Returns if the given BB is a single BB terminate pad which starts with a &#39;catch&#39; instruction.
const char *const PersonalityWrapperFn
Representation of each machine instruction.
Definition: MachineInstr.h:64
This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...
bool isEHPad() const
Returns true if the block is a landing pad.
unsigned getCalleeOpNo(const MachineInstr &MI)
Returns the operand number of a callee, assuming the argument is a call instruction.
StringRef getName() const
Return a constant reference to the value&#39;s name.
Definition: Value.cpp:214
bool isMarker(const MachineInstr &MI)
This file declares WebAssembly-specific per-machine-function information.
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:323
bool isCatch(const MachineInstr &MI)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
IRTranslator LLVM IR MI
bool isCallIndirect(const MachineInstr &MI)
bool isChild(const MachineInstr &MI, const WebAssemblyFunctionInfo &MFI)
Test whether MI is a child of some other node in an expression tree.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:414
bool isImplicit() const
bool isCatchAllTerminatePad(const MachineBasicBlock &MBB)
Returns if the given BB is a single BB terminate pad which starts with a &#39;catch_all&#39; insrtruction...