xref: /freebsd/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyUtilities.cpp (revision aae38d10b4eebf81c0942947e8b83a9bb8651d88)
1 //===-- WebAssemblyUtilities.cpp - WebAssembly Utility Functions ----------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// This file implements several utility functions for WebAssembly.
11 ///
12 //===----------------------------------------------------------------------===//
13 
14 #include "WebAssemblyUtilities.h"
15 #include "WebAssemblyMachineFunctionInfo.h"
16 #include "llvm/CodeGen/MachineInstr.h"
17 #include "llvm/CodeGen/MachineLoopInfo.h"
18 using namespace llvm;
19 
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";
26 
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)
31     return false;
32   const MachineOperand &MO = MI.getOperand(0);
33   if (!MO.isReg() || MO.isImplicit() || !MO.isDef())
34     return false;
35   unsigned Reg = MO.getReg();
36   return TargetRegisterInfo::isVirtualRegister(Reg) &&
37          MFI.isVRegStackified(Reg);
38 }
39 
40 bool WebAssembly::mayThrow(const MachineInstr &MI) {
41   switch (MI.getOpcode()) {
42   case WebAssembly::THROW:
43   case WebAssembly::THROW_S:
44   case WebAssembly::RETHROW:
45   case WebAssembly::RETHROW_S:
46     return true;
47   }
48   if (isCallIndirect(MI.getOpcode()))
49     return true;
50   if (!MI.isCall())
51     return false;
52 
53   const MachineOperand &MO = MI.getOperand(getCalleeOpNo(MI.getOpcode()));
54   assert(MO.isGlobal());
55   const auto *F = dyn_cast<Function>(MO.getGlobal());
56   if (!F)
57     return true;
58   if (F->doesNotThrow())
59     return false;
60   // These functions never throw
61   if (F->getName() == CxaBeginCatchFn || F->getName() == PersonalityWrapperFn ||
62       F->getName() == ClangCallTerminateFn || F->getName() == StdTerminateFn)
63     return false;
64 
65   // TODO Can we exclude call instructions that are marked as 'nounwind' in the
66   // original LLVm IR? (Even when the callee may throw)
67   return true;
68 }
69