Home | History | Annotate | Download | only in wasm
      1 // Copyright 2015 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 #ifndef V8_WASM_FUNCTION_BODY_DECODER_H_
      6 #define V8_WASM_FUNCTION_BODY_DECODER_H_
      7 
      8 #include <iterator>
      9 
     10 #include "src/base/compiler-specific.h"
     11 #include "src/base/iterator.h"
     12 #include "src/globals.h"
     13 #include "src/signature.h"
     14 #include "src/wasm/decoder.h"
     15 #include "src/wasm/wasm-opcodes.h"
     16 #include "src/wasm/wasm-result.h"
     17 
     18 namespace v8 {
     19 namespace internal {
     20 
     21 class BitVector;  // forward declaration
     22 
     23 namespace compiler {  // external declarations from compiler.
     24 class WasmGraphBuilder;
     25 }
     26 
     27 namespace wasm {
     28 
     29 typedef compiler::WasmGraphBuilder TFBuilder;
     30 struct WasmModule;  // forward declaration of module interface.
     31 
     32 // A wrapper around the signature and bytes of a function.
     33 struct FunctionBody {
     34   FunctionSig* sig;   // function signature
     35   const byte* base;   // base of the module bytes, for error reporting
     36   const byte* start;  // start of the function body
     37   const byte* end;    // end of the function body
     38 };
     39 
     40 static inline FunctionBody FunctionBodyForTesting(const byte* start,
     41                                                   const byte* end) {
     42   return {nullptr, start, start, end};
     43 }
     44 
     45 struct DecodeStruct {
     46   int unused;
     47 };
     48 typedef Result<DecodeStruct*> DecodeResult;
     49 inline std::ostream& operator<<(std::ostream& os, const DecodeStruct& tree) {
     50   return os;
     51 }
     52 
     53 V8_EXPORT_PRIVATE DecodeResult VerifyWasmCode(AccountingAllocator* allocator,
     54                                               const wasm::WasmModule* module,
     55                                               FunctionBody& body);
     56 DecodeResult BuildTFGraph(AccountingAllocator* allocator, TFBuilder* builder,
     57                           FunctionBody& body);
     58 bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
     59                       const wasm::WasmModule* module);
     60 
     61 // A simplified form of AST printing, e.g. from a debugger.
     62 void PrintRawWasmCode(const byte* start, const byte* end);
     63 
     64 inline DecodeResult VerifyWasmCode(AccountingAllocator* allocator,
     65                                    const WasmModule* module, FunctionSig* sig,
     66                                    const byte* start, const byte* end) {
     67   FunctionBody body = {sig, nullptr, start, end};
     68   return VerifyWasmCode(allocator, module, body);
     69 }
     70 
     71 inline DecodeResult BuildTFGraph(AccountingAllocator* allocator,
     72                                  TFBuilder* builder, FunctionSig* sig,
     73                                  const byte* start, const byte* end) {
     74   FunctionBody body = {sig, nullptr, start, end};
     75   return BuildTFGraph(allocator, builder, body);
     76 }
     77 
     78 struct BodyLocalDecls {
     79   // The size of the encoded declarations.
     80   uint32_t encoded_size;  // size of encoded declarations
     81 
     82   ZoneVector<ValueType> type_list;
     83 
     84   // Constructor initializes the vector.
     85   explicit BodyLocalDecls(Zone* zone) : encoded_size(0), type_list(zone) {}
     86 };
     87 
     88 V8_EXPORT_PRIVATE bool DecodeLocalDecls(BodyLocalDecls* decls,
     89                                         const byte* start, const byte* end);
     90 V8_EXPORT_PRIVATE BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone,
     91                                                              size_t num_locals,
     92                                                              const byte* start,
     93                                                              const byte* end);
     94 
     95 // Computes the length of the opcode at the given address.
     96 V8_EXPORT_PRIVATE unsigned OpcodeLength(const byte* pc, const byte* end);
     97 
     98 // A simple forward iterator for bytecodes.
     99 class V8_EXPORT_PRIVATE BytecodeIterator : public NON_EXPORTED_BASE(Decoder) {
    100   // Base class for both iterators defined below.
    101   class iterator_base {
    102    public:
    103     inline iterator_base& operator++() {
    104       DCHECK_LT(ptr_, end_);
    105       ptr_ += OpcodeLength(ptr_, end_);
    106       return *this;
    107     }
    108     inline bool operator==(const iterator_base& that) {
    109       return this->ptr_ == that.ptr_;
    110     }
    111     inline bool operator!=(const iterator_base& that) {
    112       return this->ptr_ != that.ptr_;
    113     }
    114 
    115    protected:
    116     const byte* ptr_;
    117     const byte* end_;
    118     iterator_base(const byte* ptr, const byte* end) : ptr_(ptr), end_(end) {}
    119   };
    120 
    121  public:
    122   // If one wants to iterate over the bytecode without looking at {pc_offset()}.
    123   class opcode_iterator
    124       : public iterator_base,
    125         public std::iterator<std::input_iterator_tag, WasmOpcode> {
    126    public:
    127     inline WasmOpcode operator*() {
    128       DCHECK_LT(ptr_, end_);
    129       return static_cast<WasmOpcode>(*ptr_);
    130     }
    131 
    132    private:
    133     friend class BytecodeIterator;
    134     opcode_iterator(const byte* ptr, const byte* end)
    135         : iterator_base(ptr, end) {}
    136   };
    137   // If one wants to iterate over the instruction offsets without looking at
    138   // opcodes.
    139   class offset_iterator
    140       : public iterator_base,
    141         public std::iterator<std::input_iterator_tag, uint32_t> {
    142    public:
    143     inline uint32_t operator*() {
    144       DCHECK_LT(ptr_, end_);
    145       return static_cast<uint32_t>(ptr_ - start_);
    146     }
    147 
    148    private:
    149     const byte* start_;
    150     friend class BytecodeIterator;
    151     offset_iterator(const byte* start, const byte* ptr, const byte* end)
    152         : iterator_base(ptr, end), start_(start) {}
    153   };
    154 
    155   // Create a new {BytecodeIterator}. If the {decls} pointer is non-null,
    156   // assume the bytecode starts with local declarations and decode them.
    157   // Otherwise, do not decode local decls.
    158   BytecodeIterator(const byte* start, const byte* end,
    159                    BodyLocalDecls* decls = nullptr);
    160 
    161   base::iterator_range<opcode_iterator> opcodes() {
    162     return base::iterator_range<opcode_iterator>(opcode_iterator(pc_, end_),
    163                                                  opcode_iterator(end_, end_));
    164   }
    165 
    166   base::iterator_range<offset_iterator> offsets() {
    167     return base::iterator_range<offset_iterator>(
    168         offset_iterator(start_, pc_, end_),
    169         offset_iterator(start_, end_, end_));
    170   }
    171 
    172   WasmOpcode current() {
    173     return static_cast<WasmOpcode>(
    174         checked_read_u8(pc_, 0, "expected bytecode"));
    175   }
    176 
    177   void next() {
    178     if (pc_ < end_) {
    179       pc_ += OpcodeLength(pc_, end_);
    180       if (pc_ >= end_) pc_ = end_;
    181     }
    182   }
    183 
    184   bool has_next() { return pc_ < end_; }
    185 };
    186 
    187 }  // namespace wasm
    188 }  // namespace internal
    189 }  // namespace v8
    190 
    191 #endif  // V8_WASM_FUNCTION_BODY_DECODER_H_
    192