-
Notifications
You must be signed in to change notification settings - Fork 243
Closed
Description
Still getting to the root of this, discussion started at https://rust-lang.zulipchat.com/#narrow/stream/122651-general/topic/f128.20system.20libraries.20noncompliant.20platforms
Comparing this Rust code:
#![feature(f128)]
#[no_mangle]
fn mul_entry(a: f128, b: f128) -> f128 {
a * b
}
fn main() {
let a = f128::from_bits(0x00007fffffffffffffffffffffffffff);
let b = f128::from_bits(0x40007fffffffffffffffffffffffffff);
let c = mul_entry(a, b);
dbg!(c);
}
Against this C version:
#define __STDC_WANT_IEC_60559_TYPES_EXT__
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#if defined(__clang__) && (defined(__i386) || defined(__x86_64))
#define _Float128 __float128
#endif
typedef struct {
uint64_t lower, upper;
} u128;
void f128_print(_Float128 val) {
u128 ival = *((u128 *)(&val));
#ifndef __clang__
char buf[1024];
strfromf128(buf, sizeof(buf), "%.32g", val);
printf("%#018" PRIx64 "%016" PRIx64 " %s\n", ival.upper, ival.lower, buf);
#else
printf("%#018" PRIx64 "%016" PRIx64 " %lf\n", ival.upper, ival.lower, (double)val);
#endif
}
_Float128 new_f128(uint64_t upper, uint64_t lower) {
u128 val;
val.lower = lower;
val.upper = upper;
return *((_Float128 *)(&val));
}
int main() {
_Float128 a = new_f128(0x00007fffffffffff, 0xffffffffffffffff);
_Float128 b = new_f128(0x40007fffffffffff, 0xffffffffffffffff);
f128_print(a);
f128_print(b);
_Float128 c = a * b;
f128_print(c);
return 0;
}
With gcc:
0x00007fffffffffffffffffffffffffff 1.6810515715560467531313389086609e-4932
0x40007fffffffffffffffffffffffffff 3
0x00017ffffffffffffffffffffffffffc 5.0431547146681402593940167259826e-4932
Clang:
0x00007fffffffffffffffffffffffffff 0.000000
0x40007fffffffffffffffffffffffffff 3.000000
0x00017ffffffffffffffffffffffffffc 0.000000
Both of those are correct. However, the Rust version is not:
[f128_demo.rs:12:5] c = 0x00017ffffffffffffffffffffffffffb
Reproduction with C:
/usr/lib/llvm-14/bin/clang -cc1 -triple aarch64-unknown-linux-gnu -emit-obj \
-mrelax-all --mrelax-relocations -disable-free -clear-ast-before-backend \
-disable-llvm-verifier -discard-value-names \
-main-file-name f128_demo.c \
-mrelocation-model pic -pic-level 2 -pic-is-pie \
-mframe-pointer=non-leaf \
-fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 \
-target-cpu generic -target-feature +neon -target-feature +v8a -target-abi aapcs \
-fallow-half-arguments-and-returns -mllvm \
-treat-scalable-fixed-error-as-warning -debugger-tuning=gdb -v \
-fcoverage-compilation-dir=/root -resource-dir /usr/lib/llvm-14/lib/clang/14.0.0 \
-internal-isystem /usr/lib/llvm-14/lib/clang/14.0.0/include -internal-isystem /usr/local/include \
-internal-isystem /usr/bin/../lib/gcc/aarch64-linux-gnu/11/../../../../aarch64-linux-gnu/include \
-internal-externc-isystem /usr/include/aarch64-linux-gnu -internal-externc-isystem /include \
-internal-externc-isystem /usr/include -fdebug-compilation-dir=/root \
-ferror-limit 19 -fno-signed-char -fgnuc-version=4.2.1 -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 \
-o f128_demo_clang.o -x c f128_demo.c
Linking:
/usr/bin/ld -pie -EL -z relro --hash-style=gnu --build-id --eh-frame-hdr -m aarch64linux \
-dynamic-linker /lib/ld-linux-aarch64.so.1 \
-o f128_demo_clang.out \
/lib/aarch64-linux-gnu/Scrt1.o /lib/aarch64-linux-gnu/crti.o /usr/bin/../lib/gcc/aarch64-linux-gnu/11/crtbeginS.o \
-L/usr/bin/../lib/gcc/aarch64-linux-gnu/11 -L/lib/aarch64-linux-gnu -L/usr/lib/aarch64-linux-gnu \
-L/usr/lib/llvm-14/bin/../lib -L/lib -L/usr/lib \
f128_demo_clang.o \
-lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed \
/usr/bin/../lib/gcc/aarch64-linux-gnu/11/crtendS.o /lib/aarch64-linux-gnu/crtn.o
This produces the same correct output as above (ending in c
). However, changing the command to link the rust library
clang f128_demo.c \
.rustup/toolchains/nightly-aarch64-unknown-linux-gnu/lib/rustlib/aarch64-unknown-linux-gnu/lib/libcompiler_builtins-8750659c02157b46.rlib \
-o f128_demo_clang_with_rustlibs.out
Produces the same output as Rust, incorrect:
./f128_demo_clang_with_rustlibs.out
0x00007fffffffffffffffffffffffffff 0.000000
0x40007fffffffffffffffffffffffffff 3.000000
0x00017ffffffffffffffffffffffffffb 0.000000
rustc 1.80.0-nightly (6e1d94708 2024-05-10)
Metadata
Metadata
Assignees
Labels
No labels