1 //===-- WebAssemblyUtilities.cpp - WebAssembly Utility Functions ----------===//
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
7 //===----------------------------------------------------------------------===//
10 /// This file implements several utility functions for WebAssembly.
12 //===----------------------------------------------------------------------===//
14 #include "WebAssemblyUtilities.h"
15 #include "WebAssemblyMachineFunctionInfo.h"
16 #include "llvm/CodeGen/MachineInstr.h"
17 #include "llvm/CodeGen/MachineLoopInfo.h"
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";
24 const char *const WebAssembly::PersonalityWrapperFn
=
25 "_Unwind_Wasm_CallPersonality";
27 /// Test whether MI is a child of some other node in an expression tree.
28 bool WebAssembly::isChild(const MachineInstr
&MI
,
29 const WebAssemblyFunctionInfo
&MFI
) {
30 if (MI
.getNumOperands() == 0)
32 const MachineOperand
&MO
= MI
.getOperand(0);
33 if (!MO
.isReg() || MO
.isImplicit() || !MO
.isDef())
35 Register Reg
= MO
.getReg();
36 return Register::isVirtualRegister(Reg
) && MFI
.isVRegStackified(Reg
);
39 bool WebAssembly::mayThrow(const MachineInstr
&MI
) {
40 switch (MI
.getOpcode()) {
41 case WebAssembly::THROW
:
42 case WebAssembly::THROW_S
:
43 case WebAssembly::RETHROW
:
44 case WebAssembly::RETHROW_S
:
47 if (isCallIndirect(MI
.getOpcode()))
52 const MachineOperand
&MO
= MI
.getOperand(getCalleeOpNo(MI
.getOpcode()));
53 assert(MO
.isGlobal() || 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)
68 const auto *F
= dyn_cast
<Function
>(MO
.getGlobal());
71 if (F
->doesNotThrow())
73 // These functions never throw
74 if (F
->getName() == CxaBeginCatchFn
|| F
->getName() == PersonalityWrapperFn
||
75 F
->getName() == ClangCallTerminateFn
|| F
->getName() == StdTerminateFn
)
78 // TODO Can we exclude call instructions that are marked as 'nounwind' in the
79 // original LLVm IR? (Even when the callee may throw)