move stuff, run both untouched and optimized

This commit is contained in:
dcode
2019-05-21 15:02:39 +02:00
parent 7128d190a5
commit c92643832c
49 changed files with 34520 additions and 43738 deletions

View File

@ -5,7 +5,8 @@
import {
Compiler,
ContextualFlags
ContextualFlags,
RuntimeFeatures
} from "./compiler";
import {
@ -141,6 +142,7 @@ export namespace BuiltinSymbols {
export const call_direct = "~lib/builtins/call_direct";
export const call_indirect = "~lib/builtins/call_indirect";
export const instantiate = "~lib/builtins/instantiate";
export const idof = "~lib/builtins/idof";
export const i8 = "~lib/builtins/i8";
export const i16 = "~lib/builtins/i16";
@ -464,11 +466,10 @@ export namespace BuiltinSymbols {
export const v8x16_shuffle = "~lib/builtins/v8x16.shuffle";
// internals
export const HEAP_BASE = "~lib/builtins/HEAP_BASE";
export const RTTI_BASE = "~lib/builtins/RTTI_BASE";
export const idof = "~lib/builtins/idof";
export const visit_globals = "~lib/builtins/__visit_globals";
export const visit_members = "~lib/builtins/__visit_members";
export const HEAP_BASE = "~lib/heap/HEAP_BASE";
export const RTTI_BASE = "~lib/rt/RTTI_BASE";
export const visit_globals = "~lib/rt/__visit_globals";
export const visit_members = "~lib/rt/__visit_members";
// std/diagnostics.ts
export const ERROR = "~lib/diagnostics/ERROR";
@ -3557,7 +3558,7 @@ export function compileCall(
return module.createUnreachable();
}
let arg0 = compiler.compileExpression(operands[0], Type.u32, ContextualFlags.IMPLICIT);
compiler.needsVisitGlobals = true;
compiler.runtimeFeatures |= RuntimeFeatures.visitGlobals;
compiler.currentType = Type.void;
return module.createCall(BuiltinSymbols.visit_globals, [ arg0 ], NativeType.None);
}
@ -3571,10 +3572,123 @@ export function compileCall(
}
let arg0 = compiler.compileExpression(operands[0], compiler.options.usizeType, ContextualFlags.IMPLICIT);
let arg1 = compiler.compileExpression(operands[1], Type.u32, ContextualFlags.IMPLICIT);
compiler.needsVisitMembers = true;
compiler.runtimeFeatures |= RuntimeFeatures.visitMembers;
compiler.currentType = Type.void;
return module.createCall(BuiltinSymbols.visit_members, [ arg0, arg1 ], NativeType.None);
}
// The following simply intercept the respective runtime calls in order to force
// compilation of runtime functionality to the bottom of generated binaries.
case compiler.program.visitInstance.internalName: {
if (
checkTypeAbsent(typeArguments, reportNode, prototype) |
checkArgsRequired(operands, 2, reportNode, compiler) // ref, cookie
) {
compiler.currentType = Type.void;
return module.createUnreachable();
}
let arg0 = compiler.compileExpression(operands[0], compiler.options.usizeType, ContextualFlags.IMPLICIT);
let arg1 = compiler.compileExpression(operands[1], Type.u32, ContextualFlags.IMPLICIT);
compiler.runtimeFeatures |= RuntimeFeatures.visit;
compiler.currentType = Type.void;
return module.createCall(compiler.program.visitInstance.internalName, [ arg0, arg1 ], NativeType.None);
}
case compiler.program.retainInstance.internalName: {
let usizeType = compiler.options.usizeType;
if (
checkTypeAbsent(typeArguments, reportNode, prototype) |
checkArgsRequired(operands, 1, reportNode, compiler) // ref
) {
compiler.currentType = usizeType;
return module.createUnreachable();
}
let arg0 = compiler.compileExpression(operands[0], usizeType, ContextualFlags.IMPLICIT);
compiler.runtimeFeatures |= RuntimeFeatures.retain;
compiler.currentType = usizeType;
return module.createCall(compiler.program.retainInstance.internalName, [ arg0 ], compiler.options.nativeSizeType);
}
case compiler.program.retainReleaseInstance.internalName: {
let usizeType = compiler.options.usizeType;
if (
checkTypeAbsent(typeArguments, reportNode, prototype) |
checkArgsRequired(operands, 2, reportNode, compiler) // newRef, oldRef
) {
compiler.currentType = usizeType;
return module.createUnreachable();
}
let arg0 = compiler.compileExpression(operands[0], usizeType, ContextualFlags.IMPLICIT);
let arg1 = compiler.compileExpression(operands[1], usizeType, ContextualFlags.IMPLICIT);
compiler.runtimeFeatures |= RuntimeFeatures.retainRelease;
compiler.currentType = usizeType;
return module.createCall(compiler.program.retainReleaseInstance.internalName, [ arg0, arg1 ], compiler.options.nativeSizeType);
}
case compiler.program.releaseInstance.internalName: {
if (
checkTypeAbsent(typeArguments, reportNode, prototype) |
checkArgsRequired(operands, 1, reportNode, compiler) // ref
) {
compiler.currentType = Type.void;
return module.createUnreachable();
}
let arg0 = compiler.compileExpression(operands[0], compiler.options.usizeType, ContextualFlags.IMPLICIT);
compiler.runtimeFeatures |= RuntimeFeatures.release;
compiler.currentType = Type.void;
return module.createCall(compiler.program.releaseInstance.internalName, [ arg0 ], NativeType.None);
}
case compiler.program.allocInstance.internalName: {
let usizeType = compiler.options.usizeType;
if (
checkTypeAbsent(typeArguments, reportNode, prototype) |
checkArgsRequired(operands, 2, reportNode, compiler) // size, id
) {
compiler.currentType = usizeType;
return module.createUnreachable();
}
let arg0 = compiler.compileExpression(operands[0], usizeType, ContextualFlags.IMPLICIT);
let arg1 = compiler.compileExpression(operands[1], Type.u32, ContextualFlags.IMPLICIT);
compiler.runtimeFeatures |= RuntimeFeatures.alloc;
compiler.currentType = usizeType;
return module.createCall(compiler.program.allocInstance.internalName, [ arg0, arg1 ], compiler.options.nativeSizeType);
}
case compiler.program.reallocInstance.internalName: {
let usizeType = compiler.options.usizeType;
if (
checkTypeAbsent(typeArguments, reportNode, prototype) |
checkArgsRequired(operands, 2, reportNode, compiler) // ref, size
) {
compiler.currentType = usizeType;
return module.createUnreachable();
}
let arg0 = compiler.compileExpression(operands[0], usizeType, ContextualFlags.IMPLICIT);
let arg1 = compiler.compileExpression(operands[1], usizeType, ContextualFlags.IMPLICIT);
compiler.runtimeFeatures |= RuntimeFeatures.realloc;
compiler.currentType = usizeType;
return module.createCall(compiler.program.reallocInstance.internalName, [ arg0, arg1 ], compiler.options.nativeSizeType);
}
case compiler.program.freeInstance.internalName: {
if (
checkTypeAbsent(typeArguments, reportNode, prototype) |
checkArgsRequired(operands, 1, reportNode, compiler) // ref
) {
compiler.currentType = Type.void;
return module.createUnreachable();
}
let arg0 = compiler.compileExpression(operands[0], compiler.options.usizeType, ContextualFlags.IMPLICIT);
compiler.runtimeFeatures |= RuntimeFeatures.free;
compiler.currentType = Type.void;
return module.createCall(compiler.program.freeInstance.internalName, [ arg0 ], NativeType.None);
}
case compiler.program.collectInstance.internalName: {
if (
checkTypeAbsent(typeArguments, reportNode, prototype) |
checkArgsRequired(operands, 0, reportNode, compiler)
) {
compiler.currentType = Type.void;
return module.createUnreachable();
}
compiler.runtimeFeatures |= RuntimeFeatures.collect;
compiler.currentType = Type.void;
return module.createCall(compiler.program.collectInstance.internalName, null, NativeType.None);
}
}
// try to defer inline asm to a concrete built-in

View File

