Patchwork [Ada] Ease interface with builtins that returns void *

login
register
mail settings
Submitter Arnaud Charlet
Date July 16, 2012, 1:10 p.m.
Message ID <20120716131054.GA5416@adacore.com>
Download mbox | patch
Permalink /patch/171186/
State New
Headers show

Comments

Arnaud Charlet - July 16, 2012, 1:10 p.m.
The natural way to import a builtin that returns void * is to use
System.Address in Ada, which is in fact an integral type.

Addressed by this patch, which makes it possible to e.g. compile:

with System;
procedure Btins1 is

   function Frame_Address (Level : Integer) return System.Address;
   pragma Import (Intrinsic, Frame_Address, "__builtin_frame_address");

   Ptr : System.Address;
   pragma Volatile (Ptr);
begin
   Ptr := Frame_Address (0);
end;

Tested on x86_64-pc-linux-gnu, committed on trunk

2012-07-16  Tristan Gingold  <gingold@adacore.com>
        
	* gcc-interface/decl.c (intrin_return_compatible_p): Map Address to     
	void *.
Duncan Sands - July 16, 2012, 1:16 p.m.
Hi Arnaud,

> The natural way to import a builtin that returns void * is to use
> System.Address in Ada, which is in fact an integral type.

how about doing this for formal arguments too and not just the return type?
This would improve optimization by LLVM of calls to standard library functions
since the optimizers bail out when they see an "int" parameter where normally
there would be a void* (or other pointer type).

Ciao, Duncan.

>
> Addressed by this patch, which makes it possible to e.g. compile:
>
> with System;
> procedure Btins1 is
>
>     function Frame_Address (Level : Integer) return System.Address;
>     pragma Import (Intrinsic, Frame_Address, "__builtin_frame_address");
>
>     Ptr : System.Address;
>     pragma Volatile (Ptr);
> begin
>     Ptr := Frame_Address (0);
> end;
>
> Tested on x86_64-pc-linux-gnu, committed on trunk
>
> 2012-07-16  Tristan Gingold  <gingold@adacore.com>
>
> 	* gcc-interface/decl.c (intrin_return_compatible_p): Map Address to
> 	void *.
>
Tristan Gingold - July 16, 2012, 1:17 p.m.
On Jul 16, 2012, at 3:16 PM, Duncan Sands wrote:

> Hi Arnaud,
> 
>> The natural way to import a builtin that returns void * is to use
>> System.Address in Ada, which is in fact an integral type.
> 
> how about doing this for formal arguments too and not just the return type?

Formal arguments were already handled.

Tristan.

> This would improve optimization by LLVM of calls to standard library functions
> since the optimizers bail out when they see an "int" parameter where normally
> there would be a void* (or other pointer type).
> 
> Ciao, Duncan.
> 
>> 
>> Addressed by this patch, which makes it possible to e.g. compile:
>> 
>> with System;
>> procedure Btins1 is
>> 
>>    function Frame_Address (Level : Integer) return System.Address;
>>    pragma Import (Intrinsic, Frame_Address, "__builtin_frame_address");
>> 
>>    Ptr : System.Address;
>>    pragma Volatile (Ptr);
>> begin
>>    Ptr := Frame_Address (0);
>> end;
>> 
>> Tested on x86_64-pc-linux-gnu, committed on trunk
>> 
>> 2012-07-16  Tristan Gingold  <gingold@adacore.com>
>> 
>> 	* gcc-interface/decl.c (intrin_return_compatible_p): Map Address to
>> 	void *.
>> 
> 
>
Duncan Sands - July 16, 2012, 1:24 p.m.
Hi Tristan,

On 16/07/12 15:17, Tristan Gingold wrote:
>
> On Jul 16, 2012, at 3:16 PM, Duncan Sands wrote:
>
>> Hi Arnaud,
>>
>>> The natural way to import a builtin that returns void * is to use
>>> System.Address in Ada, which is in fact an integral type.
>>
>> how about doing this for formal arguments too and not just the return type?
>
> Formal arguments were already handled.

indeed, for two years already.  Is there any reason not to do this for all
functions, rather than just limiting it to builtins?

