diff --git a/bin/asinit b/bin/asinit
index 5e2a18d736..62822ea573 100755
--- a/bin/asinit
+++ b/bin/asinit
@@ -53,7 +53,7 @@ console.log([
" TypeScript configuration inheriting recommended AssemblyScript settings.",
"",
colors.cyan(" ./assembly/index.ts"),
- " Exemplary entry file being compiled to WebAssembly to get you started.",
+ " Example entry file being compiled to WebAssembly to get you started.",
"",
colors.cyan(" ./build"),
" Build artifact directory where compiled WebAssembly files are stored.",
@@ -65,7 +65,7 @@ console.log([
" Main file loading the WebAssembly module and exporting its exports.",
"",
colors.cyan(" ./tests/index.js"),
- " Exemplary test to check that your module is indeed working.",
+ " Example test to check that your module is indeed working.",
"",
colors.cyan(" ./package.json"),
" Package info containing the necessary commands to compile to WebAssembly.",
@@ -122,7 +122,7 @@ rl.question(colors.white("Do you want to proceed?") + " [Y/n] ", answer => {
" ^ The optimized WebAssembly module using default optimization settings.",
" You can change the optimization settings in '" + colors.cyan("package.json")+ "'.",
"",
- "To run the exemplary tests, do:",
+ "To run the tests, do:",
"",
colors.white(" npm test"),
"",
diff --git a/lib/loader/README.md b/lib/loader/README.md
index fc4a87abd6..81c622af26 100644
--- a/lib/loader/README.md
+++ b/lib/loader/README.md
@@ -43,35 +43,25 @@ Besides demangling classes exported from your entry file to a handy object struc
```
* **__getString**(ptr: `number`): `string`
- Reads (copies) the value of a string from the module's memory.
+ Copies a string's value from the module's memory.
```ts
var str = module.__getString(ptr);
...
```
-* **__allocArray**(id: `number`, values: `number[]`): `number`
- Allocates a new array in the module's memory and returns a reference (pointer) to it.
- Automatically retains interior pointers. The `id` is the unique runtime id of the respective array class. If you are using `Int32Array` for example, the best way to know the id is an `export const INT32ARRAY_ID = idof()`. When done with the array, make sure to release it.
-
- ```ts
- var ptr = module.__retain(module.__allocArray(module.INT32ARRAY, [1, 2, 3]));
- ...
- module.__release(ptr);
- ```
+* **__getArrayBuffer**(ptr: `number`): `ArrayBuffer`
+ Copies an ArrayBuffer's value from the module's memory.
* **__getArray**(ptr: `number`): `number[]`
- Reads (copies) the values of an array from the module's memory.
+ Copies an array's values from the module's memory. Infers the array type from RTTI.
```ts
var arr = module.__getArray(ptr);
...
```
-* **__getArrayView**(ptr: `number`): `TypedArray`
- Gets a view on the values of an array in the module's memory. This differs from `__getArray` in that the data isn't copied but remains *live* in both directions. That's faster but also unsafe because if the array grows or becomes released, the view will no longer represent the correct memory region and modifying its values in this state will most likely corrupt memory. Use, but use with care.
-
- If the type of the array is known beforehand, the following even faster and even more unsafe helpers can be used that don't do any type checking:
+ If the type of the array is known beforehand, the following slightly faster helpers that don't infer the type can be used:
**__getInt8Array**(ptr: `number`): `Int8Array`
**__getUint8Array**(ptr: `number`): `Uint8Array`
@@ -85,8 +75,24 @@ Besides demangling classes exported from your entry file to a handy object struc
**__getFloat32Array**(ptr: `number`): `Float32Array`
**__getFloat64Array**(ptr: `number`): `Float64Array`
-* **__getArrayBuffer**(ptr: `number`): `ArrayBuffer`
- Reads (copies) the data of an ArrayBuffer from the module's memory.
+* **__getArrayView**(ptr: `number`): `TypedArray`
+ Gets a live view on the values of an array in the module's memory. Infers the array type from RTTI.
+
+ This differs from `__getArray` in that the data isn't copied but remains *live* in both directions. That's faster but also unsafe because if the array grows or becomes released, the view will no longer represent the correct memory region and modifying its values in this state will most likely corrupt memory. Use, but use with care.
+
+ If the type of the array is known beforehand, the following slightly faster helpers that don't infer the type can be used:
+
+ **__getInt8ArrayView**(ptr: `number`): `Int8Array`
+ **__getUint8ArrayView**(ptr: `number`): `Uint8Array`
+ **__getUint8ClampedArrayView**(ptr: `number`): `Uint8ClampedArray`
+ **__getInt16ArrayView**(ptr: `number`): `Int16Array`
+ **__getUint16ArrayView**(ptr: `number`): `Uint16Array`
+ **__getInt32ArrayView**(ptr: `number`): `Int32Array`
+ **__getUint32ArrayView**(ptr: `number`): `Uint32Array`
+ **__getInt64ArrayView**(ptr: `number`): `BigInt64Array`
+ **__getUint64ArrayView**(ptr: `number`): `BigUint64Array`
+ **__getFloat32ArrayView**(ptr: `number`): `Float32Array`
+ **__getFloat64ArrayView**(ptr: `number`): `Float64Array`
* **__retain**(ptr: `number`): `number`
Retains a reference to a managed object externally, making sure that it doesn't become collected prematurely. Returns the pointer.
@@ -107,6 +113,16 @@ Besides demangling classes exported from your entry file to a handy object struc
module.__release(ptr);
```
+* **__allocArray**(id: `number`, values: `number[]`): `number`
+ Allocates a new array in the module's memory and returns a reference (pointer) to it.
+ Automatically retains interior pointers. The `id` is the unique runtime id of the respective array class. If you are using `Int32Array` for example, the best way to know the id is an `export const INT32ARRAY_ID = idof()`. When done with the array, make sure to release it.
+
+ ```ts
+ var ptr = module.__retain(module.__allocArray(module.INT32ARRAY, [1, 2, 3]));
+ ...
+ module.__release(ptr);
+ ```
+
* **__instanceof**(ptr: `number`, baseId: `number`): `boolean`
Tests whether an object is an instance of the class represented by the specified base id.
diff --git a/lib/loader/index.d.ts b/lib/loader/index.d.ts
index c3dc305575..e494b13a28 100644
--- a/lib/loader/index.d.ts
+++ b/lib/loader/index.d.ts
@@ -22,66 +22,66 @@ interface ASUtil {
/** Allocates a new array in the module's memory and returns a reference (pointer) to it. */
__allocArray(id: number, values: ArrayLike): number;
- /** Reads (copies) the value of a string from the module's memory. */
+ /** Copies a string's value from the module's memory. */
__getString(ptr: number): string;
- /** Reads (copies) the values of an array from the module's memory. */
- __getArray(ptr: number): number[];
- /** Gets a view on the values of an array in the module's memory. */
- __getArrayView(ptr: number): ArrayBufferView;
+ /** Copies an ArrayBuffer's value from the module's memory. */
+ __getArrayBuffer(ptr: number): ArrayBuffer;
- /** Reads (copies) the values of Int8Array from the module's memory. */
+ /** Copies an array's values from the module's memory. Infers the array type from RTTI. */
+ __getArray(ptr: number): number[];
+ /** Copies an Int8Array's values from the module's memory. */
__getInt8Array(ptr: number): Int8Array;
- /** Reads (copies) the values of Uint8Array from the module's memory. */
+ /** Copies an Uint8Array's values from the module's memory. */
__getUint8Array(ptr: number): Uint8Array;
- /** Reads (copies) the values of Uint8Array from the module's memory. */
+ /** Copies an Uint8ClampedArray's values from the module's memory. */
__getUint8ClampedArray(ptr: number): Uint8ClampedArray;
- /** Reads (copies) the values of Int16Array from the module's memory. */
+ /** Copies an Int16Array's values from the module's memory. */
__getInt16Array(ptr: number): Int16Array;
- /** Reads (copies) the values of Uint16Array from the module's memory. */
+ /** Copies an Uint16Array's values from the module's memory. */
__getUint16Array(ptr: number): Uint16Array;
- /** Reads (copies) the values of Int32Array from the module's memory. */
+ /** Copies an Int32Array's values from the module's memory. */
__getInt32Array(ptr: number): Int32Array;
- /** Reads (copies) the values of Uint32Array from the module's memory. */
+ /** Copies an Uint32Array's values from the module's memory. */
__getUint32Array(ptr: number): Uint32Array;
- /** Reads (copies) the values of Int32Array from the module's memory. */
+ /** Copies an Int32Array's values from the module's memory. */
__getInt64Array?(ptr: number): BigInt64Array;
- /** Reads (copies) the values of Uint32Array from the module's memory. */
+ /** Copies an Uint32Array's values from the module's memory. */
__getUint64Array?(ptr: number): BigUint64Array;
- /** Reads (copies) the values of Float32Array from the module's memory. */
+ /** Copies a Float32Array's values from the module's memory. */
__getFloat32Array(ptr: number): Float32Array;
- /** Reads (copies) the values of Float64Array from the module's memory. */
+ /** Copies a Float64Array's values from the module's memory. */
__getFloat64Array(ptr: number): Float64Array;
- /** Reads the values of Int8Array from the module's memory. */
+ /** Gets a live view on an array's values in the module's memory. Infers the array type from RTTI. */
+ __getArrayView(ptr: number): ArrayBufferView;
+ /** Gets a live view on an Int8Array's values in the module's memory. */
__getInt8ArrayView(ptr: number): Int8Array;
- /** Reads the values of Uint8Array from the module's memory. */
+ /** Gets a live view on an Uint8Array's values in the module's memory. */
__getUint8ArrayView(ptr: number): Uint8Array;
- /** Reads the values of Uint8Array from the module's memory. */
+ /** Gets a live view on an Uint8ClampedArray's values in the module's memory. */
__getUint8ClampedArrayView(ptr: number): Uint8ClampedArray;
- /** Reads the values of Int16Array from the module's memory. */
+ /** Gets a live view on an Int16Array's values in the module's memory. */
__getInt16ArrayView(ptr: number): Int16Array;
- /** Reads the values of Uint16Array from the module's memory. */
+ /** Gets a live view on an Uint16Array's values in the module's memory. */
__getUint16ArrayView(ptr: number): Uint16Array;
- /** Reads the values of Int32Array from the module's memory. */
+ /** Gets a live view on an Int32Array's values in the module's memory. */
__getInt32ArrayView(ptr: number): Int32Array;
- /** Reads the values of Uint32Array from the module's memory. */
+ /** Gets a live view on an Uint32Array's values in the module's memory. */
__getUint32ArrayView(ptr: number): Uint32Array;
- /** Reads the values of Int32Array from the module's memory. */
+ /** Gets a live view on an Int32Array's values in the module's memory. */
__getInt64ArrayView?(ptr: number): BigInt64Array;
- /** Reads the values of Uint32Array from the module's memory. */
+ /** Gets a live view on an Uint32Array's values in the module's memory. */
__getUint64ArrayView?(ptr: number): BigUint64Array;
- /** Reads the values of Float32Array from the module's memory. */
+ /** Gets a live view on a Float32Array's values in the module's memory. */
__getFloat32ArrayView(ptr: number): Float32Array;
- /** Reads the values of Float64Array from the module's memory. */
+ /** Gets a live view on a Float64Array's values in the module's memory. */
__getFloat64ArrayView(ptr: number): Float64Array;
- /** Reads (copies) the data of an ArrayBuffer from the module's memory. */
- __getArrayBuffer(ptr: number): ArrayBuffer;
/** Retains a reference to a managed object externally, making sure that it doesn't become collected prematurely. Returns the pointer. */
__retain(ptr: number): number;
/** Releases a previously retained reference to a managed object, allowing the runtime to collect it once its reference count reaches zero. */
__release(ptr: number): void;
- /** Resets base pointer to initial offset. Uses only for stub runtime. */
+ /** Forcefully resets the heap to its initial offset, effectively clearing dynamic memory. Stub runtime only. */
__reset?(): void;
/** Allocates an instance of the class represented by the specified id. */
__alloc(size: number, id: number): number;
diff --git a/lib/loader/index.js b/lib/loader/index.js
index 7c797fe1db..f2e53d8212 100644
--- a/lib/loader/index.js
+++ b/lib/loader/index.js
@@ -180,7 +180,7 @@ function postInstantiate(baseModule, instance) {
baseModule.__allocArray = __allocArray;
- /** Gets a view on the values of an array in the module's memory. */
+ /** Gets a live view on an array's values in the module's memory. Infers the array type from RTTI. */
function __getArrayView(arr) {
const U32 = new Uint32Array(memory.buffer);
const id = U32[arr + ID_OFFSET >>> 2];
@@ -197,7 +197,7 @@ function postInstantiate(baseModule, instance) {
baseModule.__getArrayView = __getArrayView;
- /** Reads (copies) the values of an array from the module's memory. */
+ /** Copies an array's values from the module's memory. Infers the array type from RTTI. */
function __getArray(arr) {
const input = __getArrayView(arr);
const len = input.length;
@@ -208,7 +208,7 @@ function postInstantiate(baseModule, instance) {
baseModule.__getArray = __getArray;
- /** Reads (copies) the data of an ArrayBuffer from the module's memory. */
+ /** Copies an ArrayBuffer's value from the module's memory. */
function __getArrayBuffer(ptr) {
const buffer = memory.buffer;
const length = new Uint32Array(buffer)[ptr + SIZE_OFFSET >>> 2];
@@ -217,6 +217,12 @@ function postInstantiate(baseModule, instance) {
baseModule.__getArrayBuffer = __getArrayBuffer;
+ /** Copies a typed array's values from the module's memory. */
+ function getTypedArray(Type, alignLog2, ptr) {
+ return new Type(getTypedArrayView(Type, alignLog2, ptr));
+ }
+
+ /** Gets a live view on a typed array's values in the module's memory. */
function getTypedArrayView(Type, alignLog2, ptr) {
const buffer = memory.buffer;
const U32 = new Uint32Array(buffer);
@@ -224,43 +230,28 @@ function postInstantiate(baseModule, instance) {
return new Type(buffer, bufPtr, U32[bufPtr + SIZE_OFFSET >>> 2] >>> alignLog2);
}
- function getTypedArray(Type, alignLog2, ptr) {
- return new Type(getTypedArrayView(Type, alignLog2, ptr));
- }
-
- /** Gets a view on the values of a known-to-be Int8Array in the module's memory. */
baseModule.__getInt8Array = getTypedArray.bind(null, Int8Array, 0);
baseModule.__getInt8ArrayView = getTypedArrayView.bind(null, Int8Array, 0);
- /** Gets a view on the values of a known-to-be Uint8Array in the module's memory. */
baseModule.__getUint8Array = getTypedArray.bind(null, Uint8Array, 0);
baseModule.__getUint8ArrayView = getTypedArrayView.bind(null, Uint8Array, 0);
- /** Gets a view on the values of a known-to-be Uint8ClampedArray in the module's memory. */
baseModule.__getUint8ClampedArray = getTypedArray.bind(null, Uint8ClampedArray, 0);
baseModule.__getUint8ClampedArrayView = getTypedArrayView.bind(null, Uint8ClampedArray, 0);
- /** Gets a view on the values of a known-to-be Int16Array in the module's memory. */
baseModule.__getInt16Array = getTypedArray.bind(null, Int16Array, 1);
baseModule.__getInt16ArrayView = getTypedArrayView.bind(null, Int16Array, 1);
- /** Gets a view on the values of a known-to-be Uint16Array in the module's memory. */
baseModule.__getUint16Array = getTypedArray.bind(null, Uint16Array, 1);
baseModule.__getUint16ArrayView = getTypedArrayView.bind(null, Uint16Array, 1);
- /** Gets a view on the values of a known-to-be Int32Array in the module's memory. */
baseModule.__getInt32Array = getTypedArray.bind(null, Int32Array, 2);
baseModule.__getInt32ArrayView = getTypedArrayView.bind(null, Int32Array, 2);
- /** Gets a view on the values of a known-to-be Uint32Array in the module's memory. */
baseModule.__getUint32Array = getTypedArray.bind(null, Uint32Array, 2);
baseModule.__getUint32ArrayView = getTypedArrayView.bind(null, Uint32Array, 2);
if (BIGINT) {
- /** Gets a view on the values of a known-to-be-Int64Array in the module's memory. */
baseModule.__getInt64Array = getTypedArray.bind(null, BigInt64Array, 3);
baseModule.__getInt64ArrayView = getTypedArrayView.bind(null, BigInt64Array, 3);
- /** Gets a view on the values of a known-to-be-Uint64Array in the module's memory. */
baseModule.__getUint64Array = getTypedArray.bind(null, BigUint64Array, 3);
baseModule.__getUint64ArrayView = getTypedArrayView.bind(null, BigUint64Array, 3);
}
- /** Gets a view on the values of a known-to-be Float32Array in the module's memory. */
baseModule.__getFloat32Array = getTypedArray.bind(null, Float32Array, 2);
baseModule.__getFloat32ArrayView = getTypedArrayView.bind(null, Float32Array, 2);
- /** Gets a view on the values of a known-to-be Float64Array in the module's memory. */
baseModule.__getFloat64Array = getTypedArray.bind(null, Float64Array, 3);
baseModule.__getFloat64ArrayView = getTypedArrayView.bind(null, Float64Array, 3);
@@ -286,9 +277,9 @@ function postInstantiate(baseModule, instance) {
}
/** Wraps a WebAssembly function while also taking care of variable arguments. */
-function wrapFunction(fn, setargc) {
+function wrapFunction(fn, argumentsLength) {
var wrap = (...args) => {
- setargc(args.length);
+ if (argumentsLength) argumentsLength.value = args.length;
return fn(...args);
}
wrap.original = fn;
@@ -351,7 +342,7 @@ exports.instantiateStreaming = instantiateStreaming;
/** Demangles an AssemblyScript module's exports to a friendly object structure. */
function demangle(exports, baseModule) {
var module = baseModule ? Object.create(baseModule) : {};
- var setargc = exports["__setargc"] || function() {};
+ var argumentsLength = exports["__argumentsLength"];
function hasOwnProperty(elem, prop) {
return Object.prototype.hasOwnProperty.call(elem, prop);
}
@@ -401,11 +392,11 @@ function demangle(exports, baseModule) {
}
} else {
if (name === 'constructor') {
- curr[name] = wrapFunction(elem, setargc);
+ curr[name] = wrapFunction(elem, argumentsLength);
} else { // for methods
Object.defineProperty(curr, name, {
value: function (...args) {
- setargc(args.length);
+ if (argumentsLength) argumentsLength.value = args.length;
return elem(this[THIS], ...args);
}
});
@@ -421,7 +412,7 @@ function demangle(exports, baseModule) {
});
}
} else if (typeof elem === "function") {
- curr[name] = wrapFunction(elem, setargc);
+ curr[name] = wrapFunction(elem, argumentsLength);
} else {
curr[name] = elem;
}
diff --git a/lib/loader/tests/build/untouched.wasm b/lib/loader/tests/build/untouched.wasm
index d3f681bdec..58959a23f5 100644
Binary files a/lib/loader/tests/build/untouched.wasm and b/lib/loader/tests/build/untouched.wasm differ
diff --git a/src/ast.ts b/src/ast.ts
index 2980df67b7..5fd69274c8 100644
--- a/src/ast.ts
+++ b/src/ast.ts
@@ -5,7 +5,6 @@
import {
CommonFlags,
- CommonSymbols,
PATH_DELIMITER,
LIBRARY_PREFIX,
LIBRARY_SUBST
@@ -13,7 +12,6 @@ import {
import {
Token,
- Tokenizer,
Range
} from "./tokenizer";
@@ -249,8 +247,7 @@ export abstract class Node {
): IdentifierExpression {
var expr = new IdentifierExpression();
expr.range = range;
- expr.text = name; // TODO: extract from range
- expr.symbol = name; // TODO: Symbol.for(name)
+ expr.text = name;
expr.isQuoted = isQuoted;
return expr;
}
@@ -1292,8 +1289,6 @@ export class IdentifierExpression extends Expression {
/** Textual name. */
text: string;
- /** Symbol. */
- symbol: string; // TODO: symbol
/** Whether quoted or not. */
isQuoted: bool;
}
@@ -1418,7 +1413,6 @@ export class CommaExpression extends Expression {
export class ConstructorExpression extends IdentifierExpression {
kind = NodeKind.CONSTRUCTOR;
text = "constructor";
- symbol = CommonSymbols.constructor;
}
/** Represents an element access expression, e.g., array access. */
@@ -1501,7 +1495,6 @@ export class NewExpression extends Expression {
export class NullExpression extends IdentifierExpression {
kind = NodeKind.NULL;
text = "null";
- symbol = CommonSymbols.null_;
}
/** Represents an object literal expression. */
@@ -1566,28 +1559,24 @@ export class StringLiteralExpression extends LiteralExpression {
export class SuperExpression extends IdentifierExpression {
kind = NodeKind.SUPER;
text = "super";
- symbol = CommonSymbols.super_;
}
/** Represents a `this` expression. */
export class ThisExpression extends IdentifierExpression {
kind = NodeKind.THIS;
text = "this";
- symbol = CommonSymbols.this_;
}
/** Represents a `true` expression. */
export class TrueExpression extends IdentifierExpression {
kind = NodeKind.TRUE;
text = "true";
- symbol = CommonSymbols.true_;
}
/** Represents a `false` expression. */
export class FalseExpression extends IdentifierExpression {
kind = NodeKind.FALSE;
text = "false";
- symbol = CommonSymbols.false_;
}
/** Base class of all unary expressions. */
diff --git a/src/binary.ts b/src/binary.ts
deleted file mode 100644
index 43ac0e0543..0000000000
--- a/src/binary.ts
+++ /dev/null
@@ -1,301 +0,0 @@
-/**
- * Binary format utilities.
- * @module binary
- *//***/
-
-// TBD: Moving lib/parse here might make sense where the compiler has to evaluate WASM binaries on
-// the fly, like when importing other WASM files through `import`. Module integration hasn't been
-// specified, yet, though, and it somewhat conflicts with our dependency on Binaryen.
-
-/** WebAssembly section ids. */
-export enum SectionId {
- /** A custom section with an explicit name. */
- Custom = 0,
- /** Function types section. */
- Type = 1,
- /** Imports section. */
- Import = 2,
- /** Functions section. */
- Function = 3,
- /** Tables section. */
- Table = 4,
- /** Memories section. */
- Memory = 5,
- /** Globals section. */
- Global = 6,
- /** Exports section. */
- Export = 7,
- /** Start function section. */
- Start = 8,
- /** Table element section. */
- Element = 9,
- /** Function code section. */
- Code = 10,
- /** Memory segments section. */
- Data = 11
-}
-
-/** WebAssembly external kinds. */
-export enum ExternalKind {
- /** External function. */
- Function = 0,
- /** External table. */
- Table = 1,
- /** External memory. */
- Memory = 2,
- /** External global. */
- Global = 3
-}
-
-/** WebAssembly name section kinds. */
-export enum NameKind {
- /** Module name. */
- Module = 0,
- /** Function name. */
- Function = 1,
- /** Local name. */
- Local = 2,
-
- // see: https://github.com/WebAssembly/design/pull/1064
-
- /** Label name. */
- Label = 3,
- /** Function type name. */
- Type = 4,
- /** Table name. */
- Table = 5,
- /** Memory name. */
- Memory = 6,
- /** Global variable name. */
- Global = 7
-}
-
-/** WebAssembly types. */
-export enum Type {
- i32 = 0x7F,
- i64 = 0x7E,
- f32 = 0x7D,
- f64 = 0x7C,
- anyfunc = 0x70,
- func = 0x60,
- none = 0x40
-}
-
-/** WebAssembly opcodes. */
-export enum Op {
- unreachable = 0x00,
- nop = 0x01,
- block = 0x02,
- loop = 0x03,
- if_ = 0x04,
- else_ = 0x05,
- end = 0x0B,
- br = 0x0C,
- br_if = 0x0D,
- br_table = 0x0E,
- return_ = 0x0F,
- call = 0x10,
- call_indirect = 0x11,
- drop = 0x1A,
- select = 0x1B,
- get_local = 0x20,
- set_local = 0x21,
- tee_local = 0x22,
- get_global = 0x23,
- set_global = 0x24,
- i32_load = 0x28,
- i64_load = 0x29,
- f32_load = 0x2A,
- f64_load = 0x2B,
- i32_load8_s = 0x2C,
- i32_load8_u = 0x2D,
- i32_load16_s = 0x2E,
- i32_load16_u = 0x2F,
- i64_load8_s = 0x30,
- i64_load8_u = 0x31,
- i64_load16_s = 0x32,
- i64_load16_u = 0x33,
- i64_load32_s = 0x34,
- i64_load32_u = 0x35,
- i32_store = 0x36,
- i64_store = 0x37,
- f32_store = 0x38,
- f64_store = 0x39,
- i32_store8 = 0x3A,
- i32_store16 = 0x3B,
- i64_store8 = 0x3C,
- i64_store16 = 0x3D,
- i64_store32 = 0x3E,
- memory_size = 0x3F,
- memory_grow = 0x40,
- i32_const = 0x41,
- i64_const = 0x42,
- f32_const = 0x43,
- f64_const = 0x44,
- i32_eqz = 0x45,
- i32_eq = 0x46,
- i32_ne = 0x47,
- i32_lt_s = 0x48,
- i32_lt_u = 0x49,
- i32_gt_s = 0x4A,
- i32_gt_u = 0x4B,
- i32_le_s = 0x4C,
- i32_le_u = 0x4D,
- i32_ge_s = 0x4E,
- i32_ge_u = 0x4F,
- i64_eqz = 0x50,
- i64_eq = 0x51,
- i64_ne = 0x52,
- i64_lt_s = 0x53,
- i64_lt_u = 0x54,
- i64_gt_s = 0x55,
- i64_gt_u = 0x56,
- i64_le_s = 0x57,
- i64_le_u = 0x58,
- i64_ge_s = 0x59,
- i64_ge_u = 0x5A,
- f32_eq = 0x5B,
- f32_ne = 0x5C,
- f32_lt = 0x5D,
- f32_gt = 0x5E,
- f32_le = 0x5F,
- f32_ge = 0x60,
- f64_eq = 0x61,
- f64_ne = 0x62,
- f64_lt = 0x63,
- f64_gt = 0x64,
- f64_le = 0x65,
- f64_ge = 0x66,
- i32_clz = 0x67,
- i32_ctz = 0x68,
- i32_popcnt = 0x69,
- i32_add = 0x6A,
- i32_sub = 0x6B,
- i32_mul = 0x6C,
- i32_div_s = 0x6D,
- i32_div_u = 0x6E,
- i32_rem_s = 0x6F,
- i32_rem_u = 0x70,
- i32_and = 0x71,
- i32_or = 0x72,
- i32_xor = 0x73,
- i32_shl = 0x74,
- i32_shr_s = 0x75,
- i32_shr_u = 0x76,
- i32_rotl = 0x77,
- i32_rotr = 0x78,
- i64_clz = 0x79,
- i64_ctz = 0x7A,
- i64_popcnt = 0x7B,
- i64_add = 0x7C,
- i64_sub = 0x7D,
- i64_mul = 0x7E,
- i64_div_s = 0x7F,
- i64_div_u = 0x80,
- i64_rem_s = 0x81,
- i64_rem_u = 0x82,
- i64_and = 0x83,
- i64_or = 0x84,
- i64_xor = 0x85,
- i64_shl = 0x86,
- i64_shr_s = 0x87,
- i64_shr_u = 0x88,
- i64_rotl = 0x89,
- i64_rotr = 0x8A,
- f32_abs = 0x8B,
- f32_neg = 0x8C,
- f32_ceil = 0x8D,
- f32_floor = 0x8E,
- f32_trunc = 0x8F,
- f32_nearest = 0x90,
- f32_sqrt = 0x91,
- f32_add = 0x92,
- f32_sub = 0x93,
- f32_mul = 0x94,
- f32_div = 0x95,
- f32_min = 0x96,
- f32_max = 0x97,
- f32_copysign = 0x98,
- f64_abs = 0x99,
- f64_neg = 0x9A,
- f64_ceil = 0x9B,
- f64_floor = 0x9C,
- f64_trunc = 0x9D,
- f64_nearest = 0x9E,
- f64_sqrt = 0x9F,
- f64_add = 0xA0,
- f64_sub = 0xA1,
- f64_mul = 0xA2,
- f64_div = 0xA3,
- f64_min = 0xA4,
- f64_max = 0xA5,
- f64_copysign = 0xA6,
- i32_wrap_i64 = 0xA7,
- i32_trunc_s_f32 = 0xA8,
- i32_trunc_u_f32 = 0xA9,
- i32_trunc_s_f64 = 0xAA,
- i32_trunc_u_f64 = 0xAB,
- i64_extend_s_i32 = 0xAC,
- i64_extend_u_i32 = 0xAD,
- i64_trunc_s_f32 = 0xAE,
- i64_trunc_u_f32 = 0xAF,
- i64_trunc_s_f64 = 0xB0,
- i64_trunc_u_f64 = 0xB1,
- f32_convert_s_i32 = 0xB2,
- f32_convert_u_i32 = 0xB3,
- f32_convert_s_i64 = 0xB4,
- f32_convert_u_i64 = 0xB5,
- f32_demote_f64 = 0xB6,
- f64_convert_s_i32 = 0xB7,
- f64_convert_u_i32 = 0xB8,
- f64_convert_s_i64 = 0xB9,
- f64_convert_u_i64 = 0xBA,
- f64_promote_f32 = 0xBB,
- i32_reinterpret_f32 = 0xBC,
- i64_reinterpret_f64 = 0xBD,
- f32_reinterpret_i32 = 0xBE,
- f64_reinterpret_i64 = 0xBF
-}
-
-enum ReaderState {
- HEADER
-}
-
-/** WebAssembly binary reader. */
-export class Reader { // TODO
-
- /** Buffer being read. */
- private buffer: Uint8Array;
- /** Current read offset. */
- private offset: u32;
- /** Total length. */
- private length: u32;
- /** Current state. */
- private state: ReaderState;
-
- /** Constructs a new binary reader. */
- constructor(totalLength: u32, initialChunk: Uint8Array) {
- this.buffer = initialChunk;
- this.offset = 0;
- this.length = totalLength;
- this.state = ReaderState.HEADER;
- }
-
- /** Provides a chunk of data. */
- next(chunk: Uint8Array): void {
- if (!chunk.length) return;
- // var current = this.buffer;
- // var offset = this.offset;
- // var buffer = new Uint8Array((current.length - offset) + chunk.length);
- // buffer.set(current.subarray(offset), 0);
- // buffer.set(chunk, (current.length - offset));
- // this.buffer = buffer;
- // this.length -= this.offset;
- // this.offset = 0;
- unreachable();
- }
-
- finish(): void {
- unreachable();
- }
-}
diff --git a/src/builtins.ts b/src/builtins.ts
index e05fc8a075..4e98301230 100644
--- a/src/builtins.ts
+++ b/src/builtins.ts
@@ -6,8 +6,7 @@
import {
Compiler,
Constraints,
- RuntimeFeatures,
- flatten
+ RuntimeFeatures
} from "./compiler";
import {
@@ -28,8 +27,7 @@ import {
import {
Type,
TypeKind,
- TypeFlags,
- Signature
+ TypeFlags
} from "./types";
import {
@@ -93,8 +91,14 @@ import {
isPowerOf2
} from "./util";
-/** Symbols of various compiler built-ins. */
-export namespace BuiltinSymbols {
+/** Internal names of various compiler built-ins. */
+export namespace BuiltinNames {
+
+ // compiler-generated
+ export const start = "~start";
+ export const started = "~started";
+ export const argumentsLength = "~argumentsLength";
+
// std/builtins.ts
export const isInteger = "~lib/builtins/isInteger";
export const isFloat = "~lib/builtins/isFloat";
@@ -168,7 +172,6 @@ export namespace BuiltinSymbols {
export const f32 = "~lib/builtins/f32";
export const f64 = "~lib/builtins/f64";
export const v128 = "~lib/builtins/v128";
- export const void_ = "~lib/builtins/void";
export const i32_clz = "~lib/builtins/i32.clz";
export const i64_clz = "~lib/builtins/i64.clz";
@@ -548,37 +551,19 @@ export namespace BuiltinSymbols {
export const memory_grow = "~lib/memory/memory.grow";
export const memory_copy = "~lib/memory/memory.copy";
export const memory_fill = "~lib/memory/memory.fill";
- export const memory_allocate = "~lib/memory/memory.allocate";
- export const memory_free = "~lib/memory/memory.free";
- export const memory_reset = "~lib/memory/memory.reset";
-
- // std/runtime.ts
- export const runtime_instanceof = "~lib/runtime/runtime.instanceof";
- export const runtime_flags = "~lib/runtime/runtime.flags";
- export const runtime_allocate = "~lib/util/runtime/allocate";
- export const runtime_reallocate = "~lib/util/runtime/reallocate";
- export const runtime_register = "~lib/util/runtime/register";
- export const runtime_discard = "~lib/util/runtime/discard";
- export const runtime_makeArray = "~lib/util/runtime/makeArray";
// std/typedarray.ts
export const Int8Array = "~lib/typedarray/Int8Array";
export const Uint8Array = "~lib/typedarray/Uint8Array";
+ export const Uint8ClampedArray = "~lib/typedarray/Uint8ClampedArray";
export const Int16Array = "~lib/typedarray/Int16Array";
export const Uint16Array = "~lib/typedarray/Uint16Array";
export const Int32Array = "~lib/typedarray/Int32Array";
export const Uint32Array = "~lib/typedarray/Uint32Array";
export const Int64Array = "~lib/typedarray/Int64Array";
export const Uint64Array = "~lib/typedarray/Uint64Array";
- export const Uint8ClampedArray = "~lib/typedarray/Uint8ClampedArray";
export const Float32Array = "~lib/typedarray/Float32Array";
export const Float64Array = "~lib/typedarray/Float64Array";
-
- // compiler generated
- export const started = "~lib/started";
- export const argc = "~lib/argc";
- export const setargc = "~lib/setargc";
- export const capabilities = "~lib/capabilities";
}
/** Compiles a call to a built-in function. */
@@ -604,7 +589,7 @@ export function compileCall(
// === Static type evaluation =================================================================
- case BuiltinSymbols.isInteger: { // isInteger() / isInteger(value: T) -> bool
+ case BuiltinNames.isInteger: { // isInteger() / isInteger(value: T) -> bool
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
compiler.currentType = Type.bool;
if (!type) return module.unreachable();
@@ -612,7 +597,7 @@ export function compileCall(
? module.i32(1)
: module.i32(0);
}
- case BuiltinSymbols.isFloat: { // isFloat() / isFloat(value: T) -> bool
+ case BuiltinNames.isFloat: { // isFloat() / isFloat(value: T) -> bool
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
compiler.currentType = Type.bool;
if (!type) return module.unreachable();
@@ -620,7 +605,7 @@ export function compileCall(
? module.i32(1)
: module.i32(0);
}
- case BuiltinSymbols.isBoolean: { // isBoolean() / isBoolean(value: T) -> bool
+ case BuiltinNames.isBoolean: { // isBoolean() / isBoolean(value: T) -> bool
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
compiler.currentType = Type.bool;
if (!type) return module.unreachable();
@@ -628,7 +613,7 @@ export function compileCall(
? module.i32(1)
: module.i32(0);
}
- case BuiltinSymbols.isSigned: { // isSigned() / isSigned(value: T) -> bool
+ case BuiltinNames.isSigned: { // isSigned() / isSigned(value: T) -> bool
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
compiler.currentType = Type.bool;
if (!type) return module.unreachable();
@@ -636,7 +621,7 @@ export function compileCall(
? module.i32(1)
: module.i32(0);
}
- case BuiltinSymbols.isReference: { // isReference() / isReference(value: T) -> bool
+ case BuiltinNames.isReference: { // isReference() / isReference(value: T) -> bool
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
compiler.currentType = Type.bool;
if (!type) return module.unreachable();
@@ -644,7 +629,7 @@ export function compileCall(
? module.i32(1)
: module.i32(0);
}
- case BuiltinSymbols.isString: { // isString() / isString(value: T) -> bool
+ case BuiltinNames.isString: { // isString() / isString(value: T) -> bool
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
compiler.currentType = Type.bool;
if (!type) return module.unreachable();
@@ -657,7 +642,7 @@ export function compileCall(
}
return module.i32(0);
}
- case BuiltinSymbols.isArray: { // isArray() / isArray(value: T) -> bool
+ case BuiltinNames.isArray: { // isArray() / isArray(value: T) -> bool
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
compiler.currentType = Type.bool;
if (!type) return module.unreachable();
@@ -669,7 +654,7 @@ export function compileCall(
}
return module.i32(0);
}
- case BuiltinSymbols.isArrayLike: { // isArrayLike() / isArrayLike(value: T) -> bool
+ case BuiltinNames.isArrayLike: { // isArrayLike() / isArrayLike(value: T) -> bool
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
compiler.currentType = Type.bool;
if (!type) return module.unreachable();
@@ -681,19 +666,19 @@ export function compileCall(
}
return module.i32(0);
}
- case BuiltinSymbols.isFunction: { // isFunction / isFunction(value: T) -> bool
+ case BuiltinNames.isFunction: { // isFunction / isFunction(value: T) -> bool
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
compiler.currentType = Type.bool;
if (!type) return module.unreachable();
return module.i32(type.signatureReference ? 1 : 0);
}
- case BuiltinSymbols.isNullable: { // isNullable / isNullable(value: T) -> bool
+ case BuiltinNames.isNullable: { // isNullable / isNullable(value: T) -> bool
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
compiler.currentType = Type.bool;
if (!type) return module.unreachable();
return module.i32(type.is(TypeFlags.NULLABLE) ? 1 : 0);
}
- case BuiltinSymbols.isDefined: { // isDefined(expression) -> bool
+ case BuiltinNames.isDefined: { // isDefined(expression) -> bool
compiler.currentType = Type.bool;
if (
checkTypeAbsent(typeArguments, reportNode, prototype) |
@@ -707,7 +692,7 @@ export function compileCall(
);
return module.i32(element ? 1 : 0);
}
- case BuiltinSymbols.isConstant: { // isConstant(expression) -> bool
+ case BuiltinNames.isConstant: { // isConstant(expression) -> bool
compiler.currentType = Type.bool;
if (
checkTypeAbsent(typeArguments, reportNode, prototype) |
@@ -717,19 +702,19 @@ export function compileCall(
compiler.currentType = Type.bool;
return module.i32(getExpressionId(expr) == ExpressionId.Const ? 1 : 0);
}
- case BuiltinSymbols.isManaged: { // isManaged() -> bool
+ case BuiltinNames.isManaged: { // isManaged() -> bool
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
compiler.currentType = Type.bool;
if (!type) return module.unreachable();
return module.i32(type.isManaged ? 1 : 0);
}
- case BuiltinSymbols.isVoid: { // isVoid() -> bool
+ case BuiltinNames.isVoid: { // isVoid() -> bool
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
compiler.currentType = Type.bool;
if (!type) return module.unreachable();
return module.i32(type.kind == TypeKind.VOID ? 1 : 0);
}
- case BuiltinSymbols.lengthof: { // lengthof() -> i32
+ case BuiltinNames.lengthof: { // lengthof() -> i32
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
compiler.currentType = Type.i32;
if (!type) return module.unreachable();
@@ -743,7 +728,7 @@ export function compileCall(
}
return module.i32(signatureReference.parameterTypes.length);
}
- case BuiltinSymbols.sizeof: { // sizeof() -> usize
+ case BuiltinNames.sizeof: { // sizeof() -> usize
compiler.currentType = compiler.options.usizeType;
if (
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -774,7 +759,7 @@ export function compileCall(
return module.i32(byteSize);
}
}
- case BuiltinSymbols.alignof: { // alignof() -> usize
+ case BuiltinNames.alignof: { // alignof() -> usize
compiler.currentType = compiler.options.usizeType;
if (
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -806,7 +791,7 @@ export function compileCall(
return module.i32(alignLog2);
}
}
- case BuiltinSymbols.offsetof: { // offsetof(fieldName?: string) -> usize
+ case BuiltinNames.offsetof: { // offsetof(fieldName?: string) -> usize
compiler.currentType = compiler.options.usizeType;
if (
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -871,7 +856,7 @@ export function compileCall(
return module.i32(offset);
}
}
- case BuiltinSymbols.nameof: {
+ case BuiltinNames.nameof: {
let resultType = evaluateConstantType(compiler, typeArguments, operands, reportNode);
if (!resultType) {
compiler.currentType = compiler.program.stringInstance.type;
@@ -916,7 +901,7 @@ export function compileCall(
// === Math ===================================================================================
- case BuiltinSymbols.clz: { // clz(value: T) -> T
+ case BuiltinNames.clz: { // clz(value: T) -> T
if (
checkTypeOptional(typeArguments, reportNode, compiler, true) |
checkArgsRequired(operands, 1, reportNode, compiler)
@@ -953,7 +938,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.ctz: { // ctz(value: T) -> T
+ case BuiltinNames.ctz: { // ctz(value: T) -> T
if (
checkTypeOptional(typeArguments, reportNode, compiler, true) |
checkArgsRequired(operands, 1, reportNode, compiler)
@@ -990,7 +975,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.popcnt: { // popcnt(value: T) -> T
+ case BuiltinNames.popcnt: { // popcnt(value: T) -> T
if (
checkTypeOptional(typeArguments, reportNode, compiler, true) |
checkArgsRequired(operands, 1, reportNode, compiler)
@@ -1027,7 +1012,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.rotl: { // rotl(value: T, shift: T) -> T
+ case BuiltinNames.rotl: { // rotl(value: T, shift: T) -> T
if (
checkTypeOptional(typeArguments, reportNode, compiler, true) |
checkArgsRequired(operands, 2, reportNode, compiler)
@@ -1070,7 +1055,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.rotr: { // rotr(value: T, shift: T) -> T
+ case BuiltinNames.rotr: { // rotr(value: T, shift: T) -> T
if (
checkTypeOptional(typeArguments, reportNode, compiler, true) |
checkArgsRequired(operands, 2, reportNode, compiler)
@@ -1113,7 +1098,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.abs: { // abs(value: T) -> T
+ case BuiltinNames.abs: { // abs(value: T) -> T
if (
checkTypeOptional(typeArguments, reportNode, compiler, true) |
checkArgsRequired(operands, 1, reportNode, compiler)
@@ -1213,7 +1198,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.max: { // max(left: T, right: T) -> T
+ case BuiltinNames.max: { // max(left: T, right: T) -> T
if (
checkTypeOptional(typeArguments, reportNode, compiler, true) |
checkArgsRequired(operands, 2, reportNode, compiler)
@@ -1285,7 +1270,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.min: { // min(left: T, right: T) -> T
+ case BuiltinNames.min: { // min(left: T, right: T) -> T
if (
checkTypeOptional(typeArguments, reportNode, compiler, true) |
checkArgsRequired(operands, 2, reportNode, compiler)
@@ -1357,7 +1342,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.ceil: { // ceil(value: T) -> T
+ case BuiltinNames.ceil: { // ceil(value: T) -> T
if (
checkTypeOptional(typeArguments, reportNode, compiler, true) |
checkArgsRequired(operands, 1, reportNode, compiler)
@@ -1389,7 +1374,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.floor: { // floor(value: T) -> T
+ case BuiltinNames.floor: { // floor(value: T) -> T
if (
checkTypeOptional(typeArguments, reportNode, compiler, true) |
checkArgsRequired(operands, 1, reportNode, compiler)
@@ -1421,7 +1406,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.copysign: { // copysign(left: T, right: T) -> T
+ case BuiltinNames.copysign: { // copysign(left: T, right: T) -> T
if (
checkTypeOptional(typeArguments, reportNode, compiler, true) |
checkArgsRequired(operands, 2, reportNode, compiler)
@@ -1444,7 +1429,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.nearest: { // nearest(value: T) -> T
+ case BuiltinNames.nearest: { // nearest(value: T) -> T
if (
checkTypeOptional(typeArguments, reportNode, compiler, true) |
checkArgsRequired(operands, 1, reportNode, compiler)
@@ -1476,7 +1461,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.reinterpret: { // reinterpret(value: *) -> T
+ case BuiltinNames.reinterpret: { // reinterpret(value: *) -> T
if (
checkTypeRequired(typeArguments, reportNode, compiler, true) |
checkArgsRequired(operands, 1, reportNode, compiler)
@@ -1530,7 +1515,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.sqrt: { // sqrt(value: T) -> T
+ case BuiltinNames.sqrt: { // sqrt(value: T) -> T
if (
checkTypeOptional(typeArguments, reportNode, compiler, true) |
checkArgsRequired(operands, 1, reportNode, compiler)
@@ -1552,7 +1537,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.trunc: { // trunc(value: T) -> T
+ case BuiltinNames.trunc: { // trunc(value: T) -> T
if (
checkTypeOptional(typeArguments, reportNode, compiler, true) |
checkArgsRequired(operands, 1, reportNode, compiler)
@@ -1587,7 +1572,7 @@ export function compileCall(
// === Memory access ==========================================================================
- case BuiltinSymbols.load: { // load(offset: usize, immOffset?: usize, immAlign?: usize) -> T*
+ case BuiltinNames.load: { // load(offset: usize, immOffset?: usize, immAlign?: usize) -> T*
if (
checkTypeRequired(typeArguments, reportNode, compiler, true) |
checkArgsOptional(operands, 1, 3, reportNode, compiler)
@@ -1643,7 +1628,7 @@ export function compileCall(
immAlign
);
}
- case BuiltinSymbols.store: { // store(offset: usize, value: T*, offset?: usize, align?: usize) -> void
+ case BuiltinNames.store: { // store(offset: usize, value: T*, offset?: usize, align?: usize) -> void
compiler.currentType = Type.void;
if (
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -1716,7 +1701,7 @@ export function compileCall(
// === Atomics ================================================================================
- case BuiltinSymbols.atomic_load: { // load(offset: usize, immOffset?: usize) -> T*
+ case BuiltinNames.atomic_load: { // load(offset: usize, immOffset?: usize) -> T*
if (
checkFeatureEnabled(Feature.THREADS, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler, true) |
@@ -1750,7 +1735,7 @@ export function compileCall(
immOffset
);
}
- case BuiltinSymbols.atomic_store: { // store(offset: usize, value: T*, immOffset?: usize) -> void
+ case BuiltinNames.atomic_store: { // store(offset: usize, value: T*, immOffset?: usize) -> void
if (
checkFeatureEnabled(Feature.THREADS, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -1802,12 +1787,12 @@ export function compileCall(
compiler.currentType = Type.void;
return module.atomic_store(type.byteSize, arg0, arg1, inType.toNativeType(), immOffset);
}
- case BuiltinSymbols.atomic_add: // any_atomic_binary(ptr, value: T, immOffset?: usize) -> T
- case BuiltinSymbols.atomic_sub:
- case BuiltinSymbols.atomic_and:
- case BuiltinSymbols.atomic_or:
- case BuiltinSymbols.atomic_xor:
- case BuiltinSymbols.atomic_xchg: {
+ case BuiltinNames.atomic_add: // any_atomic_binary(ptr, value: T, immOffset?: usize) -> T
+ case BuiltinNames.atomic_sub:
+ case BuiltinNames.atomic_and:
+ case BuiltinNames.atomic_or:
+ case BuiltinNames.atomic_xor:
+ case BuiltinNames.atomic_xchg: {
if (
checkFeatureEnabled(Feature.THREADS, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler, true) |
@@ -1818,12 +1803,12 @@ export function compileCall(
let opName: string;
switch (prototype.internalName) {
default: assert(false);
- case BuiltinSymbols.atomic_add: { opName = "atomic.add"; break; }
- case BuiltinSymbols.atomic_sub: { opName = "atomic.sub"; break; }
- case BuiltinSymbols.atomic_and: { opName = "atomic.and"; break; }
- case BuiltinSymbols.atomic_or: { opName = "atomic.or"; break; }
- case BuiltinSymbols.atomic_xor: { opName = "atomic.xor"; break; }
- case BuiltinSymbols.atomic_xchg: { opName = "atomic.xchg"; break; }
+ case BuiltinNames.atomic_add: { opName = "atomic.add"; break; }
+ case BuiltinNames.atomic_sub: { opName = "atomic.sub"; break; }
+ case BuiltinNames.atomic_and: { opName = "atomic.and"; break; }
+ case BuiltinNames.atomic_or: { opName = "atomic.or"; break; }
+ case BuiltinNames.atomic_xor: { opName = "atomic.xor"; break; }
+ case BuiltinNames.atomic_xchg: { opName = "atomic.xchg"; break; }
}
compiler.error(
DiagnosticCode.Operation_0_cannot_be_applied_to_type_1,
@@ -1870,17 +1855,17 @@ export function compileCall(
let op: AtomicRMWOp;
switch (prototype.internalName) {
default: assert(false);
- case BuiltinSymbols.atomic_add: { op = AtomicRMWOp.Add; break; }
- case BuiltinSymbols.atomic_sub: { op = AtomicRMWOp.Sub; break; }
- case BuiltinSymbols.atomic_and: { op = AtomicRMWOp.And; break; }
- case BuiltinSymbols.atomic_or: { op = AtomicRMWOp.Or; break; }
- case BuiltinSymbols.atomic_xor: { op = AtomicRMWOp.Xor; break; }
- case BuiltinSymbols.atomic_xchg: { op = AtomicRMWOp.Xchg; break; }
+ case BuiltinNames.atomic_add: { op = AtomicRMWOp.Add; break; }
+ case BuiltinNames.atomic_sub: { op = AtomicRMWOp.Sub; break; }
+ case BuiltinNames.atomic_and: { op = AtomicRMWOp.And; break; }
+ case BuiltinNames.atomic_or: { op = AtomicRMWOp.Or; break; }
+ case BuiltinNames.atomic_xor: { op = AtomicRMWOp.Xor; break; }
+ case BuiltinNames.atomic_xchg: { op = AtomicRMWOp.Xchg; break; }
}
compiler.currentType = inType;
return module.atomic_rmw(op, type.byteSize, immOffset, arg0, arg1, inType.toNativeType());
}
- case BuiltinSymbols.atomic_cmpxchg: { // cmpxchg(ptr: usize, expected: T, replacement: T, off?: usize) -> T
+ case BuiltinNames.atomic_cmpxchg: { // cmpxchg(ptr: usize, expected: T, replacement: T, off?: usize) -> T
if (
checkFeatureEnabled(Feature.THREADS, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler, true) |
@@ -1942,7 +1927,7 @@ export function compileCall(
compiler.currentType = inType;
return module.atomic_cmpxchg(type.byteSize, immOffset, arg0, arg1, arg2, inType.toNativeType());
}
- case BuiltinSymbols.atomic_wait: { // wait(ptr: usize, expected: T, timeout: i64) -> i32
+ case BuiltinNames.atomic_wait: { // wait(ptr: usize, expected: T, timeout: i64) -> i32
if (
checkFeatureEnabled(Feature.THREADS, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -1970,7 +1955,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.atomic_notify: { // notify(ptr: usize, count: i32) -> i32
+ case BuiltinNames.atomic_notify: { // notify(ptr: usize, count: i32) -> i32
if (
checkFeatureEnabled(Feature.THREADS, reportNode, compiler) |
checkTypeAbsent(typeArguments, reportNode, prototype) |
@@ -1984,7 +1969,7 @@ export function compileCall(
compiler.currentType = Type.i32;
return module.atomic_notify(arg0, arg1);
}
- case BuiltinSymbols.atomic_fence: { // fence() -> void
+ case BuiltinNames.atomic_fence: { // fence() -> void
compiler.currentType = Type.void;
if (
checkFeatureEnabled(Feature.THREADS, reportNode, compiler) |
@@ -1996,7 +1981,7 @@ export function compileCall(
// === Control flow ===========================================================================
- case BuiltinSymbols.select: { // select(ifTrue: T, ifFalse: T, condition: bool) -> T
+ case BuiltinNames.select: { // select(ifTrue: T, ifFalse: T, condition: bool) -> T
if (
checkTypeOptional(typeArguments, reportNode, compiler, true) |
checkArgsRequired(operands, 3, reportNode, compiler)
@@ -2020,7 +2005,7 @@ export function compileCall(
compiler.currentType = type;
return module.select(arg0, arg1, arg2);
}
- case BuiltinSymbols.unreachable: { // unreachable() -> *
+ case BuiltinNames.unreachable: { // unreachable() -> *
if (typeArguments) {
compiler.error(
DiagnosticCode.Type_0_is_not_generic,
@@ -2033,7 +2018,7 @@ export function compileCall(
// === Memory =================================================================================
- case BuiltinSymbols.memory_size: { // memory.size() -> i32
+ case BuiltinNames.memory_size: { // memory.size() -> i32
compiler.currentType = Type.i32;
if (
checkTypeAbsent(typeArguments, reportNode, prototype) |
@@ -2041,7 +2026,7 @@ export function compileCall(
) return module.unreachable();
return module.host(HostOp.MemorySize);
}
- case BuiltinSymbols.memory_grow: { // memory.grow(pages: i32) -> i32
+ case BuiltinNames.memory_grow: { // memory.grow(pages: i32) -> i32
compiler.currentType = Type.i32;
if (
checkTypeAbsent(typeArguments, reportNode, prototype) |
@@ -2051,16 +2036,17 @@ export function compileCall(
compiler.compileExpression(operands[0], Type.i32, Constraints.CONV_IMPLICIT)
]);
}
- case BuiltinSymbols.memory_copy: { // memory.copy(dest: usize, src: usize: n: usize) -> void
+ case BuiltinNames.memory_copy: { // memory.copy(dest: usize, src: usize: n: usize) -> void
compiler.currentType = Type.void;
if (
checkTypeAbsent(typeArguments, reportNode, prototype) |
checkArgsRequired(operands, 3, reportNode, compiler)
) return module.unreachable();
if (!compiler.options.hasFeature(Feature.BULK_MEMORY)) {
+ // use stdlib alternative if not supported
let instance = compiler.resolver.resolveFunction(prototype, null); // reports
compiler.currentType = Type.void;
- if (!instance) return module.unreachable();
+ if (!instance || !compiler.compileFunction(instance, true)) return module.unreachable();
return compiler.compileCallDirect(instance, operands, reportNode);
}
let usizeType = compiler.options.usizeType;
@@ -2070,16 +2056,17 @@ export function compileCall(
compiler.currentType = Type.void;
return module.memory_copy(arg0, arg1, arg2);
}
- case BuiltinSymbols.memory_fill: { // memory.fill(dest: usize, value: u8, n: usize) -> void
+ case BuiltinNames.memory_fill: { // memory.fill(dest: usize, value: u8, n: usize) -> void
compiler.currentType = Type.void;
if (
checkTypeAbsent(typeArguments, reportNode, prototype) |
checkArgsRequired(operands, 3, reportNode, compiler)
) return module.unreachable();
if (!compiler.options.hasFeature(Feature.BULK_MEMORY)) {
+ // use stdlib alternative if not supported
let instance = compiler.resolver.resolveFunction(prototype, null); // reports
compiler.currentType = Type.void;
- if (!instance) return module.unreachable();
+ if (!instance || !compiler.compileFunction(instance, true)) return module.unreachable();
return compiler.compileCallDirect(instance, operands, reportNode);
}
let usizeType = compiler.options.usizeType;
@@ -2092,7 +2079,7 @@ export function compileCall(
// === Helpers ================================================================================
- case BuiltinSymbols.changetype: { // changetype(value: *) -> T
+ case BuiltinNames.changetype: { // changetype(value: *) -> T
if (
checkTypeRequired(typeArguments, reportNode, compiler, true) |
checkArgsRequired(operands, 1, reportNode, compiler)
@@ -2110,7 +2097,7 @@ export function compileCall(
}
return arg0;
}
- case BuiltinSymbols.assert: { // assert(isTrueish: T, message?: string) -> T{!= null}
+ case BuiltinNames.assert: { // assert(isTrueish: T, message?: string) -> T{!= null}
if (
checkTypeOptional(typeArguments, reportNode, compiler) |
checkArgsOptional(operands, 1, 2, reportNode, compiler)
@@ -2297,7 +2284,7 @@ export function compileCall(
);
return abort;
}
- case BuiltinSymbols.unchecked: { // unchecked(expr: *) -> *
+ case BuiltinNames.unchecked: { // unchecked(expr: *) -> *
if (
checkTypeAbsent(typeArguments, reportNode, prototype) |
checkArgsRequired(operands, 1, reportNode, compiler)
@@ -2310,7 +2297,7 @@ export function compileCall(
if (!alreadyUnchecked) flow.unset(FlowFlags.UNCHECKED_CONTEXT);
return expr;
}
- case BuiltinSymbols.instantiate: { // instantiate(...args: *[]) -> T
+ case BuiltinNames.instantiate: { // instantiate(...args: *[]) -> T
if (
checkTypeRequired(typeArguments, reportNode, compiler, true)
) return module.unreachable();
@@ -2329,7 +2316,7 @@ export function compileCall(
// === User-defined diagnostics ===============================================================
- case BuiltinSymbols.ERROR: {
+ case BuiltinNames.ERROR: {
checkTypeAbsent(typeArguments, reportNode, prototype);
compiler.error(
DiagnosticCode.User_defined_0,
@@ -2337,7 +2324,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.WARNING: {
+ case BuiltinNames.WARNING: {
checkTypeAbsent(typeArguments, reportNode, prototype);
compiler.warning(
DiagnosticCode.User_defined_0,
@@ -2345,7 +2332,7 @@ export function compileCall(
);
return module.nop();
}
- case BuiltinSymbols.INFO: {
+ case BuiltinNames.INFO: {
checkTypeAbsent(typeArguments, reportNode, prototype);
compiler.info(
DiagnosticCode.User_defined_0,
@@ -2356,7 +2343,7 @@ export function compileCall(
// === Portable type conversions ==============================================================
- case BuiltinSymbols.i8: {
+ case BuiltinNames.i8: {
if (
checkTypeAbsent(typeArguments, reportNode, prototype) |
checkArgsRequired(operands, 1, reportNode, compiler)
@@ -2366,7 +2353,7 @@ export function compileCall(
}
return compiler.compileExpression(operands[0], Type.i8, Constraints.CONV_EXPLICIT);
}
- case BuiltinSymbols.i16: {
+ case BuiltinNames.i16: {
if (
checkTypeAbsent(typeArguments, reportNode, prototype) |
checkArgsRequired(operands, 1, reportNode, compiler)
@@ -2376,7 +2363,7 @@ export function compileCall(
}
return compiler.compileExpression(operands[0], Type.i16, Constraints.CONV_EXPLICIT);
}
- case BuiltinSymbols.i32: {
+ case BuiltinNames.i32: {
if (
checkTypeAbsent(typeArguments, reportNode, prototype) |
checkArgsRequired(operands, 1, reportNode, compiler)
@@ -2386,7 +2373,7 @@ export function compileCall(
}
return compiler.compileExpression(operands[0], Type.i32, Constraints.CONV_EXPLICIT);
}
- case BuiltinSymbols.i64: {
+ case BuiltinNames.i64: {
if (
checkTypeAbsent(typeArguments, reportNode, prototype) |
checkArgsRequired(operands, 1, reportNode, compiler)
@@ -2396,7 +2383,7 @@ export function compileCall(
}
return compiler.compileExpression(operands[0], Type.i64, Constraints.CONV_EXPLICIT);
}
- case BuiltinSymbols.isize: {
+ case BuiltinNames.isize: {
let isizeType = compiler.options.isizeType;
if (
checkTypeAbsent(typeArguments, reportNode, prototype) |
@@ -2407,7 +2394,7 @@ export function compileCall(
}
return compiler.compileExpression(operands[0], isizeType, Constraints.CONV_EXPLICIT);
}
- case BuiltinSymbols.u8: {
+ case BuiltinNames.u8: {
if (
checkTypeAbsent(typeArguments, reportNode, prototype) |
checkArgsRequired(operands, 1, reportNode, compiler)
@@ -2417,7 +2404,7 @@ export function compileCall(
}
return compiler.compileExpression(operands[0], Type.u8, Constraints.CONV_EXPLICIT);
}
- case BuiltinSymbols.u16: {
+ case BuiltinNames.u16: {
if (
checkTypeAbsent(typeArguments, reportNode, prototype) |
checkArgsRequired(operands, 1, reportNode, compiler)
@@ -2427,7 +2414,7 @@ export function compileCall(
}
return compiler.compileExpression(operands[0], Type.u16, Constraints.CONV_EXPLICIT);
}
- case BuiltinSymbols.u32: {
+ case BuiltinNames.u32: {
if (
checkTypeAbsent(typeArguments, reportNode, prototype) |
checkArgsRequired(operands, 1, reportNode, compiler)
@@ -2437,7 +2424,7 @@ export function compileCall(
}
return compiler.compileExpression(operands[0], Type.u32, Constraints.CONV_EXPLICIT);
}
- case BuiltinSymbols.u64: {
+ case BuiltinNames.u64: {
if (
checkTypeAbsent(typeArguments, reportNode, prototype) |
checkArgsRequired(operands, 1, reportNode, compiler)
@@ -2447,7 +2434,7 @@ export function compileCall(
}
return compiler.compileExpression(operands[0], Type.u64, Constraints.CONV_EXPLICIT);
}
- case BuiltinSymbols.usize: {
+ case BuiltinNames.usize: {
let usizeType = compiler.options.usizeType;
if (
checkTypeAbsent(typeArguments, reportNode, prototype) |
@@ -2458,7 +2445,7 @@ export function compileCall(
}
return compiler.compileExpression(operands[0], usizeType, Constraints.CONV_EXPLICIT);
}
- case BuiltinSymbols.bool: {
+ case BuiltinNames.bool: {
if (
checkTypeAbsent(typeArguments, reportNode, prototype) |
checkArgsRequired(operands, 1, reportNode, compiler)
@@ -2468,7 +2455,7 @@ export function compileCall(
}
return compiler.compileExpression(operands[0], Type.bool, Constraints.CONV_EXPLICIT);
}
- case BuiltinSymbols.f32: {
+ case BuiltinNames.f32: {
if (
checkTypeAbsent(typeArguments, reportNode, prototype) |
checkArgsRequired(operands, 1, reportNode, compiler)
@@ -2478,7 +2465,7 @@ export function compileCall(
}
return compiler.compileExpression(operands[0], Type.f32, Constraints.CONV_EXPLICIT);
}
- case BuiltinSymbols.f64: {
+ case BuiltinNames.f64: {
if (
checkTypeAbsent(typeArguments, reportNode, prototype) |
checkArgsRequired(operands, 1, reportNode, compiler)
@@ -2491,8 +2478,8 @@ export function compileCall(
// === SIMD ===================================================================================
- case BuiltinSymbols.v128: // alias for now
- case BuiltinSymbols.i8x16: {
+ case BuiltinNames.v128: // alias for now
+ case BuiltinNames.i8x16: {
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeAbsent(typeArguments, reportNode, prototype) |
@@ -2521,7 +2508,7 @@ export function compileCall(
compiler.currentType = Type.v128;
return module.v128(bytes);
}
- case BuiltinSymbols.i16x8: {
+ case BuiltinNames.i16x8: {
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeAbsent(typeArguments, reportNode, prototype) |
@@ -2550,7 +2537,7 @@ export function compileCall(
compiler.currentType = Type.v128;
return module.v128(bytes);
}
- case BuiltinSymbols.i32x4: {
+ case BuiltinNames.i32x4: {
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeAbsent(typeArguments, reportNode, prototype) |
@@ -2579,7 +2566,7 @@ export function compileCall(
compiler.currentType = Type.v128;
return module.v128(bytes);
}
- case BuiltinSymbols.i64x2: {
+ case BuiltinNames.i64x2: {
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeAbsent(typeArguments, reportNode, prototype) |
@@ -2610,7 +2597,7 @@ export function compileCall(
compiler.currentType = Type.v128;
return module.v128(bytes);
}
- case BuiltinSymbols.f32x4: {
+ case BuiltinNames.f32x4: {
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeAbsent(typeArguments, reportNode, prototype) |
@@ -2639,7 +2626,7 @@ export function compileCall(
compiler.currentType = Type.v128;
return module.v128(bytes);
}
- case BuiltinSymbols.f64x2: {
+ case BuiltinNames.f64x2: {
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeAbsent(typeArguments, reportNode, prototype) |
@@ -2668,7 +2655,7 @@ export function compileCall(
compiler.currentType = Type.v128;
return module.v128(bytes);
}
- case BuiltinSymbols.v128_splat: { // splat(x: T) -> v128
+ case BuiltinNames.v128_splat: { // splat(x: T) -> v128
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -2709,7 +2696,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_extract_lane: { // extract_lane(x: v128, idx: u8) -> T
+ case BuiltinNames.v128_extract_lane: { // extract_lane(x: v128, idx: u8) -> T
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler, true) |
@@ -2766,7 +2753,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_replace_lane: { // replace_lane(x: v128, idx: u8, value: T) -> v128
+ case BuiltinNames.v128_replace_lane: { // replace_lane(x: v128, idx: u8, value: T) -> v128
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -2827,7 +2814,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_shuffle: { // shuffle(a: v128, b: v128, ...lanes: u8[]) -> v128
+ case BuiltinNames.v128_shuffle: { // shuffle(a: v128, b: v128, ...lanes: u8[]) -> v128
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler)
@@ -2933,7 +2920,7 @@ export function compileCall(
compiler.currentType = Type.v128;
return module.unreachable();
}
- case BuiltinSymbols.v128_swizzle: { // swizzle(a: v128, b: v128) -> v128
+ case BuiltinNames.v128_swizzle: { // swizzle(a: v128, b: v128) -> v128
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeAbsent(typeArguments, reportNode, prototype) |
@@ -2946,7 +2933,7 @@ export function compileCall(
let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT);
return module.binary(BinaryOp.SwizzleV8x16, arg0, arg1);
}
- case BuiltinSymbols.v128_load_splat: { // load_splat(ptr: usize, immOffset?: usize, immAlign?: usize) -> v128
+ case BuiltinNames.v128_load_splat: { // load_splat(ptr: usize, immOffset?: usize, immAlign?: usize) -> v128
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler, true) |
@@ -3021,7 +3008,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_load_ext: { // load_ext(ptr: usize, immOffset?: usize, immAlign?: usize) -> v128
+ case BuiltinNames.v128_load_ext: { // load_ext(ptr: usize, immOffset?: usize, immAlign?: usize) -> v128
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler, true) |
@@ -3085,7 +3072,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_add: { // add(a: v128, b: v128) -> v128
+ case BuiltinNames.v128_add: { // add(a: v128, b: v128) -> v128
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -3126,7 +3113,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_sub: { // sub(a: v128, b: v128) -> v128
+ case BuiltinNames.v128_sub: { // sub(a: v128, b: v128) -> v128
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -3167,7 +3154,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_mul: { // mul(a: v128, b: v128) -> v128
+ case BuiltinNames.v128_mul: { // mul(a: v128, b: v128) -> v128
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -3204,7 +3191,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_div: { // div(a: v128, b: v128) -> v128
+ case BuiltinNames.v128_div: { // div(a: v128, b: v128) -> v128
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -3228,7 +3215,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_add_saturate: { // add_saturate(a: v128, b: v128) -> v128
+ case BuiltinNames.v128_add_saturate: { // add_saturate(a: v128, b: v128) -> v128
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -3254,7 +3241,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_sub_saturate: { // sub_saturate(a: v128, b: v128) -> v128
+ case BuiltinNames.v128_sub_saturate: { // sub_saturate(a: v128, b: v128) -> v128
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -3280,7 +3267,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_min: { // min(a: v128, b: v128) -> v128
+ case BuiltinNames.v128_min: { // min(a: v128, b: v128) -> v128
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -3318,7 +3305,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_max: { // max(a: v128, b: v128) -> v128
+ case BuiltinNames.v128_max: { // max(a: v128, b: v128) -> v128
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -3356,7 +3343,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_dot: { // dot(a: v128, b: v128) -> v128
+ case BuiltinNames.v128_dot: { // dot(a: v128, b: v128) -> v128
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -3379,7 +3366,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_avgr: { // avgr(a: v128, b: v128) -> v128
+ case BuiltinNames.v128_avgr: { // avgr(a: v128, b: v128) -> v128
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -3403,7 +3390,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_eq: { // eq(a: v128, b: v128) -> v128
+ case BuiltinNames.v128_eq: { // eq(a: v128, b: v128) -> v128
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -3440,7 +3427,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_ne: { // ne(a: v128, b: v128) -> v128
+ case BuiltinNames.v128_ne: { // ne(a: v128, b: v128) -> v128
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -3477,7 +3464,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_lt: { // lt(a: v128, b: v128) -> v128
+ case BuiltinNames.v128_lt: { // lt(a: v128, b: v128) -> v128
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -3519,7 +3506,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_le: { // le(a: v128, b: v128) -> v128
+ case BuiltinNames.v128_le: { // le(a: v128, b: v128) -> v128
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -3561,7 +3548,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_gt: { // gt(a: v128, b: v128) -> v128
+ case BuiltinNames.v128_gt: { // gt(a: v128, b: v128) -> v128
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -3603,7 +3590,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_ge: { // ge(a: v128, b: v128) -> v128
+ case BuiltinNames.v128_ge: { // ge(a: v128, b: v128) -> v128
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -3645,7 +3632,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_narrow: {
+ case BuiltinNames.v128_narrow: {
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -3671,7 +3658,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_neg: {
+ case BuiltinNames.v128_neg: {
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -3711,7 +3698,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_abs: {
+ case BuiltinNames.v128_abs: {
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -3734,7 +3721,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_sqrt: {
+ case BuiltinNames.v128_sqrt: {
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -3757,7 +3744,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_convert: {
+ case BuiltinNames.v128_convert: {
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -3782,7 +3769,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_trunc_sat: {
+ case BuiltinNames.v128_trunc_sat: {
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -3807,7 +3794,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_widen_low: {
+ case BuiltinNames.v128_widen_low: {
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -3832,7 +3819,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_widen_high: {
+ case BuiltinNames.v128_widen_high: {
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -3857,7 +3844,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_shl: { // shl(a: v128, b: i32) -> v128
+ case BuiltinNames.v128_shl: { // shl(a: v128, b: i32) -> v128
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -3897,7 +3884,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_shr: { // shr(a: v128, b: i32) -> v128
+ case BuiltinNames.v128_shr: { // shr(a: v128, b: i32) -> v128
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -3944,7 +3931,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_and: { // and(a: v128) -> v128
+ case BuiltinNames.v128_and: { // and(a: v128) -> v128
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeAbsent(typeArguments, reportNode, prototype) |
@@ -3957,7 +3944,7 @@ export function compileCall(
let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT);
return module.binary(BinaryOp.AndV128, arg0, arg1);
}
- case BuiltinSymbols.v128_or: { // or(a: v128) -> v128
+ case BuiltinNames.v128_or: { // or(a: v128) -> v128
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeAbsent(typeArguments, reportNode, prototype) |
@@ -3970,7 +3957,7 @@ export function compileCall(
let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT);
return module.binary(BinaryOp.OrV128, arg0, arg1);
}
- case BuiltinSymbols.v128_xor: { // xor(a: v128) -> v128
+ case BuiltinNames.v128_xor: { // xor(a: v128) -> v128
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeAbsent(typeArguments, reportNode, prototype) |
@@ -3983,7 +3970,7 @@ export function compileCall(
let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT);
return module.binary(BinaryOp.XorV128, arg0, arg1);
}
- case BuiltinSymbols.v128_andnot: { // andnot(a: v128, b: v128) -> v128
+ case BuiltinNames.v128_andnot: { // andnot(a: v128, b: v128) -> v128
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeAbsent(typeArguments, reportNode, prototype) |
@@ -3996,7 +3983,7 @@ export function compileCall(
let arg1 = compiler.compileExpression(operands[1], Type.v128, Constraints.CONV_IMPLICIT);
return module.binary(BinaryOp.AndNotV128, arg0, arg1);
}
- case BuiltinSymbols.v128_not: { // not(a: v128) -> v128
+ case BuiltinNames.v128_not: { // not(a: v128) -> v128
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeAbsent(typeArguments, reportNode, prototype) |
@@ -4008,7 +3995,7 @@ export function compileCall(
let arg0 = compiler.compileExpression(operands[0], Type.v128, Constraints.CONV_IMPLICIT);
return module.unary(UnaryOp.NotV128, arg0);
}
- case BuiltinSymbols.v128_bitselect: { // bitselect(v1: v128, v2: v128, c: v128) -> v128
+ case BuiltinNames.v128_bitselect: { // bitselect(v1: v128, v2: v128, c: v128) -> v128
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeAbsent(typeArguments, reportNode, prototype) |
@@ -4022,7 +4009,7 @@ export function compileCall(
let arg2 = compiler.compileExpression(operands[2], Type.v128, Constraints.CONV_IMPLICIT);
return module.simd_ternary(SIMDTernaryOp.Bitselect, arg0, arg1, arg2);
}
- case BuiltinSymbols.v128_any_true: { // any_true(a: v128) -> bool
+ case BuiltinNames.v128_any_true: { // any_true(a: v128) -> bool
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -4061,7 +4048,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_all_true: { // all_true(a: v128) -> bool
+ case BuiltinNames.v128_all_true: { // all_true(a: v128) -> bool
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -4100,7 +4087,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_qfma: { // qfma(a: v128, b: v128, c: v128) -> v128
+ case BuiltinNames.v128_qfma: { // qfma(a: v128, b: v128, c: v128) -> v128
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -4125,7 +4112,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.v128_qfms: { // qfms(a: v128, b: v128, c: v128) -> v128
+ case BuiltinNames.v128_qfms: { // qfms(a: v128, b: v128, c: v128) -> v128
if (
checkFeatureEnabled(Feature.SIMD, reportNode, compiler) |
checkTypeRequired(typeArguments, reportNode, compiler) |
@@ -4153,7 +4140,7 @@ export function compileCall(
// === Internal runtime =======================================================================
- case BuiltinSymbols.idof: {
+ case BuiltinNames.idof: {
let type = evaluateConstantType(compiler, typeArguments, operands, reportNode);
compiler.currentType = Type.u32;
if (!type) return module.unreachable();
@@ -4173,7 +4160,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.visit_globals: {
+ case BuiltinNames.visit_globals: {
if (
checkTypeAbsent(typeArguments, reportNode, prototype) |
checkArgsRequired(operands, 1, reportNode, compiler) // cookie
@@ -4184,9 +4171,9 @@ export function compileCall(
let arg0 = compiler.compileExpression(operands[0], Type.u32, Constraints.CONV_IMPLICIT);
compiler.runtimeFeatures |= RuntimeFeatures.visitGlobals;
compiler.currentType = Type.void;
- return module.call(BuiltinSymbols.visit_globals, [ arg0 ], NativeType.None);
+ return module.call(BuiltinNames.visit_globals, [ arg0 ], NativeType.None);
}
- case BuiltinSymbols.visit_members: {
+ case BuiltinNames.visit_members: {
if (
checkTypeAbsent(typeArguments, reportNode, prototype) |
checkArgsRequired(operands, 2, reportNode, compiler) // ref, cookie
@@ -4198,9 +4185,9 @@ export function compileCall(
let arg1 = compiler.compileExpression(operands[1], Type.u32, Constraints.CONV_IMPLICIT);
compiler.runtimeFeatures |= RuntimeFeatures.visitMembers;
compiler.currentType = Type.void;
- return module.call(BuiltinSymbols.visit_members, [ arg0, arg1 ], NativeType.None);
+ return module.call(BuiltinNames.visit_members, [ arg0, arg1 ], NativeType.None);
}
- case BuiltinSymbols.isNaN: {
+ case BuiltinNames.isNaN: {
if (
checkTypeOptional(typeArguments, reportNode, compiler) |
checkArgsRequired(operands, 1, reportNode, compiler)
@@ -4274,7 +4261,7 @@ export function compileCall(
);
return module.unreachable();
}
- case BuiltinSymbols.isFinite: {
+ case BuiltinNames.isFinite: {
if (
checkTypeOptional(typeArguments, reportNode, compiler) |
checkArgsRequired(operands, 1, reportNode, compiler)
@@ -4397,320 +4384,320 @@ function tryDeferASM(
// and, or, xor, shl, shr_u, shr_s
// eq, eqz, ne, lt_s, lt_u, le_s, le_u, gt_s, gt_u, ge_s, ge_u
- case BuiltinSymbols.i32_clz: return deferASM(BuiltinSymbols.clz, compiler, Type.i32, operands, Type.i32, reportNode);
- case BuiltinSymbols.i64_clz: return deferASM(BuiltinSymbols.clz, compiler, Type.i64, operands, Type.i64, reportNode);
- case BuiltinSymbols.i32_ctz: return deferASM(BuiltinSymbols.ctz, compiler, Type.i32, operands, Type.i32, reportNode);
- case BuiltinSymbols.i64_ctz: return deferASM(BuiltinSymbols.ctz, compiler, Type.i64, operands, Type.i64, reportNode);
- case BuiltinSymbols.i32_popcnt: return deferASM(BuiltinSymbols.popcnt, compiler, Type.i32, operands, Type.i32, reportNode);
- case BuiltinSymbols.i64_popcnt: return deferASM(BuiltinSymbols.popcnt, compiler, Type.i64, operands, Type.i64, reportNode);
- case BuiltinSymbols.i32_rotl: return deferASM(BuiltinSymbols.rotl, compiler, Type.i32, operands, Type.i32, reportNode);
- case BuiltinSymbols.i64_rotl: return deferASM(BuiltinSymbols.rotl, compiler, Type.i64, operands, Type.i64, reportNode);
- case BuiltinSymbols.i32_rotr: return deferASM(BuiltinSymbols.rotr, compiler, Type.i32, operands, Type.i32, reportNode);
- case BuiltinSymbols.i64_rotr: return deferASM(BuiltinSymbols.rotr, compiler, Type.i64, operands, Type.i64, reportNode);
- case BuiltinSymbols.f32_abs: return deferASM(BuiltinSymbols.abs, compiler, Type.f32, operands, Type.f32, reportNode);
- case BuiltinSymbols.f64_abs: return deferASM(BuiltinSymbols.abs, compiler, Type.f64, operands, Type.f64, reportNode);
- case BuiltinSymbols.f32_max: return deferASM(BuiltinSymbols.max, compiler, Type.f32, operands, Type.f32, reportNode);
- case BuiltinSymbols.f64_max: return deferASM(BuiltinSymbols.max, compiler, Type.f64, operands, Type.f64, reportNode);
- case BuiltinSymbols.f32_min: return deferASM(BuiltinSymbols.min, compiler, Type.f32, operands, Type.f32, reportNode);
- case BuiltinSymbols.f64_min: return deferASM(BuiltinSymbols.min, compiler, Type.f64, operands, Type.f64, reportNode);
- case BuiltinSymbols.f32_ceil: return deferASM(BuiltinSymbols.ceil, compiler, Type.f32, operands, Type.f32, reportNode);
- case BuiltinSymbols.f64_ceil: return deferASM(BuiltinSymbols.ceil, compiler, Type.f64, operands, Type.f64, reportNode);
- case BuiltinSymbols.f32_floor: return deferASM(BuiltinSymbols.floor, compiler, Type.f32, operands, Type.f32, reportNode);
- case BuiltinSymbols.f64_floor: return deferASM(BuiltinSymbols.floor, compiler, Type.f64, operands, Type.f64, reportNode);
- case BuiltinSymbols.f32_copysign: return deferASM(BuiltinSymbols.copysign, compiler, Type.f32, operands, Type.f32, reportNode);
- case BuiltinSymbols.f64_copysign: return deferASM(BuiltinSymbols.copysign, compiler, Type.f64, operands, Type.f64, reportNode);
- case BuiltinSymbols.f32_nearest: return deferASM(BuiltinSymbols.nearest, compiler, Type.f32, operands, Type.f32, reportNode);
- case BuiltinSymbols.f64_nearest: return deferASM(BuiltinSymbols.nearest, compiler, Type.f64, operands, Type.f64, reportNode);
- case BuiltinSymbols.i32_reinterpret_f32: return deferASM(BuiltinSymbols.reinterpret, compiler, Type.i32, operands, Type.f32, reportNode);
- case BuiltinSymbols.i64_reinterpret_f64: return deferASM(BuiltinSymbols.reinterpret, compiler, Type.i64, operands, Type.f64, reportNode);
- case BuiltinSymbols.f32_reinterpret_i32: return deferASM(BuiltinSymbols.reinterpret, compiler, Type.f32, operands, Type.i32, reportNode);
- case BuiltinSymbols.f64_reinterpret_i64: return deferASM(BuiltinSymbols.reinterpret, compiler, Type.f64, operands, Type.i64, reportNode);
- case BuiltinSymbols.f32_sqrt: return deferASM(BuiltinSymbols.sqrt, compiler, Type.f32, operands, Type.f32, reportNode);
- case BuiltinSymbols.f64_sqrt: return deferASM(BuiltinSymbols.sqrt, compiler, Type.f64, operands, Type.f64, reportNode);
- case BuiltinSymbols.f32_trunc: return deferASM(BuiltinSymbols.trunc, compiler, Type.f32, operands, Type.f32, reportNode);
- case BuiltinSymbols.f64_trunc: return deferASM(BuiltinSymbols.trunc, compiler, Type.f64, operands, Type.f64, reportNode);
- case BuiltinSymbols.i32_load8_s: return deferASM(BuiltinSymbols.load, compiler, Type.i8, operands, Type.i32, reportNode);
- case BuiltinSymbols.i32_load8_u: return deferASM(BuiltinSymbols.load, compiler, Type.u8, operands, Type.i32, reportNode);
- case BuiltinSymbols.i32_load16_s: return deferASM(BuiltinSymbols.load, compiler, Type.i16, operands, Type.i32, reportNode);
- case BuiltinSymbols.i32_load16_u: return deferASM(BuiltinSymbols.load, compiler, Type.u16, operands, Type.i32, reportNode);
- case BuiltinSymbols.i32_load: return deferASM(BuiltinSymbols.load, compiler, Type.i32, operands, Type.i32, reportNode);
- case BuiltinSymbols.i64_load8_s: return deferASM(BuiltinSymbols.load, compiler, Type.i8, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_load8_u: return deferASM(BuiltinSymbols.load, compiler, Type.u8, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_load16_s: return deferASM(BuiltinSymbols.load, compiler, Type.i16, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_load16_u: return deferASM(BuiltinSymbols.load, compiler, Type.u16, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_load32_s: return deferASM(BuiltinSymbols.load, compiler, Type.i32, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_load32_u: return deferASM(BuiltinSymbols.load, compiler, Type.u32, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_load: return deferASM(BuiltinSymbols.load, compiler, Type.i64, operands, Type.i64, reportNode);
- case BuiltinSymbols.f32_load: return deferASM(BuiltinSymbols.load, compiler, Type.f32, operands, Type.f32, reportNode);
- case BuiltinSymbols.f64_load: return deferASM(BuiltinSymbols.load, compiler, Type.f64, operands, Type.f64, reportNode);
- case BuiltinSymbols.i32_store8: return deferASM(BuiltinSymbols.store, compiler, Type.i8, operands, Type.i32, reportNode);
- case BuiltinSymbols.i32_store16: return deferASM(BuiltinSymbols.store, compiler, Type.i16, operands, Type.i32, reportNode);
- case BuiltinSymbols.i32_store: return deferASM(BuiltinSymbols.store, compiler, Type.i32, operands, Type.i32, reportNode);
- case BuiltinSymbols.i64_store8: return deferASM(BuiltinSymbols.store, compiler, Type.i8, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_store16: return deferASM(BuiltinSymbols.store, compiler, Type.i16, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_store32: return deferASM(BuiltinSymbols.store, compiler, Type.i32, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_store: return deferASM(BuiltinSymbols.store, compiler, Type.i64, operands, Type.i64, reportNode);
- case BuiltinSymbols.f32_store: return deferASM(BuiltinSymbols.store, compiler, Type.f32, operands, Type.f32, reportNode);
- case BuiltinSymbols.f64_store: return deferASM(BuiltinSymbols.store, compiler, Type.f64, operands, Type.f64, reportNode);
+ case BuiltinNames.i32_clz: return deferASM(BuiltinNames.clz, compiler, Type.i32, operands, Type.i32, reportNode);
+ case BuiltinNames.i64_clz: return deferASM(BuiltinNames.clz, compiler, Type.i64, operands, Type.i64, reportNode);
+ case BuiltinNames.i32_ctz: return deferASM(BuiltinNames.ctz, compiler, Type.i32, operands, Type.i32, reportNode);
+ case BuiltinNames.i64_ctz: return deferASM(BuiltinNames.ctz, compiler, Type.i64, operands, Type.i64, reportNode);
+ case BuiltinNames.i32_popcnt: return deferASM(BuiltinNames.popcnt, compiler, Type.i32, operands, Type.i32, reportNode);
+ case BuiltinNames.i64_popcnt: return deferASM(BuiltinNames.popcnt, compiler, Type.i64, operands, Type.i64, reportNode);
+ case BuiltinNames.i32_rotl: return deferASM(BuiltinNames.rotl, compiler, Type.i32, operands, Type.i32, reportNode);
+ case BuiltinNames.i64_rotl: return deferASM(BuiltinNames.rotl, compiler, Type.i64, operands, Type.i64, reportNode);
+ case BuiltinNames.i32_rotr: return deferASM(BuiltinNames.rotr, compiler, Type.i32, operands, Type.i32, reportNode);
+ case BuiltinNames.i64_rotr: return deferASM(BuiltinNames.rotr, compiler, Type.i64, operands, Type.i64, reportNode);
+ case BuiltinNames.f32_abs: return deferASM(BuiltinNames.abs, compiler, Type.f32, operands, Type.f32, reportNode);
+ case BuiltinNames.f64_abs: return deferASM(BuiltinNames.abs, compiler, Type.f64, operands, Type.f64, reportNode);
+ case BuiltinNames.f32_max: return deferASM(BuiltinNames.max, compiler, Type.f32, operands, Type.f32, reportNode);
+ case BuiltinNames.f64_max: return deferASM(BuiltinNames.max, compiler, Type.f64, operands, Type.f64, reportNode);
+ case BuiltinNames.f32_min: return deferASM(BuiltinNames.min, compiler, Type.f32, operands, Type.f32, reportNode);
+ case BuiltinNames.f64_min: return deferASM(BuiltinNames.min, compiler, Type.f64, operands, Type.f64, reportNode);
+ case BuiltinNames.f32_ceil: return deferASM(BuiltinNames.ceil, compiler, Type.f32, operands, Type.f32, reportNode);
+ case BuiltinNames.f64_ceil: return deferASM(BuiltinNames.ceil, compiler, Type.f64, operands, Type.f64, reportNode);
+ case BuiltinNames.f32_floor: return deferASM(BuiltinNames.floor, compiler, Type.f32, operands, Type.f32, reportNode);
+ case BuiltinNames.f64_floor: return deferASM(BuiltinNames.floor, compiler, Type.f64, operands, Type.f64, reportNode);
+ case BuiltinNames.f32_copysign: return deferASM(BuiltinNames.copysign, compiler, Type.f32, operands, Type.f32, reportNode);
+ case BuiltinNames.f64_copysign: return deferASM(BuiltinNames.copysign, compiler, Type.f64, operands, Type.f64, reportNode);
+ case BuiltinNames.f32_nearest: return deferASM(BuiltinNames.nearest, compiler, Type.f32, operands, Type.f32, reportNode);
+ case BuiltinNames.f64_nearest: return deferASM(BuiltinNames.nearest, compiler, Type.f64, operands, Type.f64, reportNode);
+ case BuiltinNames.i32_reinterpret_f32: return deferASM(BuiltinNames.reinterpret, compiler, Type.i32, operands, Type.f32, reportNode);
+ case BuiltinNames.i64_reinterpret_f64: return deferASM(BuiltinNames.reinterpret, compiler, Type.i64, operands, Type.f64, reportNode);
+ case BuiltinNames.f32_reinterpret_i32: return deferASM(BuiltinNames.reinterpret, compiler, Type.f32, operands, Type.i32, reportNode);
+ case BuiltinNames.f64_reinterpret_i64: return deferASM(BuiltinNames.reinterpret, compiler, Type.f64, operands, Type.i64, reportNode);
+ case BuiltinNames.f32_sqrt: return deferASM(BuiltinNames.sqrt, compiler, Type.f32, operands, Type.f32, reportNode);
+ case BuiltinNames.f64_sqrt: return deferASM(BuiltinNames.sqrt, compiler, Type.f64, operands, Type.f64, reportNode);
+ case BuiltinNames.f32_trunc: return deferASM(BuiltinNames.trunc, compiler, Type.f32, operands, Type.f32, reportNode);
+ case BuiltinNames.f64_trunc: return deferASM(BuiltinNames.trunc, compiler, Type.f64, operands, Type.f64, reportNode);
+ case BuiltinNames.i32_load8_s: return deferASM(BuiltinNames.load, compiler, Type.i8, operands, Type.i32, reportNode);
+ case BuiltinNames.i32_load8_u: return deferASM(BuiltinNames.load, compiler, Type.u8, operands, Type.i32, reportNode);
+ case BuiltinNames.i32_load16_s: return deferASM(BuiltinNames.load, compiler, Type.i16, operands, Type.i32, reportNode);
+ case BuiltinNames.i32_load16_u: return deferASM(BuiltinNames.load, compiler, Type.u16, operands, Type.i32, reportNode);
+ case BuiltinNames.i32_load: return deferASM(BuiltinNames.load, compiler, Type.i32, operands, Type.i32, reportNode);
+ case BuiltinNames.i64_load8_s: return deferASM(BuiltinNames.load, compiler, Type.i8, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_load8_u: return deferASM(BuiltinNames.load, compiler, Type.u8, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_load16_s: return deferASM(BuiltinNames.load, compiler, Type.i16, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_load16_u: return deferASM(BuiltinNames.load, compiler, Type.u16, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_load32_s: return deferASM(BuiltinNames.load, compiler, Type.i32, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_load32_u: return deferASM(BuiltinNames.load, compiler, Type.u32, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_load: return deferASM(BuiltinNames.load, compiler, Type.i64, operands, Type.i64, reportNode);
+ case BuiltinNames.f32_load: return deferASM(BuiltinNames.load, compiler, Type.f32, operands, Type.f32, reportNode);
+ case BuiltinNames.f64_load: return deferASM(BuiltinNames.load, compiler, Type.f64, operands, Type.f64, reportNode);
+ case BuiltinNames.i32_store8: return deferASM(BuiltinNames.store, compiler, Type.i8, operands, Type.i32, reportNode);
+ case BuiltinNames.i32_store16: return deferASM(BuiltinNames.store, compiler, Type.i16, operands, Type.i32, reportNode);
+ case BuiltinNames.i32_store: return deferASM(BuiltinNames.store, compiler, Type.i32, operands, Type.i32, reportNode);
+ case BuiltinNames.i64_store8: return deferASM(BuiltinNames.store, compiler, Type.i8, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_store16: return deferASM(BuiltinNames.store, compiler, Type.i16, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_store32: return deferASM(BuiltinNames.store, compiler, Type.i32, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_store: return deferASM(BuiltinNames.store, compiler, Type.i64, operands, Type.i64, reportNode);
+ case BuiltinNames.f32_store: return deferASM(BuiltinNames.store, compiler, Type.f32, operands, Type.f32, reportNode);
+ case BuiltinNames.f64_store: return deferASM(BuiltinNames.store, compiler, Type.f64, operands, Type.f64, reportNode);
- case BuiltinSymbols.i32_atomic_load8_u: return deferASM(BuiltinSymbols.atomic_load, compiler, Type.u8, operands, Type.i32, reportNode);
- case BuiltinSymbols.i32_atomic_load16_u: return deferASM(BuiltinSymbols.atomic_load, compiler, Type.u16, operands, Type.i32, reportNode);
- case BuiltinSymbols.i32_atomic_load: return deferASM(BuiltinSymbols.atomic_load, compiler, Type.i32, operands, Type.i32, reportNode);
- case BuiltinSymbols.i64_atomic_load8_u: return deferASM(BuiltinSymbols.atomic_load, compiler, Type.u8, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_atomic_load16_u: return deferASM(BuiltinSymbols.atomic_load, compiler, Type.u16, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_atomic_load32_u: return deferASM(BuiltinSymbols.atomic_load, compiler, Type.u32, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_atomic_load: return deferASM(BuiltinSymbols.atomic_load, compiler, Type.i64, operands, Type.i64, reportNode);
+ case BuiltinNames.i32_atomic_load8_u: return deferASM(BuiltinNames.atomic_load, compiler, Type.u8, operands, Type.i32, reportNode);
+ case BuiltinNames.i32_atomic_load16_u: return deferASM(BuiltinNames.atomic_load, compiler, Type.u16, operands, Type.i32, reportNode);
+ case BuiltinNames.i32_atomic_load: return deferASM(BuiltinNames.atomic_load, compiler, Type.i32, operands, Type.i32, reportNode);
+ case BuiltinNames.i64_atomic_load8_u: return deferASM(BuiltinNames.atomic_load, compiler, Type.u8, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_atomic_load16_u: return deferASM(BuiltinNames.atomic_load, compiler, Type.u16, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_atomic_load32_u: return deferASM(BuiltinNames.atomic_load, compiler, Type.u32, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_atomic_load: return deferASM(BuiltinNames.atomic_load, compiler, Type.i64, operands, Type.i64, reportNode);
- case BuiltinSymbols.i32_atomic_store8: return deferASM(BuiltinSymbols.atomic_store, compiler, Type.u8, operands, Type.i32, reportNode);
- case BuiltinSymbols.i32_atomic_store16: return deferASM(BuiltinSymbols.atomic_store, compiler, Type.u16, operands, Type.i32, reportNode);
- case BuiltinSymbols.i32_atomic_store: return deferASM(BuiltinSymbols.atomic_store, compiler, Type.i32, operands, Type.i32, reportNode);
- case BuiltinSymbols.i64_atomic_store8: return deferASM(BuiltinSymbols.atomic_store, compiler, Type.u8, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_atomic_store16: return deferASM(BuiltinSymbols.atomic_store, compiler, Type.u16, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_atomic_store32: return deferASM(BuiltinSymbols.atomic_store, compiler, Type.u32, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_atomic_store: return deferASM(BuiltinSymbols.atomic_store, compiler, Type.i64, operands, Type.i64, reportNode);
+ case BuiltinNames.i32_atomic_store8: return deferASM(BuiltinNames.atomic_store, compiler, Type.u8, operands, Type.i32, reportNode);
+ case BuiltinNames.i32_atomic_store16: return deferASM(BuiltinNames.atomic_store, compiler, Type.u16, operands, Type.i32, reportNode);
+ case BuiltinNames.i32_atomic_store: return deferASM(BuiltinNames.atomic_store, compiler, Type.i32, operands, Type.i32, reportNode);
+ case BuiltinNames.i64_atomic_store8: return deferASM(BuiltinNames.atomic_store, compiler, Type.u8, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_atomic_store16: return deferASM(BuiltinNames.atomic_store, compiler, Type.u16, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_atomic_store32: return deferASM(BuiltinNames.atomic_store, compiler, Type.u32, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_atomic_store: return deferASM(BuiltinNames.atomic_store, compiler, Type.i64, operands, Type.i64, reportNode);
- case BuiltinSymbols.i32_atomic_rmw8_add_u: return deferASM(BuiltinSymbols.atomic_add, compiler, Type.u8, operands, Type.i32, reportNode);
- case BuiltinSymbols.i32_atomic_rmw16_add_u: return deferASM(BuiltinSymbols.atomic_add, compiler, Type.u16, operands, Type.i32, reportNode);
- case BuiltinSymbols.i32_atomic_rmw_add: return deferASM(BuiltinSymbols.atomic_add, compiler, Type.i32, operands, Type.i32, reportNode);
- case BuiltinSymbols.i64_atomic_rmw8_add_u: return deferASM(BuiltinSymbols.atomic_add, compiler, Type.u8, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_atomic_rmw16_add_u: return deferASM(BuiltinSymbols.atomic_add, compiler, Type.u16, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_atomic_rmw32_add_u: return deferASM(BuiltinSymbols.atomic_add, compiler, Type.u32, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_atomic_rmw_add: return deferASM(BuiltinSymbols.atomic_add, compiler, Type.i64, operands, Type.i64, reportNode);
+ case BuiltinNames.i32_atomic_rmw8_add_u: return deferASM(BuiltinNames.atomic_add, compiler, Type.u8, operands, Type.i32, reportNode);
+ case BuiltinNames.i32_atomic_rmw16_add_u: return deferASM(BuiltinNames.atomic_add, compiler, Type.u16, operands, Type.i32, reportNode);
+ case BuiltinNames.i32_atomic_rmw_add: return deferASM(BuiltinNames.atomic_add, compiler, Type.i32, operands, Type.i32, reportNode);
+ case BuiltinNames.i64_atomic_rmw8_add_u: return deferASM(BuiltinNames.atomic_add, compiler, Type.u8, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_atomic_rmw16_add_u: return deferASM(BuiltinNames.atomic_add, compiler, Type.u16, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_atomic_rmw32_add_u: return deferASM(BuiltinNames.atomic_add, compiler, Type.u32, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_atomic_rmw_add: return deferASM(BuiltinNames.atomic_add, compiler, Type.i64, operands, Type.i64, reportNode);
- case BuiltinSymbols.i32_atomic_rmw8_sub_u: return deferASM(BuiltinSymbols.atomic_sub, compiler, Type.u8, operands, Type.i32, reportNode);
- case BuiltinSymbols.i32_atomic_rmw16_sub_u: return deferASM(BuiltinSymbols.atomic_sub, compiler, Type.u16, operands, Type.i32, reportNode);
- case BuiltinSymbols.i32_atomic_rmw_sub: return deferASM(BuiltinSymbols.atomic_sub, compiler, Type.i32, operands, Type.i32, reportNode);
- case BuiltinSymbols.i64_atomic_rmw8_sub_u: return deferASM(BuiltinSymbols.atomic_sub, compiler, Type.u8, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_atomic_rmw16_sub_u: return deferASM(BuiltinSymbols.atomic_sub, compiler, Type.u16, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_atomic_rmw32_sub_u: return deferASM(BuiltinSymbols.atomic_sub, compiler, Type.u32, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_atomic_rmw_sub: return deferASM(BuiltinSymbols.atomic_sub, compiler, Type.i64, operands, Type.i64, reportNode);
+ case BuiltinNames.i32_atomic_rmw8_sub_u: return deferASM(BuiltinNames.atomic_sub, compiler, Type.u8, operands, Type.i32, reportNode);
+ case BuiltinNames.i32_atomic_rmw16_sub_u: return deferASM(BuiltinNames.atomic_sub, compiler, Type.u16, operands, Type.i32, reportNode);
+ case BuiltinNames.i32_atomic_rmw_sub: return deferASM(BuiltinNames.atomic_sub, compiler, Type.i32, operands, Type.i32, reportNode);
+ case BuiltinNames.i64_atomic_rmw8_sub_u: return deferASM(BuiltinNames.atomic_sub, compiler, Type.u8, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_atomic_rmw16_sub_u: return deferASM(BuiltinNames.atomic_sub, compiler, Type.u16, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_atomic_rmw32_sub_u: return deferASM(BuiltinNames.atomic_sub, compiler, Type.u32, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_atomic_rmw_sub: return deferASM(BuiltinNames.atomic_sub, compiler, Type.i64, operands, Type.i64, reportNode);
- case BuiltinSymbols.i32_atomic_rmw8_and_u: return deferASM(BuiltinSymbols.atomic_and, compiler, Type.u8, operands, Type.i32, reportNode);
- case BuiltinSymbols.i32_atomic_rmw16_and_u: return deferASM(BuiltinSymbols.atomic_and, compiler, Type.u16, operands, Type.i32, reportNode);
- case BuiltinSymbols.i32_atomic_rmw_and: return deferASM(BuiltinSymbols.atomic_and, compiler, Type.i32, operands, Type.i32, reportNode);
- case BuiltinSymbols.i64_atomic_rmw8_and_u: return deferASM(BuiltinSymbols.atomic_and, compiler, Type.u8, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_atomic_rmw16_and_u: return deferASM(BuiltinSymbols.atomic_and, compiler, Type.u16, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_atomic_rmw32_and_u: return deferASM(BuiltinSymbols.atomic_and, compiler, Type.u32, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_atomic_rmw_and: return deferASM(BuiltinSymbols.atomic_and, compiler, Type.i64, operands, Type.i64, reportNode);
+ case BuiltinNames.i32_atomic_rmw8_and_u: return deferASM(BuiltinNames.atomic_and, compiler, Type.u8, operands, Type.i32, reportNode);
+ case BuiltinNames.i32_atomic_rmw16_and_u: return deferASM(BuiltinNames.atomic_and, compiler, Type.u16, operands, Type.i32, reportNode);
+ case BuiltinNames.i32_atomic_rmw_and: return deferASM(BuiltinNames.atomic_and, compiler, Type.i32, operands, Type.i32, reportNode);
+ case BuiltinNames.i64_atomic_rmw8_and_u: return deferASM(BuiltinNames.atomic_and, compiler, Type.u8, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_atomic_rmw16_and_u: return deferASM(BuiltinNames.atomic_and, compiler, Type.u16, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_atomic_rmw32_and_u: return deferASM(BuiltinNames.atomic_and, compiler, Type.u32, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_atomic_rmw_and: return deferASM(BuiltinNames.atomic_and, compiler, Type.i64, operands, Type.i64, reportNode);
- case BuiltinSymbols.i32_atomic_rmw8_or_u: return deferASM(BuiltinSymbols.atomic_or, compiler, Type.u8, operands, Type.i32, reportNode);
- case BuiltinSymbols.i32_atomic_rmw16_or_u: return deferASM(BuiltinSymbols.atomic_or, compiler, Type.u16, operands, Type.i32, reportNode);
- case BuiltinSymbols.i32_atomic_rmw_or: return deferASM(BuiltinSymbols.atomic_or, compiler, Type.i32, operands, Type.i32, reportNode);
- case BuiltinSymbols.i64_atomic_rmw8_or_u: return deferASM(BuiltinSymbols.atomic_or, compiler, Type.u8, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_atomic_rmw16_or_u: return deferASM(BuiltinSymbols.atomic_or, compiler, Type.u16, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_atomic_rmw32_or_u: return deferASM(BuiltinSymbols.atomic_or, compiler, Type.u32, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_atomic_rmw_or: return deferASM(BuiltinSymbols.atomic_or, compiler, Type.i64, operands, Type.i64, reportNode);
+ case BuiltinNames.i32_atomic_rmw8_or_u: return deferASM(BuiltinNames.atomic_or, compiler, Type.u8, operands, Type.i32, reportNode);
+ case BuiltinNames.i32_atomic_rmw16_or_u: return deferASM(BuiltinNames.atomic_or, compiler, Type.u16, operands, Type.i32, reportNode);
+ case BuiltinNames.i32_atomic_rmw_or: return deferASM(BuiltinNames.atomic_or, compiler, Type.i32, operands, Type.i32, reportNode);
+ case BuiltinNames.i64_atomic_rmw8_or_u: return deferASM(BuiltinNames.atomic_or, compiler, Type.u8, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_atomic_rmw16_or_u: return deferASM(BuiltinNames.atomic_or, compiler, Type.u16, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_atomic_rmw32_or_u: return deferASM(BuiltinNames.atomic_or, compiler, Type.u32, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_atomic_rmw_or: return deferASM(BuiltinNames.atomic_or, compiler, Type.i64, operands, Type.i64, reportNode);
- case BuiltinSymbols.i32_atomic_rmw8_xor_u: return deferASM(BuiltinSymbols.atomic_xor, compiler, Type.u8, operands, Type.i32, reportNode);
- case BuiltinSymbols.i32_atomic_rmw16_xor_u: return deferASM(BuiltinSymbols.atomic_xor, compiler, Type.u16, operands, Type.i32, reportNode);
- case BuiltinSymbols.i32_atomic_rmw_xor: return deferASM(BuiltinSymbols.atomic_xor, compiler, Type.i32, operands, Type.i32, reportNode);
- case BuiltinSymbols.i64_atomic_rmw8_xor_u: return deferASM(BuiltinSymbols.atomic_xor, compiler, Type.u8, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_atomic_rmw16_xor_u: return deferASM(BuiltinSymbols.atomic_xor, compiler, Type.u16, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_atomic_rmw32_xor_u: return deferASM(BuiltinSymbols.atomic_xor, compiler, Type.u32, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_atomic_rmw_xor: return deferASM(BuiltinSymbols.atomic_xor, compiler, Type.i64, operands, Type.i64, reportNode);
+ case BuiltinNames.i32_atomic_rmw8_xor_u: return deferASM(BuiltinNames.atomic_xor, compiler, Type.u8, operands, Type.i32, reportNode);
+ case BuiltinNames.i32_atomic_rmw16_xor_u: return deferASM(BuiltinNames.atomic_xor, compiler, Type.u16, operands, Type.i32, reportNode);
+ case BuiltinNames.i32_atomic_rmw_xor: return deferASM(BuiltinNames.atomic_xor, compiler, Type.i32, operands, Type.i32, reportNode);
+ case BuiltinNames.i64_atomic_rmw8_xor_u: return deferASM(BuiltinNames.atomic_xor, compiler, Type.u8, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_atomic_rmw16_xor_u: return deferASM(BuiltinNames.atomic_xor, compiler, Type.u16, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_atomic_rmw32_xor_u: return deferASM(BuiltinNames.atomic_xor, compiler, Type.u32, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_atomic_rmw_xor: return deferASM(BuiltinNames.atomic_xor, compiler, Type.i64, operands, Type.i64, reportNode);
- case BuiltinSymbols.i32_atomic_rmw8_xchg_u: return deferASM(BuiltinSymbols.atomic_xchg, compiler, Type.u8, operands, Type.i32, reportNode);
- case BuiltinSymbols.i32_atomic_rmw16_xchg_u: return deferASM(BuiltinSymbols.atomic_xchg, compiler, Type.u16, operands, Type.i32, reportNode);
- case BuiltinSymbols.i32_atomic_rmw_xchg: return deferASM(BuiltinSymbols.atomic_xchg, compiler, Type.i32, operands, Type.i32, reportNode);
- case BuiltinSymbols.i64_atomic_rmw8_xchg_u: return deferASM(BuiltinSymbols.atomic_xchg, compiler, Type.u8, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_atomic_rmw16_xchg_u: return deferASM(BuiltinSymbols.atomic_xchg, compiler, Type.u16, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_atomic_rmw32_xchg_u: return deferASM(BuiltinSymbols.atomic_xchg, compiler, Type.u32, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_atomic_rmw_xchg: return deferASM(BuiltinSymbols.atomic_xchg, compiler, Type.i64, operands, Type.i64, reportNode);
+ case BuiltinNames.i32_atomic_rmw8_xchg_u: return deferASM(BuiltinNames.atomic_xchg, compiler, Type.u8, operands, Type.i32, reportNode);
+ case BuiltinNames.i32_atomic_rmw16_xchg_u: return deferASM(BuiltinNames.atomic_xchg, compiler, Type.u16, operands, Type.i32, reportNode);
+ case BuiltinNames.i32_atomic_rmw_xchg: return deferASM(BuiltinNames.atomic_xchg, compiler, Type.i32, operands, Type.i32, reportNode);
+ case BuiltinNames.i64_atomic_rmw8_xchg_u: return deferASM(BuiltinNames.atomic_xchg, compiler, Type.u8, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_atomic_rmw16_xchg_u: return deferASM(BuiltinNames.atomic_xchg, compiler, Type.u16, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_atomic_rmw32_xchg_u: return deferASM(BuiltinNames.atomic_xchg, compiler, Type.u32, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_atomic_rmw_xchg: return deferASM(BuiltinNames.atomic_xchg, compiler, Type.i64, operands, Type.i64, reportNode);
- case BuiltinSymbols.i32_atomic_rmw8_cmpxchg_u: return deferASM(BuiltinSymbols.atomic_cmpxchg, compiler, Type.u8, operands, Type.i32, reportNode);
- case BuiltinSymbols.i32_atomic_rmw16_cmpxchg_u: return deferASM(BuiltinSymbols.atomic_cmpxchg, compiler, Type.u16, operands, Type.i32, reportNode);
- case BuiltinSymbols.i32_atomic_rmw_cmpxchg: return deferASM(BuiltinSymbols.atomic_cmpxchg, compiler, Type.i32, operands, Type.i32, reportNode);
- case BuiltinSymbols.i64_atomic_rmw8_cmpxchg_u: return deferASM(BuiltinSymbols.atomic_cmpxchg, compiler, Type.u8, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_atomic_rmw16_cmpxchg_u: return deferASM(BuiltinSymbols.atomic_cmpxchg, compiler, Type.u16, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_atomic_rmw32_cmpxchg_u: return deferASM(BuiltinSymbols.atomic_cmpxchg, compiler, Type.u32, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64_atomic_rmw_cmpxchg: return deferASM(BuiltinSymbols.atomic_cmpxchg, compiler, Type.i64, operands, Type.i64, reportNode);
+ case BuiltinNames.i32_atomic_rmw8_cmpxchg_u: return deferASM(BuiltinNames.atomic_cmpxchg, compiler, Type.u8, operands, Type.i32, reportNode);
+ case BuiltinNames.i32_atomic_rmw16_cmpxchg_u: return deferASM(BuiltinNames.atomic_cmpxchg, compiler, Type.u16, operands, Type.i32, reportNode);
+ case BuiltinNames.i32_atomic_rmw_cmpxchg: return deferASM(BuiltinNames.atomic_cmpxchg, compiler, Type.i32, operands, Type.i32, reportNode);
+ case BuiltinNames.i64_atomic_rmw8_cmpxchg_u: return deferASM(BuiltinNames.atomic_cmpxchg, compiler, Type.u8, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_atomic_rmw16_cmpxchg_u: return deferASM(BuiltinNames.atomic_cmpxchg, compiler, Type.u16, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_atomic_rmw32_cmpxchg_u: return deferASM(BuiltinNames.atomic_cmpxchg, compiler, Type.u32, operands, Type.i64, reportNode);
+ case BuiltinNames.i64_atomic_rmw_cmpxchg: return deferASM(BuiltinNames.atomic_cmpxchg, compiler, Type.i64, operands, Type.i64, reportNode);
- case BuiltinSymbols.i32_wait: return deferASM(BuiltinSymbols.atomic_wait, compiler, Type.i32, operands, Type.i32, reportNode);
- case BuiltinSymbols.i64_wait: return deferASM(BuiltinSymbols.atomic_wait, compiler, Type.i64, operands, Type.i32, reportNode);
+ case BuiltinNames.i32_wait: return deferASM(BuiltinNames.atomic_wait, compiler, Type.i32, operands, Type.i32, reportNode);
+ case BuiltinNames.i64_wait: return deferASM(BuiltinNames.atomic_wait, compiler, Type.i64, operands, Type.i32, reportNode);
- case BuiltinSymbols.v128_load: return deferASM(BuiltinSymbols.load, compiler, Type.v128, operands, Type.v128, reportNode);
- case BuiltinSymbols.v128_store: return deferASM(BuiltinSymbols.store, compiler, Type.v128, operands, Type.v128, reportNode);
+ case BuiltinNames.v128_load: return deferASM(BuiltinNames.load, compiler, Type.v128, operands, Type.v128, reportNode);
+ case BuiltinNames.v128_store: return deferASM(BuiltinNames.store, compiler, Type.v128, operands, Type.v128, reportNode);
- case BuiltinSymbols.i8x16_splat: return deferASM(BuiltinSymbols.v128_splat, compiler, Type.i8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i8x16_extract_lane_s: return deferASM(BuiltinSymbols.v128_extract_lane, compiler, Type.i8, operands, Type.i8, reportNode);
- case BuiltinSymbols.i8x16_extract_lane_u: return deferASM(BuiltinSymbols.v128_extract_lane, compiler, Type.u8, operands, Type.u8, reportNode);
- case BuiltinSymbols.i8x16_replace_lane: return deferASM(BuiltinSymbols.v128_replace_lane, compiler, Type.i8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i8x16_add: return deferASM(BuiltinSymbols.v128_add, compiler, Type.i8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i8x16_sub: return deferASM(BuiltinSymbols.v128_sub, compiler, Type.i8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i8x16_mul: return deferASM(BuiltinSymbols.v128_mul, compiler, Type.i8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i8x16_min_s: return deferASM(BuiltinSymbols.v128_min, compiler, Type.i8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i8x16_min_u: return deferASM(BuiltinSymbols.v128_min, compiler, Type.u8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i8x16_max_s: return deferASM(BuiltinSymbols.v128_max, compiler, Type.i8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i8x16_max_u: return deferASM(BuiltinSymbols.v128_max, compiler, Type.u8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i8x16_avgr_u: return deferASM(BuiltinSymbols.v128_avgr, compiler, Type.u8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i8x16_neg: return deferASM(BuiltinSymbols.v128_neg, compiler, Type.i8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i8x16_add_saturate_s: return deferASM(BuiltinSymbols.v128_add_saturate, compiler, Type.i8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i8x16_add_saturate_u: return deferASM(BuiltinSymbols.v128_add_saturate, compiler, Type.u8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i8x16_sub_saturate_s: return deferASM(BuiltinSymbols.v128_sub_saturate, compiler, Type.i8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i8x16_sub_saturate_u: return deferASM(BuiltinSymbols.v128_sub_saturate, compiler, Type.u8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i8x16_shl: return deferASM(BuiltinSymbols.v128_shl, compiler, Type.i8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i8x16_shr_s: return deferASM(BuiltinSymbols.v128_shr, compiler, Type.i8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i8x16_shr_u: return deferASM(BuiltinSymbols.v128_shr, compiler, Type.u8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i8x16_any_true: return deferASM(BuiltinSymbols.v128_any_true, compiler, Type.i8, operands, Type.i32, reportNode);
- case BuiltinSymbols.i8x16_all_true: return deferASM(BuiltinSymbols.v128_all_true, compiler, Type.i8, operands, Type.i32, reportNode);
- case BuiltinSymbols.i8x16_eq: return deferASM(BuiltinSymbols.v128_eq, compiler, Type.i8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i8x16_ne: return deferASM(BuiltinSymbols.v128_ne, compiler, Type.i8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i8x16_lt_s: return deferASM(BuiltinSymbols.v128_lt, compiler, Type.i8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i8x16_lt_u: return deferASM(BuiltinSymbols.v128_lt, compiler, Type.u8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i8x16_le_s: return deferASM(BuiltinSymbols.v128_le, compiler, Type.i8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i8x16_le_u: return deferASM(BuiltinSymbols.v128_le, compiler, Type.u8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i8x16_gt_s: return deferASM(BuiltinSymbols.v128_gt, compiler, Type.i8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i8x16_gt_u: return deferASM(BuiltinSymbols.v128_gt, compiler, Type.u8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i8x16_ge_s: return deferASM(BuiltinSymbols.v128_ge, compiler, Type.i8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i8x16_ge_u: return deferASM(BuiltinSymbols.v128_ge, compiler, Type.u8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i8x16_narrow_i16x8_s: return deferASM(BuiltinSymbols.v128_narrow, compiler, Type.i16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i8x16_narrow_i16x8_u: return deferASM(BuiltinSymbols.v128_narrow, compiler, Type.u16, operands, Type.v128, reportNode);
+ case BuiltinNames.i8x16_splat: return deferASM(BuiltinNames.v128_splat, compiler, Type.i8, operands, Type.v128, reportNode);
+ case BuiltinNames.i8x16_extract_lane_s: return deferASM(BuiltinNames.v128_extract_lane, compiler, Type.i8, operands, Type.i8, reportNode);
+ case BuiltinNames.i8x16_extract_lane_u: return deferASM(BuiltinNames.v128_extract_lane, compiler, Type.u8, operands, Type.u8, reportNode);
+ case BuiltinNames.i8x16_replace_lane: return deferASM(BuiltinNames.v128_replace_lane, compiler, Type.i8, operands, Type.v128, reportNode);
+ case BuiltinNames.i8x16_add: return deferASM(BuiltinNames.v128_add, compiler, Type.i8, operands, Type.v128, reportNode);
+ case BuiltinNames.i8x16_sub: return deferASM(BuiltinNames.v128_sub, compiler, Type.i8, operands, Type.v128, reportNode);
+ case BuiltinNames.i8x16_mul: return deferASM(BuiltinNames.v128_mul, compiler, Type.i8, operands, Type.v128, reportNode);
+ case BuiltinNames.i8x16_min_s: return deferASM(BuiltinNames.v128_min, compiler, Type.i8, operands, Type.v128, reportNode);
+ case BuiltinNames.i8x16_min_u: return deferASM(BuiltinNames.v128_min, compiler, Type.u8, operands, Type.v128, reportNode);
+ case BuiltinNames.i8x16_max_s: return deferASM(BuiltinNames.v128_max, compiler, Type.i8, operands, Type.v128, reportNode);
+ case BuiltinNames.i8x16_max_u: return deferASM(BuiltinNames.v128_max, compiler, Type.u8, operands, Type.v128, reportNode);
+ case BuiltinNames.i8x16_avgr_u: return deferASM(BuiltinNames.v128_avgr, compiler, Type.u8, operands, Type.v128, reportNode);
+ case BuiltinNames.i8x16_neg: return deferASM(BuiltinNames.v128_neg, compiler, Type.i8, operands, Type.v128, reportNode);
+ case BuiltinNames.i8x16_add_saturate_s: return deferASM(BuiltinNames.v128_add_saturate, compiler, Type.i8, operands, Type.v128, reportNode);
+ case BuiltinNames.i8x16_add_saturate_u: return deferASM(BuiltinNames.v128_add_saturate, compiler, Type.u8, operands, Type.v128, reportNode);
+ case BuiltinNames.i8x16_sub_saturate_s: return deferASM(BuiltinNames.v128_sub_saturate, compiler, Type.i8, operands, Type.v128, reportNode);
+ case BuiltinNames.i8x16_sub_saturate_u: return deferASM(BuiltinNames.v128_sub_saturate, compiler, Type.u8, operands, Type.v128, reportNode);
+ case BuiltinNames.i8x16_shl: return deferASM(BuiltinNames.v128_shl, compiler, Type.i8, operands, Type.v128, reportNode);
+ case BuiltinNames.i8x16_shr_s: return deferASM(BuiltinNames.v128_shr, compiler, Type.i8, operands, Type.v128, reportNode);
+ case BuiltinNames.i8x16_shr_u: return deferASM(BuiltinNames.v128_shr, compiler, Type.u8, operands, Type.v128, reportNode);
+ case BuiltinNames.i8x16_any_true: return deferASM(BuiltinNames.v128_any_true, compiler, Type.i8, operands, Type.i32, reportNode);
+ case BuiltinNames.i8x16_all_true: return deferASM(BuiltinNames.v128_all_true, compiler, Type.i8, operands, Type.i32, reportNode);
+ case BuiltinNames.i8x16_eq: return deferASM(BuiltinNames.v128_eq, compiler, Type.i8, operands, Type.v128, reportNode);
+ case BuiltinNames.i8x16_ne: return deferASM(BuiltinNames.v128_ne, compiler, Type.i8, operands, Type.v128, reportNode);
+ case BuiltinNames.i8x16_lt_s: return deferASM(BuiltinNames.v128_lt, compiler, Type.i8, operands, Type.v128, reportNode);
+ case BuiltinNames.i8x16_lt_u: return deferASM(BuiltinNames.v128_lt, compiler, Type.u8, operands, Type.v128, reportNode);
+ case BuiltinNames.i8x16_le_s: return deferASM(BuiltinNames.v128_le, compiler, Type.i8, operands, Type.v128, reportNode);
+ case BuiltinNames.i8x16_le_u: return deferASM(BuiltinNames.v128_le, compiler, Type.u8, operands, Type.v128, reportNode);
+ case BuiltinNames.i8x16_gt_s: return deferASM(BuiltinNames.v128_gt, compiler, Type.i8, operands, Type.v128, reportNode);
+ case BuiltinNames.i8x16_gt_u: return deferASM(BuiltinNames.v128_gt, compiler, Type.u8, operands, Type.v128, reportNode);
+ case BuiltinNames.i8x16_ge_s: return deferASM(BuiltinNames.v128_ge, compiler, Type.i8, operands, Type.v128, reportNode);
+ case BuiltinNames.i8x16_ge_u: return deferASM(BuiltinNames.v128_ge, compiler, Type.u8, operands, Type.v128, reportNode);
+ case BuiltinNames.i8x16_narrow_i16x8_s: return deferASM(BuiltinNames.v128_narrow, compiler, Type.i16, operands, Type.v128, reportNode);
+ case BuiltinNames.i8x16_narrow_i16x8_u: return deferASM(BuiltinNames.v128_narrow, compiler, Type.u16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_splat: return deferASM(BuiltinSymbols.v128_splat, compiler, Type.i16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_extract_lane_s: return deferASM(BuiltinSymbols.v128_extract_lane, compiler, Type.i16, operands, Type.i16, reportNode);
- case BuiltinSymbols.i16x8_extract_lane_u: return deferASM(BuiltinSymbols.v128_extract_lane, compiler, Type.u16, operands, Type.u16, reportNode);
- case BuiltinSymbols.i16x8_replace_lane: return deferASM(BuiltinSymbols.v128_replace_lane, compiler, Type.i16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_add: return deferASM(BuiltinSymbols.v128_add, compiler, Type.i16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_sub: return deferASM(BuiltinSymbols.v128_sub, compiler, Type.i16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_mul: return deferASM(BuiltinSymbols.v128_mul, compiler, Type.i16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_min_s: return deferASM(BuiltinSymbols.v128_min, compiler, Type.i16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_min_u: return deferASM(BuiltinSymbols.v128_min, compiler, Type.u16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_max_s: return deferASM(BuiltinSymbols.v128_max, compiler, Type.i16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_max_u: return deferASM(BuiltinSymbols.v128_max, compiler, Type.u16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_avgr_u: return deferASM(BuiltinSymbols.v128_avgr, compiler, Type.u16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_neg: return deferASM(BuiltinSymbols.v128_neg, compiler, Type.i16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_add_saturate_s: return deferASM(BuiltinSymbols.v128_add_saturate, compiler, Type.i16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_add_saturate_u: return deferASM(BuiltinSymbols.v128_add_saturate, compiler, Type.u16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_sub_saturate_s: return deferASM(BuiltinSymbols.v128_sub_saturate, compiler, Type.i16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_sub_saturate_u: return deferASM(BuiltinSymbols.v128_sub_saturate, compiler, Type.u16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_shl: return deferASM(BuiltinSymbols.v128_shl, compiler, Type.i16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_shr_s: return deferASM(BuiltinSymbols.v128_shr, compiler, Type.i16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_shr_u: return deferASM(BuiltinSymbols.v128_shr, compiler, Type.u16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_any_true: return deferASM(BuiltinSymbols.v128_any_true, compiler, Type.i16, operands, Type.i32, reportNode);
- case BuiltinSymbols.i16x8_all_true: return deferASM(BuiltinSymbols.v128_all_true, compiler, Type.i16, operands, Type.i32, reportNode);
- case BuiltinSymbols.i16x8_eq: return deferASM(BuiltinSymbols.v128_eq, compiler, Type.i16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_ne: return deferASM(BuiltinSymbols.v128_ne, compiler, Type.i16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_lt_s: return deferASM(BuiltinSymbols.v128_lt, compiler, Type.i16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_lt_u: return deferASM(BuiltinSymbols.v128_lt, compiler, Type.u16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_le_s: return deferASM(BuiltinSymbols.v128_le, compiler, Type.i16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_le_u: return deferASM(BuiltinSymbols.v128_le, compiler, Type.u16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_gt_s: return deferASM(BuiltinSymbols.v128_gt, compiler, Type.i16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_gt_u: return deferASM(BuiltinSymbols.v128_gt, compiler, Type.u16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_ge_s: return deferASM(BuiltinSymbols.v128_ge, compiler, Type.i16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_ge_u: return deferASM(BuiltinSymbols.v128_ge, compiler, Type.u16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_narrow_i32x4_s: return deferASM(BuiltinSymbols.v128_narrow, compiler, Type.i32, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_narrow_i32x4_u: return deferASM(BuiltinSymbols.v128_narrow, compiler, Type.u32, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_widen_low_i8x16_s: return deferASM(BuiltinSymbols.v128_widen_low, compiler, Type.i8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_widen_low_i8x16_u: return deferASM(BuiltinSymbols.v128_widen_low, compiler, Type.u8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_widen_high_i8x16_s: return deferASM(BuiltinSymbols.v128_widen_high, compiler, Type.i8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_widen_high_i8x16_u: return deferASM(BuiltinSymbols.v128_widen_high, compiler, Type.u8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_load8x8_s: return deferASM(BuiltinSymbols.v128_load_ext, compiler, Type.i8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i16x8_load8x8_u: return deferASM(BuiltinSymbols.v128_load_ext, compiler, Type.u8, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_splat: return deferASM(BuiltinNames.v128_splat, compiler, Type.i16, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_extract_lane_s: return deferASM(BuiltinNames.v128_extract_lane, compiler, Type.i16, operands, Type.i16, reportNode);
+ case BuiltinNames.i16x8_extract_lane_u: return deferASM(BuiltinNames.v128_extract_lane, compiler, Type.u16, operands, Type.u16, reportNode);
+ case BuiltinNames.i16x8_replace_lane: return deferASM(BuiltinNames.v128_replace_lane, compiler, Type.i16, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_add: return deferASM(BuiltinNames.v128_add, compiler, Type.i16, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_sub: return deferASM(BuiltinNames.v128_sub, compiler, Type.i16, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_mul: return deferASM(BuiltinNames.v128_mul, compiler, Type.i16, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_min_s: return deferASM(BuiltinNames.v128_min, compiler, Type.i16, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_min_u: return deferASM(BuiltinNames.v128_min, compiler, Type.u16, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_max_s: return deferASM(BuiltinNames.v128_max, compiler, Type.i16, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_max_u: return deferASM(BuiltinNames.v128_max, compiler, Type.u16, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_avgr_u: return deferASM(BuiltinNames.v128_avgr, compiler, Type.u16, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_neg: return deferASM(BuiltinNames.v128_neg, compiler, Type.i16, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_add_saturate_s: return deferASM(BuiltinNames.v128_add_saturate, compiler, Type.i16, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_add_saturate_u: return deferASM(BuiltinNames.v128_add_saturate, compiler, Type.u16, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_sub_saturate_s: return deferASM(BuiltinNames.v128_sub_saturate, compiler, Type.i16, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_sub_saturate_u: return deferASM(BuiltinNames.v128_sub_saturate, compiler, Type.u16, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_shl: return deferASM(BuiltinNames.v128_shl, compiler, Type.i16, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_shr_s: return deferASM(BuiltinNames.v128_shr, compiler, Type.i16, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_shr_u: return deferASM(BuiltinNames.v128_shr, compiler, Type.u16, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_any_true: return deferASM(BuiltinNames.v128_any_true, compiler, Type.i16, operands, Type.i32, reportNode);
+ case BuiltinNames.i16x8_all_true: return deferASM(BuiltinNames.v128_all_true, compiler, Type.i16, operands, Type.i32, reportNode);
+ case BuiltinNames.i16x8_eq: return deferASM(BuiltinNames.v128_eq, compiler, Type.i16, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_ne: return deferASM(BuiltinNames.v128_ne, compiler, Type.i16, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_lt_s: return deferASM(BuiltinNames.v128_lt, compiler, Type.i16, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_lt_u: return deferASM(BuiltinNames.v128_lt, compiler, Type.u16, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_le_s: return deferASM(BuiltinNames.v128_le, compiler, Type.i16, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_le_u: return deferASM(BuiltinNames.v128_le, compiler, Type.u16, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_gt_s: return deferASM(BuiltinNames.v128_gt, compiler, Type.i16, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_gt_u: return deferASM(BuiltinNames.v128_gt, compiler, Type.u16, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_ge_s: return deferASM(BuiltinNames.v128_ge, compiler, Type.i16, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_ge_u: return deferASM(BuiltinNames.v128_ge, compiler, Type.u16, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_narrow_i32x4_s: return deferASM(BuiltinNames.v128_narrow, compiler, Type.i32, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_narrow_i32x4_u: return deferASM(BuiltinNames.v128_narrow, compiler, Type.u32, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_widen_low_i8x16_s: return deferASM(BuiltinNames.v128_widen_low, compiler, Type.i8, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_widen_low_i8x16_u: return deferASM(BuiltinNames.v128_widen_low, compiler, Type.u8, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_widen_high_i8x16_s: return deferASM(BuiltinNames.v128_widen_high, compiler, Type.i8, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_widen_high_i8x16_u: return deferASM(BuiltinNames.v128_widen_high, compiler, Type.u8, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_load8x8_s: return deferASM(BuiltinNames.v128_load_ext, compiler, Type.i8, operands, Type.v128, reportNode);
+ case BuiltinNames.i16x8_load8x8_u: return deferASM(BuiltinNames.v128_load_ext, compiler, Type.u8, operands, Type.v128, reportNode);
- case BuiltinSymbols.i32x4_splat: return deferASM(BuiltinSymbols.v128_splat, compiler, Type.i32, operands, Type.v128, reportNode);
- case BuiltinSymbols.i32x4_extract_lane: return deferASM(BuiltinSymbols.v128_extract_lane, compiler, Type.i32, operands, Type.i32, reportNode);
- case BuiltinSymbols.i32x4_replace_lane: return deferASM(BuiltinSymbols.v128_replace_lane, compiler, Type.i32, operands, Type.v128, reportNode);
- case BuiltinSymbols.i32x4_add: return deferASM(BuiltinSymbols.v128_add, compiler, Type.i32, operands, Type.v128, reportNode);
- case BuiltinSymbols.i32x4_sub: return deferASM(BuiltinSymbols.v128_sub, compiler, Type.i32, operands, Type.v128, reportNode);
- case BuiltinSymbols.i32x4_mul: return deferASM(BuiltinSymbols.v128_mul, compiler, Type.i32, operands, Type.v128, reportNode);
- case BuiltinSymbols.i32x4_min_s: return deferASM(BuiltinSymbols.v128_min, compiler, Type.i32, operands, Type.v128, reportNode);
- case BuiltinSymbols.i32x4_min_u: return deferASM(BuiltinSymbols.v128_min, compiler, Type.u32, operands, Type.v128, reportNode);
- case BuiltinSymbols.i32x4_max_s: return deferASM(BuiltinSymbols.v128_max, compiler, Type.i32, operands, Type.v128, reportNode);
- case BuiltinSymbols.i32x4_max_u: return deferASM(BuiltinSymbols.v128_max, compiler, Type.u32, operands, Type.v128, reportNode);
- case BuiltinSymbols.i32x4_dot_i16x8_s: return deferASM(BuiltinSymbols.v128_dot, compiler, Type.i16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i32x4_neg: return deferASM(BuiltinSymbols.v128_neg, compiler, Type.i32, operands, Type.v128, reportNode);
- case BuiltinSymbols.i32x4_shl: return deferASM(BuiltinSymbols.v128_shl, compiler, Type.i32, operands, Type.v128, reportNode);
- case BuiltinSymbols.i32x4_shr_s: return deferASM(BuiltinSymbols.v128_shr, compiler, Type.i32, operands, Type.v128, reportNode);
- case BuiltinSymbols.i32x4_shr_u: return deferASM(BuiltinSymbols.v128_shr, compiler, Type.u32, operands, Type.v128, reportNode);
- case BuiltinSymbols.i32x4_any_true: return deferASM(BuiltinSymbols.v128_any_true, compiler, Type.i32, operands, Type.i32, reportNode);
- case BuiltinSymbols.i32x4_all_true: return deferASM(BuiltinSymbols.v128_all_true, compiler, Type.i32, operands, Type.i32, reportNode);
- case BuiltinSymbols.i32x4_eq: return deferASM(BuiltinSymbols.v128_eq, compiler, Type.i32, operands, Type.v128, reportNode);
- case BuiltinSymbols.i32x4_ne: return deferASM(BuiltinSymbols.v128_ne, compiler, Type.i32, operands, Type.v128, reportNode);
- case BuiltinSymbols.i32x4_lt_s: return deferASM(BuiltinSymbols.v128_lt, compiler, Type.i32, operands, Type.v128, reportNode);
- case BuiltinSymbols.i32x4_lt_u: return deferASM(BuiltinSymbols.v128_lt, compiler, Type.u32, operands, Type.v128, reportNode);
- case BuiltinSymbols.i32x4_le_s: return deferASM(BuiltinSymbols.v128_le, compiler, Type.i32, operands, Type.v128, reportNode);
- case BuiltinSymbols.i32x4_le_u: return deferASM(BuiltinSymbols.v128_le, compiler, Type.u32, operands, Type.v128, reportNode);
- case BuiltinSymbols.i32x4_gt_s: return deferASM(BuiltinSymbols.v128_gt, compiler, Type.i32, operands, Type.v128, reportNode);
- case BuiltinSymbols.i32x4_gt_u: return deferASM(BuiltinSymbols.v128_gt, compiler, Type.u32, operands, Type.v128, reportNode);
- case BuiltinSymbols.i32x4_ge_s: return deferASM(BuiltinSymbols.v128_ge, compiler, Type.i32, operands, Type.v128, reportNode);
- case BuiltinSymbols.i32x4_ge_u: return deferASM(BuiltinSymbols.v128_ge, compiler, Type.u32, operands, Type.v128, reportNode);
- case BuiltinSymbols.i32x4_trunc_sat_f32x4_s: return deferASM(BuiltinSymbols.v128_trunc_sat, compiler, Type.i32, operands, Type.v128, reportNode);
- case BuiltinSymbols.i32x4_trunc_sat_f32x4_u: return deferASM(BuiltinSymbols.v128_trunc_sat, compiler, Type.u32, operands, Type.v128, reportNode);
- case BuiltinSymbols.i32x4_widen_low_i16x8_s: return deferASM(BuiltinSymbols.v128_widen_low, compiler, Type.i16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i32x4_widen_low_i16x8_u: return deferASM(BuiltinSymbols.v128_widen_low, compiler, Type.u16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i32x4_widen_high_i16x8_s: return deferASM(BuiltinSymbols.v128_widen_high, compiler, Type.i16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i32x4_widen_high_i16x8_u: return deferASM(BuiltinSymbols.v128_widen_high, compiler, Type.u16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i32x4_load16x4_s: return deferASM(BuiltinSymbols.v128_load_ext, compiler, Type.i16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i32x4_load16x4_u: return deferASM(BuiltinSymbols.v128_load_ext, compiler, Type.u16, operands, Type.v128, reportNode);
+ case BuiltinNames.i32x4_splat: return deferASM(BuiltinNames.v128_splat, compiler, Type.i32, operands, Type.v128, reportNode);
+ case BuiltinNames.i32x4_extract_lane: return deferASM(BuiltinNames.v128_extract_lane, compiler, Type.i32, operands, Type.i32, reportNode);
+ case BuiltinNames.i32x4_replace_lane: return deferASM(BuiltinNames.v128_replace_lane, compiler, Type.i32, operands, Type.v128, reportNode);
+ case BuiltinNames.i32x4_add: return deferASM(BuiltinNames.v128_add, compiler, Type.i32, operands, Type.v128, reportNode);
+ case BuiltinNames.i32x4_sub: return deferASM(BuiltinNames.v128_sub, compiler, Type.i32, operands, Type.v128, reportNode);
+ case BuiltinNames.i32x4_mul: return deferASM(BuiltinNames.v128_mul, compiler, Type.i32, operands, Type.v128, reportNode);
+ case BuiltinNames.i32x4_min_s: return deferASM(BuiltinNames.v128_min, compiler, Type.i32, operands, Type.v128, reportNode);
+ case BuiltinNames.i32x4_min_u: return deferASM(BuiltinNames.v128_min, compiler, Type.u32, operands, Type.v128, reportNode);
+ case BuiltinNames.i32x4_max_s: return deferASM(BuiltinNames.v128_max, compiler, Type.i32, operands, Type.v128, reportNode);
+ case BuiltinNames.i32x4_max_u: return deferASM(BuiltinNames.v128_max, compiler, Type.u32, operands, Type.v128, reportNode);
+ case BuiltinNames.i32x4_dot_i16x8_s: return deferASM(BuiltinNames.v128_dot, compiler, Type.i16, operands, Type.v128, reportNode);
+ case BuiltinNames.i32x4_neg: return deferASM(BuiltinNames.v128_neg, compiler, Type.i32, operands, Type.v128, reportNode);
+ case BuiltinNames.i32x4_shl: return deferASM(BuiltinNames.v128_shl, compiler, Type.i32, operands, Type.v128, reportNode);
+ case BuiltinNames.i32x4_shr_s: return deferASM(BuiltinNames.v128_shr, compiler, Type.i32, operands, Type.v128, reportNode);
+ case BuiltinNames.i32x4_shr_u: return deferASM(BuiltinNames.v128_shr, compiler, Type.u32, operands, Type.v128, reportNode);
+ case BuiltinNames.i32x4_any_true: return deferASM(BuiltinNames.v128_any_true, compiler, Type.i32, operands, Type.i32, reportNode);
+ case BuiltinNames.i32x4_all_true: return deferASM(BuiltinNames.v128_all_true, compiler, Type.i32, operands, Type.i32, reportNode);
+ case BuiltinNames.i32x4_eq: return deferASM(BuiltinNames.v128_eq, compiler, Type.i32, operands, Type.v128, reportNode);
+ case BuiltinNames.i32x4_ne: return deferASM(BuiltinNames.v128_ne, compiler, Type.i32, operands, Type.v128, reportNode);
+ case BuiltinNames.i32x4_lt_s: return deferASM(BuiltinNames.v128_lt, compiler, Type.i32, operands, Type.v128, reportNode);
+ case BuiltinNames.i32x4_lt_u: return deferASM(BuiltinNames.v128_lt, compiler, Type.u32, operands, Type.v128, reportNode);
+ case BuiltinNames.i32x4_le_s: return deferASM(BuiltinNames.v128_le, compiler, Type.i32, operands, Type.v128, reportNode);
+ case BuiltinNames.i32x4_le_u: return deferASM(BuiltinNames.v128_le, compiler, Type.u32, operands, Type.v128, reportNode);
+ case BuiltinNames.i32x4_gt_s: return deferASM(BuiltinNames.v128_gt, compiler, Type.i32, operands, Type.v128, reportNode);
+ case BuiltinNames.i32x4_gt_u: return deferASM(BuiltinNames.v128_gt, compiler, Type.u32, operands, Type.v128, reportNode);
+ case BuiltinNames.i32x4_ge_s: return deferASM(BuiltinNames.v128_ge, compiler, Type.i32, operands, Type.v128, reportNode);
+ case BuiltinNames.i32x4_ge_u: return deferASM(BuiltinNames.v128_ge, compiler, Type.u32, operands, Type.v128, reportNode);
+ case BuiltinNames.i32x4_trunc_sat_f32x4_s: return deferASM(BuiltinNames.v128_trunc_sat, compiler, Type.i32, operands, Type.v128, reportNode);
+ case BuiltinNames.i32x4_trunc_sat_f32x4_u: return deferASM(BuiltinNames.v128_trunc_sat, compiler, Type.u32, operands, Type.v128, reportNode);
+ case BuiltinNames.i32x4_widen_low_i16x8_s: return deferASM(BuiltinNames.v128_widen_low, compiler, Type.i16, operands, Type.v128, reportNode);
+ case BuiltinNames.i32x4_widen_low_i16x8_u: return deferASM(BuiltinNames.v128_widen_low, compiler, Type.u16, operands, Type.v128, reportNode);
+ case BuiltinNames.i32x4_widen_high_i16x8_s: return deferASM(BuiltinNames.v128_widen_high, compiler, Type.i16, operands, Type.v128, reportNode);
+ case BuiltinNames.i32x4_widen_high_i16x8_u: return deferASM(BuiltinNames.v128_widen_high, compiler, Type.u16, operands, Type.v128, reportNode);
+ case BuiltinNames.i32x4_load16x4_s: return deferASM(BuiltinNames.v128_load_ext, compiler, Type.i16, operands, Type.v128, reportNode);
+ case BuiltinNames.i32x4_load16x4_u: return deferASM(BuiltinNames.v128_load_ext, compiler, Type.u16, operands, Type.v128, reportNode);
- case BuiltinSymbols.i64x2_splat: return deferASM(BuiltinSymbols.v128_splat, compiler, Type.i64, operands, Type.v128, reportNode);
- case BuiltinSymbols.i64x2_extract_lane: return deferASM(BuiltinSymbols.v128_extract_lane, compiler, Type.i64, operands, Type.i64, reportNode);
- case BuiltinSymbols.i64x2_replace_lane: return deferASM(BuiltinSymbols.v128_replace_lane, compiler, Type.i64, operands, Type.v128, reportNode);
- case BuiltinSymbols.i64x2_add: return deferASM(BuiltinSymbols.v128_add, compiler, Type.i64, operands, Type.v128, reportNode);
- case BuiltinSymbols.i64x2_sub: return deferASM(BuiltinSymbols.v128_sub, compiler, Type.i64, operands, Type.v128, reportNode);
- case BuiltinSymbols.i64x2_neg: return deferASM(BuiltinSymbols.v128_neg, compiler, Type.i64, operands, Type.v128, reportNode);
- case BuiltinSymbols.i64x2_shl: return deferASM(BuiltinSymbols.v128_shl, compiler, Type.i64, operands, Type.v128, reportNode);
- case BuiltinSymbols.i64x2_shr_s: return deferASM(BuiltinSymbols.v128_shr, compiler, Type.i64, operands, Type.v128, reportNode);
- case BuiltinSymbols.i64x2_shr_u: return deferASM(BuiltinSymbols.v128_shr, compiler, Type.u64, operands, Type.v128, reportNode);
- case BuiltinSymbols.i64x2_any_true: return deferASM(BuiltinSymbols.v128_any_true, compiler, Type.i64, operands, Type.i32, reportNode);
- case BuiltinSymbols.i64x2_all_true: return deferASM(BuiltinSymbols.v128_all_true, compiler, Type.i64, operands, Type.i32, reportNode);
- case BuiltinSymbols.i64x2_trunc_sat_f64x2_s: return deferASM(BuiltinSymbols.v128_trunc_sat, compiler, Type.i64, operands, Type.v128, reportNode);
- case BuiltinSymbols.i64x2_trunc_sat_f64x2_u: return deferASM(BuiltinSymbols.v128_trunc_sat, compiler, Type.u64, operands, Type.v128, reportNode);
- case BuiltinSymbols.i64x2_load32x2_s: return deferASM(BuiltinSymbols.v128_load_ext, compiler, Type.i32, operands, Type.v128, reportNode);
- case BuiltinSymbols.i64x2_load32x2_u: return deferASM(BuiltinSymbols.v128_load_ext, compiler, Type.u32, operands, Type.v128, reportNode);
+ case BuiltinNames.i64x2_splat: return deferASM(BuiltinNames.v128_splat, compiler, Type.i64, operands, Type.v128, reportNode);
+ case BuiltinNames.i64x2_extract_lane: return deferASM(BuiltinNames.v128_extract_lane, compiler, Type.i64, operands, Type.i64, reportNode);
+ case BuiltinNames.i64x2_replace_lane: return deferASM(BuiltinNames.v128_replace_lane, compiler, Type.i64, operands, Type.v128, reportNode);
+ case BuiltinNames.i64x2_add: return deferASM(BuiltinNames.v128_add, compiler, Type.i64, operands, Type.v128, reportNode);
+ case BuiltinNames.i64x2_sub: return deferASM(BuiltinNames.v128_sub, compiler, Type.i64, operands, Type.v128, reportNode);
+ case BuiltinNames.i64x2_neg: return deferASM(BuiltinNames.v128_neg, compiler, Type.i64, operands, Type.v128, reportNode);
+ case BuiltinNames.i64x2_shl: return deferASM(BuiltinNames.v128_shl, compiler, Type.i64, operands, Type.v128, reportNode);
+ case BuiltinNames.i64x2_shr_s: return deferASM(BuiltinNames.v128_shr, compiler, Type.i64, operands, Type.v128, reportNode);
+ case BuiltinNames.i64x2_shr_u: return deferASM(BuiltinNames.v128_shr, compiler, Type.u64, operands, Type.v128, reportNode);
+ case BuiltinNames.i64x2_any_true: return deferASM(BuiltinNames.v128_any_true, compiler, Type.i64, operands, Type.i32, reportNode);
+ case BuiltinNames.i64x2_all_true: return deferASM(BuiltinNames.v128_all_true, compiler, Type.i64, operands, Type.i32, reportNode);
+ case BuiltinNames.i64x2_trunc_sat_f64x2_s: return deferASM(BuiltinNames.v128_trunc_sat, compiler, Type.i64, operands, Type.v128, reportNode);
+ case BuiltinNames.i64x2_trunc_sat_f64x2_u: return deferASM(BuiltinNames.v128_trunc_sat, compiler, Type.u64, operands, Type.v128, reportNode);
+ case BuiltinNames.i64x2_load32x2_s: return deferASM(BuiltinNames.v128_load_ext, compiler, Type.i32, operands, Type.v128, reportNode);
+ case BuiltinNames.i64x2_load32x2_u: return deferASM(BuiltinNames.v128_load_ext, compiler, Type.u32, operands, Type.v128, reportNode);
- case BuiltinSymbols.f32x4_splat: return deferASM(BuiltinSymbols.v128_splat, compiler, Type.f32, operands, Type.v128, reportNode);
- case BuiltinSymbols.f32x4_extract_lane: return deferASM(BuiltinSymbols.v128_extract_lane, compiler, Type.f32, operands, Type.f32, reportNode);
- case BuiltinSymbols.f32x4_replace_lane: return deferASM(BuiltinSymbols.v128_replace_lane, compiler, Type.f32, operands, Type.v128, reportNode);
- case BuiltinSymbols.f32x4_add: return deferASM(BuiltinSymbols.v128_add, compiler, Type.f32, operands, Type.v128, reportNode);
- case BuiltinSymbols.f32x4_sub: return deferASM(BuiltinSymbols.v128_sub, compiler, Type.f32, operands, Type.v128, reportNode);
- case BuiltinSymbols.f32x4_mul: return deferASM(BuiltinSymbols.v128_mul, compiler, Type.f32, operands, Type.v128, reportNode);
- case BuiltinSymbols.f32x4_div: return deferASM(BuiltinSymbols.v128_div, compiler, Type.f32, operands, Type.v128, reportNode);
- case BuiltinSymbols.f32x4_neg: return deferASM(BuiltinSymbols.v128_neg, compiler, Type.f32, operands, Type.v128, reportNode);
- case BuiltinSymbols.f32x4_min: return deferASM(BuiltinSymbols.v128_min, compiler, Type.f32, operands, Type.v128, reportNode);
- case BuiltinSymbols.f32x4_max: return deferASM(BuiltinSymbols.v128_max, compiler, Type.f32, operands, Type.v128, reportNode);
- case BuiltinSymbols.f32x4_abs: return deferASM(BuiltinSymbols.v128_abs, compiler, Type.f32, operands, Type.v128, reportNode);
- case BuiltinSymbols.f32x4_sqrt: return deferASM(BuiltinSymbols.v128_sqrt, compiler, Type.f32, operands, Type.v128, reportNode);
- case BuiltinSymbols.f32x4_eq: return deferASM(BuiltinSymbols.v128_eq, compiler, Type.f32, operands, Type.v128, reportNode);
- case BuiltinSymbols.f32x4_ne: return deferASM(BuiltinSymbols.v128_ne, compiler, Type.f32, operands, Type.v128, reportNode);
- case BuiltinSymbols.f32x4_lt: return deferASM(BuiltinSymbols.v128_lt, compiler, Type.f32, operands, Type.v128, reportNode);
- case BuiltinSymbols.f32x4_le: return deferASM(BuiltinSymbols.v128_le, compiler, Type.f32, operands, Type.v128, reportNode);
- case BuiltinSymbols.f32x4_gt: return deferASM(BuiltinSymbols.v128_gt, compiler, Type.f32, operands, Type.v128, reportNode);
- case BuiltinSymbols.f32x4_ge: return deferASM(BuiltinSymbols.v128_ge, compiler, Type.f32, operands, Type.v128, reportNode);
- case BuiltinSymbols.f32x4_convert_i32x4_s: return deferASM(BuiltinSymbols.v128_convert, compiler, Type.i32, operands, Type.v128, reportNode);
- case BuiltinSymbols.f32x4_convert_i32x4_u: return deferASM(BuiltinSymbols.v128_convert, compiler, Type.u32, operands, Type.v128, reportNode);
- case BuiltinSymbols.f32x4_qfma: return deferASM(BuiltinSymbols.v128_qfma, compiler, Type.f32, operands, Type.v128, reportNode);
- case BuiltinSymbols.f32x4_qfms: return deferASM(BuiltinSymbols.v128_qfms, compiler, Type.f32, operands, Type.v128, reportNode);
+ case BuiltinNames.f32x4_splat: return deferASM(BuiltinNames.v128_splat, compiler, Type.f32, operands, Type.v128, reportNode);
+ case BuiltinNames.f32x4_extract_lane: return deferASM(BuiltinNames.v128_extract_lane, compiler, Type.f32, operands, Type.f32, reportNode);
+ case BuiltinNames.f32x4_replace_lane: return deferASM(BuiltinNames.v128_replace_lane, compiler, Type.f32, operands, Type.v128, reportNode);
+ case BuiltinNames.f32x4_add: return deferASM(BuiltinNames.v128_add, compiler, Type.f32, operands, Type.v128, reportNode);
+ case BuiltinNames.f32x4_sub: return deferASM(BuiltinNames.v128_sub, compiler, Type.f32, operands, Type.v128, reportNode);
+ case BuiltinNames.f32x4_mul: return deferASM(BuiltinNames.v128_mul, compiler, Type.f32, operands, Type.v128, reportNode);
+ case BuiltinNames.f32x4_div: return deferASM(BuiltinNames.v128_div, compiler, Type.f32, operands, Type.v128, reportNode);
+ case BuiltinNames.f32x4_neg: return deferASM(BuiltinNames.v128_neg, compiler, Type.f32, operands, Type.v128, reportNode);
+ case BuiltinNames.f32x4_min: return deferASM(BuiltinNames.v128_min, compiler, Type.f32, operands, Type.v128, reportNode);
+ case BuiltinNames.f32x4_max: return deferASM(BuiltinNames.v128_max, compiler, Type.f32, operands, Type.v128, reportNode);
+ case BuiltinNames.f32x4_abs: return deferASM(BuiltinNames.v128_abs, compiler, Type.f32, operands, Type.v128, reportNode);
+ case BuiltinNames.f32x4_sqrt: return deferASM(BuiltinNames.v128_sqrt, compiler, Type.f32, operands, Type.v128, reportNode);
+ case BuiltinNames.f32x4_eq: return deferASM(BuiltinNames.v128_eq, compiler, Type.f32, operands, Type.v128, reportNode);
+ case BuiltinNames.f32x4_ne: return deferASM(BuiltinNames.v128_ne, compiler, Type.f32, operands, Type.v128, reportNode);
+ case BuiltinNames.f32x4_lt: return deferASM(BuiltinNames.v128_lt, compiler, Type.f32, operands, Type.v128, reportNode);
+ case BuiltinNames.f32x4_le: return deferASM(BuiltinNames.v128_le, compiler, Type.f32, operands, Type.v128, reportNode);
+ case BuiltinNames.f32x4_gt: return deferASM(BuiltinNames.v128_gt, compiler, Type.f32, operands, Type.v128, reportNode);
+ case BuiltinNames.f32x4_ge: return deferASM(BuiltinNames.v128_ge, compiler, Type.f32, operands, Type.v128, reportNode);
+ case BuiltinNames.f32x4_convert_i32x4_s: return deferASM(BuiltinNames.v128_convert, compiler, Type.i32, operands, Type.v128, reportNode);
+ case BuiltinNames.f32x4_convert_i32x4_u: return deferASM(BuiltinNames.v128_convert, compiler, Type.u32, operands, Type.v128, reportNode);
+ case BuiltinNames.f32x4_qfma: return deferASM(BuiltinNames.v128_qfma, compiler, Type.f32, operands, Type.v128, reportNode);
+ case BuiltinNames.f32x4_qfms: return deferASM(BuiltinNames.v128_qfms, compiler, Type.f32, operands, Type.v128, reportNode);
- case BuiltinSymbols.f64x2_splat: return deferASM(BuiltinSymbols.v128_splat, compiler, Type.f64, operands, Type.v128, reportNode);
- case BuiltinSymbols.f64x2_extract_lane: return deferASM(BuiltinSymbols.v128_extract_lane, compiler, Type.f64, operands, Type.f64, reportNode);
- case BuiltinSymbols.f64x2_replace_lane: return deferASM(BuiltinSymbols.v128_replace_lane, compiler, Type.f64, operands, Type.v128, reportNode);
- case BuiltinSymbols.f64x2_add: return deferASM(BuiltinSymbols.v128_add, compiler, Type.f64, operands, Type.v128, reportNode);
- case BuiltinSymbols.f64x2_sub: return deferASM(BuiltinSymbols.v128_sub, compiler, Type.f64, operands, Type.v128, reportNode);
- case BuiltinSymbols.f64x2_mul: return deferASM(BuiltinSymbols.v128_mul, compiler, Type.f64, operands, Type.v128, reportNode);
- case BuiltinSymbols.f64x2_div: return deferASM(BuiltinSymbols.v128_div, compiler, Type.f64, operands, Type.v128, reportNode);
- case BuiltinSymbols.f64x2_neg: return deferASM(BuiltinSymbols.v128_neg, compiler, Type.f64, operands, Type.v128, reportNode);
- case BuiltinSymbols.f64x2_min: return deferASM(BuiltinSymbols.v128_min, compiler, Type.f64, operands, Type.v128, reportNode);
- case BuiltinSymbols.f64x2_max: return deferASM(BuiltinSymbols.v128_max, compiler, Type.f64, operands, Type.v128, reportNode);
- case BuiltinSymbols.f64x2_abs: return deferASM(BuiltinSymbols.v128_abs, compiler, Type.f64, operands, Type.v128, reportNode);
- case BuiltinSymbols.f64x2_sqrt: return deferASM(BuiltinSymbols.v128_sqrt, compiler, Type.f64, operands, Type.v128, reportNode);
- case BuiltinSymbols.f64x2_eq: return deferASM(BuiltinSymbols.v128_eq, compiler, Type.f64, operands, Type.v128, reportNode);
- case BuiltinSymbols.f64x2_ne: return deferASM(BuiltinSymbols.v128_ne, compiler, Type.f64, operands, Type.v128, reportNode);
- case BuiltinSymbols.f64x2_lt: return deferASM(BuiltinSymbols.v128_lt, compiler, Type.f64, operands, Type.v128, reportNode);
- case BuiltinSymbols.f64x2_le: return deferASM(BuiltinSymbols.v128_le, compiler, Type.f64, operands, Type.v128, reportNode);
- case BuiltinSymbols.f64x2_gt: return deferASM(BuiltinSymbols.v128_gt, compiler, Type.f64, operands, Type.v128, reportNode);
- case BuiltinSymbols.f64x2_ge: return deferASM(BuiltinSymbols.v128_ge, compiler, Type.f64, operands, Type.v128, reportNode);
- case BuiltinSymbols.f64x2_convert_i64x2_s: return deferASM(BuiltinSymbols.v128_convert, compiler, Type.i64, operands, Type.v128, reportNode);
- case BuiltinSymbols.f64x2_convert_i64x2_u: return deferASM(BuiltinSymbols.v128_convert, compiler, Type.u64, operands, Type.v128, reportNode);
- case BuiltinSymbols.f64x2_qfma: return deferASM(BuiltinSymbols.v128_qfma, compiler, Type.f64, operands, Type.v128, reportNode);
- case BuiltinSymbols.f64x2_qfms: return deferASM(BuiltinSymbols.v128_qfms, compiler, Type.f64, operands, Type.v128, reportNode);
+ case BuiltinNames.f64x2_splat: return deferASM(BuiltinNames.v128_splat, compiler, Type.f64, operands, Type.v128, reportNode);
+ case BuiltinNames.f64x2_extract_lane: return deferASM(BuiltinNames.v128_extract_lane, compiler, Type.f64, operands, Type.f64, reportNode);
+ case BuiltinNames.f64x2_replace_lane: return deferASM(BuiltinNames.v128_replace_lane, compiler, Type.f64, operands, Type.v128, reportNode);
+ case BuiltinNames.f64x2_add: return deferASM(BuiltinNames.v128_add, compiler, Type.f64, operands, Type.v128, reportNode);
+ case BuiltinNames.f64x2_sub: return deferASM(BuiltinNames.v128_sub, compiler, Type.f64, operands, Type.v128, reportNode);
+ case BuiltinNames.f64x2_mul: return deferASM(BuiltinNames.v128_mul, compiler, Type.f64, operands, Type.v128, reportNode);
+ case BuiltinNames.f64x2_div: return deferASM(BuiltinNames.v128_div, compiler, Type.f64, operands, Type.v128, reportNode);
+ case BuiltinNames.f64x2_neg: return deferASM(BuiltinNames.v128_neg, compiler, Type.f64, operands, Type.v128, reportNode);
+ case BuiltinNames.f64x2_min: return deferASM(BuiltinNames.v128_min, compiler, Type.f64, operands, Type.v128, reportNode);
+ case BuiltinNames.f64x2_max: return deferASM(BuiltinNames.v128_max, compiler, Type.f64, operands, Type.v128, reportNode);
+ case BuiltinNames.f64x2_abs: return deferASM(BuiltinNames.v128_abs, compiler, Type.f64, operands, Type.v128, reportNode);
+ case BuiltinNames.f64x2_sqrt: return deferASM(BuiltinNames.v128_sqrt, compiler, Type.f64, operands, Type.v128, reportNode);
+ case BuiltinNames.f64x2_eq: return deferASM(BuiltinNames.v128_eq, compiler, Type.f64, operands, Type.v128, reportNode);
+ case BuiltinNames.f64x2_ne: return deferASM(BuiltinNames.v128_ne, compiler, Type.f64, operands, Type.v128, reportNode);
+ case BuiltinNames.f64x2_lt: return deferASM(BuiltinNames.v128_lt, compiler, Type.f64, operands, Type.v128, reportNode);
+ case BuiltinNames.f64x2_le: return deferASM(BuiltinNames.v128_le, compiler, Type.f64, operands, Type.v128, reportNode);
+ case BuiltinNames.f64x2_gt: return deferASM(BuiltinNames.v128_gt, compiler, Type.f64, operands, Type.v128, reportNode);
+ case BuiltinNames.f64x2_ge: return deferASM(BuiltinNames.v128_ge, compiler, Type.f64, operands, Type.v128, reportNode);
+ case BuiltinNames.f64x2_convert_i64x2_s: return deferASM(BuiltinNames.v128_convert, compiler, Type.i64, operands, Type.v128, reportNode);
+ case BuiltinNames.f64x2_convert_i64x2_u: return deferASM(BuiltinNames.v128_convert, compiler, Type.u64, operands, Type.v128, reportNode);
+ case BuiltinNames.f64x2_qfma: return deferASM(BuiltinNames.v128_qfma, compiler, Type.f64, operands, Type.v128, reportNode);
+ case BuiltinNames.f64x2_qfms: return deferASM(BuiltinNames.v128_qfms, compiler, Type.f64, operands, Type.v128, reportNode);
- case BuiltinSymbols.v8x16_shuffle: return deferASM(BuiltinSymbols.v128_shuffle, compiler, Type.i8, operands, Type.v128, reportNode);
- case BuiltinSymbols.v8x16_swizzle: return deferASM(BuiltinSymbols.v128_swizzle, compiler, null, operands, Type.v128, reportNode);
- case BuiltinSymbols.v8x16_load_splat: return deferASM(BuiltinSymbols.v128_load_splat, compiler, Type.u8, operands, Type.v128, reportNode);
- case BuiltinSymbols.v16x8_load_splat: return deferASM(BuiltinSymbols.v128_load_splat, compiler, Type.u16, operands, Type.v128, reportNode);
- case BuiltinSymbols.v32x4_load_splat: return deferASM(BuiltinSymbols.v128_load_splat, compiler, Type.u32, operands, Type.v128, reportNode);
- case BuiltinSymbols.v64x2_load_splat: return deferASM(BuiltinSymbols.v128_load_splat, compiler, Type.u64, operands, Type.v128, reportNode);
+ case BuiltinNames.v8x16_shuffle: return deferASM(BuiltinNames.v128_shuffle, compiler, Type.i8, operands, Type.v128, reportNode);
+ case BuiltinNames.v8x16_swizzle: return deferASM(BuiltinNames.v128_swizzle, compiler, null, operands, Type.v128, reportNode);
+ case BuiltinNames.v8x16_load_splat: return deferASM(BuiltinNames.v128_load_splat, compiler, Type.u8, operands, Type.v128, reportNode);
+ case BuiltinNames.v16x8_load_splat: return deferASM(BuiltinNames.v128_load_splat, compiler, Type.u16, operands, Type.v128, reportNode);
+ case BuiltinNames.v32x4_load_splat: return deferASM(BuiltinNames.v128_load_splat, compiler, Type.u32, operands, Type.v128, reportNode);
+ case BuiltinNames.v64x2_load_splat: return deferASM(BuiltinNames.v128_load_splat, compiler, Type.u64, operands, Type.v128, reportNode);
}
/* tslint:enable:max-line-length */
return 0;
@@ -4828,7 +4815,7 @@ export function compileVisitGlobals(compiler: Compiler): void {
}
}
}
- module.addFunction(BuiltinSymbols.visit_globals,
+ module.addFunction(BuiltinNames.visit_globals,
NativeType.I32, // cookie
NativeType.None, // => void
[ nativeSizeType ],
@@ -4933,7 +4920,7 @@ export function compileVisitMembers(compiler: Compiler): void {
}
if (!instance.base) code.push(module.return());
let block = relooper.addBlock(
- flatten(module, code, NativeType.None)
+ module.flatten(code)
);
relooper.addBranchForSwitch(outer, block, [ id ]);
blocks.push(block);
@@ -4951,7 +4938,7 @@ export function compileVisitMembers(compiler: Compiler): void {
);
relooper.addBranchForSwitch(outer, blocks[blocks.length - 1], []); // default
compiler.compileFunction(visitInstance);
- module.addFunction(BuiltinSymbols.visit_members,
+ module.addFunction(BuiltinNames.visit_members,
createType([ usizeType.toNativeType(), NativeType.I32 ]), // ref, cookie
NativeType.None, // => void
[ nativeSizeType ],
@@ -5015,9 +5002,9 @@ export function compileRTTI(compiler: Compiler): void {
var segment = compiler.addMemorySegment(data);
if (usizeType.size == 8) {
let offset = segment.offset;
- module.addGlobal(BuiltinSymbols.rtti_base, NativeType.I64, false, module.i64(i64_low(offset), i64_high(offset)));
+ module.addGlobal(BuiltinNames.rtti_base, NativeType.I64, false, module.i64(i64_low(offset), i64_high(offset)));
} else {
- module.addGlobal(BuiltinSymbols.rtti_base, NativeType.I32, false, module.i32(i64_low(segment.offset)));
+ module.addGlobal(BuiltinNames.rtti_base, NativeType.I32, false, module.i32(i64_low(segment.offset)));
}
}
diff --git a/src/common.ts b/src/common.ts
index 600a560fd4..849485c240 100644
--- a/src/common.ts
+++ b/src/common.ts
@@ -100,8 +100,8 @@ export const LIBRARY_PREFIX = LIBRARY_SUBST + PATH_DELIMITER;
/** Path index suffix. */
export const INDEX_SUFFIX = PATH_DELIMITER + "index";
-/** Common compiler symbols. */
-export namespace CommonSymbols {
+/** Common names. */
+export namespace CommonNames {
// special
export const EMPTY = "";
// types
diff --git a/src/compiler.ts b/src/compiler.ts
index 48d3a1088c..2c68a86340 100644
--- a/src/compiler.ts
+++ b/src/compiler.ts
@@ -4,7 +4,7 @@
*//***/
import {
- BuiltinSymbols,
+ BuiltinNames,
compileCall as compileBuiltinCall,
compileAbort,
compileVisitGlobals,
@@ -27,7 +27,6 @@ import {
FunctionRef,
ExpressionId,
GlobalRef,
- EventRef,
FeatureFlags,
getExpressionId,
getExpressionType,
@@ -46,7 +45,8 @@ import {
getLocalSetValue,
getGlobalGetName,
isGlobalMutable,
- createType
+ createType,
+ hasSideEffects
} from "./module";
import {
@@ -55,7 +55,7 @@ import {
STATIC_DELIMITER,
GETTER_PREFIX,
SETTER_PREFIX,
- CommonSymbols,
+ CommonNames,
INDEX_SUFFIX,
Feature,
Target
@@ -90,6 +90,7 @@ import {
FlowFlags,
Flow,
LocalFlags,
+ ConditionKind,
findUsedLocals
} from "./flow";
@@ -106,10 +107,10 @@ import {
import {
Node,
NodeKind,
- NamedTypeNode,
Range,
DecoratorKind,
AssertionKind,
+ SourceKind,
Statement,
BlockStatement,
@@ -120,6 +121,7 @@ import {
DoStatement,
EmptyStatement,
EnumDeclaration,
+ ExportDefaultStatement,
ExportStatement,
ExpressionStatement,
FieldDeclaration,
@@ -128,7 +130,6 @@ import {
IfStatement,
ImportStatement,
InstanceOfExpression,
- InterfaceDeclaration,
NamespaceDeclaration,
ReturnStatement,
SwitchStatement,
@@ -162,9 +163,7 @@ import {
nodeIsConstantValue,
findDecorator,
- isTypeOmitted,
- ExportDefaultStatement,
- SourceKind
+ isTypeOmitted
} from "./ast";
import {
@@ -276,6 +275,18 @@ export const enum RuntimeFeatures {
visitMembers = 1 << 3
}
+/** Exported names of compiler-generated elements. */
+export namespace ExportNames {
+ /** Name of the explicit start function, if applicable. */
+ export const start = "_start"; // match WASI
+ /** Name of the argumentsLength varargs helper global. */
+ export const argumentsLength = "__argumentsLength";
+ /** Name of the memory instance, if exported. */
+ export const memory = "memory";
+ /** Name of the table instance, if exported. */
+ export const table = "table";
+}
+
/** Compiler interface. */
export class Compiler extends DiagnosticEmitter {
@@ -287,10 +298,9 @@ export class Compiler extends DiagnosticEmitter {
get options(): Options { return this.program.options; }
/** Module instance being compiled. */
module: Module;
+
/** Current control flow. */
currentFlow: Flow;
- /** Current inline functions stack. */
- currentInlineFunctions: Function[] = [];
/** Current parent element if not a function, i.e. an enum or namespace. */
currentParent: Element | null = null;
/** Current type in compilation. */
@@ -305,16 +315,14 @@ export class Compiler extends DiagnosticEmitter {
stringSegments: Map = new Map();
/** Function table being compiled. First elem is blank. */
functionTable: string[] = [];
- /** Argument count helper global. */
- argcVar: GlobalRef = 0;
- /** Argument count helper setter. */
- argcSet: FunctionRef = 0;
+ /** Arguments length helper global. */
+ builtinArgumentsLength: GlobalRef = 0;
/** Requires runtime features. */
runtimeFeatures: RuntimeFeatures = RuntimeFeatures.NONE;
/** Expressions known to have skipped an autorelease. Usually function returns. */
skippedAutoreleases: Set = new Set();
- /** Registered event types. */
- events: Map = new Map();
+ /** Current inline functions stack. */
+ inlineStack: Function[] = [];
/** Compiles a {@link Program} to a {@link Module} using the specified options. */
static compile(program: Program): Module {
@@ -356,19 +364,19 @@ export class Compiler extends DiagnosticEmitter {
program.initialize(options);
// set up the main start function
- var startFunctionInstance = program.makeNativeFunction("start", new Signature(program, [], Type.void));
- startFunctionInstance.internalName = "start";
+ var startFunctionInstance = program.makeNativeFunction(BuiltinNames.start, new Signature(program, [], Type.void));
+ startFunctionInstance.internalName = BuiltinNames.start;
var startFunctionBody = new Array();
this.currentFlow = startFunctionInstance.flow;
this.currentBody = startFunctionBody;
- // add a mutable heap and rtti base dummies
+ // add mutable heap and rtti base dummies
if (options.isWasm64) {
- module.addGlobal(BuiltinSymbols.heap_base, NativeType.I64, true, module.i64(0));
- module.addGlobal(BuiltinSymbols.rtti_base, NativeType.I64, true, module.i64(0));
+ module.addGlobal(BuiltinNames.heap_base, NativeType.I64, true, module.i64(0));
+ module.addGlobal(BuiltinNames.rtti_base, NativeType.I64, true, module.i64(0));
} else {
- module.addGlobal(BuiltinSymbols.heap_base, NativeType.I32, true, module.i32(0));
- module.addGlobal(BuiltinSymbols.rtti_base, NativeType.I32, true, module.i32(0));
+ module.addGlobal(BuiltinNames.heap_base, NativeType.I32, true, module.i32(0));
+ module.addGlobal(BuiltinNames.rtti_base, NativeType.I32, true, module.i32(0));
}
// compile entry file(s) while traversing reachable elements
@@ -386,12 +394,12 @@ export class Compiler extends DiagnosticEmitter {
if (!startIsEmpty || explicitStart) {
let signature = startFunctionInstance.signature;
if (!startIsEmpty && explicitStart) {
- module.addGlobal(BuiltinSymbols.started, NativeType.I32, true, module.i32(0));
+ module.addGlobal(BuiltinNames.started, NativeType.I32, true, module.i32(0));
startFunctionBody.unshift(
module.if(
- module.global_get(BuiltinSymbols.started, NativeType.I32),
+ module.global_get(BuiltinNames.started, NativeType.I32),
module.return(),
- module.global_set(BuiltinSymbols.started, module.i32(1))
+ module.global_set(BuiltinNames.started, module.i32(1))
)
);
}
@@ -400,35 +408,35 @@ export class Compiler extends DiagnosticEmitter {
signature.nativeParams,
signature.nativeResults,
typesToNativeTypes(startFunctionInstance.additionalLocals),
- module.block(null, startFunctionBody)
+ module.flatten(startFunctionBody)
);
startFunctionInstance.finalize(module, funcRef);
if (!explicitStart) module.setStart(funcRef);
- else module.addFunctionExport(startFunctionInstance.internalName, "_start");
+ else module.addFunctionExport(startFunctionInstance.internalName, ExportNames.start);
}
// compile runtime features
if (this.runtimeFeatures & RuntimeFeatures.visitGlobals) compileVisitGlobals(this);
if (this.runtimeFeatures & RuntimeFeatures.visitMembers) compileVisitMembers(this);
- module.removeGlobal(BuiltinSymbols.rtti_base);
+ module.removeGlobal(BuiltinNames.rtti_base);
if (this.runtimeFeatures & RuntimeFeatures.RTTI) compileRTTI(this);
// update the heap base pointer
var memoryOffset = this.memoryOffset;
memoryOffset = i64_align(memoryOffset, options.usizeType.byteSize);
this.memoryOffset = memoryOffset;
- module.removeGlobal(BuiltinSymbols.heap_base);
+ module.removeGlobal(BuiltinNames.heap_base);
if (this.runtimeFeatures & RuntimeFeatures.HEAP) {
if (options.isWasm64) {
module.addGlobal(
- BuiltinSymbols.heap_base,
+ BuiltinNames.heap_base,
NativeType.I64,
false,
module.i64(i64_low(memoryOffset), i64_high(memoryOffset))
);
} else {
module.addGlobal(
- BuiltinSymbols.heap_base,
+ BuiltinNames.heap_base,
NativeType.I32,
false,
module.i32(i64_low(memoryOffset))
@@ -445,7 +453,7 @@ export class Compiler extends DiagnosticEmitter {
isSharedMemory ? options.sharedMemory : Module.UNLIMITED_MEMORY,
this.memorySegments,
options.target,
- "memory",
+ ExportNames.memory,
isSharedMemory
);
@@ -458,7 +466,7 @@ export class Compiler extends DiagnosticEmitter {
// import and/or export table if requested (default table is named '0' by Binaryen)
if (options.importTable) module.addTableImport("0", "env", "table");
- if (options.exportTable) module.addTableExport("0", "table");
+ if (options.exportTable) module.addTableExport("0", ExportNames.table);
// set up module exports
for (let file of this.program.filesByName.values()) {
@@ -514,8 +522,8 @@ export class Compiler extends DiagnosticEmitter {
}
case ElementKind.PROPERTY_PROTOTYPE: {
let getter = (element).getterPrototype;
- let setter = (element).setterPrototype;
if (getter) this.ensureModuleExport(GETTER_PREFIX + name, getter, prefix);
+ let setter = (element).setterPrototype;
if (setter) this.ensureModuleExport(SETTER_PREFIX + name, setter, prefix);
break;
}
@@ -550,7 +558,7 @@ export class Compiler extends DiagnosticEmitter {
if (signature.requiredParameters < signature.parameterTypes.length) {
// utilize trampoline to fill in omitted arguments
instance = this.ensureTrampoline(instance);
- this.ensureArgcSet();
+ this.ensureBuiltinArgumentsLength();
}
if (instance.is(CommonFlags.COMPILED)) this.module.addFunctionExport(instance.internalName, prefix + name);
break;
@@ -563,9 +571,9 @@ export class Compiler extends DiagnosticEmitter {
break;
}
case ElementKind.FIELD: {
- this.ensureModuleFieldGetter(prefix + GETTER_PREFIX + name, element);
+ this.makeExportedFieldGetter(prefix + GETTER_PREFIX + name, element);
if (!element.is(CommonFlags.READONLY)) {
- this.ensureModuleFieldSetter(prefix + SETTER_PREFIX + name, element);
+ this.makeExportedFieldSetter(prefix + SETTER_PREFIX + name, element);
}
break;
}
@@ -614,55 +622,43 @@ export class Compiler extends DiagnosticEmitter {
}
}
- /** Makes a function to get the value of a field of an exported class. */
- private ensureModuleFieldGetter(name: string, field: Field): void {
+ /** Makes an exported function to get the value of an instance field. */
+ private makeExportedFieldGetter(name: string, field: Field): void {
var type = field.type;
+ var nativeThisType = this.options.nativeSizeType;
+ var nativeValueType = type.toNativeType();
var module = this.module;
- var usizeType = this.options.usizeType;
- var loadExpr = module.load(type.byteSize, type.is(TypeFlags.SIGNED),
- module.local_get(0, usizeType.toNativeType()),
- type.toNativeType(), field.memoryOffset
- );
- // a user-defined getter would return a retained value, so:
- if (type.isManaged) loadExpr = this.makeRetain(loadExpr);
- module.addFunction(
- name,
- usizeType.toNativeType(),
- type.toNativeType(),
- null,
- loadExpr
+ var returnExpr = module.load(type.byteSize, type.is(TypeFlags.SIGNED),
+ module.local_get(0, nativeThisType),
+ nativeValueType, field.memoryOffset
);
+ // functions retain the return value for the caller
+ if (type.isManaged) returnExpr = this.makeRetain(returnExpr);
+ module.addFunction(name, nativeThisType, nativeValueType, null, returnExpr);
module.addFunctionExport(name, name);
}
- /** Makes a function to set the value of a field of an exported class. */
- private ensureModuleFieldSetter(name: string, field: Field): void {
+ /** Makes an exported function to set the value of an instance field. */
+ private makeExportedFieldSetter(name: string, field: Field): void {
var type = field.type;
+ var nativeThisType = this.options.nativeSizeType;
+ var nativeValueType = type.toNativeType();
var module = this.module;
- var nativeType = type.toNativeType();
- var usizeType = this.options.usizeType;
- var nativeSizeType = usizeType.toNativeType();
- var valueExpr = module.local_get(1, nativeType);
+ var valueExpr = module.local_get(1, nativeValueType);
if (type.isManaged) {
valueExpr = this.makeReplace(
- module.load(type.byteSize, false, // oldRef
- module.local_get(0, nativeSizeType),
- nativeType, field.memoryOffset
+ module.load(type.byteSize, false,
+ module.local_get(0, nativeThisType),
+ nativeValueType, field.memoryOffset
),
- valueExpr // newRef
+ valueExpr
);
}
- module.addFunction(
- name,
- createType([ usizeType.toNativeType(), type.toNativeType() ]),
- NativeType.None,
- null,
- module.store(
- type.byteSize,
- module.local_get(0, nativeSizeType),
+ module.addFunction(name, createType([ nativeThisType, nativeValueType ]), NativeType.None, null,
+ module.store(type.byteSize,
+ module.local_get(0, nativeThisType),
valueExpr,
- nativeType,
- field.memoryOffset
+ nativeValueType, field.memoryOffset
)
);
module.addFunctionExport(name, name);
@@ -683,24 +679,30 @@ export class Compiler extends DiagnosticEmitter {
}
case ElementKind.FUNCTION_PROTOTYPE: {
if (!element.is(CommonFlags.GENERIC)) {
- this.compileFunctionUsingTypeArguments(element, []);
+ let instance = this.resolver.resolveFunction(element, null);
+ if (instance) this.compileFunction(instance);
}
break;
}
case ElementKind.CLASS_PROTOTYPE: {
if (!element.is(CommonFlags.GENERIC)) {
- this.compileClassUsingTypeArguments(element, []);
+ let instance = this.resolver.resolveClass(element, null);
+ if (instance) this.compileClass(instance);
}
break;
}
case ElementKind.PROPERTY_PROTOTYPE: {
let getterPrototype = (element).getterPrototype;
if (getterPrototype) {
- this.compileFunctionUsingTypeArguments(getterPrototype, []);
+ assert(!getterPrototype.is(CommonFlags.GENERIC));
+ let instance = this.resolver.resolveFunction(getterPrototype, null);
+ if (instance) this.compileFunction(instance);
}
let setterPrototype = (element).setterPrototype;
if (setterPrototype) {
- this.compileFunctionUsingTypeArguments(setterPrototype, []);
+ assert(!setterPrototype.is(CommonFlags.GENERIC));
+ let instance = this.resolver.resolveFunction(setterPrototype, null);
+ if (instance) this.compileFunction(instance);
}
break;
}
@@ -710,13 +712,10 @@ export class Compiler extends DiagnosticEmitter {
case ElementKind.INDEXSIGNATURE: break;
default: assert(false, ElementKind[element.kind]);
}
- if (compileMembers) this.compileMembers(element);
- }
-
- /** Compiles an element's members. */
- compileMembers(element: Element): void {
- var members = element.members;
- if (members) for (let element of members.values()) this.compileElement(element);
+ if (compileMembers) {
+ let members = element.members;
+ if (members) for (let element of members.values()) this.compileElement(element);
+ }
}
/** Compiles a file's exports. */
@@ -773,6 +772,7 @@ export class Compiler extends DiagnosticEmitter {
this.compileTopLevelStatement(statements[i], startFunctionBody);
}
this.finishAutoreleases(flow, startFunctionBody);
+ // no need to insert unreachable since last statement should have done that
this.currentFlow = previousFlow;
this.currentBody = previousBody;
@@ -783,15 +783,12 @@ export class Compiler extends DiagnosticEmitter {
let numLocals = locals.length;
let varTypes = new Array(numLocals);
for (let i = 0; i < numLocals; ++i) varTypes[i] = locals[i].type.toNativeType();
-
module.addFunction(
startFunction.internalName,
startSignature.nativeParams,
startSignature.nativeResults,
varTypes,
- startFunctionBody.length > 1
- ? module.block(null, startFunctionBody)
- : startFunctionBody[0]
+ module.flatten(startFunctionBody)
);
previousBody.push(
module.call(startFunction.internalName, null, NativeType.None)
@@ -801,13 +798,13 @@ export class Compiler extends DiagnosticEmitter {
// === Globals ==================================================================================
+ /** Compiles a global variable. */
compileGlobal(global: Global): bool {
if (global.is(CommonFlags.COMPILED)) return true;
global.set(CommonFlags.COMPILED);
var module = this.module;
var initExpr: ExpressionRef = 0;
- var initAutoreleaseSkipped: bool = false;
var typeNode = global.typeNode;
var initializerNode = global.initializerNode;
@@ -835,7 +832,6 @@ export class Compiler extends DiagnosticEmitter {
initExpr = this.compileExpression(initializerNode, Type.auto, // reports
Constraints.MUST_WRAP | Constraints.WILL_RETAIN
);
- if (this.skippedAutoreleases.has(initExpr)) initAutoreleaseSkipped = true;
this.currentFlow = previousFlow;
if (this.currentType == Type.void) {
this.error(
@@ -858,8 +854,8 @@ export class Compiler extends DiagnosticEmitter {
// Handle ambient builtins like '__heap_base' that need to be resolved but are added explicitly
if (global.is(CommonFlags.AMBIENT) && global.hasDecorator(DecoratorFlags.BUILTIN)) {
- if (global.internalName == BuiltinSymbols.heap_base) this.runtimeFeatures |= RuntimeFeatures.HEAP;
- else if (global.internalName == BuiltinSymbols.rtti_base) this.runtimeFeatures |= RuntimeFeatures.RTTI;
+ if (global.internalName == BuiltinNames.heap_base) this.runtimeFeatures |= RuntimeFeatures.HEAP;
+ else if (global.internalName == BuiltinNames.rtti_base) this.runtimeFeatures |= RuntimeFeatures.RTTI;
return true;
}
@@ -909,15 +905,16 @@ export class Compiler extends DiagnosticEmitter {
initExpr = this.compileExpression(initializerNode, type,
Constraints.CONV_IMPLICIT | Constraints.MUST_WRAP | Constraints.WILL_RETAIN | Constraints.PREFER_STATIC
);
- if (this.skippedAutoreleases.has(initExpr)) initAutoreleaseSkipped = true;
this.currentFlow = previousFlow;
}
// If not a constant, attempt to precompute
if (getExpressionId(initExpr) != ExpressionId.Const) {
if (isDeclaredConstant) {
+ let origInitExpr = initExpr;
initExpr = module.precomputeExpression(initExpr);
if (getExpressionId(initExpr) != ExpressionId.Const) initializeInStart = true;
+ if (this.skippedAutoreleases.has(origInitExpr)) this.skippedAutoreleases.add(initExpr);
} else {
initializeInStart = true;
}
@@ -993,7 +990,7 @@ export class Compiler extends DiagnosticEmitter {
);
}
module.addGlobal(internalName, nativeType, true, this.makeZero(type));
- if (type.isManaged && !initAutoreleaseSkipped) initExpr = this.makeRetain(initExpr);
+ if (type.isManaged && !this.skippedAutoreleases.has(initExpr)) initExpr = this.makeRetain(initExpr);
this.currentBody.push(
module.global_set(internalName, initExpr)
);
@@ -1005,6 +1002,7 @@ export class Compiler extends DiagnosticEmitter {
// === Enums ====================================================================================
+ /** Compiles an enum. */
compileEnum(element: Enum): bool {
if (element.is(CommonFlags.COMPILED)) return true;
element.set(CommonFlags.COMPILED);
@@ -1096,136 +1094,17 @@ export class Compiler extends DiagnosticEmitter {
// === Functions ================================================================================
- /** Resolves the specified type arguments prior to compiling the resulting function instance. */
- compileFunctionUsingTypeArguments(
- prototype: FunctionPrototype,
- typeArguments: NamedTypeNode[],
- contextualTypeArguments: Map = makeMap(),
- alternativeReportNode: Node | null = null
- ): Function | null {
- if (prototype.hasDecorator(DecoratorFlags.BUILTIN)) return null;
- var instance = this.resolver.resolveFunctionInclTypeArguments(
- prototype,
- typeArguments,
- prototype.parent, // relative to itself
- contextualTypeArguments,
- alternativeReportNode || prototype.declaration
- );
- if (!instance) return null;
- if (!this.compileFunction(instance)) return null; // reports
- return instance;
- }
-
- /** Compiles the body of a function within the specified flow. */
- compileFunctionBody(
+ /** Compiles a priorly resolved function. */
+ compileFunction(
/** Function to compile. */
instance: Function,
- /** Target array of statements. */
- stmts: ExpressionRef[] | null = null
- ): ExpressionRef[] {
- var module = this.module;
- var bodyNode = assert(instance.prototype.bodyNode);
- var returnType = instance.signature.returnType;
- var flow = this.currentFlow;
-
- // compile statements
- if (bodyNode.kind == NodeKind.BLOCK) {
- stmts = this.compileStatements((bodyNode).statements, true, stmts);
- } else {
- // must be an expression statement if not a block
- assert(bodyNode.kind == NodeKind.EXPRESSION);
-
- // must be an arrow function
- assert(instance.prototype.arrowKind);
-
- // none of the following can be an arrow function
- assert(!instance.isAny(CommonFlags.CONSTRUCTOR | CommonFlags.GET | CommonFlags.SET));
-
- // take special care of properly retaining the returned value
- let expr = this.compileReturnedExpression((bodyNode).expression, returnType, Constraints.CONV_IMPLICIT);
-
- if (!stmts) stmts = [ expr ];
- else stmts.push(expr);
-
- if (!flow.is(FlowFlags.TERMINATES)) {
- let indexBefore = stmts.length;
- this.performAutoreleases(flow, stmts);
- this.finishAutoreleases(flow, stmts);
- let canOverflow = flow.canOverflow(expr, returnType);
- let nonNull = flow.isNonnull(expr, returnType);
- if (stmts.length > indexBefore) {
- let temp = flow.getTempLocal(returnType);
- if (!canOverflow) flow.setLocalFlag(temp.index, LocalFlags.WRAPPED);
- if (nonNull) flow.setLocalFlag(temp.index, LocalFlags.NONNULL);
- stmts[indexBefore - 1] = module.local_set(temp.index, expr);
- stmts.push(module.local_get(temp.index, returnType.toNativeType()));
- flow.freeTempLocal(temp);
- }
- if (!canOverflow) flow.set(FlowFlags.RETURNS_WRAPPED);
- if (nonNull) flow.set(FlowFlags.RETURNS_NONNULL);
- flow.set(FlowFlags.RETURNS | FlowFlags.TERMINATES);
- }
- }
-
- // make constructors return their instance pointer
- if (instance.is(CommonFlags.CONSTRUCTOR)) {
- let nativeSizeType = this.options.nativeSizeType;
- assert(instance.is(CommonFlags.INSTANCE));
- let classInstance = assert(instance.parent); assert(classInstance.kind == ElementKind.CLASS);
-
- if (!flow.is(FlowFlags.TERMINATES)) {
- let thisLocal = assert(flow.lookupLocal(CommonSymbols.this_));
-
- // if `this` wasn't accessed before, allocate if necessary and initialize `this`
- if (!flow.is(FlowFlags.ALLOCATES)) {
- // {
- // if (!this) this =
- // this.a = X
- // this.b = Y
- // }
- stmts.push(
- module.if(
- module.unary(nativeSizeType == NativeType.I64 ? UnaryOp.EqzI64 : UnaryOp.EqzI32,
- module.local_get(thisLocal.index, nativeSizeType)
- ),
- module.local_set(thisLocal.index,
- this.makeRetain(
- this.makeAllocation(classInstance)
- ),
- )
- )
- );
- this.makeFieldInitialization(classInstance, stmts);
- }
- this.performAutoreleases(flow, stmts); // `this` is excluded anyway
- this.finishAutoreleases(flow, stmts);
- stmts.push(module.local_get(thisLocal.index, this.options.nativeSizeType));
- flow.set(FlowFlags.RETURNS | FlowFlags.RETURNS_NONNULL | FlowFlags.TERMINATES);
- }
-
- // check that super has been called if this is a derived class
- if ((classInstance).base && !flow.is(FlowFlags.CALLS_SUPER)) {
- this.error(
- DiagnosticCode.Constructors_for_derived_classes_must_contain_a_super_call,
- instance.prototype.declaration.range
- );
- }
-
- // if this is a normal function, make sure that all branches terminate
- } else if (returnType != Type.void && !flow.is(FlowFlags.TERMINATES)) {
- this.error(
- DiagnosticCode.A_function_whose_declared_type_is_not_void_must_return_a_value,
- instance.prototype.functionTypeNode.returnType.range
- );
- }
-
- return stmts;
- }
-
- /** Compiles a readily resolved function instance. */
- compileFunction(instance: Function): bool {
+ /** Force compilation of stdlib alternative if a builtin. */
+ forceStdAlternative: bool = false
+ ): bool {
if (instance.is(CommonFlags.COMPILED)) return true;
- assert(!(instance.is(CommonFlags.AMBIENT) && instance.hasDecorator(DecoratorFlags.BUILTIN)));
+ if (instance.hasDecorator(DecoratorFlags.BUILTIN)) {
+ if (!forceStdAlternative) return true;
+ }
var previousType = this.currentType; // remember to retain it if compiling a function lazily
instance.set(CommonFlags.COMPILED);
@@ -1281,7 +1160,7 @@ export class Compiler extends DiagnosticEmitter {
)
)
);
- flow.setLocalFlag(index, LocalFlags.RETAINED | LocalFlags.PARAMETER);
+ flow.setLocalFlag(index, LocalFlags.RETAINED);
}
}
@@ -1298,7 +1177,7 @@ export class Compiler extends DiagnosticEmitter {
signature.nativeParams,
signature.nativeResults,
typesToNativeTypes(instance.additionalLocals),
- flatten(module, stmts, instance.signature.returnType.toNativeType())
+ module.flatten(stmts, instance.signature.returnType.toNativeType())
);
// imported function
@@ -1329,25 +1208,115 @@ export class Compiler extends DiagnosticEmitter {
return true;
}
- // === Classes ==================================================================================
+ /** Compiles the body of a function within the specified flow. */
+ private compileFunctionBody(
+ /** Function to compile. */
+ instance: Function,
+ /** Target array of statements also being returned. Creates a new array if omitted. */
+ stmts: ExpressionRef[] | null = null
+ ): ExpressionRef[] {
+ var module = this.module;
+ var bodyNode = assert(instance.prototype.bodyNode);
+ var returnType = instance.signature.returnType;
+ var flow = this.currentFlow;
- compileClassUsingTypeArguments(
- prototype: ClassPrototype,
- typeArguments: NamedTypeNode[],
- contextualTypeArguments: Map = makeMap(),
- alternativeReportNode: Node | null = null
- ): void {
- var instance = this.resolver.resolveClassInclTypeArguments(
- prototype,
- typeArguments,
- prototype.parent, // relative to itself
- contextualTypeArguments,
- alternativeReportNode || prototype.declaration
- );
- if (!instance) return;
- this.compileClass(instance);
+ // compile statements
+ if (bodyNode.kind == NodeKind.BLOCK) {
+ stmts = this.compileStatements((bodyNode).statements, true, stmts);
+ } else {
+ // must be an expression statement if not a block
+ assert(bodyNode.kind == NodeKind.EXPRESSION);
+
+ // must be an arrow function
+ assert(instance.prototype.arrowKind);
+
+ // none of the following can be an arrow function
+ assert(!instance.isAny(CommonFlags.CONSTRUCTOR | CommonFlags.GET | CommonFlags.SET));
+
+ // take special care of properly retaining the returned value
+ let expr = this.compileReturnedExpression((bodyNode).expression, returnType, Constraints.CONV_IMPLICIT);
+
+ if (!stmts) stmts = [ expr ];
+ else stmts.push(expr);
+
+ if (!flow.is(FlowFlags.TERMINATES)) {
+ let indexBefore = stmts.length;
+ this.performAutoreleases(flow, stmts);
+ this.finishAutoreleases(flow, stmts);
+ let canOverflow = flow.canOverflow(expr, returnType);
+ let nonNull = flow.isNonnull(expr, returnType);
+ if (stmts.length > indexBefore) {
+ let temp = flow.getTempLocal(returnType);
+ if (!canOverflow) flow.setLocalFlag(temp.index, LocalFlags.WRAPPED);
+ if (nonNull) flow.setLocalFlag(temp.index, LocalFlags.NONNULL);
+ stmts[indexBefore - 1] = module.local_set(temp.index, expr);
+ stmts.push(module.local_get(temp.index, returnType.toNativeType()));
+ flow.freeTempLocal(temp);
+ }
+ if (!canOverflow) flow.set(FlowFlags.RETURNS_WRAPPED);
+ if (nonNull) flow.set(FlowFlags.RETURNS_NONNULL);
+ flow.set(FlowFlags.RETURNS | FlowFlags.TERMINATES);
+ }
+ }
+
+ // make constructors return their instance pointer
+ if (instance.is(CommonFlags.CONSTRUCTOR)) {
+ let nativeSizeType = this.options.nativeSizeType;
+ assert(instance.is(CommonFlags.INSTANCE));
+ let classInstance = assert(instance.parent); assert(classInstance.kind == ElementKind.CLASS);
+
+ if (!flow.is(FlowFlags.TERMINATES)) {
+ let thisLocal = assert(flow.lookupLocal(CommonNames.this_));
+
+ // if `this` wasn't accessed before, allocate if necessary and initialize `this`
+ if (!flow.is(FlowFlags.ALLOCATES)) {
+ // {
+ // if (!this) this =
+ // this.a = X
+ // this.b = Y
+ // }
+ stmts.push(
+ module.if(
+ module.unary(nativeSizeType == NativeType.I64 ? UnaryOp.EqzI64 : UnaryOp.EqzI32,
+ module.local_get(thisLocal.index, nativeSizeType)
+ ),
+ module.local_set(thisLocal.index,
+ this.makeRetain(
+ this.makeAllocation(classInstance)
+ ),
+ )
+ )
+ );
+ this.makeFieldInitializationInConstructor(classInstance, stmts);
+ }
+ this.performAutoreleases(flow, stmts); // `this` is excluded anyway
+ this.finishAutoreleases(flow, stmts);
+ stmts.push(module.local_get(thisLocal.index, this.options.nativeSizeType));
+ flow.set(FlowFlags.RETURNS | FlowFlags.RETURNS_NONNULL | FlowFlags.TERMINATES);
+ }
+
+ // check that super has been called if this is a derived class
+ if ((classInstance).base && !flow.is(FlowFlags.CALLS_SUPER)) {
+ this.error(
+ DiagnosticCode.Constructors_for_derived_classes_must_contain_a_super_call,
+ instance.prototype.declaration.range
+ );
+ }
+
+ // if this is a normal function, make sure that all branches terminate
+ } else if (returnType != Type.void && !flow.is(FlowFlags.TERMINATES)) {
+ this.error(
+ DiagnosticCode.A_function_whose_declared_type_is_not_void_must_return_a_value,
+ instance.prototype.functionTypeNode.returnType.range
+ );
+ }
+
+ return stmts;
}
+ // === Classes ==================================================================================
+
+ /** Compiles a priorly resolved class. */
compileClass(instance: Class): bool {
if (instance.is(CommonFlags.COMPILED)) return true;
instance.set(CommonFlags.COMPILED);
@@ -1361,41 +1330,27 @@ export class Compiler extends DiagnosticEmitter {
break;
}
case ElementKind.FUNCTION_PROTOTYPE: {
- if (
- !(element).is(CommonFlags.GENERIC)
- ) {
- this.compileFunctionUsingTypeArguments(
- element,
- [],
- makeMap(),
- (element).identifierNode
- );
+ if (!element.is(CommonFlags.GENERIC)) {
+ let instance = this.resolver.resolveFunction(element, null);
+ if (instance) this.compileFunction(instance);
}
break;
}
case ElementKind.PROPERTY_PROTOTYPE: {
- let getter = (element).getterPrototype;
- if (getter) {
- this.compileFunctionUsingTypeArguments(
- getter,
- [],
- makeMap(),
- getter.identifierNode
- );
+ let getterPrototype = (element).getterPrototype;
+ if (getterPrototype) {
+ assert(!getterPrototype.is(CommonFlags.GENERIC));
+ let instance = this.resolver.resolveFunction(getterPrototype, null);
+ if (instance) this.compileFunction(instance);
}
- let setter = (element).setterPrototype;
- if (setter) {
- this.compileFunctionUsingTypeArguments(
- setter,
- [],
- makeMap(),
- setter.identifierNode
- );
+ let setterPrototype = (element).setterPrototype;
+ if (setterPrototype) {
+ assert(!setterPrototype.is(CommonFlags.GENERIC));
+ let instance = this.resolver.resolveFunction(setterPrototype, null);
+ if (instance) this.compileFunction(instance);
}
break;
}
- case ElementKind.PROPERTY: {
- }
}
}
}
@@ -1406,15 +1361,9 @@ export class Compiler extends DiagnosticEmitter {
for (let element of instanceMembers.values()) {
switch (element.kind) {
case ElementKind.FUNCTION_PROTOTYPE: {
- if (
- !(element).is(CommonFlags.GENERIC)
- ) {
- this.compileFunctionUsingTypeArguments(
- element,
- [],
- makeMap(instance.contextualTypeArguments),
- (element).declaration.name
- );
+ if (!element.is(CommonFlags.GENERIC)) {
+ let instance = this.resolver.resolveFunction(element, null);
+ if (instance) this.compileFunction(instance);
}
break;
}
@@ -1423,10 +1372,10 @@ export class Compiler extends DiagnosticEmitter {
break;
}
case ElementKind.PROPERTY: {
- let getter = (element).getterInstance;
- if (getter) this.compileFunction(getter);
- let setter = (element).setterInstance;
- if (setter) this.compileFunction(setter);
+ let getterInstance = (element).getterInstance;
+ if (getterInstance) this.compileFunction(getterInstance);
+ let setterInstance = (element).setterInstance;
+ if (setterInstance) this.compileFunction(setterInstance);
break;
}
}
@@ -1435,19 +1384,6 @@ export class Compiler extends DiagnosticEmitter {
return true;
}
- compileInterfaceDeclaration(
- declaration: InterfaceDeclaration,
- typeArguments: NamedTypeNode[],
- contextualTypeArguments: Map | null = null,
- alternativeReportNode: Node | null = null
- ): void {
- // TODO
- this.error(
- DiagnosticCode.Not_implemented,
- declaration.range
- );
- }
-
// === Memory ===================================================================================
/** Adds a static memory segment with the specified data. */
@@ -1459,7 +1395,7 @@ export class Compiler extends DiagnosticEmitter {
return segment;
}
- /** Ensures that the specified string exists in static memory and returns a pointer to it. */
+ /** Ensures that a string exists in static memory and returns a pointer to it. Deduplicates. */
ensureStaticString(stringValue: string): ExpressionRef {
var program = this.program;
var rtHeaderSize = program.runtimeHeaderSize;
@@ -1488,7 +1424,8 @@ export class Compiler extends DiagnosticEmitter {
}
}
- ensureStaticArrayBuffer(elementType: Type, values: ExpressionRef[]): MemorySegment {
+ /** Adds a buffer to static memory and returns the created segment. */
+ private addStaticBuffer(elementType: Type, values: ExpressionRef[]): MemorySegment {
var program = this.program;
var length = values.length;
var byteSize = elementType.byteSize;
@@ -1574,7 +1511,8 @@ export class Compiler extends DiagnosticEmitter {
return this.addMemorySegment(buf);
}
- ensureStaticArrayHeader(elementType: Type, bufferSegment: MemorySegment): MemorySegment {
+ /** Adds an array header to static memory and returns the created segment. */
+ private addStaticArrayHeader(elementType: Type, bufferSegment: MemorySegment): MemorySegment {
var program = this.program;
var runtimeHeaderSize = program.runtimeHeaderSize;
var arrayPrototype = assert(program.arrayPrototype);
@@ -1599,24 +1537,27 @@ export class Compiler extends DiagnosticEmitter {
// === Table ====================================================================================
/** Ensures that a table entry exists for the specified function and returns its index. */
- ensureFunctionTableEntry(func: Function): i32 {
- assert(func.is(CommonFlags.COMPILED));
- if (func.functionTableIndex >= 0) {
- return func.functionTableIndex;
+ ensureFunctionTableEntry(instance: Function): i32 {
+ assert(instance.is(CommonFlags.COMPILED));
+ var index = instance.functionTableIndex;
+ if (index >= 0) {
+ assert(index != 0); // first elem must be blank
+ return index;
}
var functionTable = this.functionTable;
- var index = 1 + functionTable.length; // first elem is blank
- if (!func.is(CommonFlags.TRAMPOLINE) && func.signature.requiredParameters < func.signature.parameterTypes.length) {
+ index = 1 + functionTable.length; // first elem is blank
+ if (!instance.is(CommonFlags.TRAMPOLINE) && instance.signature.requiredParameters < instance.signature.parameterTypes.length) {
// insert the trampoline if the function has optional parameters
- func = this.ensureTrampoline(func);
+ instance = this.ensureTrampoline(instance);
}
- functionTable.push(func.internalName);
- func.functionTableIndex = index;
+ functionTable.push(instance.internalName);
+ instance.functionTableIndex = index;
return index;
}
// === Statements ===============================================================================
+ /** Compiles a top level statement (incl. function declarations etc.) to the specified body. */
compileTopLevelStatement(statement: Statement, body: ExpressionRef[]): void {
switch (statement.kind) {
case NodeKind.CLASSDECLARATION: {
@@ -1702,8 +1643,11 @@ export class Compiler extends DiagnosticEmitter {
}
}
+ /** Compiles a statement. */
compileStatement(
+ /** Statement to compile. */
statement: Statement,
+ /** Whether this is the last statement of the body, if known. */
isLastInBody: bool = false
): ExpressionRef {
var module = this.module;
@@ -1788,9 +1732,13 @@ export class Compiler extends DiagnosticEmitter {
return stmt;
}
+ /** Compiles a series of statements. */
compileStatements(
+ /** Statements to compile. */
statements: Statement[],
+ /** Whether this is an immediate body statement. */
isBody: bool = false,
+ /** Statements to append to that is also returned. Created if omitted. */
stmts: ExpressionRef[] | null = null
): ExpressionRef[] {
var numStatements = statements.length;
@@ -1821,7 +1769,7 @@ export class Compiler extends DiagnosticEmitter {
return stmts;
}
- compileBlockStatement(
+ private compileBlockStatement(
statement: BlockStatement
): ExpressionRef {
var statements = statement.statements;
@@ -1832,12 +1780,12 @@ export class Compiler extends DiagnosticEmitter {
var stmts = this.compileStatements(statements);
if (!innerFlow.isAny(FlowFlags.TERMINATES | FlowFlags.BREAKS)) this.performAutoreleases(innerFlow, stmts);
innerFlow.freeScopedLocals();
- outerFlow.inherit(innerFlow); // TODO: only if not terminated?
+ outerFlow.inherit(innerFlow);
this.currentFlow = outerFlow;
- return flatten(this.module, stmts, NativeType.None);
+ return this.module.flatten(stmts);
}
- compileBreakStatement(
+ private compileBreakStatement(
statement: BreakStatement
): ExpressionRef {
var module = this.module;
@@ -1867,10 +1815,10 @@ export class Compiler extends DiagnosticEmitter {
flow.freeScopedLocals();
stmts.push(module.br(breakLabel));
flow.set(FlowFlags.BREAKS);
- return flatten(module, stmts, NativeType.None);
+ return module.flatten(stmts);
}
- compileContinueStatement(
+ private compileContinueStatement(
statement: ContinueStatement
): ExpressionRef {
var module = this.module;
@@ -1902,347 +1850,453 @@ export class Compiler extends DiagnosticEmitter {
}
flow.freeScopedLocals();
stmts.push(module.br(continueLabel));
- return flatten(module, stmts, NativeType.None);
+ return module.flatten(stmts);
}
- compileDoStatement(
+ private compileDoStatement(
+ /** Statement to compile. */
statement: DoStatement
): ExpressionRef {
- var module = this.module;
+ return this.doCompileDoStatement(statement, null);
+ }
+ private doCompileDoStatement(
+ /** Statement to compile. */
+ statement: DoStatement,
+ /** If recompiling, the flow with differing local flags that triggered it. */
+ flowAfter: Flow | null
+ ): ExpressionRef {
+ var module = this.module;
var outerFlow = this.currentFlow;
+
+ // (block $break └►┐ flow
+ // (loop $continue ├◄───────────┐ recompile?
+ // (body) └─┐ bodyFlow │
+ // [autorelease] ┌─┘ │
+ // ┌◄┼►╢ │ breaks or terminates?
+ // (local.set $tcond (condition)) │ └─┐ condFlow │
+ // [autorelease] │ ┌─┘ │
+ // (br_if (local.get $tcond) $continue) ├◄┴────────────┘ condition?
+ // ) └─┐
+ // ) ┌─┘
+
var label = outerFlow.pushBreakLabel();
- var innerFlow = outerFlow.fork();
- var breakLabel = "break|" + label;
- innerFlow.breakLabel = breakLabel;
- var continueLabel = "continue|" + label;
- innerFlow.continueLabel = continueLabel;
+ var flow = outerFlow.fork(/* resetBreakContext */ true);
+ if (flowAfter) flow.unifyLocalFlags(flowAfter);
+ var flowBefore = flow.fork();
+ this.currentFlow = flow;
- // Compile the condition before the body in order to...
- var condFlow = outerFlow.fork();
- this.currentFlow = condFlow;
- var condExpr = module.precomputeExpression(
- this.makeIsTrueish(
- this.compileExpression(statement.condition, Type.i32),
- this.currentType
- )
- );
- assert(!condFlow.hasScopedLocals);
- // ...unify local states before and after the condition has been executed the first time
- innerFlow.unifyLocalFlags(condFlow);
- this.currentFlow = innerFlow;
+ var breakLabel = "do-break|" + label;
+ flow.breakLabel = breakLabel;
+ var continueLabel = "do-continue|" + label;
+ flow.continueLabel = continueLabel;
- var stmts = new Array();
- if (statement.statement.kind == NodeKind.BLOCK) {
- this.compileStatements((statement.statement).statements, false, stmts);
+ // Compile the body (always executes)
+ var bodyFlow = flow.fork();
+ this.currentFlow = bodyFlow;
+ var bodyStmts = new Array();
+ var body = statement.statement;
+ if (body.kind == NodeKind.BLOCK) {
+ this.compileStatements((body).statements, false, bodyStmts);
} else {
- stmts.push(
- this.compileStatement(statement.statement)
- );
- }
- var alwaysFalse = false;
- if (getExpressionId(condExpr) == ExpressionId.Const) {
- assert(getExpressionType(condExpr) == NativeType.I32);
- if (!getConstValueI32(condExpr)) alwaysFalse = true;
+ bodyStmts.push(this.compileStatement(body));
}
- var terminates = innerFlow.is(FlowFlags.TERMINATES);
- var continues = innerFlow.isAny(FlowFlags.CONTINUES | FlowFlags.CONDITIONALLY_CONTINUES);
- var breaks = innerFlow.isAny(FlowFlags.BREAKS | FlowFlags.CONDITIONALLY_BREAKS);
- // (block $break ;; (1) skip if no breaks
- // (loop $continue ;; (2) skip if skipping (4) + no continues
- // (...) ;; (3)
- // (br_if cond $continue) ;; (4) skip if (3) does not fall through or always false
- // )
- // )
- var fallsThrough = !terminates && !innerFlow.is(FlowFlags.BREAKS);
+ // Shortcut if body never falls through
+ if (bodyFlow.isAny(FlowFlags.TERMINATES | FlowFlags.BREAKS)) {
+ bodyStmts.push(
+ module.unreachable()
+ );
+ flow.inherit(bodyFlow);
+
+ // Otherwise evaluate the condition
+ } else {
+ this.performAutoreleases(bodyFlow, bodyStmts);
+
+ let condFlow = flow.fork();
+ this.currentFlow = condFlow;
+ let condExpr = module.precomputeExpression(
+ this.makeIsTrueish(
+ this.compileExpression(statement.condition, Type.i32),
+ this.currentType
+ )
+ );
+ let condKind = evaluateConditionKind(condExpr);
+
+ // Shortcut if condition is always false
+ if (condKind == ConditionKind.FALSE) {
+ if (hasSideEffects(condExpr)) {
+ bodyStmts.push(
+ module.drop(condExpr)
+ );
+ }
+ this.performAutoreleases(condFlow, bodyStmts);
+ flow.inherit(bodyFlow);
+ } else {
+ let tcond = condFlow.getTempLocal(Type.bool);
+ bodyStmts.push(
+ module.local_set(tcond.index, condExpr)
+ );
+ this.performAutoreleases(condFlow, bodyStmts);
+ bodyStmts.push(
+ module.br(continueLabel,
+ module.local_get(tcond.index, NativeType.I32)
+ )
+ );
+ condFlow.freeTempLocal(tcond);
+ flow.inherit(condFlow);
- if (fallsThrough) {
- this.performAutoreleases(innerFlow, stmts);
- if (!alwaysFalse) { // (4)
- stmts.push(module.br(continueLabel, condExpr));
+ // Detect if local flags are incompatible before and after looping, and
+ // if so recompile by unifying local flags between iterations.
+ if (Flow.hasIncompatibleLocalStates(flowBefore, flow)) {
+ assert(!flowAfter); // should work on the first attempt
+ outerFlow.popBreakLabel();
+ this.currentFlow = outerFlow;
+ return this.doCompileWhileStatement(statement, flow);
+ }
}
}
- var expr = flatten(module, stmts, NativeType.None);
- if (fallsThrough && !alwaysFalse || continues) { // (2)
- expr = module.loop(continueLabel, expr);
- }
- if (breaks) { // (1)
- expr = module.block(breakLabel, [ expr ]);
- }
- // Switch back to the parent flow
- innerFlow.freeScopedLocals();
+ // Finalize
+ assert(!flow.hasScopedLocals);
+ outerFlow.inherit(flow);
outerFlow.popBreakLabel();
- innerFlow.unset(
- FlowFlags.BREAKS |
- FlowFlags.CONDITIONALLY_BREAKS |
- FlowFlags.CONTINUES |
- FlowFlags.CONDITIONALLY_CONTINUES
- );
- outerFlow.inherit(innerFlow);
this.currentFlow = outerFlow;
+ var expr = module.block(breakLabel, [
+ module.loop(continueLabel,
+ module.flatten(bodyStmts)
+ )
+ ]);
+ if (outerFlow.is(FlowFlags.TERMINATES)) {
+ expr = module.block(null, [ expr, module.unreachable() ]);
+ }
return expr;
}
- compileEmptyStatement(
+ private compileEmptyStatement(
statement: EmptyStatement
): ExpressionRef {
return this.module.nop();
}
- compileExpressionStatement(
+ private compileExpressionStatement(
statement: ExpressionStatement
): ExpressionRef {
return this.compileExpression(statement.expression, Type.void, Constraints.CONV_IMPLICIT);
}
- compileForStatement(
+ private compileForStatement(
+ /** Statement to compile. */
statement: ForStatement
): ExpressionRef {
- var module = this.module;
+ return this.doCompileForStatement(statement, null);
+ }
- // Set up and use the inner flow
+ private doCompileForStatement(
+ /** Statement to compile. */
+ statement: ForStatement,
+ /** If recompiling, the flow with differing local flags that triggered it. */
+ flowAfter: Flow | null
+ ): ExpressionRef {
+ var module = this.module;
var outerFlow = this.currentFlow;
+
+ // (initializer) └►┐ flow
+ // (block $break │
+ // (loop $loop ├◄───────────┐ recompile?
+ // (local.set $tcond (condition)) └─┐ condFlow │
+ // [autorelease] ┌─┘ │
+ // (if (local.get $tcond) ┌◄┤ │ condition?
+ // (block $continue │ │ │
+ // (body) │ └─┐ bodyFlow │
+ // [autorelease] │ ┌─┘ │
+ // ) ├◄┼►╢ │ breaks or terminates?
+ // (incrementor) │ └─┐ incrFlow │
+ // [autorelease] │ ┌─┘ │
+ // │ └────────────┘
+ // (br $loop) └─┐
+ // ) │
+ // ) │
+ // ) │
+ // [autorelease] ┌─┘
+
var label = outerFlow.pushBreakLabel();
- var innerFlow = outerFlow.fork();
- this.currentFlow = innerFlow;
+ var stmts = new Array();
+ var flow = outerFlow.fork(/* resetBreakContext */ true);
+ this.currentFlow = flow;
+
+ var breakLabel = "for-break" + label;
+ flow.breakLabel = breakLabel;
+ var continueLabel = "for-continue|" + label;
+ flow.continueLabel = continueLabel;
+ var loopLabel = "for-loop|" + label;
- // Compile the initializer
+ // Compile initializer if present (but wait with autoreleases)
var initializer = statement.initializer;
- var initExpr: ExpressionRef = 0;
- if (initializer) initExpr = this.compileStatement(initializer);
+ if (initializer) {
+ assert(
+ initializer.kind == NodeKind.EXPRESSION ||
+ initializer.kind == NodeKind.VARIABLE
+ );
+ stmts.push(this.compileStatement(initializer));
+ }
+
+ if (flowAfter) flow.unifyLocalFlags(flowAfter);
+ var flowBefore = flow.fork();
- // Compile the condition
- var condExpr: ExpressionRef = 0;
- var alwaysTrue = false;
- if (statement.condition) {
+ // Precompute the condition
+ var condFlow = flow.fork();
+ this.currentFlow = condFlow;
+ var condExpr: ExpressionRef;
+ var condKind: ConditionKind;
+ var condition = statement.condition;
+ if (condition) {
condExpr = module.precomputeExpression(
this.makeIsTrueish(
- this.compileExpression(statement.condition, Type.bool),
+ this.compileExpression(condition, Type.bool),
this.currentType
)
);
- // Simplify if the condition is constant
- if (getExpressionId(condExpr) == ExpressionId.Const) {
- assert(getExpressionType(condExpr) == NativeType.I32);
- if (getConstValueI32(condExpr) == /* false */ 0) {
- let stmts = new Array();
- if (initExpr) stmts.push(initExpr);
- this.performAutoreleases(innerFlow, stmts);
- innerFlow.freeScopedLocals();
- outerFlow.popBreakLabel();
- this.currentFlow = outerFlow;
- return flatten(module, stmts, NativeType.None);
+ condKind = evaluateConditionKind(condExpr);
+
+ // Shortcut if condition is always false (body never runs)
+ if (condKind == ConditionKind.FALSE) {
+ if (hasSideEffects(condExpr)) {
+ stmts.push(
+ module.drop(condExpr)
+ );
}
- alwaysTrue = true;
+ this.performAutoreleases(condFlow, stmts);
+ condFlow.freeScopedLocals();
+ flow.inherit(condFlow);
+ this.performAutoreleases(flow, stmts);
+ flow.freeScopedLocals();
+ outerFlow.inherit(flow);
+ outerFlow.popBreakLabel();
+ this.currentFlow = outerFlow;
+ return module.flatten(stmts);
}
- } else { // Omitted condition is always true
+ } else {
condExpr = module.i32(1);
- alwaysTrue = true;
- }
- innerFlow.inheritNonnullIfTrue(condExpr);
-
- // Compile the incrementor before the body in order to...
- var incrementor = statement.incrementor;
- var incrExpr: ExpressionRef = 0;
- if (incrementor) {
- let incrFlow = innerFlow.fork();
- this.currentFlow = incrFlow;
- incrExpr = this.compileExpression(incrementor, Type.void, Constraints.CONV_IMPLICIT | Constraints.WILL_DROP);
- assert(!incrFlow.hasScopedLocals);
- this.currentFlow = innerFlow;
- // ...unify local states before and after the incrementor has been executed the first time
- innerFlow.unifyLocalFlags(incrFlow);
+ condKind = ConditionKind.TRUE;
}
- // Compile body (break: drop out, continue: fall through to incrementor, + loop)
- var bodyFlow = innerFlow.fork();
+ // From here on condition is either always true or unknown
+
+ // Store condition result in a temp while we autorelease
+ var tcond = flow.getTempLocal(Type.bool);
+ var loopStmts = new Array();
+ loopStmts.push(
+ module.local_set(tcond.index, condExpr)
+ );
+ this.performAutoreleases(condFlow, loopStmts);
+ condFlow.freeScopedLocals();
+
+ flow.inherit(condFlow); // always executes
+ this.currentFlow = flow;
+
+ // Compile the body assuming the condition turned out true
+ var bodyFlow = flow.fork();
+ bodyFlow.inheritNonnullIfTrue(condExpr);
this.currentFlow = bodyFlow;
- var breakLabel = innerFlow.breakLabel = "break|" + label; bodyFlow.breakLabel = breakLabel;
- bodyFlow.breakLabel = breakLabel;
- var continueLabel = "continue|" + label;
- bodyFlow.continueLabel = continueLabel;
- var loopLabel = "loop|" + label;
- var bodyStatement = statement.statement;
- var stmts = new Array();
- if (bodyStatement.kind == NodeKind.BLOCK) {
- this.compileStatements((bodyStatement).statements, false, stmts);
+ var bodyStmts = new Array();
+ var body = statement.statement;
+ if (body.kind == NodeKind.BLOCK) {
+ this.compileStatements((body).statements, false, bodyStmts);
} else {
- stmts.push(this.compileStatement(bodyStatement));
+ bodyStmts.push(this.compileStatement(body));
}
- var terminates = bodyFlow.is(FlowFlags.TERMINATES);
- var continues = bodyFlow.isAny(FlowFlags.CONTINUES | FlowFlags.CONDITIONALLY_CONTINUES);
- var breaks = bodyFlow.isAny(FlowFlags.BREAKS | FlowFlags.CONDITIONALLY_BREAKS);
- var fallsThrough = !terminates && !innerFlow.is(FlowFlags.BREAKS);
- // Finalize body flow
- if (fallsThrough) this.performAutoreleases(bodyFlow, stmts);
+ // Check if body terminates
+ if (bodyFlow.isAny(FlowFlags.TERMINATES | FlowFlags.BREAKS)) {
+ bodyStmts.push(module.unreachable());
+ } else {
+ this.performAutoreleases(bodyFlow, bodyStmts);
+ }
+ if (condKind == ConditionKind.TRUE) flow.inherit(bodyFlow);
+ else flow.inheritBranch(bodyFlow);
bodyFlow.freeScopedLocals();
- innerFlow.inherit(bodyFlow);
- this.currentFlow = innerFlow;
- // (block $break ;; (1) skip label (needed anyway) if skipping (4) + no breaks
- // (initializer) ;; (2) [may be empty]
- // (loop $loop ;; (3) skip if (6) does not fall through + no continues
- // (br_if !cond $break) ;; (4) skip if always true
- // (block $continue ;; (5) skip if no continues or nothing else than continue
- // (...) ;; (6)
- // )
- // (incrementor) ;; (7) skip if skipping (3) [may be empty]
- // (br $loop) ;; (8) skip if skipping (3)
- // )
- // )
- var needsLabel = !alwaysTrue || breaks;
-
- var loop = new Array();
- if (!alwaysTrue) { // (4)
- loop.push(module.br(breakLabel, module.unary(UnaryOp.EqzI32, condExpr)));
- }
- if (continues) { // (5)
- if (stmts.length > 1 || getExpressionId(stmts[0]) != ExpressionId.Break) { // otherwise lonely continue
- loop.push(module.block(continueLabel, stmts));
+ var ifStmts = new Array();
+ ifStmts.push(
+ module.block(continueLabel, bodyStmts)
+ );
+
+ // Compile the incrementor if it runs
+ // Can still fall through to here if body continues, hence is already known to terminate
+ if (!bodyFlow.is(FlowFlags.TERMINATES) || bodyFlow.isAny(FlowFlags.CONTINUES | FlowFlags.CONDITIONALLY_CONTINUES)) {
+ let incrementor = statement.incrementor;
+ if (incrementor) {
+ let incrFlow = flow.fork();
+ this.currentFlow = incrFlow;
+ ifStmts.push(
+ this.compileExpression(incrementor, Type.void, Constraints.CONV_IMPLICIT | Constraints.WILL_DROP)
+ );
+ this.performAutoreleases(incrFlow, ifStmts);
+ incrFlow.freeScopedLocals();
+ flow.inherit(incrFlow); // mostly local flags, also covers late termination by throwing
+ this.currentFlow = flow;
}
- } else {
- for (let i = 0, k = stmts.length; i < k; ++i) loop.push(stmts[i]);
- }
- var expr: ExpressionRef;
- if (fallsThrough || continues) { // (3)
- if (incrExpr) loop.push(incrExpr); // (7)
- this.performAutoreleases(innerFlow, loop);
- loop.push(module.br(loopLabel)); // (8)
- if (initExpr) { // (2)
- expr = module.block(needsLabel ? breakLabel : null, [
- initExpr,
- module.loop(loopLabel, module.block(null, loop))
- ]);
- } else {
- expr = module.block(needsLabel ? breakLabel : null, [
- module.loop(loopLabel, flatten(module, loop, NativeType.None))
- ]);
+
+ ifStmts.push(
+ module.br(loopLabel)
+ );
+
+ // Detect if local flags are incompatible before and after looping, and if
+ // so recompile by unifying local flags between iterations.
+ if (Flow.hasIncompatibleLocalStates(flowBefore, flow)) {
+ assert(!flowAfter); // should work on the first attempt
+ assert(!bodyFlow.hasScopedLocals);
+ flow.freeScopedLocals();
+ outerFlow.popBreakLabel();
+ this.currentFlow = outerFlow;
+ return this.doCompileForStatement(statement, flow);
}
- } else {
- if (initExpr) loop.unshift(initExpr); // (2)
- this.performAutoreleases(innerFlow, loop);
- expr = module.block(needsLabel ? breakLabel : null, loop);
}
+ loopStmts.push(
+ module.if(module.local_get(tcond.index, NativeType.I32),
+ module.flatten(ifStmts)
+ )
+ );
- // Switch back to the parent flow
- innerFlow.freeScopedLocals();
- outerFlow.popBreakLabel();
- innerFlow.unset(
- FlowFlags.BREAKS |
- FlowFlags.CONDITIONALLY_BREAKS |
- FlowFlags.CONTINUES |
- FlowFlags.CONDITIONALLY_CONTINUES
+ stmts.push(
+ module.block(breakLabel, [
+ module.loop(loopLabel,
+ module.flatten(loopStmts)
+ )
+ ])
);
- if (alwaysTrue) outerFlow.inherit(innerFlow);
- else outerFlow.inheritConditional(innerFlow);
+ flow.freeTempLocal(tcond);
+ this.currentFlow = flow;
+
+ // Finalize
+ flow.freeScopedLocals();
+ outerFlow.inherit(flow);
+ outerFlow.popBreakLabel();
+ if (outerFlow.is(FlowFlags.TERMINATES)) {
+ stmts.push(module.unreachable());
+ } else {
+ this.performAutoreleases(flow, stmts);
+ }
this.currentFlow = outerFlow;
- return expr;
+ return module.flatten(stmts);
}
- compileIfStatement(
+ private compileIfStatement(
statement: IfStatement
): ExpressionRef {
var module = this.module;
var ifTrue = statement.ifTrue;
var ifFalse = statement.ifFalse;
- var outerFlow = this.currentFlow;
- // The condition doesn't initiate a branch yet
+ // (if └►┐ flow
+ // (condition) ┌┴───────────┐ condition?
+ // (block │ │
+ // (ifTrue) └►┐ thenFlow │
+ // [autorelease] ┌─┘ │
+ // ) ├─╢ │
+ // (block │ ┌◄┤ present?
+ // (ifFalse) │ │ └►┐ elseFlow
+ // [autorelease] │ │ ┌─┘
+ // ) │ │ ├─╢
+ // ) └┬─────────┴─┘
+ // ... ┌◄┘
+ // [autorelease] incl. condition
+
+ // Precompute the condition (always executes)
var condExpr = module.precomputeExpression(
this.makeIsTrueish(
this.compileExpression(statement.condition, Type.bool),
this.currentType
)
);
+ var condKind = evaluateConditionKind(condExpr);
- // Try to eliminate unnecesssary branches if the condition is constant
- if (
- getExpressionId(condExpr) == ExpressionId.Const &&
- getExpressionType(condExpr) == NativeType.I32
- ) {
- return getConstValueI32(condExpr)
- ? this.compileStatement(ifTrue)
- : ifFalse
+ // Shortcut if the condition is constant
+ switch (condKind) {
+ case ConditionKind.TRUE: {
+ if (hasSideEffects(condExpr)) {
+ return module.block(null, [
+ module.drop(condExpr),
+ this.compileStatement(ifTrue)
+ ]);
+ }
+ return this.compileStatement(ifTrue);
+ }
+ case ConditionKind.FALSE: {
+ if (hasSideEffects(condExpr)) {
+ return ifFalse
+ ? module.block(null, [
+ module.drop(condExpr),
+ this.compileStatement(ifFalse)
+ ])
+ : module.drop(condExpr);
+ }
+ return ifFalse
? this.compileStatement(ifFalse)
: module.nop();
+ }
}
- // Each arm initiates a branch
- var ifTrueStmts = new Array();
- var ifTrueFlow = outerFlow.fork();
- this.currentFlow = ifTrueFlow;
- ifTrueFlow.inheritNonnullIfTrue(condExpr);
+ // From here on condition is always unknown
+
+ var flow = this.currentFlow;
+
+ // Compile ifTrue assuming the condition turned out true
+ var thenStmts = new Array();
+ var thenFlow = flow.fork();
+ this.currentFlow = thenFlow;
+ thenFlow.inheritNonnullIfTrue(condExpr);
if (ifTrue.kind == NodeKind.BLOCK) {
- this.compileStatements((ifTrue).statements, false, ifTrueStmts);
+ this.compileStatements((ifTrue).statements, false, thenStmts);
} else {
- ifTrueStmts.push(this.compileStatement(ifTrue));
+ thenStmts.push(this.compileStatement(ifTrue));
}
- if (!ifTrueFlow.isAny(FlowFlags.TERMINATES | FlowFlags.BREAKS)) this.performAutoreleases(ifTrueFlow, ifTrueStmts);
- ifTrueFlow.freeScopedLocals();
- this.currentFlow = outerFlow;
+ if (thenFlow.isAny(FlowFlags.TERMINATES | FlowFlags.BREAKS)) {
+ thenStmts.push(module.unreachable());
+ } else {
+ this.performAutoreleases(thenFlow, thenStmts);
+ }
+ thenFlow.freeScopedLocals();
+ this.currentFlow = flow;
+ // Compile ifFalse assuming the condition turned out false, if present
if (ifFalse) {
- let ifFalseFlow = outerFlow.fork();
- this.currentFlow = ifFalseFlow;
- ifFalseFlow.inheritNonnullIfFalse(condExpr);
- let ifFalseStmts = new Array();
+ let elseStmts = new Array();
+ let elseFlow = flow.fork();
+ this.currentFlow = elseFlow;
+ elseFlow.inheritNonnullIfFalse(condExpr);
if (ifFalse.kind == NodeKind.BLOCK) {
- this.compileStatements((ifFalse).statements, false, ifFalseStmts);
+ this.compileStatements((ifFalse).statements, false, elseStmts);
} else {
- ifFalseStmts.push(this.compileStatement(ifFalse));
+ elseStmts.push(this.compileStatement(ifFalse));
}
- if (!ifFalseFlow.isAny(FlowFlags.TERMINATES | FlowFlags.BREAKS)) this.performAutoreleases(ifFalseFlow, ifFalseStmts);
- ifFalseFlow.freeScopedLocals();
- this.currentFlow = outerFlow;
- outerFlow.inheritMutual(ifTrueFlow, ifFalseFlow);
+ if (elseFlow.isAny(FlowFlags.TERMINATES | FlowFlags.BREAKS)) {
+ elseStmts.push(module.unreachable());
+ } else {
+ this.performAutoreleases(elseFlow, elseStmts);
+ }
+ elseFlow.freeScopedLocals();
+ this.currentFlow = flow;
+ flow.inheritMutual(thenFlow, elseFlow);
return module.if(condExpr,
- flatten(module, ifTrueStmts, NativeType.None),
- flatten(module, ifFalseStmts, NativeType.None)
+ module.flatten(thenStmts),
+ module.flatten(elseStmts)
);
} else {
- outerFlow.inheritConditional(ifTrueFlow);
- if (ifTrueFlow.is(FlowFlags.TERMINATES)) outerFlow.inheritNonnullIfFalse(condExpr);
+ flow.inheritBranch(thenFlow);
+ flow.inheritNonnullIfFalse(condExpr,
+ thenFlow.isAny(FlowFlags.TERMINATES | FlowFlags.BREAKS)
+ ? null // thenFlow terminates: just inherit
+ : thenFlow // must become nonnull in thenFlow otherwise
+ );
return module.if(condExpr,
- flatten(module, ifTrueStmts, NativeType.None)
+ module.flatten(thenStmts)
);
}
- // TODO: Detect neglected condition
- // if (!foo) {
- // foo = [notNull]
- // }
- // foo // is possibly null
- }
-
- /** Compiles an expression that is about to be returned, taking special care of retaining and setting flow states. */
- compileReturnedExpression(
- /** Expression to compile. */
- expression: Expression,
- /** Return type of the function. */
- returnType: Type,
- /** Constraints indicating contextual conditions. */
- constraints: Constraints = Constraints.NONE
- ): ExpressionRef {
- // pretend to retain the expression immediately so the autorelease, if any, is skipped
- var expr = this.compileExpression(expression, returnType, constraints | Constraints.WILL_RETAIN);
- var flow = this.currentFlow;
- if (returnType.isManaged) {
- // check if that worked, and if it didn't, keep the reference alive
- if (!this.skippedAutoreleases.has(expr)) {
- let index = this.tryUndoAutorelease(expr, flow);
- if (index == -1) expr = this.makeRetain(expr);
- this.skippedAutoreleases.add(expr);
- }
- }
- // remember return states
- if (!flow.canOverflow(expr, returnType)) flow.set(FlowFlags.RETURNS_WRAPPED);
- if (flow.isNonnull(expr, returnType)) flow.set(FlowFlags.RETURNS_NONNULL);
- return expr;
}
- compileReturnStatement(
+ private compileReturnStatement(
statement: ReturnStatement,
isLastInBody: bool
): ExpressionRef {
@@ -2296,24 +2350,24 @@ export class Compiler extends DiagnosticEmitter {
if (isLastInBody && expr && returnType != Type.void) {
if (!stmts.length) return expr;
stmts.push(expr);
- return module.block(null, stmts, returnType.toNativeType());
+ return module.flatten(stmts, returnType.toNativeType());
}
// When inlining, break to the end of the inlined function's block (no need to wrap)
- if (flow.is(FlowFlags.INLINE_CONTEXT)) {
+ if (flow.isInline) {
if (!stmts.length) return module.br(assert(flow.inlineReturnLabel), 0, expr);
stmts.push(module.br(assert(flow.inlineReturnLabel), 0, expr));
// stmts.push(module.createUnreachable());
- return module.block(null, stmts);
+ return module.flatten(stmts);
}
// Otherwise emit a normal return
if (!stmts.length) return module.return(expr);
stmts.push(module.return(expr));
- return module.block(null, stmts);
+ return module.flatten(stmts);
}
- compileSwitchStatement(
+ private compileSwitchStatement(
statement: SwitchStatement
): ExpressionRef {
var module = this.module;
@@ -2427,7 +2481,7 @@ export class Compiler extends DiagnosticEmitter {
return currentBlock;
}
- compileThrowStatement(
+ private compileThrowStatement(
statement: ThrowStatement
): ExpressionRef {
var flow = this.currentFlow;
@@ -2447,10 +2501,10 @@ export class Compiler extends DiagnosticEmitter {
}
stmts.push(compileAbort(this, message, statement));
- return flatten(this.module, stmts, NativeType.None);
+ return this.module.flatten(stmts);
}
- compileTryStatement(
+ private compileTryStatement(
statement: TryStatement
): ExpressionRef {
// TODO: can't yet support something like: try { return ... } finally { ... }
@@ -2463,7 +2517,7 @@ export class Compiler extends DiagnosticEmitter {
}
/** Compiles a variable statement. Returns `0` if an initializer is not necessary. */
- compileVariableStatement(
+ private compileVariableStatement(
statement: VariableStatement
): ExpressionRef {
var module = this.module;
@@ -2590,7 +2644,7 @@ export class Compiler extends DiagnosticEmitter {
let local: Local;
if (
declaration.isAny(CommonFlags.LET | CommonFlags.CONST) ||
- flow.is(FlowFlags.INLINE_CONTEXT)
+ flow.isInline
) { // here: not top-level
let existingLocal = flow.getScopedLocal(name);
if (existingLocal) {
@@ -2668,10 +2722,10 @@ export class Compiler extends DiagnosticEmitter {
}
return initializers.length == 0
? 0
- : flatten(module, initializers, NativeType.None);
+ : module.flatten(initializers);
}
- compileVoidStatement(
+ private compileVoidStatement(
statement: VoidStatement
): ExpressionRef {
return this.compileExpression(statement.expression, Type.void,
@@ -2679,81 +2733,146 @@ export class Compiler extends DiagnosticEmitter {
);
}
- compileWhileStatement(
+ private compileWhileStatement(
+ /** Statement to compile. */
statement: WhileStatement
+ ): ExpressionRef {
+ return this.doCompileWhileStatement(statement, null);
+ }
+
+ private doCompileWhileStatement(
+ /** Statement to compile. */
+ statement: WhileStatement,
+ /** If recompiling, the flow with differing local flags that triggered it. */
+ flowAfter: Flow | null
): ExpressionRef {
var module = this.module;
var outerFlow = this.currentFlow;
- // Compile condition
+ // (block $break └►┐ flow
+ // (loop $continue ├◄───────────┐ recompile?
+ // (local.set $tcond (condition)) └─┐ condFlow │
+ // [autorelease] ┌─┘ │
+ // (if (local.get $tcond) ┌◄┤ │ condition?
+ // (body) │ └─┐ bodyFlow │
+ // [autorelease] │ ┌─┘ │
+ // ├◄┼►╢ │ breaks or terminates?
+ // (br $continue) │ └────────────┘
+ // ) └─┐
+ // ) │
+ // ) ┌─┘
+
+ var label = outerFlow.pushBreakLabel();
+ var stmts = new Array();
+ var flow = outerFlow.fork(/* resetBreakContext */ true);
+ if (flowAfter) flow.unifyLocalFlags(flowAfter);
+ var flowBefore = flow.fork();
+ this.currentFlow = flow;
+
+ var breakLabel = "while-break|" + label;
+ flow.breakLabel = breakLabel;
+ var continueLabel = "while-continue|" + label;
+ flow.continueLabel = continueLabel;
+
+ // Precompute the condition
+ var condFlow = flow.fork();
+ this.currentFlow = condFlow;
var condExpr = module.precomputeExpression(
this.makeIsTrueish(
this.compileExpression(statement.condition, Type.bool),
this.currentType
)
);
+ var condKind = evaluateConditionKind(condExpr);
- // Simplify if the condition is constant
- var alwaysTrue = false;
- if (getExpressionId(condExpr) == ExpressionId.Const) {
- assert(getExpressionType(condExpr) == NativeType.I32);
- if (!getConstValueI32(condExpr)) return module.nop(); // simplify
- alwaysTrue = true;
+ // Shortcut if condition is always false (body never runs)
+ if (condKind == ConditionKind.FALSE) {
+ this.performAutoreleases(condFlow, stmts);
+ assert(!flow.hasScopedLocals);
+ outerFlow.popBreakLabel();
+ this.currentFlow = outerFlow;
+ return module.flatten(stmts);
}
- // Compile body
- var label = outerFlow.pushBreakLabel();
- var innerFlow = outerFlow.fork();
- this.currentFlow = innerFlow;
- var breakLabel = "break|" + label;
- innerFlow.breakLabel = breakLabel;
- var continueLabel = "continue|" + label;
- innerFlow.continueLabel = continueLabel;
- innerFlow.inheritNonnullIfTrue(condExpr);
- var stmts = new Array();
- if (statement.statement.kind == NodeKind.BLOCK) {
- this.compileStatements((statement.statement).statements, false, stmts);
+ // From here on condition is either always true or unknown
+
+ // Store condition result in a temp while we autorelease
+ var tcond = flow.getTempLocal(Type.bool);
+ stmts.push(
+ module.local_set(tcond.index, condExpr)
+ );
+ this.performAutoreleases(condFlow, stmts);
+ condFlow.freeScopedLocals();
+
+ flow.inherit(condFlow); // always executes
+ this.currentFlow = flow;
+
+ // Compile the body assuming the condition turned out true
+ var bodyFlow = flow.fork();
+ bodyFlow.inheritNonnullIfTrue(condExpr);
+ this.currentFlow = bodyFlow;
+ var bodyStmts = new Array();
+ var body = statement.statement;
+ if (body.kind == NodeKind.BLOCK) {
+ this.compileStatements((body).statements, false, bodyStmts);
} else {
- stmts.push(this.compileStatement(statement.statement));
+ bodyStmts.push(this.compileStatement(body));
}
- var terminates = innerFlow.is(FlowFlags.TERMINATES);
- // (block $break ;; (1) skip if skipping (3) + no breaks
- // (loop $continue ;; (2) skip if skipping (5) + no continues
- // (br_if !cond $break) ;; (3) skip if always true
- // (...) ;; (4)
- // (br $continue) ;; (5) skip if (4) does not fall through
- // )
- // )
- var fallsThrough = !terminates && !innerFlow.is(FlowFlags.BREAKS);
+ // Check if body terminates
+ if (bodyFlow.is(FlowFlags.TERMINATES)) {
+ bodyStmts.push(
+ module.unreachable()
+ );
+ if (condKind == ConditionKind.TRUE) flow.inherit(bodyFlow);
+ else flow.inheritBranch(bodyFlow);
+ } else {
+ let breaks = bodyFlow.is(FlowFlags.BREAKS);
+ if (breaks) {
+ bodyStmts.push(
+ module.unreachable()
+ );
+ } else {
+ this.performAutoreleases(bodyFlow, bodyStmts);
+ bodyStmts.push(
+ module.br(continueLabel)
+ );
+ }
+ if (condKind == ConditionKind.TRUE) flow.inherit(bodyFlow);
+ else flow.inheritBranch(bodyFlow);
- if (fallsThrough) { // (5)
- this.performAutoreleases(innerFlow, stmts);
- stmts.push(module.br(continueLabel));
- }
- if (!alwaysTrue) { // (3)
- stmts.unshift(module.br(breakLabel, module.unary(UnaryOp.EqzI32, condExpr)));
- }
- var expr = flatten(module, stmts, NativeType.None);
- if (fallsThrough || innerFlow.isAny(FlowFlags.CONTINUES | FlowFlags.CONDITIONALLY_CONTINUES)) { // (2)
- expr = module.loop(continueLabel, expr);
- }
- if (!alwaysTrue || innerFlow.isAny(FlowFlags.BREAKS | FlowFlags.CONDITIONALLY_BREAKS)) { // (1)
- expr = module.block(breakLabel, [ expr ]);
+ // Detect if local flags are incompatible before and after looping, and
+ // if so recompile by unifying local flags between iterations.
+ // Here: Only relevant if flow does not always break.
+ if (!breaks && Flow.hasIncompatibleLocalStates(flowBefore, flow)) {
+ assert(!flowAfter); // should work on the first attempt
+ flow.freeTempLocal(tcond);
+ outerFlow.popBreakLabel();
+ this.currentFlow = outerFlow;
+ return this.doCompileWhileStatement(statement, flow);
+ }
}
+ stmts.push(
+ module.if(module.local_get(tcond.index, NativeType.I32),
+ module.flatten(bodyStmts)
+ )
+ );
+ flow.freeTempLocal(tcond);
+ this.currentFlow = flow;
- // Switch back to the parent flow
- innerFlow.freeScopedLocals();
+ // Finalize
+ assert(!flow.hasScopedLocals);
+ outerFlow.inherit(flow);
outerFlow.popBreakLabel();
- innerFlow.unset(
- FlowFlags.BREAKS |
- FlowFlags.CONDITIONALLY_BREAKS |
- FlowFlags.CONTINUES |
- FlowFlags.CONDITIONALLY_CONTINUES
- );
- if (alwaysTrue) outerFlow.inherit(innerFlow);
- else outerFlow.inheritConditional(innerFlow);
this.currentFlow = outerFlow;
+ var expr = module.block(breakLabel, [
+ module.loop(continueLabel,
+ module.flatten(stmts)
+ )
+ ]);
+ if (condKind == ConditionKind.TRUE && outerFlow.is(FlowFlags.TERMINATES)) {
+ expr = module.block(null, [ expr, module.unreachable() ]);
+ }
return expr;
}
@@ -2924,7 +3043,7 @@ export class Compiler extends DiagnosticEmitter {
// ensure conversion and wrapping in case the respective function doesn't on its own
var currentType = this.currentType;
var wrap = (constraints & Constraints.MUST_WRAP) != 0;
- if (currentType != contextualType) {
+ if (currentType != contextualType.nonNullableType) { // allow assigning non-nullable to nullable
if (constraints & Constraints.CONV_EXPLICIT) {
expr = this.convertExpression(expr, currentType, contextualType, true, wrap, expression);
wrap = false;
@@ -2953,6 +3072,32 @@ export class Compiler extends DiagnosticEmitter {
);
}
+ /** Compiles an expression that is about to be returned, taking special care of retaining and setting flow states. */
+ private compileReturnedExpression(
+ /** Expression to compile. */
+ expression: Expression,
+ /** Return type of the function. */
+ returnType: Type,
+ /** Constraints indicating contextual conditions. */
+ constraints: Constraints = Constraints.NONE
+ ): ExpressionRef {
+ // pretend to retain the expression immediately so the autorelease, if any, is skipped
+ var expr = this.compileExpression(expression, returnType, constraints | Constraints.WILL_RETAIN);
+ var flow = this.currentFlow;
+ if (returnType.isManaged) {
+ // check if that worked, and if it didn't, keep the reference alive
+ if (!this.skippedAutoreleases.has(expr)) {
+ let index = this.tryUndoAutorelease(expr, flow);
+ if (index == -1) expr = this.makeRetain(expr);
+ this.skippedAutoreleases.add(expr);
+ }
+ }
+ // remember return states
+ if (!flow.canOverflow(expr, returnType)) flow.set(FlowFlags.RETURNS_WRAPPED);
+ if (flow.isNonnull(expr, returnType)) flow.set(FlowFlags.RETURNS_NONNULL);
+ return expr;
+ }
+
convertExpression(
expr: ExpressionRef,
/** Original type. */
@@ -3146,7 +3291,7 @@ export class Compiler extends DiagnosticEmitter {
: expr;
}
- compileAssertionExpression(
+ private compileAssertionExpression(
expression: AssertionExpression,
contextualType: Type,
constraints: Constraints
@@ -3199,7 +3344,7 @@ export class Compiler extends DiagnosticEmitter {
private f32PowInstance: Function | null = null;
private f64PowInstance: Function | null = null;
- compileBinaryExpression(
+ private compileBinaryExpression(
expression: BinaryExpression,
contextualType: Type,
constraints: Constraints
@@ -4121,7 +4266,7 @@ export class Compiler extends DiagnosticEmitter {
rightExpr = this.compileExpression(right, Type.f32, Constraints.CONV_IMPLICIT);
rightType = this.currentType;
if (!(instance = this.f32PowInstance)) {
- let namespace = this.program.lookupGlobal(CommonSymbols.Mathf);
+ let namespace = this.program.lookupGlobal(CommonNames.Mathf);
if (!namespace) {
this.error(
DiagnosticCode.Cannot_find_name_0,
@@ -4130,7 +4275,7 @@ export class Compiler extends DiagnosticEmitter {
expr = module.unreachable();
break;
}
- let prototype = namespace.members ? namespace.members.get(CommonSymbols.pow) : null;
+ let prototype = namespace.members ? namespace.members.get(CommonNames.pow) : null;
if (!prototype) {
this.error(
DiagnosticCode.Cannot_find_name_0,
@@ -4155,7 +4300,7 @@ export class Compiler extends DiagnosticEmitter {
rightExpr = this.compileExpression(right, Type.f64, Constraints.CONV_IMPLICIT);
rightType = this.currentType;
if (!(instance = this.f64PowInstance)) {
- let namespace = this.program.lookupGlobal(CommonSymbols.Math);
+ let namespace = this.program.lookupGlobal(CommonNames.Math);
if (!namespace) {
this.error(
DiagnosticCode.Cannot_find_name_0,
@@ -4164,7 +4309,7 @@ export class Compiler extends DiagnosticEmitter {
expr = module.unreachable();
break;
}
- let prototype = namespace.members ? namespace.members.get(CommonSymbols.pow) : null;
+ let prototype = namespace.members ? namespace.members.get(CommonNames.pow) : null;
if (!prototype) {
this.error(
DiagnosticCode.Cannot_find_name_0,
@@ -4397,7 +4542,7 @@ export class Compiler extends DiagnosticEmitter {
case TypeKind.F32: {
let instance = this.f32ModInstance;
if (!instance) {
- let namespace = this.program.lookupGlobal(CommonSymbols.Mathf);
+ let namespace = this.program.lookupGlobal(CommonNames.Mathf);
if (!namespace) {
this.error(
DiagnosticCode.Cannot_find_name_0,
@@ -4406,7 +4551,7 @@ export class Compiler extends DiagnosticEmitter {
expr = module.unreachable();
break;
}
- let prototype = namespace.members ? namespace.members.get(CommonSymbols.mod) : null;
+ let prototype = namespace.members ? namespace.members.get(CommonNames.mod) : null;
if (!prototype) {
this.error(
DiagnosticCode.Cannot_find_name_0,
@@ -4428,7 +4573,7 @@ export class Compiler extends DiagnosticEmitter {
case TypeKind.F64: {
let instance = this.f64ModInstance;
if (!instance) {
- let namespace = this.program.lookupGlobal(CommonSymbols.Math);
+ let namespace = this.program.lookupGlobal(CommonNames.Math);
if (!namespace) {
this.error(
DiagnosticCode.Cannot_find_name_0,
@@ -4437,7 +4582,7 @@ export class Compiler extends DiagnosticEmitter {
expr = module.unreachable();
break;
}
- let prototype = namespace.members ? namespace.members.get(CommonSymbols.mod) : null;
+ let prototype = namespace.members ? namespace.members.get(CommonNames.mod) : null;
if (!prototype) {
this.error(
DiagnosticCode.Cannot_find_name_0,
@@ -5191,6 +5336,7 @@ export class Compiler extends DiagnosticEmitter {
return this.makeAssignment(
target,
expr, // TODO: delay release above if possible?
+ this.currentType,
left,
resolver.currentThisExpression,
resolver.currentElementExpression,
@@ -5198,7 +5344,7 @@ export class Compiler extends DiagnosticEmitter {
);
}
- compileUnaryOverload(
+ private compileUnaryOverload(
operatorInstance: Function,
value: Expression,
valueExpr: ExpressionRef,
@@ -5209,7 +5355,7 @@ export class Compiler extends DiagnosticEmitter {
return this.makeCallDirect(operatorInstance, [ valueExpr ], reportNode, false);
}
- compileBinaryOverload(
+ private compileBinaryOverload(
operatorInstance: Function,
left: Expression,
leftExpr: ExpressionRef,
@@ -5235,7 +5381,7 @@ export class Compiler extends DiagnosticEmitter {
return this.makeCallDirect(operatorInstance, [ leftExpr, rightExpr ], reportNode);
}
- compileAssignment(expression: Expression, valueExpression: Expression, contextualType: Type): ExpressionRef {
+ private compileAssignment(expression: Expression, valueExpression: Expression, contextualType: Type): ExpressionRef {
var program = this.program;
var resolver = program.resolver;
var flow = this.currentFlow;
@@ -5324,9 +5470,11 @@ export class Compiler extends DiagnosticEmitter {
// compile the value and do the assignment
assert(targetType != Type.void);
+ var valueExpr = this.compileExpression(valueExpression, targetType, Constraints.CONV_IMPLICIT | Constraints.WILL_RETAIN);
return this.makeAssignment(
target,
- this.compileExpression(valueExpression, targetType, Constraints.CONV_IMPLICIT | Constraints.WILL_RETAIN),
+ valueExpr,
+ this.currentType,
expression,
thisExpression,
elementExpression,
@@ -5340,6 +5488,8 @@ export class Compiler extends DiagnosticEmitter {
target: Element,
/** Value expression that has been compiled in a previous step already. */
valueExpr: ExpressionRef,
+ /** Value expression type. */
+ valueType: Type,
/** Expression reference. Has already been compiled to `valueExpr`. */
valueExpression: Expression,
/** `this` expression reference if a field or property set. */
@@ -5365,7 +5515,7 @@ export class Compiler extends DiagnosticEmitter {
this.currentType = tee ? (target).type : Type.void;
return module.unreachable();
}
- return this.makeLocalAssignment(target, valueExpr, tee);
+ return this.makeLocalAssignment(target, valueExpr, valueType, tee);
}
case ElementKind.GLOBAL: {
if (!this.compileGlobal(target)) return module.unreachable();
@@ -5530,10 +5680,12 @@ export class Compiler extends DiagnosticEmitter {
/** Makes an assignment to a local, possibly retaining and releasing affected references and keeping track of wrap and null states. */
private makeLocalAssignment(
- /** The local to assign to. */
+ /** Local to assign to. */
local: Local,
- /** The value to assign. */
+ /** Value to assign. */
valueExpr: ExpressionRef,
+ /** Value type. */
+ valueType: Type,
/** Whether to tee the value. */
tee: bool
): ExpressionRef {
@@ -5544,10 +5696,10 @@ export class Compiler extends DiagnosticEmitter {
var localIndex = local.index;
if (type.is(TypeFlags.NULLABLE)) {
- if (flow.isNonnull(valueExpr, type)) flow.setLocalFlag(localIndex, LocalFlags.NONNULL);
+ if (!valueType.is(TypeFlags.NULLABLE) || flow.isNonnull(valueExpr, type)) flow.setLocalFlag(localIndex, LocalFlags.NONNULL);
else flow.unsetLocalFlag(localIndex, LocalFlags.NONNULL);
}
- flow.setLocalFlag(localIndex, LocalFlags.WRITTENTO);
+ flow.setLocalFlag(localIndex, LocalFlags.INITIALIZED);
if (type.isManaged) {
let alreadyRetained = this.skippedAutoreleases.has(valueExpr);
@@ -5642,7 +5794,7 @@ export class Compiler extends DiagnosticEmitter {
}
/** Makes an assignment to a field, possibly retaining and releasing affected references. */
- makeFieldAssignment(
+ private makeFieldAssignment(
/** The field to assign to. */
field: Field,
/** The value to assign. */
@@ -5730,7 +5882,7 @@ export class Compiler extends DiagnosticEmitter {
}
/** Compiles a call expression according to the specified context. */
- compileCallExpression(
+ private compileCallExpression(
/** Call expression to compile. */
expression: CallExpression,
/** Contextual type indicating the return type the caller expects, if any. */
@@ -5756,7 +5908,7 @@ export class Compiler extends DiagnosticEmitter {
let classInstance = assert(actualFunction.parent); assert(classInstance.kind == ElementKind.CLASS);
let baseClassInstance = assert((classInstance).base);
- let thisLocal = assert(flow.lookupLocal(CommonSymbols.this_));
+ let thisLocal = assert(flow.lookupLocal(CommonNames.this_));
let nativeSizeType = this.options.nativeSizeType;
// {
@@ -5781,7 +5933,7 @@ export class Compiler extends DiagnosticEmitter {
let stmts: ExpressionRef[] = [
module.local_set(thisLocal.index, theCall)
];
- this.makeFieldInitialization(classInstance, stmts);
+ this.makeFieldInitializationInConstructor(classInstance, stmts);
// check that super had been called before accessing `this`
if (flow.isAny(
@@ -5796,7 +5948,7 @@ export class Compiler extends DiagnosticEmitter {
}
flow.set(FlowFlags.ALLOCATES | FlowFlags.CALLS_SUPER);
this.currentType = Type.void;
- return module.block(null, stmts);
+ return module.flatten(stmts);
}
// otherwise resolve normally
@@ -6076,13 +6228,14 @@ export class Compiler extends DiagnosticEmitter {
// Inline if explicitly requested
if (instance.hasDecorator(DecoratorFlags.INLINE)) {
assert(!instance.is(CommonFlags.TRAMPOLINE)); // doesn't make sense
- if (this.currentInlineFunctions.includes(instance)) {
+ let inlineStack = this.inlineStack;
+ if (inlineStack.includes(instance)) {
this.warning(
DiagnosticCode.Function_0_cannot_be_inlined_into_itself,
reportNode.range, instance.internalName
);
} else {
- this.currentInlineFunctions.push(instance);
+ inlineStack.push(instance);
let parameterTypes = signature.parameterTypes;
assert(numArguments <= parameterTypes.length);
// compile argument expressions
@@ -6101,7 +6254,7 @@ export class Compiler extends DiagnosticEmitter {
this.skippedAutoreleases.add(expr);
}
}
- this.currentInlineFunctions.pop();
+ inlineStack.pop();
return expr;
}
}
@@ -6183,13 +6336,13 @@ export class Compiler extends DiagnosticEmitter {
if (thisArg) {
let classInstance = assert(instance.parent); assert(classInstance.kind == ElementKind.CLASS);
let thisType = assert(instance.signature.thisType);
- let thisLocal = flow.addScopedLocal(CommonSymbols.this_, thisType, usedLocals);
+ let thisLocal = flow.addScopedLocal(CommonNames.this_, thisType, usedLocals);
// No need to retain `this` as it can't be reassigned and thus can't become prematurely released
body.unshift(
module.local_set(thisLocal.index, thisArg)
);
let baseInstance = (classInstance).base;
- if (baseInstance) flow.addScopedAlias(CommonSymbols.super_, baseInstance.type, thisLocal.index);
+ if (baseInstance) flow.addScopedAlias(CommonNames.super_, baseInstance.type, thisLocal.index);
} else {
assert(!instance.signature.thisType);
}
@@ -6321,10 +6474,10 @@ export class Compiler extends DiagnosticEmitter {
minArguments
? module.binary(
BinaryOp.SubI32,
- module.global_get(BuiltinSymbols.argc, NativeType.I32),
+ module.global_get(BuiltinNames.argumentsLength, NativeType.I32),
module.i32(minArguments)
)
- : module.global_get(BuiltinSymbols.argc, NativeType.I32)
+ : module.global_get(BuiltinNames.argumentsLength, NativeType.I32)
)
]),
module.unreachable()
@@ -6373,41 +6526,19 @@ export class Compiler extends DiagnosticEmitter {
trampolineSignature.nativeParams,
trampolineSignature.nativeResults,
typesToNativeTypes(trampoline.additionalLocals),
- module.block(null, stmts, returnType.toNativeType())
+ module.flatten(stmts, returnType.toNativeType())
);
trampoline.finalize(module, funcRef);
return trampoline;
}
- /** Makes sure that the argument count helper global is present and returns its name. */
- private ensureArgcVar(): string {
- if (!this.argcVar) {
+ /** Makes sure that the arguments length helper global is present. */
+ ensureBuiltinArgumentsLength(): void {
+ if (!this.builtinArgumentsLength) {
let module = this.module;
- this.argcVar = module.addGlobal(
- BuiltinSymbols.argc,
- NativeType.I32,
- true,
- module.i32(0)
- );
- }
- return BuiltinSymbols.argc;
- }
-
- /** Makes sure that the argument count helper setter is present and returns its name. */
- private ensureArgcSet(): string {
- if (!this.argcSet) {
- let module = this.module;
- this.argcSet = module.addFunction(BuiltinSymbols.setargc,
- NativeType.I32,
- NativeType.None,
- null,
- module.global_set(this.ensureArgcVar(),
- module.local_get(0, NativeType.I32)
- )
- );
- module.addFunctionExport(BuiltinSymbols.setargc, "__setargc");
+ this.builtinArgumentsLength = module.addGlobal(BuiltinNames.argumentsLength, NativeType.I32, true, module.i32(0));
+ module.addGlobalExport(BuiltinNames.argumentsLength, ExportNames.argumentsLength);
}
- return BuiltinSymbols.setargc;
}
//
@@ -6623,22 +6754,22 @@ export class Compiler extends DiagnosticEmitter {
);
var lengthBefore = stmts.length;
this.performAutoreleases(flow, stmts, finalize);
+ var module = this.module;
if (stmts.length > lengthBefore) {
let nativeType = valueType.toNativeType();
let temp = flow.getTempLocal(valueType);
if (!flow.canOverflow(valueExpr, valueType)) flow.setLocalFlag(temp.index, LocalFlags.WRAPPED);
if (flow.isNonnull(valueExpr, valueType)) flow.setLocalFlag(temp.index, LocalFlags.NONNULL);
- let module = this.module;
stmts[lengthBefore - 1] = module.local_set(temp.index, valueExpr); // nop -> set
stmts.push(
module.local_get(temp.index, nativeType) // append get
);
- let ret = module.block(null, stmts, nativeType);
+ let ret = module.flatten(stmts, nativeType);
flow.freeTempLocal(temp);
return ret;
} else if (stmts.length > 1) {
stmts[lengthBefore - 1] = valueExpr; // nop -> value
- return this.module.block(null, stmts, valueType.toNativeType());
+ return module.flatten(stmts, valueType.toNativeType());
}
return valueExpr;
}
@@ -6652,7 +6783,7 @@ export class Compiler extends DiagnosticEmitter {
): void {
// Differs from `performAutoreleases` in that concluding this flow also
// concludes all its parent flows, for example on a `return`.
- if (flow.is(FlowFlags.INLINE_CONTEXT)) {
+ if (flow.isInline) {
// Traverse to the top-most flow containing the inlined function's
// locals as scoped locals and release these instead of all the locals.
let current = flow;
@@ -6705,13 +6836,14 @@ export class Compiler extends DiagnosticEmitter {
): ExpressionRef {
if (instance.hasDecorator(DecoratorFlags.INLINE)) {
assert(!instance.is(CommonFlags.TRAMPOLINE)); // doesn't make sense
- if (this.currentInlineFunctions.includes(instance)) {
+ let inlineStack = this.inlineStack;
+ if (inlineStack.includes(instance)) {
this.warning(
DiagnosticCode.Function_0_cannot_be_inlined_into_itself,
reportNode.range, instance.internalName
);
} else {
- this.currentInlineFunctions.push(instance);
+ inlineStack.push(instance);
let expr: ExpressionRef;
if (instance.is(CommonFlags.INSTANCE)) {
let theOperands = assert(operands);
@@ -6728,7 +6860,7 @@ export class Compiler extends DiagnosticEmitter {
this.skippedAutoreleases.add(expr);
}
}
- this.currentInlineFunctions.pop();
+ inlineStack.pop();
return expr;
}
}
@@ -6815,8 +6947,9 @@ export class Compiler extends DiagnosticEmitter {
this.skippedAutoreleases.add(expr);
}
}
+ this.ensureBuiltinArgumentsLength();
return module.block(null, [
- module.global_set(this.ensureArgcVar(), module.i32(numArguments)),
+ module.global_set(BuiltinNames.argumentsLength, module.i32(numArguments)),
expr
], this.currentType.toNativeType());
}
@@ -6911,8 +7044,9 @@ export class Compiler extends DiagnosticEmitter {
}
var returnType = signature.returnType;
+ this.ensureBuiltinArgumentsLength();
var expr = module.block(null, [
- module.global_set(this.ensureArgcVar(), // might be calling a trampoline
+ module.global_set(BuiltinNames.argumentsLength, // might be calling a trampoline
module.i32(numArguments)
),
module.call_indirect(
@@ -6936,7 +7070,7 @@ export class Compiler extends DiagnosticEmitter {
return expr;
}
- compileCommaExpression(
+ private compileCommaExpression(
expression: CommaExpression,
contextualType: Type,
constraints: Constraints
@@ -6950,10 +7084,10 @@ export class Compiler extends DiagnosticEmitter {
);
}
exprs[numExpressions] = this.compileExpression(expressions[numExpressions], contextualType, constraints);
- return this.module.block(null, exprs, this.currentType.toNativeType());
+ return this.module.flatten(exprs, this.currentType.toNativeType());
}
- compileElementAccessExpression(
+ private compileElementAccessExpression(
expression: ElementAccessExpression,
contextualType: Type,
constraints: Constraints
@@ -6984,7 +7118,7 @@ export class Compiler extends DiagnosticEmitter {
return module.unreachable();
}
- compileFunctionExpression(
+ private compileFunctionExpression(
expression: FunctionExpression,
contextualSignature: Signature | null,
constraints: Constraints
@@ -7107,12 +7241,9 @@ export class Compiler extends DiagnosticEmitter {
// otherwise compile like a normal function
} else {
- instance = this.compileFunctionUsingTypeArguments(
- prototype,
- [],
- contextualTypeArguments
- );
+ instance = this.resolver.resolveFunction(prototype, null, contextualTypeArguments);
if (!instance) return this.module.unreachable();
+ this.compileFunction(instance);
this.currentType = instance.signature.type;
}
@@ -7133,12 +7264,7 @@ export class Compiler extends DiagnosticEmitter {
}
}
- /**
- * Compiles an identifier in the specified context.
- * @param retainConstantType Retains the type of inlined constants if `true`, otherwise
- * precomputes them according to context.
- */
- compileIdentifierExpression(
+ private compileIdentifierExpression(
expression: IdentifierExpression,
contextualType: Type,
constraints: Constraints
@@ -7179,7 +7305,7 @@ export class Compiler extends DiagnosticEmitter {
}
case NodeKind.THIS: {
if (actualFunction.is(CommonFlags.INSTANCE)) {
- let thisLocal = assert(flow.lookupLocal(CommonSymbols.this_));
+ let thisLocal = assert(flow.lookupLocal(CommonNames.this_));
let classInstance = assert(actualFunction.parent); assert(classInstance.kind == ElementKind.CLASS);
let nativeSizeType = this.options.nativeSizeType;
if (actualFunction.is(CommonFlags.CONSTRUCTOR)) {
@@ -7203,12 +7329,12 @@ export class Compiler extends DiagnosticEmitter {
)
)
];
- this.makeFieldInitialization(classInstance, stmts);
+ this.makeFieldInitializationInConstructor(classInstance, stmts);
stmts.push(
module.local_get(thisLocal.index, nativeSizeType)
);
this.currentType = thisLocal.type;
- return module.block(null, stmts, nativeSizeType);
+ return module.flatten(stmts, nativeSizeType);
}
}
// if not a constructor, `this` type can differ
@@ -7235,8 +7361,8 @@ export class Compiler extends DiagnosticEmitter {
);
}
}
- if (flow.is(FlowFlags.INLINE_CONTEXT)) {
- let scopedThis = flow.lookupLocal(CommonSymbols.this_);
+ if (flow.isInline) {
+ let scopedThis = flow.lookupLocal(CommonNames.this_);
if (scopedThis) {
let scopedThisClass = assert(scopedThis.type.classReference);
let base = scopedThisClass.base;
@@ -7272,7 +7398,11 @@ export class Compiler extends DiagnosticEmitter {
flow,
this.currentParent || actualFunction
);
- if (!target) return module.unreachable();
+ if (!target) {
+ // make a guess to avoid assertions in calling code
+ if (this.currentType == Type.void) this.currentType = Type.i32;
+ return module.unreachable();
+ }
switch (target.kind) {
case ElementKind.LOCAL: {
@@ -7349,7 +7479,7 @@ export class Compiler extends DiagnosticEmitter {
return this.module.unreachable();
}
- compileInstanceOfExpression(
+ private compileInstanceOfExpression(
expression: InstanceOfExpression,
contextualType: Type,
constraints: Constraints
@@ -7481,7 +7611,7 @@ export class Compiler extends DiagnosticEmitter {
], NativeType.I32);
}
- compileLiteralExpression(
+ private compileLiteralExpression(
expression: LiteralExpression,
contextualType: Type,
constraints: Constraints,
@@ -7573,7 +7703,7 @@ export class Compiler extends DiagnosticEmitter {
return module.unreachable();
}
- compileStringLiteral(
+ private compileStringLiteral(
expression: StringLiteralExpression,
constraints: Constraints
): ExpressionRef {
@@ -7587,7 +7717,7 @@ export class Compiler extends DiagnosticEmitter {
return expr;
}
- compileArrayLiteral(
+ private compileArrayLiteral(
elementType: Type,
expressions: (Expression | null)[],
constraints: Constraints,
@@ -7658,13 +7788,13 @@ export class Compiler extends DiagnosticEmitter {
flow.freeTempLocal(tempDataStart);
let runtimeHeaderSize = program.runtimeHeaderSize;
- let bufferSegment = this.ensureStaticArrayBuffer(elementType, values);
+ let bufferSegment = this.addStaticBuffer(elementType, values);
let bufferAddress = i64_add(bufferSegment.offset, i64_new(runtimeHeaderSize));
// make both the buffer and array header static if assigned to a global. this can't be done
// if inside of a function because each invocation must create a new array reference then.
if (constraints & Constraints.PREFER_STATIC) {
- let arraySegment = this.ensureStaticArrayHeader(elementType, bufferSegment);
+ let arraySegment = this.addStaticArrayHeader(elementType, bufferSegment);
let arrayAddress = i64_add(arraySegment.offset, i64_new(runtimeHeaderSize));
this.currentType = arrayType;
return program.options.isWasm64
@@ -7685,7 +7815,15 @@ export class Compiler extends DiagnosticEmitter {
: module.i32(i64_low(bufferAddress))
], reportNode);
this.currentType = arrayType;
- return this.makeAutorelease(this.makeRetain(expr), arrayType);
+ expr = this.makeRetain(expr);
+ if (arrayType.isManaged) {
+ if (!(constraints & Constraints.WILL_RETAIN)) {
+ expr = this.makeAutorelease(expr, arrayType);
+ } else {
+ this.skippedAutoreleases.add(expr);
+ }
+ }
+ return expr;
}
}
@@ -7707,16 +7845,18 @@ export class Compiler extends DiagnosticEmitter {
// tempThis = makeArray(length, alignLog2, classId, source = 0)
stmts.push(
module.local_set(tempThis.index,
- this.makeCallDirect(program.allocArrayInstance, [
- module.i32(length),
- program.options.isWasm64
- ? module.i64(elementType.alignLog2)
- : module.i32(elementType.alignLog2),
- module.i32(arrayInstance.id),
- program.options.isWasm64
- ? module.i64(0)
- : module.i32(0)
- ], reportNode),
+ this.makeRetain(
+ this.makeCallDirect(program.allocArrayInstance, [
+ module.i32(length),
+ program.options.isWasm64
+ ? module.i64(elementType.alignLog2)
+ : module.i32(elementType.alignLog2),
+ module.i32(arrayInstance.id),
+ program.options.isWasm64
+ ? module.i64(0)
+ : module.i32(0)
+ ], reportNode)
+ )
)
);
// tempData = tempThis.dataStart
@@ -7755,10 +7895,18 @@ export class Compiler extends DiagnosticEmitter {
flow.freeTempLocal(tempThis);
flow.freeTempLocal(tempDataStart);
this.currentType = arrayType;
- return module.block(null, stmts, nativeArrayType);
+ var expr = module.flatten(stmts, nativeArrayType);
+ if (arrayType.isManaged) {
+ if (!(constraints & Constraints.WILL_RETAIN)) {
+ expr = this.makeAutorelease(expr, arrayType, this.currentFlow);
+ } else {
+ this.skippedAutoreleases.add(expr);
+ }
+ }
+ return expr;
}
- compileObjectLiteral(expression: ObjectLiteralExpression, contextualType: Type): ExpressionRef {
+ private compileObjectLiteral(expression: ObjectLiteralExpression, contextualType: Type): ExpressionRef {
var module = this.module;
// contextual type must be a class
@@ -7844,10 +7992,10 @@ export class Compiler extends DiagnosticEmitter {
exprs[exprs.length - 1] = module.local_get(tempLocal.index, this.options.nativeSizeType);
this.currentType = classReference.type;
- return module.block(null, exprs, this.options.nativeSizeType);
+ return module.flatten(exprs, this.options.nativeSizeType);
}
- compileNewExpression(
+ private compileNewExpression(
expression: NewExpression,
contextualType: Type,
constraints: Constraints
@@ -7907,9 +8055,9 @@ export class Compiler extends DiagnosticEmitter {
if (baseClass) {
let baseCtor = this.ensureConstructor(baseClass, reportNode);
instance = new Function(
- CommonSymbols.constructor,
+ CommonNames.constructor,
new FunctionPrototype(
- CommonSymbols.constructor,
+ CommonNames.constructor,
classInstance,
// declaration is important, i.e. to access optional parameter initializers
(baseCtor.declaration).clone()
@@ -7921,11 +8069,11 @@ export class Compiler extends DiagnosticEmitter {
// otherwise make a default constructor
} else {
instance = new Function(
- CommonSymbols.constructor,
+ CommonNames.constructor,
new FunctionPrototype(
- CommonSymbols.constructor,
+ CommonNames.constructor,
classInstance,
- this.program.makeNativeFunctionDeclaration(CommonSymbols.constructor,
+ this.program.makeNativeFunctionDeclaration(CommonNames.constructor,
CommonFlags.INSTANCE | CommonFlags.CONSTRUCTOR
)
),
@@ -7980,7 +8128,7 @@ export class Compiler extends DiagnosticEmitter {
)
);
}
- this.makeFieldInitialization(classInstance, stmts);
+ this.makeFieldInitializationInConstructor(classInstance, stmts);
var body = this.performAutoreleasesWithValue(flow, module.local_get(0, nativeSizeType), classInstance.type, stmts);
flow.freeScopedLocals();
this.currentFlow = previousFlow;
@@ -8023,12 +8171,7 @@ export class Compiler extends DiagnosticEmitter {
return expr;
}
- /**
- * Compiles a property access in the specified context.
- * @param retainConstantType Retains the type of inlined constants if `true`, otherwise
- * precomputes them according to context.
- */
- compilePropertyAccessExpression(
+ private compilePropertyAccessExpression(
expression: PropertyAccessExpression,
ctxType: Type,
constraints: Constraints
@@ -8070,7 +8213,18 @@ export class Compiler extends DiagnosticEmitter {
}
case ElementKind.FIELD: { // instance field
assert((target).memoryOffset >= 0);
- let thisExpr = this.compileExpression(assert(this.resolver.currentThisExpression), this.options.usizeType);
+ let thisExpression = assert(this.resolver.currentThisExpression);
+ let thisExpr = this.compileExpression(thisExpression, this.options.usizeType);
+ // FIXME
+ let thisType = this.currentType;
+ if (thisType.is(TypeFlags.NULLABLE)) {
+ if (!flow.isNonnull(thisExpr, thisType)) {
+ this.error(
+ DiagnosticCode.Object_is_possibly_null,
+ thisExpression.range
+ );
+ }
+ }
this.currentType = (target).type;
return module.load(
(target).type.byteSize,
@@ -8098,18 +8252,11 @@ export class Compiler extends DiagnosticEmitter {
let prototype =