[fpc-devel] C-block reference syntax (blocker for 3.2)

Sven Barth pascaldragon at googlemail.com
Sun Dec 8 20:30:47 CET 2019


Am 07.12.2019 um 22:46 schrieb Blaise at blaise.ru:
> On 07.12.2019 21:39, Sven Barth wrote:
>> I'm arguing that there is no builtin way to *access* the parameters 
>> passed in such a way.
>
> You are arguing that /now/, but it is not what you said earlier. You 
> said, verbatim:
>> one can not access VarArgs parameters inside a Delphi function 
>> (without resorting to assembly)
> Like I said, this is factually incorrect.

I had forgotten about pointers to the stack area which I got reminded 
off when I found the link I sent. But that doesn't change that there is 
no official way to access such parameters.

>
>> there are hacks
>
> A custom va_list implementation, fully conforming to the ABI and 
> particularities of the compiler, is not necessarily a hack. (In the 
> sense that is not of questionable design, implementation quality, and 
> maintainability.)
>
>> but this is not guaranteed to work on every platform.
>
> Where did that requirement of "every platform" suddenly come from? One 
> needs to roll out their own va_list implementations only for the 
> platforms A) that he targets, and B) on which the stock implementation 
> is not provided.

It's to show the restriction of the approach that is shown in the link. 
While it works on i386-win32 and probably also x86_64-win64 it would 
fail on e.g. x86_64-linux (or any other x86_64 platform following the 
Sys V ABI). I give you point A, but B is moot as there is no stock 
implementation in Delphi for *any* platform.

>
>> an anonymous function with varargs modifier will not be allowed anyway
>
> Right. FTR, my patch will eventually allow exactly that, and so does 
> DCC already.
> Or are you still not aware of the latter? For the fourth time: VARARGS 
> is allowed and works with DCC, on both sides, without BASM or ugly 
> hacks, on more than one platform :) Some of them even have stock 
> implementations of va_list, FPC should take a hint.

But only on i386-win32 and x86_64-win64. On Sys V ABI x86_64 targets 
there is no way around it, because the arguments are passed in 
registers, not in the stack area. That's why GCC implements the va[ist 
functionality using compiler intrinsics instead of macros as is the case 
on Windows.

And no, your patch WILL NOT allow that. We've consciously decided 
AGAINST implementing varargs functions in Pascal (see 
https://wiki.freepascal.org/User_Changes_2.6.0#Array_of_const_parameters_and_cdecl_routines 
) and we DO NOT WANT to support this.

So what will be allowed is this:

=== code begin ===

type
   TSomeProc = reference to procedure(aFmt: PChar); cdecl; varargs;

=== code end ===

but not this:

=== code begin ===

var
   proc: TSomeProc;
begin
   proc := procedure(aFmt: PChar) cdecl varargs
     begin
       { do something with aFmt and the variadic arguments }
     end;
end.

=== code end ===

Just as it is for procedure and method variables.

And yes, it makes sense to allow it for one, but to deny it for another, 
because as TSomeProc is an interface it can be used to interface (no pun 
intended) with external code that provides such an interface as well 
(e.g. delegates in COM/WinRT, though I have yet so see a varargs 
function there...).

For Pascal code there is "array of const" which is better anyway, cause 
all values contain type information about the passed value. And it works 
cross platform (which for FPC *is* important).

>
>> You need procvar specific functionality, because you need to restrict 
>> the available modifiers to those available for procvars.
>
> And if I use the procvardef parser, I, like Jonas, would need to 
> prohibit "OF OBJECT" and "IS NESTED". One extra work for another.

The code of procvar_dec as it is currently does not forbid it. So that 
will need to be improved anyway.

>
>> You extend tprocvardef.create with a doregister parameter
>> you convert the procvar to an interface method and then free the no 
>> longer required procvardef.
>
> Right. The unnecessary work I am currently avoiding.
> Since I have not yet submitted that part for review, let us avoid 
> premature pointless discussion.
>
>> you're parsing something that's in essence a fancy procedure/method 
>> variable which is completely independant of it being implemented by 
>> an interface
>
> "Completely independent"?
> You do realise that method reference types "being <...> interface[s]" 
> is pretty much a part of the specification?
> ----------8<----------
> type M = reference to procedure (const N: Integer);
> type C = class (TInterfacedObject, M)
>     procedure Invoke(const N: Integer); virtual; abstract;
> end;
> end.
> ----------8<----------
>
Yes, it's part of the specification (and I'm not arguing that!), but for 
the parser itself it is simply an implementation detail. Just like 
method pointers are implemented using a record that contains both a 
CodePointer and a data Pointer.

Regards,
Sven


More information about the fpc-devel mailing list