├── .gitignore
├── .npmignore
├── .travis.yml
├── LICENSE
├── README.md
├── WebAssembly.png
├── WebAssembly_uni.png
├── index.js
├── package.json
├── src
├── Reader.js
├── Writer.js
├── ast
│ ├── ReadState.js
│ ├── Reader.js
│ ├── WriteState.js
│ ├── Writer.js
│ └── index.js
├── index.js
├── reflect
│ ├── Assembly.js
│ ├── BaseExport.js
│ ├── Constant.js
│ ├── DefaultExport.js
│ ├── FunctionDeclaration.js
│ ├── FunctionDefinition.js
│ ├── FunctionImport.js
│ ├── FunctionImportSignature.js
│ ├── FunctionPointerElement.js
│ ├── FunctionPointerTable.js
│ ├── FunctionSignature.js
│ ├── GlobalVariable.js
│ ├── LocalVariable.js
│ ├── RecordExport.js
│ └── index.js
├── stmt
│ ├── BaseExpr.js
│ ├── BaseOperand.js
│ ├── BaseStmt.js
│ ├── ExprF32.js
│ ├── ExprF64.js
│ ├── ExprI32.js
│ ├── ExprVoid.js
│ ├── Stmt.js
│ ├── StmtList.js
│ ├── SwitchCase.js
│ ├── behavior
│ │ ├── BaseBehavior.js
│ │ ├── BinaryBehavior.js
│ │ ├── BlockBehavior.js
│ │ ├── BranchBehavior.js
│ │ ├── CallImportBehavior.js
│ │ ├── CallIndirectBehavior.js
│ │ ├── CallInternalBehavior.js
│ │ ├── CommaBehavior.js
│ │ ├── ConstantPoolBehavior.js
│ │ ├── GetGlobalBehavior.js
│ │ ├── GetLocalBehavior.js
│ │ ├── LabelBehavior.js
│ │ ├── LiteralBehavior.js
│ │ ├── LoadBehavior.js
│ │ ├── LoadWithOffsetBehavior.js
│ │ ├── MultiaryBehavior.js
│ │ ├── OpcodeOnlyBehavior.js
│ │ ├── ReturnBehavior.js
│ │ ├── SetGlobalBehavior.js
│ │ ├── SetLocalBehavior.js
│ │ ├── StmtListBehavior.js
│ │ ├── StoreBehavior.js
│ │ ├── StoreWithOffsetBehavior.js
│ │ ├── SwitchBehavior.js
│ │ ├── SwitchCaseMultipleBehavior.js
│ │ ├── SwitchCaseNoneBehavior.js
│ │ ├── SwitchCaseSingleBehavior.js
│ │ ├── SwitchDefaultMultipleBehavior.js
│ │ ├── SwitchDefaultNoneBehavior.js
│ │ ├── SwitchDefaultSingleBehavior.js
│ │ ├── UnaryBehavior.js
│ │ └── index.js
│ └── index.js
├── types.js
├── util.js
└── util
│ └── BufferQueue.js
├── tests
├── AngryBots-optimized.wasm
├── AngryBots.wasm
├── add-asm.js
├── add-test.js
├── add.wasm
├── assembler.js
├── fib-asm.js
├── fib.wasm
└── test.js
└── tools
├── externs
├── assert.js
└── errors.js
├── opcodes-md-template.js
├── patch-cli.js
└── unpack-cli.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | npm-debug.log
3 | .idea/
4 | raw/
5 | v8.log
6 | tests/*.txt
7 | tests/AngryBotsPacked
8 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | npm-debug.log
3 | .idea/
4 | raw/
5 | v8.log
6 | tests/*.txt
7 | tests/AngryBotsPacked
8 |
9 | WebAssembly.png
10 | WebAssembly_uni.png
11 | tests/*.wasm
12 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - 0.10
4 | - 0.12
5 | env:
6 | - VERBOSE=0
7 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |

2 |
3 | **WebAssembly** is a new, portable, size- and load-time-efficient format suitable for compilation to the web, designed
4 | in a collaborative afford under the umbrella of the W3C ([see](https://www.w3.org/community/webassembly/)).
5 |
6 | This package aims to provide tools for working with [WebAssembly](https://github.com/WebAssembly) binaries, providing
7 | interested developers with an easy way to experiment with the technology from within JavaScript itself.
8 |
9 | [](https://travis-ci.org/dcodeIO/WebAssembly)
10 |
11 | Contents
12 | --------
13 |
14 | * **[Type definitions](https://github.com/dcodeIO/WebAssembly/blob/master/src/types.js)**
15 | Relevant type and opcode definitions.
16 |
17 | * **[Reflection structure](https://github.com/dcodeIO/WebAssembly/tree/master/src/reflect)**
18 | Classes to represent the different sections of a WASM binary.
19 |
20 | * **[Statement types](https://github.com/dcodeIO/WebAssembly/tree/master/src/stmt)**
21 | Classes to represent the different statement and expression types.
22 |
23 | * **[Statement and expression behaviors](https://github.com/dcodeIO/WebAssembly/tree/master/src/stmt/behavior)**
24 | Classes describing the wire-format of any statement or expression in an easy to grasp way.
25 |
26 | * **[Reader](https://github.com/dcodeIO/WebAssembly/blob/master/src/Reader.js)**
27 | A streaming reader for disassembling WASM binaries into their respective reflection structure.
28 |
29 | * **[AstReader](https://github.com/dcodeIO/WebAssembly/blob/master/src/ast/Reader.js)**
30 | A streaming reader for disassembling function bodies into their respective AST.
31 |
32 | * **[Writer](https://github.com/dcodeIO/WebAssembly/blob/master/src/Writer.js)**
33 | A streaming writer for assembling WASM binaries from their respective reflection structure.
34 |
35 | * **[AstWriter](https://github.com/dcodeIO/WebAssembly/blob/master/src/ast/Writer.js)**
36 | A streaming writer for assembling function bodies from their respective AST.
37 |
38 | Compatibility
39 | -------------
40 | For now this library aims to be compatible with what can be learned from the [polyfill prototype](https://github.com/WebAssembly/polyfill-prototype-1),
41 | but is written in plain JavaScript and does not contain any compiled code.
42 |
43 | While this package is built for the [node.js](https://nodejs.org/) platform, it *should* be trivial to also package it
44 | for browsers using [browserify](http://browserify.org).
45 |
46 | Please note that the [WebAssembly design](https://github.com/WebAssembly/design) is still in flux and that
47 | [binary encoding](https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md) and
48 | [AST semantics](https://github.com/WebAssembly/design/blob/master/AstSemantics.md) may change at any time.
49 |
50 | Usage
51 | -----
52 |
53 | ##### Parsing a WASM binary including ASTs
54 |
55 | ```js
56 | var webassembly = require("webassembly"),
57 | Reader = webassembly.Reader;
58 |
59 | var reader = new Reader();
60 |
61 | reader.on("functionDefinition", function(definition, index) {
62 | ...
63 | });
64 |
65 | reader.on("end", function() {
66 | var myAssembly = reader.assembly;
67 | ...
68 | });
69 |
70 | // Write your WASM data to it
71 | // - either manually:
72 | reader.write(wasmBinaryData);
73 | // - or pipe it:
74 | require("fs").createReadStream("wasmBinaryFile.wasm").pipe(reader);
75 | ```
76 |
77 | ##### Just indexing a WASM binary, parsing ASTs on demand
78 |
79 | ```js
80 | var webassembly = require("webassembly"),
81 | Reader = webassembly.Reader,
82 | AstReader = webassembly.ast.Reader;
83 |
84 | var reader = new Reader({
85 | skipAhead: true // Tells the AstReader not to generate statements, skipping ahead
86 | });
87 |
88 | reader.on("end", function() {
89 | reader.assembly.functionDeclarations.forEach(function(declaration) {
90 | var definition = declaration.definition;
91 | ...
92 |
93 | // And create an AstReader from the definition manually,
94 | // piping in the relevant portion of bytes:
95 | var astReader = new AstReader(definition);
96 | astReader.on("ast", function(ast) {
97 | ...
98 | });
99 |
100 | astReader.createReadStream("wasmBinaryFile.wasm", {
101 | start: definition.byteOffset,
102 | end: definition.byteOffset + definition.byteLength
103 | }).pipe(reader);
104 | });
105 | });
106 |
107 | ...
108 | ```
109 |
110 | Documentation
111 | -------------
112 | * [Binary Format](https://github.com/dcodeIO/WebAssembly/wiki/Binary-Format)
113 | * [Opcodes](https://github.com/dcodeIO/WebAssembly/wiki/Opcodes)
114 | * [Reader](https://github.com/dcodeIO/WebAssembly/wiki/Reader)
115 |
116 | Feel free to contribute!
117 |
118 | **License:** [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.html) - Logo derived from [W3C HTML5 Logos](http://www.w3.org/html/logo/) (CC A 3.0)
119 |
--------------------------------------------------------------------------------
/WebAssembly.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dcodeIO/WebAssembly-prototype/50e84e133a6e18b0ba0908eea241f836392ebde2/WebAssembly.png
--------------------------------------------------------------------------------
/WebAssembly_uni.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dcodeIO/WebAssembly-prototype/50e84e133a6e18b0ba0908eea241f836392ebde2/WebAssembly_uni.png
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | exports = require("./src");
2 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "webassembly",
3 | "description": "JavaScript tools for working with WebAssembly (WASM) binaries.",
4 | "author": "Daniel Wirtz ",
5 | "version": "0.9.0",
6 | "main": "src/index.js",
7 | "repository": {
8 | "type": "git",
9 | "url": "https://github.com/dcodeIO/WebAssembly.git"
10 | },
11 | "bugs": {
12 | "url": "https://github.com/dcodeIO/WebAssembly/issues"
13 | },
14 | "homepage": "https://github.com/dcodeIO/WebAssembly",
15 | "keywords": [
16 | "WebAssembly",
17 | "WASM",
18 | "AST",
19 | "parser"
20 | ],
21 | "dependencies": {},
22 | "scripts": {
23 | "test": "node tests/test.js"
24 | },
25 | "engines": {
26 | "node": ">=0.10"
27 | },
28 | "license": "Apache License, Version 2.0"
29 | }
30 |
--------------------------------------------------------------------------------
/src/ast/ReadState.js:
--------------------------------------------------------------------------------
1 | var types = require("../types"),
2 | util = require("../util");
3 |
4 | var ExprI32 = require("../stmt/ExprI32"),
5 | ExprF32 = require("../stmt/ExprF32"),
6 | ExprF64 = require("../stmt/ExprF64"),
7 | ExprVoid = require("../stmt/ExprVoid"),
8 | SwitchCase = require("../stmt/SwitchCase"),
9 | Stmt = require("../stmt/Stmt");
10 |
11 | /**
12 | * AST read state.
13 | * @constructor
14 | * @param {!ast.Reader} reader
15 | * @param {number} popState
16 | * @exports ast.ReadState
17 | */
18 | function ReadState(reader, popState) {
19 |
20 | /**
21 | * Reader reference.
22 | * @type {!ast.Reader}
23 | */
24 | this.reader = reader;
25 |
26 | /**
27 | * Pop state.
28 | * @type {number}
29 | */
30 | this.popState = popState;
31 |
32 | /**
33 | * Current type.
34 | * @type {number|undefined}
35 | * @private
36 | */
37 | this._type = undefined;
38 |
39 | /**
40 | * Whether an imm is present.
41 | * @type {boolean}
42 | * @private
43 | */
44 | this._withImm = false;
45 |
46 | /**
47 | * Current statement.
48 | * @type {!stmt.BaseStmt|undefined}
49 | * @private
50 | */
51 | this._stmt = undefined;
52 |
53 | /**
54 | * States derived from the current operation.
55 | * @type {!Array.}
56 | * @private
57 | */
58 | this._states = [];
59 | }
60 |
61 | module.exports = ReadState;
62 |
63 | var Reader = require("./Reader"); // cyclic
64 |
65 | /**
66 | * Prepares for the next read operation.
67 | * @param {number} type Wire type
68 | * @param {number} code
69 | * @param {number|null} imm
70 | */
71 | ReadState.prototype.prepare = function(type, code, imm) {
72 | this._type = type;
73 | this._withImm = imm !== null;
74 | this._stmt = undefined;
75 | this._states = [];
76 | };
77 |
78 | /**
79 | * Commits the current read operation.
80 | */
81 | ReadState.prototype.commit = function() {
82 | this.reader.bufferQueue.advance();
83 | if (!this.reader.skipAhead) {
84 | this.reader.emit("stmt", this._stmt);
85 | var parent = this.reader.stack[this.reader.stack.length - 1];
86 | parent.add(this._stmt);
87 | }
88 | if (this._states.length > 0) {
89 | if (!this.reader.skipAhead) {
90 | this.reader.stack.push(this._stmt);
91 | this.reader.state.push(this.popState);
92 | }
93 | for (var i=this._states.length-1; i>=0; --i)
94 | this.reader.state.push(this._states[i]);
95 | }
96 | this.reset();
97 | };
98 |
99 | /**
100 | * Resets the internal state.
101 | */
102 | ReadState.prototype.reset = function() {
103 | this._type = this._stmt = undefined;
104 | this._withImm = false;
105 | this._states = [];
106 | this.reader.bufferQueue.reset();
107 | };
108 |
109 | /**
110 | * Gets the current function's return type.
111 | * @returns {number}
112 | */
113 | ReadState.prototype.rtype = function() {
114 | return this.reader.signature.returnType;
115 | };
116 |
117 | /**
118 | * Reads the next unsigned byte.
119 | * @returns {number}
120 | */
121 | ReadState.prototype.u8 = function() {
122 | return this.reader.bufferQueue.readUInt8();
123 | };
124 |
125 | /**
126 | * Reads the next unsigned varint.
127 | * @returns {number}
128 | */
129 | ReadState.prototype.varint = function() {
130 | return this.reader.bufferQueue.readVarint();
131 | };
132 |
133 | /**
134 | * Reads the next signed varint.
135 | * @returns {number}
136 | */
137 | ReadState.prototype.varint_s = function() {
138 | return this.reader.bufferQueue.readVarintSigned();
139 | };
140 |
141 | /**
142 | * Reads the next 32bit float.
143 | * @returns {number}
144 | */
145 | ReadState.prototype.f32 = function() {
146 | return this.reader.bufferQueue.readFloatLE();
147 | };
148 |
149 | /**
150 | * Reads the next 64bit double.
151 | * @returns {number}
152 | */
153 | ReadState.prototype.f64 = function() {
154 | return this.reader.bufferQueue.readDoubleLE();
155 | };
156 |
157 | /**
158 | * Creates a statement or expression with the specified code.
159 | * @param {number} code
160 | * @param {(number|!stmt.BaseOperand|!Array.)=} operands
161 | * @returns {!stmt.BaseStmt|undefined}
162 | */
163 | ReadState.prototype.stmt = function(code, operands) {
164 | if (this.reader.skipAhead)
165 | return;
166 | switch (this._type) {
167 | case types.WireType.ExprI32:
168 | this._stmt = new ExprI32(code, operands);
169 | break;
170 | case types.WireType.ExprF32:
171 | this._stmt = new ExprF32(code, operands);
172 | break;
173 | case types.WireType.ExprF64:
174 | this._stmt = new ExprF64(code, operands);
175 | break;
176 | case types.WireType.ExprVoid:
177 | this._stmt = new ExprVoid(code, operands);
178 | break;
179 | case types.WireType.SwitchCase:
180 | this._stmt = new SwitchCase(code, operands);
181 | break;
182 | case types.WireType.Stmt:
183 | this._stmt = new Stmt(code, operands);
184 | break;
185 | default:
186 | throw Error("illegal WireType: "+this._type);
187 |
188 | }
189 | this._stmt.withImm = this._withImm;
190 | return this._stmt;
191 | };
192 |
193 | /**
194 | * Creates a statement or expression with the specified code, converted to its counterpart without imm.
195 | * @param {number} code
196 | * @param {(number|!stmt.BaseOperand|!Array.)=} operands
197 | * @returns {!stmt.BaseStmt|boolean} `false` if there is no counterpart without imm
198 | */
199 | ReadState.prototype.stmtWithoutImm = function(code, operands) {
200 | if ((code = types.codeWithoutImm(this._type, code)) < 0)
201 | throw Error("cannot convert "+types.WireTypeNames[this._type]+" code to non-imm counterpart: "+code);
202 | return this.stmt(code, operands);
203 | };
204 |
205 | /**
206 | * Prepares to read the next statement or expression.
207 | * @param {number} wireType
208 | */
209 | ReadState.prototype.read = function(wireType) {
210 | if (wireType === undefined)
211 | throw Error("meh");
212 | this._states.push(wireType);
213 | };
214 |
215 | /**
216 | * Gets the constant of matching type at the specified index.
217 | * @param {number} index
218 | * @returns {!reflect.Constant}
219 | */
220 | ReadState.prototype.constant = function(index) {
221 | return this.reader.assembly.getConstant(this._type, index);
222 | };
223 |
224 | /**
225 | * Gets the local variable at the specified index.
226 | * @param {number} index
227 | * @param {number=} type
228 | * @returns {!reflect.LocalVariable}
229 | */
230 | ReadState.prototype.local = function(index, type) {
231 | var variable = this.reader.definition.getVariable(index);
232 | if (typeof type !== 'undefined' && variable.type !== type)
233 | throw Error("illegal local variable type: "+variable.type+" != "+type);
234 | return variable;
235 | };
236 |
237 | /**
238 | * Gets the global variable at the specified index.
239 | * @param {number} index
240 | * @param {number=} type
241 | * @returns {!reflect.GlobalVariable}
242 | */
243 | ReadState.prototype.global = function(index, type) {
244 | var variable = this.reader.assembly.getGlobalVariable(index);
245 | if (typeof type !== 'undefined' && variable.type !== type)
246 | throw Error("illegal global variable type: "+variable.type+" != "+type);
247 | return variable;
248 | };
249 |
250 | /**
251 | * Gets the function declaration at the specified index.
252 | * @param {number} index
253 | * @returns {!reflect.FunctionDeclaration}
254 | */
255 | ReadState.prototype.internal = function(index) {
256 | return this.reader.assembly.getFunctionDeclaration(index);
257 | };
258 |
259 | /**
260 | * Gets the function pointer table at the specified index.
261 | * @param {number} index
262 | * @returns {!reflect.FunctionPointerTable}
263 | */
264 | ReadState.prototype.indirect = function(index) {
265 | return this.reader.assembly.getFunctionPointerTable(index);
266 | };
267 |
268 | /**
269 | * Gets the function import signature at the specified index.
270 | * @param {number} index
271 | * @returns {!reflect.FunctionImportSignature}
272 | */
273 | ReadState.prototype.import = function(index) {
274 | return this.reader.assembly.getFunctionImportSignature(index);
275 | };
276 |
277 | /**
278 | * Advances the buffer queue.
279 | */
280 | ReadState.prototype.advance = function() {
281 | this.reader.bufferQueue.advance();
282 | };
283 |
284 | /**
285 | * Finishes the read state.
286 | */
287 | ReadState.prototype.finish = function() {
288 | this.reset();
289 | this.reader = null;
290 | };
291 |
--------------------------------------------------------------------------------
/src/ast/Reader.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2015 Daniel Wirtz
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 | var stream = require("stream"),
17 | util = require("../util"),
18 | types = require("../types"),
19 | stmt = require("../stmt/");
20 |
21 | var ReadState = require("./ReadState");
22 |
23 | var Constant = require("../reflect/Constant"),
24 | GlobalVariable = require("../reflect/GlobalVariable"),
25 | FunctionSignature = require("../reflect/FunctionSignature"),
26 | FunctionDeclaration = require("../reflect/FunctionDeclaration"),
27 | FunctionImport = require("../reflect/FunctionImport"),
28 | FunctionImportSignature = require("../reflect/FunctionImportSignature"),
29 | FunctionPointerTable = require("../reflect/FunctionPointerTable"),
30 | LocalVariable = require("../reflect/LocalVariable");
31 |
32 | var BaseStmt = stmt.BaseStmt,
33 | StmtList = stmt.StmtList,
34 | Stmt = stmt.Stmt,
35 | SwitchCase = stmt.SwitchCase,
36 | ExprI32 = stmt.ExprI32,
37 | ExprF32 = stmt.ExprF32,
38 | ExprF64 = stmt.ExprF64,
39 | ExprVoid = stmt.ExprVoid;
40 |
41 | var verbose = 0; // For debugging
42 |
43 | /**
44 | * An abstract syntax tree reader.
45 | * @constructor
46 | * @param {!reflect.FunctionDefinition} functionDefinition
47 | * @param {!util.BufferQueue=} bufferQueue
48 | * @param {!Object.=} options
49 | * @exports ast.Reader
50 | */
51 | function Reader(functionDefinition, bufferQueue, options) {
52 | stream.Writable.call(this, options);
53 |
54 | if (!(bufferQueue instanceof util.BufferQueue)) {
55 | options = bufferQueue;
56 | bufferQueue = undefined;
57 | }
58 |
59 | /**
60 | * Function definition.
61 | * @type {!reflect.FunctionDefinition}
62 | */
63 | this.definition = functionDefinition;
64 |
65 | /**
66 | * Read buffer queue.
67 | * @type {!util.BufferQueue}
68 | */
69 | this.bufferQueue = bufferQueue || new util.BufferQueue();
70 |
71 | /**
72 | * State stack.
73 | * @type {!Array.}
74 | */
75 | this.state = [Reader.State.StmtList];
76 |
77 | /**
78 | * Processing stack.
79 | * @type {Array.}
80 | */
81 | this.stack = []; // Expected to contain the root StmtList only when finished
82 |
83 | /**
84 | * Read state closure.
85 | * @type {!ast.ReadState}
86 | */
87 | this.readState = new ReadState(this, Reader.State.Pop);
88 |
89 | /**
90 | * Whether to skip ahead, not parsing the AST in detail.
91 | * @type {boolean}
92 | */
93 | this.skipAhead = !!(options && options.skipAhead);
94 | }
95 |
96 | module.exports = Reader;
97 |
98 | // Extends stream.Writable
99 | Reader.prototype = Object.create(stream.Writable.prototype);
100 |
101 | /**
102 | * Global offset.
103 | * @name ast.Reader#offset
104 | * @type {number}
105 | */
106 | Object.defineProperty(Reader.prototype, "offset", {
107 | get: function() {
108 | return this.bufferQueue.offset;
109 | }
110 | });
111 |
112 | /**
113 | * Function declaration.
114 | * @name ast.Reader#declaration
115 | * @type {!reflect.FunctionDeclaration}
116 | */
117 | Object.defineProperty(Reader.prototype, "declaration", {
118 | get: function() {
119 | return this.definition.declaration;
120 | }
121 | });
122 |
123 | /**
124 | * Function signature.
125 | * @name ast.Reader#signature
126 | * @type {!reflect.FunctionSignature}
127 | */
128 | Object.defineProperty(Reader.prototype, "signature", {
129 | get: function() {
130 | return this.definition.declaration.signature;
131 | }
132 | });
133 |
134 | /**
135 | * Assembly.
136 | * @name ast.Reader#assembly
137 | * @type {!reflect.Assembly}
138 | */
139 | Object.defineProperty(Reader.prototype, "assembly", {
140 | get: function() {
141 | return this.definition.declaration.assembly;
142 | }
143 | });
144 |
145 | /**
146 | * States.
147 | * @type {!Object.}
148 | * @const
149 | */
150 | Reader.State = {
151 | ExprI32: types.WireType.ExprI32,
152 | ExprF32: types.WireType.ExprF32,
153 | ExprF64: types.WireType.ExprF64,
154 | ExprVoid: types.WireType.ExprVoid,
155 | SwitchCase: types.WireType.SwitchCase,
156 | Stmt: types.WireType.Stmt,
157 | StmtList: types.WireType.StmtList,
158 | Pop: types.WireTypeMax + 1
159 | };
160 |
161 | Reader.prototype._write = function (chunk, encoding, callback) {
162 | if (this.state.length === 0) { // Already done or failed
163 | callback(Error("already ended"));
164 | return;
165 | }
166 | if (encoding)
167 | chunk = new Buffer(chunk, encoding);
168 | if (chunk.length === 0) {
169 | callback();
170 | return;
171 | }
172 | this.bufferQueue.push(chunk);
173 | this._process();
174 | callback();
175 | };
176 |
177 | Reader.prototype._process = function() {
178 | if (this.state.length === 0)
179 | return;
180 | do {
181 | if (this.state.length === 0) { // Done
182 | if (!this.skipAhead) {
183 | this.readState.finish();
184 | if (this.stack.length !== 1)
185 | throw Error("illegal state: stack not cleared: "+this.stack.length);
186 | var stmtList = this.stack[0];
187 | if (!(stmtList instanceof StmtList))
188 | throw Error("illegal state: last stack item is not a StmtList: " + stmtList);
189 | if (stmtList.length > 0) {
190 | stmtList.forEach(function (stmt) {
191 | if (!(stmt instanceof BaseStmt))
192 | throw Error("illegal state: StmtList contains non-Stmt: " + stmt);
193 | });
194 | }
195 | this.emit("ast", stmtList);
196 | }
197 | this.emit("end");
198 | return;
199 | }
200 | var state = this.state.pop();
201 | if (verbose >= 2)
202 | console.log("state: "+state);
203 | try {
204 | switch (state) {
205 | case Reader.State.ExprI32:
206 | this._readExprI32();
207 | break;
208 | case Reader.State.ExprF32:
209 | this._readExprF32();
210 | break;
211 | case Reader.State.ExprF64:
212 | this._readExprF64();
213 | break;
214 | case Reader.State.ExprVoid:
215 | this._readExprVoid();
216 | break;
217 | case Reader.State.SwitchCase:
218 | this._readSwitchCase();
219 | break;
220 | case Reader.State.Stmt:
221 | this._readStmt();
222 | break;
223 | case Reader.State.StmtList:
224 | this._readStmtList();
225 | break;
226 | case Reader.State.Pop:
227 | this.stack.pop();
228 | break;
229 | default:
230 | throw Error("illegal state: " + state);
231 | }
232 | } catch (err) {
233 | if (err === util.BufferQueue.E_MORE) {
234 | this.state.push(state); // Wait for more
235 | return;
236 | }
237 | if (verbose >= 1)
238 | console.log(this.inspect());
239 | this.emit("error", err);
240 | this.state = [];
241 | return;
242 | } finally {
243 | this.readState.reset();
244 | }
245 | } while (true);
246 | };
247 |
248 | Reader.prototype._readStmtList = function() {
249 | var size = this.readState.varint();
250 | this.readState.advance();
251 | if (!this.skipAhead)
252 | this.stack.push(new StmtList(size));
253 | for (var i=0; i= 1)
270 | console.log("processing "+name+":" + types[name+"Names"][code] + " @ " + (this.offset-1).toString(16));
271 | this.readState.prepare(wireType, code, null);
272 | clazz.determineBehavior(code, false).read(this.readState, code, null);
273 | } else {
274 | code = util.unpackWithImm(code);
275 | if (verbose >= 1)
276 | console.log("processing "+name+"WithImm:" + types[name+"WithImmNames"][code.code] + " @ " + (this.offset-1).toString(16));
277 | this.readState.prepare(wireType, code.code, code.imm);
278 | clazz.determineBehavior(code.code, true).read(this.readState, code.code, code.imm);
279 | }
280 | this.readState.commit();
281 | };
282 | }
283 |
284 | Reader.prototype._readStmt = makeGenericRead(types.WireType.Stmt, Stmt, "Stmt");
285 | Reader.prototype._readExprI32 = makeGenericRead(types.WireType.ExprI32, ExprI32, "I32");
286 | Reader.prototype._readExprF32 = makeGenericRead(types.WireType.ExprF32, ExprF32, "F32");
287 | Reader.prototype._readExprF64 = makeGenericRead(types.WireType.ExprF64, ExprF64, "F64");
288 | Reader.prototype._readExprVoid = makeGenericRead(types.WireType.ExprVoid, ExprVoid, "Void");
289 | Reader.prototype._readSwitchCase = makeGenericRead(types.WireType.SwitchCase, SwitchCase, "SwitchCase");
290 |
291 | /**
292 | * Inspects a statement structure.
293 | * @param {!stmt.BaseStmt|!stmt.StmtList|number} stmt
294 | * @param {number=} depth
295 | * @returns {string}
296 | */
297 | Reader.inspect = function(stmt, depth) {
298 | depth = depth || 0;
299 | var indent = "";
300 | for (var i=0; i}
36 | * @private
37 | */
38 | this._stack = [];
39 | }
40 |
41 | module.exports = WriteState;
42 |
43 | WriteState.prototype.prepare = function(type, stmt) {
44 | this._type = type;
45 | this._stmt = stmt;
46 | this._stack = [];
47 | };
48 |
49 | WriteState.prototype.commit = function() {
50 | this.writer.bufferQueue.commit();
51 | for (var i=this._stack.length-1; i>=0; --i)
52 | this.writer.stack.push(this._stack[i]);
53 | this.reset();
54 | };
55 |
56 | WriteState.prototype.reset = function() {
57 | this._type = this._stmt = undefined;
58 | this._stack = [];
59 | };
60 |
61 | WriteState.prototype.rtype = function() {
62 | return this.writer.signature.returnType;
63 | };
64 |
65 | WriteState.prototype.u8 = function(b) {
66 | this.writer.bufferQueue.writeUInt8(b);
67 | };
68 |
69 | WriteState.prototype.code = function(code) {
70 | this.writer.bufferQueue.writeUInt8(code);
71 | };
72 |
73 | WriteState.prototype.codeWithImm = function(code, imm) {
74 | if (imm < 0 || imm > types.OpWithImm_ImmMax || (code = types.codeWithImm(this._type, code)) < 0)
75 | return false;
76 | if (this.writer.preserveWithImm && !this._stmt.withImm)
77 | return false;
78 | this.writer.bufferQueue.writeUInt8(util.packWithImm(code, imm));
79 | return true;
80 | };
81 |
82 | WriteState.prototype.varint = function(value) {
83 | this.writer.bufferQueue.writeVarint(value);
84 | };
85 |
86 | WriteState.prototype.varint_s = function(value) {
87 | this.writer.bufferQueue.writeVarintSigned(value);
88 | };
89 |
90 | WriteState.prototype.f32 = function(value) {
91 | this.writer.bufferQueue.writeFloatLE(value);
92 | };
93 |
94 | WriteState.prototype.f64 = function(value) {
95 | this.writer.bufferQueue.writeDoubleLE(value);
96 | };
97 |
98 | WriteState.prototype.write = function(stmt) {
99 | this._stack.push(stmt);
100 | };
101 |
--------------------------------------------------------------------------------
/src/ast/Writer.js:
--------------------------------------------------------------------------------
1 | var stream = require("stream"),
2 | assert = require("assert"),
3 | types = require("../types"),
4 | util = require("../util");
5 |
6 | var WriteState = require("./WriteState"),
7 | StmtList = require("../stmt/StmtList"),
8 | ExprI32 = require("../stmt/ExprI32"),
9 | ExprF32 = require("../stmt/ExprF32"),
10 | ExprF64 = require("../stmt/ExprF64"),
11 | ExprVoid = require("../stmt/ExprVoid"),
12 | SwitchCase = require("../stmt/SwitchCase"),
13 | Stmt = require("../stmt/Stmt");
14 |
15 | var verbose = 0; // for debugging
16 |
17 | /**
18 | * An abstract syntax tree writer.
19 | *
20 | * The writer is created in paused mode. Call {@link ast.Writer#resume) to
21 | * begin writing the AST.
22 | *
23 | * @param {!reflect.FunctionDefinition} functionDefinition
24 | * @param {!util.BufferQueue=} bufferQueue
25 | * @param {!Object.=} options
26 | * @constructor
27 | * @extends stream.Readable
28 | * @exports ast.Writer
29 | */
30 | function Writer(functionDefinition, bufferQueue, options) {
31 | assert(functionDefinition.ast instanceof StmtList, "definition must contain an AST");
32 |
33 | stream.Readable.call(this, options);
34 |
35 | if (!(bufferQueue instanceof util.BufferQueue)) {
36 | options = bufferQueue;
37 | bufferQueue = undefined;
38 | }
39 |
40 | /**
41 | * Function definition.
42 | * @type {!reflect.FunctionDefinition}
43 | */
44 | this.definition = functionDefinition;
45 |
46 | /**
47 | * Writer buffer queue.
48 | * @type {!util.BufferQueue}
49 | */
50 | this.bufferQueue = bufferQueue || new util.BufferQueue();
51 |
52 | /**
53 | * Statement stack.
54 | * @type {!Array.}
55 | */
56 | this.stack = [functionDefinition.ast]; // StmtList
57 |
58 | /**
59 | * Write state.
60 | * @type {!ast.WriteState}
61 | */
62 | this.writeState = new WriteState(this);
63 |
64 | /**
65 | * Whether opcodes with imm should be preserved. Relevant only when rewriting ASTs with the intend to preserve
66 | * their original (unoptimized) byte code, e.g. for comparison.
67 | * @type {boolean}
68 | */
69 | this.preserveWithImm = !!(options && options.preserveWithImm);
70 |
71 | this.pause();
72 | }
73 |
74 | module.exports = Writer;
75 |
76 | // Extends Readable
77 | Writer.prototype = Object.create(stream.Readable.prototype);
78 |
79 | /**
80 | * Function declaration.
81 | * @name ast.Writer#declaration
82 | * @type {!reflect.FunctionDeclaration}
83 | */
84 | Object.defineProperty(Writer.prototype, "declaration", {
85 | get: function() {
86 | return this.definition.declaration;
87 | }
88 | });
89 |
90 | /**
91 | * Function signature.
92 | * @name ast.Writer#signature
93 | * @type {!reflect.FunctionSignature}
94 | */
95 | Object.defineProperty(Writer.prototype, "signature", {
96 | get: function() {
97 | return this.definition.declaration.signature;
98 | }
99 | });
100 |
101 | /**
102 | * Assembly.
103 | * @name ast.Writer#assembly
104 | * @type {!reflect.Assembly}
105 | */
106 | Object.defineProperty(Writer.prototype, "assembly", {
107 | get: function() {
108 | return this.definition.declaration.assembly;
109 | }
110 | });
111 |
112 | /**
113 | * Global offset.
114 | * @name ast.Writer#offset
115 | * @type {number}
116 | */
117 | Object.defineProperty(Writer.prototype, "offset", {
118 | get: function() {
119 | return this.bufferQueue.offset;
120 | }
121 | });
122 |
123 | Writer.prototype._read = function(size) {
124 | if (this.stack.length === 0)
125 | throw Error("already done");
126 | this.bufferQueue.push(new Buffer(size));
127 | this._process();
128 | };
129 |
130 | Writer.prototype._process = function() {
131 | if (this.stack.length === 0)
132 | return;
133 | while (this.stack.length > 0) {
134 | var stmt = this.stack.pop(),
135 | state = stmt.type;
136 | this.emit("switchState", state, this.offset);
137 | try {
138 | switch (state) {
139 | case types.WireType.ExprI32:
140 | this._writeExprI32(stmt);
141 | break;
142 | case types.WireType.ExprF32:
143 | this._writeExprF32(stmt);
144 | break;
145 | case types.WireType.ExprF64:
146 | this._writeExprF64(stmt);
147 | break;
148 | case types.WireType.ExprVoid:
149 | this._writeExprVoid(stmt);
150 | break;
151 | case types.WireType.SwitchCase:
152 | this._writeSwitchCase(stmt);
153 | break;
154 | case types.WireType.Stmt:
155 | this._writeStmt(stmt);
156 | break;
157 | case types.WireType.StmtList:
158 | this._writeStmtList(stmt);
159 | break;
160 | default:
161 | throw Error("illegal wire type: " + stmt.type);
162 | }
163 | } catch (err) {
164 | if (err === util.BufferQueue.E_MORE) {
165 | this.stack.push(stmt);
166 | var buf = this.bufferQueue.reset().toBuffer();
167 | this.push(buf);
168 | if (buf.length > 0)
169 | this.bufferQueue.clear();
170 | return; // Wait for more
171 | }
172 | this.emit("error", err);
173 | this.stack = [];
174 | return;
175 | }
176 | }
177 | this.bufferQueue.commit();
178 | this.push(this.bufferQueue.toBuffer());
179 | this.bufferQueue.clear();
180 | this.push(null);
181 | };
182 |
183 | Writer.prototype._writeStmtList = function(stmtList) {
184 | this.bufferQueue
185 | .writeVarint(stmtList.length)
186 | .commit();
187 | for (var i=stmtList.length-1; i>=0; --i)
188 | this.stack.push(stmtList[i]);
189 | };
190 |
191 | function makeGenericWrite(wireType, clazz, name) {
192 | return function(stmt) {
193 | if (verbose >= 1)
194 | console.log("writing "+stmt+" @ "+this.offset.toString(16));
195 | this.emit("stmt", stmt);
196 | this.writeState.prepare(wireType, stmt);
197 | stmt.behavior.write(this.writeState, stmt);
198 | this.writeState.commit();
199 | }
200 | }
201 |
202 | Writer.prototype._writeExprI32 = makeGenericWrite(types.WireType.ExprI32, ExprI32, "I32");
203 | Writer.prototype._writeExprF32 = makeGenericWrite(types.WireType.ExprF32, ExprF32, "F32");
204 | Writer.prototype._writeExprF64 = makeGenericWrite(types.WireType.ExprF64, ExprF64, "F64");
205 | Writer.prototype._writeExprVoid = makeGenericWrite(types.WireType.ExprVoid, ExprVoid, "Void");
206 | Writer.prototype._writeSwitchCase = makeGenericWrite(types.WireType.SwitchCase, SwitchCase, "SwitchCase");
207 | Writer.prototype._writeStmt = makeGenericWrite(types.WireType.Stmt, Stmt, "Stmt");
208 |
--------------------------------------------------------------------------------
/src/ast/index.js:
--------------------------------------------------------------------------------
1 | exports.Reader = require("./Reader");
2 | exports.ReadState = require("./ReadState");
3 |
4 | exports.Writer = require("./Writer");
5 | exports.WriteState = require("./WriteState");
6 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | exports.types = require("./types");
2 | exports.util = require("./util");
3 | exports.stmt = require("./stmt");
4 | exports.reflect = require("./reflect");
5 | exports.ast = require("./ast");
6 |
7 | exports.Reader = require("./Reader");
8 | exports.Writer = require("./Writer");
9 |
--------------------------------------------------------------------------------
/src/reflect/BaseExport.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Abstract base class of exports.
3 | * @constructor
4 | * @param {!Assembly} assembly
5 | * @exports reflect.BaseExport
6 | */
7 | function BaseExport(assembly) {
8 |
9 | /**
10 | * Assembly reference.
11 | * @type {!reflect.Assembly}
12 | */
13 | this.assembly = assembly;
14 | }
15 |
16 | module.exports = BaseExport;
17 |
--------------------------------------------------------------------------------
/src/reflect/Constant.js:
--------------------------------------------------------------------------------
1 | var types = require("../types");
2 |
3 | var BaseOperand = require("../stmt/BaseOperand");
4 |
5 | /**
6 | * A global constant.
7 | * @constructor
8 | * @param {!Assembly} assembly
9 | * @param {number} type
10 | * @param {number} value
11 | * @extends stmt.BaseOperand
12 | * @exports reflect.Constant
13 | */
14 | function Constant(assembly, type, value) {
15 | BaseOperand.call(this);
16 |
17 | /**
18 | * Assembly reference.
19 | * @type {!Assembly}
20 | */
21 | this.assembly = assembly;
22 |
23 | /**
24 | * Constant type.
25 | * @type {number}
26 | */
27 | this.type = type;
28 |
29 | /**
30 | * Constant value.
31 | * @type {number}
32 | */
33 | this.value = value;
34 | }
35 |
36 | module.exports = Constant;
37 |
38 | // Extends BaseOperand
39 | Constant.prototype = Object.create(BaseOperand.prototype);
40 |
41 | /**
42 | * Constant index in the constant pool of its respective type.
43 | * @name reflect.Constant#index
44 | * @type {number}
45 | */
46 | Object.defineProperty(Constant.prototype, "index", {
47 | get: function() {
48 | switch (this.type) {
49 | case types.Type.I32:
50 | return this.assembly.constantsI32.indexOf(this);
51 | case types.Type.F32:
52 | return this.assembly.constantsF32.indexOf(this);
53 | case types.Type.F64:
54 | return this.assembly.constantsF64.indexOf(this);
55 | default:
56 | throw Error("illegal type: "+this.type);
57 | }
58 | }
59 | });
60 |
61 | /**
62 | * Returns a string representation of this constant.
63 | * @returns {string}
64 | */
65 | Constant.prototype.toString = function() {
66 | return "Constant"+types.TypeNames[this.type]
67 | + " value:"+this.value;
68 | };
69 |
--------------------------------------------------------------------------------
/src/reflect/DefaultExport.js:
--------------------------------------------------------------------------------
1 | var BaseExport = require("./BaseExport"),
2 | FunctionDeclaration = require("./FunctionDeclaration");
3 |
4 | /**
5 | * A default export.
6 | * @constructor
7 | * @param {!Assembly} assembly
8 | * @param {number|!FunctionDeclaration} function_
9 | * @extends BaseExport
10 | * @exports reflect.DefaultExport
11 | */
12 | function DefaultExport(assembly, function_) {
13 | BaseExport.call(this, assembly);
14 |
15 | /**
16 | * Exported function.
17 | * @type {!reflect.FunctionDeclaration}
18 | */
19 | this.function = function_ instanceof FunctionDeclaration
20 | ? function_
21 | : this.assembly.getFunctionDeclaration(function_);
22 | }
23 |
24 | module.exports = DefaultExport;
25 |
26 | // Extends BaseExport
27 | DefaultExport.prototype = Object.create(BaseExport.prototype);
28 |
29 | /**
30 | * Returns a string representation of this export.
31 | * @returns {string}
32 | */
33 | DefaultExport.prototype.toString = function() {
34 | return "DefaultExport " + this.function.toString();
35 | };
36 |
--------------------------------------------------------------------------------
/src/reflect/FunctionDeclaration.js:
--------------------------------------------------------------------------------
1 | var types = require("../types"),
2 | util = require("../util");
3 |
4 | var FunctionSignature = require("./FunctionSignature"),
5 | BaseOperand = require("../stmt/BaseOperand");
6 |
7 | /**
8 | * A function declaration.
9 | * @constructor
10 | * @param {!reflect.Assembly} assembly
11 | * @param {number|!reflect.FunctionSignature} signature
12 | * @extends stmt.BaseOperand
13 | * @exports reflect.FunctionDeclaration
14 | */
15 | function FunctionDeclaration(assembly, signature) {
16 | BaseOperand.call(this);
17 |
18 | /**
19 | * Assembly reference.
20 | * @type {!reflect.Assembly}
21 | */
22 | this.assembly = assembly;
23 |
24 | /**
25 | * Signature reference.
26 | * @type {!reflect.FunctionSignature}
27 | */
28 | this.signature = signature instanceof FunctionSignature
29 | ? signature
30 | : assembly.getFunctionSignature(signature);
31 |
32 | /**
33 | * Function definition.
34 | * @type {reflect.FunctionDefinition}
35 | */
36 | this.definition = null; // Assigned later on
37 | }
38 |
39 | module.exports = FunctionDeclaration;
40 |
41 | // Extends BaseOperand
42 | FunctionDeclaration.prototype = Object.create(BaseOperand.prototype);
43 |
44 | /**
45 | * Function declaration index.
46 | * @name reflect.FunctionDeclaration#index
47 | * @type {number}
48 | */
49 | Object.defineProperty(FunctionDeclaration.prototype, "index", {
50 | get: function() {
51 | return this.assembly.functionDeclarations.indexOf(this);
52 | }
53 | });
54 |
55 | /**
56 | * Indexed name.
57 | * @name reflect.FunctionDeclaration#name
58 | * @type {string}
59 | */
60 | Object.defineProperty(FunctionDeclaration.prototype, "name", {
61 | get: function() {
62 | var func_name_base = this.assembly.functionImports.length + this.assembly.globalVariables.length;
63 | return this.assembly.globalName(func_name_base + this.index, "F");
64 | }
65 | });
66 |
67 | /**
68 | * Returns a string representation of this function declaration.
69 | * @returns {string}
70 | */
71 | FunctionDeclaration.prototype.toString = function() {
72 | return "FunctionDeclaration " + this.name
73 | + " idx:" + this.index
74 | + " sig:" + this.signature.index;
75 | };
76 |
--------------------------------------------------------------------------------
/src/reflect/FunctionDefinition.js:
--------------------------------------------------------------------------------
1 | var types = require("../types"),
2 | util = require("../util");
3 |
4 | var FunctionSignature = require("./FunctionSignature"),
5 | BaseStmt = require("../stmt/BaseStmt");
6 |
7 | /**
8 | * A function definition.
9 | * @constructor
10 | * @param {!reflect.FunctionDeclaration} declaration
11 | * @param {number} nI32vars
12 | * @param {number} nF32vars
13 | * @param {number} nF64vars
14 | * @param {number} byteOffset
15 | * @param {number=} byteLength
16 | * @exports reflect.FunctionDefinition
17 | */
18 | function FunctionDefinition(declaration, nI32vars, nF32vars, nF64vars, byteOffset, byteLength) {
19 |
20 | /**
21 | * Function declaration reference.
22 | * @type {!reflect.FunctionDeclaration}
23 | */
24 | this.declaration = declaration;
25 |
26 | /**
27 | * Local variables.
28 | * @type {!Array.}
29 | */
30 | this.variables = new Array(declaration.signature.argumentTypes.length + nI32vars + nF32vars + nF64vars);
31 | var index = 0;
32 | declaration.signature.argumentTypes.forEach(function (type) {
33 | this.variables[index++] = new LocalVariable(this, type);
34 | }, this);
35 | for (var i = 0; i < nI32vars; ++i, ++index)
36 | this.variables[index] = new LocalVariable(this, types.Type.I32);
37 | for (i = 0; i < nF32vars; ++i, ++index)
38 | this.variables[index] = new LocalVariable(this, types.Type.F32);
39 | for (i = 0; i < nF64vars; ++i, ++index)
40 | this.variables[index] = new LocalVariable(this, types.Type.F64);
41 |
42 | /**
43 | * Byte offset of the function body.
44 | * @type {number}
45 | */
46 | this.byteOffset = byteOffset || -1;
47 |
48 | /**
49 | * Byte length of the function body.
50 | * @type {number}
51 | */
52 | this.byteLength = byteLength || -1;
53 |
54 | /**
55 | * Abstract syntax tree.
56 | * @type {stmt.StmtList}
57 | */
58 | this.ast = null;
59 | }
60 |
61 | module.exports = FunctionDefinition;
62 |
63 | var LocalVariable = require("./LocalVariable"); // cyclic
64 |
65 | /**
66 | * Indexed internal function name.
67 | * @name reflect.FunctionDefinition#name
68 | * @type {string}
69 | */
70 | Object.defineProperty(FunctionDefinition.prototype, "name", {
71 | get: function() {
72 | return this.declaration.name;
73 | }
74 | });
75 |
76 | /**
77 | * Declaration index.
78 | * @name reflect.FunctionDefinition#index
79 | * @type {number}
80 | */
81 | Object.defineProperty(FunctionDefinition.prototype, "index", {
82 | get: function() {
83 | return this.declaration.index;
84 | }
85 | });
86 |
87 | /**
88 | * Returns a string representation of this function definition.
89 | * @returns {string}
90 | */
91 | FunctionDefinition.prototype.toString = function() {
92 | return "FunctionDefinition " + this.name
93 | + " vars:" + this.variables.length
94 | + " decl:" + this.declaration.index;
95 | };
96 |
97 | /**
98 | * Gets the variable at the specified index.
99 | * @param {number} index
100 | * @returns {!reflect.LocalVariable}
101 | */
102 | FunctionDefinition.prototype.getVariable = function(index) {
103 | util.assertInteger("index", index, 0, this.variables.length-1);
104 | return this.variables[index];
105 | };
106 |
107 | function replace(ast, oldStmt, newStmt) {
108 | var stack = [];
109 | for (var i=ast.length-1; i>=0; --i) {
110 | stack.push(ast[i]);
111 | if (ast[i] === oldStmt)
112 | ast[i] = newStmt;
113 | }
114 | while (stack.length > 0) {
115 | var current = stack.pop(), k;
116 | for (i=0,k=current.operands.length; i=0; --i)
136 | stack.push(this.ast[i]);
137 | var n = 0;
138 | while (stack.length > 0) {
139 | var stmt = stack.pop(),
140 | behavior = stmt.behavior;
141 | if (typeof behavior.optimize === 'function') {
142 | var code = stmt.code,
143 | optimizedStmt = behavior.optimize(this, stmt);
144 | if (optimizedStmt !== stmt) {
145 | replace(this.ast, stmt, optimizedStmt);
146 | ++n;
147 | } else if (optimizedStmt.code !== code)
148 | ++n;
149 | }
150 | for (i=stmt.operands.length-1; i>=0; --i) {
151 | var operand = stmt.operands[i];
152 | if (operand instanceof BaseStmt)
153 | stack.push(operand);
154 | }
155 | }
156 | return n;
157 | };
158 |
159 | /**
160 | * Builds the function header in asm.js.
161 | * @param {bool=} pack
162 | * @returns {string}
163 | */
164 | FunctionDefinition.prototype.asmHeader = function(pack) {
165 | var indent = pack ? "" : " ",
166 | ws = pack ? "" : " ",
167 | nl = pack ? "" : "\n";
168 | var sb = [];
169 | sb.push("function ", this.name, "(");
170 | var args = this.declaration.signature.argumentTypes;
171 | var assembly = this.declaration.assembly;
172 | for (var i=0; i 0)
174 | sb.push(",");
175 | sb.push(assembly.localName(i));
176 | }
177 | sb.push(")", ws, "{\n");
178 | if (args.length > 0) {
179 | for (i = 0; i < args.length; ++i) {
180 | sb.push(indent, assembly.localName(i), ws, "=", ws);
181 | switch (args[i]) {
182 | case types.Type.I32:
183 | sb.push(assembly.localName(i), "|0;", nl);
184 | break;
185 | case types.Type.F32:
186 | sb.push(util.hotStdLibName(types.HotStdLib.FRound), "(", assembly.localName(i), ");", nl);
187 | break;
188 | case types.Type.F64:
189 | sb.push("+", assembly.localName(i), ";", nl);
190 | break;
191 | }
192 | }
193 | }
194 | if (this.variables.length > args.length) {
195 | sb.push(indent, "var ");
196 | for (i = args.length; i < this.variables.length; ++i) {
197 | var v = this.variables[i];
198 | if (i > args.length)
199 | sb.push(",", nl, indent);
200 | sb.push(assembly.localName(i + args.length), ws, "=", ws);
201 | switch (v.type) {
202 | case types.Type.I32:
203 | sb.push("0");
204 | break;
205 | case types.Type.F32:
206 | sb.push(util.hotStdLibName(types.HotStdLib.FRound), "(0)");
207 | break;
208 | case types.Type.F64:
209 | sb.push("0.");
210 | }
211 | }
212 | sb.push(";");
213 | }
214 | return sb.join("");
215 | };
216 |
--------------------------------------------------------------------------------
/src/reflect/FunctionImport.js:
--------------------------------------------------------------------------------
1 | /**
2 | * A function import.
3 | * @constructor
4 | * @param {!reflect.Assembly} assembly
5 | * @param {string} importName
6 | * @param {!Array.} importSignatures
7 | * @exports reflect.FunctionImport
8 | */
9 | function FunctionImport(assembly, importName, importSignatures) {
10 |
11 | /**
12 | * Assembly reference.
13 | * @type {!reflect.Assembly}
14 | */
15 | this.assembly = assembly;
16 |
17 | /**
18 | * Import name.
19 | * @type {string}
20 | */
21 | this.importName = importName;
22 |
23 | /**
24 | * Function import signatures.
25 | * @type {!Array.}
26 | */
27 | this.signatures = [];
28 | importSignatures.forEach(function(signature) {
29 | this.signatures.push(
30 | signature instanceof FunctionImportSignature
31 | ? signature
32 | : assembly.getFunctionImportSignature(signature)
33 | );
34 | }, this);
35 | }
36 |
37 | module.exports = FunctionImport;
38 |
39 | var FunctionImportSignature = require("./FunctionImportSignature"); // cyclic
40 |
41 | /**
42 | * Function import index.
43 | * @name reflect.FunctionImport#index
44 | * @type {number}
45 | */
46 | Object.defineProperty(FunctionImport.prototype, "index", {
47 | get: function() {
48 | return this.assembly.functionImports.indexOf(this);
49 | }
50 | });
51 |
52 | /**
53 | * Indexed name.
54 | * @name reflect.FunctionImport#name
55 | * @type {number}
56 | */
57 | Object.defineProperty(FunctionImport.prototype, "name", {
58 | get: function() {
59 | return this.assembly.globalName(this.index);
60 | }
61 | });
62 |
63 | /**
64 | * Returns a string representation of this import.
65 | * @returns {string}
66 | */
67 | FunctionImport.prototype.toString = function() {
68 | return "FunctionImport " + "foreign." + this.importName
69 | + " idx:" + this.index
70 | + " sigs:" + this.signatures.length;
71 | };
72 |
--------------------------------------------------------------------------------
/src/reflect/FunctionImportSignature.js:
--------------------------------------------------------------------------------
1 | var FunctionSignature = require("./FunctionSignature"),
2 | BaseOperand = require("../stmt/BaseOperand");
3 |
4 | /**
5 | * A function import signature.
6 | * @constructor
7 | * @param {!reflect.Assembly} assembly
8 | * @param {number|!reflect.FunctionImport} functionImport
9 | * @param {number|!reflect.FunctionSignature} signature
10 | * @extends stmt.BaseOperand
11 | * @exports reflect.FunctionImportSignature
12 | */
13 | function FunctionImportSignature(assembly, functionImport, signature) {
14 |
15 | /**
16 | * Assembly reference.
17 | * @type {!reflect.Assembly}
18 | */
19 | this.assembly = assembly;
20 |
21 | /**
22 | * Function import.
23 | * @type {!reflect.FunctionImport}
24 | */
25 | this.import = functionImport instanceof FunctionImport
26 | ? functionImport
27 | : assembly.getFunctionImport(functionImport);
28 |
29 | /**
30 | * Function signature.
31 | * @type {!reflect.FunctionSignature}
32 | */
33 | this.signature = signature instanceof FunctionSignature
34 | ? signature
35 | : assembly.getFunctionSignature(signature);
36 | }
37 |
38 | module.exports = FunctionImportSignature;
39 |
40 | var FunctionImport = require("./FunctionImport"); // cyclic
41 |
42 | // Extends BaseOperand
43 | FunctionImportSignature.prototype = Object.create(BaseOperand.prototype);
44 |
45 | /**
46 | * Function import signature index.
47 | * @name reflect.FunctionImportSignature#index
48 | * @type {number}
49 | */
50 | Object.defineProperty(FunctionImportSignature.prototype, "index", {
51 | get: function() {
52 | return this.assembly.functionImportSignatures.indexOf(this);
53 | }
54 | });
55 |
56 | /**
57 | * Returns a string representation of this function import signature.
58 | * @returns {string}
59 | */
60 | FunctionImportSignature.prototype.toString = function() {
61 | return "FunctionImportSignature "
62 | + " idx:" + this.index
63 | + " sig:" + this.signature.index
64 | + " imp:" + this.import.index;
65 | };
66 |
--------------------------------------------------------------------------------
/src/reflect/FunctionPointerElement.js:
--------------------------------------------------------------------------------
1 | /**
2 | * A function pointer element.
3 | * @constructor
4 | * @param {!reflect.FunctionPointerTable} table
5 | * @param {number} value
6 | * @exports reflect.FunctionPointerElement
7 | */
8 | function FunctionPointerElement(table, value) {
9 |
10 | /**
11 | * Function pointer table reference.
12 | * @type {!reflect.FunctionPointerTable}
13 | */
14 | this.table = table;
15 |
16 | /**
17 | * Value.
18 | * @type {number}
19 | */
20 | this.value = value;
21 | }
22 |
23 | module.exports = FunctionPointerElement;
24 |
25 | /**
26 | * Returns a string representation of this function pointer element.
27 | * @returns {string}
28 | */
29 | FunctionPointerElement.prototype.toString = function() {
30 | return "FunctionPointerElement"
31 | + " tbl:" + this.table.index
32 | + " val:" + this.value;
33 | };
34 |
--------------------------------------------------------------------------------
/src/reflect/FunctionPointerTable.js:
--------------------------------------------------------------------------------
1 | var util = require("../util");
2 |
3 | var FunctionSignature = require("./FunctionSignature"),
4 | FunctionPointerElement = require("./FunctionPointerElement"),
5 | BaseOperand = require("../stmt/BaseOperand");
6 |
7 | /**
8 | * A function pointer table.
9 | * @constructor
10 | * @param {!reflect.Assembly} assembly
11 | * @param {number} index
12 | * @param {number|!reflect.FunctionSignature} signature
13 | * @param {!Array.} elements
14 | * @extends stmt.BaseOperand
15 | * @exports reflect.FunctionPointerTable
16 | */
17 | function FunctionPointerTable(assembly, signature, elements) {
18 | BaseOperand.call(this);
19 |
20 | /**
21 | * Assembly reference.
22 | * @type {!reflect.Assembly}
23 | */
24 | this.assembly = assembly;
25 |
26 | /**
27 | * Signature.
28 | * @type {!reflect.FunctionSignature}
29 | */
30 | this.signature = signature instanceof FunctionSignature
31 | ? signature
32 | : assembly.getFunctionSignature(signature);
33 |
34 | /**
35 | * Elements.
36 | * @type {!Array.}
37 | */
38 | this.elements = [];
39 | elements.forEach(function(element) {
40 | this.elements.push(
41 | element instanceof FunctionPointerElement
42 | ? element // usually not the case, but for completeness
43 | : new FunctionPointerElement(this, element)
44 | );
45 | }, this);
46 | }
47 |
48 | module.exports = FunctionPointerTable;
49 |
50 | // Extends BaseOperand
51 | FunctionPointerTable.prototype = Object.create(BaseOperand.prototype);
52 |
53 | /**
54 | * Function pointer table index.
55 | * @name reflect.FunctionPointerTable#index
56 | * @type {number}
57 | */
58 | Object.defineProperty(FunctionPointerTable.prototype, "index", {
59 | get: function() {
60 | return this.assembly.functionPointerTables.indexOf(this);
61 | }
62 | });
63 |
64 | /**
65 | * Indexed name.
66 | * @name reflect.FunctionPointerTable#name
67 | * @type {string}
68 | */
69 | Object.defineProperty(FunctionPointerTable.prototype, "name", {
70 | get: function() {
71 | var func_name_base = this.assembly.functionImports.length + this.assembly.globalVariables.length;
72 | var func_ptr_name_base = func_name_base + this.assembly.functionDeclarations.length;
73 | return this.assembly.globalName(func_ptr_name_base + this.index, "fptr");
74 | }
75 | });
76 |
77 | /**
78 | * Returns a string representation of this function pointer table.
79 | * @returns {string}
80 | */
81 | FunctionPointerTable.prototype.toString = function() {
82 | return "FunctionPointerTable " + this.index.toString() + " " + this.signature.index + " " + this.elements.length;
83 | };
84 |
--------------------------------------------------------------------------------
/src/reflect/FunctionSignature.js:
--------------------------------------------------------------------------------
1 | var types = require("../types");
2 |
3 | /**
4 | * A function signature.
5 | * @constructor
6 | * @param {!reflect.Assembly} assembly
7 | * @param {number=} returnType
8 | * @param {!Array.=} argumentTypes
9 | * @exports reflect.FunctionSignature
10 | */
11 | function FunctionSignature(assembly, returnType, argumentTypes) {
12 |
13 | /**
14 | * Assembly reference.
15 | * @type {!reflect.Assembly}
16 | */
17 | this.assembly = assembly;
18 |
19 | /**
20 | * Return type.
21 | * @type {number}
22 | */
23 | this.returnType = returnType;
24 |
25 | /**
26 | * Array of argument types.
27 | * @type {!Array.}
28 | */
29 | this.argumentTypes = argumentTypes || [];
30 |
31 | /**
32 | * Index override used by {@link reflect.Assembly#optimize}.
33 | * @type {number}
34 | * @private
35 | */
36 | this._indexOverride = -1; // FIXME
37 | }
38 |
39 | module.exports = FunctionSignature;
40 |
41 | /**
42 | * Function signature index.
43 | * @name reflect.FunctionSignature#index
44 | * @type {number}
45 | */
46 | Object.defineProperty(FunctionSignature.prototype, "index", {
47 | get: function() {
48 | if (this._indexOverride >= 0)
49 | return this._indexOverride;
50 | return this.assembly.functionSignatures.indexOf(this);
51 | }
52 | });
53 |
54 | /**
55 | * Returns a string representation of this signature.
56 | * @returns {string}
57 | */
58 | FunctionSignature.prototype.toString = function() {
59 | var sb = [];
60 | sb.push("FunctionSignature idx:", this.index.toString(), " ", types.RTypeNames[this.returnType], "(");
61 | for (var i=0; i0)
63 | sb.push(",");
64 | sb.push(types.TypeNames[this.argumentTypes[i]]);
65 | }
66 | sb.push(")");
67 | return sb.join("");
68 | };
69 |
--------------------------------------------------------------------------------
/src/reflect/GlobalVariable.js:
--------------------------------------------------------------------------------
1 | var types = require("../types"),
2 | util = require("../util");
3 |
4 | var BaseOperand = require("../stmt/BaseOperand");
5 |
6 | /**
7 | * A global variable.
8 | * @constructor
9 | * @param {!reflect.Assembly} assembly
10 | * @param {number} type
11 | * @param {string=} importName
12 | * @extends stmt.BaseOperand
13 | * @exports reflect.GlobalVariable
14 | */
15 | function GlobalVariable(assembly, type, importName) {
16 | BaseOperand.call(this);
17 |
18 | /**
19 | * Assembly reference.
20 | * @type {!reflect.Assembly}
21 | */
22 | this.assembly = assembly;
23 |
24 | /**
25 | * Variable type.
26 | * @type {number}
27 | */
28 | this.type = type;
29 |
30 | /**
31 | * Import name if not zero.
32 | * @type {?string}
33 | */
34 | this.importName = importName || null;
35 | }
36 |
37 | module.exports = GlobalVariable;
38 |
39 | // Extends BaseOperand
40 | GlobalVariable.prototype = Object.create(BaseOperand.prototype);
41 |
42 | /**
43 | * Global variable index.
44 | * @name reflect.GlobalVariable#index
45 | * @type {number}
46 | */
47 | Object.defineProperty(GlobalVariable.prototype, "index", {
48 | get: function() {
49 | return this.assembly.globalVariables.indexOf(this);
50 | }
51 | });
52 |
53 | /**
54 | * Indexed name.
55 | * @name reflect.GlobalVariable#name
56 | * @type {string}
57 | */
58 | Object.defineProperty(GlobalVariable.prototype, "name", {
59 | get: function() {
60 | var num_func_imps = this.assembly.functionImports.length;
61 | return this.assembly.globalName(num_func_imps + this.index);
62 | }
63 | });
64 |
65 | /**
66 | * Returns a string representation of this global variable.
67 | * @returns {string}
68 | */
69 | GlobalVariable.prototype.toString = function() {
70 | return "GlobalVariable " + this.name
71 | + " idx:" + this.index
72 | + " type:" + types.TypeNames[this.type]
73 | + " val:" + (this.importName === null ? "0" : "foreign."+this.importName);
74 | };
75 |
--------------------------------------------------------------------------------
/src/reflect/LocalVariable.js:
--------------------------------------------------------------------------------
1 | var types = require("../types"),
2 | util = require("../util");
3 |
4 | var BaseOperand = require("../stmt/BaseOperand");
5 |
6 | /**
7 | * A local variable.
8 | * @constructor
9 | * @param {number|!reflect.FunctionDefinition} functionDefinition
10 | * @param {number} type
11 | * @extends stmt.BaseOperand
12 | * @exports reflect.LocalVariable
13 | */
14 | function LocalVariable(functionDefinition, type) {
15 | BaseOperand.call(this);
16 |
17 | /**
18 | * Function definition reference.
19 | * @type {!reflect.FunctionDefinition}
20 | */
21 | this.functionDefinition = functionDefinition instanceof FunctionDefinition
22 | ? functionDefinition
23 | : this.assembly.getFunctionDefinition(functionDefinition);
24 |
25 | /**
26 | * Variable type.
27 | * @type {number}
28 | */
29 | this.type = type;
30 | }
31 |
32 | module.exports = LocalVariable;
33 |
34 | var FunctionDefinition = require("./FunctionDefinition"); // cyclic
35 |
36 | // Extends BaseOperand
37 | LocalVariable.prototype = Object.create(BaseOperand.prototype);
38 |
39 | /**
40 | * Local variable index.
41 | * @name reflect.LocalVariable#index
42 | * @type {number}
43 | */
44 | Object.defineProperty(LocalVariable.prototype, "index", {
45 | get: function() {
46 | return this.functionDefinition.variables.indexOf(this);
47 | }
48 | });
49 |
50 | /**
51 | * Whether this local variable is a function argument or not.
52 | * @name reflect.LocalVariable#isArgument
53 | * @type {boolean}
54 | */
55 | Object.defineProperty(LocalVariable.prototype, "isArgument", {
56 | get: function() {
57 | return this.index < this.functionDefinition.declaration.signature.argumentTypes.length;
58 | }
59 | });
60 |
61 | /**
62 | * Indexed name.
63 | * @name reflect.LocalVariable#name
64 | * @type {string}
65 | */
66 | Object.defineProperty(LocalVariable.prototype, "name", {
67 | get: function() {
68 | return this.functionDefinition.declaration.assembly.localName(this.index);
69 | }
70 | });
71 |
72 | /**
73 | * Returns a string representation of this local variable.
74 | * @returns {string}
75 | */
76 | LocalVariable.prototype.toString = function() {
77 | return "LocalVariable " + this.name
78 | + " idx:" +this.index
79 | + " type:" + types.TypeNames[this.type];
80 | };
81 |
--------------------------------------------------------------------------------
/src/reflect/RecordExport.js:
--------------------------------------------------------------------------------
1 | var BaseExport = require("./BaseExport"),
2 | FunctionDeclaration = require("./FunctionDeclaration");
3 |
4 | /**
5 | * A record export.
6 | * @constructor
7 | * @param {!reflect.Assembly} assembly
8 | * @param {!Object.=} functions
9 | * @extends reflect.BaseExport
10 | * @exports reflect.RecordExport
11 | */
12 | function RecordExport(assembly, functions) {
13 | BaseExport.call(this, assembly);
14 |
15 | /**
16 | * Internal function indexes by exported name.
17 | * @type {!Object.}
18 | */
19 | this.functions = {};
20 | Object.keys(functions).forEach(function(name) {
21 | this.functions[name] = functions[name] instanceof FunctionDeclaration
22 | ? functions[name]
23 | : assembly.getFunctionDeclaration(functions[name]);
24 | }, this);
25 | }
26 |
27 | module.exports = RecordExport;
28 |
29 | // Extends BaseExport
30 | RecordExport.prototype = Object.create(BaseExport.prototype);
31 |
32 | /**
33 | * Returns a string representation of this export.
34 | * @returns {string}
35 | */
36 | RecordExport.prototype.toString = function() {
37 | var sb = [];
38 | sb.push("RecordExport");
39 | var names = Object.keys(this.functions);
40 | for (var i=0; i|number|!stmt.BaseOperand} operands
8 | * @abstract
9 | * @extends stmt.BaseStmt
10 | * @exports stmt.BaseExpr
11 | */
12 | function BaseExpr(code, operands) {
13 | BaseStmt.call(this, code, operands);
14 | }
15 |
16 | module.exports = BaseExpr;
17 |
18 | BaseExpr.prototype = Object.create(BaseStmt.prototype);
19 |
--------------------------------------------------------------------------------
/src/stmt/BaseOperand.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Base class of all operands but plain numbers.
3 | * @constructor
4 | * @exports stmt.BaseOperand
5 | */
6 | function BaseOperand() {
7 | }
8 |
9 | module.exports = BaseOperand;
10 |
--------------------------------------------------------------------------------
/src/stmt/BaseStmt.js:
--------------------------------------------------------------------------------
1 | var types = require("../types");
2 |
3 | var BaseOperand = require("./BaseOperand");
4 |
5 | /**
6 | * Abstract base class of all statements.
7 | * @constructor
8 | * @param {number} code
9 | * @param {!Array.|number|!stmt.BaseOperand} operands
10 | * @abstract
11 | * @extends stmt.BaseOperand
12 | * @exports stmt.BaseStmt
13 | */
14 | function BaseStmt(code, operands) {
15 | BaseOperand.call(this);
16 |
17 | /**
18 | * Parent statement or list.
19 | * @type {!stmt.BaseStmt|!stmt.StmtList|null}
20 | */
21 | this.parent = null;
22 |
23 | /**
24 | * Opcode.
25 | * @type {number}
26 | */
27 | this.code = code;
28 |
29 | /**
30 | * Operands.
31 | * @type {!Array.}
32 | */
33 | this.operands = Array.isArray(operands)
34 | ? operands.slice()
35 | : typeof operands !== 'undefined'
36 | ? [operands]
37 | : [];
38 |
39 | /**
40 | * Whether this statement's opcode was originally packed with an imm.
41 | * @type {boolean}
42 | * @see {@link ast.Writer#preserveWithImm}
43 | */
44 | this.withImm = false;
45 | }
46 |
47 | module.exports = BaseStmt;
48 |
49 | /* var ExprI32 = require("./ExprI32"),
50 | ExprF32 = require("./ExprF32"),
51 | ExprF64 = require("./ExprF64"),
52 | ExprVoid = require("./ExprVoid"),
53 | SwitchCase = require("./SwitchCase"),
54 | Stmt = require("./Stmt"); */
55 |
56 | // Extends BaseOperand
57 | BaseStmt.prototype = Object.create(BaseOperand.prototype);
58 |
59 | /**
60 | * Wire type.
61 | * @name stmt.BaseExpr#type
62 | * @type {number}
63 | * @see {@link types.WireType}
64 | */
65 |
66 | /**
67 | * Opcode with imm, if any.
68 | * @name stmt.BaseStmt#codeWithImm
69 | * @type {number} -1 if there is no counterpart
70 | */
71 |
72 | /**
73 | * Behavior.
74 | * @name stmt.BaseStmt#behavior
75 | * @type {!stmt.behavior.BaseBehavior}
76 | */
77 |
78 | /**
79 | * Gets the literal opcode name.
80 | * @name stmt.BaseStmt#name
81 | * @type {string}
82 | */
83 | Object.defineProperty(BaseStmt.prototype, "name", {
84 | get: function() {
85 | switch (this.type) {
86 | case types.WireType.Stmt:
87 | return "Stmt:"+types.StmtNames[this.code];
88 | case types.WireType.ExprI32:
89 | return "I32:"+types.I32Names[this.code];
90 | case types.WireType.ExprF32:
91 | return "F32:"+types.F32Names[this.code];
92 | case types.WireType.ExprF64:
93 | return "F64:"+types.F64Names[this.code];
94 | case types.WireType.ExprVoid:
95 | return "Void:"+types.VoidNames[this.code];
96 | case types.WireType.SwitchCase:
97 | return "SwitchCase:"+types.SwitchCaseNames[this.code];
98 | default:
99 | throw Error("illegal statement type: "+this.type);
100 | }
101 | }
102 | });
103 |
104 | /**
105 | * Adds another operand.
106 | * @param {number|!stmt.BaseOperand} operand
107 | */
108 | BaseStmt.prototype.add = function(operand) {
109 | if (operand instanceof BaseStmt)
110 | operand.parent = this;
111 | this.operands.push(operand);
112 | };
113 |
114 | /**
115 | * Returns a string representation of this statement.
116 | * @param {boolean=} shortFormat
117 | * @returns {string}
118 | */
119 | BaseStmt.prototype.toString = function(shortFormat) {
120 | var sb = [];
121 | sb.push(this.name);
122 | if (shortFormat)
123 | sb.push("+", this.operands.length.toString());
124 | else
125 | for (var i= 0, operand; i|number|!stmt.BaseOperand)=} operands
10 | * @constructor
11 | * @extends stmt.BaseExpr
12 | * @exports stmt.ExprF32
13 | */
14 | function ExprF32(code, operands) {
15 | BaseExpr.call(this, code, operands);
16 | }
17 |
18 | module.exports = ExprF32;
19 |
20 | ExprF32.prototype = Object.create(BaseExpr.prototype);
21 |
22 | Object.defineProperty(ExprF32.prototype, "type", {
23 | get: function() {
24 | return types.WireType.ExprF32;
25 | }
26 | });
27 |
28 | Object.defineProperty(ExprF32.prototype, "codeWithImm", {
29 | get: function() {
30 | return types.codeWithImm(types.RType.F32, this.code);
31 | }
32 | });
33 |
34 | ExprF32.determineBehavior = function(code, withImm) {
35 | var Op;
36 | if (!withImm) {
37 | Op = types.F32;
38 | switch (code) {
39 | case Op.LitImm:
40 | return behavior.LiteralF32;
41 | case Op.LitPool:
42 | return behavior.ConstantF32;
43 | case Op.GetLoc:
44 | return behavior.GetLocalF32;
45 | case Op.GetGlo:
46 | return behavior.GetGlobalF32;
47 | case Op.SetLoc:
48 | return behavior.SetLocalF32;
49 | case Op.SetGlo:
50 | return behavior.SetGlobalF32;
51 | case Op.Load:
52 | return behavior.LoadF32;
53 | case Op.LoadOff:
54 | return behavior.LoadWithOffsetF32;
55 | case Op.Store:
56 | return behavior.StoreF32;
57 | case Op.StoreOff:
58 | return behavior.StoreWithOffsetF32;
59 | case Op.CallInt:
60 | return behavior.CallInternalF32;
61 | case Op.CallInd:
62 | return behavior.CallIndirectF32;
63 | case Op.Cond:
64 | return behavior.ConditionalF32;
65 | case Op.Comma:
66 | return behavior.CommaF32;
67 | case Op.FromS32:
68 | case Op.FromU32:
69 | return behavior.UnaryI32;
70 | case Op.FromF64:
71 | return behavior.UnaryF64;
72 | case Op.Neg:
73 | case Op.Abs:
74 | case Op.Ceil:
75 | case Op.Floor:
76 | case Op.Sqrt:
77 | return behavior.UnaryF32;
78 | case Op.Add:
79 | case Op.Sub:
80 | case Op.Mul:
81 | case Op.Div:
82 | return behavior.BinaryF32;
83 | default:
84 | throw Error("illegal F32 opcode: " + code);
85 | }
86 | } else {
87 | Op = types.F32WithImm;
88 | switch (code) {
89 | case Op.LitPool:
90 | return behavior.ConstantF32;
91 | case Op.GetLoc:
92 | return behavior.GetLocalF32;
93 | default:
94 | throw Error("illegal F32WithImm opcode: " + code);
95 | }
96 | }
97 | };
98 |
99 | Object.defineProperty(ExprF32.prototype, "behavior", {
100 | get: function() {
101 | return ExprF32.determineBehavior(this.code);
102 | }
103 | });
104 |
--------------------------------------------------------------------------------
/src/stmt/ExprF64.js:
--------------------------------------------------------------------------------
1 | var types = require("../types"),
2 | BaseExpr = require("./BaseExpr"),
3 | behavior = require("./behavior");
4 |
5 | /**
6 | * A F64 expression.
7 | * @constructor
8 | * @param {number} code
9 | * @param {(!Array.|number|!stmt.BaseOperand)=} operands
10 | * @constructor
11 | * @extends stmt.BaseExpr
12 | * @exports stmt.ExprF64
13 | */
14 | function ExprF64(code, operands) {
15 | BaseExpr.call(this, code, operands);
16 | }
17 |
18 | module.exports = ExprF64;
19 |
20 | ExprF64.prototype = Object.create(BaseExpr.prototype);
21 |
22 | Object.defineProperty(ExprF64.prototype, "type", {
23 | get: function() {
24 | return types.WireType.ExprF64;
25 | }
26 | });
27 |
28 | Object.defineProperty(ExprF64.prototype, "codeWithImm", {
29 | get: function() {
30 | return types.codeWithImm(types.RType.F64, this.code);
31 | }
32 | });
33 |
34 | ExprF64.determineBehavior = function(code, withImm) {
35 | var Op;
36 | if (!withImm) {
37 | Op = types.F64;
38 | switch (code) {
39 | case Op.LitImm:
40 | return behavior.LiteralF64;
41 | case Op.LitPool:
42 | return behavior.ConstantF64;
43 | case Op.GetLoc:
44 | return behavior.GetLocalF64;
45 | case Op.GetGlo:
46 | return behavior.GetGlobalF64;
47 | case Op.SetLoc:
48 | return behavior.SetLocalF64;
49 | case Op.SetGlo:
50 | return behavior.SetGlobalF64;
51 | case Op.Load:
52 | return behavior.LoadF64;
53 | case Op.LoadOff:
54 | return behavior.LoadWithOffsetF64;
55 | case Op.Store:
56 | return behavior.StoreF64;
57 | case Op.StoreOff:
58 | return behavior.StoreWithOffsetF64;
59 | case Op.CallInt:
60 | return behavior.CallInternalF64;
61 | case Op.CallImp:
62 | return behavior.CallImportF64;
63 | case Op.CallInd:
64 | return behavior.CallIndirectF64;
65 | case Op.Cond:
66 | return behavior.ConditionalF64;
67 | case Op.Comma:
68 | return behavior.CommaF64;
69 | case Op.FromS32:
70 | case Op.FromU32:
71 | return behavior.UnaryI32;
72 | case Op.FromF32:
73 | return behavior.UnaryF32;
74 | case Op.Neg:
75 | case Op.Abs:
76 | case Op.Ceil:
77 | case Op.Floor:
78 | case Op.Sqrt:
79 | case Op.Cos:
80 | case Op.Sin:
81 | case Op.Tan:
82 | case Op.ACos:
83 | case Op.ASin:
84 | case Op.ATan:
85 | case Op.Exp:
86 | case Op.Ln:
87 | return behavior.UnaryF64;
88 | case Op.Add:
89 | case Op.Sub:
90 | case Op.Mul:
91 | case Op.Div:
92 | case Op.Mod:
93 | case Op.ATan2:
94 | case Op.Pow:
95 | return behavior.BinaryF64;
96 | case Op.Min:
97 | case Op.Max:
98 | return behavior.MultiaryF64;
99 | default:
100 | throw Error("illegal F64 opcode: " + code);
101 | }
102 | } else {
103 | Op = types.F64WithImm;
104 | switch (code) {
105 | case Op.LitPool:
106 | return behavior.ConstantF64;
107 | case Op.GetLoc:
108 | return behavior.GetLocalF64;
109 | default:
110 | throw Error("illegal F64WithImm opcode: " + code);
111 | }
112 | }
113 | };
114 |
115 | Object.defineProperty(ExprF64.prototype, "behavior", {
116 | get: function() {
117 | return ExprF64.determineBehavior(this.code);
118 | }
119 | });
120 |
--------------------------------------------------------------------------------
/src/stmt/ExprI32.js:
--------------------------------------------------------------------------------
1 | var types = require("../types"),
2 | BaseExpr = require("./BaseExpr"),
3 | behavior = require("./behavior");
4 |
5 | /**
6 | * An I32 expression.
7 | * @constructor
8 | * @param {number} code
9 | * @param {(!Array.|number|!stmt.BaseOperand)=} operands
10 | * @constructor
11 | * @extends stmt.BaseExpr
12 | * @exports stmt.ExprI32
13 | */
14 | function ExprI32(code, operands) {
15 | BaseExpr.call(this, code, operands);
16 | }
17 |
18 | module.exports = ExprI32;
19 |
20 | ExprI32.prototype = Object.create(BaseExpr.prototype);
21 |
22 | Object.defineProperty(ExprI32.prototype, "type", {
23 | get: function() {
24 | return types.WireType.ExprI32;
25 | }
26 | });
27 |
28 | Object.defineProperty(ExprI32.prototype, "codeWithImm", {
29 | get: function() {
30 | return types.codeWithImm(types.RType.I32, this.code);
31 | }
32 | });
33 |
34 | ExprI32.determineBehavior = function(code, withImm) {
35 | var Op;
36 | if (!withImm) {
37 | Op = types.I32;
38 | switch (code) {
39 | case Op.LitImm:
40 | return behavior.LiteralI32;
41 | case Op.LitPool:
42 | return behavior.ConstantI32;
43 | case Op.GetLoc:
44 | return behavior.GetLocalI32;
45 | case Op.GetGlo:
46 | return behavior.GetGlobalI32;
47 | case Op.SetLoc:
48 | return behavior.SetLocalI32;
49 | case Op.SetGlo:
50 | return behavior.SetGlobalI32;
51 | case Op.SLoad8:
52 | case Op.ULoad8:
53 | case Op.SLoad16:
54 | case Op.ULoad16:
55 | case Op.Load32:
56 | return behavior.LoadI;
57 | case Op.SLoadOff8:
58 | case Op.ULoadOff8:
59 | case Op.SLoadOff16:
60 | case Op.ULoadOff16:
61 | case Op.LoadOff32:
62 | return behavior.LoadWithOffsetI;
63 | case Op.Store8:
64 | case Op.Store16:
65 | case Op.Store32:
66 | return behavior.StoreI;
67 | case Op.StoreOff8:
68 | case Op.StoreOff16:
69 | case Op.StoreOff32:
70 | return behavior.StoreWithOffsetI;
71 | case Op.CallInt:
72 | return behavior.CallInternalI32;
73 | case Op.CallImp:
74 | return behavior.CallImportI32;
75 | case Op.CallInd:
76 | return behavior.CallIndirectI32;
77 | case Op.Cond:
78 | return behavior.ConditionalI32;
79 | case Op.Comma:
80 | return behavior.CommaI32;
81 | case Op.FromF32:
82 | return behavior.UnaryF32;
83 | case Op.FromF64:
84 | return behavior.UnaryF64;
85 | case Op.Neg:
86 | case Op.BitNot:
87 | case Op.Clz:
88 | case Op.LogicNot:
89 | case Op.Abs:
90 | return behavior.UnaryI32;
91 | case Op.Add:
92 | case Op.Sub:
93 | case Op.Mul:
94 | case Op.SDiv:
95 | case Op.UDiv:
96 | case Op.SMod:
97 | case Op.UMod:
98 | case Op.BitOr:
99 | case Op.BitAnd:
100 | case Op.BitXor:
101 | case Op.Lsh:
102 | case Op.ArithRsh:
103 | case Op.LogicRsh:
104 | case Op.EqI32:
105 | case Op.NEqI32:
106 | case Op.SLeThI32:
107 | case Op.ULeThI32:
108 | case Op.SLeEqI32:
109 | case Op.ULeEqI32:
110 | case Op.SGrThI32:
111 | case Op.UGrThI32:
112 | case Op.SGrEqI32:
113 | case Op.UGrEqI32:
114 | return behavior.BinaryI32;
115 | case Op.EqF32:
116 | case Op.NEqF32:
117 | case Op.LeThF32:
118 | case Op.LeEqF32:
119 | case Op.GrThF32:
120 | case Op.GrEqF32:
121 | return behavior.BinaryF32;
122 | case Op.EqF64:
123 | case Op.NEqF64:
124 | case Op.LeThF64:
125 | case Op.LeEqF64:
126 | case Op.GrThF64:
127 | case Op.GrEqF64:
128 | return behavior.BinaryF64;
129 | case Op.SMin:
130 | case Op.UMin:
131 | case Op.SMax:
132 | case Op.UMax:
133 | return behavior.MultiaryI32;
134 | default:
135 | throw Error("illegal I32 opcode: " + code);
136 | }
137 | } else {
138 | Op = types.I32WithImm;
139 | switch (code) {
140 | case Op.LitPool:
141 | return behavior.ConstantI32;
142 | case Op.LitImm:
143 | return behavior.LiteralI32;
144 | case Op.GetLoc:
145 | return behavior.GetLocalI32;
146 | default:
147 | throw Error("illegal I32WithImm opcode: " + code);
148 | }
149 | }
150 | };
151 |
152 | Object.defineProperty(ExprI32.prototype, "behavior", {
153 | get: function() {
154 | return ExprI32.determineBehavior(this.code);
155 | }
156 | });
157 |
--------------------------------------------------------------------------------
/src/stmt/ExprVoid.js:
--------------------------------------------------------------------------------
1 | var types = require("../types"),
2 | BaseExpr = require("./BaseExpr"),
3 | behavior = require("./behavior");
4 |
5 | /**
6 | * A void expression.
7 | * @constructor
8 | * @param {number} code
9 | * @param {(!Array.|number|!stmt.BaseOperand)=} operands
10 | * @constructor
11 | * @extends stmt.BaseExpr
12 | * @exports stmt.ExprVoid
13 | */
14 | function ExprVoid(code, operands) {
15 | BaseExpr.call(this, code, operands);
16 | }
17 |
18 | module.exports = ExprVoid;
19 |
20 | ExprVoid.prototype = Object.create(BaseExpr.prototype);
21 |
22 | Object.defineProperty(ExprVoid.prototype, "type", {
23 | get: function() {
24 | return types.WireType.ExprVoid;
25 | }
26 | });
27 |
28 | Object.defineProperty(ExprVoid.prototype, "codeWithImm", {
29 | get: function() {
30 | return -1;
31 | }
32 | });
33 |
34 | ExprVoid.determineBehavior = function(code, withImm) {
35 | var Op;
36 | if (!withImm) {
37 | Op = types.Void;
38 | switch (code) {
39 | case Op.CallInt:
40 | return behavior.CallInternalVoid;
41 | case Op.CallImp:
42 | return behavior.CallImportVoid;
43 | case Op.CallInd:
44 | return behavior.CallIndirectVoid;
45 | default:
46 | throw Error("illegal Void opcode: " + code);
47 | }
48 | } else
49 | throw Error("illegal VoidWithImm opcode: " + code);
50 | };
51 |
52 | Object.defineProperty(ExprVoid.prototype, "behavior", {
53 | get: function() {
54 | return ExprVoid.determineBehavior(this.code);
55 | }
56 | });
57 |
--------------------------------------------------------------------------------
/src/stmt/Stmt.js:
--------------------------------------------------------------------------------
1 | var types = require("../types"),
2 | BaseStmt = require("./BaseStmt"),
3 | behavior = require("./behavior");
4 |
5 | /**
6 | * A statement.
7 | * @constructor
8 | * @param {number} code
9 | * @param {(number|!BaseStmt|!Array)=} operands
10 | * @constructor
11 | * @extends stmt.BaseStmt
12 | * @exports stmt.Stmt
13 | */
14 | function Stmt(code, operands) {
15 | BaseStmt.call(this, code, operands);
16 | }
17 |
18 | module.exports = Stmt;
19 |
20 | Stmt.prototype = Object.create(BaseStmt.prototype);
21 |
22 | Object.defineProperty(Stmt.prototype, "type", {
23 | get: function() {
24 | return types.WireType.Stmt;
25 | }
26 | });
27 |
28 | Object.defineProperty(Stmt.prototype, "codeWithImm", {
29 | get: function() {
30 | switch (this.code) {
31 | case types.Stmt.SetLoc:
32 | return types.StmtWithImm.SetLoc;
33 | case types.Stmt.SetGlo:
34 | return types.StmtWithImm.SetGlo;
35 | default:
36 | return -1;
37 | }
38 | }
39 | });
40 |
41 | Stmt.determineBehavior = function(code, withImm) {
42 | var Op;
43 | if (!withImm) {
44 | Op = types.Stmt;
45 | switch (code) {
46 | case Op.SetLoc:
47 | return behavior.SetLocal;
48 | case Op.SetGlo:
49 | return behavior.SetGlobal;
50 | case Op.I32Store8:
51 | case Op.I32Store16:
52 | case Op.I32Store32:
53 | return behavior.StoreI;
54 | case Op.I32StoreOff8:
55 | case Op.I32StoreOff16:
56 | case Op.I32StoreOff32:
57 | return behavior.StoreWithOffsetI;
58 | case Op.F32Store:
59 | return behavior.StoreF32;
60 | case Op.F32StoreOff:
61 | return behavior.StoreWithOffsetF32;
62 | case Op.F64Store:
63 | return behavior.StoreF64;
64 | case Op.F64StoreOff:
65 | return behavior.StoreWithOffsetF64;
66 | case Op.CallInt:
67 | return behavior.CallInternal;
68 | case Op.CallImp:
69 | return behavior.CallImport;
70 | case Op.CallInd:
71 | return behavior.CallIndirect;
72 | case Op.Ret:
73 | return behavior.Return;
74 | case Op.Block:
75 | return behavior.Block;
76 | case Op.IfThen:
77 | return behavior.IfThen;
78 | case Op.IfElse:
79 | return behavior.IfElse;
80 | case Op.While:
81 | return behavior.While;
82 | case Op.Do:
83 | return behavior.Do;
84 | case Op.Label:
85 | return behavior.Label;
86 | case Op.Break:
87 | return behavior.Break;
88 | case Op.Continue:
89 | return behavior.Continue;
90 | case Op.BreakLabel:
91 | return behavior.BreakLabel;
92 | case Op.ContinueLabel:
93 | return behavior.ContinueLabel;
94 | case Op.Switch:
95 | return behavior.Switch;
96 | default:
97 | throw Error("illegal Stmt opcode: " + code);
98 | }
99 | } else {
100 | Op = types.StmtWithImm;
101 | switch (code) {
102 | case Op.SetLoc:
103 | return behavior.SetLocal;
104 | case Op.SetGlo:
105 | return behavior.SetGlobal;
106 | default:
107 | throw Error("illegal StmtWithImm opcode: " + code);
108 |
109 | }
110 | }
111 | };
112 |
113 | Object.defineProperty(Stmt.prototype, "behavior", {
114 | get: function() {
115 | return Stmt.determineBehavior(this.code, false);
116 | }
117 | });
118 |
--------------------------------------------------------------------------------
/src/stmt/StmtList.js:
--------------------------------------------------------------------------------
1 | var types = require("../types");
2 |
3 | /**
4 | * A list of statements.
5 | * @constructor
6 | * @param {number} size
7 | * @extends Array
8 | * @exports stmt.StmtList
9 | */
10 | function StmtList(size) {
11 | Array.call(this, size);
12 | if (typeof size !== 'undefined')
13 | this.length = size;
14 |
15 | /**
16 | * Assembly offset.
17 | * @type {number}
18 | */
19 | this.offset = 0;
20 | }
21 |
22 | module.exports = StmtList;
23 |
24 | // Extends Array
25 | StmtList.prototype = Object.create(Array.prototype);
26 |
27 | /**
28 | * Wire type.
29 | * @name stmt.StmtList#type
30 | * @type {number}
31 | */
32 | Object.defineProperty(StmtList.prototype, "type", {
33 | get: function() {
34 | return types.WireType.StmtList;
35 | }
36 | });
37 |
38 | /**
39 | * Adds a statement to the list.
40 | * @param {!stmt.BaseStmt} stmt
41 | */
42 | StmtList.prototype.add = function(stmt) {
43 | if (this.offset >= this.length)
44 | throw Error("statement list overflow");
45 | stmt.parent = this;
46 | this[this.offset++] = stmt;
47 | };
48 |
49 | /**
50 | * Returns a string representation of this statement list.
51 | * @returns {string}
52 | */
53 | StmtList.prototype.toString = function() {
54 | return "StmtList["+this.length+"]";
55 | };
56 |
--------------------------------------------------------------------------------
/src/stmt/SwitchCase.js:
--------------------------------------------------------------------------------
1 | var types = require("../types");
2 |
3 | var BaseStmt = require("./BaseStmt"),
4 | behavior = require("./behavior");
5 |
6 | /**
7 | * A switch case statement.
8 | * @param {number} code
9 | * @param {(!BaseStmt|!Array)=} operands
10 | * @constructor
11 | * @extends stmt.BaseStmt
12 | * @exports stmt.SwitchCase
13 | */
14 | function SwitchCase(code, operands) {
15 | BaseStmt.call(this, code, operands);
16 | }
17 |
18 | module.exports = SwitchCase;
19 |
20 | // Extends BaseStmt
21 | SwitchCase.prototype = Object.create(BaseStmt.prototype);
22 |
23 | Object.defineProperty(SwitchCase.prototype, "type", {
24 | get: function() {
25 | return types.WireType.SwitchCase;
26 | }
27 | });
28 |
29 | Object.defineProperty(SwitchCase.prototype, "codeWithImm", {
30 | get: function() {
31 | return -1;
32 | }
33 | });
34 |
35 | SwitchCase.determineBehavior = function(code, withImm) {
36 | var Op;
37 | if (!withImm) {
38 | Op = types.SwitchCase;
39 | switch (code) {
40 | case Op.Case0:
41 | return behavior.SwitchCase0;
42 | case Op.Case1:
43 | return behavior.SwitchCase1;
44 | case Op.CaseN:
45 | return behavior.SwitchCaseN;
46 | case Op.Default0:
47 | return behavior.SwitchDefault0;
48 | case Op.Default1:
49 | return behavior.SwitchDefault1;
50 | case Op.DefaultN:
51 | return behavior.SwitchDefaultN;
52 | default:
53 | throw Error("illegal SwitchCase opcode: " + code);
54 | }
55 | } else
56 | throw Error("illegal SwitchCaseWithImm opcode: " + code);
57 | };
58 |
59 | Object.defineProperty(SwitchCase.prototype, "behavior", {
60 | get: function() {
61 | return SwitchCase.determineBehavior(this.code);
62 | }
63 | });
64 |
--------------------------------------------------------------------------------
/src/stmt/behavior/BaseBehavior.js:
--------------------------------------------------------------------------------
1 | var types = require("../../types");
2 |
3 | /**
4 | * Abstract base class of all behaviors.
5 | * @constructor
6 | * @param {string} name
7 | * @param {string} description
8 | * @abstract
9 | * @exports stmt.behavior.BaseBehavior
10 | */
11 | function BaseBehavior(name, description) {
12 |
13 | /**
14 | * Textual name.
15 | * @type {string}
16 | */
17 | this.name = name;
18 |
19 | /**
20 | * Textual description.
21 | * @type {string}
22 | */
23 | this.description = description;
24 | }
25 |
26 | module.exports = BaseBehavior;
27 |
28 | /**
29 | * A function capable of reading a statement with this behaviour.
30 | * @param {!ast.ReadState} s
31 | * @param {number} code
32 | * @param {number|null} imm
33 | */
34 | BaseBehavior.prototype.read = function(s, code, imm) {
35 | throw Error("not implemented");
36 | };
37 |
38 | /**
39 | * A function capable of validating a statement with this behavior.
40 | * @param {!reflect.FunctionDefinition} definition
41 | * @param {!stmt.BaseStmt} stmt
42 | */
43 | BaseBehavior.prototype.validate = function(definition, stmt) {
44 | throw Error("not implemented");
45 | };
46 |
47 | /**
48 | * A function capable of writing a statement with this behavior.
49 | * @param {!ast.WriteState} s
50 | * @param {!stmt.BaseStmt} stmt
51 | */
52 | BaseBehavior.prototype.write = function(s, stmt) {
53 | throw Error("not implemented");
54 | };
55 |
56 | /**
57 | * An optional function capable of optimizing a statement with this behavior.
58 | * @type {function(!reflect.FunctionDefinition, !stmt.BaseStmt)|undefined}
59 | */
60 | BaseBehavior.prototype.optimize;
61 |
--------------------------------------------------------------------------------
/src/stmt/behavior/BinaryBehavior.js:
--------------------------------------------------------------------------------
1 | var assert = require("assert"),
2 | types = require("../../types");
3 |
4 | var BaseBehavior = require("./BaseBehavior"),
5 | BaseExpr = require("../BaseExpr");
6 |
7 | /**
8 | * Binary behavior.
9 | * @param {string} name
10 | * @param {string} description
11 | * @param {number} type
12 | * @constructor
13 | * @extends stmt.behavior.BaseBehavior
14 | * @exports stmt.behavior.BinaryBehavior
15 | */
16 | function BinaryBehavior(name, description, type) {
17 | BaseBehavior.call(this, name, description);
18 |
19 | /**
20 | * Wire type.
21 | * @type {number}
22 | */
23 | this.type = type;
24 | }
25 |
26 | module.exports = BinaryBehavior;
27 |
28 | BinaryBehavior.prototype = Object.create(BaseBehavior.prototype);
29 |
30 | // opcode + Expr<*> left + Expr<*> right
31 | // Expr<*>, all without imm
32 |
33 | BinaryBehavior.prototype.read = function(s, code) {
34 | s.stmt(code);
35 | s.read(this.type);
36 | s.read(this.type);
37 | };
38 |
39 | BinaryBehavior.prototype.validate = function(definition, stmt) {
40 | assert.strictEqual(stmt.operands.length, 2, this.name+" requires exactly 2 operands");
41 | for (var i=0; i<2; ++i){
42 | assert(stmt.operands[i] instanceof BaseExpr, this.name+" operand "+i+ " must be an expression");
43 | assert.strictEqual(stmt.operands[i].type, this.type, this.name+" operand "+i+" expression must be "+types.RTypeNames[this.type]);
44 | }
45 | };
46 |
47 | BinaryBehavior.prototype.write = function(s, stmt) {
48 | s.code(stmt.code);
49 | s.write(stmt.operands[0]);
50 | s.write(stmt.operands[1]);
51 | };
52 |
--------------------------------------------------------------------------------
/src/stmt/behavior/BlockBehavior.js:
--------------------------------------------------------------------------------
1 | var assert = require("assert"),
2 | types = require("../../types");
3 |
4 | var BaseBehavior = require("./BaseBehavior"),
5 | Stmt = require("../Stmt");
6 |
7 | /**
8 | * Block behavior.
9 | * @param {string} name
10 | * @param {string} description
11 | * @constructor
12 | * @extends stmt.behavior.BaseBehavior
13 | * @exports stmt.behavior.BlockBehavior
14 | */
15 | function BlockBehavior(name, description) {
16 | BaseBehavior.call(this, name, description);
17 | }
18 |
19 | module.exports = BlockBehavior;
20 |
21 | // Extends Behavior
22 | BlockBehavior.prototype = Object.create(BaseBehavior.prototype);
23 |
24 | // opcode + varint count + count * Stmt
25 | // Stmt only, without imm
26 |
27 | BlockBehavior.prototype.read = function(s, code) {
28 | var count = s.varint();
29 | s.stmt(code);
30 | for (var i=0; i} types
13 | * @constructor
14 | * @extends stmt.behavior.BaseBehavior
15 | * @exports stmt.behavior.BranchBehavior
16 | */
17 | function BranchBehavior(name, description, types) {
18 | BaseBehavior.call(this, name, description);
19 |
20 | /**
21 | * Wire types.
22 | * @type {!Array.}
23 | */
24 | this.types = types;
25 | }
26 |
27 | module.exports = BranchBehavior;
28 |
29 | BranchBehavior.prototype = Object.create(BaseBehavior.prototype);
30 |
31 | // opcode + Expr value [...]
32 | // Expr<*>, all without imm
33 |
34 | BranchBehavior.prototype.read = function(s, code) {
35 | s.stmt(code);
36 | this.types.forEach(function(type) {
37 | s.read(type);
38 | }, this);
39 | };
40 |
41 | BranchBehavior.prototype.validate = function(definition, stmt) {
42 | assert.strictEqual(stmt.operands.length, this.types.length, "Branch requires exactly "+this.types.length+" operands");
43 | this.types.forEach(function(type, i) {
44 | if (type === null)
45 | assert(stmt.operands[i] instanceof Stmt, "Branch operand "+i+" must be a statement");
46 | else {
47 | assert(stmt.operands[i] instanceof BaseExpr, "Branch operand "+i+ " must be an expression");
48 | assert.strictEqual(stmt.operands[i].type, type, "Branch operand "+i+" expression must be "+types.RTypeNames[type]);
49 | }
50 | }, this);
51 | };
52 |
53 | BranchBehavior.prototype.write = function(s, stmt) {
54 | s.code(stmt.code);
55 | stmt.operands.forEach(function(operand) {
56 | s.write(operand);
57 | });
58 | };
59 |
--------------------------------------------------------------------------------
/src/stmt/behavior/CallImportBehavior.js:
--------------------------------------------------------------------------------
1 | var assert = require("assert"),
2 | types = require("../../types");
3 |
4 | var BaseBehavior = require("./BaseBehavior"),
5 | BaseExpr = require("../BaseExpr"),
6 | FunctionImportSignature = require("../../reflect/FunctionImportSignature");
7 |
8 | /**
9 | * CallImport behavior.
10 | * @param {string} name
11 | * @param {string} description
12 | * @param {number} returnType
13 | * @constructor
14 | * @extends stmt.behavior.BaseBehavior
15 | * @exports stmt.behavior.CallImportBehavior
16 | */
17 | function CallImportBehavior(name, description, returnType) {
18 | BaseBehavior.call(this, name, description);
19 |
20 | /**
21 | * Return type, if any.
22 | * @type {number}
23 | */
24 | this.returnType = returnType;
25 | }
26 |
27 | module.exports = CallImportBehavior;
28 |
29 | // Extends Behavior
30 | CallImportBehavior.prototype = Object.create(BaseBehavior.prototype);
31 |
32 | // opcode + import function index + argument list as Expr
33 | // Stmt & Expr<*>, all without imm
34 |
35 | CallImportBehavior.prototype.read = function(s, code) {
36 | var functionImportSignature = s.import(s.varint());
37 | s.stmt(code, [ functionImportSignature ]);
38 | functionImportSignature.signature.argumentTypes.forEach(function(type) {
39 | s.read(type);
40 | }, this);
41 | };
42 |
43 | CallImportBehavior.prototype.validate = function(definition, stmt) {
44 | assert(stmt.operands.length >= 1, this.name+" requires at least 1 operand");
45 | var func = stmt.operands[0];
46 | assert(func instanceof FunctionImportSignature, this.name+" function (operand 0) must be a FunctionImportSignature");
47 | assert.strictEqual(func.assembly, definition.declaration.assembly, this.name+" function (operand 0) must be part of this assembly");
48 | assert.strictEqual(func.signature.returnType, this.returnType, this.name+" function (operand 0) return type must be "+types.RTypeNames[this.returnType]);
49 | assert.strictEqual(stmt.operands.length, 1+func.signature.argumentTypes.length, this.name+" requires exactly "+(1+func.signature.argumentTypes.length)+" operands");
50 | func.signature.argumentTypes.forEach(function(type, i) {
51 | var expr = stmt.operands[1+i];
52 | assert(expr instanceof BaseExpr, this.name+" argument "+i+" (operand "+(1+i)+") must be an expression");
53 | assert.strictEqual(expr.type, type, this.name+" argument "+i+" (operand "+(1+i)+") expression must be "+types.RTypeNames[type]);
54 | }, this);
55 | };
56 |
57 | CallImportBehavior.prototype.write = function(s, stmt) {
58 | s.code(stmt.code);
59 | s.varint(stmt.operands[0].index);
60 | for (var i=1; i element index + argument list as Expr
33 | // Stmt & Expr<*>, all without imm
34 |
35 | CallIndirectBehavior.prototype.read = function(s, code) {
36 | var functionPointerTable = s.indirect(s.varint());
37 | s.stmt(code, [ functionPointerTable ]);
38 | s.read(types.WireType.ExprI32);
39 | functionPointerTable.signature.argumentTypes.forEach(function(type) {
40 | s.read(type);
41 | }, this);
42 | };
43 |
44 | CallIndirectBehavior.prototype.validate = function(definition, stmt) {
45 | assert(stmt.operands.length >= 2, this.name+" requires at least 2 operands");
46 | var func = stmt.operands[0];
47 | assert(func instanceof FunctionPointerTable, this.name+" function (operand 0) must be a FunctionPointerTable");
48 | assert.strictEqual(func.assembly, definition.declaration.assembly, this.name+" function (operand 0) must be part of this assembly");
49 | assert.strictEqual(func.signature.returnType, this.returnType, this.name+" function (operand 0) return type must be "+types.RTypeNames[this.returnType]);
50 | assert.strictEqual(stmt.operands.length, 2+func.signature.argumentTypes.length, this.name+" requires exactly "+(2+func.signature.argumentTypes.length)+" operands");
51 | var expr = stmt.operands[1];
52 | assert(expr instanceof BaseExpr, this.name+" element index (operand 1) must be an expression");
53 | assert.strictEqual(expr.type, types.RType.I32, this.name+" element index (operand 1) expression must be "+types.RTypeNames[types.RType.I32]);
54 | func.signature.argumentTypes.forEach(function(type, i) {
55 | var expr = stmt.operands[2+i];
56 | assert(expr instanceof BaseExpr, this.name+" argument "+i+" (operand "+(2+i)+") must be an expression");
57 | assert.strictEqual(expr.type, type, this.name+" argument "+i+" (operand "+(2+i)+") expression must be "+types.RTypeNames[type]);
58 | }, this);
59 | };
60 |
61 | CallIndirectBehavior.prototype.write = function(s, stmt) {
62 | s.u8(stmt.code);
63 | s.varint(stmt.operands[0].index);
64 | s.write(stmt.operands[1]);
65 | for (var i=2; i
33 | // Stmt & Expr<*>, all without imm
34 |
35 | CallInternalBehavior.prototype.read = function(s, code) {
36 | var functionDeclaration = s.internal(s.varint());
37 | s.stmt(code, [ functionDeclaration ]);
38 | functionDeclaration.signature.argumentTypes.forEach(function(type) {
39 | s.read(type);
40 | }, this);
41 | };
42 |
43 | CallInternalBehavior.prototype.validate = function(definition, stmt) {
44 | assert(stmt.operands.length >= 1, this.name+" requires at least 1 operand");
45 | var func = stmt.operands[0];
46 | assert(func instanceof FunctionDeclaration, this.name+" function (operand 0) must be a FunctionDeclaration");
47 | assert.strictEqual(func.assembly, definition.declaration.assembly, this.name+" function (operand 0) must be part of this assembly");
48 | assert.strictEqual(func.declaration.signature.returnType, this.returnType, this.name+" function (operand 0) return type must be "+types.RTypeNames[this.returnType]);
49 | assert.strictEqual(stmt.operands.length, 1+func.signature.argumentTypes.length, this.name+" requires exactly "+(1+func.signature.argumentTypes.length)+" operands");
50 | func.signature.argumentTypes.forEach(function(type, i) {
51 | var expr = stmt.operands[1+i];
52 | assert(expr instanceof BaseExpr, this.name+" argument "+i+" (operand "+(1+i)+") must be an expression");
53 | assert.strictEqual(expr.type, type, this.name+" argument "+i+" (operand "+(1+i)+") expression must be "+types.RTypeNames[type]);
54 | }, this);
55 | };
56 |
57 | CallInternalBehavior.prototype.write = function(s, stmt) {
58 | s.code(stmt.code);
59 | s.varint(stmt.operands[0].index);
60 | for (var i=1; i left + Expr<*> right
32 | // Expr<*>, all without imm
33 |
34 | CommaBehavior.prototype.read = function(s, code) {
35 | var rtype = s.u8();
36 | s.stmt(code);
37 | switch (rtype) {
38 | case types.RType.I32:
39 | case types.RType.F32:
40 | case types.RType.F64:
41 | case types.RType.Void:
42 | s.read(rtype);
43 | break;
44 | default:
45 | throw Error("illegal left hand return type: "+rtype);
46 | }
47 | s.read(this.returnType);
48 | };
49 |
50 | CommaBehavior.prototype.validate = function(definition, stmt) {
51 | assert.strictEqual(stmt.operands.length, 2, this.name+" requires exactly 2 operands");
52 | assert(stmt.operands[0] instanceof BaseExpr, this.name+" left (operand 0) must be an expression");
53 | var right = stmt.operands[1];
54 | assert(right instanceof BaseExpr, this.name+" right (operand 1) must be an expression");
55 | assert.strictEqual(right.type, this.returnType, this.name+" right (operand 1) expression must be "+types.RTypeNames[this.returnType]);
56 | };
57 |
58 | CommaBehavior.prototype.write = function(s, stmt) {
59 | s.code(stmt.code);
60 | s.u8(stmt.operands[0].type);
61 | s.write(stmt.operands[0]);
62 | s.write(stmt.operands[1]);
63 | };
64 |
--------------------------------------------------------------------------------
/src/stmt/behavior/ConstantPoolBehavior.js:
--------------------------------------------------------------------------------
1 | var assert = require("assert"),
2 | types = require("../../types");
3 |
4 | var BaseBehavior = require("./BaseBehavior"),
5 | Constant = require("../../reflect/Constant");
6 |
7 | /**
8 | * ConstantPool behavior.
9 | * @param {string} name
10 | * @param {string} description
11 | * @param {number} type
12 | * @constructor
13 | * @extends stmt.behavior.BaseBehavior
14 | * @exports stmt.behavior.ConstantPoolBehavior
15 | */
16 | function ConstantPoolBehavior(name, description, type) {
17 | BaseBehavior.call(this, name, description);
18 |
19 | /**
20 | * Constant type.
21 | * @type {number}
22 | */
23 | this.type = type;
24 | }
25 |
26 | module.exports = ConstantPoolBehavior;
27 |
28 | // Extends Behavior
29 | ConstantPoolBehavior.prototype = Object.create(BaseBehavior.prototype);
30 |
31 | // opcode + constant index
32 | // Expr<*>, all with imm
33 |
34 | ConstantPoolBehavior.prototype.read = function(s, code, imm) {
35 | if (imm !== null)
36 | s.stmtWithoutImm(code, [ s.constant(imm) ]);
37 | else
38 | s.stmt(code, [ s.constant(s.varint()) ]);
39 | };
40 |
41 | ConstantPoolBehavior.prototype.validate = function(definition, stmt) {
42 | assert.strictEqual(stmt.operands.length, 1, this.name+" requires exactly 1 operand");
43 | var constant = stmt.operands[0];
44 | assert(constant instanceof Constant, this+" constant (operand 0) must be a Constant");
45 | assert.strictEqual(constant.assembly, definition.declaration.assembly, this.name+" constant (operand 0) must be part of this assembly");
46 | assert.strictEqual(constant.type, this.type, this.name+" constant (operand 0) type must be "+types.RTypeNames[this.type]);
47 | };
48 |
49 | ConstantPoolBehavior.prototype.write = function(s, stmt) {
50 | var index = stmt.operands[0].index;
51 | if (!s.codeWithImm(stmt.code, index)) {
52 | s.code(stmt.code);
53 | s.varint(index);
54 | }
55 | };
56 |
--------------------------------------------------------------------------------
/src/stmt/behavior/GetGlobalBehavior.js:
--------------------------------------------------------------------------------
1 | var assert = require("assert"),
2 | types = require("../../types");
3 |
4 | var BaseBehavior = require("./BaseBehavior"),
5 | GlobalVariable = require("../../reflect/GlobalVariable");
6 |
7 | /**
8 | * GetGlobal behavior.
9 | * @param {string} name
10 | * @param {string} description
11 | * @param {number} type
12 | * @constructor
13 | * @extends stmt.behavior.BaseBehavior
14 | * @exports stmt.behavior.GetGlobalBehavior
15 | */
16 | function GetGlobalBehavior(name, description, type) {
17 | BaseBehavior.call(this, name, description);
18 |
19 | /**
20 | * Global variable type.
21 | * @type {number}
22 | */
23 | this.type = type;
24 | }
25 |
26 | module.exports = GetGlobalBehavior;
27 |
28 | // Extends Behavior
29 | GetGlobalBehavior.prototype = Object.create(BaseBehavior.prototype);
30 |
31 | // opcode + global variable index
32 | // Expr<*>, all without imm
33 |
34 | GetGlobalBehavior.prototype.read = function(s, code) {
35 | s.stmt(code, [ s.global(s.varint(), this.type) ]);
36 | };
37 |
38 | GetGlobalBehavior.prototype.validate = function(definition, stmt) {
39 | assert.strictEqual(stmt.operands.length, 1, "GetGlobal requires exactly 1 operand");
40 | var variable = stmt.operands[0];
41 | assert(variable instanceof GlobalVariable, "GetGlobal variable (operand 0) must be a GlobalVariable");
42 | assert.strictEqual(variable.definition.declaration.assembly, definition.definition.declaration.assembly, "GetGlobal variable (operand 0) must be part of this assembly");
43 | assert.strictEqual(variable.type, this.type, "GetGlobal variable (operand 0) type must be "+types.RTypeNames[this.type]);
44 | };
45 |
46 | GetGlobalBehavior.prototype.write = function(s, stmt) {
47 | s.code(stmt.code);
48 | s.varint(stmt.operands[0].index);
49 | };
50 |
--------------------------------------------------------------------------------
/src/stmt/behavior/GetLocalBehavior.js:
--------------------------------------------------------------------------------
1 | var assert = require("assert"),
2 | types = require("../../types");
3 |
4 | var BaseBehavior = require("./BaseBehavior"),
5 | LocalVariable = require("../../reflect/LocalVariable");
6 |
7 | /**
8 | * GetLocal behavior.
9 | * @param {string} name
10 | * @param {string} description
11 | * @param {number} type
12 | * @constructor
13 | * @extends stmt.behavior.BaseBehavior
14 | * @exports stmt.behavior.GetLocalBehavior
15 | */
16 | function GetLocalBehavior(name, description, type) {
17 | BaseBehavior.call(this, name, description);
18 |
19 | /**
20 | * Local variable type.
21 | * @type {number}
22 | */
23 | this.type = type;
24 | }
25 |
26 | module.exports = GetLocalBehavior;
27 |
28 | // Extends Behavior
29 | GetLocalBehavior.prototype = Object.create(BaseBehavior.prototype);
30 |
31 | // opcode + local variable index
32 | // Expr<*>, all with imm
33 |
34 | GetLocalBehavior.prototype.read = function(s, code, imm) {
35 | if (imm !== null)
36 | s.stmtWithoutImm(code, [ s.local(imm, this.type) ]);
37 | else
38 | s.stmt(code, [ s.local(s.varint(), this.type) ]);
39 | };
40 |
41 | GetLocalBehavior.prototype.validate = function(definition, stmt) {
42 | assert.strictEqual(stmt.operands.length, 1, "GetLocal requires exactly 1 operand");
43 | var variable = stmt.operands[0];
44 | assert(variable instanceof LocalVariable, "GetLocal variable (operand 0) must be a LocalVariable");
45 | assert.strictEqual(variable.definition, definition, "GetLocal variable (operand 0) must be part of this definition");
46 | assert.strictEqual(variable.type, this.type, "GetLocal variable (operand 0) type must be "+types.WireTypeNames[this.type]);
47 | };
48 |
49 | GetLocalBehavior.prototype.write = function(s, stmt) {
50 | var index = stmt.operands[0].index;
51 | if (!s.codeWithImm(stmt.code, index)) {
52 | s.code(stmt.code);
53 | s.varint(index);
54 | }
55 | };
56 |
--------------------------------------------------------------------------------
/src/stmt/behavior/LabelBehavior.js:
--------------------------------------------------------------------------------
1 | var assert = require("assert");
2 |
3 | var BaseBehavior = require("./BaseBehavior");
4 |
5 | /**
6 | * Label behavior.
7 | * @param {string} name
8 | * @param {string} description
9 | * @constructor
10 | * @extends stmt.behavior.BaseBehavior
11 | * @exports stmt.behavior.LabelBehavior
12 | */
13 | function LabelBehavior(name, description) {
14 | BaseBehavior.call(this, name, description);
15 | }
16 |
17 | module.exports = LabelBehavior;
18 |
19 | // Extends Behavior
20 | LabelBehavior.prototype = Object.create(BaseBehavior.prototype);
21 |
22 | // opcode + label index
23 | // Stmt only, without imm
24 |
25 | LabelBehavior.prototype.read = function(s, code, imm) {
26 | s.stmt(code, [ s.varint() ]);
27 | };
28 |
29 | LabelBehavior.prototype.validate = function(definition, stmt) {
30 | assert.strictEqual(stmt.operands.length, 1, "Label requires exactly 1 operands");
31 | var label = stmt.operands[0];
32 | assert(typeof label === 'number' && label%1 === 0 && label >= 0, "Label index (operand 0) must be a non-negative integer");
33 | };
34 |
35 | LabelBehavior.prototype.write = function(s, stmt) {
36 | s.code(stmt.code);
37 | s.varint(stmt.operands[0]);
38 | };
39 |
--------------------------------------------------------------------------------
/src/stmt/behavior/LiteralBehavior.js:
--------------------------------------------------------------------------------
1 | var assert = require("assert"),
2 | types = require("../../types");
3 |
4 | var BaseBehavior = require("./BaseBehavior");
5 |
6 | /**
7 | * Literal behavior.
8 | * @param {string} name
9 | * @param {string} description
10 | * @param {number} type
11 | * @constructor
12 | * @extends stmt.behavior.BaseBehavior
13 | * @exports stmt.behavior.LiteralBehavior
14 | */
15 | function LiteralBehavior(name, description, type) {
16 | BaseBehavior.call(this, name, description);
17 |
18 | /**
19 | * Literal type.
20 | * @type {number}
21 | */
22 | this.type = type;
23 | }
24 |
25 | module.exports = LiteralBehavior;
26 |
27 | // Extends Behavior
28 | LiteralBehavior.prototype = Object.create(BaseBehavior.prototype);
29 |
30 | // opcode + literal
31 | // Expr<*>, Expr with imm
32 |
33 | LiteralBehavior.prototype.read = function(s, code, imm) {
34 | if (this.type === types.Type.I32) {
35 | if (imm !== null)
36 | s.stmtWithoutImm(code, [ imm ]);
37 | else
38 | s.stmt(code, [ s.varint() ]);
39 | } else {
40 | var value;
41 | switch (this.type) {
42 | case types.Type.F32:
43 | value = s.f32();
44 | break;
45 | case types.Type.F64:
46 | value = s.f64();
47 | break;
48 | default:
49 | throw Error("unreachable");
50 | }
51 | s.stmt(code, [ value ]);
52 | }
53 | };
54 |
55 | LiteralBehavior.prototype.validate = function(definition, stmt) {
56 | assert.strictEqual(stmt.operands.length, 1, this.name+" requires exactly 1 operand");
57 | var value = stmt.operands[0];
58 | if (this.type === types.Type.I32)
59 | assert(typeof value === 'number' && value%1 === 0 && value >= 0, this.name+" value (operand 0) must be a non-negative integer");
60 | else
61 | assert(typeof value === 'number', this.name+" value (operand 0) must be a number");
62 | };
63 |
64 | LiteralBehavior.prototype.write = function(s, stmt) {
65 | var value = stmt.operands[0];
66 | if (this.type === types.Type.I32) {
67 | if (!s.codeWithImm(stmt.code, value)) {
68 | s.code(stmt.code);
69 | s.varint(value);
70 | }
71 | } else {
72 | s.code(stmt.code);
73 | switch (this.type) {
74 | case types.Type.F32:
75 | s.f32(value);
76 | break;
77 | case types.Type.F64:
78 | s.f64(value);
79 | break;
80 | default:
81 | throw Error("unreachable");
82 | }
83 | }
84 | };
85 |
--------------------------------------------------------------------------------
/src/stmt/behavior/LoadBehavior.js:
--------------------------------------------------------------------------------
1 | var assert = require("assert"),
2 | types = require("../../types");
3 |
4 | var BaseBehavior = require("./BaseBehavior"),
5 | ExprI32 = require("../ExprI32");
6 |
7 | /**
8 | * Load behavior.
9 | * @param {string} name
10 | * @param {string} description
11 | * @param {number} heapType
12 | * @constructor
13 | * @extends stmt.behavior.BaseBehavior
14 | * @exports stmt.behavior.LoadBehavior
15 | */
16 | function LoadBehavior(name, description, heapType) {
17 | BaseBehavior.call(this, name, description);
18 |
19 | /**
20 | * Heap type.
21 | * @type {number}
22 | */
23 | this.heapType = heapType;
24 | }
25 |
26 | module.exports = LoadBehavior;
27 |
28 | // Extends Behavior
29 | LoadBehavior.prototype = Object.create(BaseBehavior.prototype);
30 |
31 | // opcode + Expr heap index
32 | // Expr<*>, all without imm
33 |
34 | LoadBehavior.prototype.read = function(s, code) {
35 | s.stmt(code);
36 | s.read(types.WireType.ExprI32);
37 | };
38 |
39 | LoadBehavior.prototype.validate = function(definition, stmt) {
40 | assert.strictEqual(stmt.operands.length, 1, "Load requires exactly 1 operand");
41 | var index = stmt.operands[0];
42 | assert(index instanceof ExprI32, "Load heap index (operand 0) must be an I32 expression");
43 | };
44 |
45 | LoadBehavior.prototype.write = function(s, stmt) {
46 | s.code(stmt.code);
47 | s.write(stmt.operands[0]);
48 | };
49 |
--------------------------------------------------------------------------------
/src/stmt/behavior/LoadWithOffsetBehavior.js:
--------------------------------------------------------------------------------
1 | var assert = require("assert"),
2 | types = require("../../types");
3 |
4 | var BaseBehavior = require("./BaseBehavior"),
5 | ExprI32 = require("../ExprI32");
6 |
7 | /**
8 | * LoadWithOffset behavior.
9 | * @param {string} name
10 | * @param {string} description
11 | * @param {number} heapType
12 | * @constructor
13 | * @extends stmt.behavior.BaseBehavior
14 | * @exports stmt.behavior.LoadWithOffsetBehavior
15 | */
16 | function LoadWithOffsetBehavior(name, description, heapType) {
17 | BaseBehavior.call(this, name, description);
18 |
19 | /**
20 | * Heap type.
21 | * @type {number}
22 | */
23 | this.heapType = heapType;
24 | }
25 |
26 | module.exports = LoadWithOffsetBehavior;
27 |
28 | // Extends Behavior
29 | LoadWithOffsetBehavior.prototype = Object.create(BaseBehavior.prototype);
30 |
31 | // opcode + varint offset + Expr heap index
32 | // Expr<*>, all without imm
33 |
34 | LoadWithOffsetBehavior.prototype.read = function(s, code) {
35 | s.stmt(code, [ s.varint() ]);
36 | s.read(types.WireType.ExprI32);
37 | };
38 |
39 | LoadWithOffsetBehavior.prototype.validate = function(definition, stmt) {
40 | assert.strictEqual(stmt.operands.length, 2, "LoadWithOffset requires exactly 2 operands");
41 | var offset = stmt.operands[0];
42 | assert(typeof offset === 'number' && offset%1 === 0 && offset >= 0, "LoadWithOffset offset (operand 0) must be a non-negative integer");
43 | var index = stmt.operands[1];
44 | assert(index instanceof ExprI32, "LoadWithOffset heap index (operand 1) must be an I32 expression");
45 | };
46 |
47 | LoadWithOffsetBehavior.prototype.write = function(s, stmt) {
48 | s.code(stmt.code);
49 | s.varint(stmt.operands[0]);
50 | s.write(stmt.operands[1]);
51 | };
52 |
--------------------------------------------------------------------------------
/src/stmt/behavior/MultiaryBehavior.js:
--------------------------------------------------------------------------------
1 | var assert = require("assert"),
2 | types = require("../../types");
3 |
4 | var BaseBehavior = require("./BaseBehavior"),
5 | BaseExpr = require("../BaseExpr");
6 |
7 | /**
8 | * Multiary behavior.
9 | * @param {string} name
10 | * @param {string} description
11 | * @param {number} type
12 | * @constructor
13 | * @extends stmt.behavior.BaseBehavior
14 | * @exports stmt.behavior.MultiaryBehavior
15 | */
16 | function MultiaryBehavior(name, description, type) {
17 | BaseBehavior.call(this, name, description);
18 |
19 | /**
20 | * Expression type.
21 | * @type {number}
22 | */
23 | this.type = type;
24 | }
25 |
26 | module.exports = MultiaryBehavior;
27 |
28 | MultiaryBehavior.prototype = Object.create(BaseBehavior.prototype);
29 |
30 | // opcode + varint count + count * Expr<*> argument
31 | // Expr<*>, all without imm
32 |
33 | MultiaryBehavior.prototype.read = function(s, code) {
34 | var count = s.varint();
35 | s.stmt(code);
36 | for (var i=0; i if function return type is not void ]
25 | // Stmt only, without imm
26 |
27 | ReturnBehavior.prototype.read = function(s, code, imm) {
28 | var rtype = s.rtype();
29 | s.stmt(code);
30 | if (rtype !== types.RType.Void)
31 | s.read(rtype);
32 | };
33 |
34 | ReturnBehavior.prototype.validate = function(definition, stmt) {
35 | var rtype = definition.declaration.signature.returnType;
36 | if (rtype === types.RType.Void)
37 | assert.strictEqual(stmt.operands.length, 0, this.name+" requires exactly 0 operands");
38 | else {
39 | assert.strictEqual(stmt.operands.length, 1, this.name+" requires exactly 1 operand");
40 | var expr = stmt.operands[0];
41 | assert(expr instanceof BaseExpr, this.name+" return value (operand 0) must be an expression");
42 | assert.strictEqual(expr.type, rtype, this.name+" return value (operand 0) expression must be "+types.RTypeNames[rtype]);
43 | }
44 | };
45 |
46 | ReturnBehavior.prototype.write = function(s, stmt) {
47 | s.code(stmt.code);
48 | if (stmt.operands.length !== 0)
49 | s.write(stmt.operands[0]);
50 | };
51 |
--------------------------------------------------------------------------------
/src/stmt/behavior/SetGlobalBehavior.js:
--------------------------------------------------------------------------------
1 | var assert = require("assert"),
2 | types = require("../../types"),
3 | util = require("../../util");
4 |
5 | var BaseBehavior = require("./BaseBehavior"),
6 | GlobalVariable = require("../../reflect/GlobalVariable"),
7 | BaseExpr = require("../BaseExpr"),
8 | Stmt = require("../Stmt");
9 |
10 | /**
11 | * SetGlobal behavior.
12 | * @param {string} name
13 | * @param {string} description
14 | * @param {number} type
15 | * @constructor
16 | * @extends stmt.behavior.BaseBehavior
17 | * @exports stmt.behavior.SetGlobalBehavior
18 | */
19 | function SetGlobalBehavior(name, description, wireType) {
20 | BaseBehavior.call(this, name, description);
21 |
22 | /**
23 | * Wire type.
24 | * @type {number}
25 | */
26 | this.wireType = wireType;
27 | }
28 |
29 | module.exports = SetGlobalBehavior;
30 |
31 | // Extends Behavior
32 | SetGlobalBehavior.prototype = Object.create(BaseBehavior.prototype);
33 |
34 | // opcode + varint global variable index + Expr value
35 | // Stmt & Expr<*>, Stmt with imm
36 |
37 | SetGlobalBehavior.prototype.read = function(s, code, imm) {
38 | var variable;
39 | if (imm !== null)
40 | s.stmtWithoutImm(code, [ variable = s.global(imm, this.wireType !== types.WireType.Stmt ? this.wireType : undefined) ]);
41 | else
42 | s.stmt(code, [ variable = s.global(s.varint(), this.wireType !== types.WireType.Stmt ? this.wireType : undefined) ]);
43 | s.read(this.wireType === types.WireType.Stmt ? variable.type : this.wireType);
44 | };
45 |
46 | SetGlobalBehavior.prototype.validate = function(definition, stmt) {
47 | assert.strictEqual(stmt.operands.length, 2, "SetGlobal requires exactly 2 operands");
48 | var variable = stmt.operands[0];
49 | assert(variable instanceof GlobalVariable, "SetGlobal variable (operand 0) must be a GlobalVariable");
50 | assert.strictEqual(variable.assembly, definition.declaration.assembly, "SetGlobal variable (operand 0) must be part of this assembly");
51 | if (this.wireType !== types.WireType.Stmt)
52 | assert.strictEqual(variable.type, this.wireType, "SetGlobal variable (operand 0) must be "+types.TypeNames[this.wireType]);
53 | var expr = stmt.operands[1];
54 | assert(expr instanceof BaseExpr, "SetGlobal value (operand 1) must be an expression");
55 | assert.strictEqual(expr.type, variable.type, "SetGlobal value (operand 1) expression must be "+types.WireTypeNames[variable.type]);
56 | };
57 |
58 | SetGlobalBehavior.prototype.write = function(s, stmt) {
59 | var index = stmt.operands[0].index;
60 | if (!s.codeWithImm(stmt.code, index)) {
61 | s.code(stmt.code);
62 | s.varint(index);
63 | }
64 | s.write(stmt.operands[1]);
65 | };
66 |
--------------------------------------------------------------------------------
/src/stmt/behavior/SetLocalBehavior.js:
--------------------------------------------------------------------------------
1 | var assert = require("assert"),
2 | types = require("../../types");
3 |
4 | var BaseBehavior = require("./BaseBehavior"),
5 | LocalVariable = require("../../reflect/LocalVariable"),
6 | BaseExpr = require("../BaseExpr"),
7 | Stmt = require("../Stmt");
8 |
9 | /**
10 | * SetLocal behavior.
11 | * @param {string} name
12 | * @param {string} description
13 | * @param {number} wireType
14 | * @constructor
15 | * @extends stmt.behavior.BaseBehavior
16 | * @exports stmt.behavior.SetLocalBehavior
17 | */
18 | function SetLocalBehavior(name, description, wireType) {
19 | BaseBehavior.call(this, name, description);
20 |
21 | /**
22 | * Expression return type, if an expression.
23 | * @type {number}
24 | */
25 | this.wireType = wireType;
26 | }
27 |
28 | module.exports = SetLocalBehavior;
29 |
30 | // Extends Behavior
31 | SetLocalBehavior.prototype = Object.create(BaseBehavior.prototype);
32 |
33 | // opcode + varint local variable index + Expr value
34 | // Stmt & Expr<*>, Stmt with imm
35 |
36 | SetLocalBehavior.prototype.read = function(s, code, imm) {
37 | var variable;
38 | if (imm !== null)
39 | s.stmtWithoutImm(code, [ variable = s.local(imm, this.wireType !== types.WireType.Stmt ? this.wireType : undefined) ]);
40 | else
41 | s.stmt(code, [ variable = s.local(s.varint(), this.wireType !== types.WireType.Stmt ? this.wireType : undefined) ]);
42 | s.read(this.wireType === types.WireType.Stmt ? variable.type : this.wireType);
43 | };
44 |
45 | SetLocalBehavior.prototype.validate = function(definition, stmt) {
46 | assert.strictEqual(stmt.operands.length, 2, "SetLocal requires exactly 2 operands");
47 | var variable = stmt.operands[0];
48 | assert(variable instanceof LocalVariable, "SetLocal variable (operand 0) must be a LocalVariable");
49 | assert.strictEqual(variable.definition, definition, "SetLocal variable (operand 0) must be part of this definition");
50 | if (this.wireType !== types.WireType.Stmt)
51 | assert.strictEqual(variable.type, this.wireType, "SetLocal variable (operand 0) must be "+types.TypeNames[this.returnType]);
52 | var expr = stmt.operands[1];
53 | assert(expr instanceof BaseExpr, "SetLocal value (operand 1) must be an expression");
54 | assert.strictEqual(expr.type, variable.type, "SetLocal value (operand 1) expression must be "+types.WireTypeNames[variable.type]);
55 | };
56 |
57 | SetLocalBehavior.prototype.write = function(s, stmt) {
58 | var index = stmt.operands[0].index;
59 | if (!s.codeWithImm(stmt.code, index)) {
60 | s.code(stmt.code);
61 | s.varint(index);
62 | }
63 | s.write(stmt.operands[1]);
64 | };
65 |
--------------------------------------------------------------------------------
/src/stmt/behavior/StmtListBehavior.js:
--------------------------------------------------------------------------------
1 | var assert = require("assert"),
2 | types = require("../../types");
3 |
4 | var BaseBehavior = require("./BaseBehavior"),
5 | Stmt = require("../Stmt");
6 |
7 | /**
8 | * StmtList behavior.
9 | * @param {string} name
10 | * @param {string} description
11 | * @constructor
12 | * @extends stmt.behavior.BaseBehavior
13 | * @exports stmt.behavior.StmtListBehavior
14 | */
15 | function StmtListBehavior(name, description) {
16 | BaseBehavior.call(this, name, description);
17 | }
18 |
19 | module.exports = StmtListBehavior;
20 |
21 | // Extends BaseBehavior
22 | StmtListBehavior.prototype = Object.create(BaseBehavior.prototype);
23 |
24 | StmtListBehavior.prototype.read = function(s) {
25 | var count = s.varint();
26 |
27 | };
--------------------------------------------------------------------------------
/src/stmt/behavior/StoreBehavior.js:
--------------------------------------------------------------------------------
1 | var assert = require("assert"),
2 | types = require("../../types");
3 |
4 | var BaseBehavior = require("./BaseBehavior"),
5 | BaseExpr = require("../BaseExpr"),
6 | ExprI32 = require("../ExprI32");
7 |
8 | /**
9 | * Store behavior.
10 | * @param {string} name
11 | * @param {string} description
12 | * @param {number} heapType
13 | * @constructor
14 | * @extends stmt.behavior.BaseBehavior
15 | * @exports stmt.behavior.StoreBehavior
16 | */
17 | function StoreBehavior(name, description, heapType) {
18 | BaseBehavior.call(this, name, description);
19 |
20 | /**
21 | * Heap type.
22 | * @type {number}
23 | */
24 | this.heapType = heapType;
25 | }
26 |
27 | module.exports = StoreBehavior;
28 |
29 | // Extends Behavior
30 | StoreBehavior.prototype = Object.create(BaseBehavior.prototype);
31 |
32 | // opcode + Expr heap index + Expr value
33 | // Stmt & Expr<*>, all without imm
34 |
35 | StoreBehavior.prototype.read = function(s, code) {
36 | s.stmt(code);
37 | s.read(types.WireType.ExprI32);
38 | s.read(this.heapType);
39 | };
40 |
41 | StoreBehavior.prototype.validate = function(definition, stmt) {
42 | assert.strictEqual(stmt.operands.length, 2, "Store requires exactly 2 operands");
43 | var index = stmt.operands[0];
44 | assert(index instanceof ExprI32, "Store heap index (operand 0) must be an I32 expression");
45 | var value = stmt.operands[1];
46 | assert(value instanceof BaseExpr, "Store value (operand 1) must be an expression");
47 | assert.strictEqual(value.type, this.heapType, "Store value (operand 1) expression must be "+types.RTypeNames[this.heapType]);
48 | };
49 |
50 | StoreBehavior.prototype.write = function(s, stmt) {
51 | s.code(stmt.code);
52 | s.write(stmt.operands[0]);
53 | s.write(stmt.operands[1]);
54 | };
55 |
--------------------------------------------------------------------------------
/src/stmt/behavior/StoreWithOffsetBehavior.js:
--------------------------------------------------------------------------------
1 | var assert = require("assert"),
2 | types = require("../../types");
3 |
4 | var BaseBehavior = require("./BaseBehavior"),
5 | BaseExpr = require("..//BaseExpr"),
6 | ExprI32 = require("../ExprI32");
7 |
8 | /**
9 | * StoreWithOffset behavior.
10 | * @param {string} name
11 | * @param {string} description
12 | * @param {number} heapType
13 | * @constructor
14 | * @extends stmt.behavior.BaseBehavior
15 | * @exports stmt.behavior.StoreWithOffsetBehavior
16 | */
17 | function StoreWithOffsetBehavior(name, description, heapType) {
18 | BaseBehavior.call(this, name, description);
19 |
20 | /**
21 | * Heap type.
22 | * @type {number}
23 | */
24 | this.heapType = heapType;
25 | }
26 |
27 | module.exports = StoreWithOffsetBehavior;
28 |
29 | // Extends Behavior
30 | StoreWithOffsetBehavior.prototype = Object.create(BaseBehavior.prototype);
31 |
32 | // opcode + varint offset + Expr heap index + Expr value
33 | // Stmt & Expr<*>, all without imm
34 |
35 | StoreWithOffsetBehavior.prototype.read = function(s, code) {
36 | s.stmt(code, [ s.varint() ]);
37 | s.read(types.WireType.ExprI32);
38 | s.read(this.heapType);
39 | };
40 |
41 | StoreWithOffsetBehavior.prototype.validate = function(definition, stmt) {
42 | assert.strictEqual(stmt.operands.length, 3, "StoreWithOffset requires exactly 3 operands");
43 | var offset = stmt.operands[0];
44 | assert(typeof offset === 'number' && offset%1 === 0 && offset >= 0, "StoreWithOffset offset (operand 0) must be a non-negative integer");
45 | var index = stmt.operands[1];
46 | assert(index instanceof ExprI32, "StoreWithOffset heap index (operand 1) must be an I32 expression");
47 | var value = stmt.operands[2];
48 | assert(value instanceof BaseExpr, "StoreWithOffset value (operand 2) must be an expression");
49 | assert.strictEqual(value.type, this.heapType, "StoreWithOffset value (operand 1) expression must be "+types.TypeNames[this.heapType]);
50 | };
51 |
52 | StoreWithOffsetBehavior.prototype.write = function(s, stmt) {
53 | s.code(stmt.code);
54 | s.varint(stmt.operands[0]);
55 | s.write(stmt.operands[1]);
56 | s.write(stmt.operands[2]);
57 | };
58 |
--------------------------------------------------------------------------------
/src/stmt/behavior/SwitchBehavior.js:
--------------------------------------------------------------------------------
1 | var assert = require("assert"),
2 | types = require("../../types");
3 |
4 | var BaseBehavior = require("./BaseBehavior"),
5 | ExprI32 = require("../ExprI32"),
6 | SwitchCase = require("../SwitchCase");
7 |
8 | /**
9 | * Switch behavior.
10 | * @param {string} name
11 | * @param {string} description
12 | * @constructor
13 | * @extends stmt.behavior.BaseBehavior
14 | * @exports stmt.behavior.SwitchBehavior
15 | */
16 | function SwitchBehavior(name, description) {
17 | BaseBehavior.call(this, name, description);
18 | }
19 |
20 | module.exports = SwitchBehavior;
21 |
22 | // Extends Behavior
23 | SwitchBehavior.prototype = Object.create(BaseBehavior.prototype);
24 |
25 | // opcode + number of cases + Expr condition + number of cases * SwitchCase
26 | // Stmt only, without imm
27 |
28 | SwitchBehavior.prototype.read = function(s, code) {
29 | var count = s.varint();
30 | s.stmt(code);
31 | s.read(types.WireType.ExprI32);
32 | for (var i=0; i= 1, this.name+" requires at least 1 operand");
37 | var label = stmt.operands[0];
38 | assert(typeof label === 'number' && label%1 === 0, this.name+" label (operand 0) must be an integer");
39 | for (var i=1; i argument
31 | // Expr<*>, all without imm
32 |
33 | UnaryBehavior.prototype.read = function(s, code) {
34 | s.stmt(code);
35 | s.read(this.type);
36 | };
37 |
38 | UnaryBehavior.prototype.validate = function(definition, stmt) {
39 | assert.strictEqual(stmt.operands.length, 1, this.name+" requires exactly 1 operand");
40 | assert(stmt.operands[0] instanceof BaseExpr, this.name+" operand 0 must be an expression");
41 | assert.strictEqual(stmt.operands[0].type, this.type, this.name+" operand 0 expression must be "+types.TypeNames[this.type]);
42 | };
43 |
44 | UnaryBehavior.prototype.write = function(s, stmt) {
45 | s.code(stmt.code);
46 | s.write(stmt.operands[0]);
47 | };
48 |
--------------------------------------------------------------------------------
/src/stmt/behavior/index.js:
--------------------------------------------------------------------------------
1 | var types = require("../../types");
2 |
3 | /**
4 | * @namespace
5 | * @exports stmt.behavior
6 | */
7 | var behavior = module.exports = {};
8 |
9 | var BaseBehavior = behavior.BaseBehavior = require("./BaseBehavior"),
10 | GetLocalBehavior = behavior.GetLocalBehavior = require("./GetLocalBehavior"),
11 | GetGlobalBehavior = behavior.GetGlobalBehavior = require("./GetGlobalBehavior"),
12 | SetLocalBehavior = behavior.SetLocalBehavior = require("./SetLocalBehavior"),
13 | SetGlobalBehavior = behavior.SetGlobalBehavior = require("./SetGlobalBehavior"),
14 | LoadBehavior = behavior.LoadBehavior = require("./LoadBehavior"),
15 | StoreBehavior = behavior.StoreBehavior = require("./StoreBehavior"),
16 | LoadWithOffsetBehavior = behavior.LoadWithOffsetBehavior = require("./LoadWithOffsetBehavior"),
17 | StoreWithOffsetBehavior = behavior.StoreWithOffsetBehavior = require("./StoreWithOffsetBehavior"),
18 | BranchBehavior = behavior.BranchBehavior = require("./BranchBehavior"),
19 | OpcodeOnlyBehavior = behavior.OpcodeOnlyBehavior = require("./OpcodeOnlyBehavior"),
20 | LabelBehavior = behavior.LabelBehavior = require("./LabelBehavior"),
21 | ReturnBehavior = behavior.ReturnBehavior = require("./ReturnBehavior"),
22 | BlockBehavior = behavior.BlockBehavior = require("./BlockBehavior"),
23 | UnaryBehavior = behavior.UnaryBehavior = require("./UnaryBehavior"),
24 | BinaryBehavior = behavior.BinaryBehavior = require("./BinaryBehavior"),
25 | MultiaryBehavior = behavior.MultiaryBehavior = require("./MultiaryBehavior"),
26 | LiteralBehavior = behavior.LiteralBehavior = require("./LiteralBehavior"),
27 | ConstantPoolBehavior = behavior.ConstantPoolBehavior = require("./ConstantPoolBehavior"),
28 | CommaBehavior = behavior.CommaBehavior = require("./CommaBehavior"),
29 | CallInternalBehavior = behavior.CallInternalBehavior = require("./CallInternalBehavior"),
30 | CallImportBehavior = behavior.CallImportBehavior = require("./CallImportBehavior"),
31 | CallIndirectBehavior = behavior.CallIndirectBehavior = require("./CallIndirectBehavior"),
32 | SwitchBehavior = behavior.SwitchBehavior = require("./SwitchBehavior"),
33 | SwitchCaseNoneBehavior = behavior.SwitchNoneBehavior = require("./SwitchCaseNoneBehavior"),
34 | SwitchCaseSingleBehavior = behavior.SwitchCaseSingleBehavior = require("./SwitchCaseSingleBehavior"),
35 | SwitchCaseMultipleBehavior = behavior.SwitchCaseMultipleBehavior = require("./SwitchCaseMultipleBehavior"),
36 | SwitchDefaultNoneBehavior = behavior.SwitchDefaultNoneBehavior = require("./SwitchDefaultNoneBehavior"),
37 | SwitchDefaultSingleBehavior = behavior.SwitchDefaultSingleBehavior = require("./SwitchDefaultSingleBehavior"),
38 | SwitchDefaultMultipleBehavior = behavior.SwitchDefaultMultipleBehavior = require("./SwitchDefaultMultipleBehavior");
39 |
40 | // Get local variable
41 | behavior.GetLocalI32 = new GetLocalBehavior("GetLocalI32", "opcode + local I32 variable index", types.Type.I32);
42 | behavior.GetLocalF32 = new GetLocalBehavior("GetLocalF32", "opcode + local F32 variable index", types.Type.F32);
43 | behavior.GetLocalF64 = new GetLocalBehavior("GetLocalF64", "opcode + local F64 variable index", types.Type.F64);
44 |
45 | // Set local variable
46 | behavior.SetLocal = new SetLocalBehavior("SetLocal", "opcode + local variable index + Expr", types.WireType.Stmt);
47 | behavior.SetLocalI32 = new SetLocalBehavior("SetLocalI32", "opcode + local I32 variable index + Expr", types.WireType.ExprI32);
48 | behavior.SetLocalF32 = new SetLocalBehavior("SetLocalF32", "opcode + local F32 variable index + Expr", types.WireType.ExprF32);
49 | behavior.SetLocalF64 = new SetLocalBehavior("SetLocalF64", "opcode + local F64 variable index + Expr", types.WireType.ExprF64);
50 |
51 | // Get global variable
52 | behavior.GetGlobalI32 = new GetGlobalBehavior("GetGlobalI32", "opcode + global I32 variable index", types.Type.I32);
53 | behavior.GetGlobalF32 = new GetGlobalBehavior("GetGlobalF32", "opcode + global F32 variable index", types.Type.F32);
54 | behavior.GetGlobalF64 = new GetGlobalBehavior("GetGlobalF64", "opcode + global F64 variable index", types.Type.F64);
55 |
56 | // Set global variable
57 | behavior.SetGlobal = new SetGlobalBehavior("SetGlobal", "opcode + global variable index + Expr", types.WireType.Stmt);
58 | behavior.SetGlobalI32 = new SetGlobalBehavior("SetGlobalI32", "opcode + global I32 variable index + Expr", types.WireType.ExprI32);
59 | behavior.SetGlobalF32 = new SetGlobalBehavior("SetGlobalF32", "opcode + global F32 variable index + Expr", types.WireType.ExprF32);
60 | behavior.SetGlobalF64 = new SetGlobalBehavior("SetGlobalF64", "opcode + global F64 variable index + Expr", types.WireType.ExprF64);
61 |
62 | // Store on heap
63 | behavior.StoreI = new StoreBehavior("StoreI", "opcode + Expr type-specific heap index + Expr value", types.Type.I32);
64 | behavior.StoreF32 = new StoreBehavior("StoreF32", "opcode + Expr F32 heap index + Expr value", types.Type.F32);
65 | behavior.StoreF64 = new StoreBehavior("StoreF64", "opcode + Expr F64 heap index + Expr value", types.Type.F64);
66 |
67 | // Load from heap
68 | behavior.LoadI = new LoadBehavior("LoadI", "opcode + Expr type-specific heap index", types.Type.I32);
69 | behavior.LoadF32 = new LoadBehavior("LoadF32", "opcode + Expr F32 heap index", types.Type.F32);
70 | behavior.LoadF64 = new LoadBehavior("LoadF64", "opcode + Expr F64 heap index", types.Type.F64);
71 |
72 | // Store on heap with specified offset
73 | behavior.StoreWithOffsetI = new StoreWithOffsetBehavior("StoreWithOffsetI", "opcode + Expr type-specific heap index + Expr heap offset + Expr value", types.WireType.ExprI32);
74 | behavior.StoreWithOffsetF32 = new StoreWithOffsetBehavior("StoreWithOffsetF32", "opcode + Expr F32 heap index + Expr heap offset + Expr value", types.WireType.ExprF32);
75 | behavior.StoreWithOffsetF64 = new StoreWithOffsetBehavior("StoreWithOffsetF64", "opcode + Expr F64 heap index + Expr heap offset + Expr value", types.WireType.ExprF64);
76 |
77 | // Load from heap with specified offset
78 | behavior.LoadWithOffsetI = new LoadWithOffsetBehavior("LoadWithOffsetI", "opcode + Expr type-specific heap index + Expr heap offset", types.Type.I32);
79 | behavior.LoadWithOffsetF32 = new LoadWithOffsetBehavior("LoadWithOffsetF32", "opcode + Expr F32 heap index + Expr heap offset", types.Type.F32);
80 | behavior.LoadWithOffsetF64 = new LoadWithOffsetBehavior("LoadWithOffsetF64", "opcode + Expr F64 heap index + Expr heap offset", types.Type.F64);
81 |
82 | // Control flow
83 | behavior.IfThen = new BranchBehavior("IfThen", "opcode + Expr condition + Stmt then", [types.WireType.ExprI32, types.WireType.Stmt]);
84 | behavior.IfElse = new BranchBehavior("IfElse", "opcode + Expr condition + Stmt then + Stmt else", [types.WireType.ExprI32, types.WireType.Stmt, types.WireType.Stmt]);
85 | behavior.While = new BranchBehavior("While", "opcode + Expr condition + Stmt body", [types.WireType.ExprI32, types.WireType.Stmt]);
86 | behavior.Do = new BranchBehavior("Do", "opcode + Stmt body + Expr condition", [types.WireType.Stmt, types.WireType.ExprI32]);
87 | behavior.Label = new BranchBehavior("Label", "opcode + Stmt body", [types.WireType.Stmt]);
88 | behavior.ConditionalI32 = new BranchBehavior("ConditionalI32", "opcode + Expr condition + Expr then + Expr else", [types.WireType.ExprI32, types.WireType.ExprI32, types.WireType.ExprI32]);
89 | behavior.ConditionalF32 = new BranchBehavior("ConditionalF32", "opcode + Expr condition + Expr then + Expr else", [types.WireType.ExprI32, types.WireType.ExprF32, types.WireType.ExprF32]);
90 | behavior.ConditionalF64 = new BranchBehavior("ConditionalF64", "opcode + Expr condition + Expr then + Expr else", [types.WireType.ExprI32, types.WireType.ExprF64, types.WireType.ExprF64]);
91 | behavior.Break = new OpcodeOnlyBehavior("Break", "opcode only");
92 | behavior.Continue = new OpcodeOnlyBehavior("Continue", "opcode only");
93 | behavior.BreakLabel = new LabelBehavior("BreakLabel", "opcode + label index");
94 | behavior.ContinueLabel = new LabelBehavior("ContinueLabel", "opcode + label index");
95 | behavior.Return = new ReturnBehavior("Return", "opcode [ + Expr if function return type is not void ]");
96 |
97 | // Container
98 | behavior.Block = new BlockBehavior("Block", "opcode + varint count + count * Stmt");
99 |
100 | // Unary operation
101 | behavior.UnaryI32 = new UnaryBehavior("UnaryI32", "opcode + Expr", types.WireType.ExprI32);
102 | behavior.UnaryF32 = new UnaryBehavior("UnaryF32", "opcode + Expr", types.WireType.ExprF32);
103 | behavior.UnaryF64 = new UnaryBehavior("UnaryF64", "opcode + Expr", types.WireType.ExprF64);
104 |
105 | // Binary operation
106 | behavior.BinaryI32 = new BinaryBehavior("BinaryI32", "opcode + Expr + Expr", types.WireType.ExprI32);
107 | behavior.BinaryF32 = new BinaryBehavior("BinaryF32", "opcode + Expr + Expr", types.WireType.ExprF32);
108 | behavior.BinaryF64 = new BinaryBehavior("BinaryF64", "opcode + Expr + Expr", types.WireType.ExprF64);
109 |
110 | // Multiary operation (variable number of arguments)
111 | behavior.MultiaryI32 = new MultiaryBehavior("MultiaryI32", "opcode + varint count + count * Expr", types.WireType.ExprI32);
112 | behavior.MultiaryF64 = new MultiaryBehavior("MultiaryF64", "opcode + varint count + count * Expr", types.WireType.ExprF64);
113 |
114 | // Literal value
115 | behavior.LiteralI32 = new LiteralBehavior("LiteralI32", "opcode + varint/imm value", types.Type.I32);
116 | behavior.LiteralF32 = new LiteralBehavior("LiteralF32", "opcode + float value", types.Type.F32);
117 | behavior.LiteralF64 = new LiteralBehavior("LiteralF64", "opcode + double value", types.Type.F64);
118 |
119 | // Constant value
120 | behavior.ConstantI32 = new ConstantPoolBehavior("ConstantI32", "opcode + I32 constant index", types.WireType.ExprI32);
121 | behavior.ConstantF32 = new ConstantPoolBehavior("ConstantF32", "opcode + F32 constant index", types.WireType.ExprF32);
122 | behavior.ConstantF64 = new ConstantPoolBehavior("ConstantF64", "opcode + F64 constant index", types.WireType.ExprF64);
123 |
124 | // Comma expression
125 | behavior.CommaI32 = new CommaBehavior("CommaI32", "opcode + byte return type + Expr + Expr", types.WireType.ExprI32);
126 | behavior.CommaF32 = new CommaBehavior("CommaF32", "opcode + byte return type + Expr + Expr", types.WireType.ExprF32);
127 | behavior.CommaF64 = new CommaBehavior("CommaF64", "opcode + byte return type + Expr + Expr", types.WireType.ExprF64);
128 |
129 | // Function call
130 | behavior.CallInternal = new CallInternalBehavior("CallInternal", "opcode + varint function declaration index + Expr for each argument", types.WireType.ExprVoid);
131 | behavior.CallImport = new CallImportBehavior("CallImport", "opcode + varint function import signature index + Expr for each argument", types.WireType.ExprVoid);
132 | behavior.CallIndirect = new CallIndirectBehavior("CallIndirect", "opcode + varint function pointer table index + Expr element index + Expr for each argument", types.WireType.ExprVoid);
133 | behavior.CallInternalI32 = new CallInternalBehavior("CallInternalI32", "opcode + varint function declaration index + Expr for each argument", types.WireType.ExprI32);
134 | behavior.CallImportI32 = new CallImportBehavior("CallImportI32", "opcode + varint function import signature index + Expr for each argument", types.WireType.ExprI32);
135 | behavior.CallIndirectI32 = new CallIndirectBehavior("CallIndirectI32", "opcode + varint function pointer table index + Expr element index + Expr for each argument", types.WireType.ExprI32);
136 | behavior.CallInternalF32 = new CallInternalBehavior("CallInternalF32", "opcode + varint function declaration index + Expr for each argument", types.WireType.ExprF32);
137 | behavior.CallIndirectF32 = new CallIndirectBehavior("CallIndirectF32", "opcode + varint function pointer table index + Expr element index + Expr for each argument", types.WireType.ExprF32);
138 | behavior.CallInternalF64 = new CallInternalBehavior("CallInternalF64", "opcode + varint function declaration index + Expr for each argument", types.WireType.ExprF64);
139 | behavior.CallImportF64 = new CallImportBehavior("CallImportF64", "opcode + varint function import signature index + Expr for each argument", types.WireType.ExprF64);
140 | behavior.CallIndirectF64 = new CallIndirectBehavior("CallIndirectF64", "opcode + varint function pointer table index + Expr element index + Expr for each argument", types.WireType.ExprF64);
141 | behavior.CallInternalVoid = new CallInternalBehavior("CallInternalVoid", "opcode + varint function declaration index + Expr for each argument", types.WireType.ExprVoid);
142 | behavior.CallImportVoid = new CallImportBehavior("CallImportVoid", "opcode + varint function import signature index + Expr for each argument", types.WireType.ExprVoid);
143 | behavior.CallIndirectVoid = new CallIndirectBehavior("CallIndirectVoid", "opcode + varint function pointer table index + Expr element index + Expr for each argument", types.WireType.ExprVoid);
144 |
145 | // Switch and switch cases
146 | behavior.Switch = new SwitchBehavior("Switch", "opcode + varint cases + cases * SwitchCase");
147 | behavior.SwitchCase0 = new SwitchCaseNoneBehavior("SwitchCase0", "opcode + signed varint label");
148 | behavior.SwitchCase1 = new SwitchCaseSingleBehavior("SwitchCase1", "opcode + signed varint label + Stmt");
149 | behavior.SwitchCaseN = new SwitchCaseMultipleBehavior("SwitchCaseN", "opcode + signed varint label + varint count + count * Stmt");
150 | behavior.SwitchDefault0 = new SwitchDefaultNoneBehavior("SwitchDefault0", "opcode only");
151 | behavior.SwitchDefault1 = new SwitchDefaultSingleBehavior("SwitchDefault1", "opcode + Stmt");
152 | behavior.SwitchDefaultN = new SwitchDefaultMultipleBehavior("SwitchDefaultN", "opcode + varint count + count * Stmt");
153 |
--------------------------------------------------------------------------------
/src/stmt/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @namespace
3 | * @exports stmt
4 | */
5 | var stmt = module.exports = {};
6 |
7 | stmt.BaseStmt = require("./BaseStmt");
8 | stmt.BaseOperand = require("./BaseOperand");
9 | stmt.BaseExpr = require("./BaseExpr");
10 |
11 | stmt.Stmt = require("./Stmt");
12 | stmt.StmtList = require("./StmtList");
13 |
14 | stmt.ExprI32 = require("./ExprI32");
15 | stmt.ExprF32 = require("./ExprF32");
16 | stmt.ExprF64 = require("./ExprF64");
17 | stmt.ExprVoid = require("./ExprVoid");
18 |
19 | stmt.SwitchCase = require("./SwitchCase");
20 |
21 | stmt.behavior = require("./behavior");
22 |
--------------------------------------------------------------------------------
/src/util.js:
--------------------------------------------------------------------------------
1 | var types = require("./types"),
2 | assert = require("assert");
3 |
4 | /**
5 | * Utility.
6 | * @namespace
7 | * @exports util
8 | */
9 | var util = module.exports = {};
10 |
11 | /**
12 | * @alias util.BufferQueue
13 | */
14 | util.BufferQueue = require("./util/BufferQueue");
15 |
16 | // ----- protocol -----
17 |
18 | util.unpackWithImm = function(b) {
19 | if ((b & types.OpWithImm_Flag) === 0)
20 | return false;
21 | var op = (b >> types.OpWithImm_ImmBits) & types.OpWithImm_OpMax;
22 | var imm = b & types.OpWithImm_ImmMax;
23 | return {
24 | code: op,
25 | imm: imm
26 | };
27 | };
28 |
29 | util.packWithImm = function(code, imm) {
30 | return types.OpWithImm_Flag | ((code & types.OpWithImm_OpMax) << types.OpWithImm_ImmBits) | (imm & types.OpWithImm_ImmMax);
31 | };
32 |
33 | util.calculateVarint = function(value) {
34 | value = value >>> 0;
35 | if (value < 1 << 7 ) return 1;
36 | else if (value < 1 << 14) return 2;
37 | else if (value < 1 << 21) return 3;
38 | else if (value < 1 << 28) return 4;
39 | else return 5;
40 | };
41 |
42 | util.writeVarint = function(buffer, u32, offset) {
43 | var c = 1;
44 | u32 >>>= 0;
45 | while (u32 >= 1 << 7)
46 | buffer[offset++] = (u32 & 0x7f) | 0x80,
47 | u32 >>>= 7,
48 | ++c;
49 | buffer[offset] = u32;
50 | return c;
51 | };
52 |
53 | /* util.readIfI32Lit = function(buffer, offset) {
54 | if (offset >= buffer.length)
55 | throw E_MORE;
56 | var off = offset;
57 | var b = buffer[off];
58 | if (b & HasImmFlag) {
59 | var res = util.unpackWithImm(b);
60 | if (res.op === types.I32WithImm.LitImm) {
61 | off++;
62 | return {
63 | op: res.op,
64 | imm: res.imm,
65 | length: off - offset // 1
66 | };
67 | }
68 | if (res.op === types.I32WithImm.LitPool) {
69 | off++;
70 | return {
71 | op: res.op,
72 | imm: res.imm,
73 | length: off - offset // 1
74 | };
75 | }
76 | return false;
77 | }
78 | var vi;
79 | if (b === types.I32.LitImm) {
80 | off++;
81 | vi = this.readVarint(buffer, off); off += vi.length;
82 | return {
83 | op: b,
84 | imm: vi.value,
85 | length: off - offset
86 | };
87 | }
88 | if (b === types.I32.LitPool) {
89 | off++;
90 | vi = this.readVarint(buffer, off); off += vi.length;
91 | return {
92 | op: b,
93 | imm: vi.value,
94 | length: off - offset
95 | }
96 | }
97 | return false;
98 | }; */
99 |
100 | // ----- asm.js naming -----
101 |
102 | // Identifier characters
103 | var IdenChars = [
104 | 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
105 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
106 | '_', '$',
107 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
108 | ];
109 | util.FirstCharRange = 26 * 2 + 2;
110 | util.FirstCharRangeMinusDollar = 26 * 2 + 1;
111 | util.NextCharRange = IdenChars.length;
112 |
113 | util.indexedName = function(range, i) {
114 | assert(IdenChars.length === 64, "assumed below");
115 | if (i < range)
116 | return IdenChars[i];
117 | i -= range;
118 | var name = [];
119 | if (i < range * 64) {
120 | name.push(IdenChars[i >> 6]);
121 | name.push(IdenChars[i & 0x3f]);
122 |
123 | // Instead of trying to catch every >2 letter keyword, just inject a _.
124 | assert(IdenChars[0x205>>6] === 'i' && IdenChars[0x205&0x3f] === 'f');
125 | assert(IdenChars[0x20d>>6] === 'i' && IdenChars[0x20d&0x3f] === 'n');
126 | assert(IdenChars[0x0ce>>6] === 'd' && IdenChars[0x0ce&0x3f] === 'o');
127 | // Append _ if we would otherwise generate one of the two-letter keywords.
128 | if (range < util.NextCharRange && (i == 0x205 || i == 0x20d || i == 0x0ce))
129 | name.push("_");
130 | return name.join("");
131 | }
132 | i -= range * 64;
133 |
134 | // Instead of trying to catch every >2 letter keyword, just inject a _.
135 | if (range < util.NextCharRange)
136 | name.push("_");
137 |
138 | var len = 0;
139 | do {
140 | name.push(IdenChars[i & 0x3f]);
141 | len++;
142 | i = i >> 6;
143 | } while (i >= range * 64);
144 | name.push(IdenChars[i & 0x3f]);
145 | name.push(IdenChars[i >> 6]);
146 | len += 2;
147 | var a = name.slice(0, name.length - len);
148 | var b = name.slice(name.length - len);
149 | b.reverse();
150 | name = a.concat(b);
151 | return name.join("");
152 | };
153 |
154 | util.localName = function(i) {
155 | return util.indexedName(util.FirstCharRangeMinusDollar, i + types.HotStdLibNames.length);
156 | };
157 |
158 | util.globalName = function(i) {
159 | return '$' + util.indexedName(util.NextCharRange, i + types.StdLibNames.length);
160 | };
161 |
162 | util.hotStdLibName = function(index) {
163 | assert(index >= 0 && index < types.HotStdLibNames.length);
164 | return String.fromCharCode(0x61 + index);
165 | };
166 |
167 | util.stdLibName = function(index) {
168 | assert(index >= 0 && index < types.StdLibNames.length);
169 | return "$" + util.indexedName(util.FirstCharRange, index);
170 | };
171 |
172 | var FNAME_RE = /^[a-zA-Z_\$][a-zA-Z0-9_\$]*$/; // FIXME
173 |
174 | util.isValidFName = function(value) {
175 | return !!(typeof value === 'string' && FNAME_RE.test(value));
176 | };
177 |
178 | // ----- inline assertions -----
179 |
180 | util.assertInteger = function(name, value, min, max) {
181 | if (typeof value !== 'number' || value%1 !== 0)
182 | assert.fail(value, "integer", name+" must be an integer", "===");
183 | if (typeof min === 'undefined' && typeof max === 'undefined')
184 | return;
185 | if (typeof max === 'undefined')
186 | max = min, min = 0;
187 | if (value < min || value > max)
188 | assert.fail(value, "["+min+","+max+"]", name+" out of bounds", "in");
189 | };
190 |
191 | util.assertRType = function(name, value) {
192 | util.assertInteger(name, value);
193 | if (!types.isValidRType(value))
194 | assert.fail(value, types.RType, name+" must be a valid return type", "in");
195 | };
196 |
197 | util.assertType = function(name, value) {
198 | util.assertInteger(name, value);
199 | if (!types.isValidType(value))
200 | assert.fail(value, util.values(types.Type), name+" must be a valid type", "in");
201 | };
202 |
203 | util.assertFName = function(name, value) {
204 | if (!util.isValidFName(value))
205 | assert.fail(value, "function name", name+" must be a valid function name", "===");
206 | };
207 |
208 | // ----- general -----
209 |
210 | util.values = function(obj) {
211 | var values = [];
212 | for (var i in obj)
213 | if (obj.hasOwnProperty(i))
214 | values.push(obj[i]);
215 | return values;
216 | };
217 |
--------------------------------------------------------------------------------
/src/util/BufferQueue.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2015 Daniel Wirtz
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | /**
18 | * A BufferQueue.
19 | *
20 | * Used to remove the need to slice or concatenate buffers and provides the
21 | * convenience of relative read operations and occasionally performed rollbacks.
22 | *
23 | * @constructor
24 | * @exports util.BufferQueue
25 | */
26 | var BufferQueue = module.exports = function() {
27 |
28 | /**
29 | * Queued buffers.
30 | * @type {!Array.}
31 | */
32 | this.buffers = [];
33 |
34 | /**
35 | * Global offset since start.
36 | * @type {number}
37 | */
38 | this.offset = 0;
39 |
40 | /**
41 | * Current buffer index.
42 | * @type {number}
43 | */
44 | this.bufferIndex = 0;
45 |
46 | /**
47 | * Current buffer offset.
48 | * @type {number}
49 | */
50 | this.bufferOffset = 0;
51 |
52 | /**
53 | * Byte length of all queued buffers.
54 | * @type {number}
55 | */
56 | this.bufferLength = 0;
57 |
58 | /**
59 | * Previous global offset.
60 | * @type {number}
61 | */
62 | this.markedOffset = 0;
63 |
64 | /**
65 | * Previous buffer index.
66 | * @type {number}
67 | * @see {@link BufferQueue#reset}
68 | */
69 | this.markedBufferIndex = 0;
70 |
71 | /**
72 | * Previous buffer offset.
73 | * @type {number}
74 | * @see {@link BufferQueue#reset}
75 | */
76 | this.markedBufferOffset = 0;
77 | };
78 |
79 | /**
80 | * Number of remaining readable bytes.
81 | * @name BufferQueue#remaining
82 | * @type {number}
83 | */
84 | Object.defineProperty(BufferQueue.prototype, "remaining", {
85 | get: function() {
86 | if (this.buffers.length === 0)
87 | return 0;
88 | var len = this.bufferLength;
89 | for (var i=0; i 0) {
129 | this.bufferLength -= this.buffers.shift().length;
130 | this.bufferIndex--;
131 | }
132 | return this.commit();
133 | };
134 |
135 | /**
136 | * Resets the buffer queue to the last state.
137 | * @returns {!util.BufferQueue}
138 | */
139 | BufferQueue.prototype.reset = function() {
140 | this.offset = this.markedOffset;
141 | this.bufferIndex = this.markedBufferIndex;
142 | this.bufferOffset = this.markedBufferOffset;
143 | return this;
144 | };
145 |
146 | /**
147 | * Clears all buffers.
148 | * @param {boolean} resetOffset
149 | * @returns {!util.BufferQueue}
150 | */
151 | BufferQueue.prototype.clear = function(resetOffset) {
152 | this.buffers = [];
153 | this.bufferLength = 0;
154 | this.bufferIndex = this.markedBufferIndex = 0;
155 | this.bufferOffset = this.markedBufferOffset = 0;
156 | if (resetOffset)
157 | this.offset = this.markedOffset = 0;
158 | return this;
159 | };
160 |
161 | /**
162 | * Ensures that the specified number of bytes is readable.
163 | * @param {number} nBytes
164 | * @throws {BufferQueue.E_MORE}
165 | */
166 | BufferQueue.prototype.ensure = function(nBytes) {
167 | if (this.remaining < nBytes)
168 | throw BufferQueue.E_MORE;
169 | };
170 |
171 | /**
172 | * Reads an 8bit unsigned integer.
173 | * @returns {number}
174 | */
175 | BufferQueue.prototype.readUInt8 = function() {
176 | if (this.bufferIndex >= this.buffers.length)
177 | throw BufferQueue.E_MORE;
178 | var buf = this.buffers[this.bufferIndex],
179 | u8 = buf[this.bufferOffset++];
180 | this.offset++;
181 | if (this.bufferOffset >= buf.length) {
182 | this.bufferIndex++;
183 | this.bufferOffset = 0;
184 | }
185 | return u8;
186 | };
187 |
188 | /**
189 | * Writes an 8bit unsigned integer.
190 | * @param {number} u8
191 | * @returns {!util.BufferQueue}
192 | */
193 | BufferQueue.prototype.writeUInt8 = function(u8) {
194 | if (this.bufferIndex >= this.buffers.length)
195 | throw BufferQueue.E_MORE;
196 | var buf = this.buffers[this.bufferIndex];
197 | buf[this.bufferOffset++] = u8;
198 | this.offset++;
199 | if (this.bufferOffset >= buf.length) {
200 | this.bufferIndex++;
201 | this.bufferOffset = 0;
202 | }
203 | return this;
204 | };
205 |
206 | /**
207 | * Reads a little endian 32bit unsigned integer.
208 | * @returns {number}
209 | */
210 | BufferQueue.prototype.readUInt32LE = function() {
211 | return (this.readUInt8() | (this.readUInt8() << 8) | (this.readUInt8() << 16) | (this.readUInt8() << 24)) >>> 0;
212 | };
213 |
214 | /**
215 | * Writes a little endian 32bit unsigned integer.
216 | * @param {number} u32
217 | * @returns {!util.BufferQueue}
218 | */
219 | BufferQueue.prototype.writeUInt32LE = function(u32) {
220 | u32 >>>= 0;
221 | return this.writeUInt8(u32)
222 | .writeUInt8(u32 >>> 8)
223 | .writeUInt8(u32 >>> 16)
224 | .writeUInt8(u32 >>> 24);
225 | };
226 |
227 | /**
228 | * Reads an unsigned varint.
229 | * @returns {number}
230 | */
231 | BufferQueue.prototype.readVarint = function() {
232 | if (this.buffers.length === 0)
233 | throw BufferQueue.E_MORE;
234 | var value = this.readUInt8();
235 | if (value < 0x80)
236 | return value;
237 | value &= 0x7f;
238 | var c = 1;
239 | for (var shift = 7; true; shift += 7) {
240 | var b = this.readUInt8();
241 | if (b < 0x80)
242 | return (value | (b << shift)) >>> 0;
243 | if (++c > 5)
244 | throw Error("illegal varint32: >5 bytes");
245 | value = (value | ((b & 0x7f) << shift)) >>> 0;
246 | }
247 | };
248 |
249 | /**
250 | * Writes an unsigned varint.
251 | * @param {number} u32
252 | * @returns {!util.BufferQueue}
253 | */
254 | BufferQueue.prototype.writeVarint = function(u32) {
255 | u32 >>>= 0;
256 | if (u32) {
257 | for (; true; u32 >>>= 7) {
258 | if (u32 < 0x80) {
259 | this.writeUInt8(u32);
260 | return this;
261 | }
262 | this.writeUInt8(0x80 | (u32 & 0x7f));
263 | }
264 | } else
265 | this.writeUInt8(0);
266 | return this;
267 | };
268 |
269 | /**
270 | * Reads a signed varint.
271 | */
272 | BufferQueue.prototype.readVarintSigned = function() {
273 | if (this.buffers.length === 0)
274 | throw BufferQueue.E_MORE;
275 | var value = this.readUInt8();
276 | if (value < 0x80)
277 | return value << (32-7) >> (32-7);
278 | value &= 0x7f;
279 | var c = 1;
280 | for (var shift = 7; true; shift += 7) {
281 | var b = this.readUInt8();
282 | if (b < 0x80) {
283 | value = (value | (b << shift)) >>> 0;
284 | var sign_extend = (32-7) - shift;
285 | if (sign_extend > 0)
286 | return (value|0) << sign_extend >> sign_extend;
287 | return value|0;
288 | }
289 | if (++c > 5)
290 | throw Error("illegal varint32: >5 bytes");
291 | value = (value | ((b & 0x7f) << shift)) >>> 0;
292 | }
293 | };
294 |
295 | /**
296 | * Writes a signed varint.
297 | * @param {number} s32
298 | * @returns {!util.BufferQueue}
299 | */
300 | BufferQueue.prototype.writeVarintSigned = function(s32) {
301 | s32 |= 0;
302 | if (s32) {
303 | for (; true; s32 >>= 7) {
304 | if (-64 <= s32 && s32 < 64) {
305 | this.writeUInt8(s32 & 0x7f);
306 | return this;
307 | }
308 | this.writeUInt8(0x80 | (s32 & 0x7f));
309 | }
310 | } else
311 | this.writeUInt8(0);
312 | return this;
313 | };
314 |
315 | // ref: https://github.com/feross/ieee754
316 | BufferQueue.prototype._readFloat = function(isLE, mLen, nBytes) {
317 | var buffer = [];
318 | for (var i=0; i> 1,
324 | nBits = -7,
325 | d = isLE ? -1 : 1,
326 | s = buffer[i = isLE ? (nBytes - 1) : 0];
327 |
328 | i += d;
329 |
330 | e = s & ((1 << (-nBits)) - 1);
331 | s >>= (-nBits);
332 | nBits += eLen;
333 | for (; nBits > 0; e = e * 256 + buffer[i], i += d, nBits -= 8) {}
334 |
335 | m = e & ((1 << (-nBits)) - 1);
336 | e >>= (-nBits);
337 | nBits += mLen;
338 | for (; nBits > 0; m = m * 256 + buffer[i], i += d, nBits -= 8) {}
339 |
340 | if (e === 0)
341 | e = 1 - eBias;
342 | else if (e === eMax)
343 | return m ? NaN : ((s ? -1 : 1) * Infinity);
344 | else {
345 | m = m + Math.pow(2, mLen);
346 | e = e - eBias;
347 | }
348 | return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
349 | };
350 |
351 | /**
352 | * Reads a little endian 32 bit float.
353 | * @returns {number}
354 | */
355 | BufferQueue.prototype.readFloatLE = function() {
356 | return this._readFloat(true, 23, 4);
357 | };
358 |
359 | /**
360 | * Reads a little endian 64 bit double.
361 | * @returns {number}
362 | */
363 | BufferQueue.prototype.readDoubleLE = function() {
364 | return this._readFloat(true, 52, 8);
365 | };
366 |
367 | // ref: https://github.com/feross/ieee754
368 | BufferQueue.prototype._writeFloat = function(value, isLE, mLen, nBytes) {
369 | var buffer = [];
370 | for (var i=0; i> 1;
376 | var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0);
377 | var i = isLE ? 0 : (nBytes - 1);
378 | var d = isLE ? 1 : -1;
379 | var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
380 |
381 | value = Math.abs(value);
382 |
383 | if (isNaN(value) || value === Infinity) {
384 | m = isNaN(value) ? 1 : 0;
385 | e = eMax;
386 | } else {
387 | e = Math.floor(Math.log(value) / Math.LN2);
388 | if (value * (c = Math.pow(2, -e)) < 1) {
389 | e--;
390 | c *= 2;
391 | }
392 | if (e + eBias >= 1) {
393 | value += rt / c;
394 | } else {
395 | value += rt * Math.pow(2, 1 - eBias);
396 | }
397 | if (value * c >= 2) {
398 | e++;
399 | c /= 2;
400 | }
401 |
402 | if (e + eBias >= eMax) {
403 | m = 0;
404 | e = eMax;
405 | } else if (e + eBias >= 1) {
406 | m = (value * c - 1) * Math.pow(2, mLen);
407 | e = e + eBias;
408 | } else {
409 | m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
410 | e = 0;
411 | }
412 | }
413 |
414 | for (; mLen >= 8; buffer[i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
415 |
416 | e = (e << mLen) | m;
417 | eLen += mLen;
418 | for (; eLen > 0; buffer[i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
419 |
420 | buffer[i - d] |= s * 128;
421 | for (i=0; i>> 0 < 3) {
9 | return 1|0;
10 | }
11 | l = $w(k-1)|0;
12 | m = $w(k-2)|0;
13 | return l + m;
14 | }
15 |
16 | return $w;
17 | }
18 |
--------------------------------------------------------------------------------
/tests/fib.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dcodeIO/WebAssembly-prototype/50e84e133a6e18b0ba0908eea241f836392ebde2/tests/fib.wasm
--------------------------------------------------------------------------------
/tests/test.js:
--------------------------------------------------------------------------------
1 | var fs = require("fs"),
2 | path = require("path"),
3 | assert = require("assert"),
4 | pkg = require("../package.json");
5 |
6 | var webassembly = require("../"),
7 | types = webassembly.types,
8 | Reader = webassembly.Reader,
9 | AstReader = webassembly.ast.Reader,
10 | Writer = webassembly.Writer,
11 | AstWriter = webassembly.ast.Writer,
12 | Assembly = webassembly.reflect.Assembly;
13 |
14 | var verbose = 1;
15 |
16 | if (typeof process.env.VERBOSE !== 'undefined')
17 | verbose = parseInt(process.env.VERBOSE, 10);
18 |
19 | var filename = "AngryBots.wasm";
20 | var file = path.join(__dirname, filename),
21 | stats = fs.statSync(file);
22 |
23 | console.log("WebAssembly "+pkg.version+": Testing '"+filename+"' ...\n");
24 |
25 | var reader = new Reader({
26 | skipAhead: true
27 | });
28 |
29 | if (verbose) {
30 | reader.on("switchState", function (prevState, newState, offset) {
31 | console.log("switch state " + prevState + "->" + newState + " @ " + offset.toString(16));
32 | });
33 |
34 | reader.on("header", function (size) {
35 | console.log("Precomputed size: " + size);
36 | });
37 |
38 | reader.on("constants", function (nI32, nF32, nF64) {
39 | console.log("Constants: " + nI32 + "xI32, " + nF32 + "xF32, " + nF64 + "xF64");
40 | });
41 |
42 | reader.on("constant", function (constant) {
43 | console.log(constant.toString());
44 | });
45 |
46 | reader.on("constantsEnd", function () {
47 | console.log("End of constants");
48 | });
49 |
50 | reader.on("functionSignatures", function (nSigs) {
51 | console.log("Signatures: " + nSigs);
52 | });
53 |
54 | reader.on("functionSignature", function (signature) {
55 | console.log(signature.toString());
56 | });
57 |
58 | reader.on("functionImports", function (nFunctionImports, nSignatures) {
59 | console.log("Function imports: " + nFunctionImports + " (" + nSignatures + " signatures)");
60 | });
61 |
62 | reader.on("functionImport", function (fimport) {
63 | console.log(fimport.toString());
64 | });
65 |
66 | reader.on("functionImportsEnd", function () {
67 | console.log("End of function imports");
68 | });
69 |
70 | reader.on("globalVariables", function (nI32zero, nF32zero, nF64zero, nI32import, nF32import, nF64import) {
71 | console.log("Global vars: " + [nI32zero, nF32zero, nF64zero, nI32import, nF32import, nF64import]);
72 | });
73 |
74 | reader.on("globalVariable", function (variable) {
75 | console.log(variable.toString());
76 | });
77 |
78 | reader.on("globalVariablesEnd", function () {
79 | console.log("End of global variables");
80 | });
81 |
82 | reader.on("functionDeclarations", function (nDeclarations) {
83 | console.log("Function declarations: " + nDeclarations);
84 | });
85 |
86 | reader.on("functionDeclaration", function (declaration) {
87 | console.log(declaration.toString());
88 | });
89 |
90 | reader.on("functionDeclarationsEnd", function () {
91 | console.log("End of function declarations");
92 | });
93 |
94 | reader.on("functionPointerTables", function (nTables) {
95 | console.log("Function pointer tables: " + nTables);
96 | });
97 |
98 | reader.on("functionPointerTable", function (table) {
99 | console.log(table.toString());
100 | });
101 |
102 | reader.on("functionPointerTablesEnd", function () {
103 | console.log("End of function pointer tables");
104 | });
105 |
106 | reader.on("functionDefinitions", function (nDefinitions) {
107 | console.log("Function definitions: " + nDefinitions);
108 | });
109 |
110 | reader.on("functionDefinition", function (definition) {
111 | console.log(definition.asmHeader() + "\n");
112 | });
113 |
114 | reader.on("functionDefinitionsEnd", function () {
115 | console.log("End of function definitions");
116 | });
117 |
118 | reader.on("export", function (exprt) {
119 | console.log("Export: " + exprt.toString());
120 | });
121 | }
122 |
123 | reader.on("end", function() {
124 | if (reader.offset !== stats.size)
125 | throw Error("reader offset != size: "+reader.offset+" != "+stats.size);
126 | console.log("Complete: "+reader.assembly.toString()+"\n");
127 |
128 | if (verbose)
129 | console.log(reader.assembly.asmHeader(), "\n");
130 |
131 | console.log("Validating assembly ...");
132 | try {
133 | reader.assembly.validate();
134 | } catch (err) {
135 | if (err instanceof assert.AssertionError) {
136 | console.log("actual: "+err.actual);
137 | console.log("expected: "+err.expected);
138 | }
139 | throw err;
140 | }
141 | console.log("Success\n");
142 | validateAstOffsets();
143 | });
144 |
145 | console.log("Indexing assembly ...");
146 | fs.createReadStream(file).pipe(reader);
147 |
148 | function validateAstOffsets() {
149 | console.log("Reading ASTs ...");
150 |
151 | var assembly = reader.assembly;
152 | var stats = fs.statSync(file);
153 | var current = 0;
154 |
155 | function next() {
156 | if (current === assembly.functionDeclarations.length) {
157 | console.log("Complete: "+current+" ASTs\n");
158 | validateAstRewrite(assembly);
159 | return;
160 | }
161 | var declaration = assembly.functionDeclarations[current++],
162 | definition = declaration.definition;
163 | var offset = definition.byteOffset,
164 | length = definition.byteLength,
165 | n = 0;
166 | if (length < 0)
167 | throw Error("length "+length+" < 0");
168 | if (offset + length > stats.size)
169 | throw Error("offset + length "+(offset+length)+" > "+stats.size);
170 | if (verbose)
171 | console.log("Reading AST of "+definition+" @ "+definition.byteOffset.toString(16));
172 | var astReader = new AstReader(definition);
173 | astReader.on("ast", function(ast) {
174 | if (verbose)
175 | console.log("AST read complete: "+n+" statements");
176 | definition.ast = ast;
177 | });
178 | astReader.on("stmt", function(stmt) {
179 | ++n;
180 | });
181 | astReader.on("end", function() {
182 | next();
183 | });
184 | fs.createReadStream(file, {
185 | start: offset,
186 | end: offset + length
187 | }).pipe(astReader);
188 | }
189 |
190 | next();
191 | }
192 |
193 | function validateAstRewrite(assembly) {
194 | console.log("Validating AST rewrite ...");
195 | var contents = fs.readFileSync(file),
196 | current = 0;
197 |
198 | function next() {
199 | if (current >= assembly.functionDeclarations.length) {
200 | console.log("Success\n");
201 | write(assembly);
202 | return;
203 | }
204 | var definition = assembly.functionDeclarations[current].definition,
205 | astContents = contents.slice(definition.byteOffset, definition.byteOffset + definition.byteLength);
206 | var writer = new AstWriter(definition, { preserveWithImm: true }),
207 | offset = 0,
208 | n = 0;
209 | if (verbose)
210 | console.log("Writing AST of "+definition);
211 | writer.on("data", function(chunk) {
212 | for (var i=0; i"+state+" @ "+offset.toString(16));
252 | });
253 | writer.on("data", function(chunk) {
254 | if (verbose && wi++%100 === 0)
255 | process.stdout.write(".");
256 | for (var i=0; i
23 | */
24 |
25 | /**
26 | BEGIN_NODE_INCLUDE
27 | var assert = require('assert');
28 | END_NODE_INCLUDE
29 | */
30 |
31 | /**
32 | * @param {*} value
33 | * @param {string} message
34 | * @throws {assert.AssertionError}
35 | */
36 | var assert = function(value, message) {};
37 |
38 | /**
39 | * @param {{message: string, actual: *, expected: *, operator: string}} options
40 | * @constructor
41 | * @extends Error
42 | */
43 | assert.AssertionError = function(options) {};
44 |
45 | /**
46 | * @return {string}
47 | */
48 | assert.AssertionError.prototype.toString = function() {};
49 |
50 | /**
51 | * @param {*} value
52 | * @param {string=} message
53 | * @throws {assert.AssertionError}
54 | */
55 | assert.ok = function(value, message) {};
56 |
57 | /**
58 | * @param {*} actual
59 | * @param {*} expected
60 | * @param {string} message
61 | * @param {string} operator
62 | * @throws {assert.AssertionError}
63 | */
64 | assert.fail = function(actual, expected, message, operator) {};
65 |
66 | /**
67 | * @param {*} actual
68 | * @param {*} expected
69 | * @param {string=} message
70 | * @throws {assert.AssertionError}
71 | */
72 | assert.equal = function(actual, expected, message) {};
73 |
74 | /**
75 | * @param {*} actual
76 | * @param {*} expected
77 | * @param {string=} message
78 | * @throws {assert.AssertionError}
79 | */
80 | assert.notEqual = function(actual, expected, message) {};
81 |
82 | /**
83 | * @param {*} actual
84 | * @param {*} expected
85 | * @param {string=} message
86 | * @throws {assert.AssertionError}
87 | */
88 | assert.deepEqual = function(actual, expected, message) {};
89 |
90 | /**
91 | * @param {*} actual
92 | * @param {*} expected
93 | * @param {string=} message
94 | * @throws {assert.AssertionError}
95 | */
96 | assert.notDeepEqual = function(actual, expected, message) {};
97 |
98 | /**
99 | * @param {*} actual
100 | * @param {*} expected
101 | * @param {string=} message
102 | * @throws {assert.AssertionError}
103 | */
104 | assert.strictEqual = function(actual, expected, message) {};
105 |
106 | /**
107 | * @param {*} actual
108 | * @param {*} expected
109 | * @param {string=} message
110 | * @throws {assert.AssertionError}
111 | */
112 | assert.notStrictEqual = function(actual, expected, message) {};
113 |
114 | /**
115 | * @name assert.throws
116 | * @function
117 | * @param {function()} block
118 | * @param {Function|RegExp|function(*)} error
119 | * @param {string=} message
120 | * @throws {assert.AssertionError}
121 | */
122 | // Error: .\assert.js:120: ERROR - Parse error. missing name after . operator
123 | // assert.throws = function(block, error, message) {};
124 |
125 | /**
126 | * @param {function()} block
127 | * @param {Function|RegExp|function(*)} error
128 | * @param {string=} message
129 | * @throws {assert.AssertionError}
130 | */
131 | assert.doesNotThrow = function(block, error, message) {};
132 |
133 | /**
134 | * @param {*} value
135 | * @throws {assert.AssertionError}
136 | */
137 | assert.ifError = function(value) {};
--------------------------------------------------------------------------------
/tools/externs/errors.js:
--------------------------------------------------------------------------------
1 | function Error(message) {}
2 | function TypeError(message) {}
3 | function RangeError(message) {}
4 |
--------------------------------------------------------------------------------
/tools/opcodes-md-template.js:
--------------------------------------------------------------------------------
1 | var types = require("../src/types"),
2 | stmt = require("../src/stmt/");
3 |
4 | var classes = {
5 | "Stmt": [ypes.Stmt, types.StmtWithImm, stmt.Stmt],
6 | "Expr": [types.I32, types.I32WithImm, stmt.ExprI32],
7 | "Expr": [types.F32, types.F32WithImm, stmt.ExprF32],
8 | "Expr": [types.F64, types.F64WithImm, stmt.ExprF64],
9 | "Expr": [types.Void, null, stmt.ExprVoid],
10 | "SwitchCase": [types.SwitchCase, null, stmt.SwitchCase]
11 | };
12 |
13 | var md = [];
14 |
15 | function escapeHtml(s) {
16 | return s.replace(//g, ">")
18 | .replace(/"/g, """);
19 | }
20 |
21 | function codeTemplate(md, name, code, withImm, ctor) {
22 | md.push("| **", escapeHtml(name), "** | ", code.toString(10), " | ");
23 | var behavior = ctor.determineBehavior(code, withImm);
24 | md.push(escapeHtml(behavior.name), " | ", escapeHtml(behavior.description), "\n");
25 | }
26 |
27 | Object.keys(classes).forEach(function (name) {
28 | md.push(escapeHtml(name), "\n-----\n\n");
29 | var ctor = classes[name][2];
30 | if (classes[name][0]) {
31 | md.push("### Opcode without Imm\n\n");
32 | md.push("| Name | Code | Behavior | Description\n");
33 | md.push("|------|------|----------|-------------\n");
34 | Object.keys(classes[name][0]).forEach(function (codeName) {
35 | codeTemplate(md, codeName, classes[name][0][codeName], false, ctor);
36 | });
37 | md.push("\n");
38 | }
39 | if (classes[name][1]) {
40 | md.push("### Opcode with Imm\n\n");
41 | md.push("| Name | Code | Behavior | Description\n");
42 | md.push("|------|------|----------|-------------\n");
43 | Object.keys(classes[name][1]).forEach(function (codeName) {
44 | codeTemplate(md, codeName, classes[name][1][codeName], true, ctor);
45 | });
46 | md.push("\n");
47 | }
48 | });
49 |
50 | process.stdout.write(md.join(""), "utf8");
51 |
--------------------------------------------------------------------------------