blob: 5b777984ffa6409ac7de8c9eae92d83f3f85be95 [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 +000027/// Test whether MI is a child of some other node in an expression tree.
28bool WebAssembly::isChild(const MachineInstr &MI,
29 const WebAssemblyFunctionInfo &MFI) {
30 if (MI.getNumOperands() == 0)
31 return false;
32 const MachineOperand &MO = MI.getOperand(0);
33 if (!MO.isReg() || MO.isImplicit() || !MO.isDef())
34 return false;
Daniel Sanders05c145d2019-08-12 22:40:45 +000035 Register Reg = MO.getReg();
Daniel Sanders2bea69b2019-08-01 23:27:28 +000036 return Register::isVirtualRegister(Reg) && MFI.isVRegStackified(Reg);
Dan Gohman4fc4e422016-10-24 19:49:43 +000037}
Dan Gohmand934cb82017-02-24 23:18:00 +000038
Heejin Ahn817811ca2018-06-19 00:32:03 +000039bool WebAssembly::mayThrow(const MachineInstr &MI) {
40 switch (MI.getOpcode()) {
Heejin Ahnd6f48782019-01-30 03:21:57 +000041 case WebAssembly::THROW:
42 case WebAssembly::THROW_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +000043 case WebAssembly::RETHROW:
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +000044 case WebAssembly::RETHROW_S:
Heejin Ahn817811ca2018-06-19 00:32:03 +000045 return true;
46 }
Wouter van Oortmerssend8ddf832019-07-12 22:08:25 +000047 if (isCallIndirect(MI.getOpcode()))
Heejin Ahn817811ca2018-06-19 00:32:03 +000048 return true;
49 if (!MI.isCall())
50 return false;
51
Thomas Lively3ef169e2019-12-13 10:41:25 -080052 const MachineOperand &MO = getCalleeOp(MI);
Heejin Ahn58af5be2019-10-07 21:14:45 +000053 assert(MO.isGlobal() || MO.isSymbol());
54
55 if (MO.isSymbol()) {
56 // Some intrinsics are lowered to calls to external symbols, which are then
57 // lowered to calls to library functions. Most of libcalls don't throw, but
58 // we only list some of them here now.
59 // TODO Consider adding 'nounwind' info in TargetLowering::CallLoweringInfo
60 // instead for more accurate info.
61 const char *Name = MO.getSymbolName();
62 if (strcmp(Name, "memcpy") == 0 || strcmp(Name, "memmove") == 0 ||
63 strcmp(Name, "memset") == 0)
64 return false;
65 return true;
66 }
67
Heejin Ahn817811ca2018-06-19 00:32:03 +000068 const auto *F = dyn_cast<Function>(MO.getGlobal());
69 if (!F)
70 return true;
71 if (F->doesNotThrow())
72 return false;
73 // These functions never throw
74 if (F->getName() == CxaBeginCatchFn || F->getName() == PersonalityWrapperFn ||
75 F->getName() == ClangCallTerminateFn || F->getName() == StdTerminateFn)
76 return false;
Heejin Ahnc4ac74f2019-03-30 11:04:48 +000077
78 // TODO Can we exclude call instructions that are marked as 'nounwind' in the
79 // original LLVm IR? (Even when the callee may throw)
Heejin Ahn817811ca2018-06-19 00:32:03 +000080 return true;
81}
Thomas Lively3ef169e2019-12-13 10:41:25 -080082
83inline const MachineOperand &getCalleeOp(const MachineInstr &MI) {
84 switch (MI.getOpcode()) {
85 case WebAssembly::CALL_VOID:
86 case WebAssembly::CALL_VOID_S:
87 case WebAssembly::CALL_INDIRECT_VOID:
88 case WebAssembly::CALL_INDIRECT_VOID_S:
89 case WebAssembly::RET_CALL:
90 case WebAssembly::RET_CALL_S:
91 case WebAssembly::RET_CALL_INDIRECT:
92 case WebAssembly::RET_CALL_INDIRECT_S:
93 return MI.getOperand(0);
94 case WebAssembly::CALL_i32:
95 case WebAssembly::CALL_i32_S:
96 case WebAssembly::CALL_i64:
97 case WebAssembly::CALL_i64_S:
98 case WebAssembly::CALL_f32:
99 case WebAssembly::CALL_f32_S:
100 case WebAssembly::CALL_f64:
101 case WebAssembly::CALL_f64_S:
102 case WebAssembly::CALL_v16i8:
103 case WebAssembly::CALL_v16i8_S:
104 case WebAssembly::CALL_v8i16:
105 case WebAssembly::CALL_v8i16_S:
106 case WebAssembly::CALL_v4i32:
107 case WebAssembly::CALL_v4i32_S:
108 case WebAssembly::CALL_v2i64:
109 case WebAssembly::CALL_v2i64_S:
110 case WebAssembly::CALL_v4f32:
111 case WebAssembly::CALL_v4f32_S:
112 case WebAssembly::CALL_v2f64:
113 case WebAssembly::CALL_v2f64_S:
114 case WebAssembly::CALL_exnref:
115 case WebAssembly::CALL_exnref_S:
116 case WebAssembly::CALL_INDIRECT_i32:
117 case WebAssembly::CALL_INDIRECT_i32_S:
118 case WebAssembly::CALL_INDIRECT_i64:
119 case WebAssembly::CALL_INDIRECT_i64_S:
120 case WebAssembly::CALL_INDIRECT_f32:
121 case WebAssembly::CALL_INDIRECT_f32_S:
122 case WebAssembly::CALL_INDIRECT_f64:
123 case WebAssembly::CALL_INDIRECT_f64_S:
124 case WebAssembly::CALL_INDIRECT_v16i8:
125 case WebAssembly::CALL_INDIRECT_v16i8_S:
126 case WebAssembly::CALL_INDIRECT_v8i16:
127 case WebAssembly::CALL_INDIRECT_v8i16_S:
128 case WebAssembly::CALL_INDIRECT_v4i32:
129 case WebAssembly::CALL_INDIRECT_v4i32_S:
130 case WebAssembly::CALL_INDIRECT_v2i64:
131 case WebAssembly::CALL_INDIRECT_v2i64_S:
132 case WebAssembly::CALL_INDIRECT_v4f32:
133 case WebAssembly::CALL_INDIRECT_v4f32_S:
134 case WebAssembly::CALL_INDIRECT_v2f64:
135 case WebAssembly::CALL_INDIRECT_v2f64_S:
136 case WebAssembly::CALL_INDIRECT_exnref:
137 case WebAssembly::CALL_INDIRECT_exnref_S:
138 return MI.getOperand(1);
139 case WebAssembly::CALL:
140 case WebAssembly::CALL_S:
141 return MI.getOperand(MI.getNumDefs());
142 default:
143 llvm_unreachable("Not a call instruction");
144 }
145}