diff options
Diffstat (limited to 'gcc/ada/exp_ch6.adb')
-rw-r--r-- | gcc/ada/exp_ch6.adb | 58 |
1 files changed, 45 insertions, 13 deletions
diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb index edb31846708..951d272f54a 100644 --- a/gcc/ada/exp_ch6.adb +++ b/gcc/ada/exp_ch6.adb @@ -529,12 +529,13 @@ package body Exp_Ch6 is --------------------------- procedure Add_Call_By_Copy_Code is - Expr : Node_Id; - Init : Node_Id; - Temp : Entity_Id; - Var : Entity_Id; - V_Typ : Entity_Id; - Crep : Boolean; + Expr : Node_Id; + Init : Node_Id; + Temp : Entity_Id; + Indic : Node_Id := New_Occurrence_Of (Etype (Formal), Loc); + Var : Entity_Id; + V_Typ : Entity_Id; + Crep : Boolean; begin Temp := Make_Defining_Identifier (Loc, New_Internal_Name ('T')); @@ -560,10 +561,14 @@ package body Exp_Ch6 is -- parameter where the formal is an unconstrained array (in the -- latter case, we have to pass in an object with bounds). + -- If this is an out parameter, the initial copy is wasteful, so as + -- an optimization for the one-dimensional case we extract the + -- bounds of the actual and build an uninitialized temporary of the + -- right size. + if Ekind (Formal) = E_In_Out_Parameter or else (Is_Array_Type (Etype (Formal)) - and then - not Is_Constrained (Etype (Formal))) + and then not Is_Constrained (Etype (Formal))) then if Nkind (Actual) = N_Type_Conversion then if Conversion_OK (Actual) then @@ -573,6 +578,33 @@ package body Exp_Ch6 is Init := Convert_To (Etype (Formal), New_Occurrence_Of (Var, Loc)); end if; + + elsif Ekind (Formal) = E_Out_Parameter + and then Number_Dimensions (Etype (Formal)) = 1 + and then not Has_Non_Null_Base_Init_Proc (Etype (Formal)) + then + -- Actual is a one-dimensional array or slice, and the type + -- requires no initialization. Create a temporary of the + -- right size, but do copy actual into it (optimization). + + Init := Empty; + Indic := + Make_Subtype_Indication (Loc, + Subtype_Mark => + New_Occurrence_Of (Etype (Formal), Loc), + Constraint => + Make_Index_Or_Discriminant_Constraint (Loc, + Constraints => New_List ( + Make_Range (Loc, + Low_Bound => + Make_Attribute_Reference (Loc, + Prefix => New_Occurrence_Of (Var, Loc), + Attribute_name => Name_First), + High_Bound => + Make_Attribute_Reference (Loc, + Prefix => New_Occurrence_Of (Var, Loc), + Attribute_Name => Name_Last))))); + else Init := New_Occurrence_Of (Var, Loc); end if; @@ -607,8 +639,7 @@ package body Exp_Ch6 is N_Node := Make_Object_Declaration (Loc, Defining_Identifier => Temp, - Object_Definition => - New_Occurrence_Of (Etype (Formal), Loc), + Object_Definition => Indic, Expression => Init); Set_Assignment_OK (N_Node); Insert_Action (N, N_Node); @@ -2527,9 +2558,12 @@ package body Exp_Ch6 is -- In this case, for optimization purposes, we do not need to -- continue the traversal once more than one use is encountered. + ---------------- + -- Count_Uses -- + ---------------- + function Count_Uses (N : Node_Id) return Traverse_Result is begin - -- The original node is an identifier if Nkind (N) = N_Identifier @@ -2565,10 +2599,8 @@ package body Exp_Ch6 is -- Start of processing for Formal_Is_Used_Once begin - Count_Formal_Uses (Orig_Bod); return Use_Counter = 1; - end Formal_Is_Used_Once; -- Start of processing for Expand_Inlined_Call |