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