[Ada] Inlining subprogram instances
Arnaud Charlet
charlet@adacore.com
Fri Aug 1 08:20:00 GMT 2008
The back-end can only inline calls if the unit containing the body to inline
is presented to it before any calls. If a generic subprogram carries an
inline pragma, we generate the instance of the body even when the instance is
not in the main unit, because an inlined call to it might be. This processing
now extends to the case where the pragma applies to the instance itself rather
than to the original generic.
The following must compile quietly:
gcc -c -gnatn -O2 -Winline set_readonly_test.adb
with System_Types;
procedure Set_Readonly_Test is
I1, I2 : constant System_Types.Integer_T := 1;
B2 : constant Boolean := System_Types.Compare (I1, I2);
B3 : constant Boolean := System_Types.Compare2 (I1, I2);
pragma Unreferenced (B2, B3);
begin
null;
end Set_Readonly_Test;
---
function Compare_G (Left,Right : Discrete_T) return Boolean is
begin
if Left = Right then
return True;
else
return False;
end if;
end;
---
generic
type Discrete_T is (<>);
function Compare_G (Left,Right : Discrete_T) return Boolean;
---
package body System_Types is
function Compare2 (Left, Right : Integer_T) return Boolean is
begin
if Left = Right then
return True;
else
return False;
end if;
end;
end;
---
with Compare_G;
package System_Types is
type Integer_T is range -2 ** 31 .. 2 ** 31 - 1;
for Integer_T'Size use 32;
function Compare is new Compare_G (Integer_T);
pragma Inline (Compare);
function Compare2 (Left, Right : Integer_T) return Boolean;
pragma Inline (Compare2);
end System_Types;
Tested on i686-pc-linux-gnu, committed on trunk
2008-08-01 Ed Schonberg <schonberg@adacore.com>
* sem_ch12.ads (Need_Subprogram_Instance_Body): new function, to create
a pending instantiation for the body of a subprogram that is to be
inlined.
* sem_ch12.adb:
(Analyze_Subprogram_Instantiation): use Need_Subprogram_Instance_Body.
* sem_prag.adb (Make_Inline): If the pragma applies to an instance,
create a pending instance for its body, so that calls to the subprogram
can be inlined by the back-end.
-------------- next part --------------
Index: sem_prag.adb
===================================================================
--- sem_prag.adb (revision 138473)
+++ sem_prag.adb (working copy)
@@ -53,6 +53,7 @@ with Sem_Aux; use Sem_Aux;
with Sem_Ch3; use Sem_Ch3;
with Sem_Ch6; use Sem_Ch6;
with Sem_Ch8; use Sem_Ch8;
+with Sem_Ch12; use Sem_Ch12;
with Sem_Ch13; use Sem_Ch13;
with Sem_Dist; use Sem_Dist;
with Sem_Elim; use Sem_Elim;
@@ -3752,6 +3753,22 @@ package body Sem_Prag is
and then Present (Corresponding_Body (Decl))
then
Set_Inline_Flags (Corresponding_Body (Decl));
+
+ elsif Is_Generic_Instance (Subp) then
+
+ -- Indicate that the body needs to be created for
+ -- inlining subsequent calls. The instantiation
+ -- node follows the declaration of the wrapper
+ -- package created for it.
+
+ if Scope (Subp) /= Standard_Standard
+ and then
+ Need_Subprogram_Instance_Body
+ (Next (Unit_Declaration_Node (Scope (Alias (Subp)))),
+ Subp)
+ then
+ null;
+ end if;
end if;
end if;
Index: sem_ch12.adb
===================================================================
--- sem_ch12.adb (revision 138451)
+++ sem_ch12.adb (working copy)
@@ -3753,6 +3753,38 @@ package body Sem_Ch12 is
Analyze_Subprogram_Instantiation (N, E_Procedure);
end Analyze_Procedure_Instantiation;
+ -----------------------------------
+ -- Need_Subprogram_Instance_Body --
+ -----------------------------------
+
+ function Need_Subprogram_Instance_Body
+ (N : Node_Id;
+ Subp : Entity_Id) return Boolean
+ is
+ begin
+ if (Is_In_Main_Unit (N)
+ or else Is_Inlined (Subp)
+ or else Is_Inlined (Alias (Subp)))
+ and then (Operating_Mode = Generate_Code
+ or else (Operating_Mode = Check_Semantics
+ and then ASIS_Mode))
+ and then (Expander_Active or else ASIS_Mode)
+ and then not ABE_Is_Certain (N)
+ and then not Is_Eliminated (Subp)
+ then
+ Pending_Instantiations.Append
+ ((Inst_Node => N,
+ Act_Decl => Unit_Declaration_Node (Subp),
+ Expander_Status => Expander_Active,
+ Current_Sem_Unit => Current_Sem_Unit,
+ Scope_Suppress => Scope_Suppress,
+ Local_Suppress_Stack_Top => Local_Suppress_Stack_Top));
+ return True;
+ else
+ return False;
+ end if;
+ end Need_Subprogram_Instance_Body;
+
--------------------------------------
-- Analyze_Subprogram_Instantiation --
--------------------------------------
@@ -4144,22 +4176,7 @@ package body Sem_Ch12 is
-- If the context requires a full instantiation, mark node for
-- subsequent construction of the body.
- if (Is_In_Main_Unit (N)
- or else Is_Inlined (Act_Decl_Id))
- and then (Operating_Mode = Generate_Code
- or else (Operating_Mode = Check_Semantics
- and then ASIS_Mode))
- and then (Expander_Active or else ASIS_Mode)
- and then not ABE_Is_Certain (N)
- and then not Is_Eliminated (Act_Decl_Id)
- then
- Pending_Instantiations.Append
- ((Inst_Node => N,
- Act_Decl => Act_Decl,
- Expander_Status => Expander_Active,
- Current_Sem_Unit => Current_Sem_Unit,
- Scope_Suppress => Scope_Suppress,
- Local_Suppress_Stack_Top => Local_Suppress_Stack_Top));
+ if Need_Subprogram_Instance_Body (N, Act_Decl_Id) then
Check_Forward_Instantiation (Gen_Decl);
@@ -8699,6 +8716,13 @@ package body Sem_Ch12 is
begin
Gen_Body_Id := Corresponding_Body (Gen_Decl);
+ -- Subprogram body may have been created already because of
+ -- an inline pragma.
+
+ if Present (Corresponding_Body (Act_Decl)) then
+ return;
+ end if;
+
Expander_Mode_Save_And_Set (Body_Info.Expander_Status);
-- Re-establish the state of information on which checks are suppressed.
Index: sem_ch12.ads
===================================================================
--- sem_ch12.ads (revision 138451)
+++ sem_ch12.ads (working copy)
@@ -106,6 +106,16 @@ package Sem_Ch12 is
-- function and procedure instances. The flag Body_Optional has the
-- same purpose as described for Instantiate_Package_Body.
+ function Need_Subprogram_Instance_Body
+ (N : Node_Id;
+ Subp : Entity_Id) return Boolean;
+
+ -- If a subprogram instance is inlined, indicate that the body of it
+ -- must be created, to be used in inlined calls by the back-end. The
+ -- subprogram may be inlined because the generic itself carries the
+ -- pragma, or because a pragma appears for the instance in the scope.
+ -- of the instance.
+
procedure Save_Global_References (N : Node_Id);
-- Traverse the original generic unit, and capture all references to
-- entities that are defined outside of the generic in the analyzed
More information about the Gcc-patches
mailing list