LCOV - code coverage report
Current view: top level - src/wasm - wasm-text.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 59 80 73.8 %
Date: 2017-04-26 Functions: 2 2 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             : using namespace v8;
      18             : using namespace v8::internal;
      19             : using namespace v8::internal::wasm;
      20             : 
      21             : namespace {
      22         100 : bool IsValidFunctionName(const Vector<const char> &name) {
      23         100 :   if (name.is_empty()) return false;
      24             :   const char *special_chars = "_.+-*/\\^~=<>!?@#$%&|:'`";
      25         794 :   for (char c : name) {
      26         664 :     bool valid_char = (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') ||
      27         698 :                       (c >= 'A' && c <= 'Z') || strchr(special_chars, c);
      28         594 :     if (!valid_char) return false;
      29             :   }
      30             :   return true;
      31             : }
      32             : 
      33             : }  // namespace
      34             : 
      35         100 : void wasm::PrintWasmText(const WasmModule *module,
      36             :                          const ModuleWireBytes &wire_bytes, uint32_t func_index,
      37             :                          std::ostream &os,
      38             :                          debug::WasmDisassembly::OffsetTable *offset_table) {
      39             :   DCHECK_NOT_NULL(module);
      40             :   DCHECK_GT(module->functions.size(), func_index);
      41         300 :   const WasmFunction *fun = &module->functions[func_index];
      42             : 
      43         100 :   AccountingAllocator allocator;
      44         200 :   Zone zone(&allocator, ZONE_NAME);
      45         100 :   int line_nr = 0;
      46             :   int control_depth = 1;
      47             : 
      48             :   // Print the function signature.
      49         100 :   os << "func";
      50         100 :   WasmName fun_name = wire_bytes.GetNameOrNull(fun);
      51         100 :   if (IsValidFunctionName(fun_name)) {
      52         100 :     os << " $";
      53         100 :     os.write(fun_name.start(), fun_name.length());
      54             :   }
      55         200 :   if (fun->sig->parameter_count()) {
      56          12 :     os << " (param";
      57          36 :     for (auto param : fun->sig->parameters())
      58          12 :       os << ' ' << WasmOpcodes::TypeName(param);
      59             :     os << ')';
      60             :   }
      61         200 :   if (fun->sig->return_count()) {
      62           0 :     os << " (result";
      63           0 :     for (auto ret : fun->sig->returns())
      64           0 :       os << ' ' << WasmOpcodes::TypeName(ret);
      65             :     os << ')';
      66             :   }
      67         100 :   os << "\n";
      68         100 :   ++line_nr;
      69             : 
      70             :   // Print the local declarations.
      71             :   BodyLocalDecls decls(&zone);
      72             :   Vector<const byte> func_bytes = wire_bytes.GetFunctionBytes(fun);
      73         100 :   BytecodeIterator i(func_bytes.begin(), func_bytes.end(), &decls);
      74             :   DCHECK_LT(func_bytes.begin(), i.pc());
      75         100 :   if (!decls.type_list.empty()) {
      76           6 :     os << "(local";
      77          18 :     for (const ValueType &v : decls.type_list) {
      78          12 :       os << ' ' << WasmOpcodes::TypeName(v);
      79             :     }
      80           6 :     os << ")\n";
      81           6 :     ++line_nr;
      82             :   }
      83             : 
      84         370 :   for (; i.has_next(); i.next()) {
      85             :     WasmOpcode opcode = i.current();
      86         370 :     if (opcode == kExprElse || opcode == kExprEnd) --control_depth;
      87             : 
      88             :     DCHECK_LE(0, control_depth);
      89         370 :     const int kMaxIndentation = 64;
      90         740 :     int indentation = std::min(kMaxIndentation, 2 * control_depth);
      91         370 :     if (offset_table) {
      92         740 :       offset_table->emplace_back(i.pc_offset(), line_nr, indentation);
      93             :     }
      94             : 
      95             :     // 64 whitespaces
      96             :     const char padding[kMaxIndentation + 1] =
      97         370 :         "                                                                ";
      98         370 :     os.write(padding, indentation);
      99             : 
     100         370 :     switch (opcode) {
     101             :       case kExprLoop:
     102             :       case kExprIf:
     103             :       case kExprBlock:
     104             :       case kExprTry: {
     105          42 :         BlockTypeOperand<false> operand(&i, i.pc());
     106          42 :         os << WasmOpcodes::OpcodeName(opcode);
     107          42 :         for (unsigned i = 0; i < operand.arity; i++) {
     108           0 :           os << " " << WasmOpcodes::TypeName(operand.read_entry(i));
     109             :         }
     110          42 :         control_depth++;
     111             :         break;
     112             :       }
     113             :       case kExprBr:
     114             :       case kExprBrIf: {
     115           6 :         BreakDepthOperand<false> operand(&i, i.pc());
     116           6 :         os << WasmOpcodes::OpcodeName(opcode) << ' ' << operand.depth;
     117             :         break;
     118             :       }
     119             :       case kExprElse:
     120           0 :         os << "else";
     121           0 :         control_depth++;
     122           0 :         break;
     123             :       case kExprEnd:
     124         142 :         os << "end";
     125         142 :         break;
     126             :       case kExprBrTable: {
     127           0 :         BranchTableOperand<false> operand(&i, i.pc());
     128             :         BranchTableIterator<false> iterator(&i, operand);
     129           0 :         os << "br_table";
     130           0 :         while (iterator.has_next()) os << ' ' << iterator.next();
     131             :         break;
     132             :       }
     133             :       case kExprCallIndirect: {
     134           6 :         CallIndirectOperand<false> operand(&i, i.pc());
     135             :         DCHECK_EQ(0, operand.table_index);
     136           6 :         os << "call_indirect " << operand.index;
     137             :         break;
     138             :       }
     139             :       case kExprCallFunction: {
     140          64 :         CallFunctionOperand<false> operand(&i, i.pc());
     141          64 :         os << "call " << operand.index;
     142             :         break;
     143             :       }
     144             :       case kExprGetLocal:
     145             :       case kExprSetLocal:
     146             :       case kExprTeeLocal:
     147             :       case kExprCatch: {
     148          30 :         LocalIndexOperand<false> operand(&i, i.pc());
     149          30 :         os << WasmOpcodes::OpcodeName(opcode) << ' ' << operand.index;
     150             :         break;
     151             :       }
     152             :       case kExprGetGlobal:
     153             :       case kExprSetGlobal: {
     154           0 :         GlobalIndexOperand<false> operand(&i, i.pc());
     155           0 :         os << WasmOpcodes::OpcodeName(opcode) << ' ' << operand.index;
     156             :         break;
     157             :       }
     158             : #define CASE_CONST(type, str, cast_type)                           \
     159             :   case kExpr##type##Const: {                                       \
     160             :     Imm##type##Operand<false> operand(&i, i.pc());                 \
     161             :     os << #str ".const " << static_cast<cast_type>(operand.value); \
     162             :     break;                                                         \
     163             :   }
     164          24 :         CASE_CONST(I32, i32, int32_t)
     165           0 :         CASE_CONST(I64, i64, int64_t)
     166           0 :         CASE_CONST(F32, f32, float)
     167           0 :         CASE_CONST(F64, f64, double)
     168             : 
     169             : #define CASE_OPCODE(opcode, _, __) case kExpr##opcode:
     170             :         FOREACH_LOAD_MEM_OPCODE(CASE_OPCODE)
     171             :         FOREACH_STORE_MEM_OPCODE(CASE_OPCODE) {
     172           0 :           MemoryAccessOperand<false> operand(&i, i.pc(), kMaxUInt32);
     173           0 :           os << WasmOpcodes::OpcodeName(opcode) << " offset=" << operand.offset
     174           0 :              << " align=" << (1ULL << operand.alignment);
     175             :           break;
     176             :         }
     177             : 
     178             :         FOREACH_SIMPLE_OPCODE(CASE_OPCODE)
     179             :       case kExprUnreachable:
     180             :       case kExprNop:
     181             :       case kExprReturn:
     182             :       case kExprMemorySize:
     183             :       case kExprGrowMemory:
     184             :       case kExprDrop:
     185             :       case kExprSelect:
     186             :       case kExprThrow:
     187          56 :         os << WasmOpcodes::OpcodeName(opcode);
     188          56 :         break;
     189             : 
     190             :         // This group is just printed by their internal opcode name, as they
     191             :         // should never be shown to end-users.
     192             :         FOREACH_ASMJS_COMPAT_OPCODE(CASE_OPCODE)
     193             :         // TODO(wasm): Add correct printing for SIMD and atomic opcodes once
     194             :         // they are publicly available.
     195             :         FOREACH_SIMD_0_OPERAND_OPCODE(CASE_OPCODE)
     196             :         FOREACH_SIMD_1_OPERAND_OPCODE(CASE_OPCODE)
     197             :         FOREACH_ATOMIC_OPCODE(CASE_OPCODE)
     198           0 :         os << WasmOpcodes::OpcodeName(opcode);
     199           0 :         break;
     200             : 
     201             :       default:
     202           0 :         UNREACHABLE();
     203             :         break;
     204             :     }
     205             :     os << '\n';
     206         370 :     ++line_nr;
     207             :   }
     208             :   DCHECK_EQ(0, control_depth);
     209         100 :   DCHECK(i.ok());
     210         100 : }

Generated by: LCOV version 1.10