This is the mail archive of the libffi-discuss@sourceware.org mailing list for the libffi project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Libffi (git master) and guile (git master) on MIPS n32


-[ Mon, Feb 07, 2011 at 01:58:07PM -0800, Andrew Pinski ]----
> > The problem is : of these 64 bits, only the 32 lowest bits were set by
> > guile, and the upper 32 are desperately random.
> 
> How were those lower 32bits set?  If set by the 32bit instructions
> then it is automatically sign extended.  If not then there is a bug in
> how guile is doing the returns

These lowest 32bits were set by guile's foreign.c/unpack function, using
this:

// called with type = ffi_cif->rtype of course, and loc = return value address
unpack (const ffi_type *type, void *loc, SCM x)
{
  switch (type->type)
    {
	(...)
    case FFI_TYPE_SINT32:
      *(scm_t_int32 *) loc = scm_to_int32 (x);
      break;
	(...)
    }
}

(note: this cast of an lvalue is not legal C but that's another story)

AFAICT, Guile is not tell how much data it should write, so it must resort
on rtype->type.

> Unless you have a bug somewhere in which you are using a non sign
> extended value with the 32bit instructions which then it becomes
> undefined at what the value of those instructions do (could be either
> treating it as a 64bit value, or do a sign extend or even put
> 0xDEADBEEFDEADBEEF in the register which is what the Octeon simulators
> do).

Sorry I do not understand this. Let's take a concrete exemple : guile
comparison function returns -1 to qsort. So it writes -1 on the return
value location (as a 32 bits value) with the code given above. This
location, which 32 upper bits were random (but positive) now looks like
this quad-word (this is a little endian mips) :

0x7fff09c0: 0xFF 0xFF 0xFF 0xFF 0x78 0x56 0x34 0x12

Now libffi loads this value into v0 :

ffi_closure_N32:
   (...)
   # Return flags are in v0
   bne     v0, FFI_TYPE_SINT32, cls_retint  # v0 = FFI_TYPE_INT here, from the flags
   lw  v0, V0_OFF2($sp)
   (...)
cls_retint:
   bne     v0, FFI_TYPE_INT, cls_retfloat
   ld      v0, V0_OFF2($sp)                 # now v0 = 0x12345678FFFFFFFF
   b   cls_epilogue

And now we are back to the libc qsort, which will certainly compare v0
with 0 and see it's positive.



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]