Ciao, Duncan.

>
> Tristan.
>
>> This would improve optimization by LLVM of calls to standard library functions
>> since the optimizers bail out when they see an "int" parameter where normally
>> there would be a void* (or other pointer type).
>>
>> Ciao, Duncan.
>>
>>>
>>> Addressed by this patch, which makes it possible to e.g. compile:
>>>
>>> with System;
>>> procedure Btins1 is
>>>
>>>     function Frame_Address (Level : Integer) return System.Address;
>>>     pragma Import (Intrinsic, Frame_Address, "__builtin_frame_address");
>>>
>>>     Ptr : System.Address;
>>>     pragma Volatile (Ptr);
>>> begin
>>>     Ptr := Frame_Address (0);
>>> end;
>>>
>>> Tested on x86_64-pc-linux-gnu, committed on trunk
>>>
>>> 2012-07-16  Tristan Gingold  <gingold@adacore.com>
>>>
>>> 	* gcc-interface/decl.c (intrin_return_compatible_p): Map Address to
>>> 	void *.
>>>
>>
>>
>
Tristan Gingold - July 16, 2012, 1:52 p.m.
On Jul 16, 2012, at 3:24 PM, Duncan Sands wrote:

> Hi Tristan,
> 
> On 16/07/12 15:17, Tristan Gingold wrote:
>> 
>> On Jul 16, 2012, at 3:16 PM, Duncan Sands wrote:
>> 
>>> Hi Arnaud,
>>> 
>>>> The natural way to import a builtin that returns void * is to use
>>>> System.Address in Ada, which is in fact an integral type.
>>> 
>>> how about doing this for formal arguments too and not just the return type?
>> 
>> Formal arguments were already handled.
> 
> indeed, for two years already.  Is there any reason not to do this for all
> functions, rather than just limiting it to builtins?

I don't understand what do you mean.  We need to do this implicit conversion for builtins because they are known by the compiler.  Which other functions (that aren't builtins) are you referring to ?

Tristan.
Duncan Sands - July 16, 2012, 1:58 p.m.
Hi Tristan,

>> indeed, for two years already.  Is there any reason not to do this for all
>> functions, rather than just limiting it to builtins?
>
> I don't understand what do you mean.  We need to do this implicit conversion for builtins because they are known by the compiler.  Which other functions (that aren't builtins) are you referring to ?

all of them!  First off, the LLVM optimizers do a better job if an argument of a
user defined function that is really a pointer is declared as such, rather than
declared as an integer then cast to a pointer before being used.  I don't know
if the GCC optimizers are sensitive to this too.  Also, the LLVM optimizers
recognize some standard library functions that the gcc optimizers do not, but
fail to recognize them when called from Ada because they have the wrong
prototype: an integer rather than a pointer argument.  Finally I would argue
that as System.Address is really a pointer, playing pretty much exactly the
same role as void* in C, it is more philosophically correct to express it as a
void*.  That said, it should probably just be declared as a pointer in the
System package rather than doing all this mucking around in the gcc interface.

Ciao, Duncan.
Tristan Gingold - July 16, 2012, 2:31 p.m.
On Jul 16, 2012, at 3:58 PM, Duncan Sands wrote:

> Hi Tristan,
> 
>>> indeed, for two years already.  Is there any reason not to do this for all
>>> functions, rather than just limiting it to builtins?
>> 
>> I don't understand what do you mean.  We need to do this implicit conversion for builtins because they are known by the compiler.  Which other functions (that aren't builtins) are you referring to ?
> 
> all of them!  First off, the LLVM optimizers do a better job if an argument of a
> user defined function that is really a pointer is declared as such, rather than
> declared as an integer then cast to a pointer before being used.  I don't know
> if the GCC optimizers are sensitive to this too.  Also, the LLVM optimizers
> recognize some standard library functions that the gcc optimizers do not, but
> fail to recognize them when called from Ada because they have the wrong
> prototype: an integer rather than a pointer argument.  Finally I would argue
> that as System.Address is really a pointer, playing pretty much exactly the
> same role as void* in C, it is more philosophically correct to express it as a
> void*.  That said, it should probably just be declared as a pointer in the
> System package rather than doing all this mucking around in the gcc interface.

