blob: 27170dd26981ceef93f1044b7747327d9b218942 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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_AST_DECODER_H_
6#define V8_WASM_AST_DECODER_H_
7
8#include "src/signature.h"
Ben Murdoch097c5b22016-05-18 11:27:45 +01009#include "src/wasm/decoder.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000010#include "src/wasm/wasm-opcodes.h"
11#include "src/wasm/wasm-result.h"
12
13namespace v8 {
14namespace internal {
15
Ben Murdoch097c5b22016-05-18 11:27:45 +010016class BitVector; // forward declaration
17
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018namespace compiler { // external declarations from compiler.
19class WasmGraphBuilder;
20}
21
22namespace wasm {
23
Ben Murdoch097c5b22016-05-18 11:27:45 +010024// Helpers for decoding different kinds of operands which follow bytecodes.
25struct LocalIndexOperand {
26 uint32_t index;
27 LocalType type;
Ben Murdoch61f157c2016-09-16 13:49:30 +010028 unsigned length;
Ben Murdoch097c5b22016-05-18 11:27:45 +010029
30 inline LocalIndexOperand(Decoder* decoder, const byte* pc) {
31 index = decoder->checked_read_u32v(pc, 1, &length, "local index");
32 type = kAstStmt;
33 }
34};
35
36struct ImmI8Operand {
37 int8_t value;
Ben Murdoch61f157c2016-09-16 13:49:30 +010038 unsigned length;
Ben Murdoch097c5b22016-05-18 11:27:45 +010039 inline ImmI8Operand(Decoder* decoder, const byte* pc) {
40 value = bit_cast<int8_t>(decoder->checked_read_u8(pc, 1, "immi8"));
41 length = 1;
42 }
43};
44
45struct ImmI32Operand {
46 int32_t value;
Ben Murdoch61f157c2016-09-16 13:49:30 +010047 unsigned length;
Ben Murdoch097c5b22016-05-18 11:27:45 +010048 inline ImmI32Operand(Decoder* decoder, const byte* pc) {
Ben Murdochda12d292016-06-02 14:46:10 +010049 value = decoder->checked_read_i32v(pc, 1, &length, "immi32");
Ben Murdoch097c5b22016-05-18 11:27:45 +010050 }
51};
52
53struct ImmI64Operand {
54 int64_t value;
Ben Murdoch61f157c2016-09-16 13:49:30 +010055 unsigned length;
Ben Murdoch097c5b22016-05-18 11:27:45 +010056 inline ImmI64Operand(Decoder* decoder, const byte* pc) {
Ben Murdochda12d292016-06-02 14:46:10 +010057 value = decoder->checked_read_i64v(pc, 1, &length, "immi64");
Ben Murdoch097c5b22016-05-18 11:27:45 +010058 }
59};
60
61struct ImmF32Operand {
62 float value;
Ben Murdoch61f157c2016-09-16 13:49:30 +010063 unsigned length;
Ben Murdoch097c5b22016-05-18 11:27:45 +010064 inline ImmF32Operand(Decoder* decoder, const byte* pc) {
65 value = bit_cast<float>(decoder->checked_read_u32(pc, 1, "immf32"));
66 length = 4;
67 }
68};
69
70struct ImmF64Operand {
71 double value;
Ben Murdoch61f157c2016-09-16 13:49:30 +010072 unsigned length;
Ben Murdoch097c5b22016-05-18 11:27:45 +010073 inline ImmF64Operand(Decoder* decoder, const byte* pc) {
74 value = bit_cast<double>(decoder->checked_read_u64(pc, 1, "immf64"));
75 length = 8;
76 }
77};
78
79struct GlobalIndexOperand {
80 uint32_t index;
81 LocalType type;
82 MachineType machine_type;
Ben Murdoch61f157c2016-09-16 13:49:30 +010083 unsigned length;
Ben Murdoch097c5b22016-05-18 11:27:45 +010084
85 inline GlobalIndexOperand(Decoder* decoder, const byte* pc) {
86 index = decoder->checked_read_u32v(pc, 1, &length, "global index");
87 type = kAstStmt;
88 machine_type = MachineType::None();
89 }
90};
91
Ben Murdochc5610432016-08-08 18:44:38 +010092struct Control;
Ben Murdoch097c5b22016-05-18 11:27:45 +010093struct BreakDepthOperand {
Ben Murdochc5610432016-08-08 18:44:38 +010094 uint32_t arity;
Ben Murdoch097c5b22016-05-18 11:27:45 +010095 uint32_t depth;
Ben Murdochc5610432016-08-08 18:44:38 +010096 Control* target;
Ben Murdoch61f157c2016-09-16 13:49:30 +010097 unsigned length;
Ben Murdoch097c5b22016-05-18 11:27:45 +010098 inline BreakDepthOperand(Decoder* decoder, const byte* pc) {
Ben Murdoch61f157c2016-09-16 13:49:30 +010099 unsigned len1 = 0;
100 unsigned len2 = 0;
Ben Murdochc5610432016-08-08 18:44:38 +0100101 arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count");
102 depth = decoder->checked_read_u32v(pc, 1 + len1, &len2, "break depth");
103 length = len1 + len2;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100104 target = nullptr;
105 }
106};
107
Ben Murdochc5610432016-08-08 18:44:38 +0100108struct CallIndirectOperand {
109 uint32_t arity;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100110 uint32_t index;
111 FunctionSig* sig;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100112 unsigned length;
Ben Murdochc5610432016-08-08 18:44:38 +0100113 inline CallIndirectOperand(Decoder* decoder, const byte* pc) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100114 unsigned len1 = 0;
115 unsigned len2 = 0;
Ben Murdochc5610432016-08-08 18:44:38 +0100116 arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count");
117 index = decoder->checked_read_u32v(pc, 1 + len1, &len2, "signature index");
118 length = len1 + len2;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100119 sig = nullptr;
120 }
121};
122
Ben Murdochc5610432016-08-08 18:44:38 +0100123struct CallFunctionOperand {
124 uint32_t arity;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100125 uint32_t index;
126 FunctionSig* sig;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100127 unsigned length;
Ben Murdochc5610432016-08-08 18:44:38 +0100128 inline CallFunctionOperand(Decoder* decoder, const byte* pc) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100129 unsigned len1 = 0;
130 unsigned len2 = 0;
Ben Murdochc5610432016-08-08 18:44:38 +0100131 arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count");
132 index = decoder->checked_read_u32v(pc, 1 + len1, &len2, "function index");
133 length = len1 + len2;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100134 sig = nullptr;
135 }
136};
137
Ben Murdochc5610432016-08-08 18:44:38 +0100138struct CallImportOperand {
139 uint32_t arity;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100140 uint32_t index;
141 FunctionSig* sig;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100142 unsigned length;
Ben Murdochc5610432016-08-08 18:44:38 +0100143 inline CallImportOperand(Decoder* decoder, const byte* pc) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100144 unsigned len1 = 0;
145 unsigned len2 = 0;
Ben Murdochc5610432016-08-08 18:44:38 +0100146 arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count");
147 index = decoder->checked_read_u32v(pc, 1 + len1, &len2, "import index");
148 length = len1 + len2;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100149 sig = nullptr;
150 }
151};
152
Ben Murdochda12d292016-06-02 14:46:10 +0100153struct BranchTableOperand {
Ben Murdochc5610432016-08-08 18:44:38 +0100154 uint32_t arity;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100155 uint32_t table_count;
156 const byte* table;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100157 unsigned length;
Ben Murdochda12d292016-06-02 14:46:10 +0100158 inline BranchTableOperand(Decoder* decoder, const byte* pc) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100159 unsigned len1 = 0;
160 unsigned len2 = 0;
Ben Murdochc5610432016-08-08 18:44:38 +0100161 arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count");
Ben Murdochda12d292016-06-02 14:46:10 +0100162 table_count =
Ben Murdochc5610432016-08-08 18:44:38 +0100163 decoder->checked_read_u32v(pc, 1 + len1, &len2, "table count");
Ben Murdoch61f157c2016-09-16 13:49:30 +0100164 if (table_count > (UINT_MAX / sizeof(uint32_t)) - 1 ||
165 len1 + len2 > UINT_MAX - (table_count + 1) * sizeof(uint32_t)) {
166 decoder->error(pc, "branch table size overflow");
167 }
Ben Murdochc5610432016-08-08 18:44:38 +0100168 length = len1 + len2 + (table_count + 1) * sizeof(uint32_t);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100169
Ben Murdochc5610432016-08-08 18:44:38 +0100170 uint32_t table_start = 1 + len1 + len2;
Ben Murdochda12d292016-06-02 14:46:10 +0100171 if (decoder->check(pc, table_start, (table_count + 1) * sizeof(uint32_t),
172 "expected <table entries>")) {
173 table = pc + table_start;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100174 } else {
175 table = nullptr;
176 }
177 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100178 inline uint32_t read_entry(Decoder* decoder, unsigned i) {
179 DCHECK(i <= table_count);
Ben Murdochda12d292016-06-02 14:46:10 +0100180 return table ? decoder->read_u32(table + i * sizeof(uint32_t)) : 0;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100181 }
182};
183
184struct MemoryAccessOperand {
Ben Murdochda12d292016-06-02 14:46:10 +0100185 uint32_t alignment;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100186 uint32_t offset;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100187 unsigned length;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100188 inline MemoryAccessOperand(Decoder* decoder, const byte* pc) {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100189 unsigned alignment_length;
Ben Murdochda12d292016-06-02 14:46:10 +0100190 alignment =
191 decoder->checked_read_u32v(pc, 1, &alignment_length, "alignment");
Ben Murdoch61f157c2016-09-16 13:49:30 +0100192 unsigned offset_length;
Ben Murdochda12d292016-06-02 14:46:10 +0100193 offset = decoder->checked_read_u32v(pc, 1 + alignment_length,
194 &offset_length, "offset");
195 length = alignment_length + offset_length;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100196 }
197};
198
Ben Murdochc5610432016-08-08 18:44:38 +0100199struct ReturnArityOperand {
200 uint32_t arity;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100201 unsigned length;
Ben Murdochc5610432016-08-08 18:44:38 +0100202
203 inline ReturnArityOperand(Decoder* decoder, const byte* pc) {
204 arity = decoder->checked_read_u32v(pc, 1, &length, "return count");
205 }
206};
207
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000208typedef compiler::WasmGraphBuilder TFBuilder;
209struct ModuleEnv; // forward declaration of module interface.
210
Ben Murdochda12d292016-06-02 14:46:10 +0100211// All of the various data structures necessary to decode a function body.
212struct FunctionBody {
213 ModuleEnv* module; // module environment
214 FunctionSig* sig; // function signature
215 const byte* base; // base of the module bytes, for error reporting
216 const byte* start; // start of the function body
217 const byte* end; // end of the function body
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000218};
219
Ben Murdoch61f157c2016-09-16 13:49:30 +0100220static inline FunctionBody FunctionBodyForTesting(const byte* start,
221 const byte* end) {
222 return {nullptr, nullptr, start, start, end};
223}
224
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000225struct Tree;
226typedef Result<Tree*> TreeResult;
227
228std::ostream& operator<<(std::ostream& os, const Tree& tree);
229
Ben Murdochda12d292016-06-02 14:46:10 +0100230TreeResult VerifyWasmCode(base::AccountingAllocator* allocator,
231 FunctionBody& body);
232TreeResult BuildTFGraph(base::AccountingAllocator* allocator,
233 TFBuilder* builder, FunctionBody& body);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100234bool PrintAst(base::AccountingAllocator* allocator, const FunctionBody& body,
235 std::ostream& os,
236 std::vector<std::tuple<uint32_t, int, int>>* offset_table);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000237
Ben Murdochc5610432016-08-08 18:44:38 +0100238// A simplified form of AST printing, e.g. from a debugger.
239void PrintAstForDebugging(const byte* start, const byte* end);
240
Ben Murdochda12d292016-06-02 14:46:10 +0100241inline TreeResult VerifyWasmCode(base::AccountingAllocator* allocator,
242 ModuleEnv* module, FunctionSig* sig,
243 const byte* start, const byte* end) {
244 FunctionBody body = {module, sig, nullptr, start, end};
245 return VerifyWasmCode(allocator, body);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000246}
247
Ben Murdochda12d292016-06-02 14:46:10 +0100248inline TreeResult BuildTFGraph(base::AccountingAllocator* allocator,
249 TFBuilder* builder, ModuleEnv* module,
250 FunctionSig* sig, const byte* start,
251 const byte* end) {
252 FunctionBody body = {module, sig, nullptr, start, end};
253 return BuildTFGraph(allocator, builder, body);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000254}
255
Ben Murdochda12d292016-06-02 14:46:10 +0100256struct AstLocalDecls {
257 // The size of the encoded declarations.
258 uint32_t decls_encoded_size; // size of encoded declarations
259
260 // Total number of locals.
261 uint32_t total_local_count;
262
263 // List of {local type, count} pairs.
264 ZoneVector<std::pair<LocalType, uint32_t>> local_types;
265
266 // Constructor initializes the vector.
267 explicit AstLocalDecls(Zone* zone)
268 : decls_encoded_size(0), total_local_count(0), local_types(zone) {}
269};
270
271bool DecodeLocalDecls(AstLocalDecls& decls, const byte* start, const byte* end);
272BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100273 const byte* start, const byte* end);
274
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000275// Computes the length of the opcode at the given address.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100276unsigned OpcodeLength(const byte* pc, const byte* end);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000277
278// Computes the arity (number of sub-nodes) of the opcode at the given address.
Ben Murdoch61f157c2016-09-16 13:49:30 +0100279unsigned OpcodeArity(const byte* pc, const byte* end);
Ben Murdochc5610432016-08-08 18:44:38 +0100280
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000281} // namespace wasm
282} // namespace internal
283} // namespace v8
284
285#endif // V8_WASM_AST_DECODER_H_