blob: 4edd54602fb2e94dd0dd7c3e4ed6a210abdd641b [file] [log] [blame]
Dan Gohman4fc4e422016-10-24 19:49:43 +00001//===-- WebAssemblyUtilities.cpp - WebAssembly Utility Functions ----------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Dan Gohman4fc4e422016-10-24 19:49:43 +00006//
7//===----------------------------------------------------------------------===//
8///
9/// \file
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000010/// This file implements several utility functions for WebAssembly.
Dan Gohman4fc4e422016-10-24 19:49:43 +000011///
12//===----------------------------------------------------------------------===//
13
14#include "WebAssemblyUtilities.h"
15#include "WebAssemblyMachineFunctionInfo.h"
16#include "llvm/CodeGen/MachineInstr.h"
Dan Gohmanf52ee172017-02-27 22:38:58 +000017#include "llvm/CodeGen/MachineLoopInfo.h"
Dan Gohman4fc4e422016-10-24 19:49:43 +000018using namespace llvm;
19
Heejin Ahn817811ca2018-06-19 00:32:03 +000020const char *const WebAssembly::ClangCallTerminateFn = "__clang_call_terminate";
21const char *const WebAssembly::CxaBeginCatchFn = "__cxa_begin_catch";
22const char *const WebAssembly::CxaRethrowFn = "__cxa_rethrow";
23const char *const WebAssembly::StdTerminateFn = "_ZSt9terminatev";
24const char *const WebAssembly::PersonalityWrapperFn =
25 "_Unwind_Wasm_CallPersonality";
26
Dan Gohman4fc4e422016-10-24 19:49:43 +000027bool WebAssembly::isArgument(const MachineInstr &MI) {
28 switch (MI.getOpcode()) {
Thomas Lively0ff82ac2018-10-13 07:09:10 +000029 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:
Dan Gohman4fc4e422016-10-24 19:49:43 +000037 case WebAssembly::ARGUMENT_v16i8:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +000038 case WebAssembly::ARGUMENT_v16i8_S:
Dan Gohman4fc4e422016-10-24 19:49:43 +000039 case WebAssembly::ARGUMENT_v8i16:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +000040 case WebAssembly::ARGUMENT_v8i16_S:
Dan Gohman4fc4e422016-10-24 19:49:43 +000041 case WebAssembly::ARGUMENT_v4i32:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +000042 case WebAssembly::ARGUMENT_v4i32_S:
Derek Schuff51ed1312018-08-07 21:24:01 +000043 case WebAssembly::ARGUMENT_v2i64:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +000044 case WebAssembly::ARGUMENT_v2i64_S:
Dan Gohman4fc4e422016-10-24 19:49:43 +000045 case WebAssembly::ARGUMENT_v4f32:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +000046 case WebAssembly::ARGUMENT_v4f32_S:
Derek Schuff51ed1312018-08-07 21:24:01 +000047 case WebAssembly::ARGUMENT_v2f64:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +000048 case WebAssembly::ARGUMENT_v2f64_S:
Dan Gohman4fc4e422016-10-24 19:49:43 +000049 return true;
50 default:
51 return false;
52 }
53}
54
55bool WebAssembly::isCopy(const MachineInstr &MI) {
56 switch (MI.getOpcode()) {
57 case WebAssembly::COPY_I32:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +000058 case WebAssembly::COPY_I32_S:
Dan Gohman4fc4e422016-10-24 19:49:43 +000059 case WebAssembly::COPY_I64:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +000060 case WebAssembly::COPY_I64_S:
Dan Gohman4fc4e422016-10-24 19:49:43 +000061 case WebAssembly::COPY_F32:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +000062 case WebAssembly::COPY_F32_S:
Dan Gohman4fc4e422016-10-24 19:49:43 +000063 case WebAssembly::COPY_F64:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +000064 case WebAssembly::COPY_F64_S:
Thomas Livelyabf6bdc2018-08-30 22:10:43 +000065 case WebAssembly::COPY_V128:
66 case WebAssembly::COPY_V128_S:
Dan Gohman4fc4e422016-10-24 19:49:43 +000067 return true;
68 default:
69 return false;
70 }
71}
72
73bool WebAssembly::isTee(const MachineInstr &MI) {
74 switch (MI.getOpcode()) {
75 case WebAssembly::TEE_I32:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +000076 case WebAssembly::TEE_I32_S:
Dan Gohman4fc4e422016-10-24 19:49:43 +000077 case WebAssembly::TEE_I64:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +000078 case WebAssembly::TEE_I64_S:
Dan Gohman4fc4e422016-10-24 19:49:43 +000079 case WebAssembly::TEE_F32:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +000080 case WebAssembly::TEE_F32_S:
Dan Gohman4fc4e422016-10-24 19:49:43 +000081 case WebAssembly::TEE_F64:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +000082 case WebAssembly::TEE_F64_S:
Thomas Livelyabf6bdc2018-08-30 22:10:43 +000083 case WebAssembly::TEE_V128:
84 case WebAssembly::TEE_V128_S:
Dan Gohman4fc4e422016-10-24 19:49:43 +000085 return true;
86 default:
87 return false;
88 }
89}
90
91/// Test whether MI is a child of some other node in an expression tree.
92bool WebAssembly::isChild(const MachineInstr &MI,
93 const WebAssemblyFunctionInfo &MFI) {
94 if (MI.getNumOperands() == 0)
95 return false;
96 const MachineOperand &MO = MI.getOperand(0);
97 if (!MO.isReg() || MO.isImplicit() || !MO.isDef())
98 return false;
99 unsigned Reg = MO.getReg();
100 return TargetRegisterInfo::isVirtualRegister(Reg) &&
101 MFI.isVRegStackified(Reg);
102}
Dan Gohmand934cb82017-02-24 23:18:00 +0000103
Heejin Ahn817811ca2018-06-19 00:32:03 +0000104bool WebAssembly::isCallDirect(const MachineInstr &MI) {
105 switch (MI.getOpcode()) {
106 case WebAssembly::CALL_VOID:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000107 case WebAssembly::CALL_VOID_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000108 case WebAssembly::CALL_I32:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000109 case WebAssembly::CALL_I32_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000110 case WebAssembly::CALL_I64:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000111 case WebAssembly::CALL_I64_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000112 case WebAssembly::CALL_F32:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000113 case WebAssembly::CALL_F32_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000114 case WebAssembly::CALL_F64:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000115 case WebAssembly::CALL_F64_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000116 case WebAssembly::CALL_v16i8:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000117 case WebAssembly::CALL_v16i8_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000118 case WebAssembly::CALL_v8i16:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000119 case WebAssembly::CALL_v8i16_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000120 case WebAssembly::CALL_v4i32:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000121 case WebAssembly::CALL_v4i32_S:
Derek Schuff51ed1312018-08-07 21:24:01 +0000122 case WebAssembly::CALL_v2i64:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000123 case WebAssembly::CALL_v2i64_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000124 case WebAssembly::CALL_v4f32:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000125 case WebAssembly::CALL_v4f32_S:
Derek Schuff51ed1312018-08-07 21:24:01 +0000126 case WebAssembly::CALL_v2f64:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000127 case WebAssembly::CALL_v2f64_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000128 case WebAssembly::CALL_EXCEPT_REF:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000129 case WebAssembly::CALL_EXCEPT_REF_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000130 return true;
131 default:
132 return false;
133 }
134}
135
Dan Gohmand934cb82017-02-24 23:18:00 +0000136bool WebAssembly::isCallIndirect(const MachineInstr &MI) {
137 switch (MI.getOpcode()) {
138 case WebAssembly::CALL_INDIRECT_VOID:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000139 case WebAssembly::CALL_INDIRECT_VOID_S:
Dan Gohmand934cb82017-02-24 23:18:00 +0000140 case WebAssembly::CALL_INDIRECT_I32:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000141 case WebAssembly::CALL_INDIRECT_I32_S:
Dan Gohmand934cb82017-02-24 23:18:00 +0000142 case WebAssembly::CALL_INDIRECT_I64:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000143 case WebAssembly::CALL_INDIRECT_I64_S:
Dan Gohmand934cb82017-02-24 23:18:00 +0000144 case WebAssembly::CALL_INDIRECT_F32:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000145 case WebAssembly::CALL_INDIRECT_F32_S:
Dan Gohmand934cb82017-02-24 23:18:00 +0000146 case WebAssembly::CALL_INDIRECT_F64:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000147 case WebAssembly::CALL_INDIRECT_F64_S:
Dan Gohmand934cb82017-02-24 23:18:00 +0000148 case WebAssembly::CALL_INDIRECT_v16i8:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000149 case WebAssembly::CALL_INDIRECT_v16i8_S:
Dan Gohmand934cb82017-02-24 23:18:00 +0000150 case WebAssembly::CALL_INDIRECT_v8i16:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000151 case WebAssembly::CALL_INDIRECT_v8i16_S:
Dan Gohmand934cb82017-02-24 23:18:00 +0000152 case WebAssembly::CALL_INDIRECT_v4i32:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000153 case WebAssembly::CALL_INDIRECT_v4i32_S:
Derek Schuff51ed1312018-08-07 21:24:01 +0000154 case WebAssembly::CALL_INDIRECT_v2i64:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000155 case WebAssembly::CALL_INDIRECT_v2i64_S:
Dan Gohmand934cb82017-02-24 23:18:00 +0000156 case WebAssembly::CALL_INDIRECT_v4f32:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000157 case WebAssembly::CALL_INDIRECT_v4f32_S:
Derek Schuff51ed1312018-08-07 21:24:01 +0000158 case WebAssembly::CALL_INDIRECT_v2f64:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000159 case WebAssembly::CALL_INDIRECT_v2f64_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000160 case WebAssembly::CALL_INDIRECT_EXCEPT_REF:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000161 case WebAssembly::CALL_INDIRECT_EXCEPT_REF_S:
Dan Gohmand934cb82017-02-24 23:18:00 +0000162 return true;
163 default:
164 return false;
165 }
166}
Dan Gohmanf52ee172017-02-27 22:38:58 +0000167
Heejin Ahn817811ca2018-06-19 00:32:03 +0000168unsigned WebAssembly::getCalleeOpNo(const MachineInstr &MI) {
169 switch (MI.getOpcode()) {
170 case WebAssembly::CALL_VOID:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000171 case WebAssembly::CALL_VOID_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000172 case WebAssembly::CALL_INDIRECT_VOID:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000173 case WebAssembly::CALL_INDIRECT_VOID_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000174 return 0;
175 case WebAssembly::CALL_I32:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000176 case WebAssembly::CALL_I32_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000177 case WebAssembly::CALL_I64:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000178 case WebAssembly::CALL_I64_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000179 case WebAssembly::CALL_F32:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000180 case WebAssembly::CALL_F32_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000181 case WebAssembly::CALL_F64:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000182 case WebAssembly::CALL_F64_S:
Thomas Livelyabf6bdc2018-08-30 22:10:43 +0000183 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:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000195 case WebAssembly::CALL_EXCEPT_REF:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000196 case WebAssembly::CALL_EXCEPT_REF_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000197 case WebAssembly::CALL_INDIRECT_I32:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000198 case WebAssembly::CALL_INDIRECT_I32_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000199 case WebAssembly::CALL_INDIRECT_I64:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000200 case WebAssembly::CALL_INDIRECT_I64_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000201 case WebAssembly::CALL_INDIRECT_F32:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000202 case WebAssembly::CALL_INDIRECT_F32_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000203 case WebAssembly::CALL_INDIRECT_F64:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000204 case WebAssembly::CALL_INDIRECT_F64_S:
Thomas Livelyabf6bdc2018-08-30 22:10:43 +0000205 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:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000217 case WebAssembly::CALL_INDIRECT_EXCEPT_REF:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000218 case WebAssembly::CALL_INDIRECT_EXCEPT_REF_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000219 return 1;
220 default:
221 llvm_unreachable("Not a call instruction");
222 }
223}
224
225bool WebAssembly::isMarker(const MachineInstr &MI) {
226 switch (MI.getOpcode()) {
227 case WebAssembly::BLOCK:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000228 case WebAssembly::BLOCK_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000229 case WebAssembly::END_BLOCK:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000230 case WebAssembly::END_BLOCK_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000231 case WebAssembly::LOOP:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000232 case WebAssembly::LOOP_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000233 case WebAssembly::END_LOOP:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000234 case WebAssembly::END_LOOP_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000235 case WebAssembly::TRY:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000236 case WebAssembly::TRY_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000237 case WebAssembly::END_TRY:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000238 case WebAssembly::END_TRY_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000239 return true;
240 default:
241 return false;
242 }
243}
244
Heejin Ahn817811ca2018-06-19 00:32:03 +0000245bool WebAssembly::mayThrow(const MachineInstr &MI) {
246 switch (MI.getOpcode()) {
Heejin Ahnd6f48782019-01-30 03:21:57 +0000247 case WebAssembly::THROW:
248 case WebAssembly::THROW_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000249 case WebAssembly::RETHROW:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000250 case WebAssembly::RETHROW_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000251 return true;
252 }
253 if (isCallIndirect(MI))
254 return true;
255 if (!MI.isCall())
256 return false;
257
258 const MachineOperand &MO = MI.getOperand(getCalleeOpNo(MI));
259 assert(MO.isGlobal());
260 const auto *F = dyn_cast<Function>(MO.getGlobal());
261 if (!F)
262 return true;
263 if (F->doesNotThrow())
264 return false;
265 // These functions never throw
266 if (F->getName() == CxaBeginCatchFn || F->getName() == PersonalityWrapperFn ||
267 F->getName() == ClangCallTerminateFn || F->getName() == StdTerminateFn)
268 return false;
269 return true;
270}