Ah, what you want is the use of 'void *' for System.Address.
We didn't choose that because the semantic of System.Address (which includes arithmetic on the whole address space) doesn't match the void * one.

But, you can try to implement this scheme by modifying the runtime.  I don't know if this is a small work or not.

Tristan.
Duncan Sands - July 16, 2012, 2:36 p.m.
Hi Tristan,

> Ah, what you want is the use of 'void *' for System.Address.
> We didn't choose that because the semantic of System.Address (which includes arithmetic on the whole address space) doesn't match the void * one.

void* arithmetic of this kind exists, it's a gcc extension to C :)

> But, you can try to implement this scheme by modifying the runtime.  I don't know if this is a small work or not.

It crashes the front-end, so it's not trivial.

Ciao, Duncan.
Tristan Gingold - July 16, 2012, 2:42 p.m.
On Jul 16, 2012, at 4:36 PM, Duncan Sands wrote:

> Hi Tristan,
> 
>> Ah, what you want is the use of 'void *' for System.Address.
>> We didn't choose that because the semantic of System.Address (which includes arithmetic on the whole address space) doesn't match the void * one.
> 
> void* arithmetic of this kind exists, it's a gcc extension to C :)

The issue is not void * vs char *, but the fact that the C standard has restriction on pointer arithmetic.

>> But, you can try to implement this scheme by modifying the runtime.  I don't know if this is a small work or not.
> 
> It crashes the front-end, so it's not trivial.

:-)
Duncan Sands - July 16, 2012, 2:52 p.m.
Hi Tristan,

>>> Ah, what you want is the use of 'void *' for System.Address.
>>> We didn't choose that because the semantic of System.Address (which includes arithmetic on the whole address space) doesn't match the void * one.
>>
>> void* arithmetic of this kind exists, it's a gcc extension to C :)
>
> The issue is not void * vs char *, but the fact that the C standard has restriction on pointer arithmetic.

I see, -fno-strict-overflow would be needed to get System.Address modulo
arithmetic semantics if it was always turned into void*, which would then
presumably pessimize other code.  However this isn't really relevant to
whether Address formal parameters should always be turned into void* or
not.

Ciao, Duncan.

>>> But, you can try to implement this scheme by modifying the runtime.  I don't know if this is a small work or not.
>>
>> It crashes the front-end, so it's not trivial.
>
> :-)
>
Duncan Sands - July 16, 2012, 3:16 p.m.
PS: That said, I have to admit that using void* for builtins does cover the
most important cases.
Tristan Gingold - July 16, 2012, 3:25 p.m.
On Jul 16, 2012, at 5:16 PM, Duncan Sands wrote:

> PS: That said, I have to admit that using void* for builtins does cover the
> most important cases.

Agreed.  But I still think that these are two very different issues:

* Doing implicit conversion to void * for builtins is just a convenient way for interfacing with builtins.

* Using void * for System.Address shouldn't have any immediate advantage for users, but would be a better match for the representation.

Tristan.
Eric Botcazou - July 16, 2012, 4:22 p.m.
> Agreed.  But I still think that these are two very different issues:
> 
> * Doing implicit conversion to void * for builtins is just a convenient way
> for interfacing with builtins.
> 
> * Using void * for System.Address shouldn't have any immediate advantage
> for users, but would be a better match for the representation.

In fact the latter would unbreak the m68k port (this is PR ada/48835).

Patch

Index: gcc-interface/decl.c
===================================================================
--- gcc-interface/decl.c	(revision 189524)
+++ gcc-interface/decl.c	(working copy)
@@ -8046,6 +8046,10 @@ 
       && !VOID_TYPE_P (btin_return_type))
     return true;
 
+  /* If return type is Address (integer type), map it to void *.  */
+  if (Is_Descendent_Of_Address (Etype (inb->gnat_entity)))
+    ada_return_type = ptr_void_type_node;
+
   /* Check return types compatibility otherwise.  Note that this
      handles void/void as well.  */
   if (intrin_types_incompatible_p (btin_return_type, ada_return_type))