├── .gitignore
├── .travis.yml
├── Contributing.md
├── LICENSE
├── README.md
├── src
└── wasm
│ ├── asm-wasm-builder.cc
│ ├── asm-wasm-builder.h
│ ├── ast-decoder.cc
│ ├── ast-decoder.h
│ ├── decoder.h
│ ├── encoder.cc
│ ├── encoder.h
│ ├── module-decoder.cc
│ ├── module-decoder.h
│ ├── wasm-compiler.cc
│ ├── wasm-compiler.h
│ ├── wasm-js.cc
│ ├── wasm-js.h
│ ├── wasm-linkage.cc
│ ├── wasm-macro-gen.h
│ ├── wasm-module.cc
│ ├── wasm-module.h
│ ├── wasm-opcodes.cc
│ ├── wasm-opcodes.h
│ ├── wasm-result.cc
│ ├── wasm-result.h
│ └── wasm.gyp
├── test
├── cctest
│ └── wasm
│ │ ├── test-run-wasm-module.cc
│ │ ├── test-run-wasm.cc
│ │ ├── test-signatures.h
│ │ └── wasm.gyp
├── mjsunit
│ └── wasm
│ │ ├── asm-wasm.js
│ │ ├── calls.js
│ │ ├── compile-run-basic.js
│ │ ├── divrem-trap.js
│ │ ├── ffi-error.js
│ │ ├── ffi.js
│ │ ├── indirect-calls.js
│ │ ├── instantiate-module-basic.js
│ │ ├── module-memory.js
│ │ ├── params.js
│ │ ├── stackwalk.js
│ │ ├── unreachable.js
│ │ ├── verify-function-basic-errors.js
│ │ ├── verify-function-simple.js
│ │ ├── verify-module-basic-errors.js
│ │ ├── wasm-constants.js
│ │ └── wasm-object-api.js
└── unittests
│ └── wasm
│ ├── ast-decoder-unittest.cc
│ ├── encoder-unittest.cc
│ ├── module-decoder-unittest.cc
│ ├── wasm-macro-gen-unittest.cc
│ └── wasm.gyp
└── travis
├── build-and-test.sh
└── install-dependencies.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | depot_tools
2 | v8
3 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: c++
2 |
3 | sudo: off
4 |
5 | install: ./travis/install-dependencies.sh
6 |
7 | script:
8 | - ./travis/build-and-test.sh
9 |
10 | compiler:
11 | - clang
12 |
13 | os:
14 | - linux
15 | - osx
16 |
--------------------------------------------------------------------------------
/Contributing.md:
--------------------------------------------------------------------------------
1 | # Contributing to WebAssembly
2 |
3 | Interested in participating? Please follow
4 | [the same contributing guidelines as the design repository][].
5 |
6 | [the same contributing guidelines as the design repository]: https://github.com/WebAssembly/design/blob/master/Contributing.md
7 |
8 | Also, please be sure to read [the README.md](README.md) for this repository.
9 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | This license applies to all parts of V8 that are not externally
2 | maintained libraries. The externally maintained libraries used by V8
3 | are:
4 |
5 | - PCRE test suite, located in
6 | test/mjsunit/third_party/regexp-pcre/regexp-pcre.js. This is based on the
7 | test suite from PCRE-7.3, which is copyrighted by the University
8 | of Cambridge and Google, Inc. The copyright notice and license
9 | are embedded in regexp-pcre.js.
10 |
11 | - Layout tests, located in test/mjsunit/third_party/object-keys. These are
12 | based on layout tests from webkit.org which are copyrighted by
13 | Apple Computer, Inc. and released under a 3-clause BSD license.
14 |
15 | - Strongtalk assembler, the basis of the files assembler-arm-inl.h,
16 | assembler-arm.cc, assembler-arm.h, assembler-ia32-inl.h,
17 | assembler-ia32.cc, assembler-ia32.h, assembler-x64-inl.h,
18 | assembler-x64.cc, assembler-x64.h, assembler-mips-inl.h,
19 | assembler-mips.cc, assembler-mips.h, assembler.cc and assembler.h.
20 | This code is copyrighted by Sun Microsystems Inc. and released
21 | under a 3-clause BSD license.
22 |
23 | - Valgrind client API header, located at third_party/valgrind/valgrind.h
24 | This is release under the BSD license.
25 |
26 | These libraries have their own licenses; we recommend you read them,
27 | as their terms may differ from the terms below.
28 |
29 | Further license information can be found in LICENSE files located in
30 | sub-directories.
31 |
32 | Copyright 2014, the V8 project authors. All rights reserved.
33 | Redistribution and use in source and binary forms, with or without
34 | modification, are permitted provided that the following conditions are
35 | met:
36 |
37 | * Redistributions of source code must retain the above copyright
38 | notice, this list of conditions and the following disclaimer.
39 | * Redistributions in binary form must reproduce the above
40 | copyright notice, this list of conditions and the following
41 | disclaimer in the documentation and/or other materials provided
42 | with the distribution.
43 | * Neither the name of Google Inc. nor the names of its
44 | contributors may be used to endorse or promote products derived
45 | from this software without specific prior written permission.
46 |
47 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
48 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
49 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
50 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
51 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
52 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
53 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
54 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
55 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
56 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
57 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
58 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # The code of this project has been moved into the
[V8 repository](https://github.com/v8/v8).
4 |
5 | ## WebAssembly V8 Native Prototype
6 |
7 | This repository contains additional source code needed to build a prototype
8 | implementation of WebAssembly incorporated into V8.
9 |
10 | To build:
11 |
12 | * Install depot_tools:
13 | http://dev.chromium.org/developers/how-tos/install-depot-tools
14 | * Checkout this prototype:
15 | ```
16 | git clone https://github.com/WebAssembly/v8-native-prototype.git
17 | ```
18 | * Checkout V8:
19 | ```
20 | mkdir v8
21 | cd v8
22 | fetch v8
23 | cd v8
24 | ```
25 | * Add symlinks to prototype from v8:
26 | ```
27 | ln -fs $PWD/../../v8-native-prototype third_party/wasm
28 | ln -fs $PWD/../../v8-native-prototype test/mjsunit/wasm
29 | ```
30 | * make x64.debug wasm=on
31 |
--------------------------------------------------------------------------------
/src/wasm/asm-wasm-builder.h:
--------------------------------------------------------------------------------
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_ASM_WASM_BUILDER_H_
6 | #define V8_WASM_ASM_WASM_BUILDER_H_
7 |
8 | #include "src/allocation.h"
9 | #include "src/zone.h"
10 | #include "src/wasm/encoder.h"
11 |
12 | namespace v8 {
13 | namespace internal {
14 |
15 | class FunctionLiteral;
16 |
17 | namespace wasm {
18 |
19 | class AsmWasmBuilder {
20 | public:
21 | explicit AsmWasmBuilder(Isolate* isolate, Zone* zone, FunctionLiteral* root);
22 | WasmModuleIndex* Run();
23 |
24 | private:
25 | Isolate* isolate_;
26 | Zone* zone_;
27 | FunctionLiteral* literal_;
28 | };
29 | }
30 | }
31 | }
32 |
33 | #endif // V8_WASM_ASM_WASM_BUILDER_H_
34 |
--------------------------------------------------------------------------------
/src/wasm/ast-decoder.h:
--------------------------------------------------------------------------------
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_AST_DECODER_H_
6 | #define V8_WASM_AST_DECODER_H_
7 |
8 | #include "src/signature.h"
9 | #include "src/wasm/wasm-opcodes.h"
10 | #include "src/wasm/wasm-result.h"
11 |
12 | namespace v8 {
13 | namespace internal {
14 |
15 | namespace compiler { // external declarations from compiler.
16 | class WasmGraphBuilder;
17 | }
18 |
19 | namespace wasm {
20 |
21 | typedef compiler::WasmGraphBuilder TFBuilder;
22 | struct ModuleEnv; // forward declaration of module interface.
23 |
24 | // Interface the function environment during decoding, include the signature
25 | // and number of locals.
26 | struct FunctionEnv {
27 | ModuleEnv* module; // module environment
28 | FunctionSig* sig; // signature of this function
29 | uint32_t local_int32_count; // number of int32 locals
30 | uint32_t local_int64_count; // number of int64 locals
31 | uint32_t local_float32_count; // number of float32 locals
32 | uint32_t local_float64_count; // number of float64 locals
33 | uint32_t total_locals; // sum of parameters and all locals
34 |
35 | bool IsValidLocal(uint32_t index) { return index < total_locals; }
36 | uint32_t GetLocalCount() { return total_locals; }
37 | LocalType GetLocalType(uint32_t index) {
38 | if (index < sig->parameter_count()) return sig->GetParam(index);
39 | index -= sig->parameter_count();
40 | if (index < local_int32_count) return kAstI32;
41 | index -= local_int32_count;
42 | if (index < local_int64_count) return kAstI64;
43 | index -= local_int64_count;
44 | if (index < local_float32_count) return kAstF32;
45 | index -= local_float32_count;
46 | if (index < local_float64_count) return kAstF64;
47 | return kAstStmt;
48 | }
49 |
50 | void AddLocals(LocalType type, uint32_t count) {
51 | switch (type) {
52 | case kAstI32:
53 | local_int32_count += count;
54 | break;
55 | case kAstI64:
56 | local_int64_count += count;
57 | break;
58 | case kAstF32:
59 | local_float32_count += count;
60 | break;
61 | case kAstF64:
62 | local_float64_count += count;
63 | break;
64 | default:
65 | UNREACHABLE();
66 | }
67 | total_locals += count;
68 | DCHECK(total_locals ==
69 | (sig->parameter_count() + local_int32_count + local_int64_count +
70 | local_float32_count + local_float64_count));
71 | }
72 |
73 | void SumLocals() {
74 | total_locals = static_cast(sig->parameter_count()) +
75 | local_int32_count + local_int64_count + local_float32_count +
76 | local_float64_count;
77 | }
78 | };
79 |
80 | struct Tree;
81 | typedef Result TreeResult;
82 |
83 | std::ostream& operator<<(std::ostream& os, const Tree& tree);
84 |
85 | TreeResult VerifyWasmCode(FunctionEnv* env, const byte* base, const byte* start,
86 | const byte* end);
87 | TreeResult BuildTFGraph(TFBuilder* builder, FunctionEnv* env, const byte* base,
88 | const byte* start, const byte* end);
89 |
90 | inline TreeResult VerifyWasmCode(FunctionEnv* env, const byte* start,
91 | const byte* end) {
92 | return VerifyWasmCode(env, nullptr, start, end);
93 | }
94 |
95 | inline TreeResult BuildTFGraph(TFBuilder* builder, FunctionEnv* env,
96 | const byte* start, const byte* end) {
97 | return BuildTFGraph(builder, env, nullptr, start, end);
98 | }
99 |
100 | enum ReadUnsignedLEB128ErrorCode { kNoError, kInvalidLEB128, kMissingLEB128 };
101 |
102 | ReadUnsignedLEB128ErrorCode ReadUnsignedLEB128Operand(const byte*, const byte*,
103 | int*, uint32_t*);
104 |
105 | // Computes the length of the opcode at the given address.
106 | int OpcodeLength(const byte* pc);
107 |
108 | // Computes the arity (number of sub-nodes) of the opcode at the given address.
109 | int OpcodeArity(FunctionEnv* env, const byte* pc);
110 | }
111 | }
112 | }
113 |
114 | #endif // V8_WASM_AST_DECODER_H_
115 |
--------------------------------------------------------------------------------
/src/wasm/decoder.h:
--------------------------------------------------------------------------------
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_DECODER_H_
6 | #define V8_WASM_DECODER_H_
7 |
8 | #include "src/signature.h"
9 | #include "src/zone-containers.h"
10 | #include "src/base/smart-pointers.h"
11 | #include "src/wasm/wasm-result.h"
12 | #include "src/flags.h"
13 |
14 | namespace v8 {
15 | namespace internal {
16 | namespace wasm {
17 |
18 | #if DEBUG
19 | #define TRACE(...) \
20 | do { \
21 | if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \
22 | } while (false)
23 | #else
24 | #define TRACE(...)
25 | #endif
26 |
27 | // A helper utility to decode bytes, integers, fields, varints, etc, from
28 | // a buffer of bytes.
29 | class Decoder {
30 | public:
31 | Decoder(const byte* start, const byte* end)
32 | : start_(start),
33 | pc_(start),
34 | limit_(end),
35 | error_pc_(nullptr),
36 | error_pt_(nullptr) {}
37 |
38 | virtual ~Decoder() {}
39 |
40 | // Reads a 8-bit unsigned integer (byte) and advances {pc_}.
41 | uint8_t u8(const char* name = nullptr) {
42 | TRACE(" +%d %-20s: ", static_cast(pc_ - start_),
43 | name ? name : "uint8_t");
44 | if (checkAvailable(1)) {
45 | byte val = *(pc_++);
46 | TRACE("%02x = %d\n", val, val);
47 | return val;
48 | } else {
49 | error("expected 1 byte, but fell off end");
50 | return traceOffEnd();
51 | }
52 | }
53 |
54 | // Reads a 16-bit unsigned integer (little endian) and advances {pc_}.
55 | uint16_t u16(const char* name = nullptr) {
56 | TRACE(" +%d %-20s: ", static_cast(pc_ - start_),
57 | name ? name : "uint16_t");
58 | if (checkAvailable(2)) {
59 | #ifdef V8_TARGET_LITTLE_ENDIAN
60 | byte b0 = pc_[0];
61 | byte b1 = pc_[1];
62 | #else
63 | byte b1 = pc_[0];
64 | byte b0 = pc_[1];
65 | #endif
66 | uint16_t val = static_cast(b1 << 8) | b0;
67 | TRACE("%02x %02x = %d\n", pc_[0], pc_[1], val);
68 | pc_ += 2;
69 | return val;
70 | } else {
71 | error("expected 2 bytes, but fell off end");
72 | return traceOffEnd();
73 | }
74 | }
75 |
76 | // Reads a single 32-bit unsigned integer (little endian) and advances {pc_}.
77 | uint32_t u32(const char* name = nullptr) {
78 | TRACE(" +%d %-20s: ", static_cast(pc_ - start_),
79 | name ? name : "uint32_t");
80 | if (checkAvailable(4)) {
81 | #ifdef V8_TARGET_LITTLE_ENDIAN
82 | byte b0 = pc_[0];
83 | byte b1 = pc_[1];
84 | byte b2 = pc_[2];
85 | byte b3 = pc_[3];
86 | #else
87 | byte b3 = pc_[0];
88 | byte b2 = pc_[1];
89 | byte b1 = pc_[2];
90 | byte b0 = pc_[3];
91 | #endif
92 | uint32_t val = static_cast(b3 << 24) |
93 | static_cast(b2 << 16) |
94 | static_cast(b1 << 8) | b0;
95 | TRACE("%02x %02x %02x %02x = %u\n", pc_[0], pc_[1], pc_[2], pc_[3], val);
96 | pc_ += 4;
97 | return val;
98 | } else {
99 | error("expected 4 bytes, but fell off end");
100 | return traceOffEnd();
101 | }
102 | }
103 |
104 | // Reads a LEB128 variable-length 32-bit integer and advances {pc_}.
105 | uint32_t u32v(int* length, const char* name = nullptr) {
106 | TRACE(" +%d %-20s: ", static_cast(pc_ - start_),
107 | name ? name : "varint");
108 |
109 | if (!checkAvailable(1)) {
110 | error("expected at least 1 byte, but fell off end");
111 | return traceOffEnd();
112 | }
113 |
114 | const byte* pos = pc_;
115 | const byte* end = pc_ + 5;
116 | if (end > limit_) end = limit_;
117 |
118 | uint32_t result = 0;
119 | int shift = 0;
120 | byte b = 0;
121 | while (pc_ < end) {
122 | b = *pc_++;
123 | TRACE("%02x ", b);
124 | result = result | ((b & 0x7F) << shift);
125 | if ((b & 0x80) == 0) break;
126 | shift += 7;
127 | }
128 |
129 | *length = static_cast(pc_ - pos);
130 | if (pc_ == end && (b & 0x80)) {
131 | error(pc_ - 1, "varint too large");
132 | } else {
133 | TRACE("= %u\n", result);
134 | }
135 | return result;
136 | }
137 |
138 | // Check that at least {size} bytes exist between {pc_} and {limit_}.
139 | bool checkAvailable(int size) {
140 | if (pc_ < start_ || (pc_ + size) > limit_) {
141 | error(pc_, nullptr, "expected %d bytes, fell off end", size);
142 | return false;
143 | } else {
144 | return true;
145 | }
146 | }
147 |
148 | void error(const char* msg) { error(pc_, nullptr, msg); }
149 |
150 | void error(const byte* pc, const char* msg) { error(pc, nullptr, msg); }
151 |
152 | // Sets internal error state.
153 | void error(const byte* pc, const byte* pt, const char* format, ...) {
154 | if (ok()) {
155 | #if DEBUG
156 | if (FLAG_wasm_break_on_decoder_error) {
157 | base::OS::DebugBreak();
158 | }
159 | #endif
160 | const int kMaxErrorMsg = 256;
161 | char* buffer = new char[kMaxErrorMsg];
162 | va_list arguments;
163 | va_start(arguments, format);
164 | base::OS::VSNPrintF(buffer, kMaxErrorMsg - 1, format, arguments);
165 | va_end(arguments);
166 | error_msg_.Reset(buffer);
167 | error_pc_ = pc;
168 | error_pt_ = pt;
169 | onFirstError();
170 | }
171 | }
172 |
173 | // Behavior triggered on first error, overridden in subclasses.
174 | virtual void onFirstError() {}
175 |
176 | // Debugging helper to print bytes up to the end.
177 | template
178 | T traceOffEnd() {
179 | T t = 0;
180 | for (const byte* ptr = pc_; ptr < limit_; ptr++) {
181 | TRACE("%02x ", *ptr);
182 | }
183 | TRACE("\n");
184 | pc_ = limit_;
185 | return t;
186 | }
187 |
188 | // Converts the given value to a {Result}, copying the error if necessary.
189 | template
190 | Result toResult(T val) {
191 | Result result;
192 | if (error_pc_) {
193 | result.error_code = kError;
194 | result.start = start_;
195 | result.error_pc = error_pc_;
196 | result.error_pt = error_pt_;
197 | result.error_msg = error_msg_;
198 | error_msg_.Reset(nullptr);
199 | } else {
200 | result.error_code = kSuccess;
201 | result.val = val;
202 | }
203 | return result;
204 | }
205 |
206 | // Resets the boundaries of this decoder.
207 | void Reset(const byte* start, const byte* end) {
208 | start_ = start;
209 | pc_ = start;
210 | limit_ = end;
211 | error_pc_ = nullptr;
212 | error_pt_ = nullptr;
213 | error_msg_.Reset(nullptr);
214 | }
215 |
216 | bool ok() const { return error_pc_ == nullptr; }
217 | bool failed() const { return error_pc_ != nullptr; }
218 |
219 | protected:
220 | const byte* start_;
221 | const byte* pc_;
222 | const byte* limit_;
223 | const byte* error_pc_;
224 | const byte* error_pt_;
225 | base::SmartArrayPointer error_msg_;
226 | };
227 |
228 | #undef TRACE
229 | }
230 | }
231 | }
232 |
233 | #endif // V8_WASM_DECODER_H_
234 |
--------------------------------------------------------------------------------
/src/wasm/encoder.cc:
--------------------------------------------------------------------------------
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/signature.h"
6 |
7 | #include "src/v8.h"
8 | #include "src/handles.h"
9 | #include "src/zone-containers.h"
10 |
11 | #include "src/wasm/ast-decoder.h"
12 | #include "src/wasm/encoder.h"
13 | #include "src/wasm/wasm-module.h"
14 | #include "src/wasm/wasm-opcodes.h"
15 |
16 | #include "src/v8memory.h"
17 |
18 | namespace v8 {
19 | namespace internal {
20 | namespace wasm {
21 |
22 | /*TODO: add error cases for adding too many locals, too many functions and bad
23 | indices in body */
24 |
25 | namespace {
26 | void EmitUint8(byte** b, uint8_t x) {
27 | Memory::uint8_at(*b) = x;
28 | *b += 1;
29 | }
30 |
31 | void EmitUint16(byte** b, uint16_t x) {
32 | Memory::uint16_at(*b) = x;
33 | *b += 2;
34 | }
35 |
36 | void EmitUint32(byte** b, uint32_t x) {
37 | Memory::uint32_at(*b) = x;
38 | *b += 4;
39 | }
40 |
41 | void EmitVarInt(byte** b, size_t val) {
42 | while (true) {
43 | size_t next = val >> 7;
44 | byte out = static_cast(val & 0x7f);
45 | if (next) {
46 | *((*b)++) = 0x80 | out;
47 | val = next;
48 | } else {
49 | *((*b)++) = out;
50 | break;
51 | }
52 | }
53 | }
54 | }
55 |
56 | struct WasmFunctionBuilder::Type {
57 | bool param_;
58 | LocalType type_;
59 | };
60 |
61 | WasmFunctionBuilder::WasmFunctionBuilder(Zone* zone,
62 | const unsigned char* name,
63 | int name_length)
64 | : return_type_(kAstI32),
65 | locals_(zone),
66 | exported_(0),
67 | external_(0),
68 | body_(zone),
69 | local_indices_(zone),
70 | name_(zone) {
71 | if (name_length > 0) {
72 | for (int i = 0; i < name_length; i++) {
73 | name_.push_back(*(name + i));
74 | }
75 | name_.push_back('\0');
76 | }
77 | }
78 |
79 | uint16_t WasmFunctionBuilder::AddParam(LocalType type) {
80 | return AddVar(type, true);
81 | }
82 |
83 | uint16_t WasmFunctionBuilder::AddLocal(LocalType type) {
84 | return AddVar(type, false);
85 | }
86 |
87 | uint16_t WasmFunctionBuilder::AddVar(LocalType type, bool param) {
88 | locals_.push_back({param, type});
89 | return static_cast(locals_.size() - 1);
90 | }
91 |
92 | void WasmFunctionBuilder::ReturnType(LocalType type) { return_type_ = type; }
93 |
94 | void WasmFunctionBuilder::EmitCode(const byte* code, uint32_t code_size) {
95 | EmitCode(code, code_size, NULL, 0);
96 | }
97 |
98 | void WasmFunctionBuilder::EmitCode(const byte* code, uint32_t code_size,
99 | const uint32_t* local_indices,
100 | uint32_t indices_size) {
101 | size_t size = body_.size();
102 | for (size_t i = 0; i < code_size; i++) {
103 | body_.push_back(code[i]);
104 | }
105 | for (size_t i = 0; i < indices_size; i++) {
106 | local_indices_.push_back(local_indices[i] + static_cast(size));
107 | }
108 | }
109 |
110 | void WasmFunctionBuilder::Emit(WasmOpcode opcode) {
111 | body_.push_back(static_cast(opcode));
112 | }
113 |
114 | void WasmFunctionBuilder::EmitWithU8(WasmOpcode opcode, const byte immediate) {
115 | body_.push_back(static_cast(opcode));
116 | body_.push_back(immediate);
117 | }
118 |
119 | void WasmFunctionBuilder::EmitWithLocal(WasmOpcode opcode) {
120 | body_.push_back(static_cast(opcode));
121 | local_indices_.push_back(static_cast(body_.size()) - 1);
122 | }
123 |
124 | uint32_t WasmFunctionBuilder::EmitEditableImmediate(const byte immediate) {
125 | body_.push_back(immediate);
126 | return static_cast(body_.size()) - 1;
127 | }
128 |
129 | void WasmFunctionBuilder::EditImmediate(uint32_t offset, const byte immediate) {
130 | DCHECK(offset < body_.size());
131 | body_[offset] = immediate;
132 | }
133 |
134 | void WasmFunctionBuilder::Exported(uint8_t flag) { exported_ = flag; }
135 |
136 | void WasmFunctionBuilder::External(uint8_t flag) { external_ = flag; }
137 |
138 | WasmFunctionEncoder* WasmFunctionBuilder::Build(Zone* zone,
139 | WasmModuleBuilder* mb) const {
140 | WasmFunctionEncoder* e =
141 | new (zone) WasmFunctionEncoder(zone, return_type_, exported_, external_);
142 | auto var_index = new uint16_t[locals_.size()];
143 | IndexVars(e, var_index);
144 | const byte* start = body_.data();
145 | const byte* end = start + body_.size();
146 | size_t local_index = 0;
147 | for (size_t i = 0; i < body_.size();) {
148 | if (local_index < local_indices_.size() &&
149 | i == local_indices_[local_index]) {
150 | int length = 0;
151 | uint32_t index;
152 | ReadUnsignedLEB128Operand(start + i, end, &length, &index);
153 | uint16_t new_index = var_index[index];
154 | const std::vector& index_vec = UnsignedLEB128From(new_index);
155 | for (size_t j = 0; j < index_vec.size(); j++) {
156 | e->body_.push_back(index_vec.at(j));
157 | }
158 | i += length;
159 | local_index++;
160 | } else {
161 | e->body_.push_back(*(start + i));
162 | i++;
163 | }
164 | }
165 | FunctionSig::Builder sig(zone, return_type_ == kAstStmt ? 0 : 1,
166 | e->params_.size());
167 | if (return_type_ != kAstStmt) {
168 | sig.AddReturn(static_cast(return_type_));
169 | }
170 | for (size_t i = 0; i < e->params_.size(); i++) {
171 | sig.AddParam(static_cast(e->params_[i]));
172 | }
173 | e->signature_index_ = mb->AddSignature(sig.Build());
174 | delete[] var_index;
175 | e->name_.insert(e->name_.begin(), name_.begin(), name_.end());
176 | return e;
177 | }
178 |
179 | void WasmFunctionBuilder::IndexVars(WasmFunctionEncoder* e,
180 | uint16_t* var_index) const {
181 | uint16_t param = 0;
182 | uint16_t int32 = 0;
183 | uint16_t int64 = 0;
184 | uint16_t float32 = 0;
185 | uint16_t float64 = 0;
186 | for (size_t i = 0; i < locals_.size(); i++) {
187 | if (locals_.at(i).param_) {
188 | param++;
189 | } else if (locals_.at(i).type_ == kAstI32) {
190 | int32++;
191 | } else if (locals_.at(i).type_ == kAstI64) {
192 | int64++;
193 | } else if (locals_.at(i).type_ == kAstF32) {
194 | float32++;
195 | } else if (locals_.at(i).type_ == kAstF64) {
196 | float64++;
197 | }
198 | }
199 | e->local_int32_count_ = int32;
200 | e->local_int64_count_ = int64;
201 | e->local_float32_count_ = float32;
202 | e->local_float64_count_ = float64;
203 | float64 = param + int32 + int64 + float32;
204 | float32 = param + int32 + int64;
205 | int64 = param + int32;
206 | int32 = param;
207 | param = 0;
208 | for (size_t i = 0; i < locals_.size(); i++) {
209 | if (locals_.at(i).param_) {
210 | e->params_.push_back(locals_.at(i).type_);
211 | var_index[i] = param++;
212 | } else if (locals_.at(i).type_ == kAstI32) {
213 | var_index[i] = int32++;
214 | } else if (locals_.at(i).type_ == kAstI64) {
215 | var_index[i] = int64++;
216 | } else if (locals_.at(i).type_ == kAstF32) {
217 | var_index[i] = float32++;
218 | } else if (locals_.at(i).type_ == kAstF64) {
219 | var_index[i] = float64++;
220 | }
221 | }
222 | }
223 |
224 | WasmFunctionEncoder::WasmFunctionEncoder(Zone* zone, LocalType return_type,
225 | bool exported, bool external)
226 | : params_(zone), exported_(exported), external_(external), body_(zone),
227 | name_(zone) {}
228 |
229 | uint32_t WasmFunctionEncoder::HeaderSize() const {
230 | uint32_t size = 3;
231 | if (HasLocals()) size += 8;
232 | if (!external_) size += 2;
233 | if (HasName()) size += 4;
234 | return size;
235 | }
236 |
237 | uint32_t WasmFunctionEncoder::BodySize(void) const {
238 | return external_ ? 0 : static_cast(body_.size());
239 | }
240 |
241 | uint32_t WasmFunctionEncoder::NameSize() const {
242 | return exported_ ? static_cast(name_.size()) : 0;
243 | }
244 |
245 | void WasmFunctionEncoder::Serialize(byte* buffer, byte** header,
246 | byte** body) const {
247 | uint8_t decl_bits = (exported_ ? kDeclFunctionExport : 0) |
248 | (external_ ? kDeclFunctionImport : 0) |
249 | (HasLocals() ? kDeclFunctionLocals : 0) |
250 | (HasName() ? kDeclFunctionName : 0);
251 |
252 | EmitUint8(header, decl_bits);
253 | EmitUint16(header, signature_index_);
254 |
255 | if (HasName()) {
256 | uint32_t name_offset = static_cast(*body - buffer);
257 | EmitUint32(header, name_offset);
258 | std::memcpy(*body, name_.data(), name_.size());
259 | (*body) += name_.size();
260 | }
261 |
262 | if (HasLocals()) {
263 | EmitUint16(header, local_int32_count_);
264 | EmitUint16(header, local_int64_count_);
265 | EmitUint16(header, local_float32_count_);
266 | EmitUint16(header, local_float64_count_);
267 | }
268 |
269 | if (!external_) {
270 | EmitUint16(header, static_cast(body_.size()));
271 | std::memcpy(*header, body_.data(), body_.size());
272 | (*header) += body_.size();
273 | }
274 | }
275 |
276 | WasmDataSegmentEncoder::WasmDataSegmentEncoder(Zone* zone, const byte* data,
277 | uint32_t size, uint32_t dest)
278 | : data_(zone), dest_(dest) {
279 | for (size_t i = 0; i < size; i++) {
280 | data_.push_back(data[i]);
281 | }
282 | }
283 |
284 | uint32_t WasmDataSegmentEncoder::HeaderSize() const {
285 | static const int kDataSegmentSize = 13;
286 | return kDataSegmentSize;
287 | }
288 |
289 | uint32_t WasmDataSegmentEncoder::BodySize() const {
290 | return static_cast(data_.size());
291 | }
292 |
293 | void WasmDataSegmentEncoder::Serialize(byte* buffer, byte** header,
294 | byte** body) const {
295 | uint32_t body_offset = static_cast(*body - buffer);
296 | EmitUint32(header, dest_);
297 | EmitUint32(header, body_offset);
298 | EmitUint32(header, static_cast(data_.size()));
299 | EmitUint8(header, 1); // init
300 |
301 | std::memcpy(*body, data_.data(), data_.size());
302 | (*body) += data_.size();
303 | }
304 |
305 | WasmModuleBuilder::WasmModuleBuilder(Zone* zone)
306 | : zone_(zone),
307 | signatures_(zone),
308 | functions_(zone),
309 | data_segments_(zone),
310 | indirect_functions_(zone),
311 | globals_(zone),
312 | signature_map_(zone) {}
313 |
314 | uint16_t WasmModuleBuilder::AddFunction(const unsigned char* name,
315 | int name_length) {
316 | functions_.push_back(new (zone_) WasmFunctionBuilder(zone_, name,
317 | name_length));
318 | return static_cast(functions_.size() - 1);
319 | }
320 |
321 | WasmFunctionBuilder* WasmModuleBuilder::FunctionAt(size_t index) {
322 | if (functions_.size() > index) {
323 | return functions_.at(index);
324 | } else {
325 | return nullptr;
326 | }
327 | }
328 |
329 | void WasmModuleBuilder::AddDataSegment(WasmDataSegmentEncoder* data) {
330 | data_segments_.push_back(data);
331 | }
332 |
333 | int WasmModuleBuilder::CompareFunctionSigs::operator()(FunctionSig* a,
334 | FunctionSig* b) {
335 | if (a->return_count() < b->return_count()) return -1;
336 | if (a->return_count() > b->return_count()) return 1;
337 | if (a->parameter_count() < b->parameter_count()) return -1;
338 | if (a->parameter_count() > b->parameter_count()) return 1;
339 | for (size_t r = 0; r < a->return_count(); r++) {
340 | if (a->GetReturn(r) < b->GetReturn(r)) return -1;
341 | if (a->GetReturn(r) > b->GetReturn(r)) return 1;
342 | }
343 | for (size_t p = 0; p < a->parameter_count(); p++) {
344 | if (a->GetParam(p) < b->GetParam(p)) return -1;
345 | if (a->GetParam(p) > b->GetParam(p)) return 1;
346 | }
347 | return 0;
348 | }
349 |
350 | uint16_t WasmModuleBuilder::AddSignature(FunctionSig* sig) {
351 | SignatureMap::iterator pos = signature_map_.find(sig);
352 | if (pos != signature_map_.end()) {
353 | return pos->second;
354 | } else {
355 | uint16_t index = static_cast(signatures_.size());
356 | signature_map_[sig] = index;
357 | signatures_.push_back(sig);
358 | return index;
359 | }
360 | }
361 |
362 | void WasmModuleBuilder::AddIndirectFunction(uint16_t index) {
363 | indirect_functions_.push_back(index);
364 | }
365 |
366 | WasmModuleWriter* WasmModuleBuilder::Build(Zone* zone) {
367 | WasmModuleWriter* writer = new (zone) WasmModuleWriter(zone);
368 | for (auto function : functions_) {
369 | writer->functions_.push_back(function->Build(zone, this));
370 | }
371 | for (auto segment : data_segments_) {
372 | writer->data_segments_.push_back(segment);
373 | }
374 | for (auto sig : signatures_) {
375 | writer->signatures_.push_back(sig);
376 | }
377 | for (auto index : indirect_functions_) {
378 | writer->indirect_functions_.push_back(index);
379 | }
380 | for (auto global : globals_) {
381 | writer->globals_.push_back(global);
382 | }
383 | return writer;
384 | }
385 |
386 | uint32_t WasmModuleBuilder::AddGlobal(MachineType type, bool exported) {
387 | globals_.push_back(std::make_pair(type, exported));
388 | return static_cast(globals_.size() - 1);
389 | }
390 |
391 | WasmModuleWriter::WasmModuleWriter(Zone* zone)
392 | : functions_(zone),
393 | data_segments_(zone),
394 | signatures_(zone),
395 | indirect_functions_(zone),
396 | globals_(zone) {}
397 |
398 | struct Sizes {
399 | size_t header_size;
400 | size_t body_size;
401 |
402 | size_t total() { return header_size + body_size; }
403 |
404 | void Add(size_t header, size_t body) {
405 | header_size += header;
406 | body_size += body;
407 | }
408 |
409 | void AddSection(size_t size) {
410 | if (size > 0) {
411 | Add(1, 0);
412 | while (size > 0) {
413 | Add(1, 0);
414 | size = size >> 7;
415 | }
416 | }
417 | }
418 | };
419 |
420 | WasmModuleIndex* WasmModuleWriter::WriteTo(Zone* zone) const {
421 | Sizes sizes = {0, 0};
422 |
423 | sizes.Add(1, 0);
424 | sizes.Add(kDeclMemorySize, 0);
425 |
426 | sizes.AddSection(signatures_.size());
427 | for (auto sig : signatures_) {
428 | sizes.Add(2 + sig->parameter_count(), 0);
429 | }
430 |
431 | sizes.AddSection(globals_.size());
432 | if (globals_.size() > 0) {
433 | sizes.Add(kDeclGlobalSize * globals_.size(), 0);
434 | }
435 |
436 | sizes.AddSection(functions_.size());
437 | for (auto function : functions_) {
438 | sizes.Add(function->HeaderSize() + function->BodySize(),
439 | function->NameSize());
440 | }
441 |
442 | sizes.AddSection(data_segments_.size());
443 | for (auto segment : data_segments_) {
444 | sizes.Add(segment->HeaderSize(), segment->BodySize());
445 | }
446 |
447 | sizes.AddSection(indirect_functions_.size());
448 | sizes.Add(2 * static_cast(indirect_functions_.size()), 0);
449 |
450 | if (sizes.body_size > 0) sizes.Add(1, 0);
451 |
452 | ZoneVector buffer_vector(sizes.total(), zone);
453 | byte* buffer = buffer_vector.data();
454 | byte* header = buffer;
455 | byte* body = buffer + sizes.header_size;
456 |
457 | // -- emit memory declaration ------------------------------------------------
458 | EmitUint8(&header, kDeclMemory);
459 | EmitUint8(&header, 16); // min memory size
460 | EmitUint8(&header, 16); // max memory size
461 | EmitUint8(&header, 0); // memory export
462 |
463 | // -- emit globals -----------------------------------------------------------
464 | if (globals_.size() > 0) {
465 | EmitUint8(&header, kDeclGlobals);
466 | EmitVarInt(&header, globals_.size());
467 |
468 | for (auto global : globals_) {
469 | EmitUint32(&header, 0);
470 | EmitUint8(&header, WasmOpcodes::MemTypeCodeFor(global.first));
471 | EmitUint8(&header, global.second);
472 | }
473 | }
474 |
475 | // -- emit signatures --------------------------------------------------------
476 | if (signatures_.size() > 0) {
477 | EmitUint8(&header, kDeclSignatures);
478 | EmitVarInt(&header, signatures_.size());
479 |
480 | for (FunctionSig* sig : signatures_) {
481 | EmitUint8(&header, static_cast(sig->parameter_count()));
482 | if (sig->return_count() > 0) {
483 | EmitUint8(&header, WasmOpcodes::LocalTypeCodeFor(sig->GetReturn()));
484 | } else {
485 | EmitUint8(&header, kLocalVoid);
486 | }
487 | for (size_t j = 0; j < sig->parameter_count(); j++) {
488 | EmitUint8(&header, WasmOpcodes::LocalTypeCodeFor(sig->GetParam(j)));
489 | }
490 | }
491 | }
492 |
493 | // -- emit functions ---------------------------------------------------------
494 | if (functions_.size() > 0) {
495 | EmitUint8(&header, kDeclFunctions);
496 | EmitVarInt(&header, functions_.size());
497 |
498 | for (auto func : functions_) {
499 | func->Serialize(buffer, &header, &body);
500 | }
501 | }
502 |
503 | // -- emit data segments -----------------------------------------------------
504 | if (data_segments_.size() > 0) {
505 | EmitUint8(&header, kDeclDataSegments);
506 | EmitVarInt(&header, data_segments_.size());
507 |
508 | for (auto segment : data_segments_) {
509 | segment->Serialize(buffer, &header, &body);
510 | }
511 | }
512 |
513 | // -- emit function table ----------------------------------------------------
514 | if (indirect_functions_.size() > 0) {
515 | EmitUint8(&header, kDeclFunctionTable);
516 | EmitVarInt(&header, indirect_functions_.size());
517 |
518 | for (auto index : indirect_functions_) {
519 | EmitUint16(&header, index);
520 | }
521 | }
522 |
523 | if (sizes.body_size > 0) EmitUint8(&header, kDeclEnd);
524 |
525 | return new (zone) WasmModuleIndex(buffer, buffer + sizes.total());
526 | }
527 |
528 | std::vector UnsignedLEB128From(uint32_t result) {
529 | std::vector output;
530 | uint8_t next = 0;
531 | int shift = 0;
532 | do {
533 | next = static_cast(result >> shift);
534 | if (((result >> shift) & 0xFFFFFF80) != 0) {
535 | next = next | 0x80;
536 | }
537 | output.push_back(next);
538 | shift += 7;
539 | } while ((next & 0x80) != 0);
540 | return output;
541 | }
542 | }
543 | }
544 | }
545 |
--------------------------------------------------------------------------------
/src/wasm/encoder.h:
--------------------------------------------------------------------------------
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_ENCODER_H_
6 | #define V8_WASM_ENCODER_H_
7 |
8 | #include "src/signature.h"
9 | #include "src/zone-containers.h"
10 |
11 | #include "src/base/smart-pointers.h"
12 |
13 | #include "src/wasm/wasm-module.h"
14 | #include "src/wasm/wasm-opcodes.h"
15 | #include "src/wasm/wasm-result.h"
16 |
17 | namespace v8 {
18 | namespace internal {
19 | namespace wasm {
20 |
21 | class WasmModuleBuilder;
22 |
23 | class WasmFunctionEncoder : public ZoneObject {
24 | public:
25 | uint32_t HeaderSize() const;
26 | uint32_t BodySize() const;
27 | uint32_t NameSize() const;
28 | void Serialize(byte* buffer, byte** header, byte** body) const;
29 |
30 | private:
31 | WasmFunctionEncoder(Zone* zone, LocalType return_type, bool exported,
32 | bool external);
33 | friend class WasmFunctionBuilder;
34 | uint16_t signature_index_;
35 | ZoneVector params_;
36 | uint16_t local_int32_count_;
37 | uint16_t local_int64_count_;
38 | uint16_t local_float32_count_;
39 | uint16_t local_float64_count_;
40 | bool exported_;
41 | bool external_;
42 | ZoneVector body_;
43 | ZoneVector name_;
44 |
45 | bool HasLocals() const {
46 | return (local_int32_count_ + local_int64_count_ + local_float32_count_ +
47 | local_float64_count_) > 0;
48 | }
49 |
50 | bool HasName() const {
51 | return exported_ && name_.size() > 0;
52 | }
53 | };
54 |
55 | class WasmFunctionBuilder : public ZoneObject {
56 | public:
57 | uint16_t AddParam(LocalType type);
58 | uint16_t AddLocal(LocalType type);
59 | void ReturnType(LocalType type);
60 | void EmitCode(const byte* code, uint32_t code_size);
61 | void EmitCode(const byte* code, uint32_t code_size,
62 | const uint32_t* local_indices, uint32_t indices_size);
63 | void Emit(WasmOpcode opcode);
64 | void EmitWithU8(WasmOpcode opcode, const byte immediate);
65 | void EmitWithLocal(WasmOpcode opcode);
66 | uint32_t EmitEditableImmediate(const byte immediate);
67 | void EditImmediate(uint32_t offset, const byte immediate);
68 | void Exported(uint8_t flag);
69 | void External(uint8_t flag);
70 | WasmFunctionEncoder* Build(Zone* zone, WasmModuleBuilder* mb) const;
71 |
72 | private:
73 | WasmFunctionBuilder(Zone* zone, const unsigned char* name, int name_length);
74 | friend class WasmModuleBuilder;
75 | LocalType return_type_;
76 | struct Type;
77 | ZoneVector locals_;
78 | uint8_t exported_;
79 | uint8_t external_;
80 | ZoneVector body_;
81 | ZoneVector local_indices_;
82 | ZoneVector name_;
83 | uint16_t AddVar(LocalType type, bool param);
84 | void IndexVars(WasmFunctionEncoder* e, uint16_t* var_index) const;
85 | };
86 |
87 | class WasmDataSegmentEncoder : public ZoneObject {
88 | public:
89 | WasmDataSegmentEncoder(Zone* zone, const byte* data, uint32_t size,
90 | uint32_t dest);
91 | uint32_t HeaderSize() const;
92 | uint32_t BodySize() const;
93 | void Serialize(byte* buffer, byte** header, byte** body) const;
94 |
95 | private:
96 | ZoneVector data_;
97 | uint32_t dest_;
98 | };
99 |
100 | class WasmModuleIndex : public ZoneObject {
101 | public:
102 | const byte* Begin() const { return begin_; }
103 | const byte* End() const { return end_; }
104 |
105 | private:
106 | friend class WasmModuleWriter;
107 | WasmModuleIndex(const byte* begin, const byte* end)
108 | : begin_(begin), end_(end) {}
109 | const byte* begin_;
110 | const byte* end_;
111 | };
112 |
113 | class WasmModuleWriter : public ZoneObject {
114 | public:
115 | WasmModuleIndex* WriteTo(Zone* zone) const;
116 |
117 | private:
118 | friend class WasmModuleBuilder;
119 | WasmModuleWriter(Zone* zone);
120 | ZoneVector functions_;
121 | ZoneVector data_segments_;
122 | ZoneVector signatures_;
123 | ZoneVector indirect_functions_;
124 | ZoneVector> globals_;
125 | };
126 |
127 | class WasmModuleBuilder : public ZoneObject {
128 | public:
129 | WasmModuleBuilder(Zone* zone);
130 | uint16_t AddFunction(const unsigned char* name = NULL, int name_length = 0);
131 | uint32_t AddGlobal(MachineType type, bool exported);
132 | WasmFunctionBuilder* FunctionAt(size_t index);
133 | void AddDataSegment(WasmDataSegmentEncoder* data);
134 | uint16_t AddSignature(FunctionSig* sig);
135 | void AddIndirectFunction(uint16_t index);
136 | WasmModuleWriter* Build(Zone* zone);
137 |
138 | private:
139 | struct CompareFunctionSigs {
140 | int operator()(FunctionSig* a, FunctionSig* b);
141 | };
142 | typedef ZoneMap SignatureMap;
143 |
144 | Zone* zone_;
145 | ZoneVector signatures_;
146 | ZoneVector functions_;
147 | ZoneVector data_segments_;
148 | ZoneVector indirect_functions_;
149 | ZoneVector> globals_;
150 | SignatureMap signature_map_;
151 | };
152 |
153 | std::vector UnsignedLEB128From(uint32_t result);
154 | }
155 | }
156 | }
157 |
158 | #endif // V8_WASM_ENCODER_H_
159 |
--------------------------------------------------------------------------------
/src/wasm/module-decoder.h:
--------------------------------------------------------------------------------
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_MODULE_DECODER_H_
6 | #define V8_WASM_MODULE_DECODER_H_
7 |
8 | #include "src/wasm/ast-decoder.h"
9 | #include "src/wasm/wasm-module.h"
10 |
11 | namespace v8 {
12 | namespace internal {
13 | namespace wasm {
14 | // Decodes the bytes of a WASM module between {module_start} and {module_end}.
15 | ModuleResult DecodeWasmModule(Isolate* isolate, Zone* zone,
16 | const byte* module_start, const byte* module_end,
17 | bool verify_functions, bool asm_js);
18 |
19 | // Exposed for testing. Decodes a single function signature, allocating it
20 | // in the given zone. Returns {nullptr} upon failure.
21 | FunctionSig* DecodeWasmSignatureForTesting(Zone* zone, const byte* start,
22 | const byte* end);
23 |
24 | // Decodes the bytes of a WASM function between
25 | // {function_start} and {function_end}.
26 | FunctionResult DecodeWasmFunction(Isolate* isolate, Zone* zone, ModuleEnv* env,
27 | const byte* function_start,
28 | const byte* function_end);
29 | }
30 | }
31 | }
32 |
33 | #endif // V8_WASM_MODULE_DECODER_H_
34 |
--------------------------------------------------------------------------------
/src/wasm/wasm-compiler.h:
--------------------------------------------------------------------------------
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_TF_BUILDER_H_
6 | #define V8_WASM_TF_BUILDER_H_
7 |
8 | #include "src/zone.h"
9 |
10 | #include "src/wasm/wasm-opcodes.h"
11 |
12 | namespace v8 {
13 | namespace internal {
14 |
15 | namespace compiler {
16 | // Forward declarations for some compiler data structures.
17 | class Node;
18 | class JSGraph;
19 | }
20 |
21 | namespace wasm {
22 | // Forward declarations for some WASM data structures.
23 | struct ModuleEnv;
24 | struct WasmFunction;
25 | class ErrorThrower;
26 |
27 | // Expose {Node} and {Graph} opaquely as {wasm::TFNode} and {wasm::TFGraph}.
28 | typedef compiler::Node TFNode;
29 | typedef compiler::JSGraph TFGraph;
30 | }
31 |
32 | namespace compiler {
33 | // Compiles a single function, producing a code object.
34 | Handle CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate,
35 | wasm::ModuleEnv* module_env,
36 | const wasm::WasmFunction& function, int index);
37 |
38 | // Wraps a JS function, producing a code object that can be called from WASM.
39 | Handle CompileWasmToJSWrapper(Isolate* isolate, wasm::ModuleEnv* module,
40 | Handle function,
41 | uint32_t index);
42 |
43 | // Wraps a given wasm code object, producing a JSFunction that can be called
44 | // from JavaScript.
45 | Handle CompileJSToWasmWrapper(Isolate* isolate,
46 | wasm::ModuleEnv* module,
47 | Handle name,
48 | Handle wasm_code,
49 | uint32_t index);
50 |
51 | // Abstracts details of building TurboFan graph nodes for WASM to separate
52 | // the WASM decoder from the internal details of TurboFan.
53 | class WasmTrapHelper;
54 | class WasmGraphBuilder {
55 | public:
56 | WasmGraphBuilder(Zone* z, JSGraph* g);
57 |
58 | Node** Buffer(size_t count) {
59 | if (count > cur_bufsize) {
60 | size_t new_size = count + cur_bufsize + 5;
61 | cur_buffer =
62 | reinterpret_cast(zone->New(new_size * sizeof(Node*)));
63 | cur_bufsize = new_size;
64 | }
65 | return cur_buffer;
66 | }
67 |
68 | //-----------------------------------------------------------------------
69 | // Operations independent of {control} or {effect}.
70 | //-----------------------------------------------------------------------
71 | Node* Error();
72 | Node* Start(unsigned params);
73 | Node* Param(unsigned index, wasm::LocalType type);
74 | Node* Loop(Node* entry);
75 | Node* Terminate(Node* effect, Node* control);
76 | Node* Merge(unsigned count, Node** controls);
77 | Node* Phi(wasm::LocalType type, unsigned count, Node** vals, Node* control);
78 | Node* EffectPhi(unsigned count, Node** effects, Node* control);
79 | Node* Int32Constant(int32_t value);
80 | Node* Int64Constant(int64_t value);
81 | Node* Float32Constant(float value);
82 | Node* Float64Constant(double value);
83 | Node* Constant(Handle