snazzy-d/sdc

packedfloat tests failing with ldc

John-Colvin opened this issue · 6 comments

EDIT: this was done on apple silicon, I thought that was the cause, turns out it's an ldc thing, not an apple silicon thing. see #278 (comment)

Here's what I'm seeing (including my diff that I'm using to see more info)

% git diff
diff --git a/src/source/packedfloat.d b/src/source/packedfloat.d
index d680519f..cbf71754 100644
--- a/src/source/packedfloat.d
+++ b/src/source/packedfloat.d
@@ -645,7 +645,18 @@ unittest {
 
                auto f0 = sf.to!float();
                auto fi = *(cast(uint*) &f0);
-               assert(f0 == strtof(t.expected.ptr, null), t.expected);
+               auto r = strtof(t.expected.ptr, null);
+               if (f0 != r) {
+                       import std.stdio : stderr;
+                       import core.math : ldexp;
+                       stderr.writeln(t);
+                       stderr.writefln("fi               = %x", fi);
+                       stderr.writefln("t._float         = %x", t._float);
+                       stderr.writefln("*(cast(uint*)&r) = %x", *(cast(uint*)&r));
+                       auto manual = ldexp(float(t.mantissa), t.exponent);
+                       stderr.writefln("manual           = %x", *(cast(uint*)&manual));
+                       assert(false, t.expected);
+               }
                assert(fi == t._float, t.expected);
 
                auto d0 = sf.to!double();

% ldmd2 -unittest -main -debug -Isrc -i -run src/source/packedfloat.d
src/source/context.d(17): Deprecation: alias this for classes/interfaces is deprecated
core.exception.AssertError@src/source/lexnumeric.d(466): Assertion failure
----------------
??:? object.Throwable.TraceInfo core.runtime.defaultTraceHandler(void*) [0x1003ab0a3]
??:? void source.lexnumeric.__unittest_L429_C1() [0x1002c2faf]
??:? int core.runtime.runModuleUnitTests().__foreachbody6(object.ModuleInfo*) [0x1003ab32f]
??:? _d_run_main [0x1003b3c47]
??:? main [0x1002b38c3]
??:? start [0x18f0e3f27]
??:? 0x0 [0xfe3a7fffffffffff]
immutable(TestCase)("0x8000000000000001p-213", 9223372036854775809, -213, 1, 3931642474694443008)
fi               = 0
t._float         = 1
*(cast(uint*)&r) = 1
manual           = 0
core.exception.AssertError@src/source/packedfloat.d(658): 0x8000000000000001p-213
----------------
??:? object.Throwable.TraceInfo core.runtime.defaultTraceHandler(void*) [0x1003ab0a3]
??:? source.packedfloat.__unittest [0x100374797]
??:? _d_run_main [0x1003b3c47]
??:? main [0x1002b38c3]
??:? start [0x18f0e3f27]
??:? 0x0 [0xfe3a7fffffffffff]
2/20 modules FAILED unittests
Error: /var/folders/bg/ncfhn34x10b5m6cw_n_kr8580000gn/T/source.packedfloat-d4390b failed with status: 1

I'm fairly confident that this doesn't have much to do with apple silicon, and a lot to do with strtof trying to do something "useful".

Yes I think you are correct it's not an apple silicon thing. It's just an ldc thing (at least on the surface).

Here's the same thing on x86_64 linux showing it failing with ldc.

$ ldmd2 -unittest -main -debug -Isrc -i -run src/source/packedfloat.d
src/source/context.d(17): Deprecation: alias this for classes/interfaces is deprecated
immutable(TestCase)("0x8000000000000001p-213", 9223372036854775809, -213, 1, 3931642474694443008)
fi               = 0
t._float         = 1
*(cast(uint*)&r) = 1
manual           = 0
core.exception.AssertError@src/source/packedfloat.d(658): 0x8000000000000001p-213
----------------
??:? [0x55e7f5eff336]
??:? [0x55e7f5efefb2]
??:? [0x55e7f5f266d6]
??:? [0x55e7f5f0736c]
??:? [0x55e7f5efe072]
??:? [0x55e7f5ed975e]
??:? [0x55e7f5edbe3a]
??:? [0x55e7f5eff264]
??:? [0x55e7f5f0d199]
??:? [0x55e7f5f0d6c9]
??:? [0x55e7f5f0d12b]
??:? [0x55e7f5f0385e]
??:? [0x55e7f5eff114]
??:? [0x55e7f5f0700a]
??:? [0x55e7f5f06f36]
??:? [0x55e7f5f06d8c]
??:? [0x55e7f5e26aa1]
??:? __libc_start_main [0x7f5a7797ad09]
??:? [0x55e7f5e269a9]
1/20 modules FAILED unittests
Error: /tmp/source.packedfloat-8168e7 failed with status: 1

$ dmd -unittest -main -debug -Isrc -i -run src/source/packedfloat.d
src/source/context.d(17): Deprecation: alias this for classes/interfaces is deprecated
20 modules passed unittests

ldc thing or a not-dmd thing?

So after a long debug session, the code is wrong. ldc does the right thing, but the result is wrong because the code is wrong.

dmd is wrong too. but the bug in dmd and the bug in the code cancel each other out! and you end up with the correct result out of dmd.

It seems there's quite a lot more that's broken. Here's everything I have to comment out to get packedfloat.d & lexnumeric.d tests to pass:

diff --git a/src/source/lexnumeric.d b/src/source/lexnumeric.d
index 8944d57c..51e1c639 100644
--- a/src/source/lexnumeric.d
+++ b/src/source/lexnumeric.d
@@ -702,13 +702,13 @@ unittest {
 
 	checkLexFloat(".0", 0);
 	checkLexFloat(".5", 0.5);
-	checkLexFloat(".6e0", 0.6);
+	//checkLexFloat(".6e0", 0.6);
 	checkLexFloat(".7e1", 7);
 	checkLexFloat(".8e+1", 8);
 	checkLexFloat(".9e-1", 0.09);
 
-	checkLexFloat("1234567.89", 1234567.89);
-	checkLexFloat("12.3456789", 12.3456789);
+	//checkLexFloat("1234567.89", 1234567.89);
+	//checkLexFloat("12.3456789", 12.3456789);
 
 	/*
 	checkLexFloat("3.141592653589793115997963468544185161590576171875",
@@ -724,13 +724,13 @@ unittest {
 	//*/
 
 	// Decimal floats with underscores.
-	checkLexFloat("1_234_567.89", 1234567.89);
-	checkLexFloat("1_2.34_567_89", 12.3456789);
-	checkLexFloat("1_234_567.89", 1234567.89);
-	checkLexFloat("1_2.34_567_89", 12.3456789);
+	//checkLexFloat("1_234_567.89", 1234567.89);
+	//checkLexFloat("1_2.34_567_89", 12.3456789);
+	//checkLexFloat("1_234_567.89", 1234567.89);
+	//checkLexFloat("1_2.34_567_89", 12.3456789);
 
-	checkLexFloat("1_234_567_.89", 1234567.89);
-	checkLexFloat("1_234_567.89_", 1234567.89);
+	//checkLexFloat("1_234_567_.89", 1234567.89);
+	//checkLexFloat("1_234_567.89_", 1234567.89);
 
 	checkTokenSequence("_1_234_567.89",
 	                   [TokenType.Identifier, TokenType.FloatLiteral]);
diff --git a/src/source/packedfloat.d b/src/source/packedfloat.d
index d680519f..92b6f95d 100644
--- a/src/source/packedfloat.d
+++ b/src/source/packedfloat.d
@@ -588,8 +588,8 @@ unittest {
 		         0x32a0000000000000),
 		TestCase("0x8000000000000000p-213", 0x8000000000000000,
 		         CF.SmallestPowerOfTwo, 0x00000000, 0x3690000000000000),
-		TestCase("0x8000000000000001p-213", 0x8000000000000001,
-		         CF.SmallestPowerOfTwo, 0x00000001, 0x3690000000000000),
+		//TestCase("0x8000000000000001p-213", 0x8000000000000001,
+		//         CF.SmallestPowerOfTwo, 0x00000001, 0x3690000000000000),
 		TestCase("0xffffff7fffffffffp64", 0xffffff7fffffffff, 64, 0x7f7fffff,
 		         0x47effffff0000000),
 		TestCase("0xffffff8000000000p64", 0xffffff8000000000, 64, 0x7f800000,
@@ -608,8 +608,8 @@ unittest {
 		         0x0000000000000000),
 		TestCase("0x8000000000000000p-1138", 0x8000000000000000,
 		         CD.SmallestPowerOfTwo, 0x00000000, 0x0000000000000000),
-		TestCase("0x8000000000000001p-1138", 0x8000000000000001,
-		         CD.SmallestPowerOfTwo, 0x00000000, 0x0000000000000001),
+		//TestCase("0x8000000000000001p-1138", 0x8000000000000001,
+		//         CD.SmallestPowerOfTwo, 0x00000000, 0x0000000000000001),
 		TestCase("0xfffffffffffffbffp960", 0xfffffffffffffbff, 960, 0x7f800000,
 		         0x7fefffffffffffff),
 		TestCase("0xfffffffffffffc00p960", 0xfffffffffffffc00, 960, 0x7f800000,
@@ -624,14 +624,14 @@ unittest {
 		// Float subnormal to normal.
 		TestCase("0xfffffeffffffffffp-190", 0xfffffeffffffffff, -190,
 		         0x007fffff, 0x380fffffe0000000),
-		TestCase("0xffffff0000000000p-190", 0xffffff0000000000, -190,
-		         0x00800000, 0x380fffffe0000000),
+		//TestCase("0xffffff0000000000p-190", 0xffffff0000000000, -190,
+		//         0x00800000, 0x380fffffe0000000),
 
 		// Double subnormal to normal.
 		TestCase("0xfffffffffffff7ffp-1086", 0xfffffffffffff7ff, -1086,
 		         0x00000000, 0x000fffffffffffff),
-		TestCase("0xfffffffffffff800p-1086", 0xfffffffffffff800, -1086,
-		         0x00000000, 0x0010000000000000),
+		//TestCase("0xfffffffffffff800p-1086", 0xfffffffffffff800, -1086,
+		//         0x00000000, 0x0010000000000000),
 
 		// Integers past the range they can be represented exactly.
 		TestCase("0x1000001", 0x1000001, 0, 0x4b800000, 0x4170000010000000),

Fixed in e60476c . Turns out a bug in DMD was masking a bug in the code, so the result turned out to be correct on DMD entirely for the wrong reasons.