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