Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

Ticket #463 (assigned defect)

Opened 11 years ago

Last modified 10 years ago

Unittest fails in tango.math.IEEE using gdc

Reported by: larsivi Assigned to: larsivi (accepted)
Priority: major Milestone: External Bugs
Component: Core Functionality Version:
Keywords: gdc, linux, x86, triage Cc: dclugston@googlemail.com

Description

tango.core.Exception.AssertException?@tango/math/IEEE.d(279): Assertion failure

Using GDC 0.23 on linux 32 bit

Change History

05/11/07 20:30:45 changed by kris

  • version deleted.
  • milestone changed from 0.98 RC 2 to 0.99 RC3.

This may be due to the bugs in GDC 0.23 FP support, so will be deferred until a new version of GDC is released

07/03/07 03:00:31 changed by kris

  • milestone changed from 0.99 RC3 to 1.0.

Hiya Don

I'm moving six of your tickets to 1.0, since the release is already late. Can you enable some traction on these tickets, please? Some of them, I don't know what to do with. Perhaps you do?

09/30/07 18:45:41 changed by Carlos

I tried to test this, but I got these undefined symbols:

___finite
___finitef
___finitel
___fpclassifyl
___isnanl

GDC on Mac OS X.

09/30/07 18:51:42 changed by Carlos

I see why that's happening: I just now noticed #627.

11/05/07 11:35:58 changed by larsivi

Retested with gdc (GCC) 4.1.3 20070831 (prerelease gdc 0.25, using dmd 1.021) (Ubuntu 0.25-4.1.2-16ubuntu1), x86.

tango.math.IEEE unittests fails on lines

  • 296
  • 299
  • 303
  • 306
  • 307

Weird fact, the test on line 306 didn't fail until after I commented out 307.

01/14/08 13:34:58 changed by Don Clugston

There's either a bug in GDC's generation of inline asm (since GDC has problems with so many other x87 opcodes, perhaps it is failing with fldsw/fstsw?), or else it is not obeying the D ABI. It seems that the return value of ieeeFlags() is being lost; perhaps GDC expects the return value to be somewhere other than EAX.

The asm output should show which of these is the problem.

If the inline asm is OK, then adding short tmp1; asm {

: // existing function mov tmp1, AX;

}

return tmp1;

into getIeeeFlags() should allow the test to pass.

01/20/08 11:19:58 changed by larsivi

It is well known that GDC don't follow the D calling convention, will test the above to identify this particular problem though.

01/20/08 14:25:31 changed by larsivi

Seems like I'm not able to grok what you mean as I can't get what I try to compile. Could you please provide the code for what you mean such that it also compiles and runs correctly with DMD?

01/24/08 20:13:00 changed by larsivi

  • milestone changed from 1.0 to External Bugs.

01/25/08 07:39:29 changed by Don Clugston

In math.IEEE line 184-201, see if this code works for gdc.

    static IeeeFlags getIeeeFlags()
    {
        // This is a highly time-critical operation, and
        // should really be an intrinsic.
       version(D_InlineAsm_X86) {
           IeeeFlags tmp1;
           asm {
              fstsw AX;
              // NOTE: If compiler supports SSE2, need to OR the result with
              // the SSE2 status register.
              // Clear all irrelevant bits
              and EAX, 0x03D;
              mov tmp1.m_flags, EAX;
           }
           return tmp1;
       } else {
           assert(0, "Not yet supported");
       }
    }

01/25/08 09:38:05 changed by larsivi

Tested with DMD 1.025 and GDC soon-to-be 0.25 on Linux:

DMD says: tango/math/IEEE.d(198): bad type/size of operands '*(& tmp1)'

GDC says: tango/math/IEEE.d:198: Error: invalid operand

Line 198 is "mov tmp1.m_flags, EAX;"

02/15/08 09:53:09 changed by Don Clugston

OK, try this instead (it compiles OK on DMD win):

version(D_InlineAsm_X86) {

IeeeFlags? tmp1; asm {

fstsw AX; // NOTE: If compiler supports SSE2, need to OR the result with // the SSE2 status register. // Clear all irrelevant bits and EAX, 0x03D; mov tmp1, EAX;

} return tmp1;

}

02/15/08 10:37:11 changed by larsivi

With the above code, the unittests in IEEE pass correctly.

Can we then conclude that this is due to GDC breaking the calling convention?

02/15/08 14:50:09 changed by Don Clugston

Yes, GDC's inline asm seems to be OK. Int return values are supposed to be in EAX, but it seems that isn't respecting that part of the ABI. Or it could even be that it's doing something like inserting a 'return 0' at the end of any non-void function which doesnt have a return statement. Would be interesting to see the generated asm to see what it's actually generating.

