Mercurial > hg > CbC > CbC_gcc
comparison gcc/ada/inline.adb @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | 84e7813d76e9 |
children |
comparison
equal
deleted
inserted
replaced
131:84e7813d76e9 | 145:1830386684a0 |
---|---|
4 -- -- | 4 -- -- |
5 -- I N L I N E -- | 5 -- I N L I N E -- |
6 -- -- | 6 -- -- |
7 -- B o d y -- | 7 -- B o d y -- |
8 -- -- | 8 -- -- |
9 -- Copyright (C) 1992-2018, Free Software Foundation, Inc. -- | 9 -- Copyright (C) 1992-2019, Free Software Foundation, Inc. -- |
10 -- -- | 10 -- -- |
11 -- GNAT is free software; you can redistribute it and/or modify it under -- | 11 -- GNAT is free software; you can redistribute it and/or modify it under -- |
12 -- terms of the GNU General Public License as published by the Free Soft- -- | 12 -- terms of the GNU General Public License as published by the Free Soft- -- |
13 -- ware Foundation; either version 3, or (at your option) any later ver- -- | 13 -- ware Foundation; either version 3, or (at your option) any later ver- -- |
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- | 14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- |
21 -- GNAT was originally developed by the GNAT team at New York University. -- | 21 -- GNAT was originally developed by the GNAT team at New York University. -- |
22 -- Extensive contributions were provided by Ada Core Technologies Inc. -- | 22 -- Extensive contributions were provided by Ada Core Technologies Inc. -- |
23 -- -- | 23 -- -- |
24 ------------------------------------------------------------------------------ | 24 ------------------------------------------------------------------------------ |
25 | 25 |
26 with Alloc; | |
26 with Aspects; use Aspects; | 27 with Aspects; use Aspects; |
27 with Atree; use Atree; | 28 with Atree; use Atree; |
28 with Debug; use Debug; | 29 with Debug; use Debug; |
29 with Einfo; use Einfo; | 30 with Einfo; use Einfo; |
30 with Elists; use Elists; | 31 with Elists; use Elists; |
49 with Sem_Util; use Sem_Util; | 50 with Sem_Util; use Sem_Util; |
50 with Sinfo; use Sinfo; | 51 with Sinfo; use Sinfo; |
51 with Sinput; use Sinput; | 52 with Sinput; use Sinput; |
52 with Snames; use Snames; | 53 with Snames; use Snames; |
53 with Stand; use Stand; | 54 with Stand; use Stand; |
55 with Table; | |
56 with Tbuild; use Tbuild; | |
57 with Uintp; use Uintp; | |
54 with Uname; use Uname; | 58 with Uname; use Uname; |
55 with Tbuild; use Tbuild; | 59 |
60 with GNAT.HTable; | |
56 | 61 |
57 package body Inline is | 62 package body Inline is |
58 | 63 |
59 Check_Inlining_Restrictions : constant Boolean := True; | 64 Check_Inlining_Restrictions : constant Boolean := True; |
60 -- In the following cases the frontend rejects inlining because they | 65 -- In the following cases the frontend rejects inlining because they |
80 -- List of frontend inlined calls | 85 -- List of frontend inlined calls |
81 | 86 |
82 Backend_Calls : Elist_Id; | 87 Backend_Calls : Elist_Id; |
83 -- List of inline calls passed to the backend | 88 -- List of inline calls passed to the backend |
84 | 89 |
90 Backend_Instances : Elist_Id; | |
91 -- List of instances inlined for the backend | |
92 | |
85 Backend_Inlined_Subps : Elist_Id; | 93 Backend_Inlined_Subps : Elist_Id; |
86 -- List of subprograms inlined by the backend | 94 -- List of subprograms inlined by the backend |
87 | 95 |
88 Backend_Not_Inlined_Subps : Elist_Id; | 96 Backend_Not_Inlined_Subps : Elist_Id; |
89 -- List of subprograms that cannot be inlined by the backend | 97 -- List of subprograms that cannot be inlined by the backend |
98 | |
99 ----------------------------- | |
100 -- Pending_Instantiations -- | |
101 ----------------------------- | |
102 | |
103 -- We make entries in this table for the pending instantiations of generic | |
104 -- bodies that are created during semantic analysis. After the analysis is | |
105 -- complete, calling Instantiate_Bodies performs the actual instantiations. | |
106 | |
107 package Pending_Instantiations is new Table.Table ( | |
108 Table_Component_Type => Pending_Body_Info, | |
109 Table_Index_Type => Int, | |
110 Table_Low_Bound => 0, | |
111 Table_Initial => Alloc.Pending_Instantiations_Initial, | |
112 Table_Increment => Alloc.Pending_Instantiations_Increment, | |
113 Table_Name => "Pending_Instantiations"); | |
114 | |
115 ------------------------------------- | |
116 -- Called_Pending_Instantiations -- | |
117 ------------------------------------- | |
118 | |
119 -- With back-end inlining, the pending instantiations that are not in the | |
120 -- main unit or subunit are performed only after a call to the subprogram | |
121 -- instance, or to a subprogram within the package instance, is inlined. | |
122 -- Since such a call can be within a subsequent pending instantiation, | |
123 -- we make entries in this table that stores the index of these "called" | |
124 -- pending instantiations and perform them when the table is populated. | |
125 | |
126 package Called_Pending_Instantiations is new Table.Table ( | |
127 Table_Component_Type => Int, | |
128 Table_Index_Type => Int, | |
129 Table_Low_Bound => 0, | |
130 Table_Initial => Alloc.Pending_Instantiations_Initial, | |
131 Table_Increment => Alloc.Pending_Instantiations_Increment, | |
132 Table_Name => "Called_Pending_Instantiations"); | |
133 | |
134 --------------------------------- | |
135 -- To_Pending_Instantiations -- | |
136 --------------------------------- | |
137 | |
138 -- With back-end inlining, we also need to have a map from the pending | |
139 -- instantiations to their index in the Pending_Instantiations table. | |
140 | |
141 Node_Table_Size : constant := 257; | |
142 -- Number of headers in hash table | |
143 | |
144 subtype Node_Header_Num is Integer range 0 .. Node_Table_Size - 1; | |
145 -- Range of headers in hash table | |
146 | |
147 function Node_Hash (Id : Node_Id) return Node_Header_Num; | |
148 -- Simple hash function for Node_Ids | |
149 | |
150 package To_Pending_Instantiations is new GNAT.Htable.Simple_HTable | |
151 (Header_Num => Node_Header_Num, | |
152 Element => Int, | |
153 No_Element => -1, | |
154 Key => Node_Id, | |
155 Hash => Node_Hash, | |
156 Equal => "="); | |
157 | |
158 ----------------- | |
159 -- Node_Hash -- | |
160 ----------------- | |
161 | |
162 function Node_Hash (Id : Node_Id) return Node_Header_Num is | |
163 begin | |
164 return Node_Header_Num (Id mod Node_Table_Size); | |
165 end Node_Hash; | |
90 | 166 |
91 -------------------- | 167 -------------------- |
92 -- Inlined Bodies -- | 168 -- Inlined Bodies -- |
93 -------------------- | 169 -------------------- |
94 | 170 |
177 procedure Add_Call (Called : Entity_Id; Caller : Entity_Id := Empty); | 253 procedure Add_Call (Called : Entity_Id; Caller : Entity_Id := Empty); |
178 -- Make two entries in Inlined table, for an inlined subprogram being | 254 -- Make two entries in Inlined table, for an inlined subprogram being |
179 -- called, and for the inlined subprogram that contains the call. If | 255 -- called, and for the inlined subprogram that contains the call. If |
180 -- the call is in the main compilation unit, Caller is Empty. | 256 -- the call is in the main compilation unit, Caller is Empty. |
181 | 257 |
258 procedure Add_Inlined_Instance (E : Entity_Id); | |
259 -- Add instance E to the list of inlined instances for the unit | |
260 | |
182 procedure Add_Inlined_Subprogram (E : Entity_Id); | 261 procedure Add_Inlined_Subprogram (E : Entity_Id); |
183 -- Add subprogram E to the list of inlined subprogram for the unit | 262 -- Add subprogram E to the list of inlined subprograms for the unit |
184 | 263 |
185 function Add_Subp (E : Entity_Id) return Subp_Index; | 264 function Add_Subp (E : Entity_Id) return Subp_Index; |
186 -- Make entry in Inlined table for subprogram E, or return table index | 265 -- Make entry in Inlined table for subprogram E, or return table index |
187 -- that already holds E. | 266 -- that already holds E. |
188 | 267 |
427 end loop; | 506 end loop; |
428 | 507 |
429 return Dont_Inline; | 508 return Dont_Inline; |
430 end Must_Inline; | 509 end Must_Inline; |
431 | 510 |
432 Level : Inline_Level_Type; | 511 Inst : Entity_Id; |
512 Inst_Decl : Node_Id; | |
513 Level : Inline_Level_Type; | |
433 | 514 |
434 -- Start of processing for Add_Inlined_Body | 515 -- Start of processing for Add_Inlined_Body |
435 | 516 |
436 begin | 517 begin |
437 Append_New_Elmt (N, To => Backend_Calls); | 518 Append_New_Elmt (N, To => Backend_Calls); |
438 | 519 |
439 -- Skip subprograms that cannot be inlined outside their unit | 520 -- Skip subprograms that cannot or need not be inlined outside their |
521 -- unit or parent subprogram. | |
440 | 522 |
441 if Is_Abstract_Subprogram (E) | 523 if Is_Abstract_Subprogram (E) |
442 or else Convention (E) = Convention_Protected | 524 or else Convention (E) = Convention_Protected |
525 or else In_Main_Unit_Or_Subunit (E) | |
443 or else Is_Nested (E) | 526 or else Is_Nested (E) |
444 then | 527 then |
445 return; | 528 return; |
446 end if; | 529 end if; |
447 | 530 |
453 Level := Must_Inline; | 536 Level := Must_Inline; |
454 | 537 |
455 if Level = Dont_Inline then | 538 if Level = Dont_Inline then |
456 return; | 539 return; |
457 end if; | 540 end if; |
541 | |
542 -- If a previous call to the subprogram has been inlined, nothing to do | |
543 | |
544 if Is_Called (E) then | |
545 return; | |
546 end if; | |
547 | |
548 -- If the subprogram is an instance, then inline the instance | |
549 | |
550 if Is_Generic_Instance (E) then | |
551 Add_Inlined_Instance (E); | |
552 end if; | |
553 | |
554 -- Mark the subprogram as called | |
555 | |
556 Set_Is_Called (E); | |
458 | 557 |
459 -- If the call was generated by the compiler and is to a subprogram in | 558 -- If the call was generated by the compiler and is to a subprogram in |
460 -- a run-time unit, we need to suppress debugging information for it, | 559 -- a run-time unit, we need to suppress debugging information for it, |
461 -- so that the code that is eventually inlined will not affect the | 560 -- so that the code that is eventually inlined will not affect the |
462 -- debugging of the program. We do not do it if the call comes from | 561 -- debugging of the program. We do not do it if the call comes from |
474 -- where both the spec and body are in the same context, then there is | 573 -- where both the spec and body are in the same context, then there is |
475 -- no need to load any package body since the body of the function is | 574 -- no need to load any package body since the body of the function is |
476 -- in the spec. | 575 -- in the spec. |
477 | 576 |
478 if Is_Non_Loading_Expression_Function (E) then | 577 if Is_Non_Loading_Expression_Function (E) then |
479 Set_Is_Called (E); | |
480 return; | 578 return; |
481 end if; | 579 end if; |
482 | 580 |
483 -- Find unit containing E, and add to list of inlined bodies if needed. | 581 -- Find unit containing E, and add to list of inlined bodies if needed. |
484 -- If the body is already present, no need to load any other unit. This | |
485 -- is the case for an initialization procedure, which appears in the | |
486 -- package declaration that contains the type. It is also the case if | |
487 -- the body has already been analyzed. Finally, if the unit enclosing | |
488 -- E is an instance, the instance body will be analyzed in any case, | |
489 -- and there is no need to add the enclosing unit (whose body might not | |
490 -- be available). | |
491 | |
492 -- Library-level functions must be handled specially, because there is | 582 -- Library-level functions must be handled specially, because there is |
493 -- no enclosing package to retrieve. In this case, it is the body of | 583 -- no enclosing package to retrieve. In this case, it is the body of |
494 -- the function that will have to be loaded. | 584 -- the function that will have to be loaded. |
495 | 585 |
496 declare | 586 declare |
497 Pack : constant Entity_Id := Get_Code_Unit_Entity (E); | 587 Pack : constant Entity_Id := Get_Code_Unit_Entity (E); |
498 | 588 |
499 begin | 589 begin |
500 if Pack = E then | 590 if Pack = E then |
501 Set_Is_Called (E); | |
502 Inlined_Bodies.Increment_Last; | 591 Inlined_Bodies.Increment_Last; |
503 Inlined_Bodies.Table (Inlined_Bodies.Last) := E; | 592 Inlined_Bodies.Table (Inlined_Bodies.Last) := E; |
504 | 593 |
505 elsif Ekind (Pack) = E_Package then | 594 else |
506 Set_Is_Called (E); | 595 pragma Assert (Ekind (Pack) = E_Package); |
596 | |
597 -- If the subprogram is within an instance, inline the instance | |
598 | |
599 if Comes_From_Source (E) then | |
600 Inst := Scope (E); | |
601 | |
602 while Present (Inst) and then Inst /= Standard_Standard loop | |
603 exit when Is_Generic_Instance (Inst); | |
604 Inst := Scope (Inst); | |
605 end loop; | |
606 | |
607 if Present (Inst) | |
608 and then Is_Generic_Instance (Inst) | |
609 and then not Is_Called (Inst) | |
610 then | |
611 Inst_Decl := Unit_Declaration_Node (Inst); | |
612 | |
613 -- Do not inline the instance if the body already exists, | |
614 -- or the instance node is simply missing. | |
615 | |
616 if Present (Corresponding_Body (Inst_Decl)) | |
617 or else (Nkind (Parent (Inst_Decl)) /= N_Compilation_Unit | |
618 and then No (Next (Inst_Decl))) | |
619 then | |
620 Set_Is_Called (Inst); | |
621 else | |
622 Add_Inlined_Instance (Inst); | |
623 end if; | |
624 end if; | |
625 end if; | |
626 | |
627 -- If the unit containing E is an instance, nothing more to do | |
507 | 628 |
508 if Is_Generic_Instance (Pack) then | 629 if Is_Generic_Instance (Pack) then |
509 null; | 630 null; |
510 | 631 |
511 -- Do not inline the package if the subprogram is an init proc | 632 -- Do not inline the package if the subprogram is an init proc |
512 -- or other internally generated subprogram, because in that | 633 -- or other internally generated subprogram, because in that |
513 -- case the subprogram body appears in the same unit that | 634 -- case the subprogram body appears in the same unit that |
514 -- declares the type, and that body is visible to the back end. | 635 -- declares the type, and that body is visible to the back end. |
515 -- Do not inline it either if it is in the main unit. | 636 -- Do not inline it either if it is in the main unit. |
516 -- Extend the -gnatn2 processing to -gnatn1 for Inline_Always | 637 -- Extend the -gnatn2 processing to -gnatn1 for Inline_Always |
517 -- calls if the back-end takes care of inlining the call. | 638 -- calls if the back end takes care of inlining the call. |
518 -- Note that Level in Inline_Package | Inline_Call here. | 639 -- Note that Level is in Inline_Call | Inline_Package here. |
519 | 640 |
520 elsif ((Level = Inline_Call | 641 elsif ((Level = Inline_Call |
521 and then Has_Pragma_Inline_Always (E) | 642 and then Has_Pragma_Inline_Always (E) |
522 and then Back_End_Inlining) | 643 and then Back_End_Inlining) |
523 or else Level = Inline_Package) | 644 or else Level = Inline_Package) |
536 | 657 |
537 Inline_Processing_Required := True; | 658 Inline_Processing_Required := True; |
538 end; | 659 end; |
539 end Add_Inlined_Body; | 660 end Add_Inlined_Body; |
540 | 661 |
662 -------------------------- | |
663 -- Add_Inlined_Instance -- | |
664 -------------------------- | |
665 | |
666 procedure Add_Inlined_Instance (E : Entity_Id) is | |
667 Decl_Node : constant Node_Id := Unit_Declaration_Node (E); | |
668 Index : Int; | |
669 | |
670 begin | |
671 -- This machinery is only used with back-end inlining | |
672 | |
673 if not Back_End_Inlining then | |
674 return; | |
675 end if; | |
676 | |
677 -- Register the instance in the list | |
678 | |
679 Append_New_Elmt (Decl_Node, To => Backend_Instances); | |
680 | |
681 -- Retrieve the index of its corresponding pending instantiation | |
682 -- and mark this corresponding pending instantiation as needed. | |
683 | |
684 Index := To_Pending_Instantiations.Get (Decl_Node); | |
685 if Index >= 0 then | |
686 Called_Pending_Instantiations.Append (Index); | |
687 else | |
688 pragma Assert (False); | |
689 null; | |
690 end if; | |
691 | |
692 Set_Is_Called (E); | |
693 end Add_Inlined_Instance; | |
694 | |
541 ---------------------------- | 695 ---------------------------- |
542 -- Add_Inlined_Subprogram -- | 696 -- Add_Inlined_Subprogram -- |
543 ---------------------------- | 697 ---------------------------- |
544 | 698 |
545 procedure Add_Inlined_Subprogram (E : Entity_Id) is | 699 procedure Add_Inlined_Subprogram (E : Entity_Id) is |
572 end Register_Backend_Not_Inlined_Subprogram; | 726 end Register_Backend_Not_Inlined_Subprogram; |
573 | 727 |
574 -- Start of processing for Add_Inlined_Subprogram | 728 -- Start of processing for Add_Inlined_Subprogram |
575 | 729 |
576 begin | 730 begin |
577 -- If the subprogram is to be inlined, and if its unit is known to be | 731 -- We can inline the subprogram if its unit is known to be inlined or is |
578 -- inlined or is an instance whose body will be analyzed anyway or the | 732 -- an instance whose body will be analyzed anyway or the subprogram was |
579 -- subprogram was generated as a body by the compiler (for example an | 733 -- generated as a body by the compiler (for example an initialization |
580 -- initialization procedure) or its declaration was provided along with | 734 -- procedure) or its declaration was provided along with the body (for |
581 -- the body (for example an expression function), and if it is declared | 735 -- example an expression function) and it does not declare types with |
582 -- at the library level not in the main unit, and if it can be inlined | 736 -- nontrivial initialization procedures. |
583 -- by the back-end, then insert it in the list of inlined subprograms. | 737 |
584 | 738 if (Is_Inlined (Pack) |
585 if Is_Inlined (E) | 739 or else Is_Generic_Instance (Pack) |
586 and then (Is_Inlined (Pack) | 740 or else Nkind (Decl) = N_Subprogram_Body |
587 or else Is_Generic_Instance (Pack) | 741 or else Present (Corresponding_Body (Decl))) |
588 or else Nkind (Decl) = N_Subprogram_Body | |
589 or else Present (Corresponding_Body (Decl))) | |
590 and then not In_Main_Unit_Or_Subunit (E) | |
591 and then not Is_Nested (E) | |
592 and then not Has_Initialized_Type (E) | 742 and then not Has_Initialized_Type (E) |
593 then | 743 then |
594 Register_Backend_Inlined_Subprogram (E); | 744 Register_Backend_Inlined_Subprogram (E); |
595 | 745 |
596 if No (Last_Inlined) then | 746 if No (Last_Inlined) then |
603 | 753 |
604 else | 754 else |
605 Register_Backend_Not_Inlined_Subprogram (E); | 755 Register_Backend_Not_Inlined_Subprogram (E); |
606 end if; | 756 end if; |
607 end Add_Inlined_Subprogram; | 757 end Add_Inlined_Subprogram; |
758 | |
759 -------------------------------- | |
760 -- Add_Pending_Instantiation -- | |
761 -------------------------------- | |
762 | |
763 procedure Add_Pending_Instantiation (Inst : Node_Id; Act_Decl : Node_Id) is | |
764 Act_Decl_Id : Entity_Id; | |
765 Index : Int; | |
766 | |
767 begin | |
768 -- Here is a defense against a ludicrous number of instantiations | |
769 -- caused by a circular set of instantiation attempts. | |
770 | |
771 if Pending_Instantiations.Last + 1 >= Maximum_Instantiations then | |
772 Error_Msg_Uint_1 := UI_From_Int (Maximum_Instantiations); | |
773 Error_Msg_N ("too many instantiations, exceeds max of^", Inst); | |
774 Error_Msg_N ("\limit can be changed using -gnateinn switch", Inst); | |
775 raise Unrecoverable_Error; | |
776 end if; | |
777 | |
778 -- Capture the body of the generic instantiation along with its context | |
779 -- for later processing by Instantiate_Bodies. | |
780 | |
781 Pending_Instantiations.Append | |
782 ((Act_Decl => Act_Decl, | |
783 Config_Switches => Save_Config_Switches, | |
784 Current_Sem_Unit => Current_Sem_Unit, | |
785 Expander_Status => Expander_Active, | |
786 Inst_Node => Inst, | |
787 Local_Suppress_Stack_Top => Local_Suppress_Stack_Top, | |
788 Scope_Suppress => Scope_Suppress, | |
789 Warnings => Save_Warnings)); | |
790 | |
791 -- With back-end inlining, also associate the index to the instantiation | |
792 | |
793 if Back_End_Inlining then | |
794 Act_Decl_Id := Defining_Entity (Act_Decl); | |
795 Index := Pending_Instantiations.Last; | |
796 | |
797 To_Pending_Instantiations.Set (Act_Decl, Index); | |
798 | |
799 -- If an instantiation is in the main unit or subunit, or is a nested | |
800 -- subprogram, then its body is needed as per the analysis done in | |
801 -- Analyze_Package_Instantiation & Analyze_Subprogram_Instantiation. | |
802 | |
803 if In_Main_Unit_Or_Subunit (Act_Decl_Id) | |
804 or else (Is_Subprogram (Act_Decl_Id) | |
805 and then Is_Nested (Act_Decl_Id)) | |
806 then | |
807 Called_Pending_Instantiations.Append (Index); | |
808 | |
809 Set_Is_Called (Act_Decl_Id); | |
810 end if; | |
811 end if; | |
812 end Add_Pending_Instantiation; | |
608 | 813 |
609 ------------------------ | 814 ------------------------ |
610 -- Add_Scope_To_Clean -- | 815 -- Add_Scope_To_Clean -- |
611 ------------------------ | 816 ------------------------ |
612 | 817 |
1286 | 1491 |
1287 function Can_Be_Inlined_In_GNATprove_Mode | 1492 function Can_Be_Inlined_In_GNATprove_Mode |
1288 (Spec_Id : Entity_Id; | 1493 (Spec_Id : Entity_Id; |
1289 Body_Id : Entity_Id) return Boolean | 1494 Body_Id : Entity_Id) return Boolean |
1290 is | 1495 is |
1496 function Has_Formal_Or_Result_Of_Deep_Type | |
1497 (Id : Entity_Id) return Boolean; | |
1498 -- Returns true if the subprogram has at least one formal parameter or | |
1499 -- a return type of a deep type: either an access type or a composite | |
1500 -- type containing an access type. | |
1501 | |
1291 function Has_Formal_With_Discriminant_Dependent_Fields | 1502 function Has_Formal_With_Discriminant_Dependent_Fields |
1292 (Id : Entity_Id) return Boolean; | 1503 (Id : Entity_Id) return Boolean; |
1293 -- Returns true if the subprogram has at least one formal parameter of | 1504 -- Returns true if the subprogram has at least one formal parameter of |
1294 -- an unconstrained record type with per-object constraints on component | 1505 -- an unconstrained record type with per-object constraints on component |
1295 -- types. | 1506 -- types. |
1304 -- Shouldn't this be in Sem_Aux??? | 1515 -- Shouldn't this be in Sem_Aux??? |
1305 | 1516 |
1306 function In_Package_Spec (Id : Entity_Id) return Boolean; | 1517 function In_Package_Spec (Id : Entity_Id) return Boolean; |
1307 -- Return True if subprogram Id is defined in the package specification, | 1518 -- Return True if subprogram Id is defined in the package specification, |
1308 -- either its visible or private part. | 1519 -- either its visible or private part. |
1520 | |
1521 function Maybe_Traversal_Function (Id : Entity_Id) return Boolean; | |
1522 -- Return True if subprogram Id could be a traversal function, as | |
1523 -- defined in SPARK RM 3.10. This is only a safe approximation, as the | |
1524 -- knowledge of the SPARK boundary is needed to determine exactly | |
1525 -- traversal functions. | |
1526 | |
1527 --------------------------------------- | |
1528 -- Has_Formal_Or_Result_Of_Deep_Type -- | |
1529 --------------------------------------- | |
1530 | |
1531 function Has_Formal_Or_Result_Of_Deep_Type | |
1532 (Id : Entity_Id) return Boolean | |
1533 is | |
1534 function Is_Deep (Typ : Entity_Id) return Boolean; | |
1535 -- Return True if Typ is deep: either an access type or a composite | |
1536 -- type containing an access type. | |
1537 | |
1538 ------------- | |
1539 -- Is_Deep -- | |
1540 ------------- | |
1541 | |
1542 function Is_Deep (Typ : Entity_Id) return Boolean is | |
1543 begin | |
1544 case Type_Kind'(Ekind (Typ)) is | |
1545 when Access_Kind => | |
1546 return True; | |
1547 | |
1548 when E_Array_Type | |
1549 | E_Array_Subtype | |
1550 => | |
1551 return Is_Deep (Component_Type (Typ)); | |
1552 | |
1553 when Record_Kind => | |
1554 declare | |
1555 Comp : Entity_Id := First_Component_Or_Discriminant (Typ); | |
1556 begin | |
1557 while Present (Comp) loop | |
1558 if Is_Deep (Etype (Comp)) then | |
1559 return True; | |
1560 end if; | |
1561 Next_Component_Or_Discriminant (Comp); | |
1562 end loop; | |
1563 end; | |
1564 return False; | |
1565 | |
1566 when Scalar_Kind | |
1567 | E_String_Literal_Subtype | |
1568 | Concurrent_Kind | |
1569 | Incomplete_Kind | |
1570 | E_Exception_Type | |
1571 | E_Subprogram_Type | |
1572 => | |
1573 return False; | |
1574 | |
1575 when E_Private_Type | |
1576 | E_Private_Subtype | |
1577 | E_Limited_Private_Type | |
1578 | E_Limited_Private_Subtype | |
1579 => | |
1580 -- Conservatively consider that the type might be deep if | |
1581 -- its completion has not been seen yet. | |
1582 | |
1583 if No (Underlying_Type (Typ)) then | |
1584 return True; | |
1585 | |
1586 -- Do not peek under a private type if its completion has | |
1587 -- SPARK_Mode Off. In such a case, a deep type is considered | |
1588 -- by GNATprove to be not deep. | |
1589 | |
1590 elsif Present (Full_View (Typ)) | |
1591 and then Present (SPARK_Pragma (Full_View (Typ))) | |
1592 and then Get_SPARK_Mode_From_Annotation | |
1593 (SPARK_Pragma (Full_View (Typ))) = Off | |
1594 then | |
1595 return False; | |
1596 | |
1597 -- Otherwise peek under the private type. | |
1598 | |
1599 else | |
1600 return Is_Deep (Underlying_Type (Typ)); | |
1601 end if; | |
1602 end case; | |
1603 end Is_Deep; | |
1604 | |
1605 -- Local variables | |
1606 | |
1607 Subp_Id : constant Entity_Id := Ultimate_Alias (Id); | |
1608 Formal : Entity_Id; | |
1609 Formal_Typ : Entity_Id; | |
1610 | |
1611 -- Start of processing for Has_Formal_Or_Result_Of_Deep_Type | |
1612 | |
1613 begin | |
1614 -- Inspect all parameters of the subprogram looking for a formal | |
1615 -- of a deep type. | |
1616 | |
1617 Formal := First_Formal (Subp_Id); | |
1618 while Present (Formal) loop | |
1619 Formal_Typ := Etype (Formal); | |
1620 | |
1621 if Is_Deep (Formal_Typ) then | |
1622 return True; | |
1623 end if; | |
1624 | |
1625 Next_Formal (Formal); | |
1626 end loop; | |
1627 | |
1628 -- Check whether this is a function whose return type is deep | |
1629 | |
1630 if Ekind (Subp_Id) = E_Function | |
1631 and then Is_Deep (Etype (Subp_Id)) | |
1632 then | |
1633 return True; | |
1634 end if; | |
1635 | |
1636 return False; | |
1637 end Has_Formal_Or_Result_Of_Deep_Type; | |
1309 | 1638 |
1310 --------------------------------------------------- | 1639 --------------------------------------------------- |
1311 -- Has_Formal_With_Discriminant_Dependent_Fields -- | 1640 -- Has_Formal_With_Discriminant_Dependent_Fields -- |
1312 --------------------------------------------------- | 1641 --------------------------------------------------- |
1313 | 1642 |
1428 end if; | 1757 end if; |
1429 | 1758 |
1430 return Nkind (Parent (Decl)) = N_Compilation_Unit; | 1759 return Nkind (Parent (Decl)) = N_Compilation_Unit; |
1431 end Is_Unit_Subprogram; | 1760 end Is_Unit_Subprogram; |
1432 | 1761 |
1762 ------------------------------ | |
1763 -- Maybe_Traversal_Function -- | |
1764 ------------------------------ | |
1765 | |
1766 function Maybe_Traversal_Function (Id : Entity_Id) return Boolean is | |
1767 begin | |
1768 return Ekind (Id) = E_Function | |
1769 | |
1770 -- Only traversal functions return an anonymous access-to-object | |
1771 -- type in SPARK. | |
1772 | |
1773 and then Is_Anonymous_Access_Type (Etype (Id)); | |
1774 end Maybe_Traversal_Function; | |
1775 | |
1433 -- Local declarations | 1776 -- Local declarations |
1434 | 1777 |
1435 Id : Entity_Id; | 1778 Id : Entity_Id; |
1436 -- Procedure or function entity for the subprogram | 1779 -- Procedure or function entity for the subprogram |
1437 | 1780 |
1472 -- package spec, when analyzing one of its child packages, as otherwise | 1815 -- package spec, when analyzing one of its child packages, as otherwise |
1473 -- we issue spurious messages about the impossibility to inline such | 1816 -- we issue spurious messages about the impossibility to inline such |
1474 -- calls. | 1817 -- calls. |
1475 | 1818 |
1476 elsif not In_Extended_Main_Code_Unit (Id) then | 1819 elsif not In_Extended_Main_Code_Unit (Id) then |
1820 return False; | |
1821 | |
1822 -- Do not inline dispatching operations, as only their static calls | |
1823 -- can be analyzed in context, and not their dispatching calls. | |
1824 | |
1825 elsif Is_Dispatching_Operation (Id) then | |
1477 return False; | 1826 return False; |
1478 | 1827 |
1479 -- Do not inline subprograms marked No_Return, possibly used for | 1828 -- Do not inline subprograms marked No_Return, possibly used for |
1480 -- signaling errors, which GNATprove handles specially. | 1829 -- signaling errors, which GNATprove handles specially. |
1481 | 1830 |
1542 -- such parameters, the frontend cannot always ensure type compliance | 1891 -- such parameters, the frontend cannot always ensure type compliance |
1543 -- in record component accesses (in particular with records containing | 1892 -- in record component accesses (in particular with records containing |
1544 -- packed arrays). | 1893 -- packed arrays). |
1545 | 1894 |
1546 elsif Has_Formal_With_Discriminant_Dependent_Fields (Id) then | 1895 elsif Has_Formal_With_Discriminant_Dependent_Fields (Id) then |
1896 return False; | |
1897 | |
1898 -- Do not inline subprograms with a formal parameter or return type of | |
1899 -- a deep type, as in that case inlining might generate code that | |
1900 -- violates borrow-checking rules of SPARK 3.10 even if the original | |
1901 -- code did not. | |
1902 | |
1903 elsif Has_Formal_Or_Result_Of_Deep_Type (Id) then | |
1904 return False; | |
1905 | |
1906 -- Do not inline subprograms which may be traversal functions. Such | |
1907 -- inlining introduces temporary variables of named access type for | |
1908 -- which assignments are move instead of borrow/observe, possibly | |
1909 -- leading to spurious errors when checking SPARK rules related to | |
1910 -- pointer usage. | |
1911 | |
1912 elsif Maybe_Traversal_Function (Id) then | |
1547 return False; | 1913 return False; |
1548 | 1914 |
1549 -- Otherwise, this is a subprogram declared inside the private part of a | 1915 -- Otherwise, this is a subprogram declared inside the private part of a |
1550 -- package, or inside a package body, or locally in a subprogram, and it | 1916 -- package, or inside a package body, or locally in a subprogram, and it |
1551 -- does not have any contract. Inline it. | 1917 -- does not have any contract. Inline it. |
1704 is | 2070 is |
1705 procedure Build_Body_To_Inline (N : Node_Id; Spec_Id : Entity_Id); | 2071 procedure Build_Body_To_Inline (N : Node_Id; Spec_Id : Entity_Id); |
1706 -- Use generic machinery to build an unexpanded body for the subprogram. | 2072 -- Use generic machinery to build an unexpanded body for the subprogram. |
1707 -- This body is subsequently used for inline expansions at call sites. | 2073 -- This body is subsequently used for inline expansions at call sites. |
1708 | 2074 |
2075 procedure Build_Return_Object_Formal | |
2076 (Loc : Source_Ptr; | |
2077 Obj_Decl : Node_Id; | |
2078 Formals : List_Id); | |
2079 -- Create a formal parameter for return object declaration Obj_Decl of | |
2080 -- an extended return statement and add it to list Formals. | |
2081 | |
1709 function Can_Split_Unconstrained_Function (N : Node_Id) return Boolean; | 2082 function Can_Split_Unconstrained_Function (N : Node_Id) return Boolean; |
1710 -- Return true if we generate code for the function body N, the function | 2083 -- Return true if we generate code for the function body N, the function |
1711 -- body N has no local declarations and its unique statement is a single | 2084 -- body N has no local declarations and its unique statement is a single |
1712 -- extended return statement with a handled statements sequence. | 2085 -- extended return statement with a handled statements sequence. |
2086 | |
2087 procedure Copy_Formals | |
2088 (Loc : Source_Ptr; | |
2089 Subp_Id : Entity_Id; | |
2090 Formals : List_Id); | |
2091 -- Create new formal parameters from the formal parameters of subprogram | |
2092 -- Subp_Id and add them to list Formals. | |
2093 | |
2094 function Copy_Return_Object (Obj_Decl : Node_Id) return Node_Id; | |
2095 -- Create a copy of return object declaration Obj_Decl of an extended | |
2096 -- return statement. | |
1713 | 2097 |
1714 procedure Split_Unconstrained_Function | 2098 procedure Split_Unconstrained_Function |
1715 (N : Node_Id; | 2099 (N : Node_Id; |
1716 Spec_Id : Entity_Id); | 2100 Spec_Id : Entity_Id); |
1717 -- N is an inlined function body that returns an unconstrained type and | 2101 -- N is an inlined function body that returns an unconstrained type and |
1731 Body_To_Inline : out Node_Id); | 2115 Body_To_Inline : out Node_Id); |
1732 -- Generate a parameterless duplicate of subprogram body N. Note that | 2116 -- Generate a parameterless duplicate of subprogram body N. Note that |
1733 -- occurrences of pragmas referencing the formals are removed since | 2117 -- occurrences of pragmas referencing the formals are removed since |
1734 -- they have no meaning when the body is inlined and the formals are | 2118 -- they have no meaning when the body is inlined and the formals are |
1735 -- rewritten (the analysis of the non-inlined body will handle these | 2119 -- rewritten (the analysis of the non-inlined body will handle these |
1736 -- pragmas). A new internal name is associated with Body_To_Inline. | 2120 -- pragmas). A new internal name is associated with Body_To_Inline. |
1737 | 2121 |
1738 ------------------------------ | 2122 ------------------------------ |
1739 -- Generate_Subprogram_Body -- | 2123 -- Generate_Subprogram_Body -- |
1740 ------------------------------ | 2124 ------------------------------ |
1741 | 2125 |
1755 and then Scope (Current_Scope) /= Standard_Standard | 2139 and then Scope (Current_Scope) /= Standard_Standard |
1756 then | 2140 then |
1757 Body_To_Inline := | 2141 Body_To_Inline := |
1758 Copy_Generic_Node (N, Empty, Instantiating => True); | 2142 Copy_Generic_Node (N, Empty, Instantiating => True); |
1759 else | 2143 else |
2144 -- ??? Shouldn't this use New_Copy_Tree? What about global | |
2145 -- references captured in the body to inline? | |
2146 | |
1760 Body_To_Inline := Copy_Separate_Tree (N); | 2147 Body_To_Inline := Copy_Separate_Tree (N); |
1761 end if; | 2148 end if; |
1762 | 2149 |
1763 -- Remove aspects/pragmas that have no meaning in an inlined body | 2150 -- Remove aspects/pragmas that have no meaning in an inlined body |
1764 | 2151 |
1785 | 2172 |
1786 Decl : constant Node_Id := Unit_Declaration_Node (Spec_Id); | 2173 Decl : constant Node_Id := Unit_Declaration_Node (Spec_Id); |
1787 Original_Body : Node_Id; | 2174 Original_Body : Node_Id; |
1788 Body_To_Analyze : Node_Id; | 2175 Body_To_Analyze : Node_Id; |
1789 | 2176 |
2177 -- Start of processing for Build_Body_To_Inline | |
2178 | |
1790 begin | 2179 begin |
1791 pragma Assert (Current_Scope = Spec_Id); | 2180 pragma Assert (Current_Scope = Spec_Id); |
1792 | 2181 |
1793 -- Within an instance, the body to inline must be treated as a nested | 2182 -- Within an instance, the body to inline must be treated as a nested |
1794 -- generic, so that the proper global references are preserved. We | 2183 -- generic, so that the proper global references are preserved. We |
1843 pragma Assert (No (Body_To_Inline (Decl))); | 2232 pragma Assert (No (Body_To_Inline (Decl))); |
1844 Set_Body_To_Inline (Decl, Original_Body); | 2233 Set_Body_To_Inline (Decl, Original_Body); |
1845 Set_Ekind (Defining_Entity (Original_Body), Ekind (Spec_Id)); | 2234 Set_Ekind (Defining_Entity (Original_Body), Ekind (Spec_Id)); |
1846 end Build_Body_To_Inline; | 2235 end Build_Body_To_Inline; |
1847 | 2236 |
2237 -------------------------------- | |
2238 -- Build_Return_Object_Formal -- | |
2239 -------------------------------- | |
2240 | |
2241 procedure Build_Return_Object_Formal | |
2242 (Loc : Source_Ptr; | |
2243 Obj_Decl : Node_Id; | |
2244 Formals : List_Id) | |
2245 is | |
2246 Obj_Def : constant Node_Id := Object_Definition (Obj_Decl); | |
2247 Obj_Id : constant Entity_Id := Defining_Entity (Obj_Decl); | |
2248 Typ_Def : Node_Id; | |
2249 | |
2250 begin | |
2251 -- Build the type definition of the formal parameter. The use of | |
2252 -- New_Copy_Tree ensures that global references preserved in the | |
2253 -- case of generics. | |
2254 | |
2255 if Is_Entity_Name (Obj_Def) then | |
2256 Typ_Def := New_Copy_Tree (Obj_Def); | |
2257 else | |
2258 Typ_Def := New_Copy_Tree (Subtype_Mark (Obj_Def)); | |
2259 end if; | |
2260 | |
2261 -- Generate: | |
2262 -- | |
2263 -- Obj_Id : [out] Typ_Def | |
2264 | |
2265 -- Mode OUT should not be used when the return object is declared as | |
2266 -- a constant. Check the definition of the object declaration because | |
2267 -- the object has not been analyzed yet. | |
2268 | |
2269 Append_To (Formals, | |
2270 Make_Parameter_Specification (Loc, | |
2271 Defining_Identifier => | |
2272 Make_Defining_Identifier (Loc, Chars (Obj_Id)), | |
2273 In_Present => False, | |
2274 Out_Present => not Constant_Present (Obj_Decl), | |
2275 Null_Exclusion_Present => False, | |
2276 Parameter_Type => Typ_Def)); | |
2277 end Build_Return_Object_Formal; | |
2278 | |
1848 -------------------------------------- | 2279 -------------------------------------- |
1849 -- Can_Split_Unconstrained_Function -- | 2280 -- Can_Split_Unconstrained_Function -- |
1850 -------------------------------------- | 2281 -------------------------------------- |
1851 | 2282 |
1852 function Can_Split_Unconstrained_Function (N : Node_Id) return Boolean is | 2283 function Can_Split_Unconstrained_Function (N : Node_Id) return Boolean is |
1853 Ret_Node : constant Node_Id := | 2284 Stmt : constant Node_Id := |
1854 First (Statements (Handled_Statement_Sequence (N))); | 2285 First (Statements (Handled_Statement_Sequence (N))); |
1855 D : Node_Id; | 2286 Decl : Node_Id; |
1856 | 2287 |
1857 begin | 2288 begin |
1858 -- No user defined declarations allowed in the function except inside | 2289 -- No user defined declarations allowed in the function except inside |
1859 -- the unique return statement; implicit labels are the only allowed | 2290 -- the unique return statement; implicit labels are the only allowed |
1860 -- declarations. | 2291 -- declarations. |
1861 | 2292 |
1862 if not Is_Empty_List (Declarations (N)) then | 2293 Decl := First (Declarations (N)); |
1863 D := First (Declarations (N)); | 2294 while Present (Decl) loop |
1864 while Present (D) loop | 2295 if Nkind (Decl) /= N_Implicit_Label_Declaration then |
1865 if Nkind (D) /= N_Implicit_Label_Declaration then | 2296 return False; |
1866 return False; | 2297 end if; |
1867 end if; | 2298 |
1868 | 2299 Next (Decl); |
1869 Next (D); | 2300 end loop; |
1870 end loop; | |
1871 end if; | |
1872 | 2301 |
1873 -- We only split the inlined function when we are generating the code | 2302 -- We only split the inlined function when we are generating the code |
1874 -- of its body; otherwise we leave duplicated split subprograms in | 2303 -- of its body; otherwise we leave duplicated split subprograms in |
1875 -- the tree which (if referenced) generate wrong references at link | 2304 -- the tree which (if referenced) generate wrong references at link |
1876 -- time. | 2305 -- time. |
1877 | 2306 |
1878 return In_Extended_Main_Code_Unit (N) | 2307 return In_Extended_Main_Code_Unit (N) |
1879 and then Present (Ret_Node) | 2308 and then Present (Stmt) |
1880 and then Nkind (Ret_Node) = N_Extended_Return_Statement | 2309 and then Nkind (Stmt) = N_Extended_Return_Statement |
1881 and then No (Next (Ret_Node)) | 2310 and then No (Next (Stmt)) |
1882 and then Present (Handled_Statement_Sequence (Ret_Node)); | 2311 and then Present (Handled_Statement_Sequence (Stmt)); |
1883 end Can_Split_Unconstrained_Function; | 2312 end Can_Split_Unconstrained_Function; |
2313 | |
2314 ------------------ | |
2315 -- Copy_Formals -- | |
2316 ------------------ | |
2317 | |
2318 procedure Copy_Formals | |
2319 (Loc : Source_Ptr; | |
2320 Subp_Id : Entity_Id; | |
2321 Formals : List_Id) | |
2322 is | |
2323 Formal : Entity_Id; | |
2324 Spec : Node_Id; | |
2325 | |
2326 begin | |
2327 Formal := First_Formal (Subp_Id); | |
2328 while Present (Formal) loop | |
2329 Spec := Parent (Formal); | |
2330 | |
2331 -- Create an exact copy of the formal parameter. The use of | |
2332 -- New_Copy_Tree ensures that global references are preserved | |
2333 -- in case of generics. | |
2334 | |
2335 Append_To (Formals, | |
2336 Make_Parameter_Specification (Loc, | |
2337 Defining_Identifier => | |
2338 Make_Defining_Identifier (Sloc (Formal), Chars (Formal)), | |
2339 In_Present => In_Present (Spec), | |
2340 Out_Present => Out_Present (Spec), | |
2341 Null_Exclusion_Present => Null_Exclusion_Present (Spec), | |
2342 Parameter_Type => | |
2343 New_Copy_Tree (Parameter_Type (Spec)), | |
2344 Expression => New_Copy_Tree (Expression (Spec)))); | |
2345 | |
2346 Next_Formal (Formal); | |
2347 end loop; | |
2348 end Copy_Formals; | |
2349 | |
2350 ------------------------ | |
2351 -- Copy_Return_Object -- | |
2352 ------------------------ | |
2353 | |
2354 function Copy_Return_Object (Obj_Decl : Node_Id) return Node_Id is | |
2355 Obj_Id : constant Entity_Id := Defining_Entity (Obj_Decl); | |
2356 | |
2357 begin | |
2358 -- The use of New_Copy_Tree ensures that global references are | |
2359 -- preserved in case of generics. | |
2360 | |
2361 return | |
2362 Make_Object_Declaration (Sloc (Obj_Decl), | |
2363 Defining_Identifier => | |
2364 Make_Defining_Identifier (Sloc (Obj_Id), Chars (Obj_Id)), | |
2365 Aliased_Present => Aliased_Present (Obj_Decl), | |
2366 Constant_Present => Constant_Present (Obj_Decl), | |
2367 Null_Exclusion_Present => Null_Exclusion_Present (Obj_Decl), | |
2368 Object_Definition => | |
2369 New_Copy_Tree (Object_Definition (Obj_Decl)), | |
2370 Expression => New_Copy_Tree (Expression (Obj_Decl))); | |
2371 end Copy_Return_Object; | |
1884 | 2372 |
1885 ---------------------------------- | 2373 ---------------------------------- |
1886 -- Split_Unconstrained_Function -- | 2374 -- Split_Unconstrained_Function -- |
1887 ---------------------------------- | 2375 ---------------------------------- |
1888 | 2376 |
1889 procedure Split_Unconstrained_Function | 2377 procedure Split_Unconstrained_Function |
1890 (N : Node_Id; | 2378 (N : Node_Id; |
1891 Spec_Id : Entity_Id) | 2379 Spec_Id : Entity_Id) |
1892 is | 2380 is |
1893 Loc : constant Source_Ptr := Sloc (N); | 2381 Loc : constant Source_Ptr := Sloc (N); |
1894 Ret_Node : constant Node_Id := | 2382 Ret_Stmt : constant Node_Id := |
1895 First (Statements (Handled_Statement_Sequence (N))); | 2383 First (Statements (Handled_Statement_Sequence (N))); |
1896 Ret_Obj : constant Node_Id := | 2384 Ret_Obj : constant Node_Id := |
1897 First (Return_Object_Declarations (Ret_Node)); | 2385 First (Return_Object_Declarations (Ret_Stmt)); |
1898 | 2386 |
1899 procedure Build_Procedure | 2387 procedure Build_Procedure |
1900 (Proc_Id : out Entity_Id; | 2388 (Proc_Id : out Entity_Id; |
1901 Decl_List : out List_Id); | 2389 Decl_List : out List_Id); |
1902 -- Build a procedure containing the statements found in the extended | 2390 -- Build a procedure containing the statements found in the extended |
1908 | 2396 |
1909 procedure Build_Procedure | 2397 procedure Build_Procedure |
1910 (Proc_Id : out Entity_Id; | 2398 (Proc_Id : out Entity_Id; |
1911 Decl_List : out List_Id) | 2399 Decl_List : out List_Id) |
1912 is | 2400 is |
1913 Formal : Entity_Id; | 2401 Formals : constant List_Id := New_List; |
1914 Formal_List : constant List_Id := New_List; | 2402 Subp_Name : constant Name_Id := New_Internal_Name ('F'); |
1915 Proc_Spec : Node_Id; | 2403 |
1916 Proc_Body : Node_Id; | 2404 Body_Decls : List_Id := No_List; |
1917 Subp_Name : constant Name_Id := New_Internal_Name ('F'); | 2405 Decl : Node_Id; |
1918 Body_Decl_List : List_Id := No_List; | 2406 Proc_Body : Node_Id; |
1919 Param_Type : Node_Id; | 2407 Proc_Spec : Node_Id; |
1920 | 2408 |
1921 begin | 2409 begin |
1922 if Nkind (Object_Definition (Ret_Obj)) = N_Identifier then | 2410 -- Create formal parameters for the return object and all formals |
1923 Param_Type := | 2411 -- of the unconstrained function in order to pass their values to |
1924 New_Copy (Object_Definition (Ret_Obj)); | 2412 -- the procedure. |
1925 else | 2413 |
1926 Param_Type := | 2414 Build_Return_Object_Formal |
1927 New_Copy (Subtype_Mark (Object_Definition (Ret_Obj))); | 2415 (Loc => Loc, |
1928 end if; | 2416 Obj_Decl => Ret_Obj, |
1929 | 2417 Formals => Formals); |
1930 Append_To (Formal_List, | 2418 |
1931 Make_Parameter_Specification (Loc, | 2419 Copy_Formals |
1932 Defining_Identifier => | 2420 (Loc => Loc, |
1933 Make_Defining_Identifier (Loc, | 2421 Subp_Id => Spec_Id, |
1934 Chars => Chars (Defining_Identifier (Ret_Obj))), | 2422 Formals => Formals); |
1935 In_Present => False, | |
1936 Out_Present => True, | |
1937 Null_Exclusion_Present => False, | |
1938 Parameter_Type => Param_Type)); | |
1939 | |
1940 Formal := First_Formal (Spec_Id); | |
1941 | |
1942 -- Note that we copy the parameter type rather than creating | |
1943 -- a reference to it, because it may be a class-wide entity | |
1944 -- that will not be retrieved by name. | |
1945 | |
1946 while Present (Formal) loop | |
1947 Append_To (Formal_List, | |
1948 Make_Parameter_Specification (Loc, | |
1949 Defining_Identifier => | |
1950 Make_Defining_Identifier (Sloc (Formal), | |
1951 Chars => Chars (Formal)), | |
1952 In_Present => In_Present (Parent (Formal)), | |
1953 Out_Present => Out_Present (Parent (Formal)), | |
1954 Null_Exclusion_Present => | |
1955 Null_Exclusion_Present (Parent (Formal)), | |
1956 Parameter_Type => | |
1957 New_Copy_Tree (Parameter_Type (Parent (Formal))), | |
1958 Expression => | |
1959 Copy_Separate_Tree (Expression (Parent (Formal))))); | |
1960 | |
1961 Next_Formal (Formal); | |
1962 end loop; | |
1963 | 2423 |
1964 Proc_Id := Make_Defining_Identifier (Loc, Chars => Subp_Name); | 2424 Proc_Id := Make_Defining_Identifier (Loc, Chars => Subp_Name); |
1965 | 2425 |
1966 Proc_Spec := | 2426 Proc_Spec := |
1967 Make_Procedure_Specification (Loc, | 2427 Make_Procedure_Specification (Loc, |
1968 Defining_Unit_Name => Proc_Id, | 2428 Defining_Unit_Name => Proc_Id, |
1969 Parameter_Specifications => Formal_List); | 2429 Parameter_Specifications => Formals); |
1970 | 2430 |
1971 Decl_List := New_List; | 2431 Decl_List := New_List; |
1972 | 2432 |
1973 Append_To (Decl_List, | 2433 Append_To (Decl_List, |
1974 Make_Subprogram_Declaration (Loc, Proc_Spec)); | 2434 Make_Subprogram_Declaration (Loc, Proc_Spec)); |
1976 -- Can_Convert_Unconstrained_Function checked that the function | 2436 -- Can_Convert_Unconstrained_Function checked that the function |
1977 -- has no local declarations except implicit label declarations. | 2437 -- has no local declarations except implicit label declarations. |
1978 -- Copy these declarations to the built procedure. | 2438 -- Copy these declarations to the built procedure. |
1979 | 2439 |
1980 if Present (Declarations (N)) then | 2440 if Present (Declarations (N)) then |
1981 Body_Decl_List := New_List; | 2441 Body_Decls := New_List; |
1982 | 2442 |
1983 declare | 2443 Decl := First (Declarations (N)); |
1984 D : Node_Id; | 2444 while Present (Decl) loop |
1985 New_D : Node_Id; | 2445 pragma Assert (Nkind (Decl) = N_Implicit_Label_Declaration); |
1986 | 2446 |
1987 begin | 2447 Append_To (Body_Decls, |
1988 D := First (Declarations (N)); | 2448 Make_Implicit_Label_Declaration (Loc, |
1989 while Present (D) loop | 2449 Make_Defining_Identifier (Loc, |
1990 pragma Assert (Nkind (D) = N_Implicit_Label_Declaration); | 2450 Chars => Chars (Defining_Identifier (Decl))), |
1991 | 2451 Label_Construct => Empty)); |
1992 New_D := | 2452 |
1993 Make_Implicit_Label_Declaration (Loc, | 2453 Next (Decl); |
1994 Make_Defining_Identifier (Loc, | 2454 end loop; |
1995 Chars => Chars (Defining_Identifier (D))), | 2455 end if; |
1996 Label_Construct => Empty); | 2456 |
1997 Append_To (Body_Decl_List, New_D); | 2457 pragma Assert (Present (Handled_Statement_Sequence (Ret_Stmt))); |
1998 | |
1999 Next (D); | |
2000 end loop; | |
2001 end; | |
2002 end if; | |
2003 | |
2004 pragma Assert (Present (Handled_Statement_Sequence (Ret_Node))); | |
2005 | 2458 |
2006 Proc_Body := | 2459 Proc_Body := |
2007 Make_Subprogram_Body (Loc, | 2460 Make_Subprogram_Body (Loc, |
2008 Specification => Copy_Separate_Tree (Proc_Spec), | 2461 Specification => Copy_Subprogram_Spec (Proc_Spec), |
2009 Declarations => Body_Decl_List, | 2462 Declarations => Body_Decls, |
2010 Handled_Statement_Sequence => | 2463 Handled_Statement_Sequence => |
2011 Copy_Separate_Tree (Handled_Statement_Sequence (Ret_Node))); | 2464 New_Copy_Tree (Handled_Statement_Sequence (Ret_Stmt))); |
2012 | 2465 |
2013 Set_Defining_Unit_Name (Specification (Proc_Body), | 2466 Set_Defining_Unit_Name (Specification (Proc_Body), |
2014 Make_Defining_Identifier (Loc, Subp_Name)); | 2467 Make_Defining_Identifier (Loc, Subp_Name)); |
2015 | 2468 |
2016 Append_To (Decl_List, Proc_Body); | 2469 Append_To (Decl_List, Proc_Body); |
2017 end Build_Procedure; | 2470 end Build_Procedure; |
2018 | 2471 |
2019 -- Local variables | 2472 -- Local variables |
2020 | 2473 |
2021 New_Obj : constant Node_Id := Copy_Separate_Tree (Ret_Obj); | 2474 New_Obj : constant Node_Id := Copy_Return_Object (Ret_Obj); |
2022 Blk_Stmt : Node_Id; | 2475 Blk_Stmt : Node_Id; |
2476 Proc_Call : Node_Id; | |
2023 Proc_Id : Entity_Id; | 2477 Proc_Id : Entity_Id; |
2024 Proc_Call : Node_Id; | |
2025 | 2478 |
2026 -- Start of processing for Split_Unconstrained_Function | 2479 -- Start of processing for Split_Unconstrained_Function |
2027 | 2480 |
2028 begin | 2481 begin |
2029 -- Build the associated procedure, analyze it and insert it before | 2482 -- Build the associated procedure, analyze it and insert it before |
2087 Make_Simple_Return_Statement (Loc, | 2540 Make_Simple_Return_Statement (Loc, |
2088 Expression => | 2541 Expression => |
2089 New_Occurrence_Of | 2542 New_Occurrence_Of |
2090 (Defining_Identifier (New_Obj), Loc))))); | 2543 (Defining_Identifier (New_Obj), Loc))))); |
2091 | 2544 |
2092 Rewrite (Ret_Node, Blk_Stmt); | 2545 Rewrite (Ret_Stmt, Blk_Stmt); |
2093 end Split_Unconstrained_Function; | 2546 end Split_Unconstrained_Function; |
2094 | 2547 |
2095 -- Local variables | 2548 -- Local variables |
2096 | 2549 |
2097 Decl : constant Node_Id := Unit_Declaration_Node (Spec_Id); | 2550 Decl : constant Node_Id := Unit_Declaration_Node (Spec_Id); |
2126 -- Cannot build the body to inline if the attribute is already set. | 2579 -- Cannot build the body to inline if the attribute is already set. |
2127 -- This attribute may have been set if this is a subprogram renaming | 2580 -- This attribute may have been set if this is a subprogram renaming |
2128 -- declarations (see Freeze.Build_Renamed_Body). | 2581 -- declarations (see Freeze.Build_Renamed_Body). |
2129 | 2582 |
2130 elsif Present (Body_To_Inline (Decl)) then | 2583 elsif Present (Body_To_Inline (Decl)) then |
2584 return; | |
2585 | |
2586 -- Do not generate a body to inline for protected functions, because the | |
2587 -- transformation generates a call to a protected procedure, causing | |
2588 -- spurious errors. We don't inline protected operations anyway, so | |
2589 -- this is no loss. We might as well ignore intrinsics and foreign | |
2590 -- conventions as well -- just allow Ada conventions. | |
2591 | |
2592 elsif not (Convention (Spec_Id) = Convention_Ada | |
2593 or else Convention (Spec_Id) = Convention_Ada_Pass_By_Copy | |
2594 or else Convention (Spec_Id) = Convention_Ada_Pass_By_Reference) | |
2595 then | |
2131 return; | 2596 return; |
2132 | 2597 |
2133 -- Check excluded declarations | 2598 -- Check excluded declarations |
2134 | 2599 |
2135 elsif Present (Declarations (N)) | 2600 elsif Present (Declarations (N)) |
2384 procedure Make_Exit_Label; | 2849 procedure Make_Exit_Label; |
2385 -- Build declaration for exit label to be used in Return statements, | 2850 -- Build declaration for exit label to be used in Return statements, |
2386 -- sets Exit_Lab (the label node) and Lab_Decl (corresponding implicit | 2851 -- sets Exit_Lab (the label node) and Lab_Decl (corresponding implicit |
2387 -- declaration). Does nothing if Exit_Lab already set. | 2852 -- declaration). Does nothing if Exit_Lab already set. |
2388 | 2853 |
2854 procedure Make_Loop_Labels_Unique (HSS : Node_Id); | |
2855 -- When compiling for CCG and performing front-end inlining, replace | |
2856 -- loop names and references to them so that they do not conflict with | |
2857 -- homographs in the current subprogram. | |
2858 | |
2389 function Process_Formals (N : Node_Id) return Traverse_Result; | 2859 function Process_Formals (N : Node_Id) return Traverse_Result; |
2390 -- Replace occurrence of a formal with the corresponding actual, or the | 2860 -- Replace occurrence of a formal with the corresponding actual, or the |
2391 -- thunk generated for it. Replace a return statement with an assignment | 2861 -- thunk generated for it. Replace a return statement with an assignment |
2392 -- to the target of the call, with appropriate conversions if needed. | 2862 -- to the target of the call, with appropriate conversions if needed. |
2863 | |
2864 function Process_Formals_In_Aspects (N : Node_Id) return Traverse_Result; | |
2865 -- Because aspects are linked indirectly to the rest of the tree, | |
2866 -- replacement of formals appearing in aspect specifications must | |
2867 -- be performed in a separate pass, using an instantiation of the | |
2868 -- previous subprogram over aspect specifications reachable from N. | |
2393 | 2869 |
2394 function Process_Sloc (Nod : Node_Id) return Traverse_Result; | 2870 function Process_Sloc (Nod : Node_Id) return Traverse_Result; |
2395 -- If the call being expanded is that of an internal subprogram, set the | 2871 -- If the call being expanded is that of an internal subprogram, set the |
2396 -- sloc of the generated block to that of the call itself, so that the | 2872 -- sloc of the generated block to that of the call itself, so that the |
2397 -- expansion is skipped by the "next" command in gdb. Same processing | 2873 -- expansion is skipped by the "next" command in gdb. Same processing |
2472 Defining_Identifier => Lab_Ent, | 2948 Defining_Identifier => Lab_Ent, |
2473 Label_Construct => Exit_Lab); | 2949 Label_Construct => Exit_Lab); |
2474 end if; | 2950 end if; |
2475 end Make_Exit_Label; | 2951 end Make_Exit_Label; |
2476 | 2952 |
2953 ----------------------------- | |
2954 -- Make_Loop_Labels_Unique -- | |
2955 ----------------------------- | |
2956 | |
2957 procedure Make_Loop_Labels_Unique (HSS : Node_Id) is | |
2958 function Process_Loop (N : Node_Id) return Traverse_Result; | |
2959 | |
2960 ------------------ | |
2961 -- Process_Loop -- | |
2962 ------------------ | |
2963 | |
2964 function Process_Loop (N : Node_Id) return Traverse_Result is | |
2965 Id : Entity_Id; | |
2966 | |
2967 begin | |
2968 if Nkind (N) = N_Loop_Statement | |
2969 and then Present (Identifier (N)) | |
2970 then | |
2971 -- Create new external name for loop and update the | |
2972 -- corresponding entity. | |
2973 | |
2974 Id := Entity (Identifier (N)); | |
2975 Set_Chars (Id, New_External_Name (Chars (Id), 'L', -1)); | |
2976 Set_Chars (Identifier (N), Chars (Id)); | |
2977 | |
2978 elsif Nkind (N) = N_Exit_Statement | |
2979 and then Present (Name (N)) | |
2980 then | |
2981 -- The exit statement must name an enclosing loop, whose name | |
2982 -- has already been updated. | |
2983 | |
2984 Set_Chars (Name (N), Chars (Entity (Name (N)))); | |
2985 end if; | |
2986 | |
2987 return OK; | |
2988 end Process_Loop; | |
2989 | |
2990 procedure Update_Loop_Names is new Traverse_Proc (Process_Loop); | |
2991 | |
2992 -- Local variables | |
2993 | |
2994 Stmt : Node_Id; | |
2995 | |
2996 -- Start of processing for Make_Loop_Labels_Unique | |
2997 | |
2998 begin | |
2999 if Modify_Tree_For_C then | |
3000 Stmt := First (Statements (HSS)); | |
3001 while Present (Stmt) loop | |
3002 Update_Loop_Names (Stmt); | |
3003 Next (Stmt); | |
3004 end loop; | |
3005 end if; | |
3006 end Make_Loop_Labels_Unique; | |
3007 | |
2477 --------------------- | 3008 --------------------- |
2478 -- Process_Formals -- | 3009 -- Process_Formals -- |
2479 --------------------- | 3010 --------------------- |
2480 | 3011 |
2481 function Process_Formals (N : Node_Id) return Traverse_Result is | 3012 function Process_Formals (N : Node_Id) return Traverse_Result is |
2674 end if; | 3205 end if; |
2675 end Process_Formals; | 3206 end Process_Formals; |
2676 | 3207 |
2677 procedure Replace_Formals is new Traverse_Proc (Process_Formals); | 3208 procedure Replace_Formals is new Traverse_Proc (Process_Formals); |
2678 | 3209 |
3210 -------------------------------- | |
3211 -- Process_Formals_In_Aspects -- | |
3212 -------------------------------- | |
3213 | |
3214 function Process_Formals_In_Aspects | |
3215 (N : Node_Id) return Traverse_Result | |
3216 is | |
3217 A : Node_Id; | |
3218 | |
3219 begin | |
3220 if Has_Aspects (N) then | |
3221 A := First (Aspect_Specifications (N)); | |
3222 while Present (A) loop | |
3223 Replace_Formals (Expression (A)); | |
3224 | |
3225 Next (A); | |
3226 end loop; | |
3227 end if; | |
3228 return OK; | |
3229 end Process_Formals_In_Aspects; | |
3230 | |
3231 procedure Replace_Formals_In_Aspects is | |
3232 new Traverse_Proc (Process_Formals_In_Aspects); | |
3233 | |
2679 ------------------ | 3234 ------------------ |
2680 -- Process_Sloc -- | 3235 -- Process_Sloc -- |
2681 ------------------ | 3236 ------------------ |
2682 | 3237 |
2683 function Process_Sloc (Nod : Node_Id) return Traverse_Result is | 3238 function Process_Sloc (Nod : Node_Id) return Traverse_Result is |
2740 procedure Rewrite_Function_Call (N : Node_Id; Blk : Node_Id) is | 3295 procedure Rewrite_Function_Call (N : Node_Id; Blk : Node_Id) is |
2741 HSS : constant Node_Id := Handled_Statement_Sequence (Blk); | 3296 HSS : constant Node_Id := Handled_Statement_Sequence (Blk); |
2742 Fst : constant Node_Id := First (Statements (HSS)); | 3297 Fst : constant Node_Id := First (Statements (HSS)); |
2743 | 3298 |
2744 begin | 3299 begin |
3300 Make_Loop_Labels_Unique (HSS); | |
3301 | |
2745 -- Optimize simple case: function body is a single return statement, | 3302 -- Optimize simple case: function body is a single return statement, |
2746 -- which has been expanded into an assignment. | 3303 -- which has been expanded into an assignment. |
2747 | 3304 |
2748 if Is_Empty_List (Declarations (Blk)) | 3305 if Is_Empty_List (Declarations (Blk)) |
2749 and then Nkind (Fst) = N_Assignment_Statement | 3306 and then Nkind (Fst) = N_Assignment_Statement |
2827 | 3384 |
2828 procedure Rewrite_Procedure_Call (N : Node_Id; Blk : Node_Id) is | 3385 procedure Rewrite_Procedure_Call (N : Node_Id; Blk : Node_Id) is |
2829 HSS : constant Node_Id := Handled_Statement_Sequence (Blk); | 3386 HSS : constant Node_Id := Handled_Statement_Sequence (Blk); |
2830 | 3387 |
2831 begin | 3388 begin |
3389 Make_Loop_Labels_Unique (HSS); | |
3390 | |
2832 -- If there is a transient scope for N, this will be the scope of the | 3391 -- If there is a transient scope for N, this will be the scope of the |
2833 -- actions for N, and the statements in Blk need to be within this | 3392 -- actions for N, and the statements in Blk need to be within this |
2834 -- scope. For example, they need to have visibility on the constant | 3393 -- scope. For example, they need to have visibility on the constant |
2835 -- declarations created for the formals. | 3394 -- declarations created for the formals. |
2836 | 3395 |
3482 | 4041 |
3483 -- Traverse the tree and replace formals with actuals or their thunks. | 4042 -- Traverse the tree and replace formals with actuals or their thunks. |
3484 -- Attach block to tree before analysis and rewriting. | 4043 -- Attach block to tree before analysis and rewriting. |
3485 | 4044 |
3486 Replace_Formals (Blk); | 4045 Replace_Formals (Blk); |
4046 Replace_Formals_In_Aspects (Blk); | |
3487 Set_Parent (Blk, N); | 4047 Set_Parent (Blk, N); |
3488 | 4048 |
3489 if GNATprove_Mode then | 4049 if GNATprove_Mode then |
3490 null; | 4050 null; |
3491 | 4051 |
4011 -- Initialize -- | 4571 -- Initialize -- |
4012 ---------------- | 4572 ---------------- |
4013 | 4573 |
4014 procedure Initialize is | 4574 procedure Initialize is |
4015 begin | 4575 begin |
4016 Pending_Descriptor.Init; | |
4017 Pending_Instantiations.Init; | 4576 Pending_Instantiations.Init; |
4577 Called_Pending_Instantiations.Init; | |
4018 Inlined_Bodies.Init; | 4578 Inlined_Bodies.Init; |
4019 Successors.Init; | 4579 Successors.Init; |
4020 Inlined.Init; | 4580 Inlined.Init; |
4021 | 4581 |
4022 for J in Hash_Headers'Range loop | 4582 for J in Hash_Headers'Range loop |
4023 Hash_Headers (J) := No_Subp; | 4583 Hash_Headers (J) := No_Subp; |
4024 end loop; | 4584 end loop; |
4025 | 4585 |
4026 Inlined_Calls := No_Elist; | 4586 Inlined_Calls := No_Elist; |
4027 Backend_Calls := No_Elist; | 4587 Backend_Calls := No_Elist; |
4588 Backend_Instances := No_Elist; | |
4028 Backend_Inlined_Subps := No_Elist; | 4589 Backend_Inlined_Subps := No_Elist; |
4029 Backend_Not_Inlined_Subps := No_Elist; | 4590 Backend_Not_Inlined_Subps := No_Elist; |
4030 end Initialize; | 4591 end Initialize; |
4031 | 4592 |
4032 ------------------------ | 4593 ------------------------ |
4039 -- Generic associations have verified that the contract model is | 4600 -- Generic associations have verified that the contract model is |
4040 -- satisfied, so that any error that may occur in the analysis of | 4601 -- satisfied, so that any error that may occur in the analysis of |
4041 -- the body is an internal error. | 4602 -- the body is an internal error. |
4042 | 4603 |
4043 procedure Instantiate_Bodies is | 4604 procedure Instantiate_Bodies is |
4044 J : Nat; | 4605 |
4606 procedure Instantiate_Body (Info : Pending_Body_Info); | |
4607 -- Instantiate a pending body | |
4608 | |
4609 ------------------------ | |
4610 -- Instantiate_Body -- | |
4611 ------------------------ | |
4612 | |
4613 procedure Instantiate_Body (Info : Pending_Body_Info) is | |
4614 begin | |
4615 -- If the instantiation node is absent, it has been removed as part | |
4616 -- of unreachable code. | |
4617 | |
4618 if No (Info.Inst_Node) then | |
4619 null; | |
4620 | |
4621 -- If the instantiation node is a package body, this means that the | |
4622 -- instance is a compilation unit and the instantiation has already | |
4623 -- been performed by Build_Instance_Compilation_Unit_Nodes. | |
4624 | |
4625 elsif Nkind (Info.Inst_Node) = N_Package_Body then | |
4626 null; | |
4627 | |
4628 elsif Nkind (Info.Act_Decl) = N_Package_Declaration then | |
4629 Instantiate_Package_Body (Info); | |
4630 Add_Scope_To_Clean (Defining_Entity (Info.Act_Decl)); | |
4631 | |
4632 else | |
4633 Instantiate_Subprogram_Body (Info); | |
4634 end if; | |
4635 end Instantiate_Body; | |
4636 | |
4637 J, K : Nat; | |
4045 Info : Pending_Body_Info; | 4638 Info : Pending_Body_Info; |
4639 | |
4640 -- Start of processing for Instantiate_Bodies | |
4046 | 4641 |
4047 begin | 4642 begin |
4048 if Serious_Errors_Detected = 0 then | 4643 if Serious_Errors_Detected = 0 then |
4049 Expander_Active := (Operating_Mode = Opt.Generate_Code); | 4644 Expander_Active := (Operating_Mode = Opt.Generate_Code); |
4050 Push_Scope (Standard_Standard); | 4645 Push_Scope (Standard_Standard); |
4054 Start_Generic; | 4649 Start_Generic; |
4055 end if; | 4650 end if; |
4056 | 4651 |
4057 -- A body instantiation may generate additional instantiations, so | 4652 -- A body instantiation may generate additional instantiations, so |
4058 -- the following loop must scan to the end of a possibly expanding | 4653 -- the following loop must scan to the end of a possibly expanding |
4059 -- set (that's why we can't simply use a FOR loop here). | 4654 -- set (that's why we cannot simply use a FOR loop here). We must |
4655 -- also capture the element lest the set be entirely reallocated. | |
4060 | 4656 |
4061 J := 0; | 4657 J := 0; |
4062 while J <= Pending_Instantiations.Last | 4658 if Back_End_Inlining then |
4063 and then Serious_Errors_Detected = 0 | 4659 while J <= Called_Pending_Instantiations.Last |
4064 loop | 4660 and then Serious_Errors_Detected = 0 |
4065 Info := Pending_Instantiations.Table (J); | 4661 loop |
4066 | 4662 K := Called_Pending_Instantiations.Table (J); |
4067 -- If the instantiation node is absent, it has been removed | 4663 Info := Pending_Instantiations.Table (K); |
4068 -- as part of unreachable code. | 4664 Instantiate_Body (Info); |
4069 | 4665 |
4070 if No (Info.Inst_Node) then | 4666 J := J + 1; |
4071 null; | 4667 end loop; |
4072 | 4668 |
4073 elsif Nkind (Info.Act_Decl) = N_Package_Declaration then | 4669 else |
4074 Instantiate_Package_Body (Info); | 4670 while J <= Pending_Instantiations.Last |
4075 Add_Scope_To_Clean (Defining_Entity (Info.Act_Decl)); | 4671 and then Serious_Errors_Detected = 0 |
4076 | 4672 loop |
4077 else | 4673 Info := Pending_Instantiations.Table (J); |
4078 Instantiate_Subprogram_Body (Info); | 4674 Instantiate_Body (Info); |
4079 end if; | 4675 |
4080 | 4676 J := J + 1; |
4081 J := J + 1; | 4677 end loop; |
4082 end loop; | 4678 end if; |
4083 | 4679 |
4084 -- Reset the table of instantiations. Additional instantiations | 4680 -- Reset the table of instantiations. Additional instantiations |
4085 -- may be added through inlining, when additional bodies are | 4681 -- may be added through inlining, when additional bodies are |
4086 -- analyzed. | 4682 -- analyzed. |
4087 | 4683 |
4088 Pending_Instantiations.Init; | 4684 if Back_End_Inlining then |
4685 Called_Pending_Instantiations.Init; | |
4686 else | |
4687 Pending_Instantiations.Init; | |
4688 end if; | |
4089 | 4689 |
4090 -- We can now complete the cleanup actions of scopes that contain | 4690 -- We can now complete the cleanup actions of scopes that contain |
4091 -- pending instantiations (skipped for generic units, since we | 4691 -- pending instantiations (skipped for generic units, since we |
4092 -- never need any cleanups in generic units). | 4692 -- never need any cleanups in generic units). |
4093 | 4693 |
4111 Scop : Entity_Id; | 4711 Scop : Entity_Id; |
4112 | 4712 |
4113 begin | 4713 begin |
4114 Scop := Scope (E); | 4714 Scop := Scope (E); |
4115 while Scop /= Standard_Standard loop | 4715 while Scop /= Standard_Standard loop |
4116 if Ekind (Scop) in Subprogram_Kind then | 4716 if Is_Subprogram (Scop) then |
4117 return True; | 4717 return True; |
4118 | 4718 |
4119 elsif Ekind (Scop) = E_Task_Type | 4719 elsif Ekind (Scop) = E_Task_Type |
4120 or else Ekind (Scop) = E_Entry | 4720 or else Ekind (Scop) = E_Entry |
4121 or else Ekind (Scop) = E_Entry_Family | 4721 or else Ekind (Scop) = E_Entry_Family |
4149 Count := 0; | 4749 Count := 0; |
4150 Elmt := First_Elmt (Inlined_Calls); | 4750 Elmt := First_Elmt (Inlined_Calls); |
4151 while Present (Elmt) loop | 4751 while Present (Elmt) loop |
4152 Nod := Node (Elmt); | 4752 Nod := Node (Elmt); |
4153 | 4753 |
4154 if In_Extended_Main_Code_Unit (Nod) then | 4754 if not In_Internal_Unit (Nod) then |
4155 Count := Count + 1; | 4755 Count := Count + 1; |
4156 | 4756 |
4157 if Count = 1 then | 4757 if Count = 1 then |
4158 Write_Str ("List of calls inlined by the frontend"); | 4758 Write_Str ("List of calls inlined by the frontend"); |
4159 Write_Eol; | 4759 Write_Eol; |
4178 | 4778 |
4179 Elmt := First_Elmt (Backend_Calls); | 4779 Elmt := First_Elmt (Backend_Calls); |
4180 while Present (Elmt) loop | 4780 while Present (Elmt) loop |
4181 Nod := Node (Elmt); | 4781 Nod := Node (Elmt); |
4182 | 4782 |
4183 if In_Extended_Main_Code_Unit (Nod) then | 4783 if not In_Internal_Unit (Nod) then |
4184 Count := Count + 1; | 4784 Count := Count + 1; |
4185 | 4785 |
4186 if Count = 1 then | 4786 if Count = 1 then |
4187 Write_Str ("List of inlined calls passed to the backend"); | 4787 Write_Str ("List of inlined calls passed to the backend"); |
4188 Write_Eol; | 4788 Write_Eol; |
4197 | 4797 |
4198 Next_Elmt (Elmt); | 4798 Next_Elmt (Elmt); |
4199 end loop; | 4799 end loop; |
4200 end if; | 4800 end if; |
4201 | 4801 |
4802 -- Generate listing of instances inlined for the backend | |
4803 | |
4804 if Present (Backend_Instances) then | |
4805 Count := 0; | |
4806 | |
4807 Elmt := First_Elmt (Backend_Instances); | |
4808 while Present (Elmt) loop | |
4809 Nod := Node (Elmt); | |
4810 | |
4811 if not In_Internal_Unit (Nod) then | |
4812 Count := Count + 1; | |
4813 | |
4814 if Count = 1 then | |
4815 Write_Str ("List of instances inlined for the backend"); | |
4816 Write_Eol; | |
4817 end if; | |
4818 | |
4819 Write_Str (" "); | |
4820 Write_Int (Count); | |
4821 Write_Str (":"); | |
4822 Write_Location (Sloc (Nod)); | |
4823 Output.Write_Eol; | |
4824 end if; | |
4825 | |
4826 Next_Elmt (Elmt); | |
4827 end loop; | |
4828 end if; | |
4829 | |
4202 -- Generate listing of subprograms passed to the backend | 4830 -- Generate listing of subprograms passed to the backend |
4203 | 4831 |
4204 if Present (Backend_Inlined_Subps) and then Back_End_Inlining then | 4832 if Present (Backend_Inlined_Subps) and then Back_End_Inlining then |
4205 Count := 0; | 4833 Count := 0; |
4206 | 4834 |
4207 Elmt := First_Elmt (Backend_Inlined_Subps); | 4835 Elmt := First_Elmt (Backend_Inlined_Subps); |
4208 while Present (Elmt) loop | 4836 while Present (Elmt) loop |
4209 Nod := Node (Elmt); | 4837 Nod := Node (Elmt); |
4210 | 4838 |
4211 Count := Count + 1; | 4839 if not In_Internal_Unit (Nod) then |
4212 | 4840 Count := Count + 1; |
4213 if Count = 1 then | 4841 |
4214 Write_Str | 4842 if Count = 1 then |
4215 ("List of inlined subprograms passed to the backend"); | 4843 Write_Str |
4216 Write_Eol; | 4844 ("List of inlined subprograms passed to the backend"); |
4217 end if; | 4845 Write_Eol; |
4218 | 4846 end if; |
4219 Write_Str (" "); | 4847 |
4220 Write_Int (Count); | 4848 Write_Str (" "); |
4221 Write_Str (":"); | 4849 Write_Int (Count); |
4222 Write_Name (Chars (Nod)); | 4850 Write_Str (":"); |
4223 Write_Str (" ("); | 4851 Write_Name (Chars (Nod)); |
4224 Write_Location (Sloc (Nod)); | 4852 Write_Str (" ("); |
4225 Write_Str (")"); | 4853 Write_Location (Sloc (Nod)); |
4226 Output.Write_Eol; | 4854 Write_Str (")"); |
4855 Output.Write_Eol; | |
4856 end if; | |
4227 | 4857 |
4228 Next_Elmt (Elmt); | 4858 Next_Elmt (Elmt); |
4229 end loop; | 4859 end loop; |
4230 end if; | 4860 end if; |
4231 | 4861 |
4236 | 4866 |
4237 Elmt := First_Elmt (Backend_Not_Inlined_Subps); | 4867 Elmt := First_Elmt (Backend_Not_Inlined_Subps); |
4238 while Present (Elmt) loop | 4868 while Present (Elmt) loop |
4239 Nod := Node (Elmt); | 4869 Nod := Node (Elmt); |
4240 | 4870 |
4241 Count := Count + 1; | 4871 if not In_Internal_Unit (Nod) then |
4242 | 4872 Count := Count + 1; |
4243 if Count = 1 then | 4873 |
4244 Write_Str | 4874 if Count = 1 then |
4245 ("List of subprograms that cannot be inlined by the backend"); | 4875 Write_Str |
4246 Write_Eol; | 4876 ("List of subprograms that cannot be inlined by backend"); |
4247 end if; | 4877 Write_Eol; |
4248 | 4878 end if; |
4249 Write_Str (" "); | 4879 |
4250 Write_Int (Count); | 4880 Write_Str (" "); |
4251 Write_Str (":"); | 4881 Write_Int (Count); |
4252 Write_Name (Chars (Nod)); | 4882 Write_Str (":"); |
4253 Write_Str (" ("); | 4883 Write_Name (Chars (Nod)); |
4254 Write_Location (Sloc (Nod)); | 4884 Write_Str (" ("); |
4255 Write_Str (")"); | 4885 Write_Location (Sloc (Nod)); |
4256 Output.Write_Eol; | 4886 Write_Str (")"); |
4887 Output.Write_Eol; | |
4888 end if; | |
4257 | 4889 |
4258 Next_Elmt (Elmt); | 4890 Next_Elmt (Elmt); |
4259 end loop; | 4891 end loop; |
4260 end if; | 4892 end if; |
4261 end List_Inlining_Info; | 4893 end List_Inlining_Info; |
4266 | 4898 |
4267 procedure Lock is | 4899 procedure Lock is |
4268 begin | 4900 begin |
4269 Pending_Instantiations.Release; | 4901 Pending_Instantiations.Release; |
4270 Pending_Instantiations.Locked := True; | 4902 Pending_Instantiations.Locked := True; |
4903 Called_Pending_Instantiations.Release; | |
4904 Called_Pending_Instantiations.Locked := True; | |
4271 Inlined_Bodies.Release; | 4905 Inlined_Bodies.Release; |
4272 Inlined_Bodies.Locked := True; | 4906 Inlined_Bodies.Locked := True; |
4273 Successors.Release; | 4907 Successors.Release; |
4274 Successors.Locked := True; | 4908 Successors.Locked := True; |
4275 Inlined.Release; | 4909 Inlined.Release; |