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 : #include "src/wasm/function-body-decoder.h"
6 :
7 : #include "src/flags.h"
8 : #include "src/handles.h"
9 : #include "src/objects-inl.h"
10 : #include "src/ostreams.h"
11 : #include "src/wasm/decoder.h"
12 : #include "src/wasm/function-body-decoder-impl.h"
13 : #include "src/wasm/wasm-limits.h"
14 : #include "src/wasm/wasm-linkage.h"
15 : #include "src/wasm/wasm-module.h"
16 : #include "src/wasm/wasm-opcodes.h"
17 :
18 : namespace v8 {
19 : namespace internal {
20 : namespace wasm {
21 :
22 368419 : bool DecodeLocalDecls(const WasmFeatures& enabled, BodyLocalDecls* decls,
23 : const byte* start, const byte* end) {
24 : Decoder decoder(start, end);
25 368419 : if (WasmDecoder<Decoder::kValidate>::DecodeLocals(enabled, &decoder, nullptr,
26 : &decls->type_list)) {
27 : DCHECK(decoder.ok());
28 368388 : decls->encoded_size = decoder.pc_offset();
29 368388 : return true;
30 : }
31 : return false;
32 : }
33 :
34 368327 : BytecodeIterator::BytecodeIterator(const byte* start, const byte* end,
35 : BodyLocalDecls* decls)
36 368327 : : Decoder(start, end) {
37 368327 : if (decls != nullptr) {
38 368324 : if (DecodeLocalDecls(kAllWasmFeatures, decls, start, end)) {
39 368294 : pc_ += decls->encoded_size;
40 368294 : if (pc_ > end_) pc_ = end_;
41 : }
42 : }
43 368327 : }
44 :
45 168185 : DecodeResult VerifyWasmCode(AccountingAllocator* allocator,
46 : const WasmFeatures& enabled,
47 : const WasmModule* module, WasmFeatures* detected,
48 : FunctionBody& body) {
49 336370 : Zone zone(allocator, ZONE_NAME);
50 : WasmFullDecoder<Decoder::kValidate, EmptyInterface> decoder(
51 : &zone, module, enabled, detected, body);
52 168185 : decoder.Decode();
53 504555 : return decoder.toResult(nullptr);
54 : }
55 :
56 2011187 : unsigned OpcodeLength(const byte* pc, const byte* end) {
57 : Decoder decoder(pc, end);
58 2011187 : return WasmDecoder<Decoder::kNoValidate>::OpcodeLength(&decoder, pc);
59 : }
60 :
61 1987016 : std::pair<uint32_t, uint32_t> StackEffect(const WasmModule* module,
62 : FunctionSig* sig, const byte* pc,
63 : const byte* end) {
64 1987016 : WasmFeatures unused_detected_features;
65 : WasmDecoder<Decoder::kNoValidate> decoder(
66 : module, kAllWasmFeatures, &unused_detected_features, sig, pc, end);
67 3974032 : return decoder.StackEffect(pc);
68 : }
69 :
70 0 : void PrintRawWasmCode(const byte* start, const byte* end) {
71 0 : AccountingAllocator allocator;
72 0 : PrintRawWasmCode(&allocator, FunctionBody{nullptr, 0, start, end}, nullptr,
73 0 : kPrintLocals);
74 0 : }
75 :
76 : namespace {
77 32 : const char* RawOpcodeName(WasmOpcode opcode) {
78 32 : switch (opcode) {
79 : #define DECLARE_NAME_CASE(name, opcode, sig) \
80 : case kExpr##name: \
81 : return "kExpr" #name;
82 0 : FOREACH_OPCODE(DECLARE_NAME_CASE)
83 : #undef DECLARE_NAME_CASE
84 : default:
85 : break;
86 : }
87 0 : return "Unknown";
88 : }
89 : } // namespace
90 :
91 0 : bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
92 : const WasmModule* module, PrintLocals print_locals) {
93 0 : StdoutStream os;
94 0 : return PrintRawWasmCode(allocator, body, module, print_locals, os);
95 : }
96 :
97 8 : bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
98 : const WasmModule* module, PrintLocals print_locals,
99 : std::ostream& os, std::vector<int>* line_numbers) {
100 16 : Zone zone(allocator, ZONE_NAME);
101 8 : WasmFeatures unused_detected_features;
102 : WasmDecoder<Decoder::kNoValidate> decoder(module, kAllWasmFeatures,
103 8 : &unused_detected_features, body.sig,
104 8 : body.start, body.end);
105 : int line_nr = 0;
106 8 : constexpr int kNoByteCode = -1;
107 :
108 : // Print the function signature.
109 8 : if (body.sig) {
110 8 : os << "// signature: " << *body.sig << std::endl;
111 8 : if (line_numbers) line_numbers->push_back(kNoByteCode);
112 : ++line_nr;
113 : }
114 :
115 : // Print the local declarations.
116 : BodyLocalDecls decls(&zone);
117 8 : BytecodeIterator i(body.start, body.end, &decls);
118 8 : if (body.start != i.pc() && print_locals == kPrintLocals) {
119 8 : os << "// locals:";
120 8 : if (!decls.type_list.empty()) {
121 0 : ValueType type = decls.type_list[0];
122 : uint32_t count = 0;
123 0 : for (size_t pos = 0; pos < decls.type_list.size(); ++pos) {
124 0 : if (decls.type_list[pos] == type) {
125 0 : ++count;
126 : } else {
127 0 : os << " " << count << " " << ValueTypes::TypeName(type);
128 0 : type = decls.type_list[pos];
129 : count = 1;
130 : }
131 : }
132 0 : os << " " << count << " " << ValueTypes::TypeName(type);
133 : }
134 : os << std::endl;
135 8 : if (line_numbers) line_numbers->push_back(kNoByteCode);
136 : ++line_nr;
137 :
138 16 : for (const byte* locals = body.start; locals < i.pc(); locals++) {
139 16 : os << (locals == body.start ? "0x" : " 0x") << AsHex(*locals, 2) << ",";
140 : }
141 : os << std::endl;
142 8 : if (line_numbers) line_numbers->push_back(kNoByteCode);
143 : ++line_nr;
144 : }
145 :
146 : os << "// body: " << std::endl;
147 8 : if (line_numbers) line_numbers->push_back(kNoByteCode);
148 : ++line_nr;
149 : unsigned control_depth = 0;
150 72 : for (; i.has_next(); i.next()) {
151 : unsigned length =
152 32 : WasmDecoder<Decoder::kNoValidate>::OpcodeLength(&decoder, i.pc());
153 :
154 : WasmOpcode opcode = i.current();
155 96 : if (line_numbers) line_numbers->push_back(i.position());
156 32 : if (opcode == kExprElse || opcode == kExprCatch) {
157 0 : control_depth--;
158 : }
159 :
160 32 : int num_whitespaces = control_depth < 32 ? 2 * control_depth : 64;
161 :
162 : // 64 whitespaces
163 : const char* padding =
164 : " ";
165 32 : os.write(padding, num_whitespaces);
166 :
167 32 : os << RawOpcodeName(opcode) << ",";
168 :
169 64 : if (opcode == kExprLoop || opcode == kExprIf || opcode == kExprBlock ||
170 32 : opcode == kExprTry) {
171 : DCHECK_EQ(2, length);
172 :
173 0 : switch (i.pc()[1]) {
174 : #define CASE_LOCAL_TYPE(local_name, type_name) \
175 : case kLocal##local_name: \
176 : os << " kWasm" #type_name ","; \
177 : break;
178 :
179 0 : CASE_LOCAL_TYPE(I32, I32)
180 0 : CASE_LOCAL_TYPE(I64, I64)
181 0 : CASE_LOCAL_TYPE(F32, F32)
182 0 : CASE_LOCAL_TYPE(F64, F64)
183 0 : CASE_LOCAL_TYPE(S128, S128)
184 0 : CASE_LOCAL_TYPE(Void, Stmt)
185 : default:
186 0 : os << " 0x" << AsHex(i.pc()[1], 2) << ",";
187 0 : break;
188 : }
189 : #undef CASE_LOCAL_TYPE
190 : } else {
191 64 : for (unsigned j = 1; j < length; ++j) {
192 32 : os << " 0x" << AsHex(i.pc()[j], 2) << ",";
193 : }
194 : }
195 :
196 32 : switch (opcode) {
197 : case kExprElse:
198 : case kExprCatch:
199 : os << " // @" << i.pc_offset();
200 0 : control_depth++;
201 0 : break;
202 : case kExprLoop:
203 : case kExprIf:
204 : case kExprBlock:
205 : case kExprTry: {
206 : BlockTypeImmediate<Decoder::kNoValidate> imm(kAllWasmFeatures, &i,
207 0 : i.pc());
208 : os << " // @" << i.pc_offset();
209 : if (decoder.Complete(imm)) {
210 0 : for (uint32_t i = 0; i < imm.out_arity(); i++) {
211 0 : os << " " << ValueTypes::TypeName(imm.out_type(i));
212 : }
213 : }
214 0 : control_depth++;
215 : break;
216 : }
217 : case kExprEnd:
218 : os << " // @" << i.pc_offset();
219 8 : control_depth--;
220 8 : break;
221 : case kExprBr: {
222 : BranchDepthImmediate<Decoder::kNoValidate> imm(&i, i.pc());
223 : os << " // depth=" << imm.depth;
224 : break;
225 : }
226 : case kExprBrIf: {
227 : BranchDepthImmediate<Decoder::kNoValidate> imm(&i, i.pc());
228 : os << " // depth=" << imm.depth;
229 : break;
230 : }
231 : case kExprBrTable: {
232 0 : BranchTableImmediate<Decoder::kNoValidate> imm(&i, i.pc());
233 0 : os << " // entries=" << imm.table_count;
234 : break;
235 : }
236 : case kExprCallIndirect: {
237 : CallIndirectImmediate<Decoder::kNoValidate> imm(kAllWasmFeatures, &i,
238 0 : i.pc());
239 0 : os << " // sig #" << imm.sig_index;
240 : if (decoder.Complete(i.pc(), imm)) {
241 0 : os << ": " << *imm.sig;
242 : }
243 : break;
244 : }
245 : case kExprCallFunction: {
246 : CallFunctionImmediate<Decoder::kNoValidate> imm(&i, i.pc());
247 : os << " // function #" << imm.index;
248 : if (decoder.Complete(i.pc(), imm)) {
249 0 : os << ": " << *imm.sig;
250 : }
251 : break;
252 : }
253 : default:
254 : break;
255 : }
256 : os << std::endl;
257 : ++line_nr;
258 : }
259 : DCHECK(!line_numbers || line_numbers->size() == static_cast<size_t>(line_nr));
260 :
261 8 : return decoder.ok();
262 : }
263 :
264 78 : BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals,
265 : const byte* start, const byte* end) {
266 : Decoder decoder(start, end);
267 78 : return WasmDecoder<Decoder::kValidate>::AnalyzeLoopAssignment(
268 156 : &decoder, start, static_cast<uint32_t>(num_locals), zone);
269 : }
270 :
271 : } // namespace wasm
272 : } // namespace internal
273 122004 : } // namespace v8
|