• 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/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 
FunctionBodyFunctionBody40   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 
BodyLocalDeclsBodyLocalDecls76   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.
NON_EXPORTED_BASE(Decoder)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