LLVM  9.0.0svn
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 
14 #include "WebAssemblyUtilities.h"
18 using namespace llvm;
19 
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";
25  "_Unwind_Wasm_CallPersonality";
26 
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:
49  return true;
50  default:
51  return false;
52  }
53 }
54 
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:
67  case WebAssembly::COPY_EXCEPT_REF:
68  case WebAssembly::COPY_EXCEPT_REF_S:
69  return true;
70  default:
71  return false;
72  }
73 }
74 
76  switch (MI.getOpcode()) {
77  case WebAssembly::TEE_I32:
78  case WebAssembly::TEE_I32_S:
79  case WebAssembly::TEE_I64:
80  case WebAssembly::TEE_I64_S:
81  case WebAssembly::TEE_F32:
82  case WebAssembly::TEE_F32_S:
83  case WebAssembly::TEE_F64:
84  case WebAssembly::TEE_F64_S:
85  case WebAssembly::TEE_V128:
86  case WebAssembly::TEE_V128_S:
87  return true;
88  default:
89  return false;
90  }
91 }
92 
93 /// Test whether MI is a child of some other node in an expression tree.
95  const WebAssemblyFunctionInfo &MFI) {
96  if (MI.getNumOperands() == 0)
97  return false;
98  const MachineOperand &MO = MI.getOperand(0);
99  if (!MO.isReg() || MO.isImplicit() || !MO.isDef())
100  return false;
101  unsigned Reg = MO.getReg();
103  MFI.isVRegStackified(Reg);
104 }
105 
107  switch (MI.getOpcode()) {
108  case WebAssembly::CALL_VOID:
109  case WebAssembly::CALL_VOID_S:
110  case WebAssembly::CALL_I32:
111  case WebAssembly::CALL_I32_S:
112  case WebAssembly::CALL_I64:
113  case WebAssembly::CALL_I64_S:
114  case WebAssembly::CALL_F32:
115  case WebAssembly::CALL_F32_S:
116  case WebAssembly::CALL_F64:
117  case WebAssembly::CALL_F64_S:
118  case WebAssembly::CALL_v16i8:
119  case WebAssembly::CALL_v16i8_S:
120  case WebAssembly::CALL_v8i16:
121  case WebAssembly::CALL_v8i16_S:
122  case WebAssembly::CALL_v4i32:
123  case WebAssembly::CALL_v4i32_S:
124  case WebAssembly::CALL_v2i64:
125  case WebAssembly::CALL_v2i64_S:
126  case WebAssembly::CALL_v4f32:
127  case WebAssembly::CALL_v4f32_S:
128  case WebAssembly::CALL_v2f64:
129  case WebAssembly::CALL_v2f64_S:
130  case WebAssembly::CALL_EXCEPT_REF:
131  case WebAssembly::CALL_EXCEPT_REF_S:
132  return true;
133  default:
134  return false;
135  }
136 }
137 
139  switch (MI.getOpcode()) {
140  case WebAssembly::CALL_INDIRECT_VOID:
141  case WebAssembly::CALL_INDIRECT_VOID_S:
142  case WebAssembly::CALL_INDIRECT_I32:
143  case WebAssembly::CALL_INDIRECT_I32_S:
144  case WebAssembly::CALL_INDIRECT_I64:
145  case WebAssembly::CALL_INDIRECT_I64_S:
146  case WebAssembly::CALL_INDIRECT_F32:
147  case WebAssembly::CALL_INDIRECT_F32_S:
148  case WebAssembly::CALL_INDIRECT_F64:
149  case WebAssembly::CALL_INDIRECT_F64_S:
150  case WebAssembly::CALL_INDIRECT_v16i8:
151  case WebAssembly::CALL_INDIRECT_v16i8_S:
152  case WebAssembly::CALL_INDIRECT_v8i16:
153  case WebAssembly::CALL_INDIRECT_v8i16_S:
154  case WebAssembly::CALL_INDIRECT_v4i32:
155  case WebAssembly::CALL_INDIRECT_v4i32_S:
156  case WebAssembly::CALL_INDIRECT_v2i64:
157  case WebAssembly::CALL_INDIRECT_v2i64_S:
158  case WebAssembly::CALL_INDIRECT_v4f32:
159  case WebAssembly::CALL_INDIRECT_v4f32_S:
160  case WebAssembly::CALL_INDIRECT_v2f64:
161  case WebAssembly::CALL_INDIRECT_v2f64_S:
162  case WebAssembly::CALL_INDIRECT_EXCEPT_REF:
163  case WebAssembly::CALL_INDIRECT_EXCEPT_REF_S:
164  return true;
165  default:
166  return false;
167  }
168 }
169 
171  switch (MI.getOpcode()) {
172  case WebAssembly::CALL_VOID:
173  case WebAssembly::CALL_VOID_S:
174  case WebAssembly::CALL_INDIRECT_VOID:
175  case WebAssembly::CALL_INDIRECT_VOID_S:
176  return 0;
177  case WebAssembly::CALL_I32:
178  case WebAssembly::CALL_I32_S:
179  case WebAssembly::CALL_I64:
180  case WebAssembly::CALL_I64_S:
181  case WebAssembly::CALL_F32:
182  case WebAssembly::CALL_F32_S:
183  case WebAssembly::CALL_F64:
184  case WebAssembly::CALL_F64_S:
185  case WebAssembly::CALL_v16i8:
186  case WebAssembly::CALL_v16i8_S:
187  case WebAssembly::CALL_v8i16:
188  case WebAssembly::CALL_v8i16_S:
189  case WebAssembly::CALL_v4i32:
190  case WebAssembly::CALL_v4i32_S:
191  case WebAssembly::CALL_v2i64:
192  case WebAssembly::CALL_v2i64_S:
193  case WebAssembly::CALL_v4f32:
194  case WebAssembly::CALL_v4f32_S:
195  case WebAssembly::CALL_v2f64:
196  case WebAssembly::CALL_v2f64_S:
197  case WebAssembly::CALL_EXCEPT_REF:
198  case WebAssembly::CALL_EXCEPT_REF_S:
199  case WebAssembly::CALL_INDIRECT_I32:
200  case WebAssembly::CALL_INDIRECT_I32_S:
201  case WebAssembly::CALL_INDIRECT_I64:
202  case WebAssembly::CALL_INDIRECT_I64_S:
203  case WebAssembly::CALL_INDIRECT_F32:
204  case WebAssembly::CALL_INDIRECT_F32_S:
205  case WebAssembly::CALL_INDIRECT_F64:
206  case WebAssembly::CALL_INDIRECT_F64_S:
207  case WebAssembly::CALL_INDIRECT_v16i8:
208  case WebAssembly::CALL_INDIRECT_v16i8_S:
209  case WebAssembly::CALL_INDIRECT_v8i16:
210  case WebAssembly::CALL_INDIRECT_v8i16_S:
211  case WebAssembly::CALL_INDIRECT_v4i32:
212  case WebAssembly::CALL_INDIRECT_v4i32_S:
213  case WebAssembly::CALL_INDIRECT_v2i64:
214  case WebAssembly::CALL_INDIRECT_v2i64_S:
215  case WebAssembly::CALL_INDIRECT_v4f32:
216  case WebAssembly::CALL_INDIRECT_v4f32_S:
217  case WebAssembly::CALL_INDIRECT_v2f64:
218  case WebAssembly::CALL_INDIRECT_v2f64_S:
219  case WebAssembly::CALL_INDIRECT_EXCEPT_REF:
220  case WebAssembly::CALL_INDIRECT_EXCEPT_REF_S:
221  return 1;
222  default:
223  llvm_unreachable("Not a call instruction");
224  }
225 }
226 
228  switch (MI.getOpcode()) {
229  case WebAssembly::BLOCK:
230  case WebAssembly::BLOCK_S:
232  case WebAssembly::END_BLOCK_S:
233  case WebAssembly::LOOP:
234  case WebAssembly::LOOP_S:
235  case WebAssembly::END_LOOP:
236  case WebAssembly::END_LOOP_S:
237  case WebAssembly::TRY:
238  case WebAssembly::TRY_S:
239  case WebAssembly::END_TRY:
240  case WebAssembly::END_TRY_S:
241  return true;
242  default:
243  return false;
244  }
245 }
246 
248  switch (MI.getOpcode()) {
249  case WebAssembly::THROW:
250  case WebAssembly::THROW_S:
251  case WebAssembly::RETHROW:
252  case WebAssembly::RETHROW_S:
253  return true;
254  }
255  if (isCallIndirect(MI))
256  return true;
257  if (!MI.isCall())
258  return false;
259 
260  const MachineOperand &MO = MI.getOperand(getCalleeOpNo(MI));
261  assert(MO.isGlobal());
262  const auto *F = dyn_cast<Function>(MO.getGlobal());
263  if (!F)
264  return true;
265  if (F->doesNotThrow())
266  return false;
267  // These functions never throw
268  if (F->getName() == CxaBeginCatchFn || F->getName() == PersonalityWrapperFn ||
269  F->getName() == ClangCallTerminateFn || F->getName() == StdTerminateFn)
270  return false;
271 
272  // TODO Can we exclude call instructions that are marked as 'nounwind' in the
273  // original LLVm IR? (Even when the callee may throw)
274  return true;
275 }
bool isCall(QueryType Type=AnyInBundle) const
Definition: MachineInstr.h:632
This class represents lattice values for constants.
Definition: AllocatorList.h:23
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:411
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:408
const char *const CxaBeginCatchFn
const char *const StdTerminateFn
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
#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.
const char *const PersonalityWrapperFn
Representation of each machine instruction.
Definition: MachineInstr.h:63
This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...
unsigned getCalleeOpNo(const MachineInstr &MI)
Returns the operand number of a callee, assuming the argument is a call instruction.
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:332
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:413
bool isImplicit() const