Skip to content

Commit

Permalink
fix: clear garbage bits before cast short integer to float (#2813)
Browse files Browse the repository at this point in the history
Co-authored-by: CountBleck <Mr.YouKnowWhoIAm@protonmail.com>
  • Loading branch information
HerrCai0907 and CountBleck committed Jan 15, 2024
1 parent dc547a8 commit 67579de
Show file tree
Hide file tree
Showing 5 changed files with 206 additions and 26 deletions.
38 changes: 12 additions & 26 deletions src/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3647,43 +3647,29 @@ export class Compiler extends DiagnosticEmitter {

// int to float
} else if (fromType.isIntegerValue && toType.isFloatValue) {

// Clear extra bits.
expr = this.ensureSmallIntegerWrap(expr, fromType);
let op: UnaryOp;
// int to f32
if (toType.kind == TypeKind.F32) {
if (fromType.isLongIntegerValue) {
expr = module.unary(
fromType.isSignedIntegerValue
? UnaryOp.ConvertI64ToF32
: UnaryOp.ConvertU64ToF32,
expr
);
if (fromType.isSignedIntegerValue) op = UnaryOp.ConvertI64ToF32;
else op = UnaryOp.ConvertU64ToF32;
} else {
expr = module.unary(
fromType.isSignedIntegerValue
? UnaryOp.ConvertI32ToF32
: UnaryOp.ConvertU32ToF32,
expr
);
if (fromType.isSignedIntegerValue) op = UnaryOp.ConvertI32ToF32;
else op = UnaryOp.ConvertU32ToF32;
}

// int to f64
} else {
if (fromType.isLongIntegerValue) {
expr = module.unary(
fromType.isSignedIntegerValue
? UnaryOp.ConvertI64ToF64
: UnaryOp.ConvertU64ToF64,
expr
);
if (fromType.isSignedIntegerValue) op = UnaryOp.ConvertI64ToF64;
else op = UnaryOp.ConvertU64ToF64;
} else {
expr = module.unary(
fromType.isSignedIntegerValue
? UnaryOp.ConvertI32ToF64
: UnaryOp.ConvertU32ToF64,
expr
);
if (fromType.isSignedIntegerValue) op = UnaryOp.ConvertI32ToF64;
else op = UnaryOp.ConvertU32ToF64;
}
}
expr = module.unary(op, expr);

// v128 to bool
} else if (fromType == Type.v128 && toType.isBooleanValue) {
Expand Down
157 changes: 157 additions & 0 deletions tests/compiler/number-convert.debug.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
(module
(type $0 (func))
(global $~lib/memory/__data_end i32 (i32.const 8))
(global $~lib/memory/__stack_pointer (mut i32) (i32.const 32776))
(global $~lib/memory/__heap_base i32 (i32.const 32776))
(memory $0 0)
(table $0 1 1 funcref)
(elem $0 (i32.const 1))
(export "memory" (memory $0))
(start $~start)
(func $start:number-convert
i32.const 1
f32.convert_i32_u
f32.const 1
f32.eq
drop
i32.const 255
f32.convert_i32_u
f32.const 255
f32.eq
drop
i32.const 256
i32.const 255
i32.and
f32.convert_i32_u
f32.const 0
f32.eq
drop
i32.const 257
i32.const 255
i32.and
f32.convert_i32_u
f32.const 1
f32.eq
drop
i32.const 1
f32.convert_i32_s
f32.const 1
f32.eq
drop
i32.const 255
i32.extend8_s
f32.convert_i32_s
f32.const -1
f32.eq
drop
i32.const 256
i32.extend8_s
f32.convert_i32_s
f32.const 0
f32.eq
drop
i32.const 257
i32.extend8_s
f32.convert_i32_s
f32.const 1
f32.eq
drop
i32.const 1
f32.convert_i32_u
f32.const 1
f32.eq
drop
i32.const 65535
f32.convert_i32_u
f32.const 65535
f32.eq
drop
i32.const 65536
i32.const 65535
i32.and
f32.convert_i32_u
f32.const 0
f32.eq
drop
i32.const 65537
i32.const 65535
i32.and
f32.convert_i32_u
f32.const 1
f32.eq
drop
i32.const 1
f32.convert_i32_s
f32.const 1
f32.eq
drop
i32.const 65535
i32.extend16_s
f32.convert_i32_s
f32.const -1
f32.eq
drop
i32.const 65536
i32.extend16_s
f32.convert_i32_s
f32.const 0
f32.eq
drop
i32.const 65537
i32.extend16_s
f32.convert_i32_s
f32.const 1
f32.eq
drop
i32.const 1
f64.convert_i32_u
f64.const 1
f64.eq
drop
i32.const 255
f64.convert_i32_u
f64.const 255
f64.eq
drop
i32.const 256
i32.const 255
i32.and
f64.convert_i32_u
f64.const 0
f64.eq
drop
i32.const 257
i32.const 255
i32.and
f64.convert_i32_u
f64.const 1
f64.eq
drop
i32.const 1
f64.convert_i32_s
f64.const 1
f64.eq
drop
i32.const 255
i32.extend8_s
f64.convert_i32_s
f64.const -1
f64.eq
drop
i32.const 256
i32.extend8_s
f64.convert_i32_s
f64.const 0
f64.eq
drop
i32.const 257
i32.extend8_s
f64.convert_i32_s
f64.const 1
f64.eq
drop
)
(func $~start
call $start:number-convert
)
)
4 changes: 4 additions & 0 deletions tests/compiler/number-convert.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"asc_flags": [
]
}
4 changes: 4 additions & 0 deletions tests/compiler/number-convert.release.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
(module
(memory $0 0)
(export "memory" (memory $0))
)
29 changes: 29 additions & 0 deletions tests/compiler/number-convert.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
assert(<f32><u8>(1) == 1);
assert(<f32><u8>(255) == 255);
assert(<f32><u8>(256) == 0);
assert(<f32><u8>(257) == <f32>1);

assert(<f32><i8>(1) == <f32>1);
assert(<f32><i8>(255) == <f32>-1);
assert(<f32><i8>(256) == <f32>0);
assert(<f32><i8>(257) == <f32>1);

assert(<f32><u16>(1) == <f32>1);
assert(<f32><u16>(65535) == <f32>65535);
assert(<f32><u16>(65536) == <f32>0);
assert(<f32><u16>(65537) == <f32>1);

assert(<f32><i16>(1) == <f32>1);
assert(<f32><i16>(65535) == <f32>-1);
assert(<f32><i16>(65536) == <f32>0);
assert(<f32><i16>(65537) == <f32>1);

assert(<f64><u8>(1) == <f64>1);
assert(<f64><u8>(255) == <f64>255);
assert(<f64><u8>(256) == <f64>0);
assert(<f64><u8>(257) == <f64>1);

assert(<f64><i8>(1) == <f64>1);
assert(<f64><i8>(255) == <f64>-1);
assert(<f64><i8>(256) == <f64>0);
assert(<f64><i8>(257) == <f64>1);

0 comments on commit 67579de

Please sign in to comment.