LCOV - code coverage report
Current view: top level - src/wasm - wasm-text.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 71 95 74.7 %
Date: 2019-01-20 Functions: 4 4 100.0 %

          Line data    Source code
       1             : // Copyright 2016 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/wasm/wasm-text.h"
       6             : 
       7             : #include "src/debug/interface-types.h"
       8             : #include "src/objects-inl.h"
       9             : #include "src/ostreams.h"
      10             : #include "src/vector.h"
      11             : #include "src/wasm/function-body-decoder-impl.h"
      12             : #include "src/wasm/function-body-decoder.h"
      13             : #include "src/wasm/wasm-module.h"
      14             : #include "src/wasm/wasm-opcodes.h"
      15             : #include "src/zone/zone.h"
      16             : 
      17             : namespace v8 {
      18             : namespace internal {
      19             : namespace wasm {
      20             : 
      21             : namespace {
      22          97 : bool IsValidFunctionName(const Vector<const char> &name) {
      23          97 :   if (name.is_empty()) return false;
      24             :   const char *special_chars = "_.+-*/\\^~=<>!?@#$%&|:'`";
      25         723 :   for (char c : name) {
      26         612 :     bool valid_char = (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') ||
      27         635 :                       (c >= 'A' && c <= 'Z') || strchr(special_chars, c);
      28         539 :     if (!valid_char) return false;
      29             :   }
      30             :   return true;
      31             : }
      32             : 
      33             : }  // namespace
      34             : 
      35          97 : void PrintWasmText(const WasmModule* module, const ModuleWireBytes& wire_bytes,
      36             :                    uint32_t func_index, std::ostream& os,
      37             :                    debug::WasmDisassembly::OffsetTable* offset_table) {
      38             :   DCHECK_NOT_NULL(module);
      39             :   DCHECK_GT(module->functions.size(), func_index);
      40          97 :   const WasmFunction *fun = &module->functions[func_index];
      41             : 
      42          97 :   AccountingAllocator allocator;
      43         194 :   Zone zone(&allocator, ZONE_NAME);
      44          97 :   int line_nr = 0;
      45             :   int control_depth = 1;
      46             : 
      47             :   // Print the function signature.
      48          97 :   os << "func";
      49          97 :   WasmName fun_name = wire_bytes.GetNameOrNull(fun, module);
      50          97 :   if (IsValidFunctionName(fun_name)) {
      51          92 :     os << " $";
      52         184 :     os.write(fun_name.start(), fun_name.length());
      53             :   }
      54         199 :   if (fun->sig->parameter_count()) {
      55          25 :     os << " (param";
      56          75 :     for (auto param : fun->sig->parameters())
      57          50 :       os << ' ' << ValueTypes::TypeName(param);
      58             :     os << ')';
      59             :   }
      60         194 :   if (fun->sig->return_count()) {
      61           5 :     os << " (result";
      62          15 :     for (auto ret : fun->sig->returns()) os << ' ' << ValueTypes::TypeName(ret);
      63             :     os << ')';
      64             :   }
      65          97 :   os << "\n";
      66          97 :   ++line_nr;
      67             : 
      68             :   // Print the local declarations.
      69             :   BodyLocalDecls decls(&zone);
      70             :   Vector<const byte> func_bytes = wire_bytes.GetFunctionBytes(fun);
      71          97 :   BytecodeIterator i(func_bytes.begin(), func_bytes.end(), &decls);
      72             :   DCHECK_LT(func_bytes.begin(), i.pc());
      73          97 :   if (!decls.type_list.empty()) {
      74          10 :     os << "(local";
      75          40 :     for (const ValueType &v : decls.type_list) {
      76          40 :       os << ' ' << ValueTypes::TypeName(v);
      77             :     }
      78          10 :     os << ")\n";
      79          10 :     ++line_nr;
      80             :   }
      81             : 
      82         464 :   for (; i.has_next(); i.next()) {
      83             :     WasmOpcode opcode = i.current();
      84         464 :     if (opcode == kExprElse || opcode == kExprCatch || opcode == kExprEnd) {
      85         142 :       --control_depth;
      86             :     }
      87             : 
      88             :     DCHECK_LE(0, control_depth);
      89         464 :     const int kMaxIndentation = 64;
      90         928 :     int indentation = std::min(kMaxIndentation, 2 * control_depth);
      91         464 :     if (offset_table) {
      92         464 :       offset_table->emplace_back(i.pc_offset(), line_nr, indentation);
      93             :     }
      94             : 
      95             :     // 64 whitespaces
      96             :     const char padding[kMaxIndentation + 1] =
      97         464 :         "                                                                ";
      98         464 :     os.write(padding, indentation);
      99             : 
     100         464 :     switch (opcode) {
     101             :       case kExprLoop:
     102             :       case kExprIf:
     103             :       case kExprBlock:
     104             :       case kExprTry: {
     105             :         BlockTypeImmediate<Decoder::kNoValidate> imm(kAllWasmFeatures, &i,
     106          45 :                                                      i.pc());
     107          45 :         os << WasmOpcodes::OpcodeName(opcode);
     108          45 :         if (imm.type == kWasmVar) {
     109           0 :           os << " (type " << imm.sig_index << ")";
     110          45 :         } else if (imm.out_arity() > 0) {
     111           0 :           os << " " << ValueTypes::TypeName(imm.out_type(0));
     112             :         }
     113          45 :         control_depth++;
     114             :         break;
     115             :       }
     116             :       case kExprBr:
     117             :       case kExprBrIf: {
     118          10 :         BranchDepthImmediate<Decoder::kNoValidate> imm(&i, i.pc());
     119          10 :         os << WasmOpcodes::OpcodeName(opcode) << ' ' << imm.depth;
     120             :         break;
     121             :       }
     122             :       case kExprBrOnExn: {
     123           0 :         BranchDepthImmediate<Decoder::kNoValidate> imm_br(&i, i.pc());
     124             :         ExceptionIndexImmediate<Decoder::kNoValidate> imm_idx(
     125           0 :             &i, i.pc() + imm_br.length);
     126           0 :         os << WasmOpcodes::OpcodeName(opcode) << ' ' << imm_br.depth << ' '
     127             :            << imm_idx.index;
     128             :         break;
     129             :       }
     130             :       case kExprElse:
     131             :       case kExprCatch:
     132           0 :         os << WasmOpcodes::OpcodeName(opcode);
     133           0 :         control_depth++;
     134           0 :         break;
     135             :       case kExprEnd:
     136         142 :         os << "end";
     137         142 :         break;
     138             :       case kExprBrTable: {
     139           0 :         BranchTableImmediate<Decoder::kNoValidate> imm(&i, i.pc());
     140             :         BranchTableIterator<Decoder::kNoValidate> iterator(&i, imm);
     141           0 :         os << "br_table";
     142           0 :         while (iterator.has_next()) os << ' ' << iterator.next();
     143             :         break;
     144             :       }
     145             :       case kExprCallIndirect: {
     146           5 :         CallIndirectImmediate<Decoder::kNoValidate> imm(&i, i.pc());
     147             :         DCHECK_EQ(0, imm.table_index);
     148           5 :         os << "call_indirect " << imm.sig_index;
     149             :         break;
     150             :       }
     151             :       case kExprCallFunction: {
     152          48 :         CallFunctionImmediate<Decoder::kNoValidate> imm(&i, i.pc());
     153          48 :         os << "call " << imm.index;
     154             :         break;
     155             :       }
     156             :       case kExprGetLocal:
     157             :       case kExprSetLocal:
     158             :       case kExprTeeLocal: {
     159          70 :         LocalIndexImmediate<Decoder::kNoValidate> imm(&i, i.pc());
     160          70 :         os << WasmOpcodes::OpcodeName(opcode) << ' ' << imm.index;
     161             :         break;
     162             :       }
     163             :       case kExprThrow: {
     164           0 :         ExceptionIndexImmediate<Decoder::kNoValidate> imm(&i, i.pc());
     165           0 :         os << WasmOpcodes::OpcodeName(opcode) << ' ' << imm.index;
     166             :         break;
     167             :       }
     168             :       case kExprGetGlobal:
     169             :       case kExprSetGlobal: {
     170           0 :         GlobalIndexImmediate<Decoder::kNoValidate> imm(&i, i.pc());
     171           0 :         os << WasmOpcodes::OpcodeName(opcode) << ' ' << imm.index;
     172             :         break;
     173             :       }
     174             : #define CASE_CONST(type, str, cast_type)                        \
     175             :   case kExpr##type##Const: {                                    \
     176             :     Imm##type##Immediate<Decoder::kNoValidate> imm(&i, i.pc()); \
     177             :     os << #str ".const " << static_cast<cast_type>(imm.value);  \
     178             :     break;                                                      \
     179             :   }
     180         110 :         CASE_CONST(I32, i32, int32_t)
     181          20 :         CASE_CONST(I64, i64, int64_t)
     182           0 :         CASE_CONST(F32, f32, float)
     183           0 :         CASE_CONST(F64, f64, double)
     184             : #undef CASE_CONST
     185             : 
     186             : #define CASE_OPCODE(opcode, _, __) case kExpr##opcode:
     187             :         FOREACH_LOAD_MEM_OPCODE(CASE_OPCODE)
     188             :         FOREACH_STORE_MEM_OPCODE(CASE_OPCODE) {
     189             :           MemoryAccessImmediate<Decoder::kNoValidate> imm(&i, i.pc(),
     190           0 :                                                           kMaxUInt32);
     191           0 :           os << WasmOpcodes::OpcodeName(opcode) << " offset=" << imm.offset
     192           0 :              << " align=" << (1ULL << imm.alignment);
     193             :           break;
     194             :         }
     195             : 
     196             :         FOREACH_SIMPLE_OPCODE(CASE_OPCODE)
     197             :       case kExprUnreachable:
     198             :       case kExprNop:
     199             :       case kExprReturn:
     200             :       case kExprMemorySize:
     201             :       case kExprMemoryGrow:
     202             :       case kExprDrop:
     203             :       case kExprSelect:
     204          69 :         os << WasmOpcodes::OpcodeName(opcode);
     205          69 :         break;
     206             :       case kAtomicPrefix: {
     207          10 :         WasmOpcode atomic_opcode = i.prefixed_opcode();
     208          10 :         switch (atomic_opcode) {
     209             :           FOREACH_ATOMIC_OPCODE(CASE_OPCODE) {
     210             :             MemoryAccessImmediate<Decoder::kNoValidate> imm(&i, i.pc(),
     211          10 :                                                             kMaxUInt32);
     212          10 :             os << WasmOpcodes::OpcodeName(atomic_opcode)
     213          20 :                << " offset=" << imm.offset
     214          20 :                << " align=" << (1ULL << imm.alignment);
     215             :             break;
     216             :           }
     217             :           default:
     218           0 :             UNREACHABLE();
     219             :             break;
     220             :         }
     221             :         break;
     222             :       }
     223             : 
     224             :         // This group is just printed by their internal opcode name, as they
     225             :         // should never be shown to end-users.
     226             :         FOREACH_ASMJS_COMPAT_OPCODE(CASE_OPCODE)
     227             :         // TODO(wasm): Add correct printing for SIMD and atomic opcodes once
     228             :         // they are publicly available.
     229             :         FOREACH_SIMD_0_OPERAND_OPCODE(CASE_OPCODE)
     230             :         FOREACH_SIMD_1_OPERAND_OPCODE(CASE_OPCODE)
     231             :         FOREACH_SIMD_MASK_OPERAND_OPCODE(CASE_OPCODE)
     232             :         FOREACH_SIMD_MEM_OPCODE(CASE_OPCODE)
     233           0 :         os << WasmOpcodes::OpcodeName(opcode);
     234           0 :         break;
     235             : #undef CASE_OPCODE
     236             : 
     237             :       default:
     238           0 :         UNREACHABLE();
     239             :         break;
     240             :     }
     241             :     os << '\n';
     242         464 :     ++line_nr;
     243             :   }
     244             :   DCHECK_EQ(0, control_depth);
     245          97 :   DCHECK(i.ok());
     246          97 : }
     247             : 
     248             : }  // namespace wasm
     249             : }  // namespace internal
     250      183867 : }  // namespace v8

Generated by: LCOV version 1.10