• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
FunctionBodyForTesting(const byte * start,const byte * end)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 
VerifyWasmCode(AccountingAllocator * allocator,const WasmModule * module,FunctionSig * sig,const byte * start,const byte * end)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 
BuildTFGraph(AccountingAllocator * allocator,TFBuilder * builder,FunctionSig * sig,const byte * start,const byte * end)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.
BodyLocalDeclsBodyLocalDecls85   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.
NON_EXPORTED_BASE(Decoder)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