blob: 002246a77e2debd81b98d7e92af2a327e82daeb6 [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:
Heejin Ahnc4ac74f2019-03-30 11:04:48 +000067 case WebAssembly::COPY_EXCEPT_REF:
68 case WebAssembly::COPY_EXCEPT_REF_S:
Dan Gohman4fc4e422016-10-24 19:49:43 +000069 return true;
70 default:
71 return false;
72 }
73}
74
75bool WebAssembly::isTee(const MachineInstr &MI) {
76 switch (MI.getOpcode()) {
77 case WebAssembly::TEE_I32:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +000078 case WebAssembly::TEE_I32_S:
Dan Gohman4fc4e422016-10-24 19:49:43 +000079 case WebAssembly::TEE_I64:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +000080 case WebAssembly::TEE_I64_S:
Dan Gohman4fc4e422016-10-24 19:49:43 +000081 case WebAssembly::TEE_F32:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +000082 case WebAssembly::TEE_F32_S:
Dan Gohman4fc4e422016-10-24 19:49:43 +000083 case WebAssembly::TEE_F64:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +000084 case WebAssembly::TEE_F64_S:
Thomas Livelyabf6bdc2018-08-30 22:10:43 +000085 case WebAssembly::TEE_V128:
86 case WebAssembly::TEE_V128_S:
Dan Gohman4fc4e422016-10-24 19:49:43 +000087 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.
94bool WebAssembly::isChild(const MachineInstr &MI,
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();
102 return TargetRegisterInfo::isVirtualRegister(Reg) &&
103 MFI.isVRegStackified(Reg);
104}
Dan Gohmand934cb82017-02-24 23:18:00 +0000105
Heejin Ahn817811ca2018-06-19 00:32:03 +0000106bool WebAssembly::isCallDirect(const MachineInstr &MI) {
107 switch (MI.getOpcode()) {
108 case WebAssembly::CALL_VOID:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000109 case WebAssembly::CALL_VOID_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000110 case WebAssembly::CALL_I32:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000111 case WebAssembly::CALL_I32_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000112 case WebAssembly::CALL_I64:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000113 case WebAssembly::CALL_I64_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000114 case WebAssembly::CALL_F32:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000115 case WebAssembly::CALL_F32_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000116 case WebAssembly::CALL_F64:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000117 case WebAssembly::CALL_F64_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000118 case WebAssembly::CALL_v16i8:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000119 case WebAssembly::CALL_v16i8_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000120 case WebAssembly::CALL_v8i16:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000121 case WebAssembly::CALL_v8i16_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000122 case WebAssembly::CALL_v4i32:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000123 case WebAssembly::CALL_v4i32_S:
Derek Schuff51ed1312018-08-07 21:24:01 +0000124 case WebAssembly::CALL_v2i64:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000125 case WebAssembly::CALL_v2i64_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000126 case WebAssembly::CALL_v4f32:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000127 case WebAssembly::CALL_v4f32_S:
Derek Schuff51ed1312018-08-07 21:24:01 +0000128 case WebAssembly::CALL_v2f64:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000129 case WebAssembly::CALL_v2f64_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000130 case WebAssembly::CALL_EXCEPT_REF:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000131 case WebAssembly::CALL_EXCEPT_REF_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000132 return true;
133 default:
134 return false;
135 }
136}
137
Dan Gohmand934cb82017-02-24 23:18:00 +0000138bool WebAssembly::isCallIndirect(const MachineInstr &MI) {
139 switch (MI.getOpcode()) {
140 case WebAssembly::CALL_INDIRECT_VOID:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000141 case WebAssembly::CALL_INDIRECT_VOID_S:
Dan Gohmand934cb82017-02-24 23:18:00 +0000142 case WebAssembly::CALL_INDIRECT_I32:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000143 case WebAssembly::CALL_INDIRECT_I32_S:
Dan Gohmand934cb82017-02-24 23:18:00 +0000144 case WebAssembly::CALL_INDIRECT_I64:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000145 case WebAssembly::CALL_INDIRECT_I64_S:
Dan Gohmand934cb82017-02-24 23:18:00 +0000146 case WebAssembly::CALL_INDIRECT_F32:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000147 case WebAssembly::CALL_INDIRECT_F32_S:
Dan Gohmand934cb82017-02-24 23:18:00 +0000148 case WebAssembly::CALL_INDIRECT_F64:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000149 case WebAssembly::CALL_INDIRECT_F64_S:
Dan Gohmand934cb82017-02-24 23:18:00 +0000150 case WebAssembly::CALL_INDIRECT_v16i8:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000151 case WebAssembly::CALL_INDIRECT_v16i8_S:
Dan Gohmand934cb82017-02-24 23:18:00 +0000152 case WebAssembly::CALL_INDIRECT_v8i16:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000153 case WebAssembly::CALL_INDIRECT_v8i16_S:
Dan Gohmand934cb82017-02-24 23:18:00 +0000154 case WebAssembly::CALL_INDIRECT_v4i32:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000155 case WebAssembly::CALL_INDIRECT_v4i32_S:
Derek Schuff51ed1312018-08-07 21:24:01 +0000156 case WebAssembly::CALL_INDIRECT_v2i64:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000157 case WebAssembly::CALL_INDIRECT_v2i64_S:
Dan Gohmand934cb82017-02-24 23:18:00 +0000158 case WebAssembly::CALL_INDIRECT_v4f32:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000159 case WebAssembly::CALL_INDIRECT_v4f32_S:
Derek Schuff51ed1312018-08-07 21:24:01 +0000160 case WebAssembly::CALL_INDIRECT_v2f64:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000161 case WebAssembly::CALL_INDIRECT_v2f64_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000162 case WebAssembly::CALL_INDIRECT_EXCEPT_REF:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000163 case WebAssembly::CALL_INDIRECT_EXCEPT_REF_S:
Dan Gohmand934cb82017-02-24 23:18:00 +0000164 return true;
165 default:
166 return false;
167 }
168}
Dan Gohmanf52ee172017-02-27 22:38:58 +0000169
Heejin Ahn817811ca2018-06-19 00:32:03 +0000170unsigned WebAssembly::getCalleeOpNo(const MachineInstr &MI) {
171 switch (MI.getOpcode()) {
172 case WebAssembly::CALL_VOID:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000173 case WebAssembly::CALL_VOID_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000174 case WebAssembly::CALL_INDIRECT_VOID:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000175 case WebAssembly::CALL_INDIRECT_VOID_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000176 return 0;
177 case WebAssembly::CALL_I32:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000178 case WebAssembly::CALL_I32_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000179 case WebAssembly::CALL_I64:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000180 case WebAssembly::CALL_I64_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000181 case WebAssembly::CALL_F32:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000182 case WebAssembly::CALL_F32_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000183 case WebAssembly::CALL_F64:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000184 case WebAssembly::CALL_F64_S:
Thomas Livelyabf6bdc2018-08-30 22:10:43 +0000185 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:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000197 case WebAssembly::CALL_EXCEPT_REF:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000198 case WebAssembly::CALL_EXCEPT_REF_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000199 case WebAssembly::CALL_INDIRECT_I32:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000200 case WebAssembly::CALL_INDIRECT_I32_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000201 case WebAssembly::CALL_INDIRECT_I64:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000202 case WebAssembly::CALL_INDIRECT_I64_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000203 case WebAssembly::CALL_INDIRECT_F32:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000204 case WebAssembly::CALL_INDIRECT_F32_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000205 case WebAssembly::CALL_INDIRECT_F64:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000206 case WebAssembly::CALL_INDIRECT_F64_S:
Thomas Livelyabf6bdc2018-08-30 22:10:43 +0000207 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:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000219 case WebAssembly::CALL_INDIRECT_EXCEPT_REF:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000220 case WebAssembly::CALL_INDIRECT_EXCEPT_REF_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000221 return 1;
222 default:
223 llvm_unreachable("Not a call instruction");
224 }
225}
226
227bool WebAssembly::isMarker(const MachineInstr &MI) {
228 switch (MI.getOpcode()) {
229 case WebAssembly::BLOCK:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000230 case WebAssembly::BLOCK_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000231 case WebAssembly::END_BLOCK:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000232 case WebAssembly::END_BLOCK_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000233 case WebAssembly::LOOP:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000234 case WebAssembly::LOOP_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000235 case WebAssembly::END_LOOP:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000236 case WebAssembly::END_LOOP_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000237 case WebAssembly::TRY:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000238 case WebAssembly::TRY_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000239 case WebAssembly::END_TRY:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000240 case WebAssembly::END_TRY_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000241 return true;
242 default:
243 return false;
244 }
245}
246
Heejin Ahn817811ca2018-06-19 00:32:03 +0000247bool WebAssembly::mayThrow(const MachineInstr &MI) {
248 switch (MI.getOpcode()) {
Heejin Ahnd6f48782019-01-30 03:21:57 +0000249 case WebAssembly::THROW:
250 case WebAssembly::THROW_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000251 case WebAssembly::RETHROW:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000252 case WebAssembly::RETHROW_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +0000253 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;
Heejin Ahnc4ac74f2019-03-30 11:04:48 +0000271
272 // TODO Can we exclude call instructions that are marked as 'nounwind' in the
273 // original LLVm IR? (Even when the callee may throw)
Heejin Ahn817811ca2018-06-19 00:32:03 +0000274 return true;
275}