diff options
author | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-09-16 16:45:44 +0000 |
---|---|---|
committer | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-09-16 16:45:44 +0000 |
commit | 3cafcd208bc63954c0440da210594850c46af23f (patch) | |
tree | 43b7642e6ba0465e4a784b763d07ca8ebb802582 /gcc | |
parent | 81acd162118ee452e748ec3af1630742e79457bc (diff) | |
download | gcc-3cafcd208bc63954c0440da210594850c46af23f.tar.gz |
2009-09-16 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk rev 151762
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@151766 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
53 files changed, 1910 insertions, 375 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c8fb1e75ffd..8d6ae7df4d1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,116 @@ +2009-09-16 Richard Henderson <rth@redhat.com> + + PR target/41246 + * tree-cfg.c (verify_gimple_call): Validate that gimple_call_chain + is set only if DECL_NO_STATIC_CHAIN is unset. + * tree-nested.c (iter_nestinfo_start, iter_nestinfo_next): New. + (FOR_EACH_NEST_INFO): New. + (walk_all_functions): Use it. + (finalize_nesting_tree): Likewise. + (unnest_nesting_tree): Likewise. + (free_nesting_tree): Use iter_nestinfo_start, iter_nestinfo_next. + (get_chain_decl, get_chain_field): Reset DECL_NO_STATIC_CHAIN. + (convert_gimple_call): Early out if gimple_call_chain already set. + (convert_all_function_calls): Iterate until no new functions + require a static chain. + (finalize_nesting_tree_1): Assert DECL_NO_STATIC_CHAIN is unset + when building a trampoline. Use dump_function_to_file instead + of dump_function. + (lower_nested_functions): Open dump_file. Validate that decls + that have DECL_NO_STATIC_CHAIN from the front end don't have that + bit reset by this pass. + +2009-09-16 Michael Matz <matz@suse.de> + + PR fortran/41212 + * tree.h (struct tree_decl_common): Add decl_restricted_flag, + shorten decl_common_unused. + (DECL_RESTRICTED_P): New accessor. + * tree-ssa-alias.c (ptr_deref_may_alias_decl_p): Use it + to disambiguate marked decls and restrict pointers. + +2009-09-16 Richard Henderson <rth@redhat.com> + + PR middle-end/41360 + * cfgbuild.c (find_bb_boundaries): Re-instate 2009-09-02 barrier fix. + +2009-09-16 Jakub Jelinek <jakub@redhat.com> + + * integrate.c (set_block_abstract_flags): Call + set_decl_abstract_flags also on BLOCK_NONLOCALIZED_VARs. + +2009-09-16 Richard Guenther <rguenther@suse.de> + + PR middle-end/34011 + * tree-flow-inline.h (may_be_aliased): Compute readonly variables + as non-aliased. + +2009-09-16 DJ Delorie <dj@redhat.com> + Kaz Kojima <kkojima@gcc.gnu.org> + + * config/sh/sh.c (output_stack_adjust): Add new argument frame_p. + (sh_expand_prologue): Update calls to output_stack_adjust. + (sh_expand_epilogue): Likewise. + +2009-09-15 Adam Nemet <anemet@caviumnetworks.com> + + PR bootstrap/41349 + * reorg.c (redundant_insn): Don't count notes or DEBUG_INSNs when + trying to limit the extent of searches in the insn stream. + +2009-09-15 Nathan Froyd <froydnj@codesourcery.com> + Jakub Jelinek <jakub@redhat.com> + + PR target/41175 + PR target/40677 + * config/rs6000/rs6000.c (no_global_regs_above): Fix precedence + problem. + (SAVRES_NOINLINE_GPRS_SAVES_LR, SAVRES_NOINLINE_FPRS_SAVES_LR, + SAVRES_NOINLINE_FPRS_DOESNT_RESTORE_LR): New strategy bits. + (rs6000_savres_strategy): Always save FP registers inline if the + target doesn't support hardware double-precision. Set the above + bits in return value when needed. + (rs6000_savres_routine_sym): Fix computation for cache selector. + Mark the generated symbol as a function. Rename exitp argument to + lr. Move code for determining the name of the symbol... + (rs6000_savres_routine_name): ...here. New function. Add cases for + getting the names right on AIX and 64-bit Linux. + (savres_routine_name): New variable. + (rs6000_make_savres_rtx): Rename exitp argument to lr. Don't assert + lr isn't set when savep. Use r12 resp. r1 instead of r11 depending + on what the target routine uses as a base register. If savep && lr + describe saving of r0 into memory slot. + (rs6000_emit_prologue): Correct use of call_used_regs. Fix out of + line calls for AIX ABI. + (rs6000_output_function_prologue): Use rs6000_savres_routine_name to + determine FP save/restore functions. + (rs6000_emit_stack_reset): Handle savres if sp_offset != 0 and + frame_reg_rtx != sp_reg_rtx. Use gen_add3_insn instead of + gen_addsi3. + (rs6000_emit_epilogue): Adjust computation of restore_lr. + Duplicate restoration of LR and execute the appropriate one + depending on whether GPRs are being restored inline. Set r11 from + offsetted frame_reg_rtx instead of sp_reg_rtx; if frame_reg_rtx is + r11, adjust sp_offset. Use gen_add3_insn instead of gen_addsi3. + Fix out of line calls for AIX ABI. + * config/rs6000/rs6000.md (*return_and_restore_fpregs_aix_<mode>): + New insn. + * config/rs6000/spe.md (*save_gpregs_spe): Use explicit match for + register 11. + (*restore_gpregs_spe): Likewise. + (*return_and_restore_gpregs_spe): Likewise. + * config/rs6000/linux64.h (SAVE_FP_SUFFIX, RESTORE_FP_SUFFIX): + Define to empty string unconditionally. + * config/rs6000/sysv4.h (SAVE_FP_SUFFIX, RESTORE_FP_SUFFIX): + Define to empty string unconditionally. + (GP_SAVE_INLINE, FP_SAVE_INLINE): Handle TARGET_64BIT the same as + !TARGET_64BIT. + +2009-09-15 Jan Hubicka <jh@suse.cz> + + * doc/invoke.texi (inline-insns-auto): Drop from 60 to 50. + * params.def (inline-insns-auto): Likewise. + 2009-09-15 Martin Jambor <mjambor@suse.cz> * ipa-inline.c (estimate_function_body_sizes): Dump info about diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index c9d9a703efe..f0ee07fcea2 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20090915 +20090916 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index cb38dab12f0..dae5c00e6a3 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,109 @@ +2009-09-16 Eric Botcazou <ebotcazou@adacore.com> + + * gcc-interface/trans.c (Attribute_to_gnu) <Attr_Size>: Strip + conversions between original and packable version of types from + the expression. + +2009-09-16 Eric Botcazou <ebotcazou@adacore.com> + + * gcc-interface/decl.c (gnat_to_gnu_field): Add DEBUG_INFO_P parameter. + If a padding type was made for the field, declare it. + (components_to_record): Add DEBUG_INFO_P parameter. Adjust call + to gnat_to_gnu_field and call to self. + (gnat_to_gnu_entity) <E_Array_Type>: Do not redeclare padding types. + <E_Array_Subtype>: Likewise. + Adjust calls to gnat_to_gnu_field and components_to_record. + +2009-09-16 Robert Dewar <dewar@adacore.com> + + * prj-nmsc.adb: Minor reformatting + +2009-09-16 Ed Schonberg <schonberg@adacore.com> + + * exp_ch4.adb (Expand_N_Conditional_Expression): If the type of the + expression is a by-reference type (tagged or inherently limited) + introduce an access type to capture references to the values of each + branch of the conditional. + +2009-09-16 Emmanuel Briot <briot@adacore.com> + + * prj-proc.adb, prj-part.adb, prj-tree.adb, prj-tree.ads + (Project_Name_And_Node.Display_Name): new field + The display name of a project (as written in the .gpr file) is now + computed when the project file itself is parsed, not when it is + processed. + +2009-09-16 Thomas Quinot <quinot@adacore.com> + + * freeze.adb, exp_intr.adb (Expand_Intrinsic_Call): Leave calls to + intrinsics untouched (to be expanded later on by gigi) if an external + name has been specified. + (Freeze_Entity): Do not generate a default external name for + imported subprograms with convention Intrinsic (so that the above code + can identify the case where an external name has been explicitly + provided). + + * s-oscons-tmplt.c: Quote TARGET_OS early so that it is not erroneously + replaced by something else due to an existing #define clause. + +2009-09-16 Ed Schonberg <schonberg@adacore.com> + + * sinfo.ads, sinfo.adb (Is_Accessibility_Actual): New flag on + Parameter_Association node, created for the extra actual generated for + an access parameter of a function that dispatches on result, to prevent + double generation of such actuals when the call is rewritten is a + dispatching call. + * exp_ch6.adb (Expand_Call): Set Is_Accessibility_Actual when needed. + * exp_disp.adb (Expand_Dispatching_Call): Do not transfer extra actuals + that carry this flag when rewriting the original call as a dispatching + call, after propagating the controlling tag. + +2009-09-16 Vincent Celier <celier@adacore.com> + + * prj-nmsc.adb (Add_Source): New parameter Source_Dir_Rank to be put + in the source data. + (Check_File): New parameter Source_Dir_Rank, to check if a duplicate + source is allowed. + (Find_Source_Dirs): New parameter Rank to be recorded with the source + directories. + (Search_Directories): Call Check_File with the rank of the directory + * prj.adb (Project_Empty): Add new component Source_Dir_Ranks + (Free): Free also Number_Lists + (Reset): Init also Number_Lists + * prj.ads (Number_List_Table): New dynamic table for lists of numbers + (Source_Data): New component Source_Dir_Rank. Remove component + Known_Order_Of_Source_Dirs, no longer needed. + (Project_Data): New component Source_Dir_Ranks + (Project_Tree_Data): New components Number_Lists + +2009-09-16 Vincent Celier <celier@adacore.com> + + * gprep.adb (Yes_No): New global constant + Unix_Line_Terminators: New global Boolean variable + (Process_One_File): Create the out file with a "Text_Translation=" form + that depends on the use of option -T. + (Scan_Command_Line): Add option -T + (Usage): Add line for option -T + +2009-09-16 Ed Schonberg <schonberg@adacore.com> + + * exp_disp.ads, exp_disp.adb (Is_Predefined_Internal_Operation): New + predicate that describes a proper subset of + Is_Predefined_Dispatching_Operation and excludes stream operations, + which can be overridden by the user. + * sem_ch6.adb (Create_Extra_Formals): use + Is_Predefined_Internal_Operation, so that stream operations get extra + formals. + * exp_ch6.adb (Prevent double generation of extra actuals in calls to + 'Input, which may be expanded twice, first as a function call and then + as a dispatching call. + +2009-09-16 Thomas Quinot <quinot@adacore.com> + + * s-oscons-tmplt.c (Target_OS, Target_Name): New constants. + * g-expect.adb (Set_Up_Child_Communications): Use + System.OS_Constants.Target_OS to determine whether running on Windows. + 2009-09-14 Richard Henderson <rth@redhat.com> * gcc-interface/trans.c (Pragma_to_gnu): Use build5 for ASM_EXPR. diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb index 949027dd0ae..49d23162eb0 100644 --- a/gcc/ada/exp_ch4.adb +++ b/gcc/ada/exp_ch4.adb @@ -4017,8 +4017,12 @@ package body Exp_Ch4 is Thenx : constant Node_Id := Next (Cond); Elsex : constant Node_Id := Next (Thenx); Typ : constant Entity_Id := Etype (N); + Cnn : Entity_Id; + Decl : Node_Id; New_If : Node_Id; + New_N : Node_Id; + P_Decl : Node_Id; begin -- If either then or else actions are present, then given: @@ -4038,13 +4042,12 @@ package body Exp_Ch4 is -- and replace the conditional expression by a reference to Cnn - -- ??? Note: this expansion is wrong for limited types, since it does - -- a copy of a limited value. Similarly it's wrong for unconstrained or - -- class-wide types since in neither case can we have an uninitialized - -- object declaration The proper fix would be to do the following - -- expansion: + -- If the type is limited or unconstrained, the above expansion is + -- not legal, because it involves either an uninitialized object + -- or an illegal assignment. Instead, we generate: - -- Cnn : access typ; + -- type Ptr is access all Typ; + -- Cnn : Ptr; -- if cond then -- <<then actions>> -- Cnn := then-expr'Unrestricted_Access; @@ -4053,11 +4056,29 @@ package body Exp_Ch4 is -- Cnn := else-expr'Unrestricted_Access; -- end if; - -- and replace the conditional expresion by a reference to Cnn.all ??? + -- and replace the conditional expresion by a reference to Cnn.all. - if Present (Then_Actions (N)) or else Present (Else_Actions (N)) then + if Is_By_Reference_Type (Typ) then Cnn := Make_Temporary (Loc, 'C', N); + P_Decl := + Make_Full_Type_Declaration (Loc, + Defining_Identifier => + Make_Defining_Identifier (Loc, New_Internal_Name ('A')), + Type_Definition => + Make_Access_To_Object_Definition (Loc, + All_Present => True, + Subtype_Indication => + New_Reference_To (Typ, Loc))); + + Insert_Action (N, P_Decl); + + Decl := + Make_Object_Declaration (Loc, + Defining_Identifier => Cnn, + Object_Definition => + New_Occurrence_Of (Defining_Identifier (P_Decl), Loc)); + New_If := Make_Implicit_If_Statement (N, Condition => Relocate_Node (Cond), @@ -4065,47 +4086,86 @@ package body Exp_Ch4 is Then_Statements => New_List ( Make_Assignment_Statement (Sloc (Thenx), Name => New_Occurrence_Of (Cnn, Sloc (Thenx)), - Expression => Relocate_Node (Thenx))), + Expression => + Make_Attribute_Reference (Loc, + Attribute_Name => Name_Unrestricted_Access, + Prefix => Relocate_Node (Thenx)))), Else_Statements => New_List ( Make_Assignment_Statement (Sloc (Elsex), Name => New_Occurrence_Of (Cnn, Sloc (Elsex)), - Expression => Relocate_Node (Elsex)))); + Expression => + Make_Attribute_Reference (Loc, + Attribute_Name => Name_Unrestricted_Access, + Prefix => Relocate_Node (Elsex))))); - -- Move the SLOC of the parent If statement to the newly created one - -- and change it to the SLOC of the expression which, after - -- expansion, will correspond to what is being evaluated. + New_N := + Make_Explicit_Dereference (Loc, + Prefix => New_Occurrence_Of (Cnn, Loc)); - if Present (Parent (N)) - and then Nkind (Parent (N)) = N_If_Statement - then - Set_Sloc (New_If, Sloc (Parent (N))); - Set_Sloc (Parent (N), Loc); - end if; + -- For other types, we only need to expand if there are other actions + -- associated with either branch. + + elsif Present (Then_Actions (N)) or else Present (Else_Actions (N)) then + Cnn := Make_Temporary (Loc, 'C', N); + + Decl := + Make_Object_Declaration (Loc, + Defining_Identifier => Cnn, + Object_Definition => New_Occurrence_Of (Typ, Loc)); + + New_If := + Make_Implicit_If_Statement (N, + Condition => Relocate_Node (Cond), + + Then_Statements => New_List ( + Make_Assignment_Statement (Sloc (Thenx), + Name => New_Occurrence_Of (Cnn, Sloc (Thenx)), + Expression => Relocate_Node (Thenx))), + + Else_Statements => New_List ( + Make_Assignment_Statement (Sloc (Elsex), + Name => New_Occurrence_Of (Cnn, Sloc (Elsex)), + Expression => Relocate_Node (Elsex)))); Set_Assignment_OK (Name (First (Then_Statements (New_If)))); Set_Assignment_OK (Name (First (Else_Statements (New_If)))); - if Present (Then_Actions (N)) then - Insert_List_Before - (First (Then_Statements (New_If)), Then_Actions (N)); - end if; + New_N := New_Occurrence_Of (Cnn, Loc); - if Present (Else_Actions (N)) then - Insert_List_Before - (First (Else_Statements (New_If)), Else_Actions (N)); - end if; + else - Rewrite (N, New_Occurrence_Of (Cnn, Loc)); + -- No expansion needed, gigi handles it like a C conditional + -- expression. - Insert_Action (N, - Make_Object_Declaration (Loc, - Defining_Identifier => Cnn, - Object_Definition => New_Occurrence_Of (Typ, Loc))); + return; + end if; - Insert_Action (N, New_If); - Analyze_And_Resolve (N, Typ); + -- Move the SLOC of the parent If statement to the newly created one + -- and change it to the SLOC of the expression which, after + -- expansion, will correspond to what is being evaluated. + + if Present (Parent (N)) + and then Nkind (Parent (N)) = N_If_Statement + then + Set_Sloc (New_If, Sloc (Parent (N))); + Set_Sloc (Parent (N), Loc); end if; + + if Present (Then_Actions (N)) then + Insert_List_Before + (First (Then_Statements (New_If)), Then_Actions (N)); + end if; + + if Present (Else_Actions (N)) then + Insert_List_Before + (First (Else_Statements (New_If)), Else_Actions (N)); + end if; + + Insert_Action (N, Decl); + Insert_Action (N, New_If); + Rewrite (N, New_N); + Analyze_And_Resolve (N, Typ); end Expand_N_Conditional_Expression; ----------------------------------- diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb index 44944aecaf9..238aad61043 100644 --- a/gcc/ada/exp_ch6.adb +++ b/gcc/ada/exp_ch6.adb @@ -496,6 +496,7 @@ package body Exp_Ch6 is declare Activation_Chain_Actual : Node_Id; Activation_Chain_Formal : Node_Id; + begin -- Locate implicit activation chain parameter in the called function @@ -1807,6 +1808,10 @@ package body Exp_Ch6 is Make_Identifier (Loc, Chars (EF)))); Analyze_And_Resolve (Expr, Etype (EF)); + + if Nkind (N) = N_Function_Call then + Set_Is_Accessibility_Actual (Parent (Expr)); + end if; end Add_Extra_Actual; --------------------------- @@ -2287,9 +2292,10 @@ package body Exp_Ch6 is when Attribute_Access => Add_Extra_Actual (Make_Integer_Literal (Loc, - Intval => - Object_Access_Level (Prefix (Prev_Orig))), - Extra_Accessibility (Formal)); + Intval => + Object_Access_Level + (Prefix (Prev_Orig))), + Extra_Accessibility (Formal)); -- Treat the unchecked attributes as library-level @@ -2328,7 +2334,6 @@ package body Exp_Ch6 is (Make_Integer_Literal (Loc, Intval => Type_Access_Level (Etype (Prev))), Extra_Accessibility (Formal)); - end case; end if; end if; diff --git a/gcc/ada/exp_disp.adb b/gcc/ada/exp_disp.adb index f34b1e9af33..34aacef8c25 100644 --- a/gcc/ada/exp_disp.adb +++ b/gcc/ada/exp_disp.adb @@ -692,7 +692,9 @@ package body Exp_Disp is Append_To (New_Params, Duplicate_Subexpr_Move_Checks (Param)); - else + elsif Nkind (Parent (Param)) /= N_Parameter_Association + or else not Is_Accessibility_Actual (Parent (Param)) + then Append_To (New_Params, Relocate_Node (Param)); end if; @@ -1740,6 +1742,48 @@ package body Exp_Disp is return False; end Is_Predefined_Dispatching_Operation; + --------------------------------------- + -- Is_Predefined_Internal_Operation -- + --------------------------------------- + + function Is_Predefined_Internal_Operation + (E : Entity_Id) return Boolean + is + TSS_Name : TSS_Name_Type; + + begin + if not Is_Dispatching_Operation (E) then + return False; + end if; + + Get_Name_String (Chars (E)); + + -- Most predefined primitives have internally generated names. Equality + -- must be treated differently; the predefined operation is recognized + -- as a homogeneous binary operator that returns Boolean. + + if Name_Len > TSS_Name_Type'Last then + TSS_Name := + TSS_Name_Type + (Name_Buffer (Name_Len - TSS_Name'Length + 1 .. Name_Len)); + + if Chars (E) = Name_uSize + or else Chars (E) = Name_uAlignment + or else + (Chars (E) = Name_Op_Eq + and then Etype (First_Entity (E)) = Etype (Last_Entity (E))) + or else Chars (E) = Name_uAssign + or else TSS_Name = TSS_Deep_Adjust + or else TSS_Name = TSS_Deep_Finalize + or else Is_Predefined_Interface_Primitive (E) + then + return True; + end if; + end if; + + return False; + end Is_Predefined_Internal_Operation; + ------------------------------------- -- Is_Predefined_Dispatching_Alias -- ------------------------------------- diff --git a/gcc/ada/exp_disp.ads b/gcc/ada/exp_disp.ads index 18f751d978d..4aea2ca1e65 100644 --- a/gcc/ada/exp_disp.ads +++ b/gcc/ada/exp_disp.ads @@ -218,6 +218,11 @@ package Exp_Disp is function Is_Predefined_Dispatching_Operation (E : Entity_Id) return Boolean; -- Ada 2005 (AI-251): Determines if E is a predefined primitive operation + function Is_Predefined_Internal_Operation (E : Entity_Id) return Boolean; + -- Similar to the previous one, but excludes stream operations, because + -- these may be overridden, and need extra formals, like user-defined + -- operations. + function Is_Predefined_Interface_Primitive (E : Entity_Id) return Boolean; -- Ada 2005 (AI-345): Returns True if E is one of the predefined primitives -- required to implement interfaces. diff --git a/gcc/ada/exp_intr.adb b/gcc/ada/exp_intr.adb index b35c35ea9df..da1314c3aa7 100644 --- a/gcc/ada/exp_intr.adb +++ b/gcc/ada/exp_intr.adb @@ -394,6 +394,13 @@ package body Exp_Intr is Nam : Name_Id; begin + -- If an external name is specified for the intrinsic, it is handled + -- by the back-end: leave the call node unchanged for now. + + if Present (Interface_Name (E)) then + return; + end if; + -- If the intrinsic subprogram is generic, gets its original name if Present (Parent (E)) diff --git a/gcc/ada/freeze.adb b/gcc/ada/freeze.adb index 14ba41c9956..56389bb0535 100644 --- a/gcc/ada/freeze.adb +++ b/gcc/ada/freeze.adb @@ -2443,11 +2443,16 @@ package body Freeze is -- If entity is exported or imported and does not have an external -- name, now is the time to provide the appropriate default name. -- Skip this if the entity is stubbed, since we don't need a name - -- for any stubbed routine. + -- for any stubbed routine. For the case on intrinsics, if no + -- external name is specified, then calls will be handled in + -- Exp_Intr.Expand_Intrinsic_Call, and no name is needed; if + -- an external name is provided, then Expand_Intrinsic_Call leaves + -- calls in place for expansion by GIGI. if (Is_Imported (E) or else Is_Exported (E)) and then No (Interface_Name (E)) and then Convention (E) /= Convention_Stubbed + and then Convention (E) /= Convention_Intrinsic then Set_Encoded_Interface_Name (E, Get_Default_External_Name (E)); @@ -3335,9 +3340,7 @@ package body Freeze is -- For bit-packed arrays, check the size - if Is_Bit_Packed_Array (E) - and then Known_RM_Size (E) - then + if Is_Bit_Packed_Array (E) and then Known_RM_Size (E) then declare SizC : constant Node_Id := Size_Clause (E); diff --git a/gcc/ada/g-expect.adb b/gcc/ada/g-expect.adb index 02bc6cf8a79..a67696a649d 100644 --- a/gcc/ada/g-expect.adb +++ b/gcc/ada/g-expect.adb @@ -31,8 +31,9 @@ -- -- ------------------------------------------------------------------------------ -with System; use System; -with Ada.Calendar; use Ada.Calendar; +with System; use System; +with System.OS_Constants; use System.OS_Constants; +with Ada.Calendar; use Ada.Calendar; with GNAT.IO; with GNAT.OS_Lib; use GNAT.OS_Lib; @@ -1195,15 +1196,14 @@ package body GNAT.Expect is pragma Warnings (Off, Pipe2); pragma Warnings (Off, Pipe3); - On_Windows : constant Boolean := Directory_Separator = '\'; - -- This is ugly, we need a better way of doing this test ??? - Input : File_Descriptor; Output : File_Descriptor; Error : File_Descriptor; + No_Fork_On_Target : constant Boolean := Target_OS = Windows; + begin - if On_Windows then + if No_Fork_On_Target then -- Since Windows does not have a separate fork/exec, we need to -- perform the following actions: diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index ed393388c5c..58c07a777d7 100644 --- a/gcc/ada/gcc-interface/decl.c +++ b/gcc/ada/gcc-interface/decl.c @@ -131,7 +131,7 @@ static tree elaborate_expression (Node_Id, Entity_Id, tree, bool, bool, bool); static bool is_variable_size (tree); static tree elaborate_expression_1 (tree, Entity_Id, tree, bool, bool); static tree make_packable_type (tree, bool); -static tree gnat_to_gnu_field (Entity_Id, tree, int, bool); +static tree gnat_to_gnu_field (Entity_Id, tree, int, bool, bool); static tree gnat_to_gnu_param (Entity_Id, Mechanism_Type, Entity_Id, bool, bool *); static bool same_discriminant_p (Entity_Id, Entity_Id); @@ -139,7 +139,7 @@ static bool array_type_has_nonaliased_component (Entity_Id, tree); static bool compile_time_known_address_p (Node_Id); static bool cannot_be_superflat_p (Node_Id); static void components_to_record (tree, Node_Id, tree, int, bool, tree *, - bool, bool, bool, bool); + bool, bool, bool, bool, bool); static Uint annotate_value (tree); static void annotate_rep (Entity_Id, tree); static tree compute_field_positions (tree, tree, tree, tree, unsigned int); @@ -1990,7 +1990,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) /* If a padding record was made, declare it now since it will never be declared otherwise. This is necessary to ensure that its subtrees are properly marked. */ - if (tem != orig_tem) + if (tem != orig_tem && !DECL_P (TYPE_NAME (tem))) create_type_decl (TYPE_NAME (tem), tem, NULL, true, debug_info_p, gnat_entity); } @@ -2364,7 +2364,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) if (gnu_comp_size && !Is_Bit_Packed_Array (gnat_entity)) { - tree orig_gnu_type = gnu_type; + tree orig_type = gnu_type; unsigned int max_align; /* If an alignment is specified, use it as a cap on the @@ -2381,9 +2381,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) gnu_type = make_type_from_size (gnu_type, gnu_comp_size, false); if (max_align > 0 && TYPE_ALIGN (gnu_type) > max_align) - gnu_type = orig_gnu_type; + gnu_type = orig_type; else - orig_gnu_type = gnu_type; + orig_type = gnu_type; gnu_type = maybe_pad_type (gnu_type, gnu_comp_size, 0, gnat_entity, "C_PAD", false, @@ -2392,7 +2392,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) /* If a padding record was made, declare it now since it will never be declared otherwise. This is necessary to ensure that its subtrees are properly marked. */ - if (gnu_type != orig_gnu_type) + if (gnu_type != orig_type && !DECL_P (TYPE_NAME (gnu_type))) create_type_decl (TYPE_NAME (gnu_type), gnu_type, NULL, true, debug_info_p, gnat_entity); } @@ -2952,7 +2952,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) continue; gnu_field - = gnat_to_gnu_field (gnat_field, gnu_type, packed, definition); + = gnat_to_gnu_field (gnat_field, gnu_type, packed, definition, + debug_info_p); /* Make an expression using a PLACEHOLDER_EXPR from the FIELD_DECL node just created and link that with the @@ -2973,7 +2974,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) /* Add the fields into the record type and finish it up. */ components_to_record (gnu_type, Component_List (record_definition), gnu_field_list, packed, definition, NULL, - false, all_rep, false, is_unchecked_union); + false, all_rep, false, is_unchecked_union, + debug_info_p); /* If it is a tagged record force the type to BLKmode to insure that these objects will always be put in memory. Likewise for limited @@ -6412,11 +6414,14 @@ adjust_packed (tree field_type, tree record_type, int packed) record has Component_Alignment of Storage_Unit, -2 if the enclosing record has a specified alignment. - DEFINITION is true if this field is for a record being defined. */ + DEFINITION is true if this field is for a record being defined. + + DEBUG_INFO_P is true if we need to write debug information for types + that we may create in the process. */ static tree gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed, - bool definition) + bool definition, bool debug_info_p) { tree gnu_field_id = get_entity_name (gnat_field); tree gnu_field_type = gnat_to_gnu_type (Etype (gnat_field)); @@ -6635,6 +6640,8 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed, /* If a size is specified, adjust the field's type to it. */ if (gnu_size) { + tree orig_field_type; + /* If the field's type is justified modular, we would need to remove the wrapper to (better) meet the layout requirements. However we can do so only if the field is not aliased to preserve the unique @@ -6650,8 +6657,18 @@ gnat_to_gnu_field (Entity_Id gnat_field, tree gnu_record_type, int packed, gnu_field_type = make_type_from_size (gnu_field_type, gnu_size, Has_Biased_Representation (gnat_field)); + + orig_field_type = gnu_field_type; gnu_field_type = maybe_pad_type (gnu_field_type, gnu_size, 0, gnat_field, "PAD", false, definition, true); + + /* If a padding record was made, declare it now since it will never be + declared otherwise. This is necessary to ensure that its subtrees + are properly marked. */ + if (gnu_field_type != orig_field_type + && !DECL_P (TYPE_NAME (gnu_field_type))) + create_type_decl (TYPE_NAME (gnu_field_type), gnu_field_type, NULL, + true, debug_info_p, gnat_field); } /* Otherwise (or if there was an error), don't specify a position. */ @@ -6746,13 +6763,17 @@ compare_field_bitpos (const PTR rt1, const PTR rt2) modified afterwards so it will not be finalized here. UNCHECKED_UNION, if true, means that we are building a type for a record - with a Pragma Unchecked_Union. */ + with a Pragma Unchecked_Union. + + DEBUG_INFO_P, if true, means that we need to write debug information for + types that we may create in the process. */ static void components_to_record (tree gnu_record_type, Node_Id gnat_component_list, tree gnu_field_list, int packed, bool definition, tree *p_gnu_rep_list, bool cancel_alignment, - bool all_rep, bool do_not_finalize, bool unchecked_union) + bool all_rep, bool do_not_finalize, + bool unchecked_union, bool debug_info_p) { bool all_rep_and_size = all_rep && TYPE_SIZE (gnu_record_type); bool layout_with_rep = false; @@ -6780,8 +6801,8 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list, } else { - gnu_field = gnat_to_gnu_field (gnat_field, gnu_record_type, - packed, definition); + gnu_field = gnat_to_gnu_field (gnat_field, gnu_record_type, packed, + definition, debug_info_p); /* If this is the _Tag field, put it before any other fields. */ if (gnat_name == Name_uTag) @@ -6887,7 +6908,7 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list, components_to_record (gnu_variant_type, Component_List (variant), NULL_TREE, packed, definition, &gnu_our_rep_list, !all_rep_and_size, all_rep, - true, unchecked_union); + true, unchecked_union, debug_info_p); gnu_qual = choices_to_gnu (gnu_discr, Discrete_Choices (variant)); diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c index 5bce21a7063..a90a7a060bc 100644 --- a/gcc/ada/gcc-interface/trans.c +++ b/gcc/ada/gcc-interface/trans.c @@ -1279,9 +1279,16 @@ Attribute_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, int attribute) case Attr_Max_Size_In_Storage_Elements: gnu_expr = gnu_prefix; - /* Remove NOPs from GNU_EXPR and conversions from GNU_PREFIX. - We only use GNU_EXPR to see if a COMPONENT_REF was involved. */ - while (TREE_CODE (gnu_expr) == NOP_EXPR) + /* Remove NOPs and conversions between original and packable version + from GNU_EXPR, and conversions from GNU_PREFIX. We use GNU_EXPR + to see if a COMPONENT_REF was involved. */ + while (TREE_CODE (gnu_expr) == NOP_EXPR + || (TREE_CODE (gnu_expr) == VIEW_CONVERT_EXPR + && TREE_CODE (TREE_TYPE (gnu_expr)) == RECORD_TYPE + && TREE_CODE (TREE_TYPE (TREE_OPERAND (gnu_expr, 0))) + == RECORD_TYPE + && TYPE_NAME (TREE_TYPE (gnu_expr)) + == TYPE_NAME (TREE_TYPE (TREE_OPERAND (gnu_expr, 0))))) gnu_expr = TREE_OPERAND (gnu_expr, 0); gnu_prefix = remove_conversions (gnu_prefix, true); diff --git a/gcc/ada/gprep.adb b/gcc/ada/gprep.adb index ec56bcc171f..b5e6b063cac 100644 --- a/gcc/ada/gprep.adb +++ b/gcc/ada/gprep.adb @@ -6,7 +6,7 @@ -- -- -- B o d y -- -- -- --- Copyright (C) 2002-2008, Free Software Foundation, Inc. -- +-- Copyright (C) 2002-2009, Free Software Foundation, Inc. -- -- -- -- GNAT is free software; you can redistribute it and/or modify it under -- -- terms of the GNU General Public License as published by the Free Soft- -- @@ -55,6 +55,14 @@ package body GPrep is -- Argument Line Data -- ------------------------ + Unix_Line_Terminators : Boolean := False; + -- Set to True with option -T + + type String_Array is array (Boolean) of String_Access; + Yes_No : constant String_Array := + (False => new String'("YES"), + True => new String'("NO")); + Infile_Name : Name_Id := No_Name; Outfile_Name : Name_Id := No_Name; Deffile_Name : Name_Id := No_Name; @@ -484,7 +492,12 @@ package body GPrep is -- Create the output file (fails if this does not work) begin - Create (Text_Outfile, Out_File, Get_Name_String (Outfile_Name)); + Create + (File => Text_Outfile, + Mode => Out_File, + Name => Get_Name_String (Outfile_Name), + Form => "Text_Translation=" & + Yes_No (Unix_Line_Terminators).all); exception when others => @@ -722,7 +735,7 @@ package body GPrep is loop begin - Switch := GNAT.Command_Line.Getopt ("D: b c C r s u v"); + Switch := GNAT.Command_Line.Getopt ("D: b c C r s T u v"); case Switch is @@ -748,6 +761,9 @@ package body GPrep is when 's' => Opt.List_Preprocessing_Symbols := True; + when 'T' => + Unix_Line_Terminators := True; + when 'u' => Opt.Undefined_Symbols_Are_False := True; @@ -813,6 +829,7 @@ package body GPrep is Write_Line (" -D Associate symbol with value"); Write_Line (" -r Generate Source_Reference pragma"); Write_Line (" -s Print a sorted list of symbol names and values"); + Write_Line (" -T Use LF as line terminators"); Write_Line (" -u Treat undefined symbols as FALSE"); Write_Line (" -v Verbose mode"); Write_Eol; diff --git a/gcc/ada/prj-nmsc.adb b/gcc/ada/prj-nmsc.adb index 1a0371855c5..cec5e6b0a59 100644 --- a/gcc/ada/prj-nmsc.adb +++ b/gcc/ada/prj-nmsc.adb @@ -192,6 +192,7 @@ package body Prj.Nmsc is (Id : out Source_Id; Data : in out Tree_Processing_Data; Project : Project_Id; + Source_Dir_Rank : Natural; Lang_Id : Language_Ptr; Kind : Source_Kind; File_Name : File_Name_Type; @@ -295,6 +296,7 @@ package body Prj.Nmsc is procedure Check_File (Project : in out Project_Processing_Data; Data : in out Tree_Processing_Data; + Source_Dir_Rank : Natural; Path : Path_Name_Type; File_Name : File_Name_Type; Display_File_Name : File_Name_Type; @@ -539,6 +541,7 @@ package body Prj.Nmsc is (Id : out Source_Id; Data : in out Tree_Processing_Data; Project : Project_Id; + Source_Dir_Rank : Natural; Lang_Id : Language_Ptr; Kind : Source_Kind; File_Name : File_Name_Type; @@ -598,7 +601,7 @@ package body Prj.Nmsc is if Data.Flags.Allow_Duplicate_Basenames then Add_Src := True; - elsif Project.Known_Order_Of_Source_Dirs then + elsif Source_Dir_Rank /= Source.Source_Dir_Rank then Add_Src := False; else @@ -610,7 +613,7 @@ package body Prj.Nmsc is end if; else - if Project.Known_Order_Of_Source_Dirs then + if Source_Dir_Rank /= Source.Source_Dir_Rank then Add_Src := False; -- We might be seeing the same file through a different path @@ -722,6 +725,7 @@ package body Prj.Nmsc is end if; Id.Project := Project; + Id.Source_Dir_Rank := Source_Dir_Rank; Id.Language := Lang_Id; Id.Kind := Kind; Id.Alternate_Languages := Alternate_Languages; @@ -2807,6 +2811,7 @@ package body Prj.Nmsc is (Id => Source, Data => Data, Project => Project, + Source_Dir_Rank => 0, Lang_Id => Lang_Id, Kind => Kind, File_Name => File_Name, @@ -2916,16 +2921,17 @@ package body Prj.Nmsc is if Unit /= No_Name then Add_Source - (Id => Source, - Data => Data, - Project => Project, - Lang_Id => Lang_Id, - Kind => Kind, - File_Name => File_Name, - Display_File => File_Name_Type (Element.Value.Value), - Unit => Unit, - Index => Index, - Location => Element.Value.Location, + (Id => Source, + Data => Data, + Project => Project, + Source_Dir_Rank => 0, + Lang_Id => Lang_Id, + Kind => Kind, + File_Name => File_Name, + Display_File => File_Name_Type (Element.Value.Value), + Unit => Unit, + Index => Index, + Location => Element.Value.Location, Naming_Exception => True); end if; @@ -4675,7 +4681,8 @@ package body Prj.Nmsc is (Name_Source_Files, Project.Decl.Attributes, Data.Tree); - Last_Source_Dir : String_List_Id := Nil_String; + Last_Source_Dir : String_List_Id := Nil_String; + Last_Src_Dir_Rank : Number_List_Index := No_Number_List; Languages : constant Variable_Value := Prj.Util.Value_Of @@ -4684,6 +4691,7 @@ package body Prj.Nmsc is procedure Find_Source_Dirs (From : File_Name_Type; Location : Source_Ptr; + Rank : Natural; Removed : Boolean := False); -- Find one or several source directories, and add (or remove, if -- Removed is True) them to list of source directories of the project. @@ -4695,6 +4703,7 @@ package body Prj.Nmsc is procedure Find_Source_Dirs (From : File_Name_Type; Location : Source_Ptr; + Rank : Natural; Removed : Boolean := False) is Directory : constant String := Get_Name_String (From); @@ -4714,6 +4723,8 @@ package body Prj.Nmsc is Last : Natural; List : String_List_Id; Prev : String_List_Id; + Rank_List : Number_List_Index; + Prev_Rank : Number_List_Index; Element : String_Element; Found : Boolean := False; @@ -4756,6 +4767,8 @@ package body Prj.Nmsc is List := Project.Source_Dirs; Prev := Nil_String; + Rank_List := Project.Source_Dir_Ranks; + Prev_Rank := No_Number_List; while List /= Nil_String loop Element := Data.Tree.String_Elements.Table (List); @@ -4766,6 +4779,8 @@ package body Prj.Nmsc is Prev := List; List := Element.Next; + Prev_Rank := Rank_List; + Rank_List := Data.Tree.Number_Lists.Table (Rank_List).Next; end loop; -- If directory is not already in list, put it there @@ -4785,11 +4800,15 @@ package body Prj.Nmsc is Next => Nil_String, Index => 0); + Number_List_Table.Increment_Last (Data.Tree.Number_Lists); + -- Case of first source directory if Last_Source_Dir = Nil_String then Project.Source_Dirs := String_Element_Table.Last (Data.Tree.String_Elements); + Project.Source_Dir_Ranks := + Number_List_Table.Last (Data.Tree.Number_Lists); -- Here we already have source directories @@ -4798,7 +4817,11 @@ package body Prj.Nmsc is Data.Tree.String_Elements.Table (Last_Source_Dir).Next := - String_Element_Table.Last (Data.Tree.String_Elements); + String_Element_Table.Last (Data.Tree.String_Elements); + Data.Tree.Number_Lists.Table + (Last_Src_Dir_Rank).Next := + Number_List_Table.Last (Data.Tree.Number_Lists); + end if; -- And register this source directory as the new last @@ -4806,14 +4829,22 @@ package body Prj.Nmsc is Last_Source_Dir := String_Element_Table.Last (Data.Tree.String_Elements); Data.Tree.String_Elements.Table (Last_Source_Dir) := Element; + Last_Src_Dir_Rank := + Number_List_Table.Last (Data.Tree.Number_Lists); + Data.Tree.Number_Lists.Table (Last_Src_Dir_Rank) := + (Number => Rank, Next => No_Number_List); elsif Removed and Found then if Prev = Nil_String then Project.Source_Dirs := Data.Tree.String_Elements.Table (List).Next; + Project.Source_Dir_Ranks := + Data.Tree.Number_Lists.Table (Rank_List).Next; else Data.Tree.String_Elements.Table (Prev).Next := Data.Tree.String_Elements.Table (List).Next; + Data.Tree.Number_Lists.Table (Prev_Rank).Next := + Data.Tree.Number_Lists.Table (Rank_List).Next; end if; end if; @@ -4872,6 +4903,8 @@ package body Prj.Nmsc is if Current_Verbosity = High and then not Removed then Write_Str ("Find_Source_Dirs ("""); Write_Str (Directory); + Write_Str (","); + Write_Str (Rank'Img); Write_Line (""")"); end if; @@ -4884,10 +4917,6 @@ package body Prj.Nmsc is or else Directory (Directory'Last - 2) = Directory_Separator) then - if not Removed then - Project.Known_Order_Of_Source_Dirs := False; - end if; - Name_Len := Directory'Length - 3; if Name_Len = 0 then @@ -4960,6 +4989,8 @@ package body Prj.Nmsc is Path_Name : Path_Information; List : String_List_Id; Prev : String_List_Id; + Rank_List : Number_List_Index; + Prev_Rank : Number_List_Index; Dir_Exists : Boolean; begin @@ -5011,70 +5042,104 @@ package body Prj.Nmsc is (Display_Path'First .. Last_Display_Path)); Display_Path_Id := Name_Find; + -- Check if the directory is already in the list + + Prev := Nil_String; + Prev_Rank := No_Number_List; + + -- Look for source dir in current list + + List := Project.Source_Dirs; + Rank_List := Project.Source_Dir_Ranks; + while List /= Nil_String loop + Element := Data.Tree.String_Elements.Table (List); + exit when Element.Value = Path_Id; + Prev := List; + List := Element.Next; + Prev_Rank := Rank_List; + Rank_List := + Data.Tree.Number_Lists.Table (Prev_Rank).Next; + end loop; + + -- The directory is in the list if List is not Nil_String + if not Removed then -- As it is an existing directory, we add it to the - -- list of directories. + -- list of directories, if not already in the list. - String_Element_Table.Increment_Last - (Data.Tree.String_Elements); - Element := - (Value => Path_Id, - Index => 0, - Display_Value => Display_Path_Id, - Location => No_Location, - Flag => False, - Next => Nil_String); + if List = Nil_String then + String_Element_Table.Increment_Last + (Data.Tree.String_Elements); + Element := + (Value => Path_Id, + Index => 0, + Display_Value => Display_Path_Id, + Location => No_Location, + Flag => False, + Next => Nil_String); + Number_List_Table.Increment_Last + (Data.Tree.Number_Lists); - if Last_Source_Dir = Nil_String then + if Last_Source_Dir = Nil_String then - -- This is the first source directory + -- This is the first source directory - Project.Source_Dirs := String_Element_Table.Last - (Data.Tree.String_Elements); + Project.Source_Dirs := + String_Element_Table.Last + (Data.Tree.String_Elements); + Project.Source_Dir_Ranks := + Number_List_Table.Last + (Data.Tree.Number_Lists); - else - -- We already have source directories, link the - -- previous last to the new one. + else + -- We already have source directories, link the + -- previous last to the new one. + + Data.Tree.String_Elements.Table + (Last_Source_Dir).Next := + String_Element_Table.Last + (Data.Tree.String_Elements); + Data.Tree.Number_Lists.Table + (Last_Src_Dir_Rank).Next := + Number_List_Table.Last + (Data.Tree.Number_Lists); - Data.Tree.String_Elements.Table - (Last_Source_Dir).Next := + end if; + + -- And register this source directory as the new + -- last. + + Last_Source_Dir := String_Element_Table.Last (Data.Tree.String_Elements); + Data.Tree.String_Elements.Table + (Last_Source_Dir) := Element; + Last_Src_Dir_Rank := + Number_List_Table.Last + (Data.Tree.Number_Lists); + Data.Tree.Number_Lists.Table + (Last_Src_Dir_Rank) := + (Number => Rank, Next => No_Number_List); end if; - -- And register this source directory as the new last - - Last_Source_Dir := String_Element_Table.Last - (Data.Tree.String_Elements); - Data.Tree.String_Elements.Table - (Last_Source_Dir) := Element; - else -- Remove source dir, if present - Prev := Nil_String; - - -- Look for source dir in current list - - List := Project.Source_Dirs; - while List /= Nil_String loop - Element := Data.Tree.String_Elements.Table (List); - exit when Element.Value = Path_Id; - Prev := List; - List := Element.Next; - end loop; - if List /= Nil_String then -- Source dir was found, remove it from the list if Prev = Nil_String then Project.Source_Dirs := Data.Tree.String_Elements.Table (List).Next; + Project.Source_Dir_Ranks := + Data.Tree.Number_Lists.Table (Rank_List).Next; else Data.Tree.String_Elements.Table (Prev).Next := Data.Tree.String_Elements.Table (List).Next; + Data.Tree.Number_Lists.Table (Prev_Rank).Next := + Data.Tree.Number_Lists.Table (Rank_List).Next; end if; end if; end if; @@ -5276,6 +5341,13 @@ package body Prj.Nmsc is Project.Source_Dirs := String_Element_Table.Last (Data.Tree.String_Elements); + Number_List_Table.Append + (Data.Tree.Number_Lists, + (Number => 1, Next => No_Number_List)); + + Project.Source_Dir_Ranks := + Number_List_Table.Last (Data.Tree.Number_Lists); + if Current_Verbosity = High then Write_Attr ("Default source directory", @@ -5296,15 +5368,17 @@ package body Prj.Nmsc is declare Source_Dir : String_List_Id; Element : String_Element; - + Rank : Natural; begin -- Process the source directories for each element of the list Source_Dir := Source_Dirs.Values; + Rank := 0; while Source_Dir /= Nil_String loop Element := Data.Tree.String_Elements.Table (Source_Dir); + Rank := Rank + 1; Find_Source_Dirs - (File_Name_Type (Element.Value), Element.Location); + (File_Name_Type (Element.Value), Element.Location, Rank); Source_Dir := Element.Next; end loop; end; @@ -5326,6 +5400,7 @@ package body Prj.Nmsc is Find_Source_Dirs (File_Name_Type (Element.Value), Element.Location, + 0, Removed => True); Source_Dir := Element.Next; end loop; @@ -6582,6 +6657,7 @@ package body Prj.Nmsc is procedure Check_File (Project : in out Project_Processing_Data; Data : in out Tree_Processing_Data; + Source_Dir_Rank : Natural; Path : Path_Name_Type; File_Name : File_Name_Type; Display_File_Name : File_Name_Type; @@ -6606,6 +6682,14 @@ package body Prj.Nmsc is Kind : Source_Kind := Spec; begin + if Current_Verbosity = High then + Write_Line ("Checking file:"); + Write_Str (" Path = "); + Write_Line (Get_Name_String (Path)); + Write_Str (" Rank ="); + Write_Line (Source_Dir_Rank'Img); + end if; + if Name_Loc = No_Name_Location then Check_Name := For_All_Sources; @@ -6615,7 +6699,7 @@ package body Prj.Nmsc is -- Check if it is OK to have the same file name in several -- source directories. - if not Project.Project.Known_Order_Of_Source_Dirs then + if Source_Dir_Rank = Name_Loc.Source.Source_Dir_Rank then Error_Msg_File_1 := File_Name; Error_Msg (Data.Flags, @@ -6689,6 +6773,7 @@ package body Prj.Nmsc is Add_Source (Id => Source, Project => Project.Project, + Source_Dir_Rank => Source_Dir_Rank, Lang_Id => Language, Kind => Kind, Data => Data, @@ -6698,6 +6783,15 @@ package body Prj.Nmsc is Unit => Unit, Locally_Removed => Locally_Removed, Path => (Canonical_Path, Path)); + + -- If it is a source specified in a list, update the entry in + -- the Source_Names table. + + if Name_Loc.Found and then Name_Loc.Source = No_Source then + Name_Loc.Source := Source; + Source_Names_Htable.Set + (Project.Source_Names, File_Name, Name_Loc); + end if; end if; end if; end Check_File; @@ -6713,6 +6807,8 @@ package body Prj.Nmsc is is Source_Dir : String_List_Id; Element : String_Element; + Src_Dir_Rank : Number_List_Index; + Num_Nod : Number_Node; Dir : Dir_Type; Name : String (1 .. 1_000); Last : Natural; @@ -6727,12 +6823,21 @@ package body Prj.Nmsc is -- Loop through subdirectories Source_Dir := Project.Project.Source_Dirs; + Src_Dir_Rank := Project.Project.Source_Dir_Ranks; while Source_Dir /= Nil_String loop begin + Num_Nod := Data.Tree.Number_Lists.Table (Src_Dir_Rank); Element := Data.Tree.String_Elements.Table (Source_Dir); + if Element.Value /= No_Name then Get_Name_String (Element.Display_Value); + if Current_Verbosity = High then + Write_Str ("Directory: "); + Write_Str (Name_Buffer (1 .. Name_Len)); + Write_Line (Num_Nod.Number'Img); + end if; + declare Source_Directory : constant String := Name_Buffer (1 .. Name_Len) & @@ -6819,7 +6924,7 @@ package body Prj.Nmsc is -- still need to add it to the list: if we -- don't, the file will not appear in the -- mapping file and will cause the compiler - -- to fail + -- to fail. To_Remove := True; end if; @@ -6827,6 +6932,7 @@ package body Prj.Nmsc is Check_File (Project => Project, + Source_Dir_Rank => Num_Nod.Number, Data => Data, Path => Path, File_Name => File_Name, @@ -6847,6 +6953,7 @@ package body Prj.Nmsc is end; Source_Dir := Element.Next; + Src_Dir_Rank := Num_Nod.Next; end loop; if Current_Verbosity = High then @@ -7176,7 +7283,13 @@ package body Prj.Nmsc is begin if Current_Verbosity = High then Write_Str ("Removing source "); - Write_Line (Get_Name_String (Id.File) & " at" & Id.Index'Img); + Write_Str (Get_Name_String (Id.File)); + + if Id.Index /= 0 then + Write_Str (" at" & Id.Index'Img); + end if; + + Write_Eol; end if; if Replaced_By /= No_Source then diff --git a/gcc/ada/prj-part.adb b/gcc/ada/prj-part.adb index 84e3f6dab7f..fc0438ba4f0 100644 --- a/gcc/ada/prj-part.adb +++ b/gcc/ada/prj-part.adb @@ -941,6 +941,7 @@ package body Prj.Part is Name_From_Path : constant Name_Id := Project_Name_From (Path_Name, Is_Config_File => Is_Config_File); Name_Of_Project : Name_Id := No_Name; + Display_Name_Of_Project : Name_Id := No_Name; Duplicated : Boolean := False; @@ -1298,9 +1299,6 @@ package body Prj.Part is -- To get expected name of the project file, replace dots by dashes - Name_Len := Buffer_Last; - Name_Buffer (1 .. Name_Len) := Buffer (1 .. Buffer_Last); - for Index in 1 .. Name_Len loop if Name_Buffer (Index) = '.' then Name_Buffer (Index) := '-'; @@ -1337,6 +1335,19 @@ package body Prj.Part is end if; end; + -- Read the original casing of the project name + + declare + Loc : Source_Ptr := Location_Of (Project, In_Tree); + begin + for J in 1 .. Name_Len loop + Name_Buffer (J) := Sinput.Source (Loc); + Loc := Loc + 1; + end loop; + + Display_Name_Of_Project := Name_Find; + end; + declare From_Ext : Extension_Origin := None; @@ -1700,6 +1711,7 @@ package body Prj.Part is (T => In_Tree.Projects_HT, K => Name_Of_Project, E => (Name => Name_Of_Project, + Display_Name => Display_Name_Of_Project, Node => Project, Canonical_Path => Canonical_Path_Name, Extended => Extended, diff --git a/gcc/ada/prj-proc.adb b/gcc/ada/prj-proc.adb index c8766229057..9893cf6129b 100644 --- a/gcc/ada/prj-proc.adb +++ b/gcc/ada/prj-proc.adb @@ -31,7 +31,6 @@ with Prj.Attr; use Prj.Attr; with Prj.Err; use Prj.Err; with Prj.Ext; use Prj.Ext; with Prj.Nmsc; use Prj.Nmsc; -with Sinput; use Sinput; with Snames; with GNAT.Case_Util; use GNAT.Case_Util; @@ -2425,13 +2424,12 @@ package body Prj.Proc is declare Imported : Project_List; Declaration_Node : Project_Node_Id := Empty_Node; - Tref : Source_Buffer_Ptr; Name : constant Name_Id := Name_Of (From_Project_Node, From_Project_Node_Tree); - Location : Source_Ptr := - Location_Of - (From_Project_Node, From_Project_Node_Tree); + Name_Node : constant Tree_Private_Part.Project_Name_And_Node := + Tree_Private_Part.Projects_Htable.Get + (From_Project_Node_Tree.Projects_HT, Name); begin Project := Processed_Projects.Get (Name); @@ -2458,6 +2456,7 @@ package body Prj.Proc is Processed_Projects.Set (Name, Project); Project.Name := Name; + Project.Display_Name := Name_Node.Display_Name; Project.Qualifier := Project_Qualifier_Of (From_Project_Node, From_Project_Node_Tree); @@ -2471,26 +2470,7 @@ package body Prj.Proc is Virtual_Prefix then Project.Virtual := True; - Project.Display_Name := Name; - - -- If there is no file, for example when the project node tree is - -- built in memory by GPS, the Display_Name cannot be found in - -- the source, so its value is the same as Name. - - elsif Location = No_Location then - Project.Display_Name := Name; - - -- Get the spelling of the project name from the project file - - else - Tref := Source_Text (Get_Source_File_Index (Location)); - - for J in 1 .. Name_Len loop - Name_Buffer (J) := Tref (Location); - Location := Location + 1; - end loop; - Project.Display_Name := Name_Find; end if; Project.Path.Display_Name := diff --git a/gcc/ada/prj-tree.adb b/gcc/ada/prj-tree.adb index 2d94f5c4bbb..08e4977c056 100644 --- a/gcc/ada/prj-tree.adb +++ b/gcc/ada/prj-tree.adb @@ -2854,6 +2854,7 @@ package body Prj.Tree is Name, Prj.Tree.Tree_Private_Part.Project_Name_And_Node' (Name => Name, + Display_Name => Name, Canonical_Path => No_Path, Node => Project, Extended => False, diff --git a/gcc/ada/prj-tree.ads b/gcc/ada/prj-tree.ads index e68c36eaad4..e587d3705aa 100644 --- a/gcc/ada/prj-tree.ads +++ b/gcc/ada/prj-tree.ads @@ -1332,6 +1332,9 @@ package Prj.Tree is Name : Name_Id; -- Name of the project + Display_Name : Name_Id; + -- The name of the project as it appears in the .gpr file + Node : Project_Node_Id; -- Node of the project in table Project_Nodes @@ -1348,6 +1351,7 @@ package Prj.Tree is No_Project_Name_And_Node : constant Project_Name_And_Node := (Name => No_Name, + Display_Name => No_Name, Node => Empty_Node, Canonical_Path => No_Path, Extended => True, diff --git a/gcc/ada/prj.adb b/gcc/ada/prj.adb index 2bed1a81dc2..b485f706829 100644 --- a/gcc/ada/prj.adb +++ b/gcc/ada/prj.adb @@ -89,7 +89,7 @@ package body Prj is Include_Path => null, Include_Data_Set => False, Source_Dirs => Nil_String, - Known_Order_Of_Source_Dirs => True, + Source_Dir_Ranks => No_Number_List, Object_Directory => No_Path_Information, Library_TS => Empty_Time_Stamp, Exec_Directory => No_Path_Information, @@ -841,6 +841,7 @@ package body Prj is begin if Tree /= null then Name_List_Table.Free (Tree.Name_Lists); + Number_List_Table.Free (Tree.Number_Lists); String_Element_Table.Free (Tree.String_Elements); Variable_Element_Table.Free (Tree.Variable_Elements); Array_Element_Table.Free (Tree.Array_Elements); @@ -868,6 +869,7 @@ package body Prj is -- Visible tables Name_List_Table.Init (Tree.Name_Lists); + Number_List_Table.Init (Tree.Number_Lists); String_Element_Table.Init (Tree.String_Elements); Variable_Element_Table.Init (Tree.Variable_Elements); Array_Element_Table.Init (Tree.Array_Elements); diff --git a/gcc/ada/prj.ads b/gcc/ada/prj.ads index 76eb59aecbb..502ace95f8d 100644 --- a/gcc/ada/prj.ads +++ b/gcc/ada/prj.ads @@ -314,7 +314,23 @@ package Prj is Table_Low_Bound => 1, Table_Initial => 10, Table_Increment => 100); - -- The table for lists of names used in package Language_Processing + -- The table for lists of names + + type Number_List_Index is new Nat; + No_Number_List : constant Number_List_Index := 0; + + type Number_Node is record + Number : Natural := 0; + Next : Number_List_Index := No_Number_List; + end record; + + package Number_List_Table is new GNAT.Dynamic_Tables + (Table_Component_Type => Number_Node, + Table_Index_Type => Number_List_Index, + Table_Low_Bound => 1, + Table_Initial => 10, + Table_Increment => 100); + -- The table for lists of numbers package Mapping_Files_Htable is new Simple_HTable (Header_Num => Header_Num, @@ -623,6 +639,12 @@ package Prj is Project : Project_Id := No_Project; -- Project of the source + Source_Dir_Rank : Natural := 0; + -- The rank of the source directory in list declared with attribute + -- Source_Dirs. Two source files with the same name cannot appears in + -- different directory with the same rank. That can happen when the + -- recursive notation <dir>/** is used in attribute Source_Dirs. + Language : Language_Ptr := No_Language_Index; -- Index of the language. This is an index into -- Project_Tree.Languages_Data. @@ -717,6 +739,7 @@ package Prj is No_Source_Data : constant Source_Data := (Project => No_Project, + Source_Dir_Rank => 0, Language => No_Language_Index, In_Interfaces => True, Declared_In_Interfaces => False, @@ -1155,10 +1178,7 @@ package Prj is Source_Dirs : String_List_Id := Nil_String; -- The list of all the source directories - Known_Order_Of_Source_Dirs : Boolean := True; - -- False, if there is any /** in the Source_Dirs, because in this case - -- the ordering of the source subdirs depend on the OS. If True, - -- duplicate file names in the same project file are allowed. + Source_Dir_Ranks : Number_List_Index := No_Number_List; Ada_Include_Path : String_Access := null; -- The cached value of source search path for this project file. Set by @@ -1273,6 +1293,7 @@ package Prj is type Project_Tree_Data is record Name_Lists : Name_List_Table.Instance; + Number_Lists : Number_List_Table.Instance; String_Elements : String_Element_Table.Instance; Variable_Elements : Variable_Element_Table.Instance; Array_Elements : Array_Element_Table.Instance; diff --git a/gcc/ada/s-oscons-tmplt.c b/gcc/ada/s-oscons-tmplt.c index c4218c2ab78..bce8648209b 100644 --- a/gcc/ada/s-oscons-tmplt.c +++ b/gcc/ada/s-oscons-tmplt.c @@ -175,6 +175,9 @@ int counter = 0; #endif +#define STR(x) STR1(x) +#define STR1(x) #x + #ifdef __MINGW32__ unsigned int _CRT_fmode = _O_BINARY; #endif @@ -218,6 +221,25 @@ package System.OS_Constants is /* + ----------------------------- + -- Platform identification -- + ----------------------------- + +*/ +TXT(" Target_Name : constant String := " STR(TARGET) ";") +/* + type Target_OS_Type is (Windows, VMS, Other_OS); +*/ +#if defined (__MINGW32__) +# define TARGET_OS "Windows" +#elif defined (__VMS) +# define TARGET_OS "VMS" +#else +# define TARGET_OS "Other_OS" +#endif +TXT(" Target_OS : constant Target_OS_Type := " TARGET_OS ";") +/* + ------------------- -- System limits -- ------------------- diff --git a/gcc/ada/sem_ch6.adb b/gcc/ada/sem_ch6.adb index 32323400b6d..94ed69e2598 100644 --- a/gcc/ada/sem_ch6.adb +++ b/gcc/ada/sem_ch6.adb @@ -5465,7 +5465,7 @@ package body Sem_Ch6 is -- generated stream attributes do get passed through because extra -- build-in-place formals are needed in some cases (limited 'Input). - if Is_Predefined_Dispatching_Operation (E) then + if Is_Predefined_Internal_Operation (E) then goto Test_For_BIP_Extras; end if; diff --git a/gcc/ada/sinfo.adb b/gcc/ada/sinfo.adb index 816adcf5afc..dd4aaafce9a 100644 --- a/gcc/ada/sinfo.adb +++ b/gcc/ada/sinfo.adb @@ -1583,6 +1583,14 @@ package body Sinfo is return Uint3 (N); end Intval; + function Is_Accessibility_Actual + (N : Node_Id) return Boolean is + begin + pragma Assert (False + or else NT (N).Nkind = N_Parameter_Association); + return Flag12 (N); + end Is_Accessibility_Actual; + function Is_Asynchronous_Call_Block (N : Node_Id) return Boolean is begin @@ -4435,6 +4443,14 @@ package body Sinfo is Set_Uint3 (N, Val); end Set_Intval; + procedure Set_Is_Accessibility_Actual + (N : Node_Id; Val : Boolean := True) is + begin + pragma Assert (False + or else NT (N).Nkind = N_Parameter_Association); + Set_Flag12 (N, Val); + end Set_Is_Accessibility_Actual; + procedure Set_Is_Asynchronous_Call_Block (N : Node_Id; Val : Boolean := True) is begin diff --git a/gcc/ada/sinfo.ads b/gcc/ada/sinfo.ads index b598b771de3..2e666c49a64 100644 --- a/gcc/ada/sinfo.ads +++ b/gcc/ada/sinfo.ads @@ -1179,6 +1179,13 @@ package Sinfo is -- to the node for the spec of the instance, inserted as part of the -- semantic processing for instantiations in Sem_Ch12. + -- Is_Accessibility_Actual (Flag12-Sem) + -- Present in N_Parameter_Association nodes. True if the parameter is + -- an extra actual that carries the accessibility level of the actual + -- for an access parameter, in a function that dispatches on result and + -- is called in a dispatching context. Used to prevent a formal/actual + -- mismatch when the call is rewritten as a dispatching call. + -- Is_Asynchronous_Call_Block (Flag7-Sem) -- A flag set in a Block_Statement node to indicate that it is the -- expansion of an asynchronous entry call. Such a block needs cleanup @@ -4450,6 +4457,7 @@ package Sinfo is -- Selector_Name (Node2) (always non-Empty) -- Explicit_Actual_Parameter (Node3) -- Next_Named_Actual (Node4-Sem) + -- Is_Accessibility_Actual (Flag12-Sem) --------------------------- -- 6.4 Actual Parameter -- @@ -8070,6 +8078,9 @@ package Sinfo is function Intval (N : Node_Id) return Uint; -- Uint3 + function Is_Accessibility_Actual + (N : Node_Id) return Boolean; -- Flag12 + function Is_Asynchronous_Call_Block (N : Node_Id) return Boolean; -- Flag7 @@ -8979,6 +8990,9 @@ package Sinfo is procedure Set_Intval (N : Node_Id; Val : Uint); -- Uint3 + procedure Set_Is_Accessibility_Actual + (N : Node_Id; Val : Boolean := True); -- Flag12 + procedure Set_Is_Asynchronous_Call_Block (N : Node_Id; Val : Boolean := True); -- Flag7 @@ -11246,6 +11260,7 @@ package Sinfo is pragma Inline (In_Present); pragma Inline (Instance_Spec); pragma Inline (Intval); + pragma Inline (Is_Accessibility_Actual); pragma Inline (Is_Asynchronous_Call_Block); pragma Inline (Is_Component_Left_Opnd); pragma Inline (Is_Component_Right_Opnd); @@ -11545,6 +11560,7 @@ package Sinfo is pragma Inline (Set_In_Present); pragma Inline (Set_Instance_Spec); pragma Inline (Set_Intval); + pragma Inline (Set_Is_Accessibility_Actual); pragma Inline (Set_Is_Asynchronous_Call_Block); pragma Inline (Set_Is_Component_Left_Opnd); pragma Inline (Set_Is_Component_Right_Opnd); diff --git a/gcc/ada/switch-c.adb b/gcc/ada/switch-c.adb index 1ecae61a013..9ccba42377d 100644 --- a/gcc/ada/switch-c.adb +++ b/gcc/ada/switch-c.adb @@ -310,6 +310,7 @@ package body Switch.C is case Switch_Chars (Ptr) is -- -gnatea (initial delimiter of explicit switches) + -- All switches that come before -gnatea have been added by -- the GCC driver and are not stored in the ALI file. -- See also -gnatez below. @@ -370,6 +371,7 @@ package body Switch.C is return; -- -gnateC switch (CodePeer SCIL generation) + -- Not enabled for now, keep it for later??? -- use -gnatd.I only for now @@ -468,9 +470,10 @@ package body Switch.C is Ptr := Max + 1; -- -gnatez (final delimiter of explicit switches) + -- All switches that come after -gnatez have been added by - -- the GCC driver and are not stored in the ALI file. - -- See also -gnatea above. + -- the GCC driver and are not stored in the ALI file. See + -- also -gnatea above. when 'z' => Store_Switch := False; @@ -478,6 +481,7 @@ package body Switch.C is Ptr := Ptr + 1; -- -gnateS (generate SCO information) + -- Include Source Coverage Obligation information in ALI -- files for the benefit of source coverage analysis tools -- (xcov). diff --git a/gcc/cfgbuild.c b/gcc/cfgbuild.c index b5ddadd2ac9..5744108b5d4 100644 --- a/gcc/cfgbuild.c +++ b/gcc/cfgbuild.c @@ -477,9 +477,17 @@ find_bb_boundaries (basic_block bb) if (code == CODE_LABEL && LABEL_ALT_ENTRY_P (insn)) make_edge (ENTRY_BLOCK_PTR, bb, 0); } - - if (control_flow_insn_p (insn)) + else if (code == BARRIER) + { + /* __builtin_unreachable () may cause a barrier to be emitted in + the middle of a BB. We need to split it in the same manner as + if the barrier were preceded by a control_flow_insn_p insn. */ + if (!flow_transfer_insn) + flow_transfer_insn = prev_nonnote_insn_bb (insn); + } + else if (control_flow_insn_p (insn)) flow_transfer_insn = insn; + if (insn == end) break; insn = NEXT_INSN (insn); diff --git a/gcc/config/rs6000/linux64.h b/gcc/config/rs6000/linux64.h index 94d18aee1da..37148c6aec6 100644 --- a/gcc/config/rs6000/linux64.h +++ b/gcc/config/rs6000/linux64.h @@ -437,11 +437,11 @@ extern int dot_symbols; #undef SAVE_FP_PREFIX #define SAVE_FP_PREFIX (TARGET_64BIT ? "._savef" : "_savefpr_") #undef SAVE_FP_SUFFIX -#define SAVE_FP_SUFFIX (TARGET_64BIT ? "" : "_l") +#define SAVE_FP_SUFFIX "" #undef RESTORE_FP_PREFIX #define RESTORE_FP_PREFIX (TARGET_64BIT ? "._restf" : "_restfpr_") #undef RESTORE_FP_SUFFIX -#define RESTORE_FP_SUFFIX (TARGET_64BIT ? "" : "_l") +#define RESTORE_FP_SUFFIX "" /* Dwarf2 debugging. */ #undef PREFERRED_DEBUGGING_TYPE diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 932a7e31d84..564b5407322 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -18033,7 +18033,8 @@ static bool no_global_regs_above (int first, bool gpr) { int i; - for (i = first; i < gpr ? 32 : 64 ; i++) + int last = gpr ? 32 : 64; + for (i = first; i < last; i++) if (global_regs[i]) return false; return true; @@ -18050,54 +18051,136 @@ no_global_regs_above (int first, bool gpr) static GTY(()) rtx savres_routine_syms[N_SAVRES_REGISTERS][8]; -/* Return the symbol for an out-of-line register save/restore routine. +/* Temporary holding space for an out-of-line register save/restore + routine name. */ +static char savres_routine_name[30]; + +/* Return the name for an out-of-line register save/restore routine. + We are saving/restoring GPRs if GPR is true. */ + +static char * +rs6000_savres_routine_name (rs6000_stack_t *info, int regno, + bool savep, bool gpr, bool lr) +{ + const char *prefix = ""; + const char *suffix = ""; + + /* Different targets are supposed to define + {SAVE,RESTORE}_FP_{PREFIX,SUFFIX} with the idea that the needed + routine name could be defined with: + + sprintf (name, "%s%d%s", SAVE_FP_PREFIX, regno, SAVE_FP_SUFFIX) + + This is a nice idea in practice, but in reality, things are + complicated in several ways: + + - ELF targets have save/restore routines for GPRs. + + - SPE targets use different prefixes for 32/64-bit registers, and + neither of them fit neatly in the FOO_{PREFIX,SUFFIX} regimen. + + - PPC64 ELF targets have routines for save/restore of GPRs that + differ in what they do with the link register, so having a set + prefix doesn't work. (We only use one of the save routines at + the moment, though.) + + - PPC32 elf targets have "exit" versions of the restore routines + that restore the link register and can save some extra space. + These require an extra suffix. (There are also "tail" versions + of the restore routines and "GOT" versions of the save routines, + but we don't generate those at present. Same problems apply, + though.) + + We deal with all this by synthesizing our own prefix/suffix and + using that for the simple sprintf call shown above. */ + if (TARGET_SPE) + { + /* No floating point saves on the SPE. */ + gcc_assert (gpr); + + if (savep) + prefix = info->spe_64bit_regs_used ? "_save64gpr_" : "_save32gpr_"; + else + prefix = info->spe_64bit_regs_used ? "_rest64gpr_" : "_rest32gpr_"; + + if (lr) + suffix = "_x"; + } + else if (DEFAULT_ABI == ABI_V4) + { + if (TARGET_64BIT) + goto aix_names; + + if (gpr) + prefix = savep ? "_savegpr_" : "_restgpr_"; + else + prefix = savep ? "_savefpr_" : "_restfpr_"; + + if (lr) + suffix = "_x"; + } + else if (DEFAULT_ABI == ABI_AIX) + { +#ifndef POWERPC_LINUX + /* No out-of-line save/restore routines for GPRs on AIX. */ + gcc_assert (!TARGET_AIX || !gpr); +#endif + + aix_names: + if (gpr) + prefix = (savep + ? (lr ? "_savegpr0_" : "_savegpr1_") + : (lr ? "_restgpr0_" : "_restgpr1_")); +#ifdef POWERPC_LINUX + else if (lr) + prefix = (savep ? "_savefpr_" : "_restfpr_"); +#endif + else + { + prefix = savep ? SAVE_FP_PREFIX : RESTORE_FP_PREFIX; + suffix = savep ? SAVE_FP_SUFFIX : RESTORE_FP_SUFFIX; + } + } + else if (DEFAULT_ABI == ABI_DARWIN) + sorry ("Out-of-line save/restore routines not supported on Darwin"); + + sprintf (savres_routine_name, "%s%d%s", prefix, regno, suffix); + + return savres_routine_name; +} + +/* Return an RTL SYMBOL_REF for an out-of-line register save/restore routine. We are saving/restoring GPRs if GPR is true. */ static rtx -rs6000_savres_routine_sym (rs6000_stack_t *info, bool savep, bool gpr, bool exitp) +rs6000_savres_routine_sym (rs6000_stack_t *info, bool savep, + bool gpr, bool lr) { int regno = gpr ? info->first_gp_reg_save : (info->first_fp_reg_save - 32); rtx sym; int select = ((savep ? 1 : 0) << 2 - | (gpr - /* On the SPE, we never have any FPRs, but we do have - 32/64-bit versions of the routines. */ - ? (TARGET_SPE_ABI && info->spe_64bit_regs_used ? 1 : 0) - : 0) << 1 - | (exitp ? 1: 0)); + | ((TARGET_SPE_ABI + /* On the SPE, we never have any FPRs, but we do have + 32/64-bit versions of the routines. */ + ? (info->spe_64bit_regs_used ? 1 : 0) + : (gpr ? 1 : 0)) << 1) + | (lr ? 1: 0)); /* Don't generate bogus routine names. */ - gcc_assert (FIRST_SAVRES_REGISTER <= regno && regno <= LAST_SAVRES_REGISTER); + gcc_assert (FIRST_SAVRES_REGISTER <= regno + && regno <= LAST_SAVRES_REGISTER); sym = savres_routine_syms[regno-FIRST_SAVRES_REGISTER][select]; if (sym == NULL) { - char name[30]; - const char *action; - const char *regkind; - const char *exit_suffix; - - action = savep ? "save" : "rest"; + char *name; - /* SPE has slightly different names for its routines depending on - whether we are saving 32-bit or 64-bit registers. */ - if (TARGET_SPE_ABI) - { - /* No floating point saves on the SPE. */ - gcc_assert (gpr); - - regkind = info->spe_64bit_regs_used ? "64gpr" : "32gpr"; - } - else - regkind = gpr ? "gpr" : "fpr"; - - exit_suffix = exitp ? "_x" : ""; - - sprintf (name, "_%s%s_%d%s", action, regkind, regno, exit_suffix); + name = rs6000_savres_routine_name (info, regno, savep, gpr, lr); sym = savres_routine_syms[regno-FIRST_SAVRES_REGISTER][select] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name)); + SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_FUNCTION; } return sym; @@ -18124,8 +18207,11 @@ rs6000_emit_stack_reset (rs6000_stack_t *info, if (frame_reg_rtx != sp_reg_rtx) { if (sp_offset != 0) - return emit_insn (gen_addsi3 (sp_reg_rtx, frame_reg_rtx, - GEN_INT (sp_offset))); + { + rtx dest_reg = savres ? gen_rtx_REG (Pmode, 11) : sp_reg_rtx; + return emit_insn (gen_add3_insn (dest_reg, frame_reg_rtx, + GEN_INT (sp_offset))); + } else if (!savres) return emit_move_insn (sp_reg_rtx, frame_reg_rtx); } @@ -18154,7 +18240,7 @@ static rtx rs6000_make_savres_rtx (rs6000_stack_t *info, rtx frame_reg_rtx, int save_area_offset, enum machine_mode reg_mode, - bool savep, bool gpr, bool exitp) + bool savep, bool gpr, bool lr) { int i; int offset, start_reg, end_reg, n_regs; @@ -18168,20 +18254,21 @@ rs6000_make_savres_rtx (rs6000_stack_t *info, : info->first_fp_reg_save); end_reg = gpr ? 32 : 64; n_regs = end_reg - start_reg; - p = rtvec_alloc ((exitp ? 4 : 3) + n_regs); + p = rtvec_alloc ((lr ? 4 : 3) + n_regs); - /* If we're saving registers, then we should never say we're exiting. */ - gcc_assert ((savep && !exitp) || !savep); - - if (exitp) + if (!savep && lr) RTVEC_ELT (p, offset++) = gen_rtx_RETURN (VOIDmode); RTVEC_ELT (p, offset++) = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 65)); - sym = rs6000_savres_routine_sym (info, savep, gpr, exitp); + sym = rs6000_savres_routine_sym (info, savep, gpr, lr); RTVEC_ELT (p, offset++) = gen_rtx_USE (VOIDmode, sym); - RTVEC_ELT (p, offset++) = gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, 11)); + RTVEC_ELT (p, offset++) + = gen_rtx_USE (VOIDmode, + gen_rtx_REG (Pmode, DEFAULT_ABI != ABI_AIX ? 11 + : gpr && !lr ? 12 + : 1)); for (i = 0; i < end_reg - start_reg; i++) { @@ -18196,6 +18283,16 @@ rs6000_make_savres_rtx (rs6000_stack_t *info, savep ? reg : mem); } + if (savep && lr) + { + rtx addr, reg, mem; + reg = gen_rtx_REG (Pmode, 0); + addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, + GEN_INT (info->lr_save_offset)); + mem = gen_frame_mem (Pmode, addr); + RTVEC_ELT (p, i + offset) = gen_rtx_SET (VOIDmode, mem, reg); + } + return gen_rtx_PARALLEL (VOIDmode, p); } @@ -18216,7 +18313,10 @@ rs6000_reg_live_or_pic_offset_p (int reg) enum { SAVRES_MULTIPLE = 0x1, SAVRES_INLINE_FPRS = 0x2, - SAVRES_INLINE_GPRS = 0x4 + SAVRES_INLINE_GPRS = 0x4, + SAVRES_NOINLINE_GPRS_SAVES_LR = 0x8, + SAVRES_NOINLINE_FPRS_SAVES_LR = 0x10, + SAVRES_NOINLINE_FPRS_DOESNT_RESTORE_LR = 0x20 }; /* Determine the strategy for savings/restoring registers. */ @@ -18231,6 +18331,7 @@ rs6000_savres_strategy (rs6000_stack_t *info, bool savep, bool savres_gprs_inline; bool noclobber_global_gprs = no_global_regs_above (info->first_gp_reg_save, /*gpr=*/true); + int strategy; using_multiple_p = (TARGET_MULTIPLE && ! TARGET_POWERPC64 && (!TARGET_SPE_ABI @@ -18250,6 +18351,10 @@ rs6000_savres_strategy (rs6000_stack_t *info, bool savep, || info->first_fp_reg_save == 64 || !no_global_regs_above (info->first_fp_reg_save, /*gpr=*/false) + /* The out-of-line FP routines use + double-precision stores; we can't use those + routines if we don't have such stores. */ + || (TARGET_HARD_FLOAT && !TARGET_DOUBLE_FLOAT) || FP_SAVE_INLINE (info->first_fp_reg_save)); savres_gprs_inline = (common /* Saving CR interferes with the exit routines @@ -18287,9 +18392,22 @@ rs6000_savres_strategy (rs6000_stack_t *info, bool savep, savres_gprs_inline = savres_gprs_inline || using_multiple_p; } - return (using_multiple_p - | (savres_fprs_inline << 1) - | (savres_gprs_inline << 2)); + strategy = (using_multiple_p + | (savres_fprs_inline << 1) + | (savres_gprs_inline << 2)); +#ifdef POWERPC_LINUX + if (TARGET_64BIT) + { + if (!savres_fprs_inline) + strategy |= SAVRES_NOINLINE_FPRS_SAVES_LR; + else if (!savres_gprs_inline && info->first_fp_reg_save == 64) + strategy |= SAVRES_NOINLINE_GPRS_SAVES_LR; + } +#else + if (TARGET_AIX && !savres_fprs_inline) + strategy |= SAVRES_NOINLINE_FPRS_DOESNT_RESTORE_LR; +#endif + return strategy; } /* Emit function prologue as insns. */ @@ -18311,7 +18429,7 @@ rs6000_emit_prologue (void) int using_store_multiple; int using_static_chain_p = (cfun->static_chain_decl != NULL_TREE && df_regs_ever_live_p (STATIC_CHAIN_REGNUM) - && !call_used_regs[STATIC_CHAIN_REGNUM]); + && call_used_regs[STATIC_CHAIN_REGNUM]); HOST_WIDE_INT sp_offset = 0; if (TARGET_FIX_AND_CONTINUE) @@ -18496,24 +18614,30 @@ rs6000_emit_prologue (void) gen_rtx_REG (Pmode, LR_REGNO)); RTX_FRAME_RELATED_P (insn) = 1; - addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, + if (!(strategy & (SAVRES_NOINLINE_GPRS_SAVES_LR + | SAVRES_NOINLINE_FPRS_SAVES_LR))) + { + addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, GEN_INT (info->lr_save_offset + sp_offset)); - reg = gen_rtx_REG (Pmode, 0); - mem = gen_rtx_MEM (Pmode, addr); - /* This should not be of rs6000_sr_alias_set, because of - __builtin_return_address. */ + reg = gen_rtx_REG (Pmode, 0); + mem = gen_rtx_MEM (Pmode, addr); + /* This should not be of rs6000_sr_alias_set, because of + __builtin_return_address. */ - insn = emit_move_insn (mem, reg); - rs6000_frame_related (insn, frame_ptr_rtx, info->total_size, - NULL_RTX, NULL_RTX); + insn = emit_move_insn (mem, reg); + rs6000_frame_related (insn, frame_ptr_rtx, info->total_size, + NULL_RTX, NULL_RTX); + } } - /* If we need to save CR, put it into r12. */ + /* If we need to save CR, put it into r12 or r11. */ if (!WORLD_SAVE_P (info) && info->cr_save_p && frame_reg_rtx != frame_ptr_rtx) { rtx set; - cr_save_rtx = gen_rtx_REG (SImode, 12); + cr_save_rtx + = gen_rtx_REG (SImode, DEFAULT_ABI == ABI_AIX && !saving_GPRs_inline + ? 11 : 12); insn = emit_insn (gen_movesi_from_cr (cr_save_rtx)); RTX_FRAME_RELATED_P (insn) = 1; /* Now, there's no way that dwarf2out_frame_debug_expr is going @@ -18550,7 +18674,9 @@ rs6000_emit_prologue (void) info->fp_save_offset + sp_offset, DFmode, /*savep=*/true, /*gpr=*/false, - /*exitp=*/false); + /*lr=*/(strategy + & SAVRES_NOINLINE_FPRS_SAVES_LR) + != 0); insn = emit_insn (par); rs6000_frame_related (insn, frame_ptr_rtx, info->total_size, NULL_RTX, NULL_RTX); @@ -18646,7 +18772,7 @@ rs6000_emit_prologue (void) par = rs6000_make_savres_rtx (info, gen_rtx_REG (Pmode, 11), 0, reg_mode, /*savep=*/true, /*gpr=*/true, - /*exitp=*/false); + /*lr=*/false); insn = emit_insn (par); rs6000_frame_related (insn, frame_ptr_rtx, info->total_size, NULL_RTX, NULL_RTX); @@ -18661,23 +18787,23 @@ rs6000_emit_prologue (void) { rtx par; - /* Need to adjust r11 if we saved any FPRs. */ + /* Need to adjust r11 (r12) if we saved any FPRs. */ if (info->first_fp_reg_save != 64) { - rtx r11 = gen_rtx_REG (reg_mode, 11); - rtx offset = GEN_INT (info->total_size + rtx dest_reg = gen_rtx_REG (reg_mode, DEFAULT_ABI == ABI_AIX + ? 12 : 11); + rtx offset = GEN_INT (sp_offset + (-8 * (64-info->first_fp_reg_save))); - rtx ptr_reg = (sp_reg_rtx == frame_reg_rtx - ? sp_reg_rtx : r11); - - emit_insn (gen_add3_insn (r11, ptr_reg, offset)); + emit_insn (gen_add3_insn (dest_reg, frame_reg_rtx, offset)); } par = rs6000_make_savres_rtx (info, frame_reg_rtx, info->gp_save_offset + sp_offset, reg_mode, /*savep=*/true, /*gpr=*/true, - /*exitp=*/false); + /*lr=*/(strategy + & SAVRES_NOINLINE_GPRS_SAVES_LR) + != 0); insn = emit_insn (par); rs6000_frame_related (insn, frame_ptr_rtx, info->total_size, NULL_RTX, NULL_RTX); @@ -18954,9 +19080,18 @@ rs6000_output_function_prologue (FILE *file, fp values. */ if (info->first_fp_reg_save < 64 && !FP_SAVE_INLINE (info->first_fp_reg_save)) - fprintf (file, "\t.extern %s%d%s\n\t.extern %s%d%s\n", - SAVE_FP_PREFIX, info->first_fp_reg_save - 32, SAVE_FP_SUFFIX, - RESTORE_FP_PREFIX, info->first_fp_reg_save - 32, RESTORE_FP_SUFFIX); + { + char *name; + int regno = info->first_fp_reg_save - 32; + + name = rs6000_savres_routine_name (info, regno, /*savep=*/true, + /*gpr=*/false, /*lr=*/false); + fprintf (file, "\t.extern %s\n", name); + + name = rs6000_savres_routine_name (info, regno, /*savep=*/false, + /*gpr=*/false, /*lr=*/true); + fprintf (file, "\t.extern %s\n", name); + } /* Write .extern for AIX common mode routines, if needed. */ if (! TARGET_POWER && ! TARGET_POWERPC && ! common_mode_defined) @@ -19082,6 +19217,7 @@ rs6000_emit_epilogue (int sibcall) rtx frame_reg_rtx = sp_reg_rtx; rtx cfa_restores = NULL_RTX; rtx insn; + rtx cr_save_reg = NULL_RTX; enum machine_mode reg_mode = Pmode; int reg_size = TARGET_32BIT ? 4 : 8; int i; @@ -19115,8 +19251,10 @@ rs6000_emit_epilogue (int sibcall) || (cfun->calls_alloca && !frame_pointer_needed)); restore_lr = (info->lr_save_p - && restoring_GPRs_inline - && restoring_FPRs_inline); + && (restoring_FPRs_inline + || (strategy & SAVRES_NOINLINE_FPRS_DOESNT_RESTORE_LR)) + && (restoring_GPRs_inline + || info->first_fp_reg_save < 64)); if (WORLD_SAVE_P (info)) { @@ -19403,7 +19541,7 @@ rs6000_emit_epilogue (int sibcall) /* Get the old lr if we saved it. If we are restoring registers out-of-line, then the out-of-line routines can do this for us. */ - if (restore_lr) + if (restore_lr && restoring_GPRs_inline) { rtx mem = gen_frame_mem_offset (Pmode, frame_reg_rtx, info->lr_save_offset + sp_offset); @@ -19418,12 +19556,17 @@ rs6000_emit_epilogue (int sibcall) GEN_INT (info->cr_save_offset + sp_offset)); rtx mem = gen_frame_mem (SImode, addr); - emit_move_insn (gen_rtx_REG (SImode, 12), mem); + cr_save_reg = gen_rtx_REG (SImode, + DEFAULT_ABI == ABI_AIX + && !restoring_GPRs_inline + && info->first_fp_reg_save < 64 + ? 11 : 12); + emit_move_insn (cr_save_reg, mem); } /* Set LR here to try to overlap restores below. LR is always saved above incoming stack, so it never needs REG_CFA_RESTORE. */ - if (restore_lr) + if (restore_lr && restoring_GPRs_inline) emit_move_insn (gen_rtx_REG (Pmode, LR_REGNO), gen_rtx_REG (Pmode, 0)); @@ -19540,7 +19683,7 @@ rs6000_emit_epilogue (int sibcall) par = rs6000_make_savres_rtx (info, gen_rtx_REG (Pmode, 11), 0, reg_mode, /*savep=*/false, /*gpr=*/true, - /*exitp=*/true); + /*lr=*/true); emit_jump_insn (par); /* We don't want anybody else emitting things after we jumped back. */ @@ -19558,21 +19701,25 @@ rs6000_emit_epilogue (int sibcall) rs6000_emit_stack_reset (info, sp_reg_rtx, frame_reg_rtx, sp_offset, can_use_exit); else - emit_insn (gen_addsi3 (gen_rtx_REG (Pmode, 11), - sp_reg_rtx, - GEN_INT (sp_offset - info->fp_size))); + { + emit_insn (gen_add3_insn (gen_rtx_REG (Pmode, DEFAULT_ABI == ABI_AIX + ? 12 : 11), + frame_reg_rtx, + GEN_INT (sp_offset - info->fp_size))); + if (REGNO (frame_reg_rtx) == 11) + sp_offset += info->fp_size; + } par = rs6000_make_savres_rtx (info, frame_reg_rtx, info->gp_save_offset, reg_mode, /*savep=*/false, /*gpr=*/true, - /*exitp=*/can_use_exit); + /*lr=*/can_use_exit); if (can_use_exit) { if (info->cr_save_p) { - rs6000_restore_saved_cr (gen_rtx_REG (SImode, 12), - using_mtcr_multiple); + rs6000_restore_saved_cr (cr_save_reg, using_mtcr_multiple); if (DEFAULT_ABI == ABI_V4) cfa_restores = alloc_reg_note (REG_CFA_RESTORE, @@ -19659,6 +19806,16 @@ rs6000_emit_epilogue (int sibcall) } } + if (restore_lr && !restoring_GPRs_inline) + { + rtx mem = gen_frame_mem_offset (Pmode, frame_reg_rtx, + info->lr_save_offset + sp_offset); + + emit_move_insn (gen_rtx_REG (Pmode, 0), mem); + emit_move_insn (gen_rtx_REG (Pmode, LR_REGNO), + gen_rtx_REG (Pmode, 0)); + } + /* Restore fpr's if we need to do it without calling a function. */ if (restoring_FPRs_inline) for (i = 0; i < 64 - info->first_fp_reg_save; i++) @@ -19685,7 +19842,7 @@ rs6000_emit_epilogue (int sibcall) /* If we saved cr, restore it here. Just those that were used. */ if (info->cr_save_p) { - rs6000_restore_saved_cr (gen_rtx_REG (SImode, 12), using_mtcr_multiple); + rs6000_restore_saved_cr (cr_save_reg, using_mtcr_multiple); if (DEFAULT_ABI == ABI_V4) cfa_restores = alloc_reg_note (REG_CFA_RESTORE, gen_rtx_REG (SImode, CR2_REGNO), @@ -19716,13 +19873,14 @@ rs6000_emit_epilogue (int sibcall) if (!sibcall) { rtvec p; + bool lr = (strategy & SAVRES_NOINLINE_FPRS_DOESNT_RESTORE_LR) == 0; if (! restoring_FPRs_inline) p = rtvec_alloc (4 + 64 - info->first_fp_reg_save); else p = rtvec_alloc (2); RTVEC_ELT (p, 0) = gen_rtx_RETURN (VOIDmode); - RTVEC_ELT (p, 1) = (restoring_FPRs_inline + RTVEC_ELT (p, 1) = ((restoring_FPRs_inline || !lr) ? gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, 65)) : gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 65))); @@ -19737,10 +19895,12 @@ rs6000_emit_epilogue (int sibcall) sym = rs6000_savres_routine_sym (info, /*savep=*/false, /*gpr=*/false, - /*exitp=*/true); + /*lr=*/lr); RTVEC_ELT (p, 2) = gen_rtx_USE (VOIDmode, sym); RTVEC_ELT (p, 3) = gen_rtx_USE (VOIDmode, - gen_rtx_REG (Pmode, 11)); + gen_rtx_REG (Pmode, + DEFAULT_ABI == ABI_AIX + ? 1 : 11)); for (i = 0; i < 64 - info->first_fp_reg_save; i++) { rtx addr, mem; diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 8ea90d825d7..97a128bf69e 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -15436,6 +15436,19 @@ [(set_attr "type" "branch") (set_attr "length" "4")]) +(define_insn "*return_and_restore_fpregs_aix_<mode>" + [(match_parallel 0 "any_parallel_operand" + [(return) + (use (match_operand:P 1 "register_operand" "l")) + (use (match_operand:P 2 "symbol_ref_operand" "s")) + (use (match_operand:P 3 "gpc_reg_operand" "r")) + (set (match_operand:DF 4 "gpc_reg_operand" "=d") + (match_operand:DF 5 "memory_operand" "m"))])] + "" + "b %z2" + [(set_attr "type" "branch") + (set_attr "length" "4")]) + ; This is used in compiling the unwind routines. (define_expand "eh_return" [(use (match_operand 0 "general_operand" ""))] diff --git a/gcc/config/rs6000/spe.md b/gcc/config/rs6000/spe.md index 917f817c2bf..ee608b97384 100644 --- a/gcc/config/rs6000/spe.md +++ b/gcc/config/rs6000/spe.md @@ -3156,9 +3156,9 @@ [(match_parallel 0 "any_parallel_operand" [(clobber (reg:P 65)) (use (match_operand:P 1 "symbol_ref_operand" "s")) - (use (match_operand:P 2 "gpc_reg_operand" "r")) - (set (match_operand:V2SI 3 "memory_operand" "=m") - (match_operand:V2SI 4 "gpc_reg_operand" "r"))])] + (use (reg:P 11)) + (set (match_operand:V2SI 2 "memory_operand" "=m") + (match_operand:V2SI 3 "gpc_reg_operand" "r"))])] "TARGET_SPE_ABI" "bl %z1" [(set_attr "type" "branch") @@ -3168,9 +3168,9 @@ [(match_parallel 0 "any_parallel_operand" [(clobber (reg:P 65)) (use (match_operand:P 1 "symbol_ref_operand" "s")) - (use (match_operand:P 2 "gpc_reg_operand" "r")) - (set (match_operand:V2SI 3 "gpc_reg_operand" "=r") - (match_operand:V2SI 4 "memory_operand" "m"))])] + (use (reg:P 11)) + (set (match_operand:V2SI 2 "gpc_reg_operand" "=r") + (match_operand:V2SI 3 "memory_operand" "m"))])] "TARGET_SPE_ABI" "bl %z1" [(set_attr "type" "branch") @@ -3181,9 +3181,9 @@ [(return) (clobber (reg:P 65)) (use (match_operand:P 1 "symbol_ref_operand" "s")) - (use (match_operand:P 2 "gpc_reg_operand" "r")) - (set (match_operand:V2SI 3 "gpc_reg_operand" "=r") - (match_operand:V2SI 4 "memory_operand" "m"))])] + (use (reg:P 11)) + (set (match_operand:V2SI 2 "gpc_reg_operand" "=r") + (match_operand:V2SI 3 "memory_operand" "m"))])] "TARGET_SPE_ABI" "b %z1" [(set_attr "type" "branch") diff --git a/gcc/config/rs6000/sysv4.h b/gcc/config/rs6000/sysv4.h index 4d28e375363..5377b474da5 100644 --- a/gcc/config/rs6000/sysv4.h +++ b/gcc/config/rs6000/sysv4.h @@ -272,27 +272,25 @@ do { \ #endif /* Define cutoff for using external functions to save floating point. - Currently on 64-bit V.4, always use inline stores. When optimizing - for size on 32-bit targets, use external functions when - profitable. */ -#define FP_SAVE_INLINE(FIRST_REG) (optimize_size && !TARGET_64BIT \ + When optimizing for size, use external functions when profitable. */ +#define FP_SAVE_INLINE(FIRST_REG) (optimize_size \ ? ((FIRST_REG) == 62 \ || (FIRST_REG) == 63) \ : (FIRST_REG) < 64) /* And similarly for general purpose registers. */ #define GP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) < 32 \ - && (TARGET_64BIT || !optimize_size)) + && !optimize_size) /* Put jump tables in read-only memory, rather than in .text. */ #define JUMP_TABLES_IN_TEXT_SECTION 0 /* Prefix and suffix to use to saving floating point. */ #define SAVE_FP_PREFIX "_savefpr_" -#define SAVE_FP_SUFFIX (TARGET_64BIT ? "_l" : "") +#define SAVE_FP_SUFFIX "" /* Prefix and suffix to use to restoring floating point. */ #define RESTORE_FP_PREFIX "_restfpr_" -#define RESTORE_FP_SUFFIX (TARGET_64BIT ? "_l" : "") +#define RESTORE_FP_SUFFIX "" /* Type used for ptrdiff_t, as a string used in a declaration. */ #define PTRDIFF_TYPE "int" diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index ed8a698cbbc..d0f9932288a 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -177,7 +177,7 @@ static rtx find_barrier (int, rtx, rtx); static int noncall_uses_reg (rtx, rtx, rtx *); static rtx gen_block_redirect (rtx, int, int); static void sh_reorg (void); -static void output_stack_adjust (int, rtx, int, HARD_REG_SET *); +static void output_stack_adjust (int, rtx, int, HARD_REG_SET *, bool); static rtx frame_insn (rtx); static rtx push (int); static void pop (int); @@ -6037,9 +6037,9 @@ output_jump_label_table (void) static void output_stack_adjust (int size, rtx reg, int epilogue_p, - HARD_REG_SET *live_regs_mask) + HARD_REG_SET *live_regs_mask, bool frame_p) { - rtx (*emit_fn) (rtx) = epilogue_p ? &emit_insn : &frame_insn; + rtx (*emit_fn) (rtx) = frame_p ? &frame_insn : &emit_insn; if (size) { HOST_WIDE_INT align = STACK_BOUNDARY / BITS_PER_UNIT; @@ -6701,9 +6701,10 @@ sh_expand_prologue (void) && (NPARM_REGS(SImode) > crtl->args.info.arg_count[(int) SH_ARG_INT])) pretend_args = 0; + /* Dwarf2 module doesn't expect frame related insns here. */ output_stack_adjust (-pretend_args - crtl->args.info.stack_regs * 8, - stack_pointer_rtx, 0, NULL); + stack_pointer_rtx, 0, NULL, false); if (TARGET_SHCOMPACT && flag_pic && crtl->args.info.call_cookie) /* We're going to use the PIC register to load the address of the @@ -6834,7 +6835,7 @@ sh_expand_prologue (void) offset_base = d + d_rounding; output_stack_adjust (-(save_size + d_rounding), stack_pointer_rtx, - 0, NULL); + 0, NULL, true); sh5_schedule_saves (&live_regs_mask, &schedule, offset_base); tmp_pnt = schedule.temps; @@ -7009,7 +7010,7 @@ sh_expand_prologue (void) target_flags = save_flags; output_stack_adjust (-rounded_frame_size (d) + d_rounding, - stack_pointer_rtx, 0, NULL); + stack_pointer_rtx, 0, NULL, true); if (frame_pointer_needed) frame_insn (GEN_MOV (hard_frame_pointer_rtx, stack_pointer_rtx)); @@ -7074,7 +7075,7 @@ sh_expand_epilogue (bool sibcall_p) See PR/18032 and PR/40313. */ emit_insn (gen_blockage ()); output_stack_adjust (frame_size, hard_frame_pointer_rtx, e, - &live_regs_mask); + &live_regs_mask, false); /* We must avoid moving the stack pointer adjustment past code which reads from the local frame, else an interrupt could @@ -7090,7 +7091,8 @@ sh_expand_epilogue (bool sibcall_p) occur after the SP adjustment and clobber data in the local frame. */ emit_insn (gen_blockage ()); - output_stack_adjust (frame_size, stack_pointer_rtx, e, &live_regs_mask); + output_stack_adjust (frame_size, stack_pointer_rtx, e, + &live_regs_mask, false); } if (SHMEDIA_REGS_STACK_ADJUST ()) @@ -7277,7 +7279,7 @@ sh_expand_epilogue (bool sibcall_p) output_stack_adjust (crtl->args.pretend_args_size + save_size + d_rounding + crtl->args.info.stack_regs * 8, - stack_pointer_rtx, e, NULL); + stack_pointer_rtx, e, NULL, false); if (crtl->calls_eh_return) emit_insn (GEN_ADD3 (stack_pointer_rtx, stack_pointer_rtx, diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 986dd2d987d..bad291122e7 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -7639,7 +7639,7 @@ a lot of functions that would otherwise not be considered for inlining by the compiler will be investigated. To those functions, a different (more restrictive) limit compared to functions declared inline can be applied. -The default value is 60. +The default value is 50. @item large-function-insns The limit specifying really large functions. For functions larger than this diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index b8586c2c0bc..9c9744b140e 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,11 @@ +2009-09-16 Michael Matz <matz@suse.de> + + PR fortran/41212 + * trans.h (struct lang_type): Remove nontarget_type member. + * trans.c (gfc_add_modify): Don't access it. + * trans-decl.c (gfc_finish_var_decl): Don't allocate and set it, + instead set DECL_RESTRICTED_P on affected decls. + 2009-09-14 Richard Henderson <rth@redhat.com> * f95-lang.c (gfc_init_builtin_functions): Update call to diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c index 6a4c3e45cc9..4e72a23bd5c 100644 --- a/gcc/fortran/trans-decl.c +++ b/gcc/fortran/trans-decl.c @@ -581,26 +581,8 @@ gfc_finish_var_decl (tree decl, gfc_symbol * sym) if (!sym->attr.target && !sym->attr.pointer - && !sym->attr.proc_pointer - /* For now, don't bother with aggregate types. We would need - to adjust DECL_CONTEXT of all field decls. */ - && !AGGREGATE_TYPE_P (TREE_TYPE (decl))) - { - tree type = TREE_TYPE (decl); - if (!TYPE_LANG_SPECIFIC (type)) - TYPE_LANG_SPECIFIC (type) = (struct lang_type *) - ggc_alloc_cleared (sizeof (struct lang_type)); - if (!TYPE_LANG_SPECIFIC (type)->nontarget_type) - { - alias_set_type set = new_alias_set (); - type = build_distinct_type_copy (type); - TYPE_ALIAS_SET (type) = set; - TYPE_LANG_SPECIFIC (type)->nontarget_type = type; - } - else - type = TYPE_LANG_SPECIFIC (type)->nontarget_type; - TREE_TYPE (decl) = type; - } + && !sym->attr.proc_pointer) + DECL_RESTRICTED_P (decl) = 1; } diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c index f4a215aeeaf..136987a7488 100644 --- a/gcc/fortran/trans.c +++ b/gcc/fortran/trans.c @@ -162,13 +162,6 @@ gfc_add_modify (stmtblock_t * pblock, tree lhs, tree rhs) tree t1, t2; t1 = TREE_TYPE (rhs); t2 = TREE_TYPE (lhs); - /* ??? This is actually backwards, we should test the "base" type - from which the nontarget_type was copied, but we don't have this - backlink. This will do for now, it's for checking anyway. */ - if (TYPE_LANG_SPECIFIC (t1)) - t1 = TYPE_LANG_SPECIFIC (t1)->nontarget_type; - if (TYPE_LANG_SPECIFIC (t2)) - t2 = TYPE_LANG_SPECIFIC (t2)->nontarget_type; /* Make sure that the types of the rhs and the lhs are the same for scalar assignments. We should probably have something similar for aggregates, but right now removing that check just diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h index 643f28b37f4..4469023499d 100644 --- a/gcc/fortran/trans.h +++ b/gcc/fortran/trans.h @@ -629,7 +629,6 @@ struct GTY(()) lang_type { tree dataptr_type; tree span; tree base_decl[2]; - tree nontarget_type; }; struct GTY(()) lang_decl { diff --git a/gcc/integrate.c b/gcc/integrate.c index 30ef854ffff..d92cec5f67e 100644 --- a/gcc/integrate.c +++ b/gcc/integrate.c @@ -167,6 +167,7 @@ set_block_abstract_flags (tree stmt, int setting) { tree local_decl; tree subblock; + unsigned int i; BLOCK_ABSTRACT (stmt) = setting; @@ -175,6 +176,14 @@ set_block_abstract_flags (tree stmt, int setting) local_decl = TREE_CHAIN (local_decl)) set_decl_abstract_flags (local_decl, setting); + for (i = 0; i < BLOCK_NUM_NONLOCALIZED_VARS (stmt); i++) + { + local_decl = BLOCK_NONLOCALIZED_VAR (stmt, i); + if ((TREE_CODE (local_decl) == VAR_DECL && !TREE_STATIC (local_decl)) + || TREE_CODE (local_decl) == PARM_DECL) + set_decl_abstract_flags (local_decl, setting); + } + for (subblock = BLOCK_SUBBLOCKS (stmt); subblock != NULL_TREE; subblock = BLOCK_CHAIN (subblock)) diff --git a/gcc/params.def b/gcc/params.def index f8b87db00f6..ff3e41c2fbd 100644 --- a/gcc/params.def +++ b/gcc/params.def @@ -82,7 +82,7 @@ DEFPARAM (PARAM_MAX_INLINE_INSNS_SINGLE, DEFPARAM (PARAM_MAX_INLINE_INSNS_AUTO, "max-inline-insns-auto", "The maximum number of instructions when automatically inlining", - 60, 0, 0) + 50, 0, 0) DEFPARAM (PARAM_MAX_INLINE_INSNS_RECURSIVE, "max-inline-insns-recursive", diff --git a/gcc/reorg.c b/gcc/reorg.c index 4453ccabca6..4871b0e8c29 100644 --- a/gcc/reorg.c +++ b/gcc/reorg.c @@ -1630,13 +1630,14 @@ redundant_insn (rtx insn, rtx target, rtx delay_list) for (trial = PREV_INSN (target), insns_to_search = MAX_DELAY_SLOT_INSN_SEARCH; trial && insns_to_search > 0; - trial = PREV_INSN (trial), --insns_to_search) + trial = PREV_INSN (trial)) { if (LABEL_P (trial)) return 0; - if (! INSN_P (trial)) + if (!NONDEBUG_INSN_P (trial)) continue; + --insns_to_search; pat = PATTERN (trial); if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER) @@ -1735,10 +1736,11 @@ redundant_insn (rtx insn, rtx target, rtx delay_list) for (trial = PREV_INSN (target), insns_to_search = MAX_DELAY_SLOT_INSN_SEARCH; trial && !LABEL_P (trial) && insns_to_search > 0; - trial = PREV_INSN (trial), --insns_to_search) + trial = PREV_INSN (trial)) { - if (!INSN_P (trial)) + if (!NONDEBUG_INSN_P (trial)) continue; + --insns_to_search; pat = PATTERN (trial); if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5649e200a85..5730da14617 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,32 @@ +2009-09-16 Michael Matz <matz@suse.de> + + PR fortran/41212 + * gfortran.dg/pr41212.f90: New test. + +2009-09-16 Eric Botcazou <ebotcazou@adacore.com> + + * gnat.dg/alignment9.adb: New test. + +2009-09-16 Eric Botcazou <ebotcazou@adacore.com> + + * gnat.dg/discr20.ad[sb]: New test. + +2009-09-16 Richard Guenther <rguenther@suse.de> + + PR middle-end/34011 + * gcc.dg/tree-ssa/ssa-lim-7.c: New testcase. + +2009-09-16 DJ Delorie <dj@redhat.com> + Kaz Kojima <kkojima@gcc.gnu.org> + + * gcc.target/sh/struct-arg-dw2.c: New test. + +2009-09-15 Nathan Froyd <froydnj@codesourcery.com> + Jakub Jelinek <jakub@redhat.com> + + PR target/41175 + * gcc.target/powerpc/pr41175.c: New test. + 2009-09-14 Richard Henderson <rth@redhat.com> * c-c++-common/asmgoto-1.c, c-c++-common/asmgoto-2.c, diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-7.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-7.c new file mode 100644 index 00000000000..f8e15f34486 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-7.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-lim1-details" } */ + +extern const int srcshift; + +void foo (int *srcdata, int *dstdata) +{ + int i; + + for (i = 0; i < 256; i++) + dstdata[i] = srcdata[i] << srcshift; +} + +/* { dg-final { scan-tree-dump "Moving statement" "lim1" } } */ +/* { dg-final { cleanup-tree-dump "lim1" } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/pr41175.c b/gcc/testsuite/gcc.target/powerpc/pr41175.c new file mode 100644 index 00000000000..2f0137962c5 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr41175.c @@ -0,0 +1,461 @@ +/* PR target/41175 */ +/* { dg-do run } */ +/* { dg-options "-Os" } */ + +#define X2(n) X1(n##0) X1(n##1) +#define X4(n) X2(n##0) X2(n##1) +#define X8(n) X4(n##0) X4(n##1) + +#ifndef __SPE__ +#define FLOAT_REG_CONSTRAINT "f" +#else +#define FLOAT_REG_CONSTRAINT "r" +#endif + +volatile int ll; + +__attribute__((noinline)) void +foo (void) +{ + asm volatile ("" : : : "memory"); +} + +__attribute__((noinline)) void +bar (char *p) +{ + asm volatile ("" : : "r" (p) : "memory"); +} + +__attribute__((noinline)) void +f1 (void) +{ + int mem; +#undef X1 +#define X1(n) int gpr##n = 0; + X8(a) X8(b) X8(c) +#undef X1 +#define X1(n) "+r" (gpr##n), + asm volatile ("" : X8(a) "=m" (mem) : : "memory"); + asm volatile ("" : X8(b) "=m" (mem) : : "memory"); + asm volatile ("" : X8(c) "=m" (mem) : : "memory"); + foo (); +#undef X1 +#define X1(n) "r" (gpr##n), + asm volatile ("" : : X8(a) "m" (mem) : "memory"); + asm volatile ("" : : X8(b) "m" (mem) : "memory"); + asm volatile ("" : : X8(c) "m" (mem) : "memory"); +} + +__attribute__((noinline)) void +f2 (void) +{ + int mem; +#undef X1 +#define X1(n) int gpr##n = 0; + X8(a) X8(b) X8(c) +#undef X1 +#define X1(n) "+r" (gpr##n), + asm volatile ("" : X8(a) "=m" (mem) : : "memory"); + asm volatile ("" : X8(b) "=m" (mem) : : "memory"); + asm volatile ("" : X8(c) "=m" (mem) : : "memory"); + char *pp = __builtin_alloca (ll); + bar (pp); +#undef X1 +#define X1(n) "r" (gpr##n), + asm volatile ("" : : X8(a) "m" (mem) : "memory"); + asm volatile ("" : : X8(b) "m" (mem) : "memory"); + asm volatile ("" : : X8(c) "m" (mem) : "memory"); +} + +__attribute__((noinline)) void +f3 (void) +{ + int mem; +#undef X1 +#define X1(n) int gpr##n = 0; + X8(a) X8(b) X8(c) +#undef X1 +#define X1(n) "+r" (gpr##n), + asm volatile ("" : X8(a) "=m" (mem) : : "memory"); + asm volatile ("" : X8(b) "=m" (mem) : : "memory"); + asm volatile ("" : X8(c) "=m" (mem) : : "memory"); +#undef X1 +#define X1(n) "r" (gpr##n), + asm volatile ("" : : X8(a) "m" (mem) : "memory"); + asm volatile ("" : : X8(b) "m" (mem) : "memory"); + asm volatile ("" : : X8(c) "m" (mem) : "memory"); +} + +#ifndef __NO_FPRS__ +__attribute__((noinline)) void +f4 (void) +{ + int mem; +#undef X1 +#define X1(n) int gpr##n = 0; + X8(a) X8(b) X8(c) +#undef X1 +#define X1(n) double fpr##n = 0.0; + X4(d) +#undef X1 +#define X1(n) "+r" (gpr##n), + asm volatile ("" : X8(a) "=m" (mem) : : "memory"); + asm volatile ("" : X8(b) "=m" (mem) : : "memory"); + asm volatile ("" : X8(c) "=m" (mem) : : "memory"); +#undef X1 +#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n), + asm volatile ("" : X4(d) "=m" (mem) : : "memory"); + foo (); +#undef X1 +#define X1(n) "r" (gpr##n), + asm volatile ("" : : X8(a) "m" (mem) : "memory"); + asm volatile ("" : : X8(b) "m" (mem) : "memory"); + asm volatile ("" : : X8(c) "m" (mem) : "memory"); +#undef X1 +#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n), + asm volatile ("" : : X4(d) "m" (mem) : "memory"); +} + +__attribute__((noinline)) void +f5 (void) +{ + int mem; +#undef X1 +#define X1(n) int gpr##n = 0; + X8(a) X8(b) X8(c) +#undef X1 +#define X1(n) double fpr##n = 0.0; + X4(d) +#undef X1 +#define X1(n) "+r" (gpr##n), + asm volatile ("" : X8(a) "=m" (mem) : : "memory"); + asm volatile ("" : X8(b) "=m" (mem) : : "memory"); + asm volatile ("" : X8(c) "=m" (mem) : : "memory"); +#undef X1 +#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n), + asm volatile ("" : X4(d) "=m" (mem) : : "memory"); + char *pp = __builtin_alloca (ll); + bar (pp); +#undef X1 +#define X1(n) "r" (gpr##n), + asm volatile ("" : : X8(a) "m" (mem) : "memory"); + asm volatile ("" : : X8(b) "m" (mem) : "memory"); + asm volatile ("" : : X8(c) "m" (mem) : "memory"); +#undef X1 +#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n), + asm volatile ("" : : X4(d) "m" (mem) : "memory"); +} + +__attribute__((noinline)) void +f6 (void) +{ + int mem; +#undef X1 +#define X1(n) int gpr##n = 0; + X8(a) X8(b) X8(c) +#undef X1 +#define X1(n) double fpr##n = 0.0; + X4(d) +#undef X1 +#define X1(n) "+r" (gpr##n), + asm volatile ("" : X8(a) "=m" (mem) : : "memory"); + asm volatile ("" : X8(b) "=m" (mem) : : "memory"); + asm volatile ("" : X8(c) "=m" (mem) : : "memory"); +#undef X1 +#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n), + asm volatile ("" : X4(d) "=m" (mem) : : "memory"); +#undef X1 +#define X1(n) "r" (gpr##n), + asm volatile ("" : : X8(a) "m" (mem) : "memory"); + asm volatile ("" : : X8(b) "m" (mem) : "memory"); + asm volatile ("" : : X8(c) "m" (mem) : "memory"); +#undef X1 +#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n), + asm volatile ("" : : X4(d) "m" (mem) : "memory"); +} + +__attribute__((noinline)) void +f7 (void) +{ + int mem; +#undef X1 +#define X1(n) int gpr##n = 0; + X8(a) X8(b) X8(c) +#undef X1 +#define X1(n) double fpr##n = 0.0; + X2(d) +#undef X1 +#define X1(n) "+r" (gpr##n), + asm volatile ("" : X8(a) "=m" (mem) : : "memory"); + asm volatile ("" : X8(b) "=m" (mem) : : "memory"); + asm volatile ("" : X8(c) "=m" (mem) : : "memory"); +#undef X1 +#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n), + asm volatile ("" : X2(d) "=m" (mem) : : "memory"); + foo (); +#undef X1 +#define X1(n) "r" (gpr##n), + asm volatile ("" : : X8(a) "m" (mem) : "memory"); + asm volatile ("" : : X8(b) "m" (mem) : "memory"); + asm volatile ("" : : X8(c) "m" (mem) : "memory"); +#undef X1 +#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n), + asm volatile ("" : : X2(d) "m" (mem) : "memory"); +} + +__attribute__((noinline)) void +f8 (void) +{ + int mem; +#undef X1 +#define X1(n) int gpr##n = 0; + X8(a) X8(b) X8(c) +#undef X1 +#define X1(n) double fpr##n = 0.0; + X2(d) +#undef X1 +#define X1(n) "+r" (gpr##n), + asm volatile ("" : X8(a) "=m" (mem) : : "memory"); + asm volatile ("" : X8(b) "=m" (mem) : : "memory"); + asm volatile ("" : X8(c) "=m" (mem) : : "memory"); +#undef X1 +#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n), + asm volatile ("" : X2(d) "=m" (mem) : : "memory"); + char *pp = __builtin_alloca (ll); + bar (pp); +#undef X1 +#define X1(n) "r" (gpr##n), + asm volatile ("" : : X8(a) "m" (mem) : "memory"); + asm volatile ("" : : X8(b) "m" (mem) : "memory"); + asm volatile ("" : : X8(c) "m" (mem) : "memory"); +#undef X1 +#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n), + asm volatile ("" : : X2(d) "m" (mem) : "memory"); +} + +__attribute__((noinline)) void +f9 (void) +{ + int mem; +#undef X1 +#define X1(n) int gpr##n = 0; + X8(a) X8(b) X8(c) +#undef X1 +#define X1(n) double fpr##n = 0.0; + X2(d) +#undef X1 +#define X1(n) "+r" (gpr##n), + asm volatile ("" : X8(a) "=m" (mem) : : "memory"); + asm volatile ("" : X8(b) "=m" (mem) : : "memory"); + asm volatile ("" : X8(c) "=m" (mem) : : "memory"); +#undef X1 +#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n), + asm volatile ("" : X2(d) "=m" (mem) : : "memory"); +#undef X1 +#define X1(n) "r" (gpr##n), + asm volatile ("" : : X8(a) "m" (mem) : "memory"); + asm volatile ("" : : X8(b) "m" (mem) : "memory"); + asm volatile ("" : : X8(c) "m" (mem) : "memory"); +#undef X1 +#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n), + asm volatile ("" : : X2(d) "m" (mem) : "memory"); +} + +__attribute__((noinline)) void +f10 (void) +{ + int mem; +#undef X1 +#define X1(n) int gpr##n = 0; + X8(a) X8(b) X4(c) +#undef X1 +#define X1(n) double fpr##n = 0.0; + X1(d) +#undef X1 +#define X1(n) "+r" (gpr##n), + asm volatile ("" : X8(a) "=m" (mem) : : "memory"); + asm volatile ("" : X8(b) "=m" (mem) : : "memory"); + asm volatile ("" : X4(c) "=m" (mem) : : "memory"); +#undef X1 +#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n), + asm volatile ("" : X1(d) "=m" (mem) : : "memory"); + foo (); +#undef X1 +#define X1(n) "r" (gpr##n), + asm volatile ("" : : X8(a) "m" (mem) : "memory"); + asm volatile ("" : : X8(b) "m" (mem) : "memory"); + asm volatile ("" : : X4(c) "m" (mem) : "memory"); +#undef X1 +#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n), + asm volatile ("" : : X1(d) "m" (mem) : "memory"); +} + +__attribute__((noinline)) void +f11 (void) +{ + int mem; +#undef X1 +#define X1(n) int gpr##n = 0; + X8(a) X8(b) X4(c) +#undef X1 +#define X1(n) double fpr##n = 0.0; + X1(d) +#undef X1 +#define X1(n) "+r" (gpr##n), + asm volatile ("" : X8(a) "=m" (mem) : : "memory"); + asm volatile ("" : X8(b) "=m" (mem) : : "memory"); + asm volatile ("" : X4(c) "=m" (mem) : : "memory"); +#undef X1 +#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n), + asm volatile ("" : X1(d) "=m" (mem) : : "memory"); + char *pp = __builtin_alloca (ll); + bar (pp); +#undef X1 +#define X1(n) "r" (gpr##n), + asm volatile ("" : : X8(a) "m" (mem) : "memory"); + asm volatile ("" : : X8(b) "m" (mem) : "memory"); + asm volatile ("" : : X4(c) "m" (mem) : "memory"); +#undef X1 +#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n), + asm volatile ("" : : X1(d) "m" (mem) : "memory"); +} + +__attribute__((noinline)) void +f12 (void) +{ + int mem; +#undef X1 +#define X1(n) int gpr##n = 0; + X8(a) X8(b) X4(c) +#undef X1 +#define X1(n) double fpr##n = 0.0; + X1(d) +#undef X1 +#define X1(n) "+r" (gpr##n), + asm volatile ("" : X8(a) "=m" (mem) : : "memory"); + asm volatile ("" : X8(b) "=m" (mem) : : "memory"); + asm volatile ("" : X4(c) "=m" (mem) : : "memory"); +#undef X1 +#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n), + asm volatile ("" : X1(d) "=m" (mem) : : "memory"); +#undef X1 +#define X1(n) "r" (gpr##n), + asm volatile ("" : : X8(a) "m" (mem) : "memory"); + asm volatile ("" : : X8(b) "m" (mem) : "memory"); + asm volatile ("" : : X4(c) "m" (mem) : "memory"); +#undef X1 +#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n), + asm volatile ("" : : X1(d) "m" (mem) : "memory"); +} + +__attribute__((noinline)) void +f13 (void) +{ + int mem; +#undef X1 +#define X1(n) int gpr##n = 0; + X8(a) X8(b) X2(c) +#undef X1 +#define X1(n) double fpr##n = 0.0; + X8(d) +#undef X1 +#define X1(n) "+r" (gpr##n), + asm volatile ("" : X8(a) "=m" (mem) : : "memory"); + asm volatile ("" : X8(b) "=m" (mem) : : "memory"); + asm volatile ("" : X2(c) "=m" (mem) : : "memory"); +#undef X1 +#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n), + asm volatile ("" : X8(d) "=m" (mem) : : "memory"); + foo (); +#undef X1 +#define X1(n) "r" (gpr##n), + asm volatile ("" : : X8(a) "m" (mem) : "memory"); + asm volatile ("" : : X8(b) "m" (mem) : "memory"); + asm volatile ("" : : X2(c) "m" (mem) : "memory"); +#undef X1 +#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n), + asm volatile ("" : : X8(d) "m" (mem) : "memory"); +} + +__attribute__((noinline)) void +f14 (void) +{ + int mem; +#undef X1 +#define X1(n) int gpr##n = 0; + X8(a) X8(b) X2(c) +#undef X1 +#define X1(n) double fpr##n = 0.0; + X8(d) +#undef X1 +#define X1(n) "+r" (gpr##n), + asm volatile ("" : X8(a) "=m" (mem) : : "memory"); + asm volatile ("" : X8(b) "=m" (mem) : : "memory"); + asm volatile ("" : X2(c) "=m" (mem) : : "memory"); +#undef X1 +#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n), + asm volatile ("" : X8(d) "=m" (mem) : : "memory"); + char *pp = __builtin_alloca (ll); + bar (pp); +#undef X1 +#define X1(n) "r" (gpr##n), + asm volatile ("" : : X8(a) "m" (mem) : "memory"); + asm volatile ("" : : X8(b) "m" (mem) : "memory"); + asm volatile ("" : : X2(c) "m" (mem) : "memory"); +#undef X1 +#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n), + asm volatile ("" : : X8(d) "m" (mem) : "memory"); +} + +__attribute__((noinline)) void +f15 (void) +{ + int mem; +#undef X1 +#define X1(n) int gpr##n = 0; + X8(a) X8(b) X2(c) +#undef X1 +#define X1(n) double fpr##n = 0.0; + X8(d) +#undef X1 +#define X1(n) "+r" (gpr##n), + asm volatile ("" : X8(a) "=m" (mem) : : "memory"); + asm volatile ("" : X8(b) "=m" (mem) : : "memory"); + asm volatile ("" : X2(c) "=m" (mem) : : "memory"); +#undef X1 +#define X1(n) "+" FLOAT_REG_CONSTRAINT (fpr##n), + asm volatile ("" : X8(d) "=m" (mem) : : "memory"); +#undef X1 +#define X1(n) "r" (gpr##n), + asm volatile ("" : : X8(a) "m" (mem) : "memory"); + asm volatile ("" : : X8(b) "m" (mem) : "memory"); + asm volatile ("" : : X2(c) "m" (mem) : "memory"); +#undef X1 +#define X1(n) FLOAT_REG_CONSTRAINT (fpr##n), + asm volatile ("" : : X8(d) "m" (mem) : "memory"); +} +#endif + +int +main () +{ + ll = 60; + f1 (); + f2 (); + f3 (); +#ifndef __NO_FPRS__ + f4 (); + f5 (); + f6 (); + f7 (); + f8 (); + f9 (); + f10 (); + f11 (); + f12 (); + f13 (); + f14 (); + f15 (); +#endif + return 0; +} diff --git a/gcc/testsuite/gcc.target/sh/struct-arg-dw2.c b/gcc/testsuite/gcc.target/sh/struct-arg-dw2.c new file mode 100644 index 00000000000..effd13d19a4 --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/struct-arg-dw2.c @@ -0,0 +1,26 @@ +/* Verify that we don't generate fame related insn against stack adjustment + for the object sent partially in registers. */ +/* { dg-do compile { target "sh*-*-*" } } */ +/* { dg-options "-g" } */ +/* { dg-final { scan-assembler-not "\t.cfi_def_cfa_offset 16" } } */ + +typedef struct +{ + unsigned short A1; + unsigned short A2; +} A_t; + +typedef struct +{ + A_t C13[10]; +} C_t; + +void +Store (C_t Par) +{ + unsigned char *ptr; + unsigned int test; + + ptr = (unsigned char*) 0x12345678; + ptr++; +} diff --git a/gcc/testsuite/gfortran.dg/pr41212.f90 b/gcc/testsuite/gfortran.dg/pr41212.f90 new file mode 100644 index 00000000000..4bdae6dad28 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr41212.f90 @@ -0,0 +1,34 @@ +! { dg-do run } +! { dg-options "-O2" } +program m + double precision :: y,z + call b(1.0d0,y,z) + if (ABS (z - 1.213) > 0.1) call abort +contains + subroutine b( x, y, z) + implicit none + double precision :: x,y,z + integer :: i, k + double precision :: h, r + + y = 1.0d0 + z = 0.0d0 + + h = 0 + DO k = 1,10 + h = h + 1.0d0/k + + r = 1 + DO i = 1,k + r = (x/(2*i) ) * r + END DO + + y = y + (-1)**k * r + z = z + (-1)**(k+1) * h * r + + IF ( ABS(2*k/x*r) < 1d-6 ) EXIT + END DO + + z = 2*y + end subroutine b +end program m diff --git a/gcc/testsuite/gnat.dg/alignment9.adb b/gcc/testsuite/gnat.dg/alignment9.adb new file mode 100644 index 00000000000..ae7a7f67e9e --- /dev/null +++ b/gcc/testsuite/gnat.dg/alignment9.adb @@ -0,0 +1,30 @@ +-- { dg-do run } +-- { dg-options "-gnatws" } + +procedure Alignment9 is + + type Kind is (Small, Large); + for Kind'Size use 8; + + type Header is + record + K : Kind; + I : Integer; + end record; + + for Header use + record + K at 4 range 0..7; + I at 0 range 0..31; + end record; + + for Header'Size use 5*8; + for Header'Alignment use 1; + + H : Header; + +begin + if H'Size /= 40 then + raise Program_Error; + end if; +end; diff --git a/gcc/testsuite/gnat.dg/discr20.adb b/gcc/testsuite/gnat.dg/discr20.adb new file mode 100644 index 00000000000..358d5654058 --- /dev/null +++ b/gcc/testsuite/gnat.dg/discr20.adb @@ -0,0 +1,10 @@ +-- { dg-do compile } + +package body Discr20 is + + function Get (X : Wrapper) return Def is + begin + return X.It; + end Get; + +end Discr20; diff --git a/gcc/testsuite/gnat.dg/discr20.ads b/gcc/testsuite/gnat.dg/discr20.ads new file mode 100644 index 00000000000..a447b3309c3 --- /dev/null +++ b/gcc/testsuite/gnat.dg/discr20.ads @@ -0,0 +1,31 @@ +package Discr20 is + + Size : Integer; + + type Name is new String (1..Size); + + type Rec is record + It : Name; + end record; + + type Danger is (This, That); + type def (X : Danger := This) is record + case X is + when This => It : Rec; + when That => null; + end case; + end record; + + type Switch is (On, Off); + type Wrapper (Disc : Switch := On) is private; + function Get (X : Wrapper) return Def; + +private + type Wrapper (Disc : Switch := On) is record + Case Disc is + when On => It : Def; + when Off => null; + end case; + end record; + +end Discr20; diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index f596c75fe27..ef5f32284d4 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -3573,6 +3573,25 @@ verify_gimple_call (gimple stmt) return true; } + /* If there is a static chain argument, this should not be an indirect + call, and the decl should not have DECL_NO_STATIC_CHAIN set. */ + if (gimple_call_chain (stmt)) + { + if (TREE_CODE (fn) != ADDR_EXPR + || TREE_CODE (TREE_OPERAND (fn, 0)) != FUNCTION_DECL) + { + error ("static chain in indirect gimple call"); + return true; + } + fn = TREE_OPERAND (fn, 0); + + if (DECL_NO_STATIC_CHAIN (fn)) + { + error ("static chain with function that doesn't use one"); + return true; + } + } + /* ??? The C frontend passes unpromoted arguments in case it didn't see a function declaration before the call. So for now leave the call arguments unverified. Once we gimplify diff --git a/gcc/tree-flow-inline.h b/gcc/tree-flow-inline.h index eef2f4324a9..fdb33378bee 100644 --- a/gcc/tree-flow-inline.h +++ b/gcc/tree-flow-inline.h @@ -616,12 +616,18 @@ is_global_var (const_tree t) /* Return true if VAR may be aliased. A variable is considered as maybe aliased if it has its address taken by the local TU - or possibly by another TU. */ + or possibly by another TU and might be modified through a pointer. */ static inline bool may_be_aliased (const_tree var) { - return (TREE_PUBLIC (var) || DECL_EXTERNAL (var) || TREE_ADDRESSABLE (var)); + return (TREE_CODE (var) != CONST_DECL + && !((TREE_STATIC (var) || TREE_PUBLIC (var) || DECL_EXTERNAL (var)) + && TREE_READONLY (var) + && !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (var))) + && (TREE_PUBLIC (var) + || DECL_EXTERNAL (var) + || TREE_ADDRESSABLE (var))); } diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c index 7c55c8adc23..bcf971143cf 100644 --- a/gcc/tree-nested.c +++ b/gcc/tree-nested.c @@ -1,5 +1,6 @@ /* Nested function decomposition for GIMPLE. - Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 + Free Software Foundation, Inc. This file is part of GCC. @@ -102,6 +103,27 @@ struct nesting_info }; +/* Iterate over the nesting tree, starting with ROOT, depth first. */ + +static inline struct nesting_info * +iter_nestinfo_start (struct nesting_info *root) +{ + while (root->inner) + root = root->inner; + return root; +} + +static inline struct nesting_info * +iter_nestinfo_next (struct nesting_info *node) +{ + if (node->next) + return iter_nestinfo_start (node->next); + return node->outer; +} + +#define FOR_EACH_NEST_INFO(I, ROOT) \ + for ((I) = iter_nestinfo_start (ROOT); (I); (I) = iter_nestinfo_next (I)) + /* Obstack used for the bitmaps in the struct above. */ static struct bitmap_obstack nesting_info_bitmap_obstack; @@ -301,6 +323,7 @@ static tree get_chain_decl (struct nesting_info *info) { tree decl = info->chain_decl; + if (!decl) { tree type; @@ -327,6 +350,14 @@ get_chain_decl (struct nesting_info *info) TREE_READONLY (decl) = 1; info->chain_decl = decl; + + if (dump_file + && (dump_flags & TDF_DETAILS) + && DECL_NO_STATIC_CHAIN (info->context)) + fprintf (dump_file, "Resetting no-static-chain for %s\n", + lang_hooks.decl_printable_name (info->context, 2)); + + DECL_NO_STATIC_CHAIN (info->context) = 0; } return decl; } @@ -339,6 +370,7 @@ static tree get_chain_field (struct nesting_info *info) { tree field = info->chain_field; + if (!field) { tree type = build_pointer_type (get_frame_type (info->outer)); @@ -352,6 +384,14 @@ get_chain_field (struct nesting_info *info) insert_field_into_struct (get_frame_type (info), field); info->chain_field = field; + + if (dump_file + && (dump_flags & TDF_DETAILS) + && DECL_NO_STATIC_CHAIN (info->context)) + fprintf (dump_file, "Resetting no-static-chain for %s\n", + lang_hooks.decl_printable_name (info->context, 2)); + + DECL_NO_STATIC_CHAIN (info->context) = 0; } return field; } @@ -622,14 +662,9 @@ static void walk_all_functions (walk_stmt_fn callback_stmt, walk_tree_fn callback_op, struct nesting_info *root) { - do - { - if (root->inner) - walk_all_functions (callback_stmt, callback_op, root->inner); - walk_function (callback_stmt, callback_op, root); - root = root->next; - } - while (root); + struct nesting_info *n; + FOR_EACH_NEST_INFO (n, root) + walk_function (callback_stmt, callback_op, n); } @@ -1931,6 +1966,8 @@ convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p, switch (gimple_code (stmt)) { case GIMPLE_CALL: + if (gimple_call_chain (stmt)) + break; decl = gimple_call_fndecl (stmt); if (!decl) break; @@ -1998,32 +2035,71 @@ convert_gimple_call (gimple_stmt_iterator *gsi, bool *handled_ops_p, return NULL_TREE; } - -/* Walk the nesting tree starting with ROOT, depth first. Convert all - trampolines and call expressions. On the way back up, determine if - a nested function actually uses its static chain; if not, remember that. */ +/* Walk the nesting tree starting with ROOT. Convert all trampolines and + call expressions. At the same time, determine if a nested function + actually uses its static chain; if not, remember that. */ static void convert_all_function_calls (struct nesting_info *root) { + struct nesting_info *n; + int iter_count; + bool any_changed; + + /* First, optimistically set no_static_chain for all decls that haven't + used the static chain already for variable access. Notice that we + do this pre-order, because we want inner functions to be processed + first in the LIFO worklist. */ + FOR_EACH_NEST_INFO (n, root) + { + tree decl = n->context; + if (n->outer && !n->chain_decl && !n->chain_field) + { + DECL_NO_STATIC_CHAIN (decl) = 1; + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, "Guessing no-static-chain for %s\n", + lang_hooks.decl_printable_name (decl, 2)); + } + else + gcc_assert (!DECL_NO_STATIC_CHAIN (decl)); + } + + /* Walk the functions and perform transformations. Note that these + transformations can induce new uses of the static chain, which in turn + require re-examining all users of the decl. */ + /* ??? It would make sense to try to use the call graph to speed this up, + but the call graph hasn't really been built yet. Even if it did, we + would still need to iterate in this loop since address-of references + wouldn't show up in the callgraph anyway. */ + iter_count = 0; do { - if (root->inner) - convert_all_function_calls (root->inner); + any_changed = false; + iter_count++; - walk_function (convert_tramp_reference_stmt, convert_tramp_reference_op, - root); - walk_function (convert_gimple_call, NULL, root); + if (dump_file && (dump_flags & TDF_DETAILS)) + fputc ('\n', dump_file); - /* If the function does not use a static chain, then remember that. */ - if (root->outer && !root->chain_decl && !root->chain_field) - DECL_NO_STATIC_CHAIN (root->context) = 1; - else - gcc_assert (!DECL_NO_STATIC_CHAIN (root->context)); + FOR_EACH_NEST_INFO (n, root) + { + tree decl = n->context; + bool old_no_static_chain = DECL_NO_STATIC_CHAIN (decl); - root = root->next; + walk_function (convert_tramp_reference_stmt, + convert_tramp_reference_op, n); + walk_function (convert_gimple_call, NULL, n); + + /* If a call to another function created the use of a chain + within this function, we'll have to continue iteration. */ + if (old_no_static_chain && !DECL_NO_STATIC_CHAIN (decl)) + any_changed = true; + } } - while (root); + while (any_changed); + + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, "convert_all_function_calls iterations: %d\n\n", + iter_count); } struct nesting_copy_body_data @@ -2263,10 +2339,8 @@ finalize_nesting_tree_1 (struct nesting_info *root) if (!field) continue; - if (DECL_NO_STATIC_CHAIN (i->context)) - arg3 = null_pointer_node; - else - arg3 = build_addr (root->frame_decl, context); + gcc_assert (!DECL_NO_STATIC_CHAIN (i->context)); + arg3 = build_addr (root->frame_decl, context); arg2 = build_addr (i->context, context); @@ -2379,20 +2453,19 @@ finalize_nesting_tree_1 (struct nesting_info *root) } /* Dump the translated tree function. */ - dump_function (TDI_nested, root->context); + if (dump_file) + { + fputs ("\n\n", dump_file); + dump_function_to_file (root->context, dump_file, dump_flags); + } } static void finalize_nesting_tree (struct nesting_info *root) { - do - { - if (root->inner) - finalize_nesting_tree (root->inner); - finalize_nesting_tree_1 (root); - root = root->next; - } - while (root); + struct nesting_info *n; + FOR_EACH_NEST_INFO (n, root) + finalize_nesting_tree_1 (n); } /* Unnest the nodes and pass them to cgraph. */ @@ -2414,14 +2487,9 @@ unnest_nesting_tree_1 (struct nesting_info *root) static void unnest_nesting_tree (struct nesting_info *root) { - do - { - if (root->inner) - unnest_nesting_tree (root->inner); - unnest_nesting_tree_1 (root); - root = root->next; - } - while (root); + struct nesting_info *n; + FOR_EACH_NEST_INFO (n, root) + unnest_nesting_tree_1 (n); } /* Free the data structures allocated during this pass. */ @@ -2429,18 +2497,18 @@ unnest_nesting_tree (struct nesting_info *root) static void free_nesting_tree (struct nesting_info *root) { - struct nesting_info *next; + struct nesting_info *node, *next; + + node = iter_nestinfo_start (root); do { - if (root->inner) - free_nesting_tree (root->inner); - pointer_map_destroy (root->var_map); - pointer_map_destroy (root->field_map); - next = root->next; - free (root); - root = next; + next = iter_nestinfo_next (node); + pointer_map_destroy (node->var_map); + pointer_map_destroy (node->field_map); + free (node); + node = next; } - while (root); + while (node); } /* Gimplify a function and all its nested functions. */ @@ -2462,6 +2530,10 @@ lower_nested_functions (tree fndecl) { struct cgraph_node *cgn; struct nesting_info *root; +#ifdef ENABLE_CHECKING + struct nesting_info *n; + bitmap orig_decl_no_static_chain; +#endif /* If there are no nested functions, there's nothing to do. */ cgn = cgraph_node (fndecl); @@ -2470,8 +2542,23 @@ lower_nested_functions (tree fndecl) gimplify_all_functions (cgn); + dump_file = dump_begin (TDI_nested, &dump_flags); + if (dump_file) + fprintf (dump_file, "\n;; Function %s\n\n", + lang_hooks.decl_printable_name (fndecl, 2)); + bitmap_obstack_initialize (&nesting_info_bitmap_obstack); root = create_nesting_tree (cgn); + +#ifdef ENABLE_CHECKING + /* The C++ and Ada front ends set DECL_NO_STATIC_CHAIN in various + instances where they expect no static chain needed. */ + orig_decl_no_static_chain = BITMAP_ALLOC (&nesting_info_bitmap_obstack); + FOR_EACH_NEST_INFO (n, root) + if (DECL_NO_STATIC_CHAIN (n->context)) + bitmap_set_bit (orig_decl_no_static_chain, DECL_UID (n->context)); +#endif + walk_all_functions (convert_nonlocal_reference_stmt, convert_nonlocal_reference_op, root); @@ -2480,11 +2567,26 @@ lower_nested_functions (tree fndecl) root); walk_all_functions (convert_nl_goto_reference, NULL, root); walk_all_functions (convert_nl_goto_receiver, NULL, root); + convert_all_function_calls (root); finalize_nesting_tree (root); unnest_nesting_tree (root); + +#ifdef ENABLE_CHECKING + /* Validate the original settings of DECL_NO_STATIC_CHAIN. */ + FOR_EACH_NEST_INFO (n, root) + if (bitmap_bit_p (orig_decl_no_static_chain, DECL_UID (n->context))) + gcc_assert (DECL_NO_STATIC_CHAIN (n->context)); +#endif + free_nesting_tree (root); bitmap_obstack_release (&nesting_info_bitmap_obstack); + + if (dump_file) + { + dump_end (TDI_nested, dump_file); + dump_file = NULL; + } } #include "gt-tree-nested.h" diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index 9522b28c548..e619190386c 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -208,6 +208,14 @@ ptr_deref_may_alias_decl_p (tree ptr, tree decl) if (!pi) return true; + /* If the decl can be used as a restrict tag and we have a restrict + pointer and that pointers points-to set doesn't contain this decl + then they can't alias. */ + if (DECL_RESTRICTED_P (decl) + && TYPE_RESTRICT (TREE_TYPE (ptr)) + && pi->pt.vars_contains_restrict) + return bitmap_bit_p (pi->pt.vars, DECL_UID (decl)); + return pt_solution_includes (&pi->pt, decl); } diff --git a/gcc/tree.h b/gcc/tree.h index 70650489dd9..09ce8fa125c 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -1306,6 +1306,15 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int, (TREE_CHECK3 (NODE, VAR_DECL, PARM_DECL, \ RESULT_DECL)->decl_common.decl_by_reference_flag) +/* In a RESULT_DECL, PARM_DECL and VAR_DECL, means that this decl + can be used as restricted tag to disambiguate against other restrict + pointers. Used by fortran to capture something like non-addressability + (which it isn't really because the middle-end does take addresses of + such variables). */ +#define DECL_RESTRICTED_P(NODE) \ + (TREE_CHECK3 (NODE, VAR_DECL, PARM_DECL, \ + RESULT_DECL)->decl_common.decl_restricted_flag) + /* In a CALL_EXPR, means that the call is the jump from a thunk to the thunked-to function. */ #define CALL_FROM_THUNK_P(NODE) (CALL_EXPR_CHECK (NODE)->base.protected_flag) @@ -2646,8 +2655,10 @@ struct GTY(()) tree_decl_common { unsigned gimple_reg_flag : 1; /* In VAR_DECL, PARM_DECL and RESULT_DECL, this is DECL_BY_REFERENCE. */ unsigned decl_by_reference_flag : 1; + /* In VAR_DECL, PARM_DECL and RESULT_DECL, this is DECL_RESTRICTED_P. */ + unsigned decl_restricted_flag : 1; /* Padding so that 'off_align' can be on a 32-bit boundary. */ - unsigned decl_common_unused : 4; + unsigned decl_common_unused : 3; /* DECL_OFFSET_ALIGN, used only for FIELD_DECLs. */ unsigned int off_align : 8; |