@ -250,6 +250,35 @@ export const enum ContextualFlags {
STATIC_CAPABLE = 1 << 6
}
/** Runtime features to be activated by the compiler. */
export const enum RuntimeFeatures {
NONE = 0,
/** Requires HEAP_BASE and heap setup. */
HEAP = 1 << 0,
/** Requires RTTI_BASE and RTTI setup. */
RTTI = 1 << 1,
/** Requires the alloc function. */
alloc = 1 << 2,
/** Requires the realloc function. */
realloc = 1 << 3,
/** Requires the free function. */
free = 1 << 4,
/** Requires the retain function. */
retain = 1 << 5,
/** Requires the retainRelease functino. */
retainRelease = 1 << 6,
/** Requires the release function. */
release = 1 << 7,
/** Requires the collect function. */
collect = 1 << 8,
/** Requires the visit function. */
visit = 1 << 9,
/** Requires the built-in globals visitor. */
visitGlobals = 1 << 10,
/** Requires the built-in members visitor. */
visitMembers = 1 << 11
}
/** Compiler interface. */
export class Compiler extends DiagnosticEmitter {
@ -283,22 +312,8 @@ export class Compiler extends DiagnosticEmitter {
argcVar: GlobalRef = 0;
/** Argument count helper setter. */
argcSet: FunctionRef = 0;
/** Whether HEAP_BASE is required. */
needsHeap: bool = false;
/** Indicates whether the __visit_globals function must be generated. */
needsVisitGlobals: bool = false;
/** Indicated whether the __visit_members function must be generated. */
needsVisitMembers: bool = false;
/** Whether RTTI is required. */
needsRTTI: bool = false;
/** Whether the alloc function is required. */
needsAlloc: bool = false;
/** Whether the retain function is required. */
needsRetain: bool = false;
/** Whether the retainRelease function is required. */
needsRetainRelease: bool = false;
/** Whether the release function is required. */
needsRelease: bool = false;
/** Requires runtime features. */
runtimeFeatures: RuntimeFeatures = RuntimeFeatures.NONE;
/** Expressions known to have skipped an autorelease. Usually function returns. */
skippedAutoreleases: Set<ExpressionRef> = new Set();
@ -347,7 +362,7 @@ export class Compiler extends DiagnosticEmitter {
this.currentFlow = startFunctionInstance.flow;
this.currentBody = startFunctionBody;
// add a mutable heap base dummy
// add a mutable heap and rtti base dummies
if (options.isWasm64) {
module.addGlobal(BuiltinSymbols.HEAP_BASE, NativeType.I64, true, module.createI64(0));
module.addGlobal(BuiltinSymbols.RTTI_BASE, NativeType.I64, true, module.createI64(0));
@ -383,26 +398,28 @@ export class Compiler extends DiagnosticEmitter {
if (!explicitStartFunction) module.setStart(funcRef);
}
// compile gc features if utilized. has two uses: first, whenever the compiler
// uses these, all it has to do is set a flag to true. second, when inspecting
// generated WATs, it's quite useful that these functions come last.
if (this.needsAlloc) this.compileFunction(program.allocInstance);
if (this.needsRetain) this.compileFunction(program.retainInstance);
if (this.needsRetainRelease) this.compileFunction(program.retainReleaseInstance);
if (this.needsRelease) this.compileFunction(program.releaseInstance);
if (this.needsVisitGlobals) compileVisitGlobals(this);
if (this.needsVisitMembers) compileVisitMembers(this); // called by release
// compile runtime implementation (after actual code). note that these may modify features and order is important.
if (this.runtimeFeatures & RuntimeFeatures.visit) this.compileFunction(program.visitInstance);
if (this.runtimeFeatures & RuntimeFeatures.retain) this.compileFunction(program.retainInstance);
if (this.runtimeFeatures & RuntimeFeatures.retainRelease) this.compileFunction(program.retainReleaseInstance);
if (this.runtimeFeatures & RuntimeFeatures.release) this.compileFunction(program.releaseInstance);
if (this.runtimeFeatures & RuntimeFeatures.collect) this.compileFunction(program.collectInstance);
if (this.runtimeFeatures & RuntimeFeatures.visitGlobals) compileVisitGlobals(this);
if (this.runtimeFeatures & RuntimeFeatures.visitMembers) compileVisitMembers(this); // called by release
if (this.runtimeFeatures & RuntimeFeatures.realloc) this.compileFunction(program.reallocInstance);
if (this.runtimeFeatures & RuntimeFeatures.alloc) this.compileFunction(program.allocInstance);
if (this.runtimeFeatures & RuntimeFeatures.free) this.compileFunction(program.freeInstance);
// compile runtime type information
module.removeGlobal(BuiltinSymbols.RTTI_BASE);
if (this.needsRTTI) compileRTTI(this);
if (this.runtimeFeatures & RuntimeFeatures.RTTI) compileRTTI(this);
// update the heap base pointer
var memoryOffset = this.memoryOffset;
memoryOffset = i64_align(memoryOffset, options.usizeType.byteSize);
this.memoryOffset = memoryOffset;
module.removeGlobal(BuiltinSymbols.HEAP_BASE);
if (this.needsHeap) {
if (this.runtimeFeatures & RuntimeFeatures.HEAP) {
if (options.isWasm64) {
module.addGlobal(
BuiltinSymbols.HEAP_BASE,
@ -833,8 +850,8 @@ export class Compiler extends DiagnosticEmitter {
// ambient builtins like 'HEAP_BASE' need to be resolved but are added explicitly
if (global.is(CommonFlags.AMBIENT) && global.hasDecorator(DecoratorFlags.BUILTIN)) {
if (global.internalName == BuiltinSymbols.HEAP_BASE) this.needsHeap = true;
else if (global.internalName == BuiltinSymbols.RTTI_BASE) this.needsRTTI = true;
if (global.internalName == BuiltinSymbols.HEAP_BASE) this.runtimeFeatures |= RuntimeFeatures.HEAP;
else if (global.internalName == BuiltinSymbols.RTTI_BASE) this.runtimeFeatures |= RuntimeFeatures.RTTI;
return true;
}
@ -2333,6 +2350,7 @@ export class Compiler extends DiagnosticEmitter {
}
// Switch back to the parent flow
if (!innerFlow.isAny(FlowFlags.ANY_TERMINATING)) this.performAutoreleases(innerFlow, stmts);
innerFlow.unset(
FlowFlags.BREAKS |
FlowFlags.CONDITIONALLY_BREAKS
@ -6524,19 +6542,19 @@ export class Compiler extends DiagnosticEmitter {
/** Makes retain call, retaining the expression's value. */
makeRetain(expr: ExpressionRef): ExpressionRef {
this.needsRetain = true;
this.runtimeFeatures |= RuntimeFeatures.retain;
return this.module.createCall(this.program.retainInstance.internalName, [ expr ], this.options.nativeSizeType);
}
/** Makes a retainRelease call, retaining the new expression's value and releasing the old expression's value. */
makeRetainRelease(exprNew: ExpressionRef, exprOld: ExpressionRef): ExpressionRef {
this.needsRetainRelease = true;
this.runtimeFeatures |= RuntimeFeatures.retainRelease;
return this.module.createCall(this.program.retainReleaseInstance.internalName, [ exprNew, exprOld ], this.options.nativeSizeType);
}
/** Makes a release call, releasing the expression's value. Changes the current type to void.*/
makeRelease(expr: ExpressionRef): ExpressionRef {
this.needsRelease = true;
this.runtimeFeatures |= RuntimeFeatures.release;
return this.module.createCall(this.program.releaseInstance.internalName, [ expr ], NativeType.None);
}
@ -8846,7 +8864,7 @@ export class Compiler extends DiagnosticEmitter {
var module = this.module;
var options = this.options;
this.currentType = classInstance.type;
this.needsAlloc = true;
this.runtimeFeatures |= RuntimeFeatures.alloc;
return module.createCall(program.allocInstance.internalName, [
options.isWasm64
? module.createI64(classInstance.currentMemoryOffset)

View File

@ -280,8 +280,8 @@ export abstract class DiagnosticEmitter {
var message = DiagnosticMessage.create(code, category, arg0, arg1, arg2).withRange(range);
if (relatedRange) message.relatedRange = relatedRange;
this.diagnostics.push(message);
// console.log(formatDiagnosticMessage(message, true, true) + "\n"); // temporary
// console.log(<string>new Error("stack").stack);
console.log(formatDiagnosticMessage(message, true, true) + "\n"); // temporary
console.log(<string>new Error("stack").stack);
}
/** Emits an informatory diagnostic message. */

View File

@ -1042,13 +1042,13 @@ export class Program extends DiagnosticEmitter {
let flag = decoratorKindToFlag(kind);
if (flag) {
if (flag == DecoratorFlags.BUILTIN) {
if (decorator.range.source.isLibrary) {
flags |= flag;
} else {
if (!(acceptedFlags & flag) && !decorator.range.source.isLibrary) {
this.error(
DiagnosticCode.Decorator_0_is_not_valid_here,
decorator.range, decorator.name.range.toString()
);
} else {
flags |= flag;
}
} else if (!(acceptedFlags & flag)) {
this.error(
@ -1562,7 +1562,7 @@ export class Program extends DiagnosticEmitter {
parent: Element
): void {
var name = declaration.name.text;
var validDecorators = DecoratorFlags.UNSAFE;
var validDecorators = DecoratorFlags.UNSAFE | DecoratorFlags.BUILTIN;
if (declaration.is(CommonFlags.AMBIENT)) {
validDecorators |= DecoratorFlags.EXTERNAL;
} else {

View File

@ -152,6 +152,10 @@ export declare function alignof<T>(): usize; // | u32 / u64
@builtin
export declare function offsetof<T>(fieldName?: string): usize; // | u32 / u64
// @ts-ignore: decorator
@builtin
export declare function idof<T>(): u32;
// @ts-ignore: decorator
@builtin
export declare function select<T>(ifTrue: T, ifFalse: T, condition: bool): T;
@ -1708,18 +1712,6 @@ export namespace v8x16 {
): v128;
}
// @ts-ignore: decorator
@builtin
export declare function ERROR(message?: string): void;
// @ts-ignore: decorator
@builtin
export declare function WARNING(message?: string): void;
// @ts-ignore: decorator
@builtin
export declare function INFO(message?: string): void;
// @ts-ignore: decorator
@external("env", "abort")
declare function abort(
@ -1740,23 +1732,3 @@ declare function trace(
a3?: f64,
a4?: f64
): void;
// @ts-ignore: decorator
@builtin
export declare const HEAP_BASE: usize;
// @ts-ignore: decorator
@builtin
export declare const RTTI_BASE: usize;
// @ts-ignore: decorator
@builtin
export declare function idof<T>(): u32;
// @ts-ignore: decorator
@builtin @unsafe
export declare function __visit_globals(cookie: u32): void;
// @ts-ignore: decorator
@builtin @unsafe
export declare function __visit_members(ref: usize, cookie: u32): void;

View File

@ -0,0 +1,11 @@
// @ts-ignore: decorator
@builtin
export declare function ERROR(message?: string): void;
// @ts-ignore: decorator
@builtin
export declare function WARNING(message?: string): void;
// @ts-ignore: decorator
@builtin
export declare function INFO(message?: string): void;

3
std/assembly/heap.ts Normal file
View File

@ -0,0 +1,3 @@
// @ts-ignore: decorator
@builtin
export declare const HEAP_BASE: usize;

84
std/assembly/rt.ts Normal file
View File

@ -0,0 +1,84 @@
import { idof } from "./builtins";
import { RTTIData, RTTIFlags } from "./common/rtti";
import { E_INDEXOUTOFRANGE } from "./util/error";
import { BLOCK, BLOCK_OVERHEAD } from "./rt/common";
import { ArrayBufferView } from "./arraybuffer";
// @ts-ignore: decorator
@builtin
export declare const RTTI_BASE: usize;
// @ts-ignore: decorator
@builtin @unsafe
export declare function __visit_globals(cookie: u32): void;
// @ts-ignore: decorator
@builtin @unsafe
export declare function __visit_members(ref: usize, cookie: u32): void;
// @ts-ignore: decorator
@unsafe
export function __typeinfo(id: u32): RTTIFlags {
var ptr = RTTI_BASE;
if (!id || id > load<u32>(ptr)) throw new Error(E_INDEXOUTOFRANGE);
return changetype<RTTIData>(ptr + id * offsetof<RTTIData>()).flags;
}
// @ts-ignore: decorator
@unsafe
export function __instanceof(ref: usize, superId: u32): bool { // keyword
var id = changetype<BLOCK>(ref - BLOCK_OVERHEAD).rtId;
var ptr = RTTI_BASE;
if (id && id <= load<u32>(ptr)) {
do if (id == superId) return true;
while (id = changetype<RTTIData>(ptr + id * offsetof<RTTIData>()).base);
}
return false;
}
// @ts-ignore: decorator
@unsafe
export function __allocArray(length: i32, alignLog2: usize, id: u32, data: usize = 0): usize {
var array = __alloc(offsetof<i32[]>(), id);
var bufferSize = <usize>length << alignLog2;
var buffer = __alloc(bufferSize, idof<ArrayBuffer>());
store<usize>(array, __retain(buffer), offsetof<ArrayBufferView>("data"));
changetype<ArrayBufferView>(array).dataStart = buffer;
changetype<ArrayBufferView>(array).dataLength = bufferSize;
store<i32>(changetype<usize>(array), length, offsetof<i32[]>("length_"));
if (data) memory.copy(buffer, data, bufferSize);
return array;
}
// These are provided by the respective implementation, included as another entry file by asc:
// @builtin @unsafe
// export declare function __alloc(size: usize, id: u32): usize;
// // @ts-ignore: decorator
// @builtin @unsafe
// export declare function __realloc(ref: usize, size: usize): usize;
// // @ts-ignore: decorator
// @builtin @unsafe
// export declare function __free(ref: usize): void;
// // @ts-ignore: decorator
// @builtin @unsafe
// export declare function __retain(ref: usize): usize;
// // @ts-ignore: decorator
// @builtin @unsafe
// export declare function __retainRelease(ref: usize, oldRef: usize): usize;
// // @ts-ignore: decorator
// @builtin @unsafe
// export declare function __release(ref: usize): void;
// // @ts-ignore: decorator
// @builtin @unsafe
// export declare function __collect(): void;
// // @ts-ignore: decorator
// @builtin @unsafe
// export declare function __visit(ref: usize, cookie: u32): void;

View File

@ -17,10 +17,10 @@ Interface
Frees a dynamically allocated chunk of memory by its address.
* **__retain**(ref: `usize`): `usize`<br />
Retains a reference to an instance of a reference type. The instance doesn't become collected as long as there's at least one retained reference. Returns the retained reference.
Retains a reference to an object. The object doesn't become collected as long as there's at least one retained reference. Returns the retained reference.
* **__release**(ref: `usize`): `void`<br />
Releases a reference to an instance of a reference type. The instance is considered for collection once all references to it have been released.
Releases a reference to an object. The object is considered for collection once all references to it have been released.
* **__collect**(): `void`<br />
Forces a full garbage collection cycle. By default this means that reference cycles are resolved and possibly collected.
@ -28,7 +28,7 @@ Interface
### Internals
* **__retainRelease**(newRef: `usize`, oldRef: `usize`): `usize`<br />
Retains a reference to an instance of a reference type while releasing the reference it replaces. Returns the retained reference.
Retains a reference to an object type while releasing the reference it replaces. Returns the retained reference.
* **__visit**(ref: `usize`, cookie: `u32`): `void`<br />
Concrete visitor implementation called during traversal. Cookie can be used to indicate one of multiple operations.
@ -36,13 +36,13 @@ Interface
### Built-ins
* **__typeinfo**(id: `u32`): `RTTIFlags`<br />
Obtains the runtime type information for objects with the specified runtime id. Runtime type information is a set of flags indicating whether a reference type is managed, an array or similar, and what the relevant alignments when creating an instance are etc.
Obtains the runtime type information for objects with the specified runtime id. Runtime type information is a set of flags indicating whether a reference type is managed, an array or similar, and what the relevant alignments when creating an instance externally are etc.
* **__visit_globals**(cookie: `u32`): `void`<br />
Calls `__visit` on each global that is of a reference type. Not used anymore (originally provided to support tracing GCs) but still here for possible future use.
* **__visit_members**(ref: `usize`, cookie: `u32`): `void`<br />
Calls `__visit` on each member of the instance pointed to by `ref` that is of a reference type.
Calls `__visit` on each member of the object pointed to by `ref`.
Full/half
---------
@ -57,7 +57,7 @@ The [stub](./index-stub.ts) runtime, though fully functional, provides minimal d
Integration notes
-----------------
The underlying reference counting implementation works very similar to other implementations. When an object is stored in a local, global or field, its reference becomes retained (reference count is incremented by 1), respectively when it becomes deleted, it is released (reference count is decremented by 1). Once the reference count reaches zero, the object is considered for collection. Now, if an object is inherently acyclic (most objects are), it is free'd right away, while otherwise it is added to a cycle pool and considered for cycle collection on the next `__collect`.
The underlying reference counting implementation works very similar to other implementations. When an object is stored in a local, global or field, its reference becomes retained (reference count is incremented by 1), respectively when it becomes deleted, it is released (reference count is decremented by 1). Once the reference count reaches zero, the object is considered for collection and the reference count of all contained objects (fields, array elements etc.) is decremented by 1. Now, if an object is inherently acyclic (most objects are), it is free'd right away, while otherwise it is added to a cycle pool and considered for cycle collection on the next `__collect`.
Differences to other implementations include:
@ -68,20 +68,19 @@ Differences to other implementations include:
Even though the rules are simple, working with the runtime internals within standard library code can be tricky and requires knowledge of where the compiler will insert runtime calls automatically. For instance, when `changetype`ing a pointer to a reference type or vice-versa, the typechange is performed with no side effects. Means: No retains or releases are inserted and the user has to take care of the implications.
GOOD: In case of doubt, the following pattern is universal:
**GOOD:** In case of doubt, the following pattern is universal:
```ts
var ref = changetype<Ref>(__alloc(SIZE, idof<Ref>())); // retains the object in `ref`
// here, the __retain is inserted by the assignment to ref, not by changetype or __alloc
...
return ref; // knows `ref` is already retained and simply returns it
```
BAD: One common pattern one shouldn't use is:
**BAD:** A pattern one shouldn't use is:
```ts
someFunc(changetype<Ref>(__alloc(SIZE, idof<Ref>()))); // might free the object before the call returns
```
You know the drill.
BONUS: Beware of runtime calls in conditional expressions like a ternary IF, logical AND or OR. Each arm can be in either of two states (either in-flight if immediately retained/returned or not if the expression or the target doesn't support it). Don't fight the compiler there.
**BONUS:** Beware of runtime calls in conditional expressions like a ternary IF, logical AND or OR. Each arm can be in either of two states (either in-flight if immediately retained/returned or not if the expression or the target doesn't support it). Don't fight the compiler there.

View File

@ -41,48 +41,3 @@
// @ts-ignore: decorator
@inline export const BLOCK_MAXSIZE: usize = (1 << 30) - BLOCK_OVERHEAD;
/////////////////////////////////// Type information interface ////////////////////////////////////
import { RTTI_BASE } from "builtins";
import { RTTIData, RTTIFlags } from "common/rtti";
import { E_INDEXOUTOFRANGE } from "../util/error";
// @ts-ignore: decorator
@unsafe @global
export function __typeinfo(id: u32): RTTIFlags {
var ptr = RTTI_BASE;
if (!id || id > load<u32>(ptr)) throw new Error(E_INDEXOUTOFRANGE);
return changetype<RTTIData>(ptr + id * offsetof<RTTIData>()).flags;
}
// @ts-ignore: decorator
@unsafe @global
export function __instanceof(ref: usize, superId: u32): bool { // keyword
var id = changetype<BLOCK>(ref - BLOCK_OVERHEAD).rtId;
var ptr = RTTI_BASE;
if (id && id <= load<u32>(ptr)) {
do if (id == superId) return true;
while (id = changetype<RTTIData>(ptr + id * offsetof<RTTIData>()).base);
}
return false;
}
///////////////////////////////////////////// Helpers /////////////////////////////////////////////
import { idof } from "builtins";
import { ArrayBufferView } from "arraybuffer";
// @ts-ignore: decorator
@unsafe @global
export function __allocArray(length: i32, alignLog2: usize, id: u32, data: usize = 0): usize {
var array = __alloc(offsetof<i32[]>(), id);
var bufferSize = <usize>length << alignLog2;
var buffer = __alloc(bufferSize, idof<ArrayBuffer>());
store<usize>(array, __retain(buffer), offsetof<ArrayBufferView>("data"));
changetype<ArrayBufferView>(array).dataStart = buffer;
changetype<ArrayBufferView>(array).dataLength = bufferSize;
store<i32>(changetype<usize>(array), length, offsetof<i32[]>("length_"));
if (data) memory.copy(buffer, data, bufferSize);
return array;
}

View File

@ -1,3 +1,3 @@
export { __alloc, __realloc, __free } from "rt/tlsf";
export { __retain, __release, __collect } from "rt/purerc";
export { __instanceof, __typeinfo } from "rt/common";
export { __retain, __release, __collect } from "rt/pure";
export { __instanceof, __typeinfo } from "rt";

View File

@ -1,2 +1,2 @@
export { __alloc, __realloc, __free, __retain, __release, __collect } from "rt/stub";
export { __instanceof, __typeinfo } from "rt/common";
export { __instanceof, __typeinfo } from "rt";

View File

@ -61,7 +61,7 @@ import { RTTIFlags } from "common/rtti";
@inline const VISIT_COLLECTWHITE = 5;
// @ts-ignore: decorator
@global
@global @unsafe @builtin
function __visit(ref: usize, cookie: i32): void {
if (ref < HEAP_BASE) return;
var s = changetype<Block>(ref - BLOCK_OVERHEAD);
@ -243,20 +243,20 @@ function collectWhite(s: Block): void {
}
// @ts-ignore: decorator
@global @unsafe
@global @unsafe @builtin
export function __retain(ref: usize): usize {
if (ref > HEAP_BASE) increment(changetype<Block>(ref - BLOCK_OVERHEAD));
return ref;
}
// @ts-ignore: decorator
@global @unsafe
@global @unsafe @builtin
export function __release(ref: usize): void {
if (ref > HEAP_BASE) decrement(changetype<Block>(ref - BLOCK_OVERHEAD));
}
// @ts-ignore: decorator
@global @unsafe
@global @unsafe @builtin
export function __retainRelease(ref: usize, oldRef: usize): usize {
if (ref != oldRef) {
let heapBase = HEAP_BASE;

View File

@ -9,7 +9,7 @@ var startOffset: usize = (HEAP_BASE + AL_MASK) & ~AL_MASK;
var offset: usize = startOffset;
// @ts-ignore: decorator
@unsafe @global
@unsafe @global @builtin
export function __alloc(size: usize, id: u32): usize {
if (size > BLOCK_MAXSIZE) unreachable();
var ptr = offset + BLOCK_OVERHEAD;
@ -30,7 +30,7 @@ export function __alloc(size: usize, id: u32): usize {
}
// @ts-ignore: decorator
@unsafe @global
@unsafe @global @builtin
export function __realloc(ref: usize, size: usize): usize {
var block = changetype<BLOCK>(ref - BLOCK_OVERHEAD);
var oldSize = <usize>block.rtSize;
@ -45,7 +45,7 @@ export function __realloc(ref: usize, size: usize): usize {
}
// @ts-ignore: decorator
@unsafe @global
@unsafe @global @builtin
export function __free(ref: usize): void {
}
@ -56,28 +56,28 @@ export function __free(ref: usize): void {
// }
// @ts-ignore: decorator
@global @unsafe
@global @unsafe @builtin
export function __retain(ref: usize): usize {
return ref;
}
// @ts-ignore: decorator
@global @unsafe
@global @unsafe @builtin
export function __release(ref: usize): void {
}
// @ts-ignore: decorator
@global @unsafe
function __visit(ref: usize, cookie: u32): void {
@global @unsafe @builtin
export function __visit(ref: usize, cookie: u32): void {
}
// @ts-ignore: decorator
@global @unsafe
function __retainRelease(ref: usize, oldRef: usize): usize {
@global @unsafe @builtin
export function __retainRelease(ref: usize, oldRef: usize): usize {
return ref;
}
// @ts-ignore: decorator
@global @unsafe
@global @unsafe @builtin
export function __collect(): void {
}

View File

@ -534,7 +534,7 @@ export function freeBlock(root: Root, block: Block): void {
}
// @ts-ignore: decorator
@global @unsafe
@global @unsafe @builtin
export function __alloc(size: usize, id: u32): usize {
var root = ROOT;
if (!root) {
@ -547,7 +547,7 @@ export function __alloc(size: usize, id: u32): usize {
}
// @ts-ignore: decorator
@global @unsafe
@global @unsafe @builtin
export function __realloc(ref: usize, size: usize): usize {
if (DEBUG) assert(ROOT); // must be initialized
assert(ref != 0 && !(ref & AL_MASK)); // must exist and be aligned
@ -555,7 +555,7 @@ export function __realloc(ref: usize, size: usize): usize {
}
// @ts-ignore: decorator
@global @unsafe
@global @unsafe @builtin
export function __free(ref: usize): void {
if (DEBUG) assert(ROOT); // must be initialized
assert(ref != 0 && !(ref & AL_MASK)); // must exist and be aligned

1
tests/.gitignore vendored
View File

@ -1,2 +1,3 @@
*.wasm
*.wasm.map
temp.*

View File

@ -152,6 +152,8 @@ tests.forEach(filename => {
Array.prototype.push.apply(cmd, asc_flags);
if (args.createBinary)
cmd.push("--binaryFile", basename + ".untouched.wasm");
else
cmd.push("--binaryFile", "temp.wasm");
asc.main(cmd, {
stdout: stdout,
stderr: stderr
@ -212,7 +214,7 @@ tests.forEach(filename => {
"--validate",
"--measure",
"--binaryFile", // -> stdout
// "-O3"
"-O3"
];
if (asc_flags)
Array.prototype.push.apply(cmd, asc_flags);
@ -229,127 +231,18 @@ tests.forEach(filename => {
failedTests.push(basename);
return 1;
}
// Instantiate
try {
let memory = new WebAssembly.Memory({ initial: 10 });
let exports = {};
function getString(ptr) {
const RUNTIME_HEADER_SIZE = 16;
if (!ptr) return "null";
var U32 = new Uint32Array(exports.memory ? exports.memory.buffer : memory.buffer);
var U16 = new Uint16Array(exports.memory ? exports.memory.buffer : memory.buffer);
var len16 = U32[(ptr - RUNTIME_HEADER_SIZE + 12) >>> 2] >>> 1;
var ptr16 = ptr >>> 1;
return String.fromCharCode.apply(String, U16.subarray(ptr16, ptr16 + len16));
}
var binaryBuffer = stdout.toBuffer();
if (args.createBinary)
fs.writeFileSync(path.join(basedir, basename + ".optimized.wasm"), binaryBuffer);
let rtrace = new Map();
let rtraceEnabled = false;
let rtraceRetains = 0;
let rtraceReleases = 0;
let rtraceFrees = 0;
let rtraceUsesAfterFree = 0;
let runTime = asc.measure(() => {
exports = new WebAssembly.Instance(new WebAssembly.Module(binaryBuffer), {
env: {
memory,
abort: function(msg, file, line, column) {
console.log(colorsUtil.red(" abort: " + getString(msg) + " at " + getString(file) + ":" + line + ":" + column));
},
trace: function(msg, n) {
console.log(" trace: " + getString(msg) + (n ? " " : "") + Array.prototype.slice.call(arguments, 2, 2 + n).join(", "));
},
externalFunction: function() { },
externalConstant: 1
},
math: {
mod: function(a, b) { return a % b; }
},
Math,
Date,
// tests/declare
declare: {
externalFunction: function() { },
externalConstant: 1,
"my.externalFunction": function() { },
"my.externalConstant": 2
},
// tests/external
external: {
foo: function() {},
"foo.bar": function() {},
bar: function() {}
},
foo: {
baz: function() {},
"var": 3
},
// runtime tracing
rtrace: {
retain: function(s) {
++rtraceRetains;
let rc = rtrace.get(s) | 0;
rtrace.set(s, ++rc);
// console.log(" retain(" + s + ", RC=" + rc + ")");
rtraceEnabled = true;
},
release: function(s) {
++rtraceReleases;
let rc = rtrace.get(s) | 0;
if (--rc <= 0) {
rtrace.delete(s);
if (rc < 0) {
++rtraceUsesAfterFree;
console.log(" USEAFTERFREE(" + s + ", RC=" + rc + ")");
}
} else rtrace.set(s, rc);
// console.log(" release(" + s + ", RC=" + rc + ")");
rtraceEnabled = true;
},
free: function(s) {
++rtraceFrees;
let rc = rtrace.get(s) | 0;
// if (rc != 0) console.log(" free(" + s + ", RC=" + rc + ")");
rtrace.delete(s);
rtraceEnabled = true;
}
}
}).exports;
if (exports.main) {
console.log(colorsUtil.white(" [main]"));
var code = exports.main();
console.log(colorsUtil.white(" [exit " + code + "]\n"));
}
if (rtraceEnabled) {
console.log("- " + "rtrace: " + rtraceRetains + " retains, " + rtraceReleases + " releases, " + rtraceFrees + " explicit frees");
if (rtrace.size || rtraceUsesAfterFree) {
let msg = "memory leak detected: " + rtrace.size + " leaking, " + rtraceUsesAfterFree + " uses after free";
console.log(" " + colorsUtil.red("ERROR: ") + msg);
failed = true;
failedMessages.set(basename, msg);
}
console.log();
}
});
console.log("- " + colorsUtil.green("instantiate OK") + " (" + asc.formatTime(runTime) + ")");
console.log("\n " + Object.keys(exports).map(key => {
return "[" + (typeof exports[key]).substring(0, 3) + "] " + key + " = " + exports[key]
}).join("\n "));
} catch (e) {
console.log("- " + colorsUtil.red("instantiate ERROR: ") + e.stack);
let untouchedBuffer = fs.readFileSync(path.join(basedir, "temp.wasm"));
let optimizedBuffer = stdout.toBuffer();
if (!testInstantiate(basename, untouchedBuffer, "untouched")) {
failed = true;
failedMessages.set(basename, e.message);
failedTests.push(basename);
} else {
console.log();
if (!testInstantiate(basename, optimizedBuffer, "optimized")) {
failed = true;
failedTests.push(basename);
}
}
if (failed) failedTests.push(basename);
console.log();
});
if (failed) return 1;
@ -377,3 +270,127 @@ if (failedTests.length) {
if (!process.exitCode) {
console.log("[ " + colorsUtil.white("OK") + " ]");
}
function testInstantiate(basename, binaryBuffer, name) {
var failed = false;
try {
let memory = new WebAssembly.Memory({ initial: 10 });
let exports = {};
function getString(ptr) {
const RUNTIME_HEADER_SIZE = 16;
if (!ptr) return "null";
var U32 = new Uint32Array(exports.memory ? exports.memory.buffer : memory.buffer);
var U16 = new Uint16Array(exports.memory ? exports.memory.buffer : memory.buffer);
var len16 = U32[(ptr - RUNTIME_HEADER_SIZE + 12) >>> 2] >>> 1;
var ptr16 = ptr >>> 1;
return String.fromCharCode.apply(String, U16.subarray(ptr16, ptr16 + len16));
}
let rtrace = new Map();
let rtraceEnabled = false;
let rtraceRetains = 0;
let rtraceReleases = 0;
let rtraceFrees = 0;
let rtraceUsesAfterFree = 0;
let runTime = asc.measure(() => {
exports = new WebAssembly.Instance(new WebAssembly.Module(binaryBuffer), {
env: {
memory,
abort: function(msg, file, line, column) {
console.log(colorsUtil.red(" abort: " + getString(msg) + " at " + getString(file) + ":" + line + ":" + column));
},
trace: function(msg, n) {
console.log(" trace: " + getString(msg) + (n ? " " : "") + Array.prototype.slice.call(arguments, 2, 2 + n).join(", "));
},
externalFunction: function() { },
externalConstant: 1
},
math: {
mod: function(a, b) { return a % b; }
},
Math,
Date,
// tests/declare
declare: {
externalFunction: function() { },
externalConstant: 1,
"my.externalFunction": function() { },
"my.externalConstant": 2
},
// tests/external
external: {
foo: function() {},
"foo.bar": function() {},
bar: function() {}
},
foo: {
baz: function() {},
"var": 3
},
// runtime tracing
rtrace: {
retain: function(s) {
++rtraceRetains;
let rc = rtrace.get(s) | 0;
rtrace.set(s, ++rc);
// console.log(" retain(" + s + ", RC=" + rc + ")");
rtraceEnabled = true;
},
release: function(s) {
++rtraceReleases;
let rc = rtrace.get(s) | 0;
if (--rc <= 0) {
rtrace.delete(s);
if (rc < 0) {
++rtraceUsesAfterFree;
console.log(" USEAFTERFREE(" + s + ", RC=" + rc + ")");
}
} else rtrace.set(s, rc);
// console.log(" release(" + s + ", RC=" + rc + ")");
rtraceEnabled = true;
},
free: function(s) {
++rtraceFrees;
let rc = rtrace.get(s) | 0;
// if (rc != 0) console.log(" free(" + s + ", RC=" + rc + ")");
rtrace.delete(s);
rtraceEnabled = true;
}
}
}).exports;
if (exports.main) {
console.log(colorsUtil.white(" [main]"));
var code = exports.main();
console.log(colorsUtil.white(" [exit " + code + "]\n"));
}
});
if (rtraceEnabled) {
if (rtrace.size || rtraceUsesAfterFree) {
let msg = "memory leak detected: " + rtrace.size + " leaking, " + rtraceUsesAfterFree + " uses after free";
console.log("- " + colorsUtil.red("rtrace " + name + " ERROR: ") + msg);
failed = true;
failedMessages.set(basename, msg);
}
}
if (!failed) {
console.log("- " + colorsUtil.green("instantiate " + name + " OK") + " (" + asc.formatTime(runTime) + ")");
if (rtraceEnabled) {
console.log("\n " + rtraceRetains + " retains\n " + rtraceReleases + " releases\n " + rtraceFrees + " explicit frees");
}
console.log("\n " + Object.keys(exports).map(key => {
return "[" + (typeof exports[key]).substring(0, 3) + "] " + key + " = " + exports[key]
}).join("\n "));
return true;
}
} catch (e) {
console.log("- " + colorsUtil.red("instantiate " + name + " ERROR: ") + e.stack);
failed = true;
failedMessages.set(basename, e.message);
}
return false;
}

View File

@ -3,9 +3,7 @@
(type $FUNCSIG$v (func))
(import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32)))
(memory $0 1)
(data (i32.const 8) "\n\00\00\00\01\00\00\00\10\00\00\00\n\00\00\00d\00o\00.\00t\00s\00")
(table $0 1 funcref)
(elem (i32.const 0) $null)
(data (i32.const 8) "\n\00\00\00\01\00\00\00\10\00\00\00\n\00\00\00d\00o\00.\00t\00s")
(global $do/n (mut i32) (i32.const 10))
(global $do/m (mut i32) (i32.const 0))
(global $do/o (mut i32) (i32.const 0))
@ -13,26 +11,19 @@
(start $start)
(func $start:do (; 1 ;) (type $FUNCSIG$v)
(local $0 i32)
block $break|0
loop $continue|0
block
global.get $do/n
i32.const 1
i32.sub
global.set $do/n
global.get $do/m
i32.const 1
i32.add
global.set $do/m
end
global.get $do/n
br_if $continue|0
end
loop $continue|0
global.get $do/n
i32.const 1
i32.sub
global.set $do/n
global.get $do/m
i32.const 1
i32.add
global.set $do/m
global.get $do/n
br_if $continue|0
end
global.get $do/n
i32.const 0
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
@ -43,8 +34,7 @@
end
global.get $do/m
i32.const 10
i32.eq
i32.eqz
i32.ne
if
i32.const 0
i32.const 24
@ -55,24 +45,18 @@
end
i32.const 10
global.set $do/n
block $break|1
loop $continue|1
nop
block (result i32)
global.get $do/n
local.tee $0
i32.const 1
i32.sub
global.set $do/n
local.get $0
end
br_if $continue|1
end
loop $continue|1
global.get $do/n
local.tee $0
i32.const 1
i32.sub
global.set $do/n
local.get $0
br_if $continue|1
end
global.get $do/n
i32.const -1
i32.eq
i32.eqz
i32.ne
if
i32.const 0
i32.const 24
@ -85,66 +69,51 @@
global.set $do/n
i32.const 0
global.set $do/m
block $break|2
loop $continue|2
block
global.get $do/n
i32.const 1
i32.sub
global.set $do/n
global.get $do/m
i32.const 1
i32.add
global.set $do/m
block $break|3
loop $continue|3
block
global.get $do/n
i32.const 1
i32.sub
global.set $do/n
global.get $do/o
i32.const 1
i32.add
global.set $do/o
end
global.get $do/n
br_if $continue|3
end
end
global.get $do/n
i32.const 0
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 24
i32.const 2
call $~lib/builtins/abort
unreachable
end
global.get $do/o
i32.const 9
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 25
i32.const 2
call $~lib/builtins/abort
unreachable
end
end
loop $continue|2
global.get $do/n
i32.const 1
i32.sub
global.set $do/n
global.get $do/m
i32.const 1
i32.add
global.set $do/m
loop $continue|3
global.get $do/n
br_if $continue|2
i32.const 1
i32.sub
global.set $do/n
global.get $do/o
i32.const 1
i32.add
global.set $do/o
global.get $do/n
br_if $continue|3
end
global.get $do/n
if
i32.const 0
i32.const 24
i32.const 24
i32.const 2
call $~lib/builtins/abort
unreachable
end
global.get $do/o
i32.const 9
i32.ne
if
i32.const 0
i32.const 24
i32.const 25
i32.const 2
call $~lib/builtins/abort
unreachable
end
global.get $do/n
br_if $continue|2
end
global.get $do/n
i32.const 0
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
@ -155,8 +124,7 @@
end
global.get $do/m
i32.const 1
i32.eq
i32.eqz
i32.ne
if
i32.const 0
i32.const 24
@ -167,8 +135,7 @@
end
global.get $do/o
i32.const 9
i32.eq
i32.eqz
i32.ne
if
i32.const 0
i32.const 24
@ -182,5 +149,6 @@
call $start:do
)
(func $null (; 3 ;) (type $FUNCSIG$v)
nop
)
)

View File

@ -1,9 +1,8 @@
(module
(type $FUNCSIG$v (func))
(memory $0 0)
(table $0 1 funcref)
(elem (i32.const 0) $null)
(export "memory" (memory $0))
(func $null (; 0 ;) (type $FUNCSIG$v)
nop
)
)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -7,472 +7,135 @@
(type $FUNCSIG$iii (func (param i32 i32) (result i32)))
(import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32)))
(memory $0 1)
(data (i32.const 8) "\n\00\00\00\01\00\00\00\10\00\00\00\n\00\00\00e\00r\00r\00o\00r\00")
(data (i32.const 40) "\"\00\00\00\01\00\00\00\10\00\00\00\"\00\00\00r\00e\00t\00a\00i\00n\00-\00r\00e\00l\00e\00a\00s\00e\00.\00t\00s\00")
(data (i32.const 8) "\n\00\00\00\01\00\00\00\10\00\00\00\n\00\00\00e\00r\00r\00o\00r")
(data (i32.const 40) "\"\00\00\00\01\00\00\00\10\00\00\00\"\00\00\00r\00e\00t\00a\00i\00n\00-\00r\00e\00l\00e\00a\00s\00e\00.\00t\00s")
(table $0 1 funcref)
(elem (i32.const 0) $null)
(elem (i32.const 0) $retain-release/receiveRef)
(global $retain-release/REF (mut i32) (i32.const 0))
(global $retain-release/glo (mut i32) (i32.const 0))
(global $retain-release/TARGET (mut i32) (i32.const 0))
(global $~lib/argc (mut i32) (i32.const 0))
(global $~lib/rt/stub/startOffset (mut i32) (i32.const 0))
(global $~lib/rt/stub/offset (mut i32) (i32.const 0))
(global $~lib/builtins/HEAP_BASE i32 (i32.const 92))
(export "memory" (memory $0))
(export "returnRef" (func $retain-release/returnRef))
(export "receiveRef" (func $retain-release/receiveRef))
(export "receiveRefDrop" (func $retain-release/receiveRefDrop))
(export "receiveRefRetain" (func $retain-release/receiveRefRetain))
(export "receiveRefDrop" (func $retain-release/receiveRef))
(export "receiveRefRetain" (func $retain-release/receiveRef))
(export "takeRef" (func $retain-release/takeRef))
(export "provideRef" (func $retain-release/provideRef))
(export "provideRef" (func $retain-release/receiveRef))
(export "takeReturnRef" (func $retain-release/takeReturnRef))
(export "provideReceiveRef" (func $retain-release/provideReceiveRef))
(export "provideReceiveRef" (func $retain-release/receiveRef))
(export "newRef" (func $retain-release/newRef))
(export "assignGlobal" (func $retain-release/assignGlobal))
(export "assignField" (func $retain-release/assignField))
(export "scopeBlock" (func $retain-release/scopeBlock))
(export "scopeBlockToUninitialized" (func $retain-release/scopeBlockToUninitialized))
(export "scopeBlockToInitialized" (func $retain-release/scopeBlockToInitialized))
(export "scopeBlockToConditional" (func $retain-release/scopeBlockToConditional))
(export "scopeTopLevelUninitialized" (func $retain-release/scopeTopLevelUninitialized))
(export "scopeTopLevelInitialized" (func $retain-release/scopeTopLevelInitialized))
(export "scopeTopLevelConditional" (func $retain-release/scopeTopLevelConditional))
(export "scopeIf" (func $retain-release/scopeIf))
(export "scopeIfElse" (func $retain-release/scopeIfElse))
(export "scopeWhile" (func $retain-release/scopeWhile))
(export "scopeDo" (func $retain-release/scopeDo))
(export "scopeFor" (func $retain-release/scopeFor))
(export "scopeBreak" (func $retain-release/scopeBreak))
(export "scopeContinue" (func $retain-release/scopeContinue))
(export "scopeBlock" (func $retain-release/receiveRef))
(export "scopeBlockToUninitialized" (func $retain-release/receiveRef))
(export "scopeBlockToInitialized" (func $retain-release/receiveRef))
(export "scopeBlockToConditional" (func $retain-release/takeRef))
(export "scopeTopLevelUninitialized" (func $retain-release/receiveRef))
(export "scopeTopLevelInitialized" (func $retain-release/receiveRef))
(export "scopeTopLevelConditional" (func $retain-release/takeRef))
(export "scopeIf" (func $retain-release/takeRef))
(export "scopeIfElse" (func $retain-release/takeRef))
(export "scopeWhile" (func $retain-release/takeRef))
(export "scopeDo" (func $retain-release/takeRef))
(export "scopeFor" (func $retain-release/takeRef))
(export "scopeBreak" (func $retain-release/takeRef))
(export "scopeContinue" (func $retain-release/takeRef))
(export "scopeThrow" (func $retain-release/scopeThrow))
(export "scopeUnreachable" (func $retain-release/scopeUnreachable))
(export "callInline" (func $retain-release/callInline))
(export "provideRefInline" (func $retain-release/provideRefInline))
(export "receiveRefInline" (func $retain-release/receiveRefInline))
(export "receiveRefInlineDrop" (func $retain-release/receiveRefInlineDrop))
(export "callInline" (func $retain-release/receiveRef))
(export "provideRefInline" (func $retain-release/receiveRef))
(export "receiveRefInline" (func $retain-release/receiveRef))
(export "receiveRefInlineDrop" (func $retain-release/receiveRef))
(export "provideRefIndirect" (func $retain-release/provideRefIndirect))
(export "receiveRefIndirect" (func $retain-release/receiveRefIndirect))
(export "receiveRefIndirectDrop" (func $retain-release/receiveRefIndirectDrop))
(export "receiveRefIndirectDrop" (func $retain-release/receiveRefIndirect))
(start $start)
(func $retain-release/Ref#constructor (; 1 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
local.get $0
i32.eqz
if
i32.const 0
i32.const 17
call $~lib/rt/stub/__alloc
call $~lib/rt/stub/__retain
local.set $0
end
(func $retain-release/Ref#constructor (; 1 ;) (type $FUNCSIG$i) (result i32)
i32.const 0
i32.const 17
call $~lib/rt/stub/__alloc
)
(func $retain-release/returnRef (; 2 ;) (type $FUNCSIG$i) (result i32)
global.get $retain-release/REF
)
(func $retain-release/receiveRef (; 3 ;) (type $FUNCSIG$v)
nop
)
(func $retain-release/takeRef (; 4 ;) (type $FUNCSIG$vi) (param $0 i32)
nop
)
(func $retain-release/takeReturnRef (; 5 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
local.get $0
)
(func $retain-release/Target#constructor (; 2 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
local.get $0
i32.eqz
if
i32.const 4
i32.const 18
call $~lib/rt/stub/__alloc
call $~lib/rt/stub/__retain
local.set $0
end
local.get $0
i32.const 0
i32.store
local.get $0
)
(func $start:retain-release (; 3 ;) (type $FUNCSIG$v)
i32.const 0
(func $retain-release/newRef (; 6 ;) (type $FUNCSIG$v)
call $retain-release/Ref#constructor
global.set $retain-release/REF
i32.const 0
call $retain-release/Target#constructor
global.set $retain-release/TARGET
)
(func $retain-release/returnRef (; 4 ;) (type $FUNCSIG$i) (result i32)
global.get $retain-release/REF
call $~lib/rt/stub/__retain
)
(func $retain-release/receiveRef (; 5 ;) (type $FUNCSIG$v)
(local $0 i32)
call $retain-release/returnRef
local.tee $0
i32.eqz
drop
local.get $0
call $~lib/rt/stub/__release
)
(func $retain-release/receiveRefDrop (; 6 ;) (type $FUNCSIG$v)
call $retain-release/returnRef
call $~lib/rt/stub/__release
)
(func $retain-release/receiveRefRetain (; 7 ;) (type $FUNCSIG$v)
(local $0 i32)
call $retain-release/returnRef
local.set $0
local.get $0
call $~lib/rt/stub/__release
)
(func $retain-release/takeRef (; 8 ;) (type $FUNCSIG$vi) (param $0 i32)
local.get $0
call $~lib/rt/stub/__retain
drop
local.get $0
call $~lib/rt/stub/__release
)
(func $retain-release/provideRef (; 9 ;) (type $FUNCSIG$v)
(func $retain-release/assignGlobal (; 7 ;) (type $FUNCSIG$v)
global.get $retain-release/REF
call $retain-release/takeRef
)
(func $retain-release/takeReturnRef (; 10 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
local.get $0
call $~lib/rt/stub/__retain
drop
local.get $0
)
(func $retain-release/provideReceiveRef (; 11 ;) (type $FUNCSIG$v)
(local $0 i32)
global.get $retain-release/REF
call $retain-release/takeReturnRef
local.tee $0
i32.eqz
drop
local.get $0
call $~lib/rt/stub/__release
)
(func $retain-release/newRef (; 12 ;) (type $FUNCSIG$v)
i32.const 0
call $retain-release/Ref#constructor
call $~lib/rt/stub/__release
)
(func $retain-release/assignGlobal (; 13 ;) (type $FUNCSIG$v)
global.get $retain-release/REF
global.get $retain-release/glo
call $~lib/rt/stub/__retainRelease
global.set $retain-release/glo
)
(func $retain-release/assignField (; 14 ;) (type $FUNCSIG$v)
(func $retain-release/assignField (; 8 ;) (type $FUNCSIG$v)
(local $0 i32)
global.get $retain-release/TARGET
local.tee $0
global.get $retain-release/REF
local.get $0
i32.load
call $~lib/rt/stub/__retainRelease
drop
local.get $0
global.get $retain-release/REF
i32.store
)
(func $retain-release/scopeBlock (; 15 ;) (type $FUNCSIG$v)
(local $0 i32)
global.get $retain-release/REF
call $~lib/rt/stub/__retain
local.set $0
local.get $0
call $~lib/rt/stub/__release
)
(func $retain-release/scopeBlockToUninitialized (; 16 ;) (type $FUNCSIG$v)
(local $0 i32)
(local $1 i32)
i32.const 0
local.set $0
global.get $retain-release/REF
call $~lib/rt/stub/__retain
local.set $1
local.get $1
local.get $0
call $~lib/rt/stub/__retainRelease
local.set $0
local.get $1
call $~lib/rt/stub/__release
local.get $0
call $~lib/rt/stub/__release
)
(func $retain-release/scopeBlockToInitialized (; 17 ;) (type $FUNCSIG$v)
(local $0 i32)
(local $1 i32)
global.get $retain-release/REF
call $~lib/rt/stub/__retain
local.set $0
global.get $retain-release/REF
call $~lib/rt/stub/__retain
local.set $1
local.get $1
local.get $0
call $~lib/rt/stub/__retainRelease
local.set $0
local.get $1
call $~lib/rt/stub/__release
local.get $0
call $~lib/rt/stub/__release
)
(func $retain-release/scopeBlockToConditional (; 18 ;) (type $FUNCSIG$vi) (param $0 i32)
(local $1 i32)
(local $2 i32)
i32.const 0
local.set $1
(func $retain-release/scopeThrow (; 9 ;) (type $FUNCSIG$vi) (param $0 i32)
local.get $0
if
global.get $retain-release/REF
local.get $1
call $~lib/rt/stub/__retainRelease
local.set $1
end
global.get $retain-release/REF
call $~lib/rt/stub/__retain
local.set $2
local.get $2
local.get $1
call $~lib/rt/stub/__retainRelease
local.set $1
local.get $2
call $~lib/rt/stub/__release
local.get $1
call $~lib/rt/stub/__release
)
(func $retain-release/scopeTopLevelUninitialized (; 19 ;) (type $FUNCSIG$v)
(local $0 i32)
i32.const 0
local.set $0
local.get $0
call $~lib/rt/stub/__release
)
(func $retain-release/scopeTopLevelInitialized (; 20 ;) (type $FUNCSIG$v)
(local $0 i32)
global.get $retain-release/REF
call $~lib/rt/stub/__retain
local.set $0
local.get $0
call $~lib/rt/stub/__release
)
(func $retain-release/scopeTopLevelConditional (; 21 ;) (type $FUNCSIG$vi) (param $0 i32)
(local $1 i32)
i32.const 0
local.set $1
local.get $0
if
global.get $retain-release/REF
local.get $1
call $~lib/rt/stub/__retainRelease
local.set $1
end
local.get $1
call $~lib/rt/stub/__release
)
(func $retain-release/scopeIf (; 22 ;) (type $FUNCSIG$vi) (param $0 i32)
(local $1 i32)
local.get $0
if
global.get $retain-release/REF
call $~lib/rt/stub/__retain
local.set $1
local.get $1
call $~lib/rt/stub/__release
end
)
(func $retain-release/scopeIfElse (; 23 ;) (type $FUNCSIG$vi) (param $0 i32)
(local $1 i32)
local.get $0
if
global.get $retain-release/REF
call $~lib/rt/stub/__retain
local.set $1
local.get $1
call $~lib/rt/stub/__release
else
global.get $retain-release/REF
call $~lib/rt/stub/__retain
local.set $1
local.get $1
call $~lib/rt/stub/__release
end
)
(func $retain-release/scopeWhile (; 24 ;) (type $FUNCSIG$vi) (param $0 i32)
(local $1 i32)
loop $continue|0
local.get $0
if
global.get $retain-release/REF
call $~lib/rt/stub/__retain
local.set $1
local.get $1
call $~lib/rt/stub/__release
br $continue|0
end
end
)
(func $retain-release/scopeDo (; 25 ;) (type $FUNCSIG$vi) (param $0 i32)
(local $1 i32)
loop $continue|0
block
global.get $retain-release/REF
call $~lib/rt/stub/__retain
local.set $1
local.get $1
call $~lib/rt/stub/__release
end
local.get $0
br_if $continue|0
end
)
(func $retain-release/scopeFor (; 26 ;) (type $FUNCSIG$vi) (param $0 i32)
(local $1 i32)
block $break|0
loop $repeat|0
local.get $0
i32.eqz
br_if $break|0
global.get $retain-release/REF
call $~lib/rt/stub/__retain
local.set $1
local.get $1
call $~lib/rt/stub/__release
br $repeat|0
unreachable
end
i32.const 24
i32.const 56
i32.const 313
i32.const 4
call $~lib/builtins/abort
unreachable
end
)
(func $retain-release/scopeBreak (; 27 ;) (type $FUNCSIG$vi) (param $0 i32)
(local $1 i32)
block $break|0
loop $continue|0
local.get $0
if
global.get $retain-release/REF
call $~lib/rt/stub/__retain
local.set $1
local.get $1
call $~lib/rt/stub/__release
br $break|0
end
end
end
)
(func $retain-release/scopeContinue (; 28 ;) (type $FUNCSIG$vi) (param $0 i32)
(local $1 i32)
loop $continue|0
local.get $0
if
global.get $retain-release/REF
call $~lib/rt/stub/__retain
local.set $1
local.get $1
call $~lib/rt/stub/__release
br $continue|0
end
end
)
(func $retain-release/scopeThrow (; 29 ;) (type $FUNCSIG$vi) (param $0 i32)
(local $1 i32)
loop $continue|0
local.get $0
if
global.get $retain-release/REF
call $~lib/rt/stub/__retain
local.set $1
local.get $1
call $~lib/rt/stub/__release
block
i32.const 24
i32.const 56
i32.const 310
i32.const 4
call $~lib/builtins/abort
unreachable
unreachable
end
unreachable
end
end
)
(func $retain-release/scopeUnreachable (; 30 ;) (type $FUNCSIG$vi) (param $0 i32)
(local $1 i32)
loop $continue|0
local.get $0
if
global.get $retain-release/REF
call $~lib/rt/stub/__retain
local.set $1
unreachable
local.get $1
call $~lib/rt/stub/__release
br $continue|0
end
end
)
(func $retain-release/callInline (; 31 ;) (type $FUNCSIG$v)
(local $0 i32)
global.get $retain-release/REF
call $~lib/rt/stub/__retain
local.set $0
(func $retain-release/scopeUnreachable (; 10 ;) (type $FUNCSIG$vi) (param $0 i32)
local.get $0
call $~lib/rt/stub/__release
)
(func $retain-release/provideRefInline (; 32 ;) (type $FUNCSIG$v)
(local $0 i32)
global.get $retain-release/REF
call $~lib/rt/stub/__retain
local.set $0
local.get $0
call $~lib/rt/stub/__release
)
(func $retain-release/receiveRefInline (; 33 ;) (type $FUNCSIG$v)
(local $0 i32)
block $retain-release/returnRefInline|inlined.0 (result i32)
global.get $retain-release/REF
call $~lib/rt/stub/__retain
if
unreachable
end
local.tee $0
i32.eqz
drop
local.get $0
call $~lib/rt/stub/__release
)
(func $retain-release/receiveRefInlineDrop (; 34 ;) (type $FUNCSIG$v)
block $retain-release/returnRefInline|inlined.1 (result i32)
global.get $retain-release/REF
call $~lib/rt/stub/__retain
end
call $~lib/rt/stub/__release
)
(func $retain-release/provideRefIndirect (; 35 ;) (type $FUNCSIG$vi) (param $0 i32)
(func $retain-release/provideRefIndirect (; 11 ;) (type $FUNCSIG$vi) (param $0 i32)
i32.const 1
global.set $~lib/argc
global.get $retain-release/REF
local.get $0
call_indirect (type $FUNCSIG$vi)
)
(func $retain-release/receiveRefIndirect (; 36 ;) (type $FUNCSIG$vi) (param $0 i32)
(local $1 i32)
block (result i32)
i32.const 0
global.set $~lib/argc
local.get $0
call_indirect (type $FUNCSIG$i)
local.tee $1
end
i32.eqz
drop
local.get $1
call $~lib/rt/stub/__release
)
(func $retain-release/receiveRefIndirectDrop (; 37 ;) (type $FUNCSIG$vi) (param $0 i32)
(func $retain-release/receiveRefIndirect (; 12 ;) (type $FUNCSIG$vi) (param $0 i32)
i32.const 0
global.set $~lib/argc
local.get $0
call_indirect (type $FUNCSIG$i)
call $~lib/rt/stub/__release
drop
)
(func $start (; 38 ;) (type $FUNCSIG$v)
call $start:retain-release
(func $start (; 13 ;) (type $FUNCSIG$v)
(local $0 i32)
call $retain-release/Ref#constructor
global.set $retain-release/REF
i32.const 4
i32.const 18
call $~lib/rt/stub/__alloc
local.tee $0
i32.const 0
i32.store
local.get $0
global.set $retain-release/TARGET
)
(func $~lib/rt/stub/__alloc (; 39 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32)
(func $~lib/rt/stub/__alloc (; 14 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32)
(local $2 i32)
(local $3 i32)
(local $4 i32)
(local $5 i32)
(local $6 i32)
(local $7 i32)
(local $8 i32)
local.get $0
i32.const 1073741808
i32.gt_u
@ -482,59 +145,45 @@
global.get $~lib/rt/stub/offset
i32.const 16
i32.add
local.set $2
local.get $2
local.get $0
local.tee $3
local.get $0
i32.const 1
local.get $0
i32.const 1
local.tee $4
local.get $3
local.get $4
i32.gt_u
select
i32.add
i32.const 15
i32.add
i32.const 15
i32.const -1
i32.xor
i32.const -16
i32.and
local.set $5
local.tee $2
current_memory
local.set $6
local.get $5
local.get $6
local.tee $4
i32.const 16
i32.shl
i32.gt_u
if
local.get $5
local.get $4
local.get $2
local.get $3
i32.sub
i32.const 65535
i32.add
i32.const 65535
i32.const -1
i32.xor
i32.const -65536
i32.and
i32.const 16
i32.shr_u
local.set $3
local.get $6
local.tee $4
local.get $3
local.tee $7
local.tee $5
local.get $4
local.get $7
local.get $5
i32.gt_s
select
local.set $4
local.get $4
grow_memory
i32.const 0
i32.lt_s
if
local.get $3
local.get $5
grow_memory
i32.const 0
i32.lt_s
@ -543,29 +192,17 @@
end
end
end
local.get $5
global.set $~lib/rt/stub/offset
local.get $2
global.set $~lib/rt/stub/offset
local.get $3
i32.const 16
i32.sub
local.set $8
local.get $8
local.tee $2
local.get $1
i32.store offset=8
local.get $8
local.get $2
local.get $0
i32.store offset=12
local.get $2
)
(func $~lib/rt/stub/__retain (; 40 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
local.get $0
)
(func $~lib/rt/stub/__retainRelease (; 41 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32)
local.get $0
)
(func $~lib/rt/stub/__release (; 42 ;) (type $FUNCSIG$vi) (param $0 i32)
nop
)
(func $null (; 43 ;) (type $FUNCSIG$v)
local.get $3
)
)

View File

@ -17,7 +17,7 @@
(global $~lib/argc (mut i32) (i32.const 0))
(global $~lib/rt/stub/startOffset (mut i32) (i32.const 0))
(global $~lib/rt/stub/offset (mut i32) (i32.const 0))
(global $~lib/builtins/HEAP_BASE i32 (i32.const 92))
(global $~lib/heap/HEAP_BASE i32 (i32.const 92))
(export "memory" (memory $0))
(export "returnRef" (func $retain-release/returnRef))
(export "receiveRef" (func $retain-release/receiveRef))
@ -374,7 +374,7 @@
block
i32.const 24
i32.const 56
i32.const 310
i32.const 313
i32.const 4
call $~lib/builtins/abort
unreachable

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,388 +1,25 @@
(module
(type $FUNCSIG$iii (func (param i32 i32) (result i32)))
(type $FUNCSIG$viii (func (param i32 i32 i32)))
(type $FUNCSIG$vi (func (param i32)))
(type $FUNCSIG$ii (func (param i32) (result i32)))
(type $FUNCSIG$v (func))
(type $FUNCSIG$viiii (func (param i32 i32 i32 i32)))
(type $FUNCSIG$v (func))
(import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32)))
(memory $0 1)
(data (i32.const 8) "$\00\00\00\01\00\00\00\10\00\00\00$\00\00\00I\00n\00d\00e\00x\00 \00o\00u\00t\00 \00o\00f\00 \00r\00a\00n\00g\00e\00")
(data (i32.const 64) "\"\00\00\00\01\00\00\00\10\00\00\00\"\00\00\00~\00l\00i\00b\00/\00r\00t\00/\00c\00o\00m\00m\00o\00n\00.\00t\00s\00")
(data (i32.const 120) "\10\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00")
(table $0 1 funcref)
(elem (i32.const 0) $null)
(global $~lib/rt/stub/startOffset (mut i32) (i32.const 0))
(global $~lib/rt/stub/offset (mut i32) (i32.const 0))
(global $~lib/builtins/RTTI_BASE i32 (i32.const 120))
(global $~lib/builtins/HEAP_BASE i32 (i32.const 256))
(data (i32.const 8) "$\00\00\00\01\00\00\00\10\00\00\00$\00\00\00I\00n\00d\00e\00x\00 \00o\00u\00t\00 \00o\00f\00 \00r\00a\00n\00g\00e")
(data (i32.const 64) "\14\00\00\00\01\00\00\00\10\00\00\00\14\00\00\00~\00l\00i\00b\00/\00r\00t\00.\00t\00s")
(data (i32.const 104) "\10\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08")
(export "memory" (memory $0))
(export "__alloc" (func $~lib/rt/stub/__alloc))
(export "__realloc" (func $~lib/rt/stub/__realloc))
(export "__free" (func $~lib/rt/stub/__free))
(export "__retain" (func $~lib/rt/stub/__retain))
(export "__release" (func $~lib/rt/stub/__release))
(export "__collect" (func $~lib/rt/stub/__collect))
(export "__instanceof" (func $~lib/rt/common/__instanceof))
(export "__typeinfo" (func $~lib/rt/common/__typeinfo))
(start $start)
(func $~lib/rt/stub/__alloc (; 1 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32)
(local $2 i32)
(local $3 i32)
(local $4 i32)
(local $5 i32)
(local $6 i32)
(local $7 i32)
(local $8 i32)
local.get $0
i32.const 1073741808
i32.gt_u
if
unreachable
end
global.get $~lib/rt/stub/offset
i32.const 16
i32.add
local.set $2
local.get $2
local.get $0
local.tee $3
i32.const 1
local.tee $4
local.get $3
local.get $4
i32.gt_u
select
i32.add
i32.const 15
i32.add
i32.const 15
i32.const -1
i32.xor
i32.and
local.set $5
current_memory
local.set $6
local.get $5
local.get $6
i32.const 16
i32.shl
i32.gt_u
if
local.get $5
local.get $2
i32.sub
i32.const 65535
i32.add
i32.const 65535
i32.const -1
i32.xor
i32.and
i32.const 16
i32.shr_u
local.set $3
local.get $6
local.tee $4
local.get $3
local.tee $7
local.get $4
local.get $7
i32.gt_s
select
local.set $4
local.get $4
grow_memory
i32.const 0
i32.lt_s
if
local.get $3
grow_memory
i32.const 0
i32.lt_s
if
unreachable
end
end
end
local.get $5
global.set $~lib/rt/stub/offset
local.get $2
i32.const 16
i32.sub
local.set $8
local.get $8
local.get $1
i32.store offset=8
local.get $8
local.get $0
i32.store offset=12
local.get $2
)
(func $~lib/memory/memory.copy (; 2 ;) (type $FUNCSIG$viii) (param $0 i32) (param $1 i32) (param $2 i32)
(local $3 i32)
(local $4 i32)
(local $5 i32)
(local $6 i32)
block $~lib/util/memory/memmove|inlined.0
local.get $0
local.set $5
local.get $1
local.set $4
local.get $2
local.set $3
local.get $5
local.get $4
i32.eq
if
br $~lib/util/memory/memmove|inlined.0
end
local.get $5
local.get $4
i32.lt_u
if
local.get $4
i32.const 7
i32.and
local.get $5
i32.const 7
i32.and
i32.eq
if
block $break|0
loop $continue|0
local.get $5
i32.const 7
i32.and
if
local.get $3
i32.eqz
if
br $~lib/util/memory/memmove|inlined.0
end
local.get $3
i32.const 1
i32.sub
local.set $3
block (result i32)
local.get $5
local.tee $6
i32.const 1
i32.add
local.set $5
local.get $6
end
block (result i32)
local.get $4
local.tee $6
i32.const 1
i32.add
local.set $4
local.get $6
end
i32.load8_u
i32.store8
br $continue|0
end
end
end
block $break|1
loop $continue|1
local.get $3
i32.const 8
i32.ge_u
if
local.get $5
local.get $4
i64.load
i64.store
local.get $3
i32.const 8
i32.sub
local.set $3
local.get $5
i32.const 8
i32.add
local.set $5
local.get $4
i32.const 8
i32.add
local.set $4
br $continue|1
end
end
end
end
block $break|2
loop $continue|2
local.get $3
if
block (result i32)
local.get $5
local.tee $6
i32.const 1
i32.add
local.set $5
local.get $6
end
block (result i32)
local.get $4
local.tee $6
i32.const 1
i32.add
local.set $4
local.get $6
end
i32.load8_u
i32.store8
local.get $3
i32.const 1
i32.sub
local.set $3
br $continue|2
end
end
end
else
local.get $4
i32.const 7
i32.and
local.get $5
i32.const 7
i32.and
i32.eq
if
block $break|3
loop $continue|3
local.get $5
local.get $3
i32.add
i32.const 7
i32.and
if
local.get $3
i32.eqz
if
br $~lib/util/memory/memmove|inlined.0
end
local.get $5
local.get $3
i32.const 1
i32.sub
local.tee $3
i32.add
local.get $4
local.get $3
i32.add
i32.load8_u
i32.store8
br $continue|3
end
end
end
block $break|4
loop $continue|4
local.get $3
i32.const 8
i32.ge_u
if
local.get $3
i32.const 8
i32.sub
local.set $3
local.get $5
local.get $3
i32.add
local.get $4
local.get $3
i32.add
i64.load
i64.store
br $continue|4
end
end
end
end
block $break|5
loop $continue|5
local.get $3
if
local.get $5
local.get $3
i32.const 1
i32.sub
local.tee $3
i32.add
local.get $4
local.get $3
i32.add
i32.load8_u
i32.store8
br $continue|5
end
end
end
end
end
)
(func $~lib/rt/stub/__realloc (; 3 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32)
(local $2 i32)
(local $3 i32)
(local $4 i32)
local.get $0
i32.const 16
i32.sub
local.set $2
local.get $2
i32.load offset=12
local.set $3
local.get $1
local.get $3
i32.gt_u
if
local.get $1
local.get $2
i32.load offset=8
call $~lib/rt/stub/__alloc
local.set $4
local.get $4
local.get $0
local.get $3
call $~lib/memory/memory.copy
local.get $4
local.set $0
else
local.get $2
local.get $1
i32.store offset=12
end
local.get $0
)
(func $~lib/rt/stub/__free (; 4 ;) (type $FUNCSIG$vi) (param $0 i32)
nop
)
(func $~lib/rt/stub/__retain (; 5 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
local.get $0
)
(func $~lib/rt/stub/__release (; 6 ;) (type $FUNCSIG$vi) (param $0 i32)
nop
)
(func $~lib/rt/stub/__collect (; 7 ;) (type $FUNCSIG$v)
nop
)
(func $~lib/rt/common/__instanceof (; 8 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32)
(local $2 i32)
(local $3 i32)
(export "__instanceof" (func $~lib/rt/__instanceof))
(export "__typeinfo" (func $~lib/rt/__typeinfo))
(func $~lib/rt/__instanceof (; 1 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32)
local.get $0
i32.const 16
i32.sub
i32.load offset=8
local.set $2
global.get $~lib/builtins/RTTI_BASE
local.set $3
local.get $2
local.tee $0
if (result i32)
local.get $2
local.get $3
local.get $0
i32.const 104
i32.load
i32.le_u
else
@ -390,66 +27,51 @@
end
if
loop $continue|0
local.get $2
local.get $0
local.get $1
i32.eq
if
i32.const 1
return
end
local.get $3
local.get $2
i32.const 8
i32.mul
local.get $0
i32.const 3
i32.shl
i32.const 104
i32.add
i32.load offset=4
local.tee $2
local.tee $0
br_if $continue|0
end
end
i32.const 0
)
(func $~lib/rt/common/__typeinfo (; 9 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
(local $1 i32)
global.get $~lib/builtins/RTTI_BASE
local.set $1
(func $~lib/rt/__typeinfo (; 2 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
local.get $0
i32.eqz
if (result i32)
i32.const 1
else
local.get $0
local.get $1
i32.const 104
i32.load
i32.gt_u
else
i32.const 1
end
if
i32.const 24
i32.const 80
i32.const 55
i32.const 23
i32.const 34
call $~lib/builtins/abort
unreachable
end
local.get $1
local.get $0
i32.const 8
i32.mul
i32.const 3
i32.shl
i32.const 104
i32.add
i32.load
)
(func $start (; 10 ;) (type $FUNCSIG$v)
global.get $~lib/builtins/HEAP_BASE
i32.const 15
i32.add
i32.const 15
i32.const -1
i32.xor
i32.and
global.set $~lib/rt/stub/startOffset
global.get $~lib/rt/stub/startOffset
global.set $~lib/rt/stub/offset
)
(func $null (; 11 ;) (type $FUNCSIG$v)
(func $null (; 3 ;) (type $FUNCSIG$v)
nop
)
)

View File

@ -1,375 +1,20 @@
(module
(type $FUNCSIG$iii (func (param i32 i32) (result i32)))
(type $FUNCSIG$viii (func (param i32 i32 i32)))
(type $FUNCSIG$vi (func (param i32)))
(type $FUNCSIG$ii (func (param i32) (result i32)))
(type $FUNCSIG$v (func))
(type $FUNCSIG$viiii (func (param i32 i32 i32 i32)))
(type $FUNCSIG$v (func))
(import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32)))
(memory $0 1)
(data (i32.const 8) "$\00\00\00\01\00\00\00\10\00\00\00$\00\00\00I\00n\00d\00e\00x\00 \00o\00u\00t\00 \00o\00f\00 \00r\00a\00n\00g\00e\00")
(data (i32.const 64) "\"\00\00\00\01\00\00\00\10\00\00\00\"\00\00\00~\00l\00i\00b\00/\00r\00t\00/\00c\00o\00m\00m\00o\00n\00.\00t\00s\00")
(data (i32.const 120) "\10\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00")
(data (i32.const 64) "\14\00\00\00\01\00\00\00\10\00\00\00\14\00\00\00~\00l\00i\00b\00/\00r\00t\00.\00t\00s\00")
(data (i32.const 104) "\10\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00")
(table $0 1 funcref)
(elem (i32.const 0) $null)
(global $~lib/rt/stub/startOffset (mut i32) (i32.const 0))
(global $~lib/rt/stub/offset (mut i32) (i32.const 0))
(global $~lib/builtins/RTTI_BASE i32 (i32.const 120))
(global $~lib/builtins/HEAP_BASE i32 (i32.const 256))
(global $~lib/rt/RTTI_BASE i32 (i32.const 104))
(export "memory" (memory $0))
(export "__alloc" (func $~lib/rt/stub/__alloc))
(export "__realloc" (func $~lib/rt/stub/__realloc))
(export "__free" (func $~lib/rt/stub/__free))
(export "__retain" (func $~lib/rt/stub/__retain))
(export "__release" (func $~lib/rt/stub/__release))
(export "__collect" (func $~lib/rt/stub/__collect))
(export "__instanceof" (func $~lib/rt/common/__instanceof))
(export "__typeinfo" (func $~lib/rt/common/__typeinfo))
(start $start)
(func $~lib/rt/stub/__alloc (; 1 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32)
(local $2 i32)
(local $3 i32)
(local $4 i32)
(local $5 i32)
(local $6 i32)
(local $7 i32)
(local $8 i32)
local.get $0
i32.const 1073741808
i32.gt_u
if
unreachable
end
global.get $~lib/rt/stub/offset
i32.const 16
i32.add
local.set $2
local.get $2
local.get $0
local.tee $3
i32.const 1
local.tee $4
local.get $3
local.get $4
i32.gt_u
select
i32.add
i32.const 15
i32.add
i32.const 15
i32.const -1
i32.xor
i32.and
local.set $5
current_memory
local.set $6
local.get $5
local.get $6
i32.const 16
i32.shl
i32.gt_u
if
local.get $5
local.get $2
i32.sub
i32.const 65535
i32.add
i32.const 65535
i32.const -1
i32.xor
i32.and
i32.const 16
i32.shr_u
local.set $3
local.get $6
local.tee $4
local.get $3
local.tee $7
local.get $4
local.get $7
i32.gt_s
select
local.set $4
local.get $4
grow_memory
i32.const 0
i32.lt_s
if
local.get $3
grow_memory
i32.const 0
i32.lt_s
if
unreachable
end
end
end
local.get $5
global.set $~lib/rt/stub/offset
local.get $2
i32.const 16
i32.sub
local.set $8
local.get $8
local.get $1
i32.store offset=8
local.get $8
local.get $0
i32.store offset=12
local.get $2
)
(func $~lib/memory/memory.copy (; 2 ;) (type $FUNCSIG$viii) (param $0 i32) (param $1 i32) (param $2 i32)
(local $3 i32)
(local $4 i32)
(local $5 i32)
(local $6 i32)
block $~lib/util/memory/memmove|inlined.0
local.get $0
local.set $5
local.get $1
local.set $4
local.get $2
local.set $3
local.get $5
local.get $4
i32.eq
if
br $~lib/util/memory/memmove|inlined.0
end
local.get $5
local.get $4
i32.lt_u
if
local.get $4
i32.const 7
i32.and
local.get $5
i32.const 7
i32.and
i32.eq
if
block $break|0
loop $continue|0
local.get $5
i32.const 7
i32.and
if
local.get $3
i32.eqz
if
br $~lib/util/memory/memmove|inlined.0
end
local.get $3
i32.const 1
i32.sub
local.set $3
block (result i32)
local.get $5
local.tee $6
i32.const 1
i32.add
local.set $5
local.get $6
end
block (result i32)
local.get $4
local.tee $6
i32.const 1
i32.add
local.set $4
local.get $6
end
i32.load8_u
i32.store8
br $continue|0
end
end
end
block $break|1
loop $continue|1
local.get $3
i32.const 8
i32.ge_u
if
local.get $5
local.get $4
i64.load
i64.store
local.get $3
i32.const 8
i32.sub
local.set $3
local.get $5
i32.const 8
i32.add
local.set $5
local.get $4
i32.const 8
i32.add
local.set $4
br $continue|1
end
end
end
end
block $break|2
loop $continue|2
local.get $3
if
block (result i32)
local.get $5
local.tee $6
i32.const 1
i32.add
local.set $5
local.get $6
end
block (result i32)
local.get $4
local.tee $6
i32.const 1
i32.add
local.set $4
local.get $6
end
i32.load8_u
i32.store8
local.get $3
i32.const 1
i32.sub
local.set $3
br $continue|2
end
end
end
else
local.get $4
i32.const 7
i32.and
local.get $5
i32.const 7
i32.and
i32.eq
if
block $break|3
loop $continue|3
local.get $5
local.get $3
i32.add
i32.const 7
i32.and
if
local.get $3
i32.eqz
if
br $~lib/util/memory/memmove|inlined.0
end
local.get $5
local.get $3
i32.const 1
i32.sub
local.tee $3
i32.add
local.get $4
local.get $3
i32.add
i32.load8_u
i32.store8
br $continue|3
end
end
end
block $break|4
loop $continue|4
local.get $3
i32.const 8
i32.ge_u
if
local.get $3
i32.const 8
i32.sub
local.set $3
local.get $5
local.get $3
i32.add
local.get $4
local.get $3
i32.add
i64.load
i64.store
br $continue|4
end
end
end
end
block $break|5
loop $continue|5
local.get $3
if
local.get $5
local.get $3
i32.const 1
i32.sub
local.tee $3
i32.add
local.get $4
local.get $3
i32.add
i32.load8_u
i32.store8
br $continue|5
end
end
end
end
end
)
(func $~lib/rt/stub/__realloc (; 3 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32)
(local $2 i32)
(local $3 i32)
(local $4 i32)
local.get $0
i32.const 16
i32.sub
local.set $2
local.get $2
i32.load offset=12
local.set $3
local.get $1
local.get $3
i32.gt_u
if
local.get $1
local.get $2
i32.load offset=8
call $~lib/rt/stub/__alloc
local.set $4
local.get $4
local.get $0
local.get $3
call $~lib/memory/memory.copy
local.get $4
local.set $0
else
local.get $2
local.get $1
i32.store offset=12
end
local.get $0
)
(func $~lib/rt/stub/__free (; 4 ;) (type $FUNCSIG$vi) (param $0 i32)
nop
)
(func $~lib/rt/stub/__retain (; 5 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
local.get $0
)
(func $~lib/rt/stub/__release (; 6 ;) (type $FUNCSIG$vi) (param $0 i32)
nop
)
(func $~lib/rt/stub/__collect (; 7 ;) (type $FUNCSIG$v)
nop
)
(func $~lib/rt/common/__instanceof (; 8 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32)
(export "__instanceof" (func $~lib/rt/__instanceof))
(export "__typeinfo" (func $~lib/rt/__typeinfo))
(func $~lib/rt/__instanceof (; 1 ;) (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32)
(local $2 i32)
(local $3 i32)
local.get $0
@ -377,7 +22,7 @@
i32.sub
i32.load offset=8
local.set $2
global.get $~lib/builtins/RTTI_BASE
global.get $~lib/rt/RTTI_BASE
local.set $3
local.get $2
if (result i32)
@ -409,9 +54,9 @@
end
i32.const 0
)
(func $~lib/rt/common/__typeinfo (; 9 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
(func $~lib/rt/__typeinfo (; 2 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
(local $1 i32)
global.get $~lib/builtins/RTTI_BASE
global.get $~lib/rt/RTTI_BASE
local.set $1
local.get $0
i32.eqz
@ -426,7 +71,7 @@
if
i32.const 24
i32.const 80
i32.const 55
i32.const 23
i32.const 34
call $~lib/builtins/abort
unreachable
@ -438,18 +83,6 @@
i32.add
i32.load
)
(func $start (; 10 ;) (type $FUNCSIG$v)
global.get $~lib/builtins/HEAP_BASE
i32.const 15
i32.add
i32.const 15
i32.const -1
i32.xor
i32.and
global.set $~lib/rt/stub/startOffset
global.get $~lib/rt/stub/startOffset
global.set $~lib/rt/stub/offset
)
(func $null (; 11 ;) (type $FUNCSIG$v)
(func $null (; 3 ;) (type $FUNCSIG$v)
)
)

View File

@ -1,7 +1,7 @@
(module
(type $FUNCSIG$v (func))
(memory $0 1)
(data (i32.const 8) "\0e\00\00\00\01\00\00\00\11\00\00\00\0e\00\00\00s\00i\00m\00d\00.\00t\00s\00")
(data (i32.const 8) "\0e\00\00\00\01\00\00\00\11\00\00\00\0e\00\00\00s\00i\00m\00d\00.\00t\00s")
(export "memory" (memory $0))
(func $start (; 0 ;) (type $FUNCSIG$v)
nop

View File

@ -1,23 +1,16 @@
(module
(type $FUNCSIG$i (func (result i32)))
(type $FUNCSIG$viiii (func (param i32 i32 i32 i32)))
(type $FUNCSIG$v (func))
(import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32)))
(memory $0 1)
(data (i32.const 8) "\1c\00\00\00\01\00\00\00\10\00\00\00\1c\00\00\00s\00t\00a\00t\00i\00c\00-\00t\00h\00i\00s\00.\00t\00s\00")
(table $0 1 funcref)
(elem (i32.const 0) $null)
(global $static-this/Foo.bar (mut i32) (i32.const 42))
(data (i32.const 8) "\1c\00\00\00\01\00\00\00\10\00\00\00\1c\00\00\00s\00t\00a\00t\00i\00c\00-\00t\00h\00i\00s\00.\00t\00s")
(global $static-this/Foo.bar i32 (i32.const 42))
(export "memory" (memory $0))
(start $start)
(func $static-this/Foo.getBar (; 1 ;) (type $FUNCSIG$i) (result i32)
(func $start (; 1 ;) (type $FUNCSIG$v)
global.get $static-this/Foo.bar
)
(func $start:static-this (; 2 ;) (type $FUNCSIG$v)
call $static-this/Foo.getBar
i32.const 42
i32.eq
i32.eqz
i32.ne
if
i32.const 0
i32.const 24
@ -27,9 +20,7 @@
unreachable
end
)
(func $start (; 3 ;) (type $FUNCSIG$v)
call $start:static-this
)
(func $null (; 4 ;) (type $FUNCSIG$v)
(func $null (; 2 ;) (type $FUNCSIG$v)
nop
)
)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -4,174 +4,65 @@
(type $FUNCSIG$v (func))
(import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32)))
(memory $0 1)
(data (i32.const 8) "\12\00\00\00\01\00\00\00\10\00\00\00\12\00\00\00s\00w\00i\00t\00c\00h\00.\00t\00s\00")
(table $0 1 funcref)
(elem (i32.const 0) $null)
(data (i32.const 8) "\12\00\00\00\01\00\00\00\10\00\00\00\12\00\00\00s\00w\00i\00t\00c\00h\00.\00t\00s")
(export "memory" (memory $0))
(start $start)
(func $switch/doSwitch (; 1 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
(local $1 i32)
block $break|0
block $case4|0
block $case3|0
block $case2|0
block $case1|0
block $case0|0
local.get $0
local.set $1
local.get $1
i32.const 1
i32.eq
br_if $case0|0
local.get $1
i32.const 0
i32.eq
br_if $case1|0
local.get $1
i32.const 2
i32.eq
br_if $case3|0
local.get $1
i32.const 3
i32.eq
br_if $case4|0
br $case2|0
end
i32.const 1
return
end
end
i32.const 0
return
block $case4|0
block $case2|0
local.get $0
i32.const 1
i32.ne
if
local.get $0
i32.eqz
br_if $case2|0
local.get $0
i32.const 2
i32.eq
br_if $case4|0
local.get $0
i32.const 3
i32.eq
br_if $case4|0
br $case2|0
end
i32.const 1
return
end
i32.const 23
i32.const 0
return
unreachable
end
unreachable
unreachable
i32.const 23
)
(func $switch/doSwitchDefaultOmitted (; 2 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
(local $1 i32)
block $break|0
block $case2|0
block $case1|0
block $case0|0
local.get $0
local.set $1
local.get $1
i32.const 1
i32.eq
br_if $case0|0
local.get $1
i32.const 2
i32.eq
br_if $case1|0
local.get $1
i32.const 3
i32.eq
br_if $case2|0
br $break|0
end
i32.const 1
return
local.get $0
i32.const 1
i32.ne
if
local.get $0
i32.const 2
i32.eq
br_if $case2|0
local.get $0
i32.const 3
i32.eq
br_if $case2|0
br $break|0
end
i32.const 1
return
end
i32.const 23
return
end
i32.const 0
)
(func $switch/doSwitchBreakCase (; 3 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
(local $1 i32)
block $break|0
block $case1|0
block $case0|0
local.get $0
local.set $1
local.get $1
i32.const 1
i32.eq
br_if $case0|0
br $case1|0
end
br $break|0
end
i32.const 2
return
end
i32.const 1
)
(func $switch/doSwitchBreakDefault (; 4 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
(local $1 i32)
block $break|0
block $case1|0
block $case0|0
local.get $0
local.set $1
local.get $1
i32.const 1
i32.eq
br_if $case0|0
br $case1|0
end
i32.const 1
return
end
br $break|0
end
i32.const 2
)
(func $switch/doSwitchFallThroughCase (; 5 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
(local $1 i32)
block $break|0
block $case1|0
block $case0|0
local.get $0
local.set $1
local.get $1
i32.const 1
i32.eq
br_if $case1|0
br $case0|0
end
i32.const 2
return
end
end
i32.const 1
)
(func $switch/doSwitchFallThroughDefault (; 6 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
(local $1 i32)
block $break|0
block $case1|0
block $case0|0
local.get $0
local.set $1
local.get $1
i32.const 1
i32.eq
br_if $case0|0
br $case1|0
end
i32.const 1
return
end
end
i32.const 2
)
(func $switch/doSwitchEmpty (; 7 ;) (type $FUNCSIG$ii) (param $0 i32) (result i32)
local.get $0
drop
i32.const 2
)
(func $start:switch (; 8 ;) (type $FUNCSIG$v)
(func $start:switch (; 3 ;) (type $FUNCSIG$v)
i32.const 0
call $switch/doSwitch
i32.const 0
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
@ -183,8 +74,7 @@
i32.const 1
call $switch/doSwitch
i32.const 1
i32.eq
i32.eqz
i32.ne
if
i32.const 0
i32.const 24
@ -196,8 +86,7 @@
i32.const 2
call $switch/doSwitch
i32.const 23
i32.eq
i32.eqz
i32.ne
if
i32.const 0
i32.const 24
@ -209,8 +98,7 @@
i32.const 3
call $switch/doSwitch
i32.const 23
i32.eq
i32.eqz
i32.ne
if
i32.const 0
i32.const 24
@ -221,9 +109,6 @@
end
i32.const 4
call $switch/doSwitch
i32.const 0
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
@ -234,9 +119,6 @@
end
i32.const 0
call $switch/doSwitch
i32.const 0
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
@ -248,8 +130,7 @@
i32.const 1
call $switch/doSwitch
i32.const 1
i32.eq
i32.eqz
i32.ne
if
i32.const 0
i32.const 24
@ -261,8 +142,7 @@
i32.const 2
call $switch/doSwitch
i32.const 23
i32.eq
i32.eqz
i32.ne
if
i32.const 0
i32.const 24
@ -274,8 +154,7 @@
i32.const 3
call $switch/doSwitch
i32.const 23
i32.eq
i32.eqz
i32.ne
if
i32.const 0
i32.const 24
@ -286,9 +165,6 @@
end
i32.const 4
call $switch/doSwitch
i32.const 0
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
@ -299,9 +175,6 @@
end
i32.const 0
call $switch/doSwitchDefaultOmitted
i32.const 0
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
@ -313,8 +186,7 @@
i32.const 1
call $switch/doSwitchDefaultOmitted
i32.const 1
i32.eq
i32.eqz
i32.ne
if
i32.const 0
i32.const 24
@ -326,8 +198,7 @@
i32.const 2
call $switch/doSwitchDefaultOmitted
i32.const 23
i32.eq
i32.eqz
i32.ne
if
i32.const 0
i32.const 24
@ -339,8 +210,7 @@
i32.const 3
call $switch/doSwitchDefaultOmitted
i32.const 23
i32.eq
i32.eqz
i32.ne
if
i32.const 0
i32.const 24
@ -351,9 +221,6 @@
end
i32.const 4
call $switch/doSwitchDefaultOmitted
i32.const 0
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
@ -362,205 +229,11 @@
call $~lib/builtins/abort
unreachable
end
i32.const 0
call $switch/doSwitchBreakCase
i32.const 2
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 51
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 1
call $switch/doSwitchBreakCase
i32.const 1
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 52
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 2
call $switch/doSwitchBreakCase
i32.const 2
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 53
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 0
call $switch/doSwitchBreakDefault
i32.const 2
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 62
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 1
call $switch/doSwitchBreakDefault
i32.const 1
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 63
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 2
call $switch/doSwitchBreakDefault
i32.const 2
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 64
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 0
call $switch/doSwitchFallThroughCase
i32.const 2
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 73
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 1
call $switch/doSwitchFallThroughCase
i32.const 1
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 74
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 2
call $switch/doSwitchFallThroughCase
i32.const 2
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 75
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 0
call $switch/doSwitchFallThroughDefault
i32.const 2
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 84
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 1
call $switch/doSwitchFallThroughDefault
i32.const 1
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 85
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 2
call $switch/doSwitchFallThroughDefault
i32.const 2
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 86
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 0
call $switch/doSwitchEmpty
i32.const 2
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 92
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 1
call $switch/doSwitchEmpty
i32.const 2
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 93
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 2
call $switch/doSwitchEmpty
i32.const 2
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 94
i32.const 0
call $~lib/builtins/abort
unreachable
end
)
(func $start (; 9 ;) (type $FUNCSIG$v)
(func $start (; 4 ;) (type $FUNCSIG$v)
call $start:switch
)
(func $null (; 10 ;) (type $FUNCSIG$v)
(func $null (; 5 ;) (type $FUNCSIG$v)
nop
)
)

View File

@ -1,545 +1,15 @@
(module
(type $FUNCSIG$viiii (func (param i32 i32 i32 i32)))
(type $FUNCSIG$v (func))
(import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32)))
(memory $0 1)
(data (i32.const 8) "\0e\00\00\00\01\00\00\00\10\00\00\00\0e\00\00\00w\00a\00s\00i\00.\00t\00s\00")
(table $0 1 funcref)
(elem (i32.const 0) $null)
(global $~lib/common/target/Target.WASM32 i32 (i32.const 0))
(global $~lib/common/target/Target.WASM64 i32 (i32.const 1))
(global $~lib/common/target/Target.JS i32 (i32.const 2))
(global $~lib/ASC_TARGET i32 (i32.const 0))
(data (i32.const 8) "\0e\00\00\00\01\00\00\00\10\00\00\00\0e\00\00\00w\00a\00s\00i\00.\00t\00s")
(global $wasi/sig (mut i32) (i32.const 1))
(export "memory" (memory $0))
(start $start)
(func $start:wasi (; 1 ;) (type $FUNCSIG$v)
i32.const 0
i32.const 0
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 4
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 8
i32.const 8
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 5
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 16
i32.const 16
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 6
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 20
i32.const 20
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 7
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 24
i32.const 24
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 8
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 0
i32.const 0
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 10
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 8
i32.const 8
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 11
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 10
i32.const 10
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 12
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 16
i32.const 16
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 13
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 24
i32.const 24
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 14
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 32
i32.const 32
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 15
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 0
i32.const 0
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 17
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 2
i32.const 2
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 18
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 8
i32.const 8
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 19
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 16
i32.const 16
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 20
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 24
i32.const 24
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 21
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 0
i32.const 0
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 23
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 8
i32.const 8
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 24
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 16
i32.const 16
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 25
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 20
i32.const 20
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 26
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 24
i32.const 24
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 27
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 32
i32.const 32
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 28
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 40
i32.const 40
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 29
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 48
i32.const 48
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 30
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 56
i32.const 56
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 31
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 0
i32.const 0
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 33
i32.const 0
call $~lib/builtins/abort
unreachable
end
block
i32.const 4
i32.const 4
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 35
i32.const 2
call $~lib/builtins/abort
unreachable
end
i32.const 8
i32.const 8
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 36
i32.const 2
call $~lib/builtins/abort
unreachable
end
end
i32.const 0
i32.const 0
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 44
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 8
i32.const 8
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 45
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 16
i32.const 16
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 46
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 24
i32.const 24
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 47
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 32
i32.const 32
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 48
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 40
i32.const 40
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 49
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 48
i32.const 48
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 50
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 56
i32.const 56
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 51
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 0
i32.const 0
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 53
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 8
i32.const 8
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 54
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 16
i32.const 16
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 55
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 20
i32.const 20
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 56
i32.const 0
call $~lib/builtins/abort
unreachable
end
i32.const 0
i32.const 0
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 58
i32.const 0
call $~lib/builtins/abort
unreachable
end
block
i32.const 4
i32.const 4
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 60
i32.const 2
call $~lib/builtins/abort
unreachable
end
i32.const 8
i32.const 8
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 61
i32.const 2
call $~lib/builtins/abort
unreachable
end
end
(func $start (; 0 ;) (type $FUNCSIG$v)
i32.const 9
global.set $wasi/sig
)
(func $start (; 2 ;) (type $FUNCSIG$v)
call $start:wasi
)
(func $null (; 3 ;) (type $FUNCSIG$v)
(func $null (; 1 ;) (type $FUNCSIG$v)
nop
)
)

View File

@ -3,9 +3,7 @@
(type $FUNCSIG$v (func))
(import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32)))
(memory $0 1)
(data (i32.const 8) "\10\00\00\00\01\00\00\00\10\00\00\00\10\00\00\00w\00h\00i\00l\00e\00.\00t\00s\00")
(table $0 1 funcref)
(elem (i32.const 0) $null)
(data (i32.const 8) "\10\00\00\00\01\00\00\00\10\00\00\00\10\00\00\00w\00h\00i\00l\00e\00.\00t\00s")
(global $while/n (mut i32) (i32.const 10))
(global $while/m (mut i32) (i32.const 0))
(global $while/o (mut i32) (i32.const 0))
@ -13,26 +11,21 @@
(start $start)
(func $start:while (; 1 ;) (type $FUNCSIG$v)
(local $0 i32)
block $break|0
loop $continue|0
loop $continue|0
global.get $while/n
if
global.get $while/n
if
global.get $while/n
i32.const 1
i32.sub
global.set $while/n
global.get $while/m
i32.const 1
i32.add
global.set $while/m
br $continue|0
end
i32.const 1
i32.sub
global.set $while/n
global.get $while/m
i32.const 1
i32.add
global.set $while/m
br $continue|0
end
end
global.get $while/n
i32.const 0
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
@ -43,8 +36,7 @@
end
global.get $while/m
i32.const 10
i32.eq
i32.eqz
i32.ne
if
i32.const 0
i32.const 24
@ -57,66 +49,55 @@
global.set $while/n
i32.const 0
global.set $while/m
block $break|1
loop $continue|1
loop $continue|1
global.get $while/n
if
global.get $while/n
i32.const 1
i32.sub
global.set $while/n
global.get $while/m
i32.const 1
i32.add
global.set $while/m
loop $continue|2
global.get $while/n
if
global.get $while/n
i32.const 1
i32.sub
global.set $while/n
global.get $while/o
i32.const 1
i32.add
global.set $while/o
br $continue|2
end
end
global.get $while/n
if
global.get $while/n
i32.const 1
i32.sub
global.set $while/n
global.get $while/m
i32.const 1
i32.add
global.set $while/m
block $break|2
loop $continue|2
global.get $while/n
if
global.get $while/n
i32.const 1
i32.sub
global.set $while/n
global.get $while/o
i32.const 1
i32.add
global.set $while/o
br $continue|2
end
end
end
global.get $while/n
i32.const 0
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 21
i32.const 2
call $~lib/builtins/abort
unreachable
end
global.get $while/o
i32.const 9
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
i32.const 22
i32.const 2
call $~lib/builtins/abort
unreachable
end
br $continue|1
i32.const 24
i32.const 21
i32.const 2
call $~lib/builtins/abort
unreachable
end
global.get $while/o
i32.const 9
i32.ne
if
i32.const 0
i32.const 24
i32.const 22
i32.const 2
call $~lib/builtins/abort
unreachable
end
br $continue|1
end
end
global.get $while/n
i32.const 0
i32.eq
i32.eqz
if
i32.const 0
i32.const 24
@ -127,8 +108,7 @@
end
global.get $while/m
i32.const 1
i32.eq
i32.eqz
i32.ne
if
i32.const 0
i32.const 24
@ -139,8 +119,7 @@
end
global.get $while/o
i32.const 9
i32.eq
i32.eqz
i32.ne
if
i32.const 0
i32.const 24
@ -153,36 +132,29 @@
global.set $while/n
i32.const 0
global.set $while/m
block $break|3
loop $continue|3
block (result i32)
global.get $while/n
local.tee $0
i32.const 1
i32.sub
global.set $while/n
local.get $0
end
if (result i32)
global.get $while/m
i32.const 1
i32.add
local.tee $0
global.set $while/m
local.get $0
else
i32.const 0
end
if
nop
br $continue|3
end
loop $continue|3
global.get $while/n
local.tee $0
i32.const 1
i32.sub
global.set $while/n
local.get $0
if
global.get $while/m
i32.const 1
i32.add
local.tee $0
global.set $while/m
else
i32.const 0
local.set $0
end
local.get $0
br_if $continue|3
end
global.get $while/n
i32.const -1
i32.eq
i32.eqz
i32.ne
if
i32.const 0
i32.const 24
@ -193,8 +165,7 @@
end
global.get $while/m
i32.const 1
i32.eq
i32.eqz
i32.ne
if
i32.const 0
i32.const 24
@ -208,5 +179,6 @@
call $start:while
)
(func $null (; 3 ;) (type $FUNCSIG$v)
nop
)
)