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