Progress and a tiny WASM binary parser

This commit is contained in:
dcodeIO 2018-04-03 23:56:48 +02:00
parent 06198a3723
commit 5823e35f37
58 changed files with 12075 additions and 3964 deletions

View File

@ -23,6 +23,9 @@ A few early examples to get an idea:
* **[PSON decoder](./examples/pson)**<br />
A simple decoder for the PSON binary format.
* **[WASM parser](./lib/parse)**<br />
A WebAssembly binary parser in WebAssembly.
Or browse the [compiler tests](./tests/compiler) for a more in-depth overview of what's supported already. One of them is a [showcase](./tests/compiler/showcase.ts).
Installation

View File

@ -93,7 +93,7 @@ exports.compileString = (source, extraArgs={}) => new Promise((resolve, reject)
const libDir = path.join(__dirname, "../std", "assembly");
const libFiles = require("glob").sync("**/*.ts", { cwd: libDir });
libFiles.forEach(file =>
exports.libraryFiles["~lib/" + file.replace(/\.ts$/, "")] = readFileNode(path.join(libDir, file), { encoding: "utf8" })
exports.libraryFiles[file.replace(/\.ts$/, "")] = readFileNode(path.join(libDir, file), { encoding: "utf8" })
);
}
@ -249,54 +249,71 @@ exports.main = function main(argv, options, callback) {
// Load library file if explicitly requested
if (sourcePath.startsWith(exports.libraryPrefix)) {
for (let i = 0, k = libDirs.length; i < k; ++i) {
if (exports.libraryFiles.hasOwnProperty(sourcePath)) {
sourceText = exports.libraryFiles[sourcePath];
sourcePath += ".ts";
} else {
sourceText = readFile(path.join(
libDirs[i],
sourcePath.substring(exports.libraryPrefix.length) + ".ts")
);
const plainName = sourcePath.substring(exports.libraryPrefix.length);
const indexName = sourcePath.substring(exports.libraryPrefix.length) + "/index";
if (exports.libraryFiles.hasOwnProperty(plainName)) {
sourceText = exports.libraryFiles[plainName];
sourcePath = exports.libraryPrefix + plainName + ".ts";
} else if (exports.libraryFiles.hasOwnProperty(indexName)) {
sourceText = exports.libraryFiles[indexName];
sourcePath = exports.libraryPrefix + indexName + ".ts";
} else {
for (let i = 0, k = libDirs.length; i < k; ++i) {
const dir = libDirs[i];
sourceText = readFile(path.join(dir, plainName + ".ts"));
if (sourceText !== null) {
sourcePath += ".ts";
sourcePath = exports.libraryPrefix + plainName + ".ts";
break;
} else {
sourceText = readFile(path.join(dir, indexName + ".ts"));
if (sourceText !== null) {
sourcePath = exports.libraryPrefix + indexName + ".ts";
break;
}
}
}
}
// Otherwise try nextFile.ts, nextFile/index.ts, ~lib/nextFile.ts
// Otherwise try nextFile.ts, nextFile/index.ts, ~lib/nextFile.ts, ~lib/nextFile/index.ts
} else {
sourceText = readFile(path.join(baseDir, sourcePath + ".ts"));
const plainName = sourcePath;
const indexName = sourcePath + "/index";
sourceText = readFile(path.join(baseDir, plainName + ".ts"));
if (sourceText !== null) {
sourcePath += ".ts";
sourcePath = plainName + ".ts";
} else {
sourceText = readFile(path.join(baseDir, sourcePath, "index.ts"));
sourceText = readFile(path.join(baseDir, indexName + ".ts"));
if (sourceText !== null) {
sourcePath += "/index.ts";
} else {
const key = exports.libraryPrefix + sourcePath;
if (exports.libraryFiles.hasOwnProperty(key)) {
sourceText = exports.libraryFiles[key];
sourcePath = key + ".ts";
sourcePath = indexName + ".ts";
} else if (!plainName.startsWith(".")) {
if (exports.libraryFiles.hasOwnProperty(plainName)) {
sourceText = exports.libraryFiles[plainName];
sourcePath = exports.libraryPrefix + plainName + ".ts";
} else if (exports.libraryFiles.hasOwnProperty(indexName)) {
sourceText = exports.libraryFiles[indexName];
sourcePath = exports.libraryPrefix + indexName + ".ts";
} else {
for (let i = 0, k = libDirs.length; i < k; ++i) {
const dir = libDirs[i];
sourceText = readFile(path.join(dir, sourcePath + ".ts"));
sourceText = readFile(path.join(dir, plainName + ".ts"));
if (sourceText !== null) {
sourcePath = exports.libraryPrefix + sourcePath + ".ts";
sourcePath = exports.libraryPrefix + plainName + ".ts";
break;
} else {
sourceText = readFile(path.join(dir, indexName + ".ts"));
if (sourceText !== null) {
sourcePath = exports.libraryPrefix + indexName + ".ts";
break;
}
}
}
if (sourceText === null) {
return callback(
Error("Import file '" + sourcePath + ".ts' not found.")
);
}
}
}
}
}
if (sourceText == null) {
return callback(Error("Import file '" + plainName + ".ts' not found."));
}
stats.parseCount++;
stats.parseTime += measure(() => {
assemblyscript.parseFile(sourceText, sourcePath, false, parser);

2
dist/asc.js vendored

File diff suppressed because one or more lines are too long

2
dist/asc.js.map vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -12,10 +12,6 @@
["boolean", "Use `bool` instead."]
]
},
"object-literal-shorthand": {
"severity": "error",
"options": ["never"]
},
"restrict-plus-operands": {
"severity": "error"
},

95
lib/parse/README.md Normal file
View File

@ -0,0 +1,95 @@
# ![AS](https://avatars1.githubusercontent.com/u/28916798?s=48) parse
A WebAssembly binary parser in WebAssembly.
API
---
* **parse**(binary: `Uint8Array`, options?: `ParseOptions`): `void`<br />
Parses the contents of a WebAssembly binary according to the specified options.
* **ParseOptions**<br />
Options specified to the parser. The `onSection` callback determines the sections being evaluated in detail.
* **onSection**?(id: `SectionId`, payloadOff: `number`, payloadLen: `number`, nameOff: `number`, nameLen: `number`): `boolean`<br />
Called with each section in the binary. Returning `true` evaluates the section.
* **onType**?(index: `number`, form: `number`): `void`<br />
Called with each function type if the type section is evaluated.
* **onTypeParam**?(index: `number`, paramIndex: `number`, paramType: `Type`): `void`<br />
Called with each function parameter if the type section is evaluated.
* **onTypeReturn**?(index: `number`, returnIndex: `number`, returnType: `Type`): `void`<br />
Called with each function return type if the type section is evaluated.
* **onImport**?(index: `number`, kind: `ExternalKind`, moduleOff: `number`, moduleLen: `number`, fieldOff: `number`, fieldLen: `number`): `void`<br />
Called with each import if the import section is evaluated.
* **onFunctionImport**?(index: `number`, type: `number`): `void`<br />
Called with each function import if the import section is evaluated.
* **onTableImport**?(index: `number`, type: `Type`, initial: `number`, maximum: `number`, flags: `number`): `void`<br />
Called with each table import if the import section is evaluated.
* **onMemoryImport**?(index: `number`, initial: `number`, maximum: `number`, flags: `number`): `void`<br />
Called with each memory import if the import section is evaluated.
* **onGlobalImport**?(index: `number`, type: `Type`, mutability: `number`): `void`<br />
Called with each global import if the import section is evaluated.
* **onMemory**?(index: `number`, initial: `number`, maximum: `number`, flags: `number`): `void`<br />
Called with each memory if the memory section is evaluated.
* **onFunction**?(index: `number`, typeIndex: `number`): `void`<br />
Called with each function if the function section is evaluated.
* **onGlobal**?(index: `number`, type: `Type`, mutability: `number`): `void`<br />
Called with each global if the global section is evaluated.
* **onStart**?(index: `number`): `void`<br />
Called with the start function index if the start section is evaluated.
* **onExport**?(index: `number`, kind: `ExternalKind`, kindIndex: `number`, nameOff: `number`, nameLen: `number`): `void`<br />
Called with each export if the export section is evaluated.
* **Type**<br />
A value or element type, depending on context.
| Name | Value
|---------|-------
| i32 | 0x7f
| i64 | 0x7e
| f32 | 0x7d
| f64 | 0x7c
| anyfunc | 0x70
| func | 0x60
| none | 0x40
* **SectionId**<br />
Numerical id of the current section.
| Name | Value
|----------|-------
| Custom | 0
| Type | 1
| Import | 2
| Function | 3
| Table | 4
| Memory | 5
| Global | 6
| Export | 7
| Start | 8
| Element | 9
| Code | 10
| Data | 11
* **ExternalKind**<br />
Kind of an export or import.
| Name | Value
|----------|-------
| Function | 0
| Table | 1
| Memory | 2
| Global | 3

285
lib/parse/assembly/index.ts Normal file
View File

@ -0,0 +1,285 @@
/** A WebAssembly module that parses WebAssembly modules. */
// Common constants shared between AssemblyScript and TypeScript
import {
Type,
SectionId,
ExternalKind,
MAX_PAGES,
MAX_TABLES,
Opcode
} from "../src/common";
/** Current offset in memory. */
var off: usize = 0;
/** Reads an unsigned integer from memory. */
function readUint<T>(): u32 {
var pos = off;
var val = <u32>load<T>(pos);
off = pos + sizeof<T>();
return val;
}
/** Reads an unsigned 64-bit integer from memory. */
function readUint64(): u64 {
var pos = off;
var val = load<u64>(pos);
off = pos + 8;
return val;
}
/** Reads a LEB128-encoded unsigned integer from memory. */
function readVaruint(size: u32): u32 {
var val: u32 = 0;
var shl: u32 = 0;
var byt: u32;
var pos = off;
do {
byt = load<u8>(pos++);
val |= (byt & 0x7F) << shl;
if (!(byt & 0x80)) break;
shl += 7;
} while (true);
off = pos;
return val;
}
/** Reads a LEB128-encoded signed integer from memory. */
function readVarint(size: u32): i32 {
var val: u32 = 0;
var shl: u32 = 0;
var byt: u32;
var pos = off;
do {
byt = load<u8>(pos++);
val |= (byt & 0x7F) << shl;
shl += 7;
} while (byt & 0x80);
off = pos;
return select<u32>(val | (~0 << shl), val, shl < size && (byt & 0x40) != 0);
}
/** Reads a LEB128-encoded signed 64-bit integer from memory. */
function readVarint64(): i64 {
var val: u64 = 0;
var shl: u64 = 0;
var byt: u64;
var pos = off;
do {
byt = load<u8>(pos++);
val |= (byt & 0x7F) << shl;
shl += 7;
} while (byt & 0x80);
off = pos;
return select<u64>(val | (~0 << shl), val, shl < 64 && (byt & 0x40) != 0);
}
// Imported callbacks
declare function onSection(id: u32, offset: u32, length: u32, nameOffset: u32, nameLength: u32): bool;
declare function onType(index: u32, form: u32): void;
declare function onTypeParam(index: u32, paramIndex: u32, paramType: u32): void;
declare function onTypeReturn(index: u32, returnIndex: u32, returnType: u32): void;
declare function onImport(index: u32, kind: u32, moduleOff: u32, moduleLen: u32, fieldOff: u32, fieldLen: u32): void;
declare function onFunctionImport(index: u32, type: u32): void;
declare function onTableImport(index: u32, type: u32, initial: u32, maximum: u32, flags: u32): void;
declare function onMemoryImport(index: u32, initial: u32, maximum: u32, flags: u32): void;
declare function onGlobalImport(index: u32, type: u32, mutability: u32): void;
declare function onMemory(index: u32, initial: u32, maximum: u32, flags: u32): void;
declare function onFunction(index: u32, typeIndex: u32): void;
declare function onGlobal(index: u32, type: u32, mutability: u32): void;
declare function onExport(index: u32, kind: u32, kindIndex: u32, nameOffset: u32, nameLength: u32): void;
declare function onStart(index: u32): void;
/** Starts parsing the module that has been placed in memory. */
function parse(): void {
var magic = readUint<u32>();
if (magic != 0x6D736100) unreachable();
var version = readUint<u32>();
if (version != 1) unreachable();
var end: usize = current_memory() << 16;
while (off < end) {
let section_off = off;
let id = readVaruint(7);
let payload_len = readVaruint(32);
let name_off = 0;
let name_len = 0;
if (!id) {
name_len = readVaruint(32);
if (!name_len) {
off = section_off;
break;
}
name_off = off;
off += name_len;
} else if (id > <u32>SectionId.Data) unreachable();
let payload_off = off;
if (onSection(
id,
payload_off,
payload_len,
name_off,
name_len
)) {
switch (id) {
case SectionId.Type: {
let count = readVaruint(32);
for (let index: u32 = 0; index < count; ++index) {
let form = readVarint(7) & 0x7f;
onType(index, form);
let paramCount = readVaruint(32);
for (let paramIndex: u32 = 0; paramIndex < paramCount; ++paramIndex) {
let paramType = readVarint(7) & 0x7f;
onTypeParam(index, paramIndex, paramType);
}
let returnCount = readVaruint(1); // MVP
for (let returnIndex: u32 = 0; returnIndex < returnCount; ++returnIndex) {
let returnType = readVarint(7) & 0x7f;
onTypeReturn(index, returnIndex, returnType);
}
}
break;
}
case SectionId.Import: {
let count = readVaruint(32);
for (let index: u32 = 0; index < count; ++index) {
let module_len = readVaruint(32);
let module_off = off;
off += module_off;
let field_len = readVaruint(32);
let field_off = off;
off += field_off;
let kind = readUint<u8>();
onImport(
index,
kind,
module_off,
module_len,
field_off,
field_len
);
switch (kind) {
case ExternalKind.Function: {
let type = readVaruint(32);
onFunctionImport(index, type);
break;
}
case ExternalKind.Table: {
let type = readVarint(7) & 0x7f;
let flags = readVaruint(1);
let initial = readVaruint(32);
let maximum: u32 = flags & 1 ? readVaruint(32) : MAX_TABLES;
onTableImport(index, type, initial, maximum, flags);
break;
}
case ExternalKind.Memory: {
let flags = readVaruint(1);
let initial = readVaruint(32);
let maximum: u32 = flags & 1 ? readVaruint(32) : MAX_PAGES;
onMemoryImport(index, initial, maximum, flags);
break;
}
case ExternalKind.Global: {
let type = readVarint(7) & 0x7f;
let mutability = readVaruint(1);
onGlobalImport(index, type, mutability);
break;
}
default: unreachable();
}
}
break;
}
case SectionId.Function: {
let count = readVaruint(32);
for (let index: u32 = 0; index < count; ++index) {
let typeIndex = readVaruint(32);
onFunction(index, typeIndex);
}
break;
}
case SectionId.Memory: {
let count = readVaruint(32);
for (let index: u32 = 0; index < count; ++index) {
let flags = readVaruint(1);
let initial = readVaruint(32);
let maximum: u32 = flags ? readVaruint(32) : MAX_PAGES;
onMemory(index, initial, maximum, flags);
}
break;
}
case SectionId.Global: {
let count = readVaruint(32);
for (let index: u32 = 0; index < count; ++index) {
let type = readVarint(7) & 0x7f;
let mutability = readVaruint(1);
let op = readUint<u8>();
switch (op) {
case Opcode.i32_const: {
readVarint(32);
break;
}
case Opcode.i64_const: {
readVarint64();
break;
}
case Opcode.f32_const: {
readUint<u32>();
break;
}
case Opcode.f64_const: {
readUint64();
break;
}
case Opcode.get_global: {
readVaruint(32);
break;
}
default: unreachable();
}
op = readUint<u8>();
if (op != Opcode.end) unreachable();
onGlobal(index, type, mutability);
}
break;
}
case SectionId.Export: {
let count = readVaruint(32);
for (let index: u32 = 0; index < count; ++index) {
let field_len = readVaruint(32);
let field_off = off;
off += field_len;
let kind = readUint<u8>();
let kind_index = readVaruint(32);
onExport(
index,
kind,
kind_index,
field_off,
field_len
);
}
break;
}
case SectionId.Start: {
let index = readVaruint(32);
onStart(
index
);
break;
}
case SectionId.Custom:
case SectionId.Code: { // TODO
off += payload_len;
break;
}
default: unreachable();
}
} else { // skip
off += payload_len;
}
}
}
// Start parsing immediately
parse();

View File

@ -0,0 +1,6 @@
{
"extends": "../../../std/assembly.json",
"include": [
"./**/*.ts"
]
}

2
lib/parse/build/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.wasm
*.wasm.map

1
lib/parse/index.d.ts vendored Normal file
View File

@ -0,0 +1 @@
export * from "./src";

2
lib/parse/index.js Normal file

File diff suppressed because one or more lines are too long

1
lib/parse/index.js.map Normal file

File diff suppressed because one or more lines are too long

6884
lib/parse/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

30
lib/parse/package.json Normal file
View File

@ -0,0 +1,30 @@
{
"name": "@assemblyscript/parse",
"version": "1.0.0",
"license": "Apache-2.0",
"main": "index.js",
"types": "index.d.ts",
"scripts": {
"build:as": "asc assembly/index.ts -O3 -b build/index.wasm --noMemory --importMemory --sourceMap --noDebug --validate",
"build": "npm run build:as && webpack --mode production --display-modules",
"test": "ts-node tests/"
},
"files": [
"package.json",
"index.d.ts",
"index.js",
"index.js.map",
"src/",
"README.md"
],
"dependencies": {},
"devDependencies": {
"@types/webassembly-js-api": "0.0.1",
"assemblyscript": "AssemblyScript/assemblyscript",
"ts-loader": "^4.1.0",
"ts-node": "^5.0.1",
"typescript": "^2.8.1",
"webpack": "^4.4.1",
"webpack-cli": "^2.0.13"
}
}

218
lib/parse/src/common.ts Normal file
View File

@ -0,0 +1,218 @@
/** Common constants shared between AssemblyScript and TypeScript. */
/** WebAssembly types. */
export enum Type {
i32 = 0x7f,
i64 = 0x7e,
f32 = 0x7d,
f64 = 0x7c,
anyfunc = 0x70,
func = 0x60,
none = 0x40
}
/** WebAssembly section ids. */
export enum SectionId {
Custom = 0,
Type = 1,
Import = 2,
Function = 3,
Table = 4,
Memory = 5,
Global = 6,
Export = 7,
Start = 8,
Element = 9,
Code = 10,
Data = 11
}
/** WebAssembly external kinds. */
export enum ExternalKind {
Function = 0,
Table = 1,
Memory = 2,
Global = 3
}
/** Maximum number of pages. */
export const MAX_PAGES = 0xffff;
/** Maximum number of tables. */
export const MAX_TABLES = 1; // MVP
/** WebAssembly opcodes. */
export enum Opcode { // just a few of these are actually used
// 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,
// current_memory = 0x3f,
// grow_memory = 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
}

151
lib/parse/src/index.ts Normal file
View File

@ -0,0 +1,151 @@
import { Type, SectionId, ExternalKind } from "./common";
export { Type, SectionId, ExternalKind };
/** Cached compiled parser. */
var compiled: WebAssembly.Module | null = null;
declare var WASM_DATA: string; // injected by webpack
if (typeof WASM_DATA !== "string") WASM_DATA = require("fs").readFileSync(__dirname + "/../build/index.wasm", "base64");
/** Options specified to the parser. The `onSection` callback determines the sections being evaluated in detail. */
export interface ParseOptions {
/** Called with each section in the binary. Returning `true` evaluates the section. */
onSection?(id: SectionId, payloadOff: number, payloadLen: number, nameOff: number, nameLen: number): boolean;
/** Called with each function type if the type section is evaluated. */
onType?(index: number, form: number): void;
/** Called with each function parameter if the type section is evaluated. */
onTypeParam?(index: number, paramIndex: number, paramType: Type): void;
/** Called with each function return type if the type section is evaluated. */
onTypeReturn?(index: number, returnIndex: number, returnType: Type): void;
/** Called with each import if the import section is evaluated. */
onImport?(index: number, kind: ExternalKind, moduleOff: number, moduleLen: number, fieldOff: number, fieldLen: number): void;
/** Called with each function import if the import section is evaluated. */
onFunctionImport?(index: number, type: number): void;
/** Called with each table import if the import section is evaluated. */
onTableImport?(index: number, type: Type, initial: number, maximum: number, flags: number): void;
/** Called with each memory import if the import section is evaluated. */
onMemoryImport?(index: number, initial: number, maximum: number, flags: number): void;
/** Called with each global import if the import section is evaluated. */
onGlobalImport?(index: number, type: Type, mutability: number): void;
/** Called with each memory if the memory section is evaluated.*/
onMemory?(index: number, initial: number, maximum: number, flags: number): void;
/** Called with each function if the function section is evaluated. */
onFunction?(index: number, typeIndex: number): void;
/** Called with each global if the global section is evaluated. */
onGlobal?(index: number, type: Type, mutability: number): void;
/** Called with the start function index if the start section is evaluated. */
onStart?(index: number): void;
/** Called with each export if the export section is evaluated. */
onExport?(index: number, kind: ExternalKind, kindIndex: number, nameOff: number, nameLen: number);
}
/** Parses the contents of a WebAssembly binary according to the specified options. */
export function parse(binary: Uint8Array, options?: ParseOptions): void {
if (!options) options = {};
// compile the parser if not yet compiled
if (!compiled) compiled = new WebAssembly.Module(base64_decode(WASM_DATA));
// use the binary as the parser's memory
var bytes = binary.length + 5; // leave space for u8 + u32 zero terminator
var pages = ((bytes + 0xffff) & ~0xffff) >> 16;
var memory = new WebAssembly.Memory({ initial: pages });
var buffer = new Uint8Array(memory.buffer);
buffer.set(binary);
// provide a way to read strings from memory
parse.readString = (offset: number, length: number): string => utf8_read(buffer, offset, offset + length);
// instantiate the parser and return its exports
function nop(): void {}
var imports = {
env: {
memory: memory
}
};
[
"onSection",
"onType",
"onTypeParam",
"onTypeReturn",
"onImport",
"onFunctionImport",
"onTableImport",
"onMemoryImport",
"onGlobalImport",
"onMemory",
"onFunction",
"onGlobal",
"onExport",
"onStart"
].forEach((name: string): void => imports.env[name] = options[name] || nop);
var instance = new WebAssembly.Instance(compiled, imports);
return instance.exports;
}
export declare namespace parse {
/** Utility function for reading an UTF8 encoded string from memory while parsing. */
function readString(offset: number, length: number): string;
}
// see: https://github.com/dcodeIO/protobuf.js/tree/master/lib/utf8
function utf8_read(buffer: Uint8Array, start: number, end: number): string {
var len = end - start;
if (len < 1) return "";
var parts: string[] | null = null,
chunk: number[] = [],
i = 0, // char offset
t = 0; // temporary
while (start < end) {
t = buffer[start++];
if (t < 128) {
chunk[i++] = t;
} else if (t > 191 && t < 224) {
chunk[i++] = (t & 31) << 6 | buffer[start++] & 63;
} else if (t > 239 && t < 365) {
t = ((t & 7) << 18 | (buffer[start++] & 63) << 12 | (buffer[start++] & 63) << 6 | buffer[start++] & 63) - 0x10000;
chunk[i++] = 0xD800 + (t >> 10);
chunk[i++] = 0xDC00 + (t & 1023);
} else {
chunk[i++] = (t & 15) << 12 | (buffer[start++] & 63) << 6 | buffer[start++] & 63;
}
if (i > 8191) {
(parts || (parts = [])).push(String.fromCharCode.apply(String, chunk));
i = 0;
}
}
if (parts) {
if (i) parts.push(String.fromCharCode.apply(String, chunk.slice(0, i)));
return parts.join("");
}
return String.fromCharCode.apply(String, chunk.slice(0, i));
}
// see: https://github.com/dcodeIO/protobuf.js/tree/master/lib/base64
function base64_decode(string: string): Uint8Array {
var length = string.length;
if (length) {
let n = 0,
p = length;
while (--p % 4 > 1 && string.charCodeAt(p) === 61) ++n;
length = Math.ceil(length * 3) / 4 - n;
}
var buffer = new Uint8Array(length);
var j = 0, o = 0, t = 0;
for (let i = 0, k = string.length; i < k;) {
let c = string.charCodeAt(i++);
if (c === 61 && j > 1) break;
if ((c = s64[c]) === undefined) throw Error();
switch (j) {
case 0: { t = c; j = 1; break; }
case 1: { buffer[o++] = t << 2 | (c & 48) >> 4; t = c; j = 2; break; }
case 2: { buffer[o++] = (t & 15) << 4 | (c & 60) >> 2; t = c; j = 3; break; }
case 3: { buffer[o++] = (t & 3) << 6 | c; j = 0; break; }
}
}
if (j === 1) throw Error();
return buffer;
}
var s64 = new Array(123);
for (let i = 0; i < 64;) s64[i < 26 ? i + 65 : i < 52 ? i + 71 : i < 62 ? i - 4 : i - 59 | 43] = i++;

View File

@ -0,0 +1,8 @@
{
"compilerOptions": {
"module": "commonjs"
},
"include": [
"./**/*.ts"
]
}

87
lib/parse/tests/index.ts Normal file
View File

@ -0,0 +1,87 @@
import * as fs from "fs";
import {
Type,
SectionId,
ExternalKind,
parse
} from "..";
const testBinary = fs.readFileSync(__dirname + "/libm.wasm");
function onSection(id: SectionId, offset: number, length: number, nameOffset: number, nameLength: number): boolean {
var name = id == 0 ? parse.readString(nameOffset, nameLength) : SectionId[id];
console.log(name + " section at " + offset + ".." + (offset + length));
return true;
}
function onType(index: number, form: Type): void {
console.log("- FunctionType[" + index + "] is " + Type[form]);
}
function onTypeParam(index: number, paramIndex: number, paramType: Type): void {
console.log(" > param[" + paramIndex + "] = " + Type[paramType]);
}
function onTypeReturn(index: number, returnIndex: number, returnType: Type): void {
console.log(" > return[" + returnIndex + "] = " + Type[returnType]);
}
function onImport(index: number, kind: ExternalKind, moduleOff: number, moduleLen: number, fieldOff: number, fieldLen: number): void {
var moduleName = parse.readString(moduleOff, moduleLen);
var fieldName = parse.readString(fieldOff, fieldLen);
console.log("- Import[" + index + "] is '" + moduleName + "." + fieldName + "'");
}
function onFunctionImport(index: number, type: number): void {
console.log(" > FunctionType[" + type + "]");
}
function onTableImport(index: number, type: Type, initial: number, maximum: number, flags: number): void {
console.log(" > " + Type[type] + ", initial=" + initial + ", maximum=" + maximum);
}
function onMemoryImport(index: number, initial: number, maximum: number, flags: number): void {
console.log(" > initial=" + initial + ", maximum=" + maximum);
}
function onGlobalImport(index: number, type: Type, mutability: number): void {
console.log(" > " + (mutability & 1 ? "mutable " : "const ") + Type[type]);
}
function onMemory(index: number, initial: number, maximum: number, flags: number): void {
console.log("- Memory[" + index + "]: initial=" + initial + ", maximum=" + maximum);
}
function onFunction(index: number, typeIndex: number): void {
console.log("- Function[" + index + "]: FunctionType[" + typeIndex + "]");
}
function onGlobal(index: number, type: Type, mutability: number): void {
console.log("- Global[" + index + "]: " + (mutability & 1 ? "mutable " : "const ") + Type[type]);
}
function onStart(index: number): void {
console.log("- Start: Function[" + index + "]");
}
function onExport(index: number, kind: ExternalKind, kindIndex: number, fieldOffset: number, fieldLength: number): void {
var field = parse.readString(fieldOffset, fieldLength);
console.log("- Export[" + index + "]: '" + field + "' -> " + ExternalKind[kind] + "[" + kindIndex + "]");
}
const result = parse(testBinary, {
onSection,
onType,
onTypeParam,
onTypeReturn,
onImport,
onFunctionImport,
onTableImport,
onMemoryImport,
onGlobalImport,
onMemory,
onFunction,
onGlobal,
onStart,
onExport
});

BIN
lib/parse/tests/libm.wasm Normal file

Binary file not shown.

View File

@ -0,0 +1,37 @@
const fs = require("fs");
const path = require("path");
const webpack = require("webpack");
const wasmData = fs.readFileSync(__dirname + "/build/index.wasm");
module.exports = {
entry: [ "./src/index.ts" ],
module: {
rules: [
{
test: /\.ts$/,
use: "ts-loader",
exclude: /node_modules/
}
]
},
resolve: {
extensions: [ ".ts", ".js" ]
},
node: {
fs: false
},
output: {
filename: "index.js",
path: __dirname,
library: "asparse",
libraryTarget: "umd",
globalObject: "typeof self !== 'undefined' ? self : this"
},
plugins: [
new webpack.DefinePlugin({
WASM_DATA: JSON.stringify(wasmData.toString("base64"))
})
],
devtool: "source-map"
};

View File

@ -49,7 +49,8 @@ import {
ConstantValueKind,
PATH_DELIMITER,
LIBRARY_PREFIX
LIBRARY_PREFIX,
Flow
} from "./program";
import {
@ -200,6 +201,8 @@ export class Compiler extends DiagnosticEmitter {
module: Module;
/** Current function in compilation. */
currentFunction: Function;
/** Outer function in compilation, if compiling a function expression. */
outerFunction: Function | null = null;
/** Current enum in compilation. */
currentEnum: Enum | null = null;
/** Current type in compilation. */
@ -482,43 +485,47 @@ export class Compiler extends DiagnosticEmitter {
var initExpr: ExpressionRef = 0;
if (global.type == Type.void) { // type is void if not yet resolved or not annotated
if (declaration) {
// resolve now if annotated
if (declaration.type) {
let resolvedType = this.program.resolveType(declaration.type); // reports
if (!resolvedType) return false;
if (resolvedType == Type.void) {
// resolve now if annotated
if (declaration.type) {
let resolvedType = this.program.resolveType(declaration.type); // reports
if (!resolvedType) return false;
if (resolvedType == Type.void) {
this.error(
DiagnosticCode.Type_expected,
declaration.type.range
);
return false;
}
global.type = resolvedType;
// infer from initializer if not annotated
} else if (declaration.initializer) { // infer type using void/NONE for literal inference
initExpr = this.compileExpression( // reports
declaration.initializer,
Type.void,
ConversionKind.NONE
);
if (this.currentType == Type.void) {
this.error(
DiagnosticCode.Type_0_is_not_assignable_to_type_1,
declaration.initializer.range, this.currentType.toString(), "<auto>"
);
return false;
}
global.type = this.currentType;
// must either be annotated or have an initializer
} else {
this.error(
DiagnosticCode.Type_expected,
declaration.type.range
declaration.name.range.atEnd
);
return false;
}
global.type = resolvedType;
// infer from initializer if not annotated
} else if (declaration.initializer) { // infer type using void/NONE for literal inference
initExpr = this.compileExpression( // reports
declaration.initializer,
Type.void,
ConversionKind.NONE
);
if (this.currentType == Type.void) {
this.error(
DiagnosticCode.Type_0_is_not_assignable_to_type_1,
declaration.initializer.range, this.currentType.toString(), "<auto>"
);
return false;
}
global.type = this.currentType;
// must either be annotated or have an initializer
} else {
this.error(
DiagnosticCode.Type_expected,
declaration.name.range.atEnd
);
return false;
assert(false); // must have a declaration if 'void' (and thus resolved later on)
}
}
@ -546,7 +553,7 @@ export class Compiler extends DiagnosticEmitter {
} else {
this.error(
DiagnosticCode.Operation_not_supported,
declaration.range
assert(declaration).range
);
}
return false;
@ -563,7 +570,7 @@ export class Compiler extends DiagnosticEmitter {
} else {
// evaluate initializer if present
if (declaration.initializer) {
if (declaration && declaration.initializer) {
if (!initExpr) {
initExpr = this.compileExpression(declaration.initializer, global.type);
}
@ -630,7 +637,7 @@ export class Compiler extends DiagnosticEmitter {
assert(false);
this.error(
DiagnosticCode.Operation_not_supported,
global.declaration.range
assert(global.declaration).range
);
global.constantValueKind = ConstantValueKind.INTEGER;
global.constantIntegerValue = i64_new(0);
@ -638,11 +645,15 @@ export class Compiler extends DiagnosticEmitter {
}
}
global.set(CommonFlags.INLINED); // inline the value from now on
if (declaration.isTopLevel) { // but keep the element as it might be re-exported
module.addGlobal(internalName, nativeType, false, initExpr);
}
if (declaration.range.source.isEntry && declaration.isTopLevelExport) {
module.addGlobalExport(global.internalName, declaration.programLevelInternalName);
if (declaration) {
if (declaration.isTopLevel) { // but keep the element as it might be re-exported
module.addGlobal(internalName, nativeType, false, initExpr);
}
if (declaration.range.source.isEntry && declaration.isTopLevelExport) {
module.addGlobalExport(global.internalName, declaration.programLevelInternalName);
}
} else {
assert(false); // must have a declaration if constant
}
} else /* mutable */ {
@ -763,7 +774,7 @@ export class Compiler extends DiagnosticEmitter {
// functions
/** Compiles a function given its declaration. */
/** Compiles a top-level function given its declaration. */
compileFunctionDeclaration(
declaration: FunctionDeclaration,
typeArguments: TypeNode[],
@ -775,6 +786,7 @@ export class Compiler extends DiagnosticEmitter {
<FunctionPrototype>element,
typeArguments,
contextualTypeArguments,
null, // no outer scope (is top level)
(<FunctionPrototype>element).declaration.name
);
}
@ -784,6 +796,7 @@ export class Compiler extends DiagnosticEmitter {
prototype: FunctionPrototype,
typeArguments: TypeNode[],
contextualTypeArguments: Map<string,Type> | null,
outerScope: Flow | null,
reportNode: Node
): Function | null {
var instance = prototype.resolveUsingTypeArguments( // reports
@ -791,7 +804,9 @@ export class Compiler extends DiagnosticEmitter {
contextualTypeArguments,
reportNode
);
if (!(instance && this.compileFunction(instance))) return null;
if (!instance) return null;
instance.outerScope = outerScope;
if (!this.compileFunction(instance)) return null;
return instance;
}
@ -1032,7 +1047,8 @@ export class Compiler extends DiagnosticEmitter {
this.compileFunctionUsingTypeArguments(
<FunctionPrototype>element,
[],
null,
null, // no contextual type arguments
null, // no outer scope
(<FunctionPrototype>element).declaration.name
);
}
@ -1084,7 +1100,8 @@ export class Compiler extends DiagnosticEmitter {
let functionInstance = this.compileFunctionUsingTypeArguments(
<FunctionPrototype>element,
[],
null,
null, // no contextual type arguments
null, // no outer scope
(<FunctionPrototype>element).declaration.name
);
if (functionInstance) {
@ -1810,9 +1827,9 @@ export class Compiler extends DiagnosticEmitter {
}
if (!isInlined) {
if (declaration.isAny(CommonFlags.LET | CommonFlags.CONST)) { // here: not top-level
currentFunction.flow.addScopedLocal(name, type, declaration.name); // reports
currentFunction.flow.addScopedLocal(type, name, declaration); // reports
} else {
currentFunction.addLocal(type, name); // reports
currentFunction.addLocal(type, name, declaration); // reports
}
if (init) {
initializers.push(this.compileAssignmentWithValue(declaration.name, init));
@ -1965,10 +1982,6 @@ export class Compiler extends DiagnosticEmitter {
}
default: {
assert(false);
this.error(
DiagnosticCode.Operation_not_supported,
element.declaration.range
);
return this.module.createUnreachable();
}
}
@ -4805,6 +4818,7 @@ export class Compiler extends DiagnosticEmitter {
prototype,
[],
currentFunction.contextualTypeArguments,
currentFunction.flow,
declaration
);
if (!instance) return this.module.createUnreachable();
@ -5514,7 +5528,7 @@ export class Compiler extends DiagnosticEmitter {
var currentFunction = this.currentFunction;
// make a getter for the expression (also obtains the type)
var getValue = this.compileExpression(
var getValue = this.compileExpression( // reports
expression.operand,
contextualType == Type.void
? Type.i32
@ -5522,6 +5536,10 @@ export class Compiler extends DiagnosticEmitter {
ConversionKind.NONE,
false // wrapped below
);
if (_BinaryenExpressionGetId(getValue) == ExpressionId.Unreachable) {
// shortcut if compiling the getter already failed
return getValue;
}
var currentType = this.currentType;
var op: BinaryOp;

View File

@ -63,7 +63,8 @@ import {
VariableStatement,
ParameterKind,
SignatureNode
SignatureNode,
VariableDeclaration
} from "./ast";
import {
@ -420,7 +421,7 @@ export class Program extends DiagnosticEmitter {
if (implementsTypes) {
let numImplementsTypes = implementsTypes.length;
if (prototype.is(CommonFlags.UNMANAGED)) {
if (implementsTypes && numImplementsTypes) {
if (numImplementsTypes) {
this.error(
DiagnosticCode.Structs_cannot_implement_interfaces,
Range.join(
@ -544,8 +545,8 @@ export class Program extends DiagnosticEmitter {
this,
name,
internalName,
declaration,
Type.void
Type.void, // resolved later on
declaration
);
classPrototype.members.set(name, staticField);
this.elementsLookup.set(internalName, staticField);
@ -1454,8 +1455,8 @@ export class Program extends DiagnosticEmitter {
this,
simpleName,
internalName,
declaration,
Type.void // resolved later on
Type.void, // resolved later on
declaration
);
global.namespace = namespace;
this.elementsLookup.set(internalName, global);
@ -1714,6 +1715,19 @@ export class Program extends DiagnosticEmitter {
return resolvedElement.set(element);
}
// check outer scope locals
// let outerScope = contextualFunction.outerScope;
// while (outerScope) {
// if (element = outerScope.getScopedLocal(name)) {
// let scopedLocal = <Local>element;
// let scopedGlobal = scopedLocal.scopedGlobal;
// if (!scopedGlobal) scopedGlobal = outerScope.addScopedGlobal(scopedLocal);
// if (!resolvedElement) resolvedElement = new ResolvedElement();
// return resolvedElement.set(scopedGlobal);
// }
// outerScope = outerScope.currentFunction.outerScope;
// }
// search contextual parent namespaces if applicable
if (namespace = contextualFunction.prototype.namespace) {
do {
@ -2241,7 +2255,7 @@ export class VariableLikeElement extends Element {
// kind varies
/** Declaration reference. */
declaration: VariableLikeDeclarationStatement;
declaration: VariableLikeDeclarationStatement | null;
/** Variable type. Is {@link Type.void} for type-inferred {@link Global}s before compilation. */
type: Type;
/** Constant value kind. */
@ -2251,6 +2265,18 @@ export class VariableLikeElement extends Element {
/** Constant float value, if applicable. */
constantFloatValue: f64;
protected constructor(
program: Program,
simpleName: string,
internalName: string,
type: Type,
declaration: VariableLikeDeclarationStatement | null
) {
super(program, simpleName, internalName);
this.type = type;
this.declaration = declaration;
}
withConstantIntegerValue(lo: i32, hi: i32): this {
this.constantValueKind = ConstantValueKind.INTEGER;
this.constantIntegerValue = i64_new(lo, hi);
@ -2275,12 +2301,11 @@ export class Global extends VariableLikeElement {
program: Program,
simpleName: string,
internalName: string,
declaration: VariableLikeDeclarationStatement,
type: Type
type: Type,
declaration: VariableLikeDeclarationStatement | null
) {
super(program, simpleName, internalName);
this.declaration = declaration;
this.flags = declaration.flags;
super(program, simpleName, internalName, type, declaration);
this.flags = declaration ? declaration.flags : CommonFlags.NONE;
this.type = type; // resolved later if `void`
}
}
@ -2312,11 +2337,18 @@ export class Local extends VariableLikeElement {
/** Local index. */
index: i32;
/** Respective scoped global, if any. */
scopedGlobal: Global | null = null;
constructor(program: Program, simpleName: string, index: i32, type: Type) {
super(program, simpleName, simpleName);
constructor(
program: Program,
simpleName: string,
index: i32,
type: Type,
declaration: VariableLikeDeclarationStatement | null = null
) {
super(program, simpleName, simpleName, type, declaration);
this.index = index;
this.type = type;
}
}
@ -2552,6 +2584,8 @@ export class Function extends Element {
functionTableIndex: i32 = -1;
/** Trampoline function for calling with omitted arguments. */
trampoline: Function | null = null;
/** The outer scope, if a function expression. */
outerScope: Flow | null = null;
private nextBreakId: i32 = 0;
private breakStack: i32[] | null = null;
@ -2604,6 +2638,7 @@ export class Function extends Element {
parameterName,
localIndex++,
parameterType
// FIXME: declaration?
)
);
}
@ -2612,7 +2647,7 @@ export class Function extends Element {
}
/** Adds a local of the specified type, with an optional name. */
addLocal(type: Type, name: string | null = null): Local {
addLocal(type: Type, name: string | null = null, declaration: VariableDeclaration | null = null): Local {
// if it has a name, check previously as this method will throw otherwise
var localIndex = this.signature.parameterTypes.length + this.additionalLocals.length;
if (this.is(CommonFlags.INSTANCE)) ++localIndex;
@ -2622,7 +2657,8 @@ export class Function extends Element {
? name
: "var$" + localIndex.toString(10),
localIndex,
type
type,
declaration
);
if (name) {
if (this.locals.has(name)) throw new Error("duplicate local name");
@ -2833,8 +2869,13 @@ export class Field extends VariableLikeElement {
memoryOffset: i32 = -1;
/** Constructs a new field. */
constructor(prototype: FieldPrototype, internalName: string, type: Type) {
super(prototype.program, prototype.simpleName, internalName);
constructor(
prototype: FieldPrototype,
internalName: string,
type: Type,
declaration: FieldDeclaration
) {
super(prototype.program, prototype.simpleName, internalName, type, declaration);
this.prototype = prototype;
this.flags = prototype.flags;
this.type = type;
@ -3020,7 +3061,8 @@ export class ClassPrototype extends Element {
let fieldInstance = new Field(
<FieldPrototype>member,
internalName + INSTANCE_DELIMITER + (<FieldPrototype>member).simpleName,
fieldType
fieldType,
fieldDeclaration
);
switch (fieldType.byteSize) { // align
case 1: break;
@ -3281,6 +3323,8 @@ export class Flow {
breakLabel: string | null;
/** Scoped local variables. */
scopedLocals: Map<string,Local> | null = null;
/** Scoped global variables. */
// scopedGlobals: Map<Local,Global> | null = null;
/** Creates the parent flow of the specified function. */
static create(currentFunction: Function): Flow {
@ -3346,13 +3390,13 @@ export class Flow {
}
/** Adds a new scoped local of the specified name. */
addScopedLocal(name: string, type: Type, reportNode: Node): void {
addScopedLocal(type: Type, name: string, declaration: VariableDeclaration): void {
var scopedLocal = this.currentFunction.getTempLocal(type);
if (!this.scopedLocals) this.scopedLocals = new Map();
else if (this.scopedLocals.has(name)) {
this.currentFunction.program.error(
DiagnosticCode.Duplicate_identifier_0,
reportNode.range
declaration.name.range
);
return;
}
@ -3371,6 +3415,27 @@ export class Flow {
return this.currentFunction.locals.get(name);
}
/** Adds a scoped global for an outer scoped local. */
// addScopedGlobal(scopedLocal: Local): Global {
// var scopedGlobals = this.scopedGlobals;
// var scopedGlobal: Global | null;
// if (!scopedGlobals) {
// this.scopedGlobals = scopedGlobals = new Map();
// } else {
// scopedGlobal = scopedGlobals.get(scopedLocal);
// if (scopedGlobal) return scopedGlobal;
// }
// scopedGlobal = new Global(
// scopedLocal.program,
// scopedLocal.simpleName,
// this.currentFunction.internalName + "~" + scopedLocal.internalName,
// scopedLocal.type,
// assert(scopedLocal.declaration)
// );
// scopedGlobals.set(scopedLocal, scopedGlobal);
// return scopedGlobal;
// }
/** Finalizes this flow. Must be the topmost parent flow of the function. */
finalize(): void {
assert(this.parent == null, "must be the topmost parent flow");

View File

@ -7,28 +7,31 @@
* @module std/assembly/allocator/arena
*//***/
import { MASK as AL_MASK } from "./common/alignment";
import { AL_MASK } from "./common";
var startOffset: usize = (HEAP_BASE + AL_MASK) & ~AL_MASK;
var offset: usize = startOffset;
@global
export function allocate_memory(size: usize): usize {
if (!size) return 0;
var ptr = offset;
var newPtr = (ptr + size + AL_MASK) & ~AL_MASK;
var pagesBefore = current_memory();
if (newPtr > <usize>pagesBefore << 16) {
let pagesNeeded = ((newPtr - ptr + 0xffff) & ~0xffff) >>> 16;
let pagesWanted = max(pagesBefore, pagesNeeded); // double memory
if (grow_memory(pagesWanted) < 0) {
if (grow_memory(pagesNeeded) < 0) {
unreachable(); // out of memory
const MAX_SIZE: usize = 1 << 30;
if (size && size < MAX_SIZE) {
let ptr = offset;
let newPtr = (ptr + size + AL_MASK) & ~AL_MASK;
let pagesBefore = current_memory();
if (newPtr > <usize>pagesBefore << 16) {
let pagesNeeded = ((newPtr - ptr + 0xffff) & ~0xffff) >>> 16;
let pagesWanted = max(pagesBefore, pagesNeeded); // double memory
if (grow_memory(pagesWanted) < 0) {
if (grow_memory(pagesNeeded) < 0) {
unreachable(); // out of memory
}
}
}
offset = newPtr;
return ptr;
}
offset = newPtr;
return ptr;
return 0;
}
@global

View File

@ -347,7 +347,7 @@ export function allocate_memory(request: usize): usize {
* a hard-coded limit on the maximum allocation size because of the way this
* allocator works.
*/
if (request + HEADER_SIZE > MAX_ALLOC) {
if (request > MAX_ALLOC - HEADER_SIZE) {
return 0;
}

View File

@ -1,13 +0,0 @@
/**
* Shared alignment constants.
* @module std/assembly/allocator/common/alignment
*//***/
/** Number of alignment bits. */
export const BITS: u32 = 3;
/** Number of possible alignment values. */
export const SIZE: usize = 1 << <usize>BITS;
/** Mask to obtain just the alignment bits. */
export const MASK: usize = SIZE - 1;

View File

@ -0,0 +1,16 @@
/**
* Shared allocator constants.
* @module std/assembly/allocator/common
*//***/
/** Number of alignment bits. */
export const AL_BITS: u32 = 3;
/** Number of possible alignment values. */
export const AL_SIZE: usize = 1 << <usize>AL_BITS;
/** Mask to obtain just the alignment bits. */
export const AL_MASK: usize = AL_SIZE - 1;
/** Maximum 32-bit allocation size. */
export const MAX_SIZE_32: usize = 1 << 30; // 1GB

View File

@ -16,10 +16,11 @@
// FL: first level, SL: second level, AL: alignment, SB: small block
import {
BITS as AL_BITS,
SIZE as AL_SIZE,
MASK as AL_MASK
} from "./common/alignment";
AL_BITS,
AL_SIZE,
AL_MASK,
MAX_SIZE_32
} from "./common";
const SL_BITS: u32 = 5;
const SL_SIZE: usize = 1 << <usize>SL_BITS;
@ -32,6 +33,8 @@ const FL_BITS: u32 = (sizeof<usize>() == sizeof<u32>()
: 32 // ^= up to 4GB per block
) - SB_BITS;
// assert(1 << (FL_BITS + SB_BITS) == MAX_SIZE_32);
// ╒════════════════ Block structure layout (32-bit) ══════════════╕
// 3 2 1
// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 bits
@ -457,7 +460,8 @@ export function allocate_memory(size: usize): usize {
// search for a suitable block
var data: usize = 0;
if (size && size < Block.MAX_SIZE) {
if (size && size <= Block.MAX_SIZE) {
// 32-bit MAX_SIZE is 1 << 30 and itself aligned, hence the following can't overflow MAX_SIZE
size = max<usize>((size + AL_MASK) & ~AL_MASK, Block.MIN_SIZE);
let block = root.search(size);

View File

@ -2,161 +2,170 @@
(type $ii (func (param i32) (result i32)))
(type $iv (func (param i32)))
(type $v (func))
(global "$(lib)/allocator/arena/startOffset" (mut i32) (i32.const 0))
(global "$(lib)/allocator/arena/offset" (mut i32) (i32.const 0))
(global $~lib/allocator/arena/startOffset (mut i32) (i32.const 0))
(global $~lib/allocator/arena/offset (mut i32) (i32.const 0))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "allocate_memory" (func "$(lib)/allocator/arena/allocate_memory"))
(export "free_memory" (func "$(lib)/allocator/arena/free_memory"))
(export "reset_memory" (func "$(lib)/allocator/arena/reset_memory"))
(export "allocate_memory" (func $~lib/allocator/arena/allocate_memory))
(export "free_memory" (func $~lib/allocator/arena/free_memory))
(export "reset_memory" (func $~lib/allocator/arena/reset_memory))
(export "memory" (memory $0))
(start $start)
(func "$(lib)/allocator/arena/allocate_memory" (; 0 ;) (type $ii) (param $0 i32) (result i32)
(func $~lib/allocator/arena/allocate_memory (; 0 ;) (type $ii) (param $0 i32) (result i32)
(local $1 i32)
(local $2 i32)
(local $3 i32)
(local $4 i32)
;;@ (lib)/allocator/arena.ts:17:2
;;@ ~lib/allocator/arena.ts:18:2
(if
;;@ (lib)/allocator/arena.ts:17:6
(i32.eqz
;;@ (lib)/allocator/arena.ts:17:7
(select
;;@ ~lib/allocator/arena.ts:18:14
(i32.lt_u
(get_local $0)
;;@ ~lib/allocator/arena.ts:18:21
(i32.const 1073741824)
)
(get_local $0)
;;@ ~lib/allocator/arena.ts:18:6
(get_local $0)
)
;;@ (lib)/allocator/arena.ts:17:20
(return
(i32.const 0)
)
)
;;@ (lib)/allocator/arena.ts:21:2
(if
;;@ (lib)/allocator/arena.ts:21:6
(i32.gt_u
;;@ (lib)/allocator/arena.ts:19:2
(tee_local $2
;;@ (lib)/allocator/arena.ts:19:15
(i32.and
(i32.add
;;@ (lib)/allocator/arena.ts:19:16
(i32.add
;;@ (lib)/allocator/arena.ts:18:2
(tee_local $1
;;@ (lib)/allocator/arena.ts:18:12
(get_global "$(lib)/allocator/arena/offset")
)
;;@ (lib)/allocator/arena.ts:19:22
(get_local $0)
)
;;@ (lib)/allocator/arena.ts:19:29
(i32.const 7)
)
(i32.const -8)
)
)
;;@ (lib)/allocator/arena.ts:21:15
(i32.shl
;;@ (lib)/allocator/arena.ts:20:2
(tee_local $0
;;@ (lib)/allocator/arena.ts:20:20
(current_memory)
)
;;@ (lib)/allocator/arena.ts:21:37
(i32.const 16)
)
)
;;@ (lib)/allocator/arena.ts:24:4
(if
;;@ (lib)/allocator/arena.ts:24:8
(i32.lt_s
(grow_memory
;;@ (lib)/allocator/arena.ts:23:22
(select
;;@ (lib)/allocator/arena.ts:23:26
(get_local $0)
(tee_local $4
;;@ (lib)/allocator/arena.ts:22:4
(tee_local $3
;;@ (lib)/allocator/arena.ts:22:22
(i32.shr_u
(i32.and
;;@ (lib)/allocator/arena.ts:22:23
(i32.add
;;@ (lib)/allocator/arena.ts:22:24
(i32.sub
(get_local $2)
;;@ (lib)/allocator/arena.ts:22:33
(get_local $1)
)
;;@ (lib)/allocator/arena.ts:22:39
(i32.const 65535)
)
(i32.const -65536)
;;@ ~lib/allocator/arena.ts:18:31
(block
;;@ ~lib/allocator/arena.ts:22:4
(if
;;@ ~lib/allocator/arena.ts:22:8
(i32.gt_u
;;@ ~lib/allocator/arena.ts:20:4
(tee_local $2
;;@ ~lib/allocator/arena.ts:20:17
(i32.and
(i32.add
;;@ ~lib/allocator/arena.ts:20:18
(i32.add
;;@ ~lib/allocator/arena.ts:19:4
(tee_local $1
;;@ ~lib/allocator/arena.ts:19:14
(get_global $~lib/allocator/arena/offset)
)
;;@ (lib)/allocator/arena.ts:22:62
(i32.const 16)
;;@ ~lib/allocator/arena.ts:20:24
(get_local $0)
)
;;@ ~lib/allocator/arena.ts:20:31
(i32.const 7)
)
(i32.const -8)
)
)
;;@ ~lib/allocator/arena.ts:22:17
(i32.shl
;;@ ~lib/allocator/arena.ts:21:4
(tee_local $0
;;@ ~lib/allocator/arena.ts:21:22
(current_memory)
)
;;@ ~lib/allocator/arena.ts:22:39
(i32.const 16)
)
)
;;@ ~lib/allocator/arena.ts:25:6
(if
;;@ ~lib/allocator/arena.ts:25:10
(i32.lt_s
(grow_memory
;;@ ~lib/allocator/arena.ts:24:24
(select
;;@ ~lib/allocator/arena.ts:24:28
(get_local $0)
(tee_local $4
;;@ ~lib/allocator/arena.ts:23:6
(tee_local $3
;;@ ~lib/allocator/arena.ts:23:24
(i32.shr_u
(i32.and
;;@ ~lib/allocator/arena.ts:23:25
(i32.add
;;@ ~lib/allocator/arena.ts:23:26
(i32.sub
(get_local $2)
;;@ ~lib/allocator/arena.ts:23:35
(get_local $1)
)
;;@ ~lib/allocator/arena.ts:23:41
(i32.const 65535)
)
(i32.const -65536)
)
;;@ ~lib/allocator/arena.ts:23:64
(i32.const 16)
)
)
)
(i32.gt_s
(get_local $0)
(get_local $4)
)
)
)
(i32.gt_s
(get_local $0)
(get_local $4)
;;@ ~lib/allocator/arena.ts:25:37
(i32.const 0)
)
;;@ ~lib/allocator/arena.ts:26:8
(if
;;@ ~lib/allocator/arena.ts:26:12
(i32.lt_s
(grow_memory
;;@ ~lib/allocator/arena.ts:26:24
(get_local $3)
)
;;@ ~lib/allocator/arena.ts:26:39
(i32.const 0)
)
;;@ ~lib/allocator/arena.ts:27:10
(unreachable)
)
)
;;@ (lib)/allocator/arena.ts:24:35
(i32.const 0)
)
;;@ (lib)/allocator/arena.ts:25:6
(if
;;@ (lib)/allocator/arena.ts:25:10
(i32.lt_s
(grow_memory
;;@ (lib)/allocator/arena.ts:25:22
(get_local $3)
)
;;@ (lib)/allocator/arena.ts:25:37
(i32.const 0)
)
;;@ (lib)/allocator/arena.ts:26:8
(unreachable)
;;@ ~lib/allocator/arena.ts:31:4
(set_global $~lib/allocator/arena/offset
;;@ ~lib/allocator/arena.ts:31:13
(get_local $2)
)
;;@ ~lib/allocator/arena.ts:32:11
(return
(get_local $1)
)
)
)
;;@ (lib)/allocator/arena.ts:30:2
(set_global "$(lib)/allocator/arena/offset"
;;@ (lib)/allocator/arena.ts:30:11
(get_local $2)
)
;;@ (lib)/allocator/arena.ts:31:9
(get_local $1)
;;@ ~lib/allocator/arena.ts:34:9
(i32.const 0)
)
(func "$(lib)/allocator/arena/free_memory" (; 1 ;) (type $iv) (param $0 i32)
;;@ (lib)/allocator/arena.ts:35:46
(func $~lib/allocator/arena/free_memory (; 1 ;) (type $iv) (param $0 i32)
;;@ ~lib/allocator/arena.ts:38:46
(nop)
)
(func "$(lib)/allocator/arena/reset_memory" (; 2 ;) (type $v)
;;@ (lib)/allocator/arena.ts:41:2
(set_global "$(lib)/allocator/arena/offset"
;;@ (lib)/allocator/arena.ts:41:11
(get_global "$(lib)/allocator/arena/startOffset")
(func $~lib/allocator/arena/reset_memory (; 2 ;) (type $v)
;;@ ~lib/allocator/arena.ts:44:2
(set_global $~lib/allocator/arena/offset
;;@ ~lib/allocator/arena.ts:44:11
(get_global $~lib/allocator/arena/startOffset)
)
)
(func $start (; 3 ;) (type $v)
(set_global "$(lib)/allocator/arena/startOffset"
;;@ (lib)/allocator/arena.ts:12:25
(set_global $~lib/allocator/arena/startOffset
;;@ ~lib/allocator/arena.ts:12:25
(i32.and
(i32.add
;;@ (lib)/allocator/arena.ts:12:26
;;@ ~lib/allocator/arena.ts:12:26
(get_global $HEAP_BASE)
;;@ (lib)/allocator/arena.ts:12:38
;;@ ~lib/allocator/arena.ts:12:38
(i32.const 7)
)
(i32.const -8)
)
)
(set_global "$(lib)/allocator/arena/offset"
;;@ (lib)/allocator/arena.ts:13:20
(get_global "$(lib)/allocator/arena/startOffset")
(set_global $~lib/allocator/arena/offset
;;@ ~lib/allocator/arena.ts:13:20
(get_global $~lib/allocator/arena/startOffset)
)
)
)

View File

@ -3,196 +3,208 @@
(type $ii (func (param i32) (result i32)))
(type $iv (func (param i32)))
(type $v (func))
(global "$(lib)/allocator/common/alignment/BITS" i32 (i32.const 3))
(global "$(lib)/allocator/common/alignment/SIZE" i32 (i32.const 8))
(global "$(lib)/allocator/common/alignment/MASK" i32 (i32.const 7))
(global "$(lib)/allocator/arena/startOffset" (mut i32) (i32.const 0))
(global "$(lib)/allocator/arena/offset" (mut i32) (i32.const 0))
(global $~lib/allocator/common/index/AL_BITS i32 (i32.const 3))
(global $~lib/allocator/common/index/AL_SIZE i32 (i32.const 8))
(global $~lib/allocator/common/index/AL_MASK i32 (i32.const 7))
(global $~lib/allocator/common/index/MAX_SIZE_32 i32 (i32.const 1073741824))
(global $~lib/allocator/arena/startOffset (mut i32) (i32.const 0))
(global $~lib/allocator/arena/offset (mut i32) (i32.const 0))
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "allocate_memory" (func "$(lib)/allocator/arena/allocate_memory"))
(export "free_memory" (func "$(lib)/allocator/arena/free_memory"))
(export "reset_memory" (func "$(lib)/allocator/arena/reset_memory"))
(export "allocate_memory" (func $~lib/allocator/arena/allocate_memory))
(export "free_memory" (func $~lib/allocator/arena/free_memory))
(export "reset_memory" (func $~lib/allocator/arena/reset_memory))
(export "memory" (memory $0))
(start $start)
(func "$(lib)/allocator/arena/allocate_memory" (; 0 ;) (type $ii) (param $0 i32) (result i32)
(func $~lib/allocator/arena/allocate_memory (; 0 ;) (type $ii) (param $0 i32) (result i32)
(local $1 i32)
(local $2 i32)
(local $3 i32)
(local $4 i32)
(local $5 i32)
(local $6 i32)
;;@ (lib)/allocator/arena.ts:17:2
;;@ ~lib/allocator/arena.ts:17:2
(nop)
;;@ ~lib/allocator/arena.ts:18:2
(if
;;@ (lib)/allocator/arena.ts:17:6
(i32.eqz
;;@ (lib)/allocator/arena.ts:17:7
;;@ ~lib/allocator/arena.ts:18:6
(if (result i32)
(get_local $0)
;;@ ~lib/allocator/arena.ts:18:14
(i32.lt_u
(get_local $0)
;;@ ~lib/allocator/arena.ts:18:21
(i32.const 1073741824)
)
(get_local $0)
)
;;@ (lib)/allocator/arena.ts:17:20
(return
(i32.const 0)
)
)
;;@ (lib)/allocator/arena.ts:18:2
(set_local $1
;;@ (lib)/allocator/arena.ts:18:12
(get_global "$(lib)/allocator/arena/offset")
)
;;@ (lib)/allocator/arena.ts:19:2
(set_local $2
;;@ (lib)/allocator/arena.ts:19:15
(i32.and
(i32.add
;;@ (lib)/allocator/arena.ts:19:16
(i32.add
(get_local $1)
;;@ (lib)/allocator/arena.ts:19:22
(get_local $0)
)
;;@ (lib)/allocator/arena.ts:19:29
(i32.const 7)
)
;;@ (lib)/allocator/arena.ts:19:40
(i32.xor
;;@ (lib)/allocator/arena.ts:19:41
(i32.const 7)
(i32.const -1)
)
)
)
;;@ (lib)/allocator/arena.ts:20:2
(set_local $3
;;@ (lib)/allocator/arena.ts:20:20
(current_memory)
)
;;@ (lib)/allocator/arena.ts:21:2
(if
;;@ (lib)/allocator/arena.ts:21:6
(i32.gt_u
(get_local $2)
;;@ (lib)/allocator/arena.ts:21:15
(i32.shl
(get_local $3)
;;@ (lib)/allocator/arena.ts:21:37
(i32.const 16)
)
)
;;@ (lib)/allocator/arena.ts:21:41
;;@ ~lib/allocator/arena.ts:18:31
(block
;;@ (lib)/allocator/arena.ts:22:4
(set_local $4
;;@ (lib)/allocator/arena.ts:22:22
(i32.shr_u
(i32.and
;;@ (lib)/allocator/arena.ts:22:23
;;@ ~lib/allocator/arena.ts:19:4
(set_local $1
;;@ ~lib/allocator/arena.ts:19:14
(get_global $~lib/allocator/arena/offset)
)
;;@ ~lib/allocator/arena.ts:20:4
(set_local $2
;;@ ~lib/allocator/arena.ts:20:17
(i32.and
(i32.add
;;@ ~lib/allocator/arena.ts:20:18
(i32.add
;;@ (lib)/allocator/arena.ts:22:24
(i32.sub
(get_local $2)
;;@ (lib)/allocator/arena.ts:22:33
(get_local $1)
)
;;@ (lib)/allocator/arena.ts:22:39
(i32.const 65535)
)
;;@ (lib)/allocator/arena.ts:22:49
(i32.xor
;;@ (lib)/allocator/arena.ts:22:50
(i32.const 65535)
(i32.const -1)
(get_local $1)
;;@ ~lib/allocator/arena.ts:20:24
(get_local $0)
)
;;@ ~lib/allocator/arena.ts:20:31
(i32.const 7)
)
;;@ (lib)/allocator/arena.ts:22:62
(i32.const 16)
)
)
;;@ (lib)/allocator/arena.ts:23:4
(set_local $5
;;@ (lib)/allocator/arena.ts:23:22
(select
(tee_local $5
;;@ (lib)/allocator/arena.ts:23:26
(get_local $3)
)
(tee_local $6
;;@ (lib)/allocator/arena.ts:23:39
(get_local $4)
)
(i32.gt_s
(get_local $5)
(get_local $6)
;;@ ~lib/allocator/arena.ts:20:42
(i32.xor
;;@ ~lib/allocator/arena.ts:20:43
(i32.const 7)
(i32.const -1)
)
)
)
;;@ (lib)/allocator/arena.ts:24:4
;;@ ~lib/allocator/arena.ts:21:4
(set_local $3
;;@ ~lib/allocator/arena.ts:21:22
(current_memory)
)
;;@ ~lib/allocator/arena.ts:22:4
(if
;;@ (lib)/allocator/arena.ts:24:8
(i32.lt_s
(grow_memory
;;@ (lib)/allocator/arena.ts:24:20
(get_local $5)
;;@ ~lib/allocator/arena.ts:22:8
(i32.gt_u
(get_local $2)
;;@ ~lib/allocator/arena.ts:22:17
(i32.shl
(get_local $3)
;;@ ~lib/allocator/arena.ts:22:39
(i32.const 16)
)
;;@ (lib)/allocator/arena.ts:24:35
(i32.const 0)
)
;;@ (lib)/allocator/arena.ts:25:6
(if
;;@ (lib)/allocator/arena.ts:25:10
(i32.lt_s
(grow_memory
;;@ (lib)/allocator/arena.ts:25:22
(get_local $4)
;;@ ~lib/allocator/arena.ts:22:43
(block
;;@ ~lib/allocator/arena.ts:23:6
(set_local $4
;;@ ~lib/allocator/arena.ts:23:24
(i32.shr_u
(i32.and
;;@ ~lib/allocator/arena.ts:23:25
(i32.add
;;@ ~lib/allocator/arena.ts:23:26
(i32.sub
(get_local $2)
;;@ ~lib/allocator/arena.ts:23:35
(get_local $1)
)
;;@ ~lib/allocator/arena.ts:23:41
(i32.const 65535)
)
;;@ ~lib/allocator/arena.ts:23:51
(i32.xor
;;@ ~lib/allocator/arena.ts:23:52
(i32.const 65535)
(i32.const -1)
)
)
;;@ ~lib/allocator/arena.ts:23:64
(i32.const 16)
)
)
;;@ ~lib/allocator/arena.ts:24:6
(set_local $5
;;@ ~lib/allocator/arena.ts:24:24
(select
(tee_local $5
;;@ ~lib/allocator/arena.ts:24:28
(get_local $3)
)
(tee_local $6
;;@ ~lib/allocator/arena.ts:24:41
(get_local $4)
)
(i32.gt_s
(get_local $5)
(get_local $6)
)
)
)
;;@ ~lib/allocator/arena.ts:25:6
(if
;;@ ~lib/allocator/arena.ts:25:10
(i32.lt_s
(grow_memory
;;@ ~lib/allocator/arena.ts:25:22
(get_local $5)
)
;;@ ~lib/allocator/arena.ts:25:37
(i32.const 0)
)
;;@ ~lib/allocator/arena.ts:26:8
(if
;;@ ~lib/allocator/arena.ts:26:12
(i32.lt_s
(grow_memory
;;@ ~lib/allocator/arena.ts:26:24
(get_local $4)
)
;;@ ~lib/allocator/arena.ts:26:39
(i32.const 0)
)
;;@ ~lib/allocator/arena.ts:27:10
(unreachable)
)
;;@ (lib)/allocator/arena.ts:25:37
(i32.const 0)
)
;;@ (lib)/allocator/arena.ts:26:8
(unreachable)
)
)
;;@ ~lib/allocator/arena.ts:31:4
(set_global $~lib/allocator/arena/offset
;;@ ~lib/allocator/arena.ts:31:13
(get_local $2)
)
;;@ ~lib/allocator/arena.ts:32:11
(return
(get_local $1)
)
)
)
;;@ (lib)/allocator/arena.ts:30:2
(set_global "$(lib)/allocator/arena/offset"
;;@ (lib)/allocator/arena.ts:30:11
(get_local $2)
)
;;@ (lib)/allocator/arena.ts:31:9
;;@ ~lib/allocator/arena.ts:34:9
(return
(get_local $1)
(i32.const 0)
)
)
(func "$(lib)/allocator/arena/free_memory" (; 1 ;) (type $iv) (param $0 i32)
(func $~lib/allocator/arena/free_memory (; 1 ;) (type $iv) (param $0 i32)
)
(func "$(lib)/allocator/arena/reset_memory" (; 2 ;) (type $v)
;;@ (lib)/allocator/arena.ts:41:2
(set_global "$(lib)/allocator/arena/offset"
;;@ (lib)/allocator/arena.ts:41:11
(get_global "$(lib)/allocator/arena/startOffset")
(func $~lib/allocator/arena/reset_memory (; 2 ;) (type $v)
;;@ ~lib/allocator/arena.ts:44:2
(set_global $~lib/allocator/arena/offset
;;@ ~lib/allocator/arena.ts:44:11
(get_global $~lib/allocator/arena/startOffset)
)
)
(func $start (; 3 ;) (type $v)
(set_global "$(lib)/allocator/arena/startOffset"
;;@ (lib)/allocator/arena.ts:12:25
(set_global $~lib/allocator/arena/startOffset
;;@ ~lib/allocator/arena.ts:12:25
(i32.and
(i32.add
;;@ (lib)/allocator/arena.ts:12:26
;;@ ~lib/allocator/arena.ts:12:26
(get_global $HEAP_BASE)
;;@ (lib)/allocator/arena.ts:12:38
;;@ ~lib/allocator/arena.ts:12:38
(i32.const 7)
)
;;@ (lib)/allocator/arena.ts:12:49
;;@ ~lib/allocator/arena.ts:12:49
(i32.xor
;;@ (lib)/allocator/arena.ts:12:50
;;@ ~lib/allocator/arena.ts:12:50
(i32.const 7)
(i32.const -1)
)
)
)
(set_global "$(lib)/allocator/arena/offset"
;;@ (lib)/allocator/arena.ts:13:20
(get_global "$(lib)/allocator/arena/startOffset")
(set_global $~lib/allocator/arena/offset
;;@ ~lib/allocator/arena.ts:13:20
(get_global $~lib/allocator/arena/startOffset)
)
)
)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,5 @@
const fs = require("fs");
const COMMON_MAX = 1 << 30;
function test(file) {
console.log("Testing '" + file + "' ...\n");
@ -23,6 +24,13 @@ function test(file) {
console.log("mem final: " + exports.memory.buffer.byteLength);
console.log();
if (exports.allocate_memory(COMMON_MAX + 1) != 0) {
throw Error("allocation is allowed to overflow MAX_SIZE");
}
if (exports.allocate_memory(0xffffffff) != 0) {
throw Error("allocation is allowed to overflow INT_MAX");
}
}
if (process.argv.length > 2) {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,4 @@
(module
(memory $0 1)
(export "memory" (memory $0))
)

16
tests/compiler/closure.ts Normal file
View File

@ -0,0 +1,16 @@
// TODO
// export function outer(): () => () => i32 {
// var inner: i32 = 42; // should become a global right away
// return function a(): () => i32 {
// return function b(): i32 {
// return inner++;
// };
// };
// }
// var fnA = outer();
// var fnB = fnA();
// assert(fnB() == 42);
// assert(fnB() == 43);

View File

@ -0,0 +1,5 @@
(module
(global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "memory" (memory $0))
)

View File

@ -22,81 +22,88 @@
(local $3 i32)
(local $4 i32)
(if
(i32.eqz
(select
(i32.lt_u
(get_local $0)
(i32.const 1073741824)
)
(get_local $0)
(get_local $0)
)
(return
(i32.const 0)
)
)
(if
(i32.gt_u
(tee_local $2
(i32.and
(i32.add
(i32.add
(tee_local $1
(get_global $~lib/allocator/arena/offset)
)
(get_local $0)
)
(i32.const 7)
)
(i32.const -8)
)
)
(i32.shl
(tee_local $0
(current_memory)
)
(i32.const 16)
)
)
(if
(i32.lt_s
(grow_memory
(select
(get_local $0)
(tee_local $4
(tee_local $3
(i32.shr_u
(i32.and
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.const -65536)
(block
(if
(i32.gt_u
(tee_local $2
(i32.and
(i32.add
(i32.add
(tee_local $1
(get_global $~lib/allocator/arena/offset)
)
(i32.const 16)
(get_local $0)
)
(i32.const 7)
)
(i32.const -8)
)
)
(i32.shl
(tee_local $0
(current_memory)
)
(i32.const 16)
)
)
(if
(i32.lt_s
(grow_memory
(select
(get_local $0)
(tee_local $4
(tee_local $3
(i32.shr_u
(i32.and
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.const -65536)
)
(i32.const 16)
)
)
)
(i32.gt_s
(get_local $0)
(get_local $4)
)
)
)
(i32.gt_s
(get_local $0)
(get_local $4)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $3)
)
(i32.const 0)
)
(unreachable)
)
)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $3)
)
(i32.const 0)
)
(unreachable)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(return
(get_local $1)
)
)
)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(get_local $1)
(i32.const 0)
)
(func $~lib/memory/set_memory (; 2 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32)
(local $3 i64)

View File

@ -7,9 +7,10 @@
(type $iv (func (param i32)))
(type $v (func))
(import "env" "abort" (func $abort (param i32 i32 i32 i32)))
(global $~lib/allocator/common/alignment/BITS i32 (i32.const 3))
(global $~lib/allocator/common/alignment/SIZE i32 (i32.const 8))
(global $~lib/allocator/common/alignment/MASK i32 (i32.const 7))
(global $~lib/allocator/common/index/AL_BITS i32 (i32.const 3))
(global $~lib/allocator/common/index/AL_SIZE i32 (i32.const 8))
(global $~lib/allocator/common/index/AL_MASK i32 (i32.const 7))
(global $~lib/allocator/common/index/MAX_SIZE_32 i32 (i32.const 1073741824))
(global $~lib/allocator/arena/startOffset (mut i32) (i32.const 0))
(global $~lib/allocator/arena/offset (mut i32) (i32.const 0))
(global $std/allocator_arena/size i32 (i32.const 42))
@ -28,100 +29,108 @@
(local $4 i32)
(local $5 i32)
(local $6 i32)
(nop)
(if
(i32.eqz
(if (result i32)
(get_local $0)
(i32.lt_u
(get_local $0)
(i32.const 1073741824)
)
(get_local $0)
)
(return
(i32.const 0)
)
)
(set_local $1
(get_global $~lib/allocator/arena/offset)
)
(set_local $2
(i32.and
(i32.add
(i32.add
(get_local $1)
(get_local $0)
)
(i32.const 7)
)
(i32.xor
(i32.const 7)
(i32.const -1)
)
)
)
(set_local $3
(current_memory)
)
(if
(i32.gt_u
(get_local $2)
(i32.shl
(get_local $3)
(i32.const 16)
)
)
(block
(set_local $4
(i32.shr_u
(i32.and
(set_local $1
(get_global $~lib/allocator/arena/offset)
)
(set_local $2
(i32.and
(i32.add
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.xor
(i32.const 65535)
(i32.const -1)
(get_local $1)
(get_local $0)
)
(i32.const 7)
)
(i32.xor
(i32.const 7)
(i32.const -1)
)
(i32.const 16)
)
)
(set_local $5
(select
(tee_local $5
(get_local $3)
)
(tee_local $6
(get_local $4)
)
(i32.gt_s
(get_local $5)
(get_local $6)
)
)
(set_local $3
(current_memory)
)
(if
(i32.lt_s
(grow_memory
(get_local $5)
(i32.gt_u
(get_local $2)
(i32.shl
(get_local $3)
(i32.const 16)
)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $4)
(block
(set_local $4
(i32.shr_u
(i32.and
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.xor
(i32.const 65535)
(i32.const -1)
)
)
(i32.const 16)
)
)
(set_local $5
(select
(tee_local $5
(get_local $3)
)
(tee_local $6
(get_local $4)
)
(i32.gt_s
(get_local $5)
(get_local $6)
)
)
)
(if
(i32.lt_s
(grow_memory
(get_local $5)
)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $4)
)
(i32.const 0)
)
(unreachable)
)
(i32.const 0)
)
(unreachable)
)
)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(return
(get_local $1)
)
)
)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(return
(get_local $1)
(i32.const 0)
)
)
(func $~lib/memory/set_memory (; 2 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32)

View File

@ -33,81 +33,88 @@
(local $3 i32)
(local $4 i32)
(if
(i32.eqz
(select
(i32.lt_u
(get_local $0)
(i32.const 1073741824)
)
(get_local $0)
(get_local $0)
)
(return
(i32.const 0)
)
)
(if
(i32.gt_u
(tee_local $2
(i32.and
(i32.add
(i32.add
(tee_local $1
(get_global $~lib/allocator/arena/offset)
)
(get_local $0)
)
(i32.const 7)
)
(i32.const -8)
)
)
(i32.shl
(tee_local $0
(current_memory)
)
(i32.const 16)
)
)
(if
(i32.lt_s
(grow_memory
(select
(get_local $0)
(tee_local $4
(tee_local $3
(i32.shr_u
(i32.and
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.const -65536)
(block
(if
(i32.gt_u
(tee_local $2
(i32.and
(i32.add
(i32.add
(tee_local $1
(get_global $~lib/allocator/arena/offset)
)
(i32.const 16)
(get_local $0)
)
(i32.const 7)
)
(i32.const -8)
)
)
(i32.shl
(tee_local $0
(current_memory)
)
(i32.const 16)
)
)
(if
(i32.lt_s
(grow_memory
(select
(get_local $0)
(tee_local $4
(tee_local $3
(i32.shr_u
(i32.and
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.const -65536)
)
(i32.const 16)
)
)
)
(i32.gt_s
(get_local $0)
(get_local $4)
)
)
)
(i32.gt_s
(get_local $0)
(get_local $4)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $3)
)
(i32.const 0)
)
(unreachable)
)
)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $3)
)
(i32.const 0)
)
(unreachable)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(return
(get_local $1)
)
)
)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(get_local $1)
(i32.const 0)
)
(func $~lib/array/Array<i32>#get:length (; 2 ;) (type $ii) (param $0 i32) (result i32)
(i32.load offset=8

View File

@ -10,9 +10,10 @@
(type $iiiii (func (param i32 i32 i32 i32) (result i32)))
(type $v (func))
(import "env" "abort" (func $abort (param i32 i32 i32 i32)))
(global $~lib/allocator/common/alignment/BITS i32 (i32.const 3))
(global $~lib/allocator/common/alignment/SIZE i32 (i32.const 8))
(global $~lib/allocator/common/alignment/MASK i32 (i32.const 7))
(global $~lib/allocator/common/index/AL_BITS i32 (i32.const 3))
(global $~lib/allocator/common/index/AL_SIZE i32 (i32.const 8))
(global $~lib/allocator/common/index/AL_MASK i32 (i32.const 7))
(global $~lib/allocator/common/index/MAX_SIZE_32 i32 (i32.const 1073741824))
(global $~lib/allocator/arena/startOffset (mut i32) (i32.const 0))
(global $~lib/allocator/arena/offset (mut i32) (i32.const 0))
(global $std/array/arr (mut i32) (i32.const 0))
@ -38,100 +39,108 @@
(local $4 i32)
(local $5 i32)
(local $6 i32)
(nop)
(if
(i32.eqz
(if (result i32)
(get_local $0)
(i32.lt_u
(get_local $0)
(i32.const 1073741824)
)
(get_local $0)
)
(return
(i32.const 0)
)
)
(set_local $1
(get_global $~lib/allocator/arena/offset)
)
(set_local $2
(i32.and
(i32.add
(i32.add
(get_local $1)
(get_local $0)
)
(i32.const 7)
)
(i32.xor
(i32.const 7)
(i32.const -1)
)
)
)
(set_local $3
(current_memory)
)
(if
(i32.gt_u
(get_local $2)
(i32.shl
(get_local $3)
(i32.const 16)
)
)
(block
(set_local $4
(i32.shr_u
(i32.and
(set_local $1
(get_global $~lib/allocator/arena/offset)
)
(set_local $2
(i32.and
(i32.add
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.xor
(i32.const 65535)
(i32.const -1)
(get_local $1)
(get_local $0)
)
(i32.const 7)
)
(i32.xor
(i32.const 7)
(i32.const -1)
)
(i32.const 16)
)
)
(set_local $5
(select
(tee_local $5
(get_local $3)
)
(tee_local $6
(get_local $4)
)
(i32.gt_s
(get_local $5)
(get_local $6)
)
)
(set_local $3
(current_memory)
)
(if
(i32.lt_s
(grow_memory
(get_local $5)
(i32.gt_u
(get_local $2)
(i32.shl
(get_local $3)
(i32.const 16)
)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $4)
(block
(set_local $4
(i32.shr_u
(i32.and
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.xor
(i32.const 65535)
(i32.const -1)
)
)
(i32.const 16)
)
)
(set_local $5
(select
(tee_local $5
(get_local $3)
)
(tee_local $6
(get_local $4)
)
(i32.gt_s
(get_local $5)
(get_local $6)
)
)
)
(if
(i32.lt_s
(grow_memory
(get_local $5)
)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $4)
)
(i32.const 0)
)
(unreachable)
)
(i32.const 0)
)
(unreachable)
)
)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(return
(get_local $1)
)
)
)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(return
(get_local $1)
(i32.const 0)
)
)
(func $~lib/array/Array<i32>#get:length (; 2 ;) (type $ii) (param $0 i32) (result i32)

View File

@ -22,81 +22,88 @@
(local $3 i32)
(local $4 i32)
(if
(i32.eqz
(select
(i32.lt_u
(get_local $0)
(i32.const 1073741824)
)
(get_local $0)
(get_local $0)
)
(return
(i32.const 0)
)
)
(if
(i32.gt_u
(tee_local $2
(i32.and
(i32.add
(i32.add
(tee_local $1
(get_global $~lib/allocator/arena/offset)
)
(get_local $0)
)
(i32.const 7)
)
(i32.const -8)
)
)
(i32.shl
(tee_local $0
(current_memory)
)
(i32.const 16)
)
)
(if
(i32.lt_s
(grow_memory
(select
(get_local $0)
(tee_local $4
(tee_local $3
(i32.shr_u
(i32.and
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.const -65536)
(block
(if
(i32.gt_u
(tee_local $2
(i32.and
(i32.add
(i32.add
(tee_local $1
(get_global $~lib/allocator/arena/offset)
)
(i32.const 16)
(get_local $0)
)
(i32.const 7)
)
(i32.const -8)
)
)
(i32.shl
(tee_local $0
(current_memory)
)
(i32.const 16)
)
)
(if
(i32.lt_s
(grow_memory
(select
(get_local $0)
(tee_local $4
(tee_local $3
(i32.shr_u
(i32.and
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.const -65536)
)
(i32.const 16)
)
)
)
(i32.gt_s
(get_local $0)
(get_local $4)
)
)
)
(i32.gt_s
(get_local $0)
(get_local $4)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $3)
)
(i32.const 0)
)
(unreachable)
)
)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $3)
)
(i32.const 0)
)
(unreachable)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(return
(get_local $1)
)
)
)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(get_local $1)
(i32.const 0)
)
(func $~lib/arraybuffer/ArrayBuffer#constructor (; 2 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
(local $2 i32)

View File

@ -7,9 +7,10 @@
(type $iiiv (func (param i32 i32 i32)))
(type $v (func))
(import "env" "abort" (func $abort (param i32 i32 i32 i32)))
(global $~lib/allocator/common/alignment/BITS i32 (i32.const 3))
(global $~lib/allocator/common/alignment/SIZE i32 (i32.const 8))
(global $~lib/allocator/common/alignment/MASK i32 (i32.const 7))
(global $~lib/allocator/common/index/AL_BITS i32 (i32.const 3))
(global $~lib/allocator/common/index/AL_SIZE i32 (i32.const 8))
(global $~lib/allocator/common/index/AL_MASK i32 (i32.const 7))
(global $~lib/allocator/common/index/MAX_SIZE_32 i32 (i32.const 1073741824))
(global $~lib/allocator/arena/startOffset (mut i32) (i32.const 0))
(global $~lib/allocator/arena/offset (mut i32) (i32.const 0))
(global $~lib/arraybuffer/HEADER_SIZE i32 (i32.const 4))
@ -28,100 +29,108 @@
(local $4 i32)
(local $5 i32)
(local $6 i32)
(nop)
(if
(i32.eqz
(if (result i32)
(get_local $0)
(i32.lt_u
(get_local $0)
(i32.const 1073741824)
)
(get_local $0)
)
(return
(i32.const 0)
)
)
(set_local $1
(get_global $~lib/allocator/arena/offset)
)
(set_local $2
(i32.and
(i32.add
(i32.add
(get_local $1)
(get_local $0)
)
(i32.const 7)
)
(i32.xor
(i32.const 7)
(i32.const -1)
)
)
)
(set_local $3
(current_memory)
)
(if
(i32.gt_u
(get_local $2)
(i32.shl
(get_local $3)
(i32.const 16)
)
)
(block
(set_local $4
(i32.shr_u
(i32.and
(set_local $1
(get_global $~lib/allocator/arena/offset)
)
(set_local $2
(i32.and
(i32.add
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.xor
(i32.const 65535)
(i32.const -1)
(get_local $1)
(get_local $0)
)
(i32.const 7)
)
(i32.xor
(i32.const 7)
(i32.const -1)
)
(i32.const 16)
)
)
(set_local $5
(select
(tee_local $5
(get_local $3)
)
(tee_local $6
(get_local $4)
)
(i32.gt_s
(get_local $5)
(get_local $6)
)
)
(set_local $3
(current_memory)
)
(if
(i32.lt_s
(grow_memory
(get_local $5)
(i32.gt_u
(get_local $2)
(i32.shl
(get_local $3)
(i32.const 16)
)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $4)
(block
(set_local $4
(i32.shr_u
(i32.and
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.xor
(i32.const 65535)
(i32.const -1)
)
)
(i32.const 16)
)
)
(set_local $5
(select
(tee_local $5
(get_local $3)
)
(tee_local $6
(get_local $4)
)
(i32.gt_s
(get_local $5)
(get_local $6)
)
)
)
(if
(i32.lt_s
(grow_memory
(get_local $5)
)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $4)
)
(i32.const 0)
)
(unreachable)
)
(i32.const 0)
)
(unreachable)
)
)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(return
(get_local $1)
)
)
)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(return
(get_local $1)
(i32.const 0)
)
)
(func $~lib/arraybuffer/ArrayBuffer#constructor (; 2 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)

View File

@ -24,81 +24,88 @@
(local $3 i32)
(local $4 i32)
(if
(i32.eqz
(select
(i32.lt_u
(get_local $0)
(i32.const 1073741824)
)
(get_local $0)
(get_local $0)
)
(return
(i32.const 0)
)
)
(if
(i32.gt_u
(tee_local $2
(i32.and
(i32.add
(i32.add
(tee_local $1
(get_global $~lib/allocator/arena/offset)
)
(get_local $0)
)
(i32.const 7)
)
(i32.const -8)
)
)
(i32.shl
(tee_local $0
(current_memory)
)
(i32.const 16)
)
)
(if
(i32.lt_s
(grow_memory
(select
(get_local $0)
(tee_local $4
(tee_local $3
(i32.shr_u
(i32.and
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.const -65536)
(block
(if
(i32.gt_u
(tee_local $2
(i32.and
(i32.add
(i32.add
(tee_local $1
(get_global $~lib/allocator/arena/offset)
)
(i32.const 16)
(get_local $0)
)
(i32.const 7)
)
(i32.const -8)
)
)
(i32.shl
(tee_local $0
(current_memory)
)
(i32.const 16)
)
)
(if
(i32.lt_s
(grow_memory
(select
(get_local $0)
(tee_local $4
(tee_local $3
(i32.shr_u
(i32.and
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.const -65536)
)
(i32.const 16)
)
)
)
(i32.gt_s
(get_local $0)
(get_local $4)
)
)
)
(i32.gt_s
(get_local $0)
(get_local $4)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $3)
)
(i32.const 0)
)
(unreachable)
)
)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $3)
)
(i32.const 0)
)
(unreachable)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(return
(get_local $1)
)
)
)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(get_local $1)
(i32.const 0)
)
(func $std/constructor/EmptyCtor#constructor (; 1 ;) (type $ii) (param $0 i32) (result i32)
(if (result i32)

View File

@ -2,9 +2,10 @@
(type $i (func (result i32)))
(type $ii (func (param i32) (result i32)))
(type $v (func))
(global $~lib/allocator/common/alignment/BITS i32 (i32.const 3))
(global $~lib/allocator/common/alignment/SIZE i32 (i32.const 8))
(global $~lib/allocator/common/alignment/MASK i32 (i32.const 7))
(global $~lib/allocator/common/index/AL_BITS i32 (i32.const 3))
(global $~lib/allocator/common/index/AL_SIZE i32 (i32.const 8))
(global $~lib/allocator/common/index/AL_MASK i32 (i32.const 7))
(global $~lib/allocator/common/index/MAX_SIZE_32 i32 (i32.const 1073741824))
(global $~lib/allocator/arena/startOffset (mut i32) (i32.const 0))
(global $~lib/allocator/arena/offset (mut i32) (i32.const 0))
(global $std/constructor/emptyCtor (mut i32) (i32.const 0))
@ -29,100 +30,108 @@
(local $4 i32)
(local $5 i32)
(local $6 i32)
(nop)
(if
(i32.eqz
(if (result i32)
(get_local $0)
(i32.lt_u
(get_local $0)
(i32.const 1073741824)
)
(get_local $0)
)
(return
(i32.const 0)
)
)
(set_local $1
(get_global $~lib/allocator/arena/offset)
)
(set_local $2
(i32.and
(i32.add
(i32.add
(get_local $1)
(get_local $0)
)
(i32.const 7)
)
(i32.xor
(i32.const 7)
(i32.const -1)
)
)
)
(set_local $3
(current_memory)
)
(if
(i32.gt_u
(get_local $2)
(i32.shl
(get_local $3)
(i32.const 16)
)
)
(block
(set_local $4
(i32.shr_u
(i32.and
(set_local $1
(get_global $~lib/allocator/arena/offset)
)
(set_local $2
(i32.and
(i32.add
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.xor
(i32.const 65535)
(i32.const -1)
(get_local $1)
(get_local $0)
)
(i32.const 7)
)
(i32.xor
(i32.const 7)
(i32.const -1)
)
(i32.const 16)
)
)
(set_local $5
(select
(tee_local $5
(get_local $3)
)
(tee_local $6
(get_local $4)
)
(i32.gt_s
(get_local $5)
(get_local $6)
)
)
(set_local $3
(current_memory)
)
(if
(i32.lt_s
(grow_memory
(get_local $5)
(i32.gt_u
(get_local $2)
(i32.shl
(get_local $3)
(i32.const 16)
)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $4)
(block
(set_local $4
(i32.shr_u
(i32.and
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.xor
(i32.const 65535)
(i32.const -1)
)
)
(i32.const 16)
)
)
(set_local $5
(select
(tee_local $5
(get_local $3)
)
(tee_local $6
(get_local $4)
)
(i32.gt_s
(get_local $5)
(get_local $6)
)
)
)
(if
(i32.lt_s
(grow_memory
(get_local $5)
)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $4)
)
(i32.const 0)
)
(unreachable)
)
(i32.const 0)
)
(unreachable)
)
)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(return
(get_local $1)
)
)
)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(return
(get_local $1)
(i32.const 0)
)
)
(func $std/constructor/EmptyCtor#constructor (; 1 ;) (type $ii) (param $0 i32) (result i32)

View File

@ -15,81 +15,88 @@
(local $3 i32)
(local $4 i32)
(if
(i32.eqz
(select
(i32.lt_u
(get_local $0)
(i32.const 1073741824)
)
(get_local $0)
(get_local $0)
)
(return
(i32.const 0)
)
)
(if
(i32.gt_u
(tee_local $2
(i32.and
(i32.add
(i32.add
(tee_local $1
(get_global $~lib/allocator/arena/offset)
)
(get_local $0)
)
(i32.const 7)
)
(i32.const -8)
)
)
(i32.shl
(tee_local $0
(current_memory)
)
(i32.const 16)
)
)
(if
(i32.lt_s
(grow_memory
(select
(get_local $0)
(tee_local $4
(tee_local $3
(i32.shr_u
(i32.and
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.const -65536)
(block
(if
(i32.gt_u
(tee_local $2
(i32.and
(i32.add
(i32.add
(tee_local $1
(get_global $~lib/allocator/arena/offset)
)
(i32.const 16)
(get_local $0)
)
(i32.const 7)
)
(i32.const -8)
)
)
(i32.shl
(tee_local $0
(current_memory)
)
(i32.const 16)
)
)
(if
(i32.lt_s
(grow_memory
(select
(get_local $0)
(tee_local $4
(tee_local $3
(i32.shr_u
(i32.and
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.const -65536)
)
(i32.const 16)
)
)
)
(i32.gt_s
(get_local $0)
(get_local $4)
)
)
)
(i32.gt_s
(get_local $0)
(get_local $4)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $3)
)
(i32.const 0)
)
(unreachable)
)
)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $3)
)
(i32.const 0)
)
(unreachable)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(return
(get_local $1)
)
)
)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(get_local $1)
(i32.const 0)
)
(func $std/new/AClass#constructor (; 1 ;) (type $ifi) (param $0 i32) (param $1 f32) (result i32)
(local $2 i32)

View File

@ -3,9 +3,10 @@
(type $ifi (func (param i32 f32) (result i32)))
(type $ii (func (param i32) (result i32)))
(type $v (func))
(global $~lib/allocator/common/alignment/BITS i32 (i32.const 3))
(global $~lib/allocator/common/alignment/SIZE i32 (i32.const 8))
(global $~lib/allocator/common/alignment/MASK i32 (i32.const 7))
(global $~lib/allocator/common/index/AL_BITS i32 (i32.const 3))
(global $~lib/allocator/common/index/AL_SIZE i32 (i32.const 8))
(global $~lib/allocator/common/index/AL_MASK i32 (i32.const 7))
(global $~lib/allocator/common/index/MAX_SIZE_32 i32 (i32.const 1073741824))
(global $~lib/allocator/arena/startOffset (mut i32) (i32.const 0))
(global $~lib/allocator/arena/offset (mut i32) (i32.const 0))
(global $std/new/aClass (mut i32) (i32.const 0))
@ -20,100 +21,108 @@
(local $4 i32)
(local $5 i32)
(local $6 i32)
(nop)
(if
(i32.eqz
(if (result i32)
(get_local $0)
(i32.lt_u
(get_local $0)
(i32.const 1073741824)
)
(get_local $0)
)
(return
(i32.const 0)
)
)
(set_local $1
(get_global $~lib/allocator/arena/offset)
)
(set_local $2
(i32.and
(i32.add
(i32.add
(get_local $1)
(get_local $0)
)
(i32.const 7)
)
(i32.xor
(i32.const 7)
(i32.const -1)
)
)
)
(set_local $3
(current_memory)
)
(if
(i32.gt_u
(get_local $2)
(i32.shl
(get_local $3)
(i32.const 16)
)
)
(block
(set_local $4
(i32.shr_u
(i32.and
(set_local $1
(get_global $~lib/allocator/arena/offset)
)
(set_local $2
(i32.and
(i32.add
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.xor
(i32.const 65535)
(i32.const -1)
(get_local $1)
(get_local $0)
)
(i32.const 7)
)
(i32.xor
(i32.const 7)
(i32.const -1)
)
(i32.const 16)
)
)
(set_local $5
(select
(tee_local $5
(get_local $3)
)
(tee_local $6
(get_local $4)
)
(i32.gt_s
(get_local $5)
(get_local $6)
)
)
(set_local $3
(current_memory)
)
(if
(i32.lt_s
(grow_memory
(get_local $5)
(i32.gt_u
(get_local $2)
(i32.shl
(get_local $3)
(i32.const 16)
)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $4)
(block
(set_local $4
(i32.shr_u
(i32.and
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.xor
(i32.const 65535)
(i32.const -1)
)
)
(i32.const 16)
)
)
(set_local $5
(select
(tee_local $5
(get_local $3)
)
(tee_local $6
(get_local $4)
)
(i32.gt_s
(get_local $5)
(get_local $6)
)
)
)
(if
(i32.lt_s
(grow_memory
(get_local $5)
)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $4)
)
(i32.const 0)
)
(unreachable)
)
(i32.const 0)
)
(unreachable)
)
)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(return
(get_local $1)
)
)
)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(return
(get_local $1)
(i32.const 0)
)
)
(func $std/new/AClass#constructor (; 1 ;) (type $ifi) (param $0 i32) (param $1 f32) (result i32)

View File

@ -48,81 +48,88 @@
(local $3 i32)
(local $4 i32)
(if
(i32.eqz
(select
(i32.lt_u
(get_local $0)
(i32.const 1073741824)
)
(get_local $0)
(get_local $0)
)
(return
(i32.const 0)
)
)
(if
(i32.gt_u
(tee_local $2
(i32.and
(i32.add
(i32.add
(tee_local $1
(get_global $~lib/allocator/arena/offset)
)
(get_local $0)
)
(i32.const 7)
)
(i32.const -8)
)
)
(i32.shl
(tee_local $0
(current_memory)
)
(i32.const 16)
)
)
(if
(i32.lt_s
(grow_memory
(select
(get_local $0)
(tee_local $4
(tee_local $3
(i32.shr_u
(i32.and
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.const -65536)
(block
(if
(i32.gt_u
(tee_local $2
(i32.and
(i32.add
(i32.add
(tee_local $1
(get_global $~lib/allocator/arena/offset)
)
(i32.const 16)
(get_local $0)
)
(i32.const 7)
)
(i32.const -8)
)
)
(i32.shl
(tee_local $0
(current_memory)
)
(i32.const 16)
)
)
(if
(i32.lt_s
(grow_memory
(select
(get_local $0)
(tee_local $4
(tee_local $3
(i32.shr_u
(i32.and
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.const -65536)
)
(i32.const 16)
)
)
)
(i32.gt_s
(get_local $0)
(get_local $4)
)
)
)
(i32.gt_s
(get_local $0)
(get_local $4)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $3)
)
(i32.const 0)
)
(unreachable)
)
)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $3)
)
(i32.const 0)
)
(unreachable)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(return
(get_local $1)
)
)
)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(get_local $1)
(i32.const 0)
)
(func $std/operator-overloading/Tester#constructor (; 2 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
(local $3 i32)

View File

@ -6,9 +6,10 @@
(type $iiiiv (func (param i32 i32 i32 i32)))
(type $v (func))
(import "env" "abort" (func $abort (param i32 i32 i32 i32)))
(global $~lib/allocator/common/alignment/BITS i32 (i32.const 3))
(global $~lib/allocator/common/alignment/SIZE i32 (i32.const 8))
(global $~lib/allocator/common/alignment/MASK i32 (i32.const 7))
(global $~lib/allocator/common/index/AL_BITS i32 (i32.const 3))
(global $~lib/allocator/common/index/AL_SIZE i32 (i32.const 8))
(global $~lib/allocator/common/index/AL_MASK i32 (i32.const 7))
(global $~lib/allocator/common/index/MAX_SIZE_32 i32 (i32.const 1073741824))
(global $~lib/allocator/arena/startOffset (mut i32) (i32.const 0))
(global $~lib/allocator/arena/offset (mut i32) (i32.const 0))
(global $std/operator-overloading/a1 (mut i32) (i32.const 0))
@ -53,100 +54,108 @@
(local $4 i32)
(local $5 i32)
(local $6 i32)
(nop)
(if
(i32.eqz
(if (result i32)
(get_local $0)
(i32.lt_u
(get_local $0)
(i32.const 1073741824)
)
(get_local $0)
)
(return
(i32.const 0)
)
)
(set_local $1
(get_global $~lib/allocator/arena/offset)
)
(set_local $2
(i32.and
(i32.add
(i32.add
(get_local $1)
(get_local $0)
)
(i32.const 7)
)
(i32.xor
(i32.const 7)
(i32.const -1)
)
)
)
(set_local $3
(current_memory)
)
(if
(i32.gt_u
(get_local $2)
(i32.shl
(get_local $3)
(i32.const 16)
)
)
(block
(set_local $4
(i32.shr_u
(i32.and
(set_local $1
(get_global $~lib/allocator/arena/offset)
)
(set_local $2
(i32.and
(i32.add
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.xor
(i32.const 65535)
(i32.const -1)
(get_local $1)
(get_local $0)
)
(i32.const 7)
)
(i32.xor
(i32.const 7)
(i32.const -1)
)
(i32.const 16)
)
)
(set_local $5
(select
(tee_local $5
(get_local $3)
)
(tee_local $6
(get_local $4)
)
(i32.gt_s
(get_local $5)
(get_local $6)
)
)
(set_local $3
(current_memory)
)
(if
(i32.lt_s
(grow_memory
(get_local $5)
(i32.gt_u
(get_local $2)
(i32.shl
(get_local $3)
(i32.const 16)
)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $4)
(block
(set_local $4
(i32.shr_u
(i32.and
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.xor
(i32.const 65535)
(i32.const -1)
)
)
(i32.const 16)
)
)
(set_local $5
(select
(tee_local $5
(get_local $3)
)
(tee_local $6
(get_local $4)
)
(i32.gt_s
(get_local $5)
(get_local $6)
)
)
)
(if
(i32.lt_s
(grow_memory
(get_local $5)
)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $4)
)
(i32.const 0)
)
(unreachable)
)
(i32.const 0)
)
(unreachable)
)
)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(return
(get_local $1)
)
)
)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(return
(get_local $1)
(i32.const 0)
)
)
(func $std/operator-overloading/Tester#constructor (; 2 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)

View File

@ -21,81 +21,88 @@
(local $3 i32)
(local $4 i32)
(if
(i32.eqz
(select
(i32.lt_u
(get_local $0)
(i32.const 1073741824)
)
(get_local $0)
(get_local $0)
)
(return
(i32.const 0)
)
)
(if
(i32.gt_u
(tee_local $2
(i32.and
(i32.add
(i32.add
(tee_local $1
(get_global $~lib/allocator/arena/offset)
)
(get_local $0)
)
(i32.const 7)
)
(i32.const -8)
)
)
(i32.shl
(tee_local $0
(current_memory)
)
(i32.const 16)
)
)
(if
(i32.lt_s
(grow_memory
(select
(get_local $0)
(tee_local $4
(tee_local $3
(i32.shr_u
(i32.and
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.const -65536)
(block
(if
(i32.gt_u
(tee_local $2
(i32.and
(i32.add
(i32.add
(tee_local $1
(get_global $~lib/allocator/arena/offset)
)
(i32.const 16)
(get_local $0)
)
(i32.const 7)
)
(i32.const -8)
)
)
(i32.shl
(tee_local $0
(current_memory)
)
(i32.const 16)
)
)
(if
(i32.lt_s
(grow_memory
(select
(get_local $0)
(tee_local $4
(tee_local $3
(i32.shr_u
(i32.and
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.const -65536)
)
(i32.const 16)
)
)
)
(i32.gt_s
(get_local $0)
(get_local $4)
)
)
)
(i32.gt_s
(get_local $0)
(get_local $4)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $3)
)
(i32.const 0)
)
(unreachable)
)
)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $3)
)
(i32.const 0)
)
(unreachable)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(return
(get_local $1)
)
)
)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(get_local $1)
(i32.const 0)
)
(func $~lib/set/Set<i32>#get:size (; 2 ;) (type $ii) (param $0 i32) (result i32)
(i32.load offset=8

View File

@ -7,9 +7,10 @@
(type $iv (func (param i32)))
(type $v (func))
(import "env" "abort" (func $abort (param i32 i32 i32 i32)))
(global $~lib/allocator/common/alignment/BITS i32 (i32.const 3))
(global $~lib/allocator/common/alignment/SIZE i32 (i32.const 8))
(global $~lib/allocator/common/alignment/MASK i32 (i32.const 7))
(global $~lib/allocator/common/index/AL_BITS i32 (i32.const 3))
(global $~lib/allocator/common/index/AL_SIZE i32 (i32.const 8))
(global $~lib/allocator/common/index/AL_MASK i32 (i32.const 7))
(global $~lib/allocator/common/index/MAX_SIZE_32 i32 (i32.const 1073741824))
(global $~lib/allocator/arena/startOffset (mut i32) (i32.const 0))
(global $~lib/allocator/arena/offset (mut i32) (i32.const 0))
(global $std/set/set (mut i32) (i32.const 0))
@ -26,100 +27,108 @@
(local $4 i32)
(local $5 i32)
(local $6 i32)
(nop)
(if
(i32.eqz
(if (result i32)
(get_local $0)
(i32.lt_u
(get_local $0)
(i32.const 1073741824)
)
(get_local $0)
)
(return
(i32.const 0)
)
)
(set_local $1
(get_global $~lib/allocator/arena/offset)
)
(set_local $2
(i32.and
(i32.add
(i32.add
(get_local $1)
(get_local $0)
)
(i32.const 7)
)
(i32.xor
(i32.const 7)
(i32.const -1)
)
)
)
(set_local $3
(current_memory)
)
(if
(i32.gt_u
(get_local $2)
(i32.shl
(get_local $3)
(i32.const 16)
)
)
(block
(set_local $4
(i32.shr_u
(i32.and
(set_local $1
(get_global $~lib/allocator/arena/offset)
)
(set_local $2
(i32.and
(i32.add
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.xor
(i32.const 65535)
(i32.const -1)
(get_local $1)
(get_local $0)
)
(i32.const 7)
)
(i32.xor
(i32.const 7)
(i32.const -1)
)
(i32.const 16)
)
)
(set_local $5
(select
(tee_local $5
(get_local $3)
)
(tee_local $6
(get_local $4)
)
(i32.gt_s
(get_local $5)
(get_local $6)
)
)
(set_local $3
(current_memory)
)
(if
(i32.lt_s
(grow_memory
(get_local $5)
(i32.gt_u
(get_local $2)
(i32.shl
(get_local $3)
(i32.const 16)
)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $4)
(block
(set_local $4
(i32.shr_u
(i32.and
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.xor
(i32.const 65535)
(i32.const -1)
)
)
(i32.const 16)
)
)
(set_local $5
(select
(tee_local $5
(get_local $3)
)
(tee_local $6
(get_local $4)
)
(i32.gt_s
(get_local $5)
(get_local $6)
)
)
)
(if
(i32.lt_s
(grow_memory
(get_local $5)
)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $4)
)
(i32.const 0)
)
(unreachable)
)
(i32.const 0)
)
(unreachable)
)
)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(return
(get_local $1)
)
)
)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(return
(get_local $1)
(i32.const 0)
)
)
(func $~lib/set/Set<i32>#get:size (; 2 ;) (type $ii) (param $0 i32) (result i32)

View File

@ -59,81 +59,88 @@
(local $3 i32)
(local $4 i32)
(if
(i32.eqz
(select
(i32.lt_u
(get_local $0)
(i32.const 1073741824)
)
(get_local $0)
(get_local $0)
)
(return
(i32.const 0)
)
)
(if
(i32.gt_u
(tee_local $2
(i32.and
(i32.add
(i32.add
(tee_local $1
(get_global $~lib/allocator/arena/offset)
)
(get_local $0)
)
(i32.const 7)
)
(i32.const -8)
)
)
(i32.shl
(tee_local $0
(current_memory)
)
(i32.const 16)
)
)
(if
(i32.lt_s
(grow_memory
(select
(get_local $0)
(tee_local $4
(tee_local $3
(i32.shr_u
(i32.and
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.const -65536)
(block
(if
(i32.gt_u
(tee_local $2
(i32.and
(i32.add
(i32.add
(tee_local $1
(get_global $~lib/allocator/arena/offset)
)
(i32.const 16)
(get_local $0)
)
(i32.const 7)
)
(i32.const -8)
)
)
(i32.shl
(tee_local $0
(current_memory)
)
(i32.const 16)
)
)
(if
(i32.lt_s
(grow_memory
(select
(get_local $0)
(tee_local $4
(tee_local $3
(i32.shr_u
(i32.and
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.const -65536)
)
(i32.const 16)
)
)
)
(i32.gt_s
(get_local $0)
(get_local $4)
)
)
)
(i32.gt_s
(get_local $0)
(get_local $4)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $3)
)
(i32.const 0)
)
(unreachable)
)
)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $3)
)
(i32.const 0)
)
(unreachable)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(return
(get_local $1)
)
)
)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(get_local $1)
(i32.const 0)
)
(func $~lib/memory/copy_memory (; 4 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32)
(local $3 i32)

View File

@ -17,9 +17,10 @@
(type $iiFv (func (param i32 i32 f64)))
(type $v (func))
(import "env" "abort" (func $abort (param i32 i32 i32 i32)))
(global $~lib/allocator/common/alignment/BITS i32 (i32.const 3))
(global $~lib/allocator/common/alignment/SIZE i32 (i32.const 8))
(global $~lib/allocator/common/alignment/MASK i32 (i32.const 7))
(global $~lib/allocator/common/index/AL_BITS i32 (i32.const 3))
(global $~lib/allocator/common/index/AL_SIZE i32 (i32.const 8))
(global $~lib/allocator/common/index/AL_MASK i32 (i32.const 7))
(global $~lib/allocator/common/index/MAX_SIZE_32 i32 (i32.const 1073741824))
(global $~lib/allocator/arena/startOffset (mut i32) (i32.const 0))
(global $~lib/allocator/arena/offset (mut i32) (i32.const 0))
(global $std/static-array/i i32 (i32.const 8))
@ -74,100 +75,108 @@
(local $4 i32)
(local $5 i32)
(local $6 i32)
(nop)
(if
(i32.eqz
(if (result i32)
(get_local $0)
(i32.lt_u
(get_local $0)
(i32.const 1073741824)
)
(get_local $0)
)
(return
(i32.const 0)
)
)
(set_local $1
(get_global $~lib/allocator/arena/offset)
)
(set_local $2
(i32.and
(i32.add
(i32.add
(get_local $1)
(get_local $0)
)
(i32.const 7)
)
(i32.xor
(i32.const 7)
(i32.const -1)
)
)
)
(set_local $3
(current_memory)
)
(if
(i32.gt_u
(get_local $2)
(i32.shl
(get_local $3)
(i32.const 16)
)
)
(block
(set_local $4
(i32.shr_u
(i32.and
(set_local $1
(get_global $~lib/allocator/arena/offset)
)
(set_local $2
(i32.and
(i32.add
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.xor
(i32.const 65535)
(i32.const -1)
(get_local $1)
(get_local $0)
)
(i32.const 7)
)
(i32.xor
(i32.const 7)
(i32.const -1)
)
(i32.const 16)
)
)
(set_local $5
(select
(tee_local $5
(get_local $3)
)
(tee_local $6
(get_local $4)
)
(i32.gt_s
(get_local $5)
(get_local $6)
)
)
(set_local $3
(current_memory)
)
(if
(i32.lt_s
(grow_memory
(get_local $5)
(i32.gt_u
(get_local $2)
(i32.shl
(get_local $3)
(i32.const 16)
)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $4)
(block
(set_local $4
(i32.shr_u
(i32.and
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.xor
(i32.const 65535)
(i32.const -1)
)
)
(i32.const 16)
)
)
(set_local $5
(select
(tee_local $5
(get_local $3)
)
(tee_local $6
(get_local $4)
)
(i32.gt_s
(get_local $5)
(get_local $6)
)
)
)
(if
(i32.lt_s
(grow_memory
(get_local $5)
)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $4)
)
(i32.const 0)
)
(unreachable)
)
(i32.const 0)
)
(unreachable)
)
)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(return
(get_local $1)
)
)
)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(return
(get_local $1)
(i32.const 0)
)
)
(func $~lib/memory/copy_memory (; 4 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32)

View File

@ -1226,81 +1226,88 @@
(local $3 i32)
(local $4 i32)
(if
(i32.eqz
(select
(i32.lt_u
(get_local $0)
(i32.const 1073741824)
)
(get_local $0)
(get_local $0)
)
(return
(i32.const 0)
)
)
(if
(i32.gt_u
(tee_local $2
(i32.and
(i32.add
(i32.add
(tee_local $1
(get_global $~lib/allocator/arena/offset)
)
(get_local $0)
)
(i32.const 7)
)
(i32.const -8)
)
)
(i32.shl
(tee_local $0
(current_memory)
)
(i32.const 16)
)
)
(if
(i32.lt_s
(grow_memory
(select
(get_local $0)
(tee_local $4
(tee_local $3
(i32.shr_u
(i32.and
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.const -65536)
(block
(if
(i32.gt_u
(tee_local $2
(i32.and
(i32.add
(i32.add
(tee_local $1
(get_global $~lib/allocator/arena/offset)
)
(i32.const 16)
(get_local $0)
)
(i32.const 7)
)
(i32.const -8)
)
)
(i32.shl
(tee_local $0
(current_memory)
)
(i32.const 16)
)
)
(if
(i32.lt_s
(grow_memory
(select
(get_local $0)
(tee_local $4
(tee_local $3
(i32.shr_u
(i32.and
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.const -65536)
)
(i32.const 16)
)
)
)
(i32.gt_s
(get_local $0)
(get_local $4)
)
)
)
(i32.gt_s
(get_local $0)
(get_local $4)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $3)
)
(i32.const 0)
)
(unreachable)
)
)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $3)
)
(i32.const 0)
)
(unreachable)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(return
(get_local $1)
)
)
)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(get_local $1)
(i32.const 0)
)
(func $~lib/string/allocate (; 18 ;) (type $ii) (param $0 i32) (result i32)
(local $1 i32)

View File

@ -9,9 +9,10 @@
(type $iiiv (func (param i32 i32 i32)))
(type $v (func))
(import "env" "abort" (func $abort (param i32 i32 i32 i32)))
(global $~lib/allocator/common/alignment/BITS i32 (i32.const 3))
(global $~lib/allocator/common/alignment/SIZE i32 (i32.const 8))
(global $~lib/allocator/common/alignment/MASK i32 (i32.const 7))
(global $~lib/allocator/common/index/AL_BITS i32 (i32.const 3))
(global $~lib/allocator/common/index/AL_SIZE i32 (i32.const 8))
(global $~lib/allocator/common/index/AL_MASK i32 (i32.const 7))
(global $~lib/allocator/common/index/MAX_SIZE_32 i32 (i32.const 1073741824))
(global $~lib/allocator/arena/startOffset (mut i32) (i32.const 0))
(global $~lib/allocator/arena/offset (mut i32) (i32.const 0))
(global $std/string/str (mut i32) (i32.const 4))
@ -1415,100 +1416,108 @@
(local $4 i32)
(local $5 i32)
(local $6 i32)
(nop)
(if
(i32.eqz
(if (result i32)
(get_local $0)
(i32.lt_u
(get_local $0)
(i32.const 1073741824)
)
(get_local $0)
)
(return
(i32.const 0)
)
)
(set_local $1
(get_global $~lib/allocator/arena/offset)
)
(set_local $2
(i32.and
(i32.add
(i32.add
(get_local $1)
(get_local $0)
)
(i32.const 7)
)
(i32.xor
(i32.const 7)
(i32.const -1)
)
)
)
(set_local $3
(current_memory)
)
(if
(i32.gt_u
(get_local $2)
(i32.shl
(get_local $3)
(i32.const 16)
)
)
(block
(set_local $4
(i32.shr_u
(i32.and
(set_local $1
(get_global $~lib/allocator/arena/offset)
)
(set_local $2
(i32.and
(i32.add
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.xor
(i32.const 65535)
(i32.const -1)
(get_local $1)
(get_local $0)
)
(i32.const 7)
)
(i32.xor
(i32.const 7)
(i32.const -1)
)
(i32.const 16)
)
)
(set_local $5
(select
(tee_local $5
(get_local $3)
)
(tee_local $6
(get_local $4)
)
(i32.gt_s
(get_local $5)
(get_local $6)
)
)
(set_local $3
(current_memory)
)
(if
(i32.lt_s
(grow_memory
(get_local $5)
(i32.gt_u
(get_local $2)
(i32.shl
(get_local $3)
(i32.const 16)
)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $4)
(block
(set_local $4
(i32.shr_u
(i32.and
(i32.add
(i32.sub
(get_local $2)
(get_local $1)
)
(i32.const 65535)
)
(i32.xor
(i32.const 65535)
(i32.const -1)
)
)
(i32.const 16)
)
)
(set_local $5
(select
(tee_local $5
(get_local $3)
)
(tee_local $6
(get_local $4)
)
(i32.gt_s
(get_local $5)
(get_local $6)
)
)
)
(if
(i32.lt_s
(grow_memory
(get_local $5)
)
(i32.const 0)
)
(if
(i32.lt_s
(grow_memory
(get_local $4)
)
(i32.const 0)
)
(unreachable)
)
(i32.const 0)
)
(unreachable)
)
)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(return
(get_local $1)
)
)
)
(set_global $~lib/allocator/arena/offset
(get_local $2)
)
(return
(get_local $1)
(i32.const 0)
)
)
(func $~lib/string/allocate (; 18 ;) (type $ii) (param $0 i32) (result i32)

View File

@ -64,7 +64,7 @@ const bin = {
const libDir = path.join(__dirname, "std", "assembly");
const libFiles = require("glob").sync("**/*.ts", { cwd: libDir });
const lib = {};
libFiles.forEach(file => lib["~lib/" + file.replace(/\.ts$/, "")] = bundleFile(path.join(libDir, file)));
libFiles.forEach(file => lib[file.replace(/\.ts$/, "")] = bundleFile(path.join(libDir, file)));
return lib;
})(),
BUNDLE_DEFINITIONS: {