From 4cbc7536e33e074e96b3b73839402574d02cf75a Mon Sep 17 00:00:00 2001 From: dcode Date: Fri, 25 Mar 2022 19:29:51 +0100 Subject: [PATCH] Fix invalid assumption when compiling binary overloads --- src/compiler.ts | 11 +- tests/compiler/resolve-binary.debug.wat | 170 +++++++++++++++++++--- tests/compiler/resolve-binary.release.wat | 136 +++++++++++------ tests/compiler/resolve-binary.ts | 33 +++++ 4 files changed, 281 insertions(+), 69 deletions(-) diff --git a/src/compiler.ts b/src/compiler.ts index 73959fefc0..b6ee5c883c 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -5735,14 +5735,15 @@ export class Compiler extends DiagnosticEmitter { reportNode: Node ): ExpressionRef { var rightType: Type; + var signature = operatorInstance.signature; + var parameterTypes = signature.parameterTypes; if (operatorInstance.is(CommonFlags.INSTANCE)) { - assert(leftType.isStrictlyAssignableTo(operatorInstance.signature.parameterTypes[0])); - let classInstance = assert(operatorInstance.parent); assert(classInstance.kind == ElementKind.CLASS); - rightType = operatorInstance.signature.parameterTypes[0]; + leftExpr = this.convertExpression(leftExpr, leftType, assert(signature.thisType), false, left); + rightType = parameterTypes[0]; } else { - rightType = operatorInstance.signature.parameterTypes[1]; + leftExpr = this.convertExpression(leftExpr, leftType, parameterTypes[0], false, left); + rightType = parameterTypes[1]; } - leftExpr = this.convertExpression(leftExpr, leftType, operatorInstance.signature.parameterTypes[0], false, left); var rightExpr = this.compileExpression(right, rightType, Constraints.CONV_IMPLICIT); return this.makeCallDirect(operatorInstance, [ leftExpr, rightExpr ], reportNode); } diff --git a/tests/compiler/resolve-binary.debug.wat b/tests/compiler/resolve-binary.debug.wat index 13f2f9e6ee..8795bd6e97 100644 --- a/tests/compiler/resolve-binary.debug.wat +++ b/tests/compiler/resolve-binary.debug.wat @@ -1,7 +1,7 @@ (module (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) - (type $i32_i32_=>_none (func (param i32 i32))) (type $i32_=>_i32 (func (param i32) (result i32))) + (type $i32_i32_=>_none (func (param i32 i32))) (type $i32_=>_none (func (param i32))) (type $none_=>_none (func)) (type $i32_i32_i32_=>_none (func (param i32 i32 i32))) @@ -45,10 +45,11 @@ (global $resolve-binary/foo (mut i32) (i32.const 0)) (global $resolve-binary/bar (mut i32) (i32.const 0)) (global $resolve-binary/bar2 (mut i32) (i32.const 0)) + (global $resolve-binary/baz (mut i32) (i32.const 0)) (global $~lib/rt/__rtti_base i32 (i32.const 10192)) - (global $~lib/memory/__data_end i32 (i32.const 10236)) - (global $~lib/memory/__stack_pointer (mut i32) (i32.const 26620)) - (global $~lib/memory/__heap_base i32 (i32.const 26620)) + (global $~lib/memory/__data_end i32 (i32.const 10244)) + (global $~lib/memory/__stack_pointer (mut i32) (i32.const 26628)) + (global $~lib/memory/__heap_base i32 (i32.const 26628)) (memory $0 1) (data (i32.const 12) "\1c\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\08\00\00\00t\00r\00u\00e\00\00\00\00\00") (data (i32.const 44) "\1c\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\n\00\00\00f\00a\00l\00s\00e\00\00\00") @@ -95,7 +96,7 @@ (data (i32.const 10092) "\1c\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\06\00\00\00d\00i\00v\00\00\00\00\00\00\00") (data (i32.const 10124) "\1c\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\06\00\00\00r\00e\00m\00\00\00\00\00\00\00") (data (i32.const 10156) "\1c\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\06\00\00\00p\00o\00w\00\00\00\00\00\00\00") - (data (i32.const 10192) "\05\00\00\00 \00\00\00\00\00\00\00 \00\00\00\00\00\00\00\00\00\00\00\00\00\00\00 \00\00\00\00\00\00\00 \00\00\00\00\00\00\00") + (data (i32.const 10192) "\06\00\00\00 \00\00\00\00\00\00\00 \00\00\00\00\00\00\00\00\00\00\00\00\00\00\00 \00\00\00\00\00\00\00 \00\00\00\00\00\00\00 \00\00\00\00\00\00\00") (table $0 1 funcref) (elem $0 (i32.const 1)) (export "memory" (memory $0)) @@ -5255,6 +5256,18 @@ (func $resolve-binary/Bar#self (param $0 i32) (result i32) local.get $0 ) + (func $resolve-binary/Baz#add (param $0 i32) (param $1 i32) (result i32) + local.get $1 + ) + (func $resolve-binary/Baz#sub (param $0 i32) (param $1 i32) (result i32) + local.get $0 + ) + (func $resolve-binary/Baz.mul (param $0 i32) (param $1 i32) (result i32) + local.get $1 + ) + (func $resolve-binary/Baz.div (param $0 i32) (param $1 i32) (result i32) + local.get $0 + ) (func $~lib/rt/__visit_globals (param $0 i32) (local $1 i32) global.get $resolve-binary/foo @@ -5278,6 +5291,13 @@ local.get $0 call $~lib/rt/itcms/__visit end + global.get $resolve-binary/baz + local.tee $1 + if + local.get $1 + local.get $0 + call $~lib/rt/itcms/__visit + end i32.const 576 local.get $0 call $~lib/rt/itcms/__visit @@ -5304,24 +5324,27 @@ ) (func $~lib/rt/__visit_members (param $0 i32) (param $1 i32) block $invalid - block $resolve-binary/Bar - block $resolve-binary/Foo - block $~lib/arraybuffer/ArrayBufferView - block $~lib/string/String - block $~lib/arraybuffer/ArrayBuffer - local.get $0 - i32.const 8 - i32.sub - i32.load - br_table $~lib/arraybuffer/ArrayBuffer $~lib/string/String $~lib/arraybuffer/ArrayBufferView $resolve-binary/Foo $resolve-binary/Bar $invalid + block $resolve-binary/Baz + block $resolve-binary/Bar + block $resolve-binary/Foo + block $~lib/arraybuffer/ArrayBufferView + block $~lib/string/String + block $~lib/arraybuffer/ArrayBuffer + local.get $0 + i32.const 8 + i32.sub + i32.load + br_table $~lib/arraybuffer/ArrayBuffer $~lib/string/String $~lib/arraybuffer/ArrayBufferView $resolve-binary/Foo $resolve-binary/Bar $resolve-binary/Baz $invalid + end + return end return end + local.get $0 + local.get $1 + call $~lib/arraybuffer/ArrayBufferView~visit return end - local.get $0 - local.get $1 - call $~lib/arraybuffer/ArrayBufferView~visit return end return @@ -5338,8 +5361,8 @@ global.get $~lib/memory/__data_end i32.lt_s if - i32.const 26640 - i32.const 26688 + i32.const 26656 + i32.const 26704 i32.const 1 i32.const 1 call $~lib/builtins/abort @@ -6909,6 +6932,85 @@ call $~lib/builtins/abort unreachable end + i32.const 0 + call $resolve-binary/Baz#constructor + global.set $resolve-binary/baz + global.get $resolve-binary/baz + local.set $0 + global.get $~lib/memory/__stack_pointer + local.get $0 + i32.store + local.get $0 + i32.const 42 + call $resolve-binary/Baz#add + i32.const 42 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 96 + i32.const 363 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + global.get $resolve-binary/baz + local.set $0 + global.get $~lib/memory/__stack_pointer + local.get $0 + i32.store + local.get $0 + i32.const 42 + call $resolve-binary/Baz#sub + global.get $resolve-binary/baz + i32.eq + i32.eqz + if + i32.const 0 + i32.const 96 + i32.const 366 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + global.get $resolve-binary/baz + local.set $0 + global.get $~lib/memory/__stack_pointer + local.get $0 + i32.store + local.get $0 + i32.const 42 + call $resolve-binary/Baz.mul + i32.const 42 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 96 + i32.const 369 + i32.const 1 + call $~lib/builtins/abort + unreachable + end + global.get $resolve-binary/baz + local.set $0 + global.get $~lib/memory/__stack_pointer + local.get $0 + i32.store + local.get $0 + i32.const 42 + call $resolve-binary/Baz.div + global.get $resolve-binary/baz + i32.eq + i32.eqz + if + i32.const 0 + i32.const 96 + i32.const 372 + i32.const 1 + call $~lib/builtins/abort + unreachable + end global.get $~lib/memory/__stack_pointer i32.const 20 i32.add @@ -7220,4 +7322,32 @@ global.set $~lib/memory/__stack_pointer local.get $1 ) + (func $resolve-binary/Baz#constructor (param $0 i32) (result i32) + (local $1 i32) + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + call $~stack_check + global.get $~lib/memory/__stack_pointer + i32.const 0 + i32.store + local.get $0 + i32.eqz + if + global.get $~lib/memory/__stack_pointer + i32.const 0 + i32.const 5 + call $~lib/rt/itcms/__new + local.tee $0 + i32.store + end + local.get $0 + local.set $1 + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + local.get $1 + ) ) diff --git a/tests/compiler/resolve-binary.release.wat b/tests/compiler/resolve-binary.release.wat index aae3004b71..fa86a3c2f7 100644 --- a/tests/compiler/resolve-binary.release.wat +++ b/tests/compiler/resolve-binary.release.wat @@ -26,7 +26,8 @@ (global $resolve-binary/foo (mut i32) (i32.const 0)) (global $resolve-binary/bar (mut i32) (i32.const 0)) (global $resolve-binary/bar2 (mut i32) (i32.const 0)) - (global $~lib/memory/__stack_pointer (mut i32) (i32.const 27644)) + (global $resolve-binary/baz (mut i32) (i32.const 0)) + (global $~lib/memory/__stack_pointer (mut i32) (i32.const 27652)) (memory $0 1) (data (i32.const 1036) "\1c") (data (i32.const 1048) "\01\00\00\00\08\00\00\00t\00r\00u\00e") @@ -90,7 +91,7 @@ (data (i32.const 11116) "\1c\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\06\00\00\00d\00i\00v") (data (i32.const 11148) "\1c\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\06\00\00\00r\00e\00m") (data (i32.const 11180) "\1c\00\00\00\00\00\00\00\00\00\00\00\01\00\00\00\06\00\00\00p\00o\00w") - (data (i32.const 11216) "\05\00\00\00 \00\00\00\00\00\00\00 \00\00\00\00\00\00\00\00\00\00\00\00\00\00\00 \00\00\00\00\00\00\00 ") + (data (i32.const 11216) "\06\00\00\00 \00\00\00\00\00\00\00 \00\00\00\00\00\00\00\00\00\00\00\00\00\00\00 \00\00\00\00\00\00\00 \00\00\00\00\00\00\00 ") (export "memory" (memory $0)) (start $~start) (func $~lib/string/String.__eq (param $0 i32) (param $1 i32) (result i32) @@ -231,6 +232,12 @@ local.get $0 call $byn-split-outlined-A$~lib/rt/itcms/__visit end + global.get $resolve-binary/baz + local.tee $0 + if + local.get $0 + call $byn-split-outlined-A$~lib/rt/itcms/__visit + end i32.const 1600 call $byn-split-outlined-A$~lib/rt/itcms/__visit i32.const 1408 @@ -808,10 +815,10 @@ if unreachable end - i32.const 27648 + i32.const 27664 i32.const 0 i32.store - i32.const 29216 + i32.const 29232 i32.const 0 i32.store loop $for-loop|0 @@ -822,7 +829,7 @@ local.get $0 i32.const 2 i32.shl - i32.const 27648 + i32.const 27664 i32.add i32.const 0 i32.store offset=4 @@ -840,7 +847,7 @@ i32.add i32.const 2 i32.shl - i32.const 27648 + i32.const 27664 i32.add i32.const 0 i32.store offset=96 @@ -858,13 +865,13 @@ br $for-loop|0 end end - i32.const 27648 - i32.const 29220 + i32.const 27664 + i32.const 29236 memory.size i32.const 16 i32.shl call $~lib/rt/tlsf/addMemory - i32.const 27648 + i32.const 27664 global.set $~lib/rt/tlsf/ROOT ) (func $~lib/rt/itcms/step (result i32) @@ -949,7 +956,7 @@ local.set $0 loop $while-continue|0 local.get $0 - i32.const 27644 + i32.const 27652 i32.lt_u if local.get $0 @@ -1049,7 +1056,7 @@ unreachable end local.get $0 - i32.const 27644 + i32.const 27652 i32.lt_u if local.get $0 @@ -1072,7 +1079,7 @@ i32.const 4 i32.add local.tee $0 - i32.const 27644 + i32.const 27652 i32.ge_u if global.get $~lib/rt/tlsf/ROOT @@ -1677,11 +1684,11 @@ i32.sub global.set $~lib/memory/__stack_pointer global.get $~lib/memory/__stack_pointer - i32.const 11260 + i32.const 11268 i32.lt_s if - i32.const 27664 - i32.const 27712 + i32.const 27680 + i32.const 27728 i32.const 1 i32.const 1 call $~lib/builtins/abort @@ -2544,11 +2551,11 @@ i32.sub global.set $~lib/memory/__stack_pointer global.get $~lib/memory/__stack_pointer - i32.const 11260 + i32.const 11268 i32.lt_s if - i32.const 27664 - i32.const 27712 + i32.const 27680 + i32.const 27728 i32.const 1 i32.const 1 call $~lib/builtins/abort @@ -2682,27 +2689,30 @@ ) (func $~lib/rt/__visit_members (param $0 i32) block $invalid - block $resolve-binary/Bar - block $resolve-binary/Foo - block $~lib/arraybuffer/ArrayBufferView - block $~lib/string/String - block $~lib/arraybuffer/ArrayBuffer - local.get $0 - i32.const 8 - i32.sub - i32.load - br_table $~lib/arraybuffer/ArrayBuffer $~lib/string/String $~lib/arraybuffer/ArrayBufferView $resolve-binary/Foo $resolve-binary/Bar $invalid + block $resolve-binary/Baz + block $resolve-binary/Bar + block $resolve-binary/Foo + block $~lib/arraybuffer/ArrayBufferView + block $~lib/string/String + block $~lib/arraybuffer/ArrayBuffer + local.get $0 + i32.const 8 + i32.sub + i32.load + br_table $~lib/arraybuffer/ArrayBuffer $~lib/string/String $~lib/arraybuffer/ArrayBufferView $resolve-binary/Foo $resolve-binary/Bar $resolve-binary/Baz $invalid + end + return end return end - return - end - local.get $0 - i32.load - local.tee $0 - if local.get $0 - call $byn-split-outlined-A$~lib/rt/itcms/__visit + i32.load + local.tee $0 + if + local.get $0 + call $byn-split-outlined-A$~lib/rt/itcms/__visit + end + return end return end @@ -2724,7 +2734,7 @@ global.set $~lib/memory/__stack_pointer block $folding-inner0 global.get $~lib/memory/__stack_pointer - i32.const 11260 + i32.const 11268 i32.lt_s br_if $folding-inner0 global.get $~lib/memory/__stack_pointer @@ -2848,7 +2858,7 @@ memory.size i32.const 16 i32.shl - i32.const 27644 + i32.const 27652 i32.sub i32.const 1 i32.shr_u @@ -3607,7 +3617,7 @@ i32.sub global.set $~lib/memory/__stack_pointer global.get $~lib/memory/__stack_pointer - i32.const 11260 + i32.const 11268 i32.lt_s br_if $folding-inner0 global.get $~lib/memory/__stack_pointer @@ -4014,13 +4024,51 @@ unreachable end global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.sub + global.set $~lib/memory/__stack_pointer + global.get $~lib/memory/__stack_pointer + i32.const 11268 + i32.lt_s + br_if $folding-inner0 + global.get $~lib/memory/__stack_pointer + local.tee $0 + i32.const 0 + i32.store + local.get $0 + i32.const 0 + i32.const 5 + call $~lib/rt/itcms/__new + local.tee $0 + i32.store + global.get $~lib/memory/__stack_pointer + i32.const 4 + i32.add + global.set $~lib/memory/__stack_pointer + local.get $0 + global.set $resolve-binary/baz + global.get $~lib/memory/__stack_pointer + global.get $resolve-binary/baz + local.tee $0 + i32.store + global.get $~lib/memory/__stack_pointer + local.get $0 + i32.store + global.get $~lib/memory/__stack_pointer + local.tee $1 + local.get $0 + i32.store + local.get $1 + local.get $0 + i32.store + global.get $~lib/memory/__stack_pointer i32.const 20 i32.add global.set $~lib/memory/__stack_pointer return end - i32.const 27664 - i32.const 27712 + i32.const 27680 + i32.const 27728 i32.const 1 i32.const 1 call $~lib/builtins/abort @@ -4033,11 +4081,11 @@ i32.sub global.set $~lib/memory/__stack_pointer global.get $~lib/memory/__stack_pointer - i32.const 11260 + i32.const 11268 i32.lt_s if - i32.const 27664 - i32.const 27712 + i32.const 27680 + i32.const 27728 i32.const 1 i32.const 1 call $~lib/builtins/abort @@ -4102,7 +4150,7 @@ if i32.const 0 local.get $1 - i32.const 27644 + i32.const 27652 i32.lt_u local.get $1 i32.load offset=8 diff --git a/tests/compiler/resolve-binary.ts b/tests/compiler/resolve-binary.ts index 95f475263e..29ef2c04b6 100644 --- a/tests/compiler/resolve-binary.ts +++ b/tests/compiler/resolve-binary.ts @@ -339,3 +339,36 @@ assert( bar2 ); assert(bar == bar2); + +// overload with varying right type +class Baz { + @operator("+") + add(other: i32): i32 { + return other; + } + @operator("-") + sub(other: i32): Baz { + return this; + } + @operator("*") + static mul(left: Baz, right: i32): i32 { + return right; + } + @operator("/") + static div(left: Baz, right: i32): Baz { + return left; + } +} +var baz = new Baz(); +assert( + (baz + 42) == 42 +); +assert( + (baz - 42) == baz +); +assert( + (baz * 42) == 42 +); +assert( + (baz / 42) == baz +);