]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Target / WebAssembly / WebAssemblyUtilities.cpp
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"
16 #include "WebAssemblyMachineFunctionInfo.h"
17 #include "llvm/CodeGen/MachineInstr.h"
18 #include "llvm/CodeGen/MachineLoopInfo.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";
25 const char *const WebAssembly::PersonalityWrapperFn =
26     "_Unwind_Wasm_CallPersonality";
27
28 bool WebAssembly::isArgument(const MachineInstr &MI) {
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
56 bool WebAssembly::isCopy(const MachineInstr &MI) {
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
74 bool WebAssembly::isTee(const MachineInstr &MI) {
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.
93 bool WebAssembly::isChild(const MachineInstr &MI,
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();
101   return TargetRegisterInfo::isVirtualRegister(Reg) &&
102          MFI.isVRegStackified(Reg);
103 }
104
105 bool WebAssembly::isCallDirect(const MachineInstr &MI) {
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
137 bool WebAssembly::isCallIndirect(const MachineInstr &MI) {
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
169 unsigned WebAssembly::getCalleeOpNo(const MachineInstr &MI) {
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
226 bool WebAssembly::isMarker(const MachineInstr &MI) {
227   switch (MI.getOpcode()) {
228   case WebAssembly::BLOCK:
229   case WebAssembly::BLOCK_S:
230   case WebAssembly::END_BLOCK:
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
246 bool WebAssembly::isThrow(const MachineInstr &MI) {
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
258 bool WebAssembly::isRethrow(const MachineInstr &MI) {
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
270 bool WebAssembly::isCatch(const MachineInstr &MI) {
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
284 bool WebAssembly::mayThrow(const MachineInstr &MI) {
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
313 bool WebAssembly::isCatchTerminatePad(const MachineBasicBlock &MBB) {
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
333 bool WebAssembly::isCatchAllTerminatePad(const MachineBasicBlock &MBB) {
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 }