|  | //===-- WebAssemblyUtilities.cpp - WebAssembly Utility Functions ----------===// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | /// | 
|  | /// \file | 
|  | /// This file implements several utility functions for WebAssembly. | 
|  | /// | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "WebAssemblyUtilities.h" | 
|  | #include "WebAssemblyMachineFunctionInfo.h" | 
|  | #include "llvm/CodeGen/MachineInstr.h" | 
|  | #include "llvm/CodeGen/MachineLoopInfo.h" | 
|  | using namespace llvm; | 
|  |  | 
|  | const char *const WebAssembly::ClangCallTerminateFn = "__clang_call_terminate"; | 
|  | const char *const WebAssembly::CxaBeginCatchFn = "__cxa_begin_catch"; | 
|  | const char *const WebAssembly::CxaRethrowFn = "__cxa_rethrow"; | 
|  | const char *const WebAssembly::StdTerminateFn = "_ZSt9terminatev"; | 
|  | const char *const WebAssembly::PersonalityWrapperFn = | 
|  | "_Unwind_Wasm_CallPersonality"; | 
|  |  | 
|  | /// Test whether MI is a child of some other node in an expression tree. | 
|  | bool WebAssembly::isChild(const MachineInstr &MI, | 
|  | const WebAssemblyFunctionInfo &MFI) { | 
|  | if (MI.getNumOperands() == 0) | 
|  | return false; | 
|  | const MachineOperand &MO = MI.getOperand(0); | 
|  | if (!MO.isReg() || MO.isImplicit() || !MO.isDef()) | 
|  | return false; | 
|  | Register Reg = MO.getReg(); | 
|  | return Register::isVirtualRegister(Reg) && MFI.isVRegStackified(Reg); | 
|  | } | 
|  |  | 
|  | bool WebAssembly::mayThrow(const MachineInstr &MI) { | 
|  | switch (MI.getOpcode()) { | 
|  | case WebAssembly::THROW: | 
|  | case WebAssembly::THROW_S: | 
|  | case WebAssembly::RETHROW: | 
|  | case WebAssembly::RETHROW_S: | 
|  | return true; | 
|  | } | 
|  | if (isCallIndirect(MI.getOpcode())) | 
|  | return true; | 
|  | if (!MI.isCall()) | 
|  | return false; | 
|  |  | 
|  | const MachineOperand &MO = getCalleeOp(MI); | 
|  | assert(MO.isGlobal() || MO.isSymbol()); | 
|  |  | 
|  | if (MO.isSymbol()) { | 
|  | // Some intrinsics are lowered to calls to external symbols, which are then | 
|  | // lowered to calls to library functions. Most of libcalls don't throw, but | 
|  | // we only list some of them here now. | 
|  | // TODO Consider adding 'nounwind' info in TargetLowering::CallLoweringInfo | 
|  | // instead for more accurate info. | 
|  | const char *Name = MO.getSymbolName(); | 
|  | if (strcmp(Name, "memcpy") == 0 || strcmp(Name, "memmove") == 0 || | 
|  | strcmp(Name, "memset") == 0) | 
|  | return false; | 
|  | return true; | 
|  | } | 
|  |  | 
|  | const auto *F = dyn_cast<Function>(MO.getGlobal()); | 
|  | if (!F) | 
|  | return true; | 
|  | if (F->doesNotThrow()) | 
|  | return false; | 
|  | // These functions never throw | 
|  | if (F->getName() == CxaBeginCatchFn || F->getName() == PersonalityWrapperFn || | 
|  | F->getName() == ClangCallTerminateFn || F->getName() == StdTerminateFn) | 
|  | return false; | 
|  |  | 
|  | // TODO Can we exclude call instructions that are marked as 'nounwind' in the | 
|  | // original LLVm IR? (Even when the callee may throw) | 
|  | return true; | 
|  | } | 
|  |  | 
|  | const MachineOperand &WebAssembly::getCalleeOp(const MachineInstr &MI) { | 
|  | switch (MI.getOpcode()) { | 
|  | case WebAssembly::CALL: | 
|  | case WebAssembly::CALL_S: | 
|  | case WebAssembly::RET_CALL: | 
|  | case WebAssembly::RET_CALL_S: | 
|  | return MI.getOperand(MI.getNumExplicitDefs()); | 
|  | case WebAssembly::CALL_INDIRECT: | 
|  | case WebAssembly::CALL_INDIRECT_S: | 
|  | case WebAssembly::RET_CALL_INDIRECT: | 
|  | case WebAssembly::RET_CALL_INDIRECT_S: | 
|  | return MI.getOperand(MI.getNumOperands() - 1); | 
|  | default: | 
|  | llvm_unreachable("Not a call instruction"); | 
|  | } | 
|  | } |