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