[fpc-pascal] Mozilla XPCOM

Jonas Maebe jonas.maebe at elis.ugent.be
Mon Jun 7 16:25:59 CEST 2010


On 07 Jun 2010, at 15:59, José Mejuto wrote:

> Monday, June 7, 2010, 10:34:26 AM, you wrote:
>
> JM> safecall is not supported (= ignored) on non-Windows platforms,
> JM> because it is completely Windows-specific. Afaik, GCC does not  
> support
> JM> any safecall calling convention on Linux either.
>
> It is "silently" changed by stdcall do not ?

It is completely ignored. So it is the same as the default calling  
convention (which is register on i386, and stdcall=register=cdecl=...  
on other platforms).

> JM> Are you certain when using XPCOM with GCC, it automatically  
> transforms
> JM> every function so that
>
> First I must conclude that XPCOM in Linux is compiled with GCC and
> which version is being used, but I'm quite sure it is GCC ;)
>
> JM> a) the result is passed as a hidden parameter by reference
> JM> b) the actual function results becomes an error code
>
> Plain function result is in EAX, if I call (in ASM) QueryInterface
> with garbaged IIDs I get "$80004002" in the EAX (NOT_INTERFACE). Just
> the same as in Windows using safecall except the stack clean.

Ok. In the mean time I found some more info about how XPCOM works:
* http://benjamin.smedbergs.us/blog/2008-09-26/allocated-memory-and-shared-library-boundaries/ 
  : apparently, all code that makes use of XPCOM via C/C++ is supposed  
to be written in IDL, which is then transformed into C++ code that  
conforms to the safecall conventions (apart from the caller rather  
than the callee cleaning up).
* https://developer.mozilla.org/En/Xptcall_Porting_Guide : a  
description of how the dispatching works (but that's not really  
relevant in case of FPC, since FPC natively supports calling COM  
interfaces on Linux).

> JM> c) a check is inserted after every call that checks this error  
> code
>
> To check this I must compile something with GCC and I do not have it
> installed and I do not have a source to compile with it. I should
> investigate following other paths.

At first sight that does not happen in XPCOM, even on Windows (but  
since we do it on Windows, maybe we should also do it elsewhere for  
consistency reasons).

>> Could this be considered a bug in fpc interfaces ?
>>
> JM> Yes, it is always wrong to assume that "const" enforces passing by
> JM> reference (except when using the mwpascal calling convention).
>
> So a "const x: TGUID" will be passed by reference in safecall and as
> 16 bytes in cdecl ? Is this OK ? Is this how GCC excepts a const
> parameter TGUID to be passed ?

In C, "const" does not modify how a parameter is passed in any way. If  
a parameter is passed by value without "const", then it's also passed  
by value with "const". The problems are
a) in Pascal, the behaviour of const is completely undefined (the  
compiler can do whatever it wants)
b) a lot of people use Pascal "const" as translation for C's "const *"  
for record parameters, which is wrong (but which sometimes works by  
accident)

Moreover, in FPC not all platforms consistently treat const record  
parameters the same as a regular parameters for cdecl (at least ARM  
currently always passes const records by reference for some reason).  
In short: "const" is a mess as far as predicting how it affects  
passing record parameters, and hence it should never be used in record  
parameter declarations for external C functions.

It's possible that it has a special meaning for safecall, I don't know.

> I'm asking because now I have changed
> my interface definition to use PGUID instead (both windows and linux)
> and it works more or less, but now I have a problem in the
> TInterfacedObject which seems to be the cause of some crashes, but I
> can not say by now if it is related to XPCOM exposing a different
> "IUnknown" (maybe cdecl instead stdcall) or TGUID related. I'll
> investigate further.

I think that nobody who understands both on the code generator and the  
RTL side of COM interfaces ever worked on XPCOM interoperability on  
non-Windows.

> One question, is there any way in fpc to "define" the calling
> convention as a C define ? Just something like:
>
> {$IFDEF UNIX}
>  {$DEFINE THECALLING cdecl}
> {$ELSE}
>  {$DEFINE THECALLING safecall}
> {$ENDIF}
> function x: integer; THECALLING;
>
> I had replaced all safecalls with:
>
> {$IFDEF xx}safecall{$ENDIF}{$IFDEF y}cdecl{$ENDIF}
>
> But it is quite "awful" :)

Yes, it is possible with {$macro on}. Example from the opengl unit:

{$MODE Delphi}
{$MACRO ON}
{$IFDEF Windows}
   {$DEFINE extdecl := stdcall}
{$ELSE}
   {$DEFINE extdecl := cdecl}
   {$IFDEF MorphOS}
     {$INLINE ON}
     {$DEFINE GL_UNIT}
   {$ELSE}
     {$LINKLIB c}
   {$ENDIF}
{$ENDIF}
...
var
   glAccum: procedure(op: GLenum; value: GLfloat); extdecl;


I'm personally not really interested in fixing this whole mess though.  
I spend a lot of time in the past disabling safecall in the compiler  
for all non-Windows platforms because it always generated wrong code  
elsewhere. Now it seems it should be
a) enabled everywhere, and then
b) fixed for all platforms, which requires modification to the  
parameter managers of most architectures (since most don't contain any  
support for safecall)


Jonas




More information about the fpc-pascal mailing list