Regardless, this will do for now. Is 'version(GDC)' correct? (I don't know what its predefined version identifier is. If so, please fold this in and close the ticket.

    static IeeeFlags getIeeeFlags()
    {
        // This is a highly time-critical operation, and
        // should really be an intrinsic. 


       version(D_InlineAsm_X86) {
          version(GDC) {
          IeeeFlags tmp1;
           asm {
              fstsw AX;
              // NOTE: If compiler supports SSE2, need to OR the result with
              // the SSE2 status register.
              // Clear all irrelevant bits
              and EAX, 0x03D;
              mov tmp, EAX;
           }
           return tmp1;
         } else { // DMD
           // In this case, we
           // take advantage of the fact that for DMD
           // a struct containing only a int is returned in EAX.
           asm {
              fstsw AX;
              // NOTE: If compiler supports SSE2, need to OR the result with
              // the SSE2 status register.
              // Clear all irrelevant bits
              and EAX, 0x03D;
           }
       } else {
           /*   SPARC:
               int retval;
               asm { st %fsr, retval; }
               return retval;
            */
           assert(0, "Not yet supported");
       }
    }

02/15/08 19:43:42 changed by larsivi

(In [3192]) Workaround for gdc function calling mess. thanks Don! refs #463

02/15/08 19:45:47 changed by larsivi

  • status changed from new to assigned.
  • owner changed from Don Clugston to larsivi.

Note, version id is GNU. I want to keep the ticket until we can remove the workaround.

02/17/08 19:58:13 changed by larsivi

  • keywords changed from gdc, linux to gdc, linux, x86.

Disassembly for correct ASM, but segmentation fault:

00000000 <_D5tango4math4IEEE9IeeeFlags12getIeeeFlagsFZS5tango4math4IEEE9IeeeFlags>:
       0:	55                   	push   %ebp
       1:	89 e5                	mov    %esp,%ebp
       3:	9b df e0             	fstsw  %ax
       6:	83 e0 3d             	and    $0x3d,%eax
       9:	5d                   	pop    %ebp
       a:	c2 04 00             	ret    $0x4

Disassembly for working workarounded code:

00000000 <_D5tango4math4IEEE9IeeeFlags12getIeeeFlagsFZS5tango4math4IEEE9IeeeFlags>:
       0:	55                   	push   %ebp
       1:	89 e5                	mov    %esp,%ebp
       3:	83 ec 10             	sub    $0x10,%esp
       6:	8b 55 08             	mov    0x8(%ebp),%edx
       9:	c7 45 fc 00 00 00 00 	movl   $0x0,-0x4(%ebp)
      10:	9b df e0             	fstsw  %ax
      13:	83 e0 3d             	and    $0x3d,%eax
      16:	89 45 fc             	mov    %eax,-0x4(%ebp)
      19:	8b 45 fc             	mov    -0x4(%ebp),%eax
      1c:	89 02                	mov    %eax,(%edx)
      1e:	89 d0                	mov    %edx,%eax
      20:	c9                   	leave  
      21:	c2 04 00             	ret    $0x4

02/18/08 08:19:53 changed by Don Clugston

Looks as though it's returning a pointer to the struct, instead of in EAX. Oops -- GDC is correct, according to the ABI page:

# For Windows, 1, 2 and 4 byte structs are returned in EAX. # For other struct sizes, and for all structs on Linux, the return value is stored through a hidden pointer passed as an argument to the function.

I hadn't noticed that DMD is different on Linux compared to Windows. How annoying!

Does GDC have the same difference? (I would imagine that it doesn't, it seems very quirky).

02/18/08 08:34:03 changed by larsivi

Here is the dump for DMD btw:

00000000 <_D5tango4math4IEEE9IeeeFlags12getIeeeFlagsFZS5tango4math4IEEE9IeeeFlags>:
   0:	55                   	push   %ebp
   1:	8b ec                	mov    %esp,%ebp
   3:	df e0                	fnstsw %ax
   5:	83 e0 3d             	and    $0x3d,%eax
   8:	5d                   	pop    %ebp
   9:	c3                   	ret    
   a:	90                   	nop    
   b:	90                   	nop   

02/18/08 09:23:49 changed by larsivi

huh, disassembly of the DMD version shows fnstsw is used and with GDC fstsw - any significance in that?

02/18/08 09:24:43 changed by larsivi

Oh, and DMD doesn't seem to return a pointer to struct ...

02/23/08 11:06:44 changed by larsivi

Any conclusion, Don?

03/21/08 11:49:35 changed by larsivi

Don?

04/08/08 16:48:47 changed by larsivi

  • cc set to Don, Clugston.

I'd like to get some closure on this one (from the expert).

05/07/08 18:26:16 changed by larsivi

  • cc changed from Don, Clugston to "Don, Clugston".

05/07/08 18:27:30 changed by larsivi

  • cc changed from "Don, Clugston" to dclugston@googlemail.com.

05/24/08 18:37:57 changed by larsivi

  • keywords changed from gdc, linux, x86 to gdc, linux, x86, triage.

05/26/08 06:23:12 changed by Don Clugston

(a) There's no difference between fnstsw and fstsw. Don't worry about that. (fnstsw behaves oddly on 8087, it's the same as fstsw on 80287(!) or later, except that it is faster) (b) It should be version(Linux) (or is that version(Posix)?) instead of version(GDC). Other than that, we can close this ticket.

05/26/08 16:36:28 changed by larsivi

Posix, yes - but what about GDC on Windows?