Skip to content

frem float miscompilation #5399

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
pepyakin opened this issue Jul 20, 2017 · 2 comments
Closed

frem float miscompilation #5399

pepyakin opened this issue Jul 20, 2017 · 2 comments

Comments

@pepyakin
Copy link

pepyakin commented Jul 20, 2017

Source: rust-lang/rust#42629

Minimized example:

define float @foo(float, float) unnamed_addr #2 {
start:
  %2 = frem float %0, %1
  ret float %2
}
emcc -s BINARYEN=1 -s "EXPORTED_FUNCTIONS=['_foo']" example.ll

Gives following output (stripped):

[wasm-validator error in function $_foo] 3 != 4: call param types must match[wasm-validator error in function $_foo] 3 != 4: call param types must match, on
[f64] (call $f64-rem
 [f32] (get_local $0)
 [f32] (get_local $1)
), on
[f64] (call $f64-rem
 [f32] (get_local $0)
 [f32] (get_local $1)
)
(on argument
(on argument 0)
0)
[wasm-validator error in function $_foo] [wasm-validator error in function $_foo] 3 != 4: 3 != 4: call param types must match, on
[f64call param types must match, on
[f64] (call $] (call $f64-rem
 [f64-rem
 [f32] (get_local f32] (get_local $0)
$0)
 [f32]  [f32] (get_local $1(get_local $1)
)
)
)
(on argument 1)

emcc version:

emcc (Emscripten gcc/clang-like replacement) 1.37.15 (commit f6d143855e660647e8f09795e7d2dbdd5b64245c)
@pepyakin
Copy link
Author

It seems like f64-rem is asm2wasm binaryen stuff.

Invoking emcc with -s "BINARYEN=1" produces following (minimized) asm.js:

function () {
  "almost asm";

  var STACKTOP = 0, STACK_MAX = 0;
  var Math_fround=global.Math.fround;

  function _foo($0,$1) {
    $0 = Math_fround($0);
    $1 = Math_fround($1);
    var $2 = Math_fround(0), label = 0, sp = 0;
    sp = STACKTOP;
    $2 = Math_fround($0 % $1);
    return (Math_fround($2));
  }
  return { _foo: _foo };
}

asm2wasm chocking with this input:

[wasm-validator error in function $_foo] 3 != 4: call param types must match, on
[f64] (call $f64-rem
 [f32] (get_local $0)
 [f32] (get_local $1)
)
(on argument 0)
[wasm-validator error in function $_foo] 3 != 4: call param types must match, on
[f64] (call $f64-rem
 [f32] (get_local $0)
 [f32] (get_local $1)
)
(on argument 1)
(module
 (type $FUNCSIG$ddd (func (param f64 f64) (result f64)))
 (import "asm2wasm" "f64-rem" (func $f64-rem (param f64 f64) (result f64)))
 (import "env" "memory" (memory $0 256 256))
 (import "env" "table" (table 0 0 anyfunc))
 (import "env" "memoryBase" (global $memoryBase i32))
 (import "env" "tableBase" (global $tableBase i32))
 (global $STACKTOP (mut i32) (i32.const 0))
 (global $STACK_MAX (mut i32) (i32.const 0))
 (export "_foo" (func $legalstub$_foo))
 (func $_foo (param $$0 f32) (param $$1 f32) (result f32)
  (local $$2 f32)
  (local $label i32)
  (local $sp i32)
  (set_local $sp
   (get_global $STACKTOP)
  )
  (set_local $$2
   (f32.demote/f64
    (call $f64-rem
     (get_local $$0)
     (get_local $$1)
    )
   )
  )
  (return
   (get_local $$2)
  )
 )
 (func $legalstub$_foo (param $0 f64) (param $1 f64) (result f64)
  (f64.promote/f32
   (call $_foo
    (f32.demote/f64
     (get_local $0)
    )
    (f32.demote/f64
     (get_local $1)
    )
   )
  )
 )
)

When used without binaryen, emscripten produces asm.js like following (minimized):

function () {
  "almost asm";

  var STACKTOP = 0, STACK_MAX = 0;
  var Math_fround=global.Math.fround;

  function _foo($0,$1) {
   $0 = +$0;
   $1 = +$1;
   var $2 = 0.0, label = 0, sp = 0;
   sp = STACKTOP;
   $2 = $0 % $1;
   return (+$2);
  }

  return { _foo: _foo };
}

which compiles down to nice webassembly:

(module
 (type $FUNCSIG$ddd (func (param f64 f64) (result f64)))
 (import "asm2wasm" "f64-rem" (func $f64-rem (param f64 f64) (result f64)))
 (import "env" "memory" (memory $0 256 256))
 (import "env" "table" (table 0 0 anyfunc))
 (import "env" "memoryBase" (global $memoryBase i32))
 (import "env" "tableBase" (global $tableBase i32))
 (global $STACKTOP (mut i32) (i32.const 0))
 (global $STACK_MAX (mut i32) (i32.const 0))
 (export "_foo" (func $_foo))
 (func $_foo (param $$0 f64) (param $$1 f64) (result f64)
  (local $$2 f64)
  (local $label i32)
  (local $sp i32)
  (set_local $sp
   (get_global $STACKTOP)
  )
  (set_local $$2
   (call $f64-rem
    (get_local $$0)
    (get_local $$1)
   )
  )
  (return
   (get_local $$2)
  )
 )
)

I'm not an expert in emscripten/binaryen thing, but I tend to think binaryen is actual culprit here.

@kripken
Copy link
Member

kripken commented Jul 20, 2017

Should be fixed by that binaryen PR.

@kripken kripken closed this as completed Jul 20, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants