Take advantage of smaller integer load and store ops

This commit is contained in:
dcodeIO 2018-01-23 15:44:25 +01:00
parent 5d142ba647
commit 2fa7fc7885
13 changed files with 719 additions and 124 deletions

View File

@ -21,9 +21,11 @@ export function step(): void {
for (var x: u32 = 0; x < w; ++x) { for (var x: u32 = 0; x < w; ++x) {
var xm1 = select<u32>(wm1, x - 1, x == 0), var xm1 = select<u32>(wm1, x - 1, x == 0),
xp1 = select<u32>(0, x + 1, x == wm1); xp1 = select<u32>(0, x + 1, x == wm1);
var n = load<u8>(ym1 * w + xm1) + load<u8>(ym1 * w + x) + load<u8>(ym1 * w + xp1) var n = (
+ load<u8>(y * w + xm1) + load<u8>(y * w + xp1) load<u8>(ym1 * w + xm1) + load<u8>(ym1 * w + x) + load<u8>(ym1 * w + xp1) +
+ load<u8>(yp1 * w + xm1) + load<u8>(yp1 * w + x) + load<u8>(yp1 * w + xp1); load<u8>(y * w + xm1) + load<u8>(y * w + xp1) +
load<u8>(yp1 * w + xm1) + load<u8>(yp1 * w + x) + load<u8>(yp1 * w + xp1)
);
if (load<u8>(y * w + x)) { if (load<u8>(y * w + x)) {
if (n < 2 || n > 3) if (n < 2 || n > 3)
store<u8>(s + y * w + x, 0); store<u8>(s + y * w + x, 0);

View File

@ -1338,7 +1338,7 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
// memory access // memory access
case "load": // load<T!>(offset: usize, constantOffset?: usize) -> T case "load": // load<T!>(offset: usize, constantOffset?: usize) -> *
if (operands.length < 1 || operands.length > 2) { if (operands.length < 1 || operands.length > 2) {
if (!(typeArguments && typeArguments.length == 1)) if (!(typeArguments && typeArguments.length == 1))
compiler.error(DiagnosticCode.Expected_0_type_arguments_but_got_1, reportNode.range, "1", typeArguments ? typeArguments.length.toString(10) : "0"); compiler.error(DiagnosticCode.Expected_0_type_arguments_but_got_1, reportNode.range, "1", typeArguments ? typeArguments.length.toString(10) : "0");
@ -1358,37 +1358,43 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
offset = operands.length == 2 ? evaluateConstantOffset(compiler, operands[1]) : 0; // reports offset = operands.length == 2 ? evaluateConstantOffset(compiler, operands[1]) : 0; // reports
if (offset < 0) if (offset < 0)
return module.createUnreachable(); return module.createUnreachable();
compiler.currentType = typeArguments[0]; return module.createLoad(typeArguments[0].byteSize, typeArguments[0].is(TypeFlags.SIGNED | TypeFlags.INTEGER), arg0,
return module.createLoad(typeArguments[0].byteSize, typeArguments[0].is(TypeFlags.SIGNED | TypeFlags.INTEGER), arg0, typeArguments[0].toNativeType(), offset); typeArguments[0].is(TypeFlags.INTEGER) && contextualType.is(TypeFlags.INTEGER) && contextualType.size >= typeArguments[0].size
? (compiler.currentType = contextualType).toNativeType()
: (compiler.currentType = typeArguments[0]).toNativeType()
, offset);
case "store": // store<T?>(offset: usize, value: T, constantOffset?: usize) -> void case "store": // store<T!>(offset: usize, value: *, constantOffset?: usize) -> void
compiler.currentType = Type.void; compiler.currentType = Type.void;
if (operands.length < 2 || operands.length > 3) { if (operands.length < 2 || operands.length > 3) {
if (typeArguments && typeArguments.length != 1) if (!(typeArguments && typeArguments.length == 1))
compiler.error(DiagnosticCode.Expected_0_type_arguments_but_got_1, reportNode.range, "1", typeArguments.length.toString(10)); compiler.error(DiagnosticCode.Expected_0_type_arguments_but_got_1, reportNode.range, "1", typeArguments ? typeArguments.length.toString(10) : "0");
if (operands.length < 2) if (operands.length < 2)
compiler.error(DiagnosticCode.Expected_at_least_0_arguments_but_got_1, reportNode.range, "2", operands.length.toString(10)); compiler.error(DiagnosticCode.Expected_at_least_0_arguments_but_got_1, reportNode.range, "2", operands.length.toString(10));
else else
compiler.error(DiagnosticCode.Expected_0_arguments_but_got_1, reportNode.range, "3", operands.length.toString(10)); compiler.error(DiagnosticCode.Expected_0_arguments_but_got_1, reportNode.range, "3", operands.length.toString(10));
return module.createUnreachable(); return module.createUnreachable();
} }
if (typeArguments) { if (!(typeArguments && typeArguments.length == 1)) {
if (typeArguments.length != 1) { compiler.error(DiagnosticCode.Expected_0_type_arguments_but_got_1, reportNode.range, "1", typeArguments ? typeArguments.length.toString(10) : "0");
compiler.error(DiagnosticCode.Expected_0_type_arguments_but_got_1, reportNode.range, "1", typeArguments.length.toString(10)); return module.createUnreachable();
return module.createUnreachable();
}
arg0 = compiler.compileExpression(operands[0], compiler.options.usizeType);
arg1 = compiler.compileExpression(operands[1], typeArguments[0]);
} else {
arg0 = compiler.compileExpression(operands[0], compiler.options.usizeType);
arg1 = compiler.compileExpression(operands[1], Type.i32, ConversionKind.NONE);
} }
type = compiler.currentType; arg0 = compiler.compileExpression(operands[0], compiler.options.usizeType);
arg1 = compiler.compileExpression(operands[1], typeArguments[0],
typeArguments[0].is(TypeFlags.INTEGER)
? ConversionKind.NONE // wraps a larger integer type to a smaller one, i.e. i32.store8
: ConversionKind.IMPLICIT
);
if (compiler.currentType.is(TypeFlags.INTEGER) && typeArguments[0].is(TypeFlags.INTEGER) && typeArguments[0].size > compiler.currentType.size) {
arg1 = compiler.convertExpression(arg1, compiler.currentType, typeArguments[0], ConversionKind.IMPLICIT, operands[1]);
type = typeArguments[0];
} else
type = compiler.currentType;
offset = operands.length == 3 ? evaluateConstantOffset(compiler, operands[2]) : 0; // reports offset = operands.length == 3 ? evaluateConstantOffset(compiler, operands[2]) : 0; // reports
if (offset < 0) if (offset < 0)
return module.createUnreachable(); return module.createUnreachable();
compiler.currentType = Type.void; compiler.currentType = Type.void;
return module.createStore(type.byteSize, arg0, arg1, type.toNativeType(), offset); return module.createStore(typeArguments[0].byteSize, arg0, arg1, type.toNativeType(), offset);
case "sizeof": // sizeof<T!>() -> usize case "sizeof": // sizeof<T!>() -> usize
compiler.currentType = compiler.options.usizeType; compiler.currentType = compiler.options.usizeType;

View File

@ -578,15 +578,15 @@ export class Compiler extends DiagnosticEmitter {
// compile statements // compile statements
var stmts: ExpressionRef[] | null = null; var stmts: ExpressionRef[] | null = null;
if (!instance.is(ElementFlags.DECLARED)) { if (!instance.is(ElementFlags.DECLARED)) {
declaration = assert(declaration); declaration = assert(declaration, "declaration expected");
var previousFunction = this.currentFunction; var previousFunction = this.currentFunction;
this.currentFunction = instance; this.currentFunction = instance;
var statements = assert(declaration.statements); var statements = assert(declaration.statements, "implementation expected");
stmts = this.compileStatements(statements); stmts = this.compileStatements(statements);
// make sure the top-level branch or all child branches return // make sure the top-level branch or all child branches return
var allBranchesReturn = this.currentFunction.flow.finalize(); var allBranchesReturn = this.currentFunction.flow.finalize();
if (instance.returnType != Type.void && !allBranchesReturn) if (instance.returnType != Type.void && !allBranchesReturn)
this.error(DiagnosticCode.A_function_whose_declared_type_is_not_void_must_return_a_value, assert(declaration.returnType).range); this.error(DiagnosticCode.A_function_whose_declared_type_is_not_void_must_return_a_value, assert(declaration.returnType, "return type expected").range);
this.currentFunction = previousFunction; this.currentFunction = previousFunction;
} }
@ -895,6 +895,7 @@ export class Compiler extends DiagnosticEmitter {
this.error(DiagnosticCode.A_break_statement_can_only_be_used_within_an_enclosing_iteration_or_switch_statement, statement.range); this.error(DiagnosticCode.A_break_statement_can_only_be_used_within_an_enclosing_iteration_or_switch_statement, statement.range);
return this.module.createUnreachable(); return this.module.createUnreachable();
} }
this.currentFunction.flow.set(FlowFlags.POSSIBLY_BREAKS);
return this.module.createBreak(breakLabel); return this.module.createBreak(breakLabel);
} }
@ -909,6 +910,7 @@ export class Compiler extends DiagnosticEmitter {
this.error(DiagnosticCode.A_continue_statement_can_only_be_used_within_an_enclosing_iteration_statement, statement.range); this.error(DiagnosticCode.A_continue_statement_can_only_be_used_within_an_enclosing_iteration_statement, statement.range);
return this.module.createUnreachable(); return this.module.createUnreachable();
} }
this.currentFunction.flow.set(FlowFlags.POSSIBLY_CONTINUES);
return this.module.createBreak(continueLabel); return this.module.createBreak(continueLabel);
} }
@ -1022,8 +1024,6 @@ export class Compiler extends DiagnosticEmitter {
} }
compileReturnStatement(statement: ReturnStatement): ExpressionRef { compileReturnStatement(statement: ReturnStatement): ExpressionRef {
assert(this.currentFunction);
var expression: ExpressionRef = 0; var expression: ExpressionRef = 0;
if (statement.value) if (statement.value)
expression = this.compileExpression(<Expression>statement.value, this.currentFunction.returnType); expression = this.compileExpression(<Expression>statement.value, this.currentFunction.returnType);
@ -1353,7 +1353,7 @@ export class Compiler extends DiagnosticEmitter {
convertExpression(expr: ExpressionRef, fromType: Type, toType: Type, conversionKind: ConversionKind, reportNode: Node): ExpressionRef { convertExpression(expr: ExpressionRef, fromType: Type, toType: Type, conversionKind: ConversionKind, reportNode: Node): ExpressionRef {
if (conversionKind == ConversionKind.NONE) { if (conversionKind == ConversionKind.NONE) {
assert(false); assert(false, "concrete type expected");
return expr; return expr;
} }
@ -1437,7 +1437,7 @@ export class Compiler extends DiagnosticEmitter {
// float to void // float to void
} else { } else {
assert(toType.flags == TypeFlags.NONE); assert(toType.flags == TypeFlags.NONE, "void type expected");
expr = this.module.createDrop(expr); expr = this.module.createDrop(expr);
} }
@ -2296,11 +2296,10 @@ export class Compiler extends DiagnosticEmitter {
// otherwise make use of the temp. local // otherwise make use of the temp. local
else { else {
assert(tempLocal);
expr = this.module.createIf( expr = this.module.createIf(
condition, condition,
right, right,
this.module.createGetLocal((<Local>tempLocal).index, this.currentType.toNativeType()) this.module.createGetLocal(assert(tempLocal, "tempLocal must be set").index, this.currentType.toNativeType())
); );
} }
break; break;
@ -2331,10 +2330,9 @@ export class Compiler extends DiagnosticEmitter {
// otherwise make use of the temp. local // otherwise make use of the temp. local
else { else {
assert(tempLocal);
expr = this.module.createIf( expr = this.module.createIf(
condition, condition,
this.module.createGetLocal((<Local>tempLocal).index, this.currentType.toNativeType()), this.module.createGetLocal(assert(tempLocal, "tempLocal must be set").index, this.currentType.toNativeType()),
right right
); );
} }
@ -2345,7 +2343,7 @@ export class Compiler extends DiagnosticEmitter {
throw new Error("not implemented"); throw new Error("not implemented");
} }
if (possiblyOverflows && wrapSmallIntegers) { if (possiblyOverflows && wrapSmallIntegers) {
assert(this.currentType.is(TypeFlags.SMALL | TypeFlags.INTEGER)); assert(this.currentType.is(TypeFlags.SMALL | TypeFlags.INTEGER)), "small integer type expected";
expr = makeSmallIntegerWrap(expr, this.currentType, this.module); expr = makeSmallIntegerWrap(expr, this.currentType, this.module);
} }
return compound return compound
@ -2366,7 +2364,7 @@ export class Compiler extends DiagnosticEmitter {
case ElementKind.GLOBAL: case ElementKind.GLOBAL:
if (!this.compileGlobal(<Global>element)) // reports; not yet compiled if a static field compiled as a global if (!this.compileGlobal(<Global>element)) // reports; not yet compiled if a static field compiled as a global
return this.module.createUnreachable(); return this.module.createUnreachable();
assert((<Global>element).type != Type.void); assert((<Global>element).type != Type.void, "concrete type expected");
// fall-through // fall-through
case ElementKind.LOCAL: case ElementKind.LOCAL:
@ -2429,7 +2427,7 @@ export class Compiler extends DiagnosticEmitter {
case ElementKind.GLOBAL: case ElementKind.GLOBAL:
if (!this.compileGlobal(<Global>element)) // reports; not yet compiled if a static field compiled as a global if (!this.compileGlobal(<Global>element)) // reports; not yet compiled if a static field compiled as a global
return this.module.createUnreachable(); return this.module.createUnreachable();
assert((<Global>element).type != Type.void); assert((<Global>element).type != Type.void, "concrete type expected");
this.currentType = tee ? (<Global>element).type : Type.void; this.currentType = tee ? (<Global>element).type : Type.void;
if ((<Local>element).is(ElementFlags.CONSTANT)) { if ((<Local>element).is(ElementFlags.CONSTANT)) {
this.error(DiagnosticCode.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property, expression.range, (<Local>element).internalName); this.error(DiagnosticCode.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property, expression.range, (<Local>element).internalName);
@ -2448,9 +2446,9 @@ export class Compiler extends DiagnosticEmitter {
this.error(DiagnosticCode.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property, expression.range, (<Field>element).internalName); this.error(DiagnosticCode.Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property, expression.range, (<Field>element).internalName);
return this.module.createUnreachable(); return this.module.createUnreachable();
} }
assert(resolved.targetExpression != null); assert(resolved.targetExpression != null, "target expression expected");
targetExpr = this.compileExpression(<Expression>resolved.targetExpression, this.options.target == Target.WASM64 ? Type.usize64 : Type.usize32, ConversionKind.NONE); targetExpr = this.compileExpression(<Expression>resolved.targetExpression, this.options.target == Target.WASM64 ? Type.usize64 : Type.usize32, ConversionKind.NONE);
assert(this.currentType.classType); assert(this.currentType.classType, "class type expected");
this.currentType = tee ? (<Field>element).type : Type.void; this.currentType = tee ? (<Field>element).type : Type.void;
var elementNativeType = (<Field>element).type.toNativeType(); var elementNativeType = (<Field>element).type.toNativeType();
if (!tee) if (!tee)

View File

@ -240,7 +240,8 @@ export class Module {
ref: ModuleRef; ref: ModuleRef;
lit: BinaryenLiteral; lit: BinaryenLiteral;
static MAX_MEMORY_WASM32: Index = 0xffff; static readonly MAX_MEMORY_WASM32: Index = 0xffff;
// TODO: static readonly MAX_MEMORY_WASM64
static create(): Module { static create(): Module {
var module = new Module(); var module = new Module();

View File

@ -2134,6 +2134,10 @@ export const enum FlowFlags {
RETURNS = 1 << 0, RETURNS = 1 << 0,
/** This branch possibly throws. */ /** This branch possibly throws. */
POSSIBLY_THROWS = 1 << 1, POSSIBLY_THROWS = 1 << 1,
/** This branch possible breaks. */
POSSIBLY_BREAKS = 1 << 2,
/** This branch possible continues. */
POSSIBLY_CONTINUES = 1 << 3
} }
/** A control flow evaluator. */ /** A control flow evaluator. */
@ -2185,17 +2189,22 @@ export class Flow {
/** Leaves the current branch or scope and returns the parent flow. */ /** Leaves the current branch or scope and returns the parent flow. */
leaveBranchOrScope(): Flow { leaveBranchOrScope(): Flow {
var parent = assert(this.parent); var parent = assert(this.parent);
// Free block-scoped locals
if (this.scopedLocals) { if (this.scopedLocals) {
for (var scopedLocal of this.scopedLocals.values()) for (var scopedLocal of this.scopedLocals.values())
this.currentFunction.freeTempLocal(scopedLocal); this.currentFunction.freeTempLocal(scopedLocal);
this.scopedLocals = null; this.scopedLocals = null;
} }
// Mark parent as THROWS if any child throws
if (this.is(FlowFlags.POSSIBLY_THROWS))
parent.set(FlowFlags.POSSIBLY_THROWS);
this.continueLabel = null; // Propagate flags to parent
this.breakLabel = null; if (this.is(FlowFlags.POSSIBLY_THROWS))
parent.set(FlowFlags.POSSIBLY_THROWS);
if (this.is(FlowFlags.POSSIBLY_BREAKS) && parent.breakLabel == this.breakLabel)
parent.set(FlowFlags.POSSIBLY_BREAKS);
if (this.is(FlowFlags.POSSIBLY_CONTINUES) && parent.continueLabel == this.continueLabel)
parent.set(FlowFlags.POSSIBLY_CONTINUES);
return parent; return parent;
} }

4
std/assembly.d.ts vendored
View File

@ -155,9 +155,9 @@ declare function sqrt<T = f32 | f64>(value: T): T;
/** Rounds to the nearest integer towards zero of a 32-bit or 64-bit float. */ /** Rounds to the nearest integer towards zero of a 32-bit or 64-bit float. */
declare function trunc<T = f32 | f64>(value: T): T; declare function trunc<T = f32 | f64>(value: T): T;
/** Loads a value of the specified type from memory. Equivalent to dereferncing a pointer in other languages. */ /** Loads a value of the specified type from memory. Equivalent to dereferncing a pointer in other languages. */
declare function load<T>(ptr: usize, constantOffset?: usize): T; declare function load<T>(ptr: usize, constantOffset?: usize): any;
/** Stores a value of the specified type to memory. Equivalent to dereferencing a pointer in other languages when assigning a value. */ /** Stores a value of the specified type to memory. Equivalent to dereferencing a pointer in other languages when assigning a value. */
declare function store<T>(ptr: usize, value: T, constantOffset?: usize): void; declare function store<T>(ptr: usize, value: any, constantOffset?: usize): void;
/** Returns the current memory size in units of pages. One page is 64kb. */ /** Returns the current memory size in units of pages. One page is 64kb. */
declare function current_memory(): i32; declare function current_memory(): i32;
/** Grows linear memory by a given unsigned delta of pages. One page is 64kb. Returns the previous memory size in units of pages or `-1` on failure. */ /** Grows linear memory by a given unsigned delta of pages. One page is 64kb. Returns the previous memory size in units of pages or `-1` on failure. */

View File

@ -5,6 +5,8 @@
(global $builtins/I (mut i64) (i64.const 0)) (global $builtins/I (mut i64) (i64.const 0))
(global $builtins/f (mut f32) (f32.const 0)) (global $builtins/f (mut f32) (f32.const 0))
(global $builtins/F (mut f64) (f64.const 0)) (global $builtins/F (mut f64) (f64.const 0))
(global $builtins/u (mut i32) (i32.const 0))
(global $builtins/U (mut i64) (i64.const 0))
(global $builtins/s (mut i32) (i32.const 0)) (global $builtins/s (mut i32) (i32.const 0))
(memory $0 1) (memory $0 1)
(export "test" (func $builtins/test)) (export "test" (func $builtins/test))
@ -414,6 +416,138 @@
(i32.const 8) (i32.const 8)
) )
) )
(set_global $builtins/i
(i32.load8_s
(i32.const 8)
)
)
(set_global $builtins/i
(i32.load16_s
(i32.const 8)
)
)
(set_global $builtins/i
(i32.load
(i32.const 8)
)
)
(set_global $builtins/i
(i32.load8_u
(i32.const 8)
)
)
(set_global $builtins/i
(i32.load16_u
(i32.const 8)
)
)
(set_global $builtins/i
(i32.load
(i32.const 8)
)
)
(set_global $builtins/u
(i32.load8_u
(i32.const 8)
)
)
(set_global $builtins/u
(i32.load16_u
(i32.const 8)
)
)
(set_global $builtins/u
(i32.load
(i32.const 8)
)
)
(set_global $builtins/u
(i32.load8_s
(i32.const 8)
)
)
(set_global $builtins/u
(i32.load16_s
(i32.const 8)
)
)
(set_global $builtins/u
(i32.load
(i32.const 8)
)
)
(set_global $builtins/I
(i64.load8_s
(i32.const 8)
)
)
(set_global $builtins/I
(i64.load16_s
(i32.const 8)
)
)
(set_global $builtins/I
(i64.load32_s
(i32.const 8)
)
)
(set_global $builtins/I
(i64.load
(i32.const 8)
)
)
(set_global $builtins/U
(i64.load8_u
(i32.const 8)
)
)
(set_global $builtins/U
(i64.load16_u
(i32.const 8)
)
)
(set_global $builtins/U
(i64.load32_u
(i32.const 8)
)
)
(set_global $builtins/U
(i64.load
(i32.const 8)
)
)
(i32.store8
(i32.const 8)
(i32.const 1)
)
(i32.store16
(i32.const 8)
(i32.const 1)
)
(i32.store
(i32.const 8)
(i32.const 1)
)
(i64.store8
(i32.const 8)
(i64.const 1)
)
(i64.store16
(i32.const 8)
(i64.const 1)
)
(i64.store32
(i32.const 8)
(i64.const 1)
)
(i64.store
(i32.const 8)
(i64.const 1)
)
(i64.store
(i32.const 8)
(i64.const 1)
)
(set_global $builtins/i (set_global $builtins/i
(i32.const 1067450368) (i32.const 1067450368)
) )

View File

@ -125,6 +125,47 @@ store<f32>(0, load<f32>(0, constantOffset), constantOffset);
F = load<f64>(0, constantOffset); store<f64>(0, F, constantOffset); F = load<f64>(0, constantOffset); store<f64>(0, F, constantOffset);
store<f64>(0, load<f64>(0, constantOffset), constantOffset); store<f64>(0, load<f64>(0, constantOffset), constantOffset);
// load and store smaller types
i = load<i8>(8);
i = load<i16>(8);
i = load<i32>(8);
i = load<u8>(8);
i = load<u16>(8);
i = load<u32>(8);
var u: u32;
u = load<u8>(8);
u = load<u16>(8);
u = load<u32>(8);
u = load<i8>(8);
u = load<i16>(8);
u = load<i32>(8);
I = load<i8>(8);
I = load<i16>(8);
I = load<i32>(8);
I = load<i64>(8);
var U: u64;
U = load<u8>(8);
U = load<u16>(8);
U = load<u32>(8);
U = load<u64>(8);
store<i8>(8, <i32>1);
store<i16>(8, <i32>1);
store<i32>(8, <i32>1);
store<i8>(8, <i64>1);
store<i16>(8, <i64>1);
store<i32>(8, <i64>1);
store<i64>(8, <i64>1);
store<i64>(8, <i32>1); // must extend
// reinterpretation // reinterpretation
reinterpret<i32>(1.25); reinterpret<i32>(1.25);

View File

@ -7,6 +7,8 @@
(global $builtins/f (mut f32) (f32.const 0)) (global $builtins/f (mut f32) (f32.const 0))
(global $builtins/F (mut f64) (f64.const 0)) (global $builtins/F (mut f64) (f64.const 0))
(global $builtins/constantOffset i32 (i32.const 8)) (global $builtins/constantOffset i32 (i32.const 8))
(global $builtins/u (mut i32) (i32.const 0))
(global $builtins/U (mut i64) (i64.const 0))
(global $builtins/s (mut i32) (i32.const 0)) (global $builtins/s (mut i32) (i32.const 0))
(global $i8.MIN_VALUE i32 (i32.const -128)) (global $i8.MIN_VALUE i32 (i32.const -128))
(global $i8.MAX_VALUE i32 (i32.const 127)) (global $i8.MAX_VALUE i32 (i32.const 127))
@ -810,6 +812,140 @@
(i32.const 0) (i32.const 0)
) )
) )
(set_global $builtins/i
(i32.load8_s
(i32.const 8)
)
)
(set_global $builtins/i
(i32.load16_s
(i32.const 8)
)
)
(set_global $builtins/i
(i32.load
(i32.const 8)
)
)
(set_global $builtins/i
(i32.load8_u
(i32.const 8)
)
)
(set_global $builtins/i
(i32.load16_u
(i32.const 8)
)
)
(set_global $builtins/i
(i32.load
(i32.const 8)
)
)
(set_global $builtins/u
(i32.load8_u
(i32.const 8)
)
)
(set_global $builtins/u
(i32.load16_u
(i32.const 8)
)
)
(set_global $builtins/u
(i32.load
(i32.const 8)
)
)
(set_global $builtins/u
(i32.load8_s
(i32.const 8)
)
)
(set_global $builtins/u
(i32.load16_s
(i32.const 8)
)
)
(set_global $builtins/u
(i32.load
(i32.const 8)
)
)
(set_global $builtins/I
(i64.load8_s
(i32.const 8)
)
)
(set_global $builtins/I
(i64.load16_s
(i32.const 8)
)
)
(set_global $builtins/I
(i64.load32_s
(i32.const 8)
)
)
(set_global $builtins/I
(i64.load
(i32.const 8)
)
)
(set_global $builtins/U
(i64.load8_u
(i32.const 8)
)
)
(set_global $builtins/U
(i64.load16_u
(i32.const 8)
)
)
(set_global $builtins/U
(i64.load32_u
(i32.const 8)
)
)
(set_global $builtins/U
(i64.load
(i32.const 8)
)
)
(i32.store8
(i32.const 8)
(i32.const 1)
)
(i32.store16
(i32.const 8)
(i32.const 1)
)
(i32.store
(i32.const 8)
(i32.const 1)
)
(i64.store8
(i32.const 8)
(i64.const 1)
)
(i64.store16
(i32.const 8)
(i64.const 1)
)
(i64.store32
(i32.const 8)
(i64.const 1)
)
(i64.store
(i32.const 8)
(i64.const 1)
)
(i64.store
(i32.const 8)
(i64.extend_s/i32
(i32.const 1)
)
)
(drop (drop
(i32.reinterpret/f32 (i32.reinterpret/f32
(f32.const 1.25) (f32.const 1.25)
@ -1454,6 +1590,8 @@
GLOBAL: builtins/f GLOBAL: builtins/f
GLOBAL: builtins/F GLOBAL: builtins/F
GLOBAL: builtins/constantOffset GLOBAL: builtins/constantOffset
GLOBAL: builtins/u
GLOBAL: builtins/U
GLOBAL: builtins/s GLOBAL: builtins/s
FUNCTION_PROTOTYPE: builtins/test FUNCTION_PROTOTYPE: builtins/test
[program.exports] [program.exports]

View File

@ -84,39 +84,28 @@
) )
(block (block
(set_local $2 (set_local $2
(i32.and (i32.add
(i32.add (i32.add
(i32.add (i32.add
(i32.add (i32.add
(i32.add (i32.add
(i32.add (i32.add
(i32.add (i32.add
(i32.add (i32.load8_u
(i32.load8_u (i32.add
(i32.add (i32.mul
(i32.mul (get_local $3)
(get_local $3) (get_global $../../examples/game-of-life/assembly/game-of-life/w)
(get_global $../../examples/game-of-life/assembly/game-of-life/w)
)
(tee_local $2
(select
(i32.sub
(get_local $1)
(i32.const 1)
)
(get_local $6)
(get_local $1)
)
)
) )
) (tee_local $2
(i32.load8_u (select
(i32.add (i32.sub
(i32.mul (get_local $1)
(get_local $3) (i32.const 1)
(get_global $../../examples/game-of-life/assembly/game-of-life/w) )
(get_local $6)
(get_local $1)
) )
(get_local $1)
) )
) )
) )
@ -126,29 +115,29 @@
(get_local $3) (get_local $3)
(get_global $../../examples/game-of-life/assembly/game-of-life/w) (get_global $../../examples/game-of-life/assembly/game-of-life/w)
) )
(tee_local $7 (get_local $1)
(select
(i32.const 0)
(i32.add
(get_local $1)
(i32.const 1)
)
(i32.eq
(get_local $1)
(get_local $6)
)
)
)
) )
) )
) )
(i32.load8_u (i32.load8_u
(i32.add (i32.add
(i32.mul (i32.mul
(get_local $0) (get_local $3)
(get_global $../../examples/game-of-life/assembly/game-of-life/w) (get_global $../../examples/game-of-life/assembly/game-of-life/w)
) )
(get_local $2) (tee_local $7
(select
(i32.const 0)
(i32.add
(get_local $1)
(i32.const 1)
)
(i32.eq
(get_local $1)
(get_local $6)
)
)
)
) )
) )
) )
@ -158,17 +147,17 @@
(get_local $0) (get_local $0)
(get_global $../../examples/game-of-life/assembly/game-of-life/w) (get_global $../../examples/game-of-life/assembly/game-of-life/w)
) )
(get_local $7) (get_local $2)
) )
) )
) )
(i32.load8_u (i32.load8_u
(i32.add (i32.add
(i32.mul (i32.mul
(get_local $4) (get_local $0)
(get_global $../../examples/game-of-life/assembly/game-of-life/w) (get_global $../../examples/game-of-life/assembly/game-of-life/w)
) )
(get_local $2) (get_local $7)
) )
) )
) )
@ -178,7 +167,7 @@
(get_local $4) (get_local $4)
(get_global $../../examples/game-of-life/assembly/game-of-life/w) (get_global $../../examples/game-of-life/assembly/game-of-life/w)
) )
(get_local $1) (get_local $2)
) )
) )
) )
@ -188,11 +177,19 @@
(get_local $4) (get_local $4)
(get_global $../../examples/game-of-life/assembly/game-of-life/w) (get_global $../../examples/game-of-life/assembly/game-of-life/w)
) )
(get_local $7) (get_local $1)
) )
) )
) )
(i32.const 255) (i32.load8_u
(i32.add
(i32.mul
(get_local $4)
(get_global $../../examples/game-of-life/assembly/game-of-life/w)
)
(get_local $7)
)
)
) )
) )
(if (if
@ -208,15 +205,15 @@
(if (if
(i32.and (i32.and
(select (select
(i32.lt_u (i32.lt_s
(get_local $2) (get_local $2)
(i32.const 2) (i32.const 2)
) )
(i32.gt_u (i32.gt_s
(get_local $2) (get_local $2)
(i32.const 3) (i32.const 3)
) )
(i32.lt_u (i32.lt_s
(get_local $2) (get_local $2)
(i32.const 2) (i32.const 2)
) )

View File

@ -128,31 +128,20 @@
) )
) )
(set_local $8 (set_local $8
(i32.and (i32.add
(i32.add (i32.add
(i32.add (i32.add
(i32.add (i32.add
(i32.add (i32.add
(i32.add (i32.add
(i32.add (i32.add
(i32.add (i32.load8_u
(i32.load8_u (i32.add
(i32.add (i32.mul
(i32.mul (get_local $3)
(get_local $3) (get_global $../../examples/game-of-life/assembly/game-of-life/w)
(get_global $../../examples/game-of-life/assembly/game-of-life/w)
)
(get_local $6)
)
)
(i32.load8_u
(i32.add
(i32.mul
(get_local $3)
(get_global $../../examples/game-of-life/assembly/game-of-life/w)
)
(get_local $5)
) )
(get_local $6)
) )
) )
(i32.load8_u (i32.load8_u
@ -161,17 +150,17 @@
(get_local $3) (get_local $3)
(get_global $../../examples/game-of-life/assembly/game-of-life/w) (get_global $../../examples/game-of-life/assembly/game-of-life/w)
) )
(get_local $7) (get_local $5)
) )
) )
) )
(i32.load8_u (i32.load8_u
(i32.add (i32.add
(i32.mul (i32.mul
(get_local $2) (get_local $3)
(get_global $../../examples/game-of-life/assembly/game-of-life/w) (get_global $../../examples/game-of-life/assembly/game-of-life/w)
) )
(get_local $6) (get_local $7)
) )
) )
) )
@ -181,17 +170,17 @@
(get_local $2) (get_local $2)
(get_global $../../examples/game-of-life/assembly/game-of-life/w) (get_global $../../examples/game-of-life/assembly/game-of-life/w)
) )
(get_local $7) (get_local $6)
) )
) )
) )
(i32.load8_u (i32.load8_u
(i32.add (i32.add
(i32.mul (i32.mul
(get_local $4) (get_local $2)
(get_global $../../examples/game-of-life/assembly/game-of-life/w) (get_global $../../examples/game-of-life/assembly/game-of-life/w)
) )
(get_local $6) (get_local $7)
) )
) )
) )
@ -201,7 +190,7 @@
(get_local $4) (get_local $4)
(get_global $../../examples/game-of-life/assembly/game-of-life/w) (get_global $../../examples/game-of-life/assembly/game-of-life/w)
) )
(get_local $5) (get_local $6)
) )
) )
) )
@ -211,11 +200,19 @@
(get_local $4) (get_local $4)
(get_global $../../examples/game-of-life/assembly/game-of-life/w) (get_global $../../examples/game-of-life/assembly/game-of-life/w)
) )
(get_local $7) (get_local $5)
) )
) )
) )
(i32.const 255) (i32.load8_u
(i32.add
(i32.mul
(get_local $4)
(get_global $../../examples/game-of-life/assembly/game-of-life/w)
)
(get_local $7)
)
)
) )
) )
(if (if
@ -232,17 +229,17 @@
(i32.and (i32.and
(if (result i32) (if (result i32)
(i32.ne (i32.ne
(i32.lt_u (i32.lt_s
(get_local $8) (get_local $8)
(i32.const 2) (i32.const 2)
) )
(i32.const 0) (i32.const 0)
) )
(i32.lt_u (i32.lt_s
(get_local $8) (get_local $8)
(i32.const 2) (i32.const 2)
) )
(i32.gt_u (i32.gt_s
(get_local $8) (get_local $8)
(i32.const 3) (i32.const 3)
) )

View File

@ -24,6 +24,8 @@
(global $builtins/I (mut i64) (i64.const 0)) (global $builtins/I (mut i64) (i64.const 0))
(global $builtins/f (mut f32) (f32.const 0)) (global $builtins/f (mut f32) (f32.const 0))
(global $builtins/F (mut f64) (f64.const 0)) (global $builtins/F (mut f64) (f64.const 0))
(global $builtins/u (mut i32) (i32.const 0))
(global $builtins/U (mut i64) (i64.const 0))
(global $builtins/s (mut i32) (i32.const 0)) (global $builtins/s (mut i32) (i32.const 0))
(global $showcase/ANamespace.aNamespacedGlobal (mut i32) (i32.const 42)) (global $showcase/ANamespace.aNamespacedGlobal (mut i32) (i32.const 42))
(global $showcase/AnEnum.ONE i32 (i32.const 1)) (global $showcase/AnEnum.ONE i32 (i32.const 1))
@ -3658,6 +3660,138 @@
(i32.const 8) (i32.const 8)
) )
) )
(set_global $builtins/i
(i32.load8_s
(i32.const 8)
)
)
(set_global $builtins/i
(i32.load16_s
(i32.const 8)
)
)
(set_global $builtins/i
(i32.load
(i32.const 8)
)
)
(set_global $builtins/i
(i32.load8_u
(i32.const 8)
)
)
(set_global $builtins/i
(i32.load16_u
(i32.const 8)
)
)
(set_global $builtins/i
(i32.load
(i32.const 8)
)
)
(set_global $builtins/u
(i32.load8_u
(i32.const 8)
)
)
(set_global $builtins/u
(i32.load16_u
(i32.const 8)
)
)
(set_global $builtins/u
(i32.load
(i32.const 8)
)
)
(set_global $builtins/u
(i32.load8_s
(i32.const 8)
)
)
(set_global $builtins/u
(i32.load16_s
(i32.const 8)
)
)
(set_global $builtins/u
(i32.load
(i32.const 8)
)
)
(set_global $builtins/I
(i64.load8_s
(i32.const 8)
)
)
(set_global $builtins/I
(i64.load16_s
(i32.const 8)
)
)
(set_global $builtins/I
(i64.load32_s
(i32.const 8)
)
)
(set_global $builtins/I
(i64.load
(i32.const 8)
)
)
(set_global $builtins/U
(i64.load8_u
(i32.const 8)
)
)
(set_global $builtins/U
(i64.load16_u
(i32.const 8)
)
)
(set_global $builtins/U
(i64.load32_u
(i32.const 8)
)
)
(set_global $builtins/U
(i64.load
(i32.const 8)
)
)
(i32.store8
(i32.const 8)
(i32.const 1)
)
(i32.store16
(i32.const 8)
(i32.const 1)
)
(i32.store
(i32.const 8)
(i32.const 1)
)
(i64.store8
(i32.const 8)
(i64.const 1)
)
(i64.store16
(i32.const 8)
(i64.const 1)
)
(i64.store32
(i32.const 8)
(i64.const 1)
)
(i64.store
(i32.const 8)
(i64.const 1)
)
(i64.store
(i32.const 8)
(i64.const 1)
)
(set_global $builtins/i (set_global $builtins/i
(i32.const 1067450368) (i32.const 1067450368)
) )

View File

@ -34,6 +34,8 @@
(global $builtins/f (mut f32) (f32.const 0)) (global $builtins/f (mut f32) (f32.const 0))
(global $builtins/F (mut f64) (f64.const 0)) (global $builtins/F (mut f64) (f64.const 0))
(global $builtins/constantOffset i32 (i32.const 8)) (global $builtins/constantOffset i32 (i32.const 8))
(global $builtins/u (mut i32) (i32.const 0))
(global $builtins/U (mut i64) (i64.const 0))
(global $builtins/s (mut i32) (i32.const 0)) (global $builtins/s (mut i32) (i32.const 0))
(global $i8.MIN_VALUE i32 (i32.const -128)) (global $i8.MIN_VALUE i32 (i32.const -128))
(global $i8.MAX_VALUE i32 (i32.const 127)) (global $i8.MAX_VALUE i32 (i32.const 127))
@ -5195,6 +5197,140 @@
(i32.const 0) (i32.const 0)
) )
) )
(set_global $builtins/i
(i32.load8_s
(i32.const 8)
)
)
(set_global $builtins/i
(i32.load16_s
(i32.const 8)
)
)
(set_global $builtins/i
(i32.load
(i32.const 8)
)
)
(set_global $builtins/i
(i32.load8_u
(i32.const 8)
)
)
(set_global $builtins/i
(i32.load16_u
(i32.const 8)
)
)
(set_global $builtins/i
(i32.load
(i32.const 8)
)
)
(set_global $builtins/u
(i32.load8_u
(i32.const 8)
)
)
(set_global $builtins/u
(i32.load16_u
(i32.const 8)
)
)
(set_global $builtins/u
(i32.load
(i32.const 8)
)
)
(set_global $builtins/u
(i32.load8_s
(i32.const 8)
)
)
(set_global $builtins/u
(i32.load16_s
(i32.const 8)
)
)
(set_global $builtins/u
(i32.load
(i32.const 8)
)
)
(set_global $builtins/I
(i64.load8_s
(i32.const 8)
)
)
(set_global $builtins/I
(i64.load16_s
(i32.const 8)
)
)
(set_global $builtins/I
(i64.load32_s
(i32.const 8)
)
)
(set_global $builtins/I
(i64.load
(i32.const 8)
)
)
(set_global $builtins/U
(i64.load8_u
(i32.const 8)
)
)
(set_global $builtins/U
(i64.load16_u
(i32.const 8)
)
)
(set_global $builtins/U
(i64.load32_u
(i32.const 8)
)
)
(set_global $builtins/U
(i64.load
(i32.const 8)
)
)
(i32.store8
(i32.const 8)
(i32.const 1)
)
(i32.store16
(i32.const 8)
(i32.const 1)
)
(i32.store
(i32.const 8)
(i32.const 1)
)
(i64.store8
(i32.const 8)
(i64.const 1)
)
(i64.store16
(i32.const 8)
(i64.const 1)
)
(i64.store32
(i32.const 8)
(i64.const 1)
)
(i64.store
(i32.const 8)
(i64.const 1)
)
(i64.store
(i32.const 8)
(i64.extend_s/i32
(i32.const 1)
)
)
(drop (drop
(i32.reinterpret/f32 (i32.reinterpret/f32
(f32.const 1.25) (f32.const 1.25)
@ -6369,6 +6505,8 @@
GLOBAL: builtins/f GLOBAL: builtins/f
GLOBAL: builtins/F GLOBAL: builtins/F
GLOBAL: builtins/constantOffset GLOBAL: builtins/constantOffset
GLOBAL: builtins/u
GLOBAL: builtins/U
GLOBAL: builtins/s GLOBAL: builtins/s
FUNCTION_PROTOTYPE: builtins/test FUNCTION_PROTOTYPE: builtins/test
FUNCTION_PROTOTYPE: memcpy/memcpy FUNCTION_PROTOTYPE: memcpy/memcpy