LCOV - code coverage report
Current view: top level - lib/Target/WebAssembly - WebAssemblyUtilities.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 46 70 65.7 %
Date: 2018-10-20 13:21:21 Functions: 10 14 71.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===-- WebAssemblyUtilities.cpp - WebAssembly Utility Functions ----------===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : ///
      10             : /// \file
      11             : /// This file implements several utility functions for WebAssembly.
      12             : ///
      13             : //===----------------------------------------------------------------------===//
      14             : 
      15             : #include "WebAssemblyUtilities.h"
      16             : #include "WebAssemblyMachineFunctionInfo.h"
      17             : #include "llvm/CodeGen/MachineInstr.h"
      18             : #include "llvm/CodeGen/MachineLoopInfo.h"
      19             : using namespace llvm;
      20             : 
      21             : const char *const WebAssembly::ClangCallTerminateFn = "__clang_call_terminate";
      22             : const char *const WebAssembly::CxaBeginCatchFn = "__cxa_begin_catch";
      23             : const char *const WebAssembly::CxaRethrowFn = "__cxa_rethrow";
      24             : const char *const WebAssembly::StdTerminateFn = "_ZSt9terminatev";
      25             : const char *const WebAssembly::PersonalityWrapperFn =
      26             :     "_Unwind_Wasm_CallPersonality";
      27             : 
      28      156741 : bool WebAssembly::isArgument(const MachineInstr &MI) {
      29      313482 :   switch (MI.getOpcode()) {
      30             :   case WebAssembly::ARGUMENT_i32:
      31             :   case WebAssembly::ARGUMENT_i32_S:
      32             :   case WebAssembly::ARGUMENT_i64:
      33             :   case WebAssembly::ARGUMENT_i64_S:
      34             :   case WebAssembly::ARGUMENT_f32:
      35             :   case WebAssembly::ARGUMENT_f32_S:
      36             :   case WebAssembly::ARGUMENT_f64:
      37             :   case WebAssembly::ARGUMENT_f64_S:
      38             :   case WebAssembly::ARGUMENT_v16i8:
      39             :   case WebAssembly::ARGUMENT_v16i8_S:
      40             :   case WebAssembly::ARGUMENT_v8i16:
      41             :   case WebAssembly::ARGUMENT_v8i16_S:
      42             :   case WebAssembly::ARGUMENT_v4i32:
      43             :   case WebAssembly::ARGUMENT_v4i32_S:
      44             :   case WebAssembly::ARGUMENT_v2i64:
      45             :   case WebAssembly::ARGUMENT_v2i64_S:
      46             :   case WebAssembly::ARGUMENT_v4f32:
      47             :   case WebAssembly::ARGUMENT_v4f32_S:
      48             :   case WebAssembly::ARGUMENT_v2f64:
      49             :   case WebAssembly::ARGUMENT_v2f64_S:
      50             :     return true;
      51      119530 :   default:
      52      119530 :     return false;
      53             :   }
      54             : }
      55             : 
      56        3879 : bool WebAssembly::isCopy(const MachineInstr &MI) {
      57        7758 :   switch (MI.getOpcode()) {
      58             :   case WebAssembly::COPY_I32:
      59             :   case WebAssembly::COPY_I32_S:
      60             :   case WebAssembly::COPY_I64:
      61             :   case WebAssembly::COPY_I64_S:
      62             :   case WebAssembly::COPY_F32:
      63             :   case WebAssembly::COPY_F32_S:
      64             :   case WebAssembly::COPY_F64:
      65             :   case WebAssembly::COPY_F64_S:
      66             :   case WebAssembly::COPY_V128:
      67             :   case WebAssembly::COPY_V128_S:
      68             :     return true;
      69        3840 :   default:
      70        3840 :     return false;
      71             :   }
      72             : }
      73             : 
      74        3981 : bool WebAssembly::isTee(const MachineInstr &MI) {
      75        3981 :   switch (MI.getOpcode()) {
      76             :   case WebAssembly::TEE_I32:
      77             :   case WebAssembly::TEE_I32_S:
      78             :   case WebAssembly::TEE_I64:
      79             :   case WebAssembly::TEE_I64_S:
      80             :   case WebAssembly::TEE_F32:
      81             :   case WebAssembly::TEE_F32_S:
      82             :   case WebAssembly::TEE_F64:
      83             :   case WebAssembly::TEE_F64_S:
      84             :   case WebAssembly::TEE_V128:
      85             :   case WebAssembly::TEE_V128_S:
      86             :     return true;
      87             :   default:
      88             :     return false;
      89             :   }
      90             : }
      91             : 
      92             : /// Test whether MI is a child of some other node in an expression tree.
      93         709 : bool WebAssembly::isChild(const MachineInstr &MI,
      94             :                           const WebAssemblyFunctionInfo &MFI) {
      95         709 :   if (MI.getNumOperands() == 0)
      96             :     return false;
      97         709 :   const MachineOperand &MO = MI.getOperand(0);
      98         709 :   if (!MO.isReg() || MO.isImplicit() || !MO.isDef())
      99             :     return false;
     100         527 :   unsigned Reg = MO.getReg();
     101        1047 :   return TargetRegisterInfo::isVirtualRegister(Reg) &&
     102             :          MFI.isVRegStackified(Reg);
     103             : }
     104             : 
     105           0 : bool WebAssembly::isCallDirect(const MachineInstr &MI) {
     106           0 :   switch (MI.getOpcode()) {
     107             :   case WebAssembly::CALL_VOID:
     108             :   case WebAssembly::CALL_VOID_S:
     109             :   case WebAssembly::CALL_I32:
     110             :   case WebAssembly::CALL_I32_S:
     111             :   case WebAssembly::CALL_I64:
     112             :   case WebAssembly::CALL_I64_S:
     113             :   case WebAssembly::CALL_F32:
     114             :   case WebAssembly::CALL_F32_S:
     115             :   case WebAssembly::CALL_F64:
     116             :   case WebAssembly::CALL_F64_S:
     117             :   case WebAssembly::CALL_v16i8:
     118             :   case WebAssembly::CALL_v16i8_S:
     119             :   case WebAssembly::CALL_v8i16:
     120             :   case WebAssembly::CALL_v8i16_S:
     121             :   case WebAssembly::CALL_v4i32:
     122             :   case WebAssembly::CALL_v4i32_S:
     123             :   case WebAssembly::CALL_v2i64:
     124             :   case WebAssembly::CALL_v2i64_S:
     125             :   case WebAssembly::CALL_v4f32:
     126             :   case WebAssembly::CALL_v4f32_S:
     127             :   case WebAssembly::CALL_v2f64:
     128             :   case WebAssembly::CALL_v2f64_S:
     129             :   case WebAssembly::CALL_EXCEPT_REF:
     130             :   case WebAssembly::CALL_EXCEPT_REF_S:
     131             :     return true;
     132             :   default:
     133             :     return false;
     134             :   }
     135             : }
     136             : 
     137          33 : bool WebAssembly::isCallIndirect(const MachineInstr &MI) {
     138          66 :   switch (MI.getOpcode()) {
     139             :   case WebAssembly::CALL_INDIRECT_VOID:
     140             :   case WebAssembly::CALL_INDIRECT_VOID_S:
     141             :   case WebAssembly::CALL_INDIRECT_I32:
     142             :   case WebAssembly::CALL_INDIRECT_I32_S:
     143             :   case WebAssembly::CALL_INDIRECT_I64:
     144             :   case WebAssembly::CALL_INDIRECT_I64_S:
     145             :   case WebAssembly::CALL_INDIRECT_F32:
     146             :   case WebAssembly::CALL_INDIRECT_F32_S:
     147             :   case WebAssembly::CALL_INDIRECT_F64:
     148             :   case WebAssembly::CALL_INDIRECT_F64_S:
     149             :   case WebAssembly::CALL_INDIRECT_v16i8:
     150             :   case WebAssembly::CALL_INDIRECT_v16i8_S:
     151             :   case WebAssembly::CALL_INDIRECT_v8i16:
     152             :   case WebAssembly::CALL_INDIRECT_v8i16_S:
     153             :   case WebAssembly::CALL_INDIRECT_v4i32:
     154             :   case WebAssembly::CALL_INDIRECT_v4i32_S:
     155             :   case WebAssembly::CALL_INDIRECT_v2i64:
     156             :   case WebAssembly::CALL_INDIRECT_v2i64_S:
     157             :   case WebAssembly::CALL_INDIRECT_v4f32:
     158             :   case WebAssembly::CALL_INDIRECT_v4f32_S:
     159             :   case WebAssembly::CALL_INDIRECT_v2f64:
     160             :   case WebAssembly::CALL_INDIRECT_v2f64_S:
     161             :   case WebAssembly::CALL_INDIRECT_EXCEPT_REF:
     162             :   case WebAssembly::CALL_INDIRECT_EXCEPT_REF_S:
     163             :     return true;
     164           0 :   default:
     165           0 :     return false;
     166             :   }
     167             : }
     168             : 
     169         237 : unsigned WebAssembly::getCalleeOpNo(const MachineInstr &MI) {
     170         237 :   switch (MI.getOpcode()) {
     171             :   case WebAssembly::CALL_VOID:
     172             :   case WebAssembly::CALL_VOID_S:
     173             :   case WebAssembly::CALL_INDIRECT_VOID:
     174             :   case WebAssembly::CALL_INDIRECT_VOID_S:
     175             :     return 0;
     176             :   case WebAssembly::CALL_I32:
     177             :   case WebAssembly::CALL_I32_S:
     178             :   case WebAssembly::CALL_I64:
     179             :   case WebAssembly::CALL_I64_S:
     180             :   case WebAssembly::CALL_F32:
     181             :   case WebAssembly::CALL_F32_S:
     182             :   case WebAssembly::CALL_F64:
     183             :   case WebAssembly::CALL_F64_S:
     184             :   case WebAssembly::CALL_v16i8:
     185             :   case WebAssembly::CALL_v16i8_S:
     186             :   case WebAssembly::CALL_v8i16:
     187             :   case WebAssembly::CALL_v8i16_S:
     188             :   case WebAssembly::CALL_v4i32:
     189             :   case WebAssembly::CALL_v4i32_S:
     190             :   case WebAssembly::CALL_v2i64:
     191             :   case WebAssembly::CALL_v2i64_S:
     192             :   case WebAssembly::CALL_v4f32:
     193             :   case WebAssembly::CALL_v4f32_S:
     194             :   case WebAssembly::CALL_v2f64:
     195             :   case WebAssembly::CALL_v2f64_S:
     196             :   case WebAssembly::CALL_EXCEPT_REF:
     197             :   case WebAssembly::CALL_EXCEPT_REF_S:
     198             :   case WebAssembly::CALL_INDIRECT_I32:
     199             :   case WebAssembly::CALL_INDIRECT_I32_S:
     200             :   case WebAssembly::CALL_INDIRECT_I64:
     201             :   case WebAssembly::CALL_INDIRECT_I64_S:
     202             :   case WebAssembly::CALL_INDIRECT_F32:
     203             :   case WebAssembly::CALL_INDIRECT_F32_S:
     204             :   case WebAssembly::CALL_INDIRECT_F64:
     205             :   case WebAssembly::CALL_INDIRECT_F64_S:
     206             :   case WebAssembly::CALL_INDIRECT_v16i8:
     207             :   case WebAssembly::CALL_INDIRECT_v16i8_S:
     208             :   case WebAssembly::CALL_INDIRECT_v8i16:
     209             :   case WebAssembly::CALL_INDIRECT_v8i16_S:
     210             :   case WebAssembly::CALL_INDIRECT_v4i32:
     211             :   case WebAssembly::CALL_INDIRECT_v4i32_S:
     212             :   case WebAssembly::CALL_INDIRECT_v2i64:
     213             :   case WebAssembly::CALL_INDIRECT_v2i64_S:
     214             :   case WebAssembly::CALL_INDIRECT_v4f32:
     215             :   case WebAssembly::CALL_INDIRECT_v4f32_S:
     216             :   case WebAssembly::CALL_INDIRECT_v2f64:
     217             :   case WebAssembly::CALL_INDIRECT_v2f64_S:
     218             :   case WebAssembly::CALL_INDIRECT_EXCEPT_REF:
     219             :   case WebAssembly::CALL_INDIRECT_EXCEPT_REF_S:
     220             :     return 1;
     221           0 :   default:
     222           0 :     llvm_unreachable("Not a call instruction");
     223             :   }
     224             : }
     225             : 
     226           0 : bool WebAssembly::isMarker(const MachineInstr &MI) {
     227           0 :   switch (MI.getOpcode()) {
     228             :   case WebAssembly::BLOCK:
     229             :   case WebAssembly::BLOCK_S:
     230             :   case WebAssembly::END_BLOCK:
     231             :   case WebAssembly::END_BLOCK_S:
     232             :   case WebAssembly::LOOP:
     233             :   case WebAssembly::LOOP_S:
     234             :   case WebAssembly::END_LOOP:
     235             :   case WebAssembly::END_LOOP_S:
     236             :   case WebAssembly::TRY:
     237             :   case WebAssembly::TRY_S:
     238             :   case WebAssembly::END_TRY:
     239             :   case WebAssembly::END_TRY_S:
     240             :     return true;
     241           0 :   default:
     242           0 :     return false;
     243             :   }
     244             : }
     245             : 
     246           0 : bool WebAssembly::isThrow(const MachineInstr &MI) {
     247           0 :   switch (MI.getOpcode()) {
     248             :   case WebAssembly::THROW_I32:
     249             :   case WebAssembly::THROW_I32_S:
     250             :   case WebAssembly::THROW_I64:
     251             :   case WebAssembly::THROW_I64_S:
     252             :     return true;
     253           0 :   default:
     254           0 :     return false;
     255             :   }
     256             : }
     257             : 
     258         546 : bool WebAssembly::isRethrow(const MachineInstr &MI) {
     259        1092 :   switch (MI.getOpcode()) {
     260             :   case WebAssembly::RETHROW:
     261             :   case WebAssembly::RETHROW_S:
     262             :   case WebAssembly::RETHROW_TO_CALLER:
     263             :   case WebAssembly::RETHROW_TO_CALLER_S:
     264             :     return true;
     265         546 :   default:
     266         546 :     return false;
     267             :   }
     268             : }
     269             : 
     270         339 : bool WebAssembly::isCatch(const MachineInstr &MI) {
     271         678 :   switch (MI.getOpcode()) {
     272             :   case WebAssembly::CATCH_I32:
     273             :   case WebAssembly::CATCH_I32_S:
     274             :   case WebAssembly::CATCH_I64:
     275             :   case WebAssembly::CATCH_I64_S:
     276             :   case WebAssembly::CATCH_ALL:
     277             :   case WebAssembly::CATCH_ALL_S:
     278             :     return true;
     279         306 :   default:
     280         306 :     return false;
     281             :   }
     282             : }
     283             : 
     284           0 : bool WebAssembly::mayThrow(const MachineInstr &MI) {
     285           0 :   switch (MI.getOpcode()) {
     286             :   case WebAssembly::THROW_I32:
     287             :   case WebAssembly::THROW_I32_S:
     288             :   case WebAssembly::THROW_I64:
     289             :   case WebAssembly::THROW_I64_S:
     290             :   case WebAssembly::RETHROW:
     291             :   case WebAssembly::RETHROW_S:
     292             :     return true;
     293             :   }
     294           0 :   if (isCallIndirect(MI))
     295             :     return true;
     296           0 :   if (!MI.isCall())
     297             :     return false;
     298             : 
     299           0 :   const MachineOperand &MO = MI.getOperand(getCalleeOpNo(MI));
     300             :   assert(MO.isGlobal());
     301           0 :   const auto *F = dyn_cast<Function>(MO.getGlobal());
     302             :   if (!F)
     303             :     return true;
     304           0 :   if (F->doesNotThrow())
     305             :     return false;
     306             :   // These functions never throw
     307           0 :   if (F->getName() == CxaBeginCatchFn || F->getName() == PersonalityWrapperFn ||
     308           0 :       F->getName() == ClangCallTerminateFn || F->getName() == StdTerminateFn)
     309           0 :     return false;
     310             :   return true;
     311             : }
     312             : 
     313         149 : bool WebAssembly::isCatchTerminatePad(const MachineBasicBlock &MBB) {
     314         149 :   if (!MBB.isEHPad())
     315             :     return false;
     316             :   bool SeenCatch = false;
     317         601 :   for (auto &MI : MBB) {
     318         540 :     if (MI.getOpcode() == WebAssembly::CATCH_I32 ||
     319         501 :         MI.getOpcode() == WebAssembly::CATCH_I64 ||
     320        1041 :         MI.getOpcode() == WebAssembly::CATCH_I32_S ||
     321             :         MI.getOpcode() == WebAssembly::CATCH_I64_S)
     322             :       SeenCatch = true;
     323         885 :     if (SeenCatch && MI.isCall()) {
     324          45 :       const MachineOperand &CalleeOp = MI.getOperand(getCalleeOpNo(MI));
     325          45 :       if (CalleeOp.isGlobal() &&
     326          45 :           CalleeOp.getGlobal()->getName() == ClangCallTerminateFn)
     327             :         return true;
     328             :     }
     329             :   }
     330             :   return false;
     331             : }
     332             : 
     333          62 : bool WebAssembly::isCatchAllTerminatePad(const MachineBasicBlock &MBB) {
     334          62 :   if (!MBB.isEHPad())
     335             :     return false;
     336             :   bool SeenCatchAll = false;
     337         507 :   for (auto &MI : MBB) {
     338         900 :     if (MI.getOpcode() == WebAssembly::CATCH_ALL ||
     339             :         MI.getOpcode() == WebAssembly::CATCH_ALL_S)
     340             :       SeenCatchAll = true;
     341         546 :     if (SeenCatchAll && MI.isCall()) {
     342          21 :       const MachineOperand &CalleeOp = MI.getOperand(getCalleeOpNo(MI));
     343          21 :       if (CalleeOp.isGlobal() &&
     344          21 :           CalleeOp.getGlobal()->getName() == StdTerminateFn)
     345             :         return true;
     346             :     }
     347             :   }
     348             :   return false;
     349             : }

Generated by: LCOV version 1.13