diff --git a/src/compiler.ts b/src/compiler.ts index 671dbefb..4db27486 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -1123,6 +1123,9 @@ export class Compiler extends DiagnosticEmitter { let right: ExpressionRef; let compound: Token = 0; + let condition: ExpressionRef; + let tempLocal: Local; + switch (expression.operator) { case Token.LESSTHAN: @@ -1340,6 +1343,38 @@ export class Compiler extends DiagnosticEmitter { : BinaryOp.XorI32; break; + case Token.AMPERSAND_AMPERSAND: // left && right + left = this.compileExpression(expression.left, contextualType, contextualType == Type.void ? ConversionKind.NONE : ConversionKind.IMPLICIT); + right = this.compileExpression(expression.right, this.currentType); + tempLocal = this.currentFunction.addLocal(this.currentType); + return this.module.createIf( + this.currentType.isLongInteger + ? this.module.createBinary(BinaryOp.NeI64, this.module.createTeeLocal(tempLocal.index, left), this.module.createI64(0, 0)) + : this.currentType == Type.f64 + ? this.module.createBinary(BinaryOp.NeF64, this.module.createTeeLocal(tempLocal.index, left), this.module.createF64(0)) + : this.currentType == Type.f32 + ? this.module.createBinary(BinaryOp.NeF32, this.module.createTeeLocal(tempLocal.index, left), this.module.createF32(0)) + : this.module.createTeeLocal(tempLocal.index, left), + right, + this.module.createGetLocal(tempLocal.index, typeToNativeType(tempLocal.type)) + ); + + case Token.BAR_BAR: // left || right + left = this.compileExpression(expression.left, contextualType, contextualType == Type.void ? ConversionKind.NONE : ConversionKind.IMPLICIT); + right = this.compileExpression(expression.right, this.currentType); + tempLocal = this.currentFunction.addLocal(this.currentType); + return this.module.createIf( + this.currentType.isLongInteger + ? this.module.createBinary(BinaryOp.NeI64, this.module.createTeeLocal(tempLocal.index, left), this.module.createI64(0, 0)) + : this.currentType == Type.f64 + ? this.module.createBinary(BinaryOp.NeF64, this.module.createTeeLocal(tempLocal.index, left), this.module.createF64(0)) + : this.currentType == Type.f32 + ? this.module.createBinary(BinaryOp.NeF32, this.module.createTeeLocal(tempLocal.index, left), this.module.createF32(0)) + : this.module.createTeeLocal(tempLocal.index, left), + this.module.createGetLocal(tempLocal.index, typeToNativeType(tempLocal.type)), + right + ); + default: throw new Error("not implemented"); } @@ -2010,7 +2045,7 @@ function typeToNativeZero(module: Module, type: Type): ExpressionRef { : module.createI32(0); } -function typeToBinaryenOne(module: Module, type: Type): ExpressionRef { +function typeToNativeOne(module: Module, type: Type): ExpressionRef { return type.kind == TypeKind.F32 ? module.createF32(1) : type.kind == TypeKind.F64 diff --git a/tests/README.md b/tests/README.md index c766f909..9e16d05b 100644 --- a/tests/README.md +++ b/tests/README.md @@ -16,7 +16,7 @@ $>npm run test:parser -- --create Compiler -------- -Tests consist of a test case that is compiled to a module, converted to text format and then compared to its respective fixture. +Tests consist of a test case that is compiled to a module, validated, interpreted, converted to text format and then compared to its respective fixture. ``` $> npm run test:compiler [case name] diff --git a/tests/compiler.ts b/tests/compiler.ts index d94c235b..4c15bdeb 100644 --- a/tests/compiler.ts +++ b/tests/compiler.ts @@ -47,6 +47,7 @@ glob.sync(filter, { cwd: __dirname + "/compiler" }).forEach(filename => { const program = parser.finish(); const module = Compiler.compile(program); const actual = module.toText() + "(;\n[program.elements]\n " + iterate(program.elements.keys()).join("\n ") + "\n[program.exports]\n " + iterate(program.exports.keys()).join("\n ") + "\n;)\n"; + let actualOptimized: string | null = null; const fixture = path.basename(filename, ".ts") + ".wast"; if (module.validate()) { @@ -58,12 +59,18 @@ glob.sync(filter, { cwd: __dirname + "/compiler" }).forEach(filename => { process.exitCode = 1; console.log(chalk.default.red("interpret ERROR")); } + module.optimize(); + actualOptimized = module.toText(); } else - console.log(chalk.default.red("validate ERROR")); + console.log(chalk.default.red("validate ERROR")); if (isCreate) { fs.writeFileSync(__dirname + "/compiler/" + fixture, actual, { encoding: "utf8" }); console.log("Created"); + if (actualOptimized != null) { + fs.writeFileSync(__dirname + "/compiler/" + path.basename(filename, ".ts") + ".optimized.wast", actualOptimized, { encoding: "utf8" }); + console.log("Created optimized"); + } } else { const expected = fs.readFileSync(__dirname + "/compiler/" + fixture, { encoding: "utf8" }); const diffs = diff("compiler/" + fixture, expected, actual); diff --git a/tests/compiler/binary.optimized.wast b/tests/compiler/binary.optimized.wast new file mode 100644 index 00000000..c00d003e --- /dev/null +++ b/tests/compiler/binary.optimized.wast @@ -0,0 +1,518 @@ +(module + (type $v (func)) + (global $binary/i (mut i32) (i32.const 0)) + (global $binary/b (mut i32) (i32.const 0)) + (global $binary/I (mut i64) (i64.const 0)) + (global $binary/f (mut f32) (f32.const 0)) + (global $binary/F (mut f64) (f64.const 0)) + (memory $0 1) + (data (i32.const 4) "\08") + (export "memory" (memory $0)) + (start $start) + (func $start (; 0 ;) (type $v) + (drop + (i32.div_s + (get_global $binary/i) + (i32.const 1) + ) + ) + (drop + (i32.rem_s + (get_global $binary/i) + (i32.const 1) + ) + ) + (set_global $binary/b + (i32.lt_s + (get_global $binary/i) + (i32.const 1) + ) + ) + (set_global $binary/b + (i32.gt_s + (get_global $binary/i) + (i32.const 1) + ) + ) + (set_global $binary/b + (i32.le_s + (get_global $binary/i) + (i32.const 1) + ) + ) + (set_global $binary/b + (i32.ge_s + (get_global $binary/i) + (i32.const 1) + ) + ) + (set_global $binary/b + (i32.eq + (get_global $binary/i) + (i32.const 1) + ) + ) + (set_global $binary/b + (i32.eq + (get_global $binary/i) + (i32.const 1) + ) + ) + (set_global $binary/i + (i32.add + (get_global $binary/i) + (i32.const 1) + ) + ) + (set_global $binary/i + (i32.sub + (get_global $binary/i) + (i32.const 1) + ) + ) + (set_global $binary/i + (i32.mul + (get_global $binary/i) + (i32.const 1) + ) + ) + (set_global $binary/i + (i32.div_s + (get_global $binary/i) + (i32.const 1) + ) + ) + (set_global $binary/i + (i32.rem_s + (get_global $binary/i) + (i32.const 1) + ) + ) + (set_global $binary/i + (i32.shl + (get_global $binary/i) + (i32.const 1) + ) + ) + (set_global $binary/i + (i32.shr_s + (get_global $binary/i) + (i32.const 1) + ) + ) + (set_global $binary/i + (i32.shr_u + (get_global $binary/i) + (i32.const 1) + ) + ) + (set_global $binary/i + (i32.and + (get_global $binary/i) + (i32.const 1) + ) + ) + (set_global $binary/i + (i32.or + (get_global $binary/i) + (i32.const 1) + ) + ) + (set_global $binary/i + (i32.xor + (get_global $binary/i) + (i32.const 1) + ) + ) + (set_global $binary/i + (i32.add + (get_global $binary/i) + (i32.const 1) + ) + ) + (set_global $binary/i + (i32.sub + (get_global $binary/i) + (i32.const 1) + ) + ) + (set_global $binary/i + (i32.mul + (get_global $binary/i) + (i32.const 1) + ) + ) + (set_global $binary/i + (i32.rem_s + (get_global $binary/i) + (i32.const 1) + ) + ) + (set_global $binary/i + (i32.shl + (get_global $binary/i) + (i32.const 1) + ) + ) + (set_global $binary/i + (i32.shr_s + (get_global $binary/i) + (i32.const 1) + ) + ) + (set_global $binary/i + (i32.shr_u + (get_global $binary/i) + (i32.const 1) + ) + ) + (set_global $binary/i + (i32.and + (get_global $binary/i) + (i32.const 1) + ) + ) + (set_global $binary/i + (i32.or + (get_global $binary/i) + (i32.const 1) + ) + ) + (set_global $binary/i + (i32.xor + (get_global $binary/i) + (i32.const 1) + ) + ) + (drop + (i64.div_s + (get_global $binary/I) + (i64.const 1) + ) + ) + (drop + (i64.rem_s + (get_global $binary/I) + (i64.const 1) + ) + ) + (set_global $binary/b + (i64.lt_s + (get_global $binary/I) + (i64.const 1) + ) + ) + (set_global $binary/b + (i64.gt_s + (get_global $binary/I) + (i64.const 1) + ) + ) + (set_global $binary/b + (i64.le_s + (get_global $binary/I) + (i64.const 1) + ) + ) + (set_global $binary/b + (i64.ge_s + (get_global $binary/I) + (i64.const 1) + ) + ) + (set_global $binary/b + (i64.eq + (get_global $binary/I) + (i64.const 1) + ) + ) + (set_global $binary/b + (i64.eq + (get_global $binary/I) + (i64.const 1) + ) + ) + (set_global $binary/I + (i64.add + (get_global $binary/I) + (i64.const 1) + ) + ) + (set_global $binary/I + (i64.sub + (get_global $binary/I) + (i64.const 1) + ) + ) + (set_global $binary/I + (i64.mul + (get_global $binary/I) + (i64.const 1) + ) + ) + (set_global $binary/I + (i64.div_s + (get_global $binary/I) + (i64.const 1) + ) + ) + (set_global $binary/I + (i64.rem_s + (get_global $binary/I) + (i64.const 1) + ) + ) + (set_global $binary/I + (i64.shl + (get_global $binary/I) + (i64.const 1) + ) + ) + (set_global $binary/I + (i64.shr_s + (get_global $binary/I) + (i64.const 1) + ) + ) + (set_global $binary/I + (i64.shr_u + (get_global $binary/I) + (i64.const 1) + ) + ) + (set_global $binary/I + (i64.and + (get_global $binary/I) + (i64.const 1) + ) + ) + (set_global $binary/I + (i64.or + (get_global $binary/I) + (i64.const 1) + ) + ) + (set_global $binary/I + (i64.xor + (get_global $binary/I) + (i64.const 1) + ) + ) + (set_global $binary/I + (i64.add + (get_global $binary/I) + (i64.const 1) + ) + ) + (set_global $binary/I + (i64.sub + (get_global $binary/I) + (i64.const 1) + ) + ) + (set_global $binary/I + (i64.mul + (get_global $binary/I) + (i64.const 1) + ) + ) + (set_global $binary/I + (i64.rem_s + (get_global $binary/I) + (i64.const 1) + ) + ) + (set_global $binary/I + (i64.shl + (get_global $binary/I) + (i64.const 1) + ) + ) + (set_global $binary/I + (i64.shr_s + (get_global $binary/I) + (i64.const 1) + ) + ) + (set_global $binary/I + (i64.shr_u + (get_global $binary/I) + (i64.const 1) + ) + ) + (set_global $binary/I + (i64.and + (get_global $binary/I) + (i64.const 1) + ) + ) + (set_global $binary/I + (i64.or + (get_global $binary/I) + (i64.const 1) + ) + ) + (set_global $binary/I + (i64.xor + (get_global $binary/I) + (i64.const 1) + ) + ) + (set_global $binary/b + (f32.lt + (get_global $binary/f) + (f32.const 1) + ) + ) + (set_global $binary/b + (f32.gt + (get_global $binary/f) + (f32.const 1) + ) + ) + (set_global $binary/b + (f32.le + (get_global $binary/f) + (f32.const 1) + ) + ) + (set_global $binary/b + (f32.ge + (get_global $binary/f) + (f32.const 1) + ) + ) + (set_global $binary/b + (f32.eq + (get_global $binary/f) + (f32.const 1) + ) + ) + (set_global $binary/b + (f32.eq + (get_global $binary/f) + (f32.const 1) + ) + ) + (set_global $binary/f + (f32.add + (get_global $binary/f) + (f32.const 1) + ) + ) + (set_global $binary/f + (f32.sub + (get_global $binary/f) + (f32.const 1) + ) + ) + (set_global $binary/f + (f32.mul + (get_global $binary/f) + (f32.const 1) + ) + ) + (set_global $binary/f + (f32.div + (get_global $binary/f) + (f32.const 1) + ) + ) + (set_global $binary/f + (f32.add + (get_global $binary/f) + (f32.const 1) + ) + ) + (set_global $binary/f + (f32.sub + (get_global $binary/f) + (f32.const 1) + ) + ) + (set_global $binary/f + (f32.mul + (get_global $binary/f) + (f32.const 1) + ) + ) + (set_global $binary/b + (f64.lt + (get_global $binary/F) + (f64.const 1) + ) + ) + (set_global $binary/b + (f64.gt + (get_global $binary/F) + (f64.const 1) + ) + ) + (set_global $binary/b + (f64.le + (get_global $binary/F) + (f64.const 1) + ) + ) + (set_global $binary/b + (f64.ge + (get_global $binary/F) + (f64.const 1) + ) + ) + (set_global $binary/b + (f64.eq + (get_global $binary/F) + (f64.const 1) + ) + ) + (set_global $binary/b + (f64.eq + (get_global $binary/F) + (f64.const 1) + ) + ) + (set_global $binary/F + (f64.add + (get_global $binary/F) + (f64.const 1) + ) + ) + (set_global $binary/F + (f64.sub + (get_global $binary/F) + (f64.const 1) + ) + ) + (set_global $binary/F + (f64.mul + (get_global $binary/F) + (f64.const 1) + ) + ) + (set_global $binary/F + (f64.div + (get_global $binary/F) + (f64.const 1) + ) + ) + (set_global $binary/F + (f64.add + (get_global $binary/F) + (f64.const 1) + ) + ) + (set_global $binary/F + (f64.sub + (get_global $binary/F) + (f64.const 1) + ) + ) + (set_global $binary/F + (f64.mul + (get_global $binary/F) + (f64.const 1) + ) + ) + ) +) diff --git a/tests/compiler/builtins.optimized.wast b/tests/compiler/builtins.optimized.wast new file mode 100644 index 00000000..4d12c32b --- /dev/null +++ b/tests/compiler/builtins.optimized.wast @@ -0,0 +1,253 @@ +(module + (type $v (func)) + (global $builtins/i (mut i32) (i32.const 0)) + (global $builtins/I (mut i64) (i64.const 0)) + (global $builtins/f (mut f32) (f32.const 0)) + (global $builtins/b (mut i32) (i32.const 0)) + (global $builtins/F (mut f64) (f64.const 0)) + (global $builtins/s (mut i32) (i32.const 0)) + (memory $0 1) + (data (i32.const 4) "\08") + (export "memory" (memory $0)) + (start $start) + (func $start (; 0 ;) (type $v) + (local $0 f32) + (local $1 f64) + (set_global $builtins/i + (i32.const 31) + ) + (set_global $builtins/i + (i32.const 0) + ) + (set_global $builtins/i + (i32.const 1) + ) + (set_global $builtins/i + (i32.const 2) + ) + (set_global $builtins/i + (i32.const -2147483648) + ) + (set_global $builtins/I + (i64.const 63) + ) + (set_global $builtins/I + (i64.const 0) + ) + (set_global $builtins/I + (i64.const 1) + ) + (set_global $builtins/I + (i64.const 2) + ) + (set_global $builtins/I + (i64.const -9223372036854775808) + ) + (set_global $builtins/f + (f32.const nan:0x400000) + ) + (set_global $builtins/f + (f32.const inf) + ) + (set_global $builtins/f + (f32.const 1.25) + ) + (set_global $builtins/f + (f32.const 2) + ) + (set_global $builtins/f + (f32.const 1.25) + ) + (set_global $builtins/f + (f32.const 1) + ) + (set_global $builtins/f + (f32.const 2.5) + ) + (set_global $builtins/f + (f32.const 1.25) + ) + (set_global $builtins/f + (f32.const 1.25) + ) + (set_global $builtins/f + (f32.const 1.1180340051651) + ) + (set_global $builtins/f + (f32.const 1) + ) + (set_global $builtins/b + (f32.ne + (tee_local $0 + (f32.const 1.25) + ) + (get_local $0) + ) + ) + (set_global $builtins/b + (select + (f32.ne + (f32.abs + (tee_local $0 + (f32.const 1.25) + ) + ) + (f32.const inf) + ) + (i32.const 0) + (f32.eq + (get_local $0) + (get_local $0) + ) + ) + ) + (set_global $builtins/F + (f64.const nan:0x8000000000000) + ) + (set_global $builtins/F + (f64.const inf) + ) + (set_global $builtins/F + (f64.const 1.25) + ) + (set_global $builtins/F + (f64.const 2) + ) + (set_global $builtins/F + (f64.const 1.25) + ) + (set_global $builtins/F + (f64.const 1) + ) + (set_global $builtins/F + (f64.const 2.5) + ) + (set_global $builtins/F + (f64.const 1.25) + ) + (set_global $builtins/F + (f64.const 1) + ) + (set_global $builtins/F + (f64.const 1.118033988749895) + ) + (set_global $builtins/F + (f64.const 1) + ) + (set_global $builtins/b + (f64.ne + (tee_local $1 + (f64.const 1.25) + ) + (get_local $1) + ) + ) + (set_global $builtins/b + (select + (f64.ne + (f64.abs + (tee_local $1 + (f64.const 1.25) + ) + ) + (f64.const inf) + ) + (i32.const 0) + (f64.eq + (get_local $1) + (get_local $1) + ) + ) + ) + (drop + (current_memory) + ) + (drop + (grow_memory + (i32.const 1) + ) + ) + (set_global $builtins/s + (current_memory) + ) + (set_global $builtins/s + (grow_memory + (i32.const 1) + ) + ) + (set_global $builtins/i + (i32.load + (i32.const 4) + ) + ) + (i32.store + (i32.const 4) + (get_global $builtins/i) + ) + (if + (f32.eq + (tee_local $0 + (f32.const nan:0x400000) + ) + (get_local $0) + ) + (unreachable) + ) + (if + (select + (f32.ne + (f32.abs + (tee_local $0 + (f32.const nan:0x400000) + ) + ) + (f32.const inf) + ) + (i32.const 0) + (f32.eq + (get_local $0) + (get_local $0) + ) + ) + (unreachable) + ) + (if + (select + (f32.ne + (f32.abs + (tee_local $0 + (f32.const inf) + ) + ) + (f32.const inf) + ) + (i32.const 0) + (f32.eq + (get_local $0) + (get_local $0) + ) + ) + (unreachable) + ) + (if + (i32.eqz + (select + (f64.ne + (f64.abs + (tee_local $1 + (f64.const 0) + ) + ) + (f64.const inf) + ) + (i32.const 0) + (f64.eq + (get_local $1) + (get_local $1) + ) + ) + ) + (unreachable) + ) + ) +) diff --git a/tests/compiler/do.optimized.wast b/tests/compiler/do.optimized.wast new file mode 100644 index 00000000..9045677e --- /dev/null +++ b/tests/compiler/do.optimized.wast @@ -0,0 +1,43 @@ +(module + (type $iv (func (param i32))) + (memory $0 1) + (data (i32.const 4) "\08") + (export "loopDo" (func $do/loopDo)) + (export "loopDoInDo" (func $do/loopDoInDo)) + (export "memory" (memory $0)) + (func $do/loopDo (; 0 ;) (type $iv) (param $0 i32) + (loop $continue$1.1 + (br_if $continue$1.1 + (tee_local $0 + (i32.sub + (get_local $0) + (i32.const 1) + ) + ) + ) + ) + ) + (func $do/loopDoInDo (; 1 ;) (type $iv) (param $0 i32) + (loop $continue$1.1 + (set_local $0 + (i32.sub + (get_local $0) + (i32.const 1) + ) + ) + (loop $continue$1.2 + (br_if $continue$1.2 + (tee_local $0 + (i32.sub + (get_local $0) + (i32.const 1) + ) + ) + ) + ) + (br_if $continue$1.1 + (get_local $0) + ) + ) + ) +) diff --git a/tests/compiler/export.optimized.wast b/tests/compiler/export.optimized.wast new file mode 100644 index 00000000..ac29552f --- /dev/null +++ b/tests/compiler/export.optimized.wast @@ -0,0 +1,20 @@ +(module + (type $iii (func (param i32 i32) (result i32))) + (memory $0 1) + (data (i32.const 4) "\08") + (export "add" (func $export/add)) + (export "renamed_sub" (func $export/sub)) + (export "memory" (memory $0)) + (func $export/add (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (i32.add + (get_local $0) + (get_local $1) + ) + ) + (func $export/sub (; 1 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (i32.sub + (get_local $0) + (get_local $1) + ) + ) +) diff --git a/tests/compiler/if.optimized.wast b/tests/compiler/if.optimized.wast new file mode 100644 index 00000000..915c9c7c --- /dev/null +++ b/tests/compiler/if.optimized.wast @@ -0,0 +1,25 @@ +(module + (type $ii (func (param i32) (result i32))) + (memory $0 1) + (data (i32.const 4) "\08") + (export "ifThenElse" (func $if/ifThenElse)) + (export "ifThen" (func $if/ifThen)) + (export "ifThenElseBlock" (func $if/ifThenElse)) + (export "memory" (memory $0)) + (func $if/ifThenElse (; 0 ;) (type $ii) (param $0 i32) (result i32) + (if (result i32) + (get_local $0) + (i32.const 1) + (i32.const 0) + ) + ) + (func $if/ifThen (; 1 ;) (type $ii) (param $0 i32) (result i32) + (if + (get_local $0) + (return + (i32.const 1) + ) + ) + (i32.const 0) + ) +) diff --git a/tests/compiler/import.optimized.wast b/tests/compiler/import.optimized.wast new file mode 100644 index 00000000..98cf5b20 --- /dev/null +++ b/tests/compiler/import.optimized.wast @@ -0,0 +1,36 @@ +(module + (type $iii (func (param i32 i32) (result i32))) + (type $v (func)) + (global $export/a (mut i32) (i32.const 1)) + (global $export/b (mut i32) (i32.const 2)) + (memory $0 1) + (data (i32.const 4) "\08") + (export "memory" (memory $0)) + (start $start) + (func $export/add (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (i32.add + (get_local $0) + (get_local $1) + ) + ) + (func $export/sub (; 1 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (i32.sub + (get_local $0) + (get_local $1) + ) + ) + (func $start (; 2 ;) (type $v) + (drop + (i32.add + (call $export/add + (get_global $export/a) + (get_global $export/b) + ) + (call $export/sub + (get_global $export/b) + (get_global $export/a) + ) + ) + ) + ) +) diff --git a/tests/compiler/literals.optimized.wast b/tests/compiler/literals.optimized.wast new file mode 100644 index 00000000..2b1bd4dc --- /dev/null +++ b/tests/compiler/literals.optimized.wast @@ -0,0 +1,10 @@ +(module + (type $v (func)) + (memory $0 1) + (data (i32.const 4) "\08") + (export "memory" (memory $0)) + (start $start) + (func $start (; 0 ;) (type $v) + (nop) + ) +) diff --git a/tests/compiler/logical.optimized.wast b/tests/compiler/logical.optimized.wast new file mode 100644 index 00000000..e67c8205 --- /dev/null +++ b/tests/compiler/logical.optimized.wast @@ -0,0 +1,75 @@ +(module + (type $v (func)) + (memory $0 1) + (data (i32.const 4) "\08") + (export "memory" (memory $0)) + (start $start) + (func $start (; 0 ;) (type $v) + (local $0 i32) + (local $1 f64) + (if + (tee_local $0 + (i32.const 0) + ) + (unreachable) + ) + (if + (f64.ne + (tee_local $1 + (f64.const 0) + ) + (f64.const 0) + ) + (unreachable) + ) + (if + (i32.eqz + (tee_local $0 + (i32.const 1) + ) + ) + (unreachable) + ) + (if + (f64.eq + (tee_local $1 + (f64.const 1) + ) + (f64.const 0) + ) + (unreachable) + ) + (if + (i32.eqz + (if (result i32) + (tee_local $0 + (i32.const 1) + ) + (tee_local $0 + (i32.const 2) + ) + (get_local $0) + ) + ) + (unreachable) + ) + (if + (f64.eq + (if (result f64) + (f64.ne + (tee_local $1 + (f64.const 1) + ) + (f64.const 0) + ) + (tee_local $1 + (f64.const 2) + ) + (get_local $1) + ) + (f64.const 0) + ) + (unreachable) + ) + ) +) diff --git a/tests/compiler/logical.ts b/tests/compiler/logical.ts new file mode 100644 index 00000000..01f0928c --- /dev/null +++ b/tests/compiler/logical.ts @@ -0,0 +1,7 @@ +0 && unreachable(); +0.0 && unreachable(); +1 || unreachable(); +1.0 || unreachable(); + +1 && 2 || unreachable(); +1.0 && 2.0 || unreachable(); diff --git a/tests/compiler/logical.wast b/tests/compiler/logical.wast new file mode 100644 index 00000000..8dca9c4b --- /dev/null +++ b/tests/compiler/logical.wast @@ -0,0 +1,123 @@ +(module + (type $v (func)) + (memory $0 1) + (data (i32.const 4) "\08\00\00\00") + (export "memory" (memory $0)) + (start $start) + (func $start (; 0 ;) (type $v) + (local $0 i32) + (local $1 f64) + (local $2 i32) + (local $3 f64) + (local $4 i32) + (local $5 i32) + (local $6 f64) + (local $7 f64) + (drop + (if (result i32) + (tee_local $0 + (i32.const 0) + ) + (unreachable) + (get_local $0) + ) + ) + (drop + (if (result f64) + (f64.ne + (tee_local $1 + (f64.const 0) + ) + (f64.const 0) + ) + (unreachable) + (get_local $1) + ) + ) + (drop + (if (result i32) + (tee_local $2 + (i32.const 1) + ) + (get_local $2) + (unreachable) + ) + ) + (drop + (if (result f64) + (f64.ne + (tee_local $3 + (f64.const 1) + ) + (f64.const 0) + ) + (get_local $3) + (unreachable) + ) + ) + (drop + (if (result i32) + (tee_local $5 + (if (result i32) + (tee_local $4 + (i32.const 1) + ) + (i32.const 2) + (get_local $4) + ) + ) + (get_local $5) + (unreachable) + ) + ) + (drop + (if (result f64) + (f64.ne + (tee_local $7 + (if (result f64) + (f64.ne + (tee_local $6 + (f64.const 1) + ) + (f64.const 0) + ) + (f64.const 2) + (get_local $6) + ) + ) + (f64.const 0) + ) + (get_local $7) + (unreachable) + ) + ) + ) +) +(; +[program.elements] + clz + ctz + popcnt + rotl + rotr + abs + ceil + copysign + floor + max + min + nearest + sqrt + trunc + current_memory + grow_memory + unreachable + isNaN + isFinite + assert + sizeof + load + store +[program.exports] + +;) diff --git a/tests/compiler/reexport.optimized.wast b/tests/compiler/reexport.optimized.wast new file mode 100644 index 00000000..e73d0fd3 --- /dev/null +++ b/tests/compiler/reexport.optimized.wast @@ -0,0 +1,38 @@ +(module + (type $iii (func (param i32 i32) (result i32))) + (type $v (func)) + (memory $0 1) + (data (i32.const 4) "\08") + (export "add" (func $export/add)) + (export "renamed_sub" (func $export/sub)) + (export "renamed_add" (func $export/add)) + (export "rerenamed_sub" (func $export/sub)) + (export "memory" (memory $0)) + (start $start) + (func $export/add (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (i32.add + (get_local $0) + (get_local $1) + ) + ) + (func $export/sub (; 1 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32) + (i32.sub + (get_local $0) + (get_local $1) + ) + ) + (func $start (; 2 ;) (type $v) + (drop + (i32.add + (call $export/add + (i32.const 1) + (i32.const 2) + ) + (call $export/sub + (i32.const 3) + (i32.const 4) + ) + ) + ) + ) +) diff --git a/tests/compiler/switch.optimized.wast b/tests/compiler/switch.optimized.wast new file mode 100644 index 00000000..bb32ec06 --- /dev/null +++ b/tests/compiler/switch.optimized.wast @@ -0,0 +1,122 @@ +(module + (type $ii (func (param i32) (result i32))) + (memory $0 1) + (data (i32.const 4) "\08") + (export "doSwitch" (func $switch/doSwitch)) + (export "doSwitchDefaultFirst" (func $switch/doSwitchDefaultFirst)) + (export "doSwitchDefaultOmitted" (func $switch/doSwitchDefaultOmitted)) + (export "memory" (memory $0)) + (func $switch/doSwitch (; 0 ;) (type $ii) (param $0 i32) (result i32) + (local $1 i32) + (block $case4$1.1 + (block $case2$1.1 + (if + (i32.ne + (tee_local $1 + (get_local $0) + ) + (i32.const 1) + ) + (block + (br_if $case2$1.1 + (i32.eqz + (get_local $1) + ) + ) + (br_if $case4$1.1 + (i32.eq + (get_local $1) + (i32.const 2) + ) + ) + (br_if $case4$1.1 + (i32.eq + (get_local $1) + (i32.const 3) + ) + ) + (br $case2$1.1) + ) + ) + (return + (i32.const 1) + ) + ) + (return + (i32.const 0) + ) + ) + (i32.const 23) + ) + (func $switch/doSwitchDefaultFirst (; 1 ;) (type $ii) (param $0 i32) (result i32) + (local $1 i32) + (block $case3$1.1 + (if + (i32.ne + (tee_local $1 + (get_local $0) + ) + (i32.const 1) + ) + (block + (br_if $case3$1.1 + (i32.eq + (get_local $1) + (i32.const 2) + ) + ) + (br_if $case3$1.1 + (i32.eq + (get_local $1) + (i32.const 3) + ) + ) + (return + (i32.const 0) + ) + ) + ) + (return + (i32.const 1) + ) + ) + (i32.const 23) + ) + (func $switch/doSwitchDefaultOmitted (; 2 ;) (type $ii) (param $0 i32) (result i32) + (local $1 i32) + (block $break$1.1 + (block $case2$1.1 + (if + (i32.ne + (tee_local $1 + (get_local $0) + ) + (i32.const 1) + ) + (block + (br_if $case2$1.1 + (i32.eq + (get_local $1) + (i32.const 2) + ) + ) + (br_if $case2$1.1 + (i32.eq + (get_local $1) + (i32.const 3) + ) + ) + (br $break$1.1) + ) + ) + (return + (i32.const 1) + ) + ) + (return + (i32.const 23) + ) + ) + (i32.const 0) + ) +) diff --git a/tests/compiler/ternary.optimized.wast b/tests/compiler/ternary.optimized.wast new file mode 100644 index 00000000..5e7ebd53 --- /dev/null +++ b/tests/compiler/ternary.optimized.wast @@ -0,0 +1,19 @@ +(module + (type $v (func)) + (global $ternary/a (mut i32) (i32.const 0)) + (memory $0 1) + (data (i32.const 4) "\08") + (export "memory" (memory $0)) + (start $start) + (func $start (; 0 ;) (type $v) + (set_global $ternary/a + (i32.const 1) + ) + (set_global $ternary/a + (i32.const 1) + ) + (set_global $ternary/a + (i32.const 1) + ) + ) +) diff --git a/tests/compiler/unary.optimized.wast b/tests/compiler/unary.optimized.wast new file mode 100644 index 00000000..772fef91 --- /dev/null +++ b/tests/compiler/unary.optimized.wast @@ -0,0 +1,407 @@ +(module + (type $v (func)) + (global $unary/i (mut i32) (i32.const 0)) + (global $unary/I (mut i64) (i64.const 0)) + (global $unary/f (mut f32) (f32.const 0)) + (global $unary/F (mut f64) (f64.const 0)) + (memory $0 1) + (data (i32.const 4) "\08") + (export "memory" (memory $0)) + (start $start) + (func $start (; 0 ;) (type $v) + (local $0 i32) + (local $1 i64) + (local $2 f32) + (local $3 f64) + (set_global $unary/i + (i32.add + (get_global $unary/i) + (i32.const 1) + ) + ) + (set_global $unary/i + (i32.sub + (get_global $unary/i) + (i32.const 1) + ) + ) + (set_global $unary/i + (i32.add + (get_global $unary/i) + (i32.const 1) + ) + ) + (set_global $unary/i + (i32.sub + (get_global $unary/i) + (i32.const 1) + ) + ) + (set_global $unary/i + (i32.const 1) + ) + (set_global $unary/i + (i32.const -1) + ) + (set_global $unary/i + (i32.const 0) + ) + (set_global $unary/i + (i32.const -2) + ) + (set_global $unary/i + (i32.sub + (i32.const 0) + (get_global $unary/i) + ) + ) + (set_global $unary/i + (i32.eqz + (get_global $unary/i) + ) + ) + (set_global $unary/i + (i32.xor + (get_global $unary/i) + (i32.const -1) + ) + ) + (set_global $unary/i + (block (result i32) + (set_global $unary/i + (i32.add + (get_global $unary/i) + (i32.const 1) + ) + ) + (get_global $unary/i) + ) + ) + (set_global $unary/i + (block (result i32) + (set_global $unary/i + (i32.sub + (get_global $unary/i) + (i32.const 1) + ) + ) + (get_global $unary/i) + ) + ) + (set_global $unary/i + (block (result i32) + (set_global $unary/i + (i32.add + (tee_local $0 + (get_global $unary/i) + ) + (i32.const 1) + ) + ) + (get_local $0) + ) + ) + (set_global $unary/i + (block (result i32) + (set_global $unary/i + (i32.sub + (tee_local $0 + (get_global $unary/i) + ) + (i32.const 1) + ) + ) + (get_local $0) + ) + ) + (set_global $unary/I + (i64.add + (get_global $unary/I) + (i64.const 1) + ) + ) + (set_global $unary/I + (i64.sub + (get_global $unary/I) + (i64.const 1) + ) + ) + (set_global $unary/I + (i64.add + (get_global $unary/I) + (i64.const 1) + ) + ) + (set_global $unary/I + (i64.sub + (get_global $unary/I) + (i64.const 1) + ) + ) + (set_global $unary/I + (i64.const 1) + ) + (set_global $unary/I + (i64.const -1) + ) + (set_global $unary/I + (i64.const 0) + ) + (set_global $unary/I + (i64.const -2) + ) + (set_global $unary/I + (i64.sub + (i64.const 0) + (get_global $unary/I) + ) + ) + (set_global $unary/I + (i64.extend_s/i32 + (i64.eqz + (get_global $unary/I) + ) + ) + ) + (set_global $unary/I + (i64.xor + (get_global $unary/I) + (i64.const -1) + ) + ) + (set_global $unary/I + (block (result i64) + (set_global $unary/I + (i64.add + (get_global $unary/I) + (i64.const 1) + ) + ) + (get_global $unary/I) + ) + ) + (set_global $unary/I + (block (result i64) + (set_global $unary/I + (i64.sub + (get_global $unary/I) + (i64.const 1) + ) + ) + (get_global $unary/I) + ) + ) + (set_global $unary/I + (block (result i64) + (set_global $unary/I + (i64.add + (tee_local $1 + (get_global $unary/I) + ) + (i64.const 1) + ) + ) + (get_local $1) + ) + ) + (set_global $unary/I + (block (result i64) + (set_global $unary/I + (i64.sub + (tee_local $1 + (get_global $unary/I) + ) + (i64.const 1) + ) + ) + (get_local $1) + ) + ) + (set_global $unary/f + (f32.add + (get_global $unary/f) + (f32.const 1) + ) + ) + (set_global $unary/f + (f32.sub + (get_global $unary/f) + (f32.const 1) + ) + ) + (set_global $unary/f + (f32.add + (get_global $unary/f) + (f32.const 1) + ) + ) + (set_global $unary/f + (f32.sub + (get_global $unary/f) + (f32.const 1) + ) + ) + (set_global $unary/f + (f32.const 1.25) + ) + (set_global $unary/f + (f32.const -1.25) + ) + (set_global $unary/i + (i32.const 0) + ) + (set_global $unary/f + (f32.neg + (get_global $unary/f) + ) + ) + (set_global $unary/i + (f32.eq + (get_global $unary/f) + (f32.const 0) + ) + ) + (set_global $unary/f + (block (result f32) + (set_global $unary/f + (f32.add + (get_global $unary/f) + (f32.const 1) + ) + ) + (get_global $unary/f) + ) + ) + (set_global $unary/f + (block (result f32) + (set_global $unary/f + (f32.sub + (get_global $unary/f) + (f32.const 1) + ) + ) + (get_global $unary/f) + ) + ) + (set_global $unary/f + (block (result f32) + (set_global $unary/f + (f32.add + (tee_local $2 + (get_global $unary/f) + ) + (f32.const 1) + ) + ) + (get_local $2) + ) + ) + (set_global $unary/f + (block (result f32) + (set_global $unary/f + (f32.sub + (tee_local $2 + (get_global $unary/f) + ) + (f32.const 1) + ) + ) + (get_local $2) + ) + ) + (set_global $unary/F + (f64.add + (get_global $unary/F) + (f64.const 1) + ) + ) + (set_global $unary/F + (f64.sub + (get_global $unary/F) + (f64.const 1) + ) + ) + (set_global $unary/F + (f64.add + (get_global $unary/F) + (f64.const 1) + ) + ) + (set_global $unary/F + (f64.sub + (get_global $unary/F) + (f64.const 1) + ) + ) + (set_global $unary/F + (f64.const 1.25) + ) + (set_global $unary/F + (f64.const -1.25) + ) + (set_global $unary/I + (i64.const 0) + ) + (set_global $unary/F + (f64.neg + (get_global $unary/F) + ) + ) + (set_global $unary/I + (i64.extend_s/i32 + (f64.eq + (get_global $unary/F) + (f64.const 0) + ) + ) + ) + (set_global $unary/F + (block (result f64) + (set_global $unary/F + (f64.add + (get_global $unary/F) + (f64.const 1) + ) + ) + (get_global $unary/F) + ) + ) + (set_global $unary/F + (block (result f64) + (set_global $unary/F + (f64.sub + (get_global $unary/F) + (f64.const 1) + ) + ) + (get_global $unary/F) + ) + ) + (set_global $unary/F + (block (result f64) + (set_global $unary/F + (f64.add + (tee_local $3 + (get_global $unary/F) + ) + (f64.const 1) + ) + ) + (get_local $3) + ) + ) + (set_global $unary/F + (block (result f64) + (set_global $unary/F + (f64.sub + (tee_local $3 + (get_global $unary/F) + ) + (f64.const 1) + ) + ) + (get_local $3) + ) + ) + ) +) diff --git a/tests/compiler/while.optimized.wast b/tests/compiler/while.optimized.wast new file mode 100644 index 00000000..08359040 --- /dev/null +++ b/tests/compiler/while.optimized.wast @@ -0,0 +1,54 @@ +(module + (type $iv (func (param i32))) + (memory $0 1) + (data (i32.const 4) "\08") + (export "loopWhile" (func $while/loopWhile)) + (export "loopWhileInWhile" (func $while/loopWhileInWhile)) + (export "memory" (memory $0)) + (func $while/loopWhile (; 0 ;) (type $iv) (param $0 i32) + (loop $continue$1.1 + (if + (get_local $0) + (block + (set_local $0 + (i32.sub + (get_local $0) + (i32.const 1) + ) + ) + (br $continue$1.1) + ) + ) + ) + ) + (func $while/loopWhileInWhile (; 1 ;) (type $iv) (param $0 i32) + (loop $continue$1.1 + (if + (get_local $0) + (block + (set_local $0 + (i32.sub + (get_local $0) + (i32.const 1) + ) + ) + (loop $continue$1.2 + (if + (get_local $0) + (block + (set_local $0 + (i32.sub + (get_local $0) + (i32.const 1) + ) + ) + (br $continue$1.2) + ) + ) + ) + (br $continue$1.1) + ) + ) + ) + ) +)