forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			99 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			99 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
//===-- 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");
 | 
						|
  }
 | 
						|
}
 |