<html>
<head>
<base href="https://bugs.llvm.org/">
</head>
<body><table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Bug ID</th>
<td><a class="bz_bug_link
bz_status_NEW "
title="NEW - [WebAssembly] Float cast after !! can be wrong when compiled with -x c++"
href="https://bugs.llvm.org/show_bug.cgi?id=44012">44012</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>[WebAssembly] Float cast after !! can be wrong when compiled with -x c++
</td>
</tr>
<tr>
<th>Product</th>
<td>libraries
</td>
</tr>
<tr>
<th>Version</th>
<td>trunk
</td>
</tr>
<tr>
<th>Hardware</th>
<td>PC
</td>
</tr>
<tr>
<th>OS</th>
<td>other
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Severity</th>
<td>release blocker
</td>
</tr>
<tr>
<th>Priority</th>
<td>P
</td>
</tr>
<tr>
<th>Component</th>
<td>Backend: WebAssembly
</td>
</tr>
<tr>
<th>Assignee</th>
<td>tlively@google.com
</td>
</tr>
<tr>
<th>Reporter</th>
<td>bernhard_mlist@outlook.com
</td>
</tr>
<tr>
<th>CC</th>
<td>llvm-bugs@lists.llvm.org
</td>
</tr></table>
<p>
<div>
<pre>With all llvm/clang versions that support the wasm32 target (8, 9, current
build of 10) the following function returns the correct 0.0f when compiled with
'-x c' but it wrongfully returns 1.0f when compiled with '-x c++'.
#ifdef __cplusplus
extern "C"
#endif
float test()
{
static unsigned int mask = 2;
mask |= 4;
return (float)(!!(mask & 1));
}
Here is how I built it to a wasm module:
clang -x c -nostdinc -O3 -target wasm32 -c -o test.c.o test.c
wasm-ld -no-entry -export=test -o test.c.wasm test.c.o
clang -x c++ -nostdinc -O3 -target wasm32 -c -o test.cpp.o test.c
wasm-ld -no-entry -export=test -o test.cpp.wasm test.cpp.o
And here is how I run the test in node.js v12
node -e "WebAssembly.instantiate(new
Uint8Array(require('fs').readFileSync('test.c.wasm'))).then(m => {
console.log('c: ' + m.instance.exports.test()); })"
node -e "WebAssembly.instantiate(new
Uint8Array(require('fs').readFileSync('test.cpp.wasm'))).then(m => {
console.log('cpp: ' + m.instance.exports.test()); })"
The output I get is
c: 0
cpp: 1
And this is the disassembly when running it through the wasm2wat tool from
wabt:
wasm2wat -f test.c.wasm
(func $test (type 0) (result f32)
(local i32)
(i32.store offset=1024
(i32.const 0)
(i32.and
(local.tee 0
(i32.load offset=1024
(i32.const 0)))
(i32.const 5)))
(f32.convert_i32_s
(i32.and
(local.get 0)
(i32.const 1))))
wasm2wat -f test.cpp.wasm
(func $test (type 0) (result f32)
(local i32)
(i32.store offset=1024
(i32.const 0)
(i32.and
(local.tee 0
(i32.load offset=1024
(i32.const 0)))
(i32.const 5)))
(select
(f32.const 0x1p+0 (;=1;))
(f32.const 0x0p+0 (;=0;))
(local.get 0)))
The disassembly of the '-x c' module reads basically what the original C code
was.
But it looks like the '-x c++' module returns something like
(value_of_mask_at_function_entry ? 1 : 0) which makes no sense to me.
If the code line `mask |= 4` is changed into `mask &= 1`, the function returns
1 the first time it is called, then 0 afterwards which matches that assumption
(the '-x c' variant stays correct).
Playing with compilation flag variations like -O0 did not affect the result.
Here's the versions I tested with (all on Win64)
LLD 10.0.0 / clang version 10.0.0 (trunk) Target: x86_64-pc-windows-msvc
LLD 8.0.0 / clang version 8.0.0 (tags/RELEASE_800/final) Target:
x86_64-pc-windows-msvc
LLD 9.0.0 / clang version 9.0.0 (tags/RELEASE_900/final) Target:
x86_64-pc-windows-msvc
They all produced identical assembly as far as I can tell.</pre>
</div>
</p>
<hr>
<span>You are receiving this mail because:</span>
<ul>
<li>You are on the CC list for the bug.</li>
</ul>
</body>
</html>