1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 2014-2015, Free Software Foundation, Inc. --
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- --
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- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
26 with Atree
; use Atree
;
27 with Einfo
; use Einfo
;
28 with Elists
; use Elists
;
29 with Exp_Util
; use Exp_Util
;
31 with Namet
; use Namet
;
32 with Nlists
; use Nlists
;
33 with Nmake
; use Nmake
;
35 with Rtsfind
; use Rtsfind
;
36 with Sinput
; use Sinput
;
38 with Sem_Ch8
; use Sem_Ch8
;
39 with Sem_Mech
; use Sem_Mech
;
40 with Sem_Res
; use Sem_Res
;
41 with Sem_Util
; use Sem_Util
;
42 with Sinfo
; use Sinfo
;
43 with Snames
; use Snames
;
45 with Tbuild
; use Tbuild
;
46 with Uintp
; use Uintp
;
48 package body Exp_Unst
is
50 -- Tables used by Unnest_Subprogram
52 type Subp_Entry
is record
54 -- Entity of the subprogram
57 -- Subprogram_Body node for this subprogram
60 -- Subprogram level (1 = outer subprogram (Subp argument), 2 = nested
61 -- immediately within this outer subprogram etc.)
64 -- This is a copy of the Uplevel_References field from the entity for
65 -- the subprogram. Copy this to reuse the field for Subps_Index.
68 -- This entity is defined for all subprograms with uplevel references
69 -- except for the top-level subprogram (Subp itself). It is the entity
70 -- for the formal which is added to the parameter list to pass the
71 -- pointer to the activation record. Note that for this entity, n is
72 -- one less than the current level.
78 -- These AREC entities are defined only for subprograms for which we
79 -- generate an activation record declaration, i.e. for subprograms
80 -- with at least one nested subprogram that have uplevel referennces.
81 -- They are set to Empty for all other cases.
84 -- This AREC entity is the uplink component. It is other than Empty only
85 -- for nested subprograms that themselves have nested subprograms and
86 -- have uplevel references. Note that the n here is one less than the
87 -- level of the subprogram defining the activation record.
91 subtype SI_Type
is Nat
;
93 package Subps
is new Table
.Table
(
94 Table_Component_Type
=> Subp_Entry
,
95 Table_Index_Type
=> SI_Type
,
98 Table_Increment
=> 200,
99 Table_Name
=> "Unnest_Subps");
100 -- Records the subprograms in the nest whose outer subprogram is Subp
102 type Call_Entry
is record
107 -- Entity of the subprogram containing the call
110 -- Entity of the subprogram called
113 package Calls
is new Table
.Table
(
114 Table_Component_Type
=> Call_Entry
,
115 Table_Index_Type
=> Nat
,
116 Table_Low_Bound
=> 1,
117 Table_Initial
=> 100,
118 Table_Increment
=> 200,
119 Table_Name
=> "Unnest_Calls");
120 -- Records each call within the outer subprogram and all nested subprograms
121 -- that are to other subprograms nested within the outer subprogram. These
122 -- are the calls that may need an additional parameter.
124 -------------------------------------
125 -- Check_Uplevel_Reference_To_Type --
126 -------------------------------------
128 procedure Check_Uplevel_Reference_To_Type
(Typ
: Entity_Id
) is
129 function Check_Dynamic_Type
(T
: Entity_Id
) return Boolean;
130 -- This is an internal recursive routine that checks if T or any of
131 -- its subsdidiary types are dynamic. If so, then the original Typ is
132 -- marked as having an uplevel reference, as is the subsidiary type in
133 -- question, and any referenced dynamic bounds are also marked as having
134 -- an uplevel reference, and True is returned. If the type is a static
135 -- type, then False is returned;
137 ------------------------
138 -- Check_Dynamic_Type --
139 ------------------------
141 function Check_Dynamic_Type
(T
: Entity_Id
) return Boolean is
142 DT
: Boolean := False;
145 -- If it's a static type, nothing to do
147 if Is_Static_Type
(T
) then
150 -- If the type is uplevel referenced, then it must be dynamic
152 elsif Has_Uplevel_Reference
(T
) then
153 Set_Has_Uplevel_Reference
(Typ
);
156 -- Otherwise we need to figure out what the story is with this type
161 -- For a scalar type, check bounds
163 if Is_Scalar_Type
(T
) then
165 -- If both bounds static, then this is a static type
168 LB
: constant Node_Id
:= Type_Low_Bound
(T
);
169 UB
: constant Node_Id
:= Type_High_Bound
(T
);
172 if not Is_Static_Expression
(LB
) then
173 Set_Has_Uplevel_Reference
(Entity
(LB
));
177 if not Is_Static_Expression
(UB
) then
178 Set_Has_Uplevel_Reference
(Entity
(UB
));
183 -- For record type, check all components
185 elsif Is_Record_Type
(T
) then
190 C
:= First_Component_Or_Discriminant
(T
);
191 while Present
(C
) loop
192 if Check_Dynamic_Type
(Etype
(C
)) then
196 Next_Component_Or_Discriminant
(C
);
200 -- For array type, check index types and component type
202 elsif Is_Array_Type
(T
) then
207 if Check_Dynamic_Type
(Component_Type
(T
)) then
211 IX
:= First_Index
(T
);
212 while Present
(IX
) loop
213 if Check_Dynamic_Type
(Etype
(IX
)) then
221 -- For now, ignore other types
227 -- See if we marked that type as dynamic
230 Set_Has_Uplevel_Reference
(T
);
231 Set_Has_Uplevel_Reference
(Typ
);
234 -- If not mark it as static
237 Set_Is_Static_Type
(T
);
241 end Check_Dynamic_Type
;
243 -- Start of processing for Check_Uplevel_Reference_To_Type
246 -- Nothing to do if we know this is a static type
248 if Is_Static_Type
(Typ
) then
251 -- Nothing to do if already marked as uplevel referenced
253 elsif Has_Uplevel_Reference
(Typ
) then
256 -- Otherwise check if we have a dynamic type
259 if Check_Dynamic_Type
(Typ
) then
260 Set_Has_Uplevel_Reference
(Typ
);
265 end Check_Uplevel_Reference_To_Type
;
267 ----------------------------
268 -- Note_Uplevel_Reference --
269 ----------------------------
271 procedure Note_Uplevel_Reference
(N
: Node_Id
; Subp
: Entity_Id
) is
273 -- Nothing to do if reference has no entity field
275 if Nkind
(N
) not in N_Entity
then
279 -- Establish list if first call for Uplevel_References
281 if No
(Uplevel_References
(Subp
)) then
282 Set_Uplevel_References
(Subp
, New_Elmt_List
);
285 -- Add new entry to Uplevel_References. Each entry is two elements of
286 -- the list. The first is the actual reference, the second is the
287 -- enclosing subprogram at the point of reference
289 Append_Elmt
(N
, Uplevel_References
(Subp
));
291 if Is_Subprogram
(Current_Scope
) then
292 Append_Elmt
(Current_Scope
, Uplevel_References
(Subp
));
295 (Enclosing_Subprogram
(Current_Scope
), Uplevel_References
(Subp
));
298 Set_Has_Uplevel_Reference
(Entity
(N
));
299 Set_Has_Uplevel_Reference
(Subp
);
300 end Note_Uplevel_Reference
;
302 -----------------------
303 -- Unnest_Subprogram --
304 -----------------------
306 procedure Unnest_Subprogram
(Subp
: Entity_Id
; Subp_Body
: Node_Id
) is
307 function AREC_String
(Lev
: Pos
) return String;
308 -- Given a level value, 1, 2, ... returns the string AREC, AREC2, ...
310 function Enclosing_Subp
(Subp
: SI_Type
) return SI_Type
;
311 -- Subp is the index of a subprogram which has a Lev greater than 1.
312 -- This function returns the index of the enclosing subprogram which
313 -- will have a Lev value one less than this.
315 function Get_Level
(Sub
: Entity_Id
) return Nat
;
316 -- Sub is either Subp itself, or a subprogram nested within Subp. This
317 -- function returns the level of nesting (Subp = 1, subprograms that
318 -- are immediately nested within Subp = 2, etc).
320 function Subp_Index
(Sub
: Entity_Id
) return SI_Type
;
321 -- Given the entity for a subprogram, return corresponding Subps index
327 function AREC_String
(Lev
: Pos
) return String is
331 AREC_String
(Lev
/ 10) & Character'Val (Lev
mod 10 + 48);
334 "AREC" & Character'Val (Lev
+ 48);
342 function Enclosing_Subp
(Subp
: SI_Type
) return SI_Type
is
343 STJ
: Subp_Entry
renames Subps
.Table
(Subp
);
344 Ret
: constant SI_Type
:= Subp_Index
(Enclosing_Subprogram
(STJ
.Ent
));
346 pragma Assert
(STJ
.Lev
> 1);
347 pragma Assert
(Subps
.Table
(Ret
).Lev
= STJ
.Lev
- 1);
355 function Get_Level
(Sub
: Entity_Id
) return Nat
is
366 S
:= Enclosing_Subprogram
(S
);
376 function Subp_Index
(Sub
: Entity_Id
) return SI_Type
is
378 pragma Assert
(Is_Subprogram
(Sub
));
379 return SI_Type
(UI_To_Int
(Subps_Index
(Sub
)));
382 -- Start of processing for Unnest_Subprogram
385 -- At least for now, do not unnest anything but main source unit
387 if not In_Extended_Main_Source_Unit
(Subp_Body
) then
391 -- First step, we must mark all nested subprograms that require a static
392 -- link (activation record) because either they contain explicit uplevel
393 -- references (as indicated by Has_Uplevel_Reference being set at this
394 -- point), or they make calls to other subprograms in the same nest that
395 -- require a static link (in which case we set this flag).
397 -- This is a recursive definition, and to implement this, we have to
398 -- build a call graph for the set of nested subprograms, and then go
399 -- over this graph to implement recursively the invariant that if a
400 -- subprogram has a call to a subprogram requiring a static link, then
401 -- the calling subprogram requires a static link.
403 -- First populate the above tables
408 Build_Tables
: declare
409 function Visit_Node
(N
: Node_Id
) return Traverse_Result
;
410 -- Visit a single node in Subp
416 function Visit_Node
(N
: Node_Id
) return Traverse_Result
is
420 function Find_Current_Subprogram
return Entity_Id
;
421 -- Finds the current subprogram containing the call N
423 -----------------------------
424 -- Find_Current_Subprogram --
425 -----------------------------
427 function Find_Current_Subprogram
return Entity_Id
is
435 if Nkind
(Nod
) = N_Subprogram_Body
then
436 if Acts_As_Spec
(Nod
) then
437 return Defining_Unit_Name
(Specification
(Nod
));
439 return Corresponding_Spec
(Nod
);
443 end Find_Current_Subprogram
;
445 -- Start of processing for Visit_Node
450 if Nkind_In
(N
, N_Procedure_Call_Statement
, N_Function_Call
)
452 -- We are only interested in direct calls, not indirect calls
453 -- (where Name (N) is an explicit dereference) at least for now!
455 and then Nkind
(Name
(N
)) in N_Has_Entity
457 Ent
:= Entity
(Name
(N
));
459 -- We are only interested in calls to subprograms nested
460 -- within Subp. Calls to Subp itself or to subprograms that
461 -- are outside the nested structure do not affect us.
463 if Scope_Within
(Ent
, Subp
) then
465 -- For now, ignore calls to generic instances. Seems to be
466 -- some problem there which we will investigate later ???
468 if Original_Location
(Sloc
(Ent
)) /= Sloc
(Ent
)
469 or else Is_Generic_Instance
(Ent
)
473 -- Here we have a call to keep and analyze
476 Csub
:= Find_Current_Subprogram
;
478 -- Both caller and callee must be subprograms (we ignore
479 -- generic subprograms).
481 if Is_Subprogram
(Csub
) and then Is_Subprogram
(Ent
) then
482 Calls
.Append
((N
, Find_Current_Subprogram
, Ent
));
487 -- Record a subprogram. We record a subprogram body that acts as
488 -- a spec. Otherwise we record a subprogram declaration, providing
489 -- that it has a corresponding body we can get hold of. The case
490 -- of no corresponding body being available is ignored for now.
492 elsif (Nkind
(N
) = N_Subprogram_Body
and then Acts_As_Spec
(N
))
493 or else (Nkind
(N
) = N_Subprogram_Declaration
494 and then Present
(Corresponding_Body
(N
)))
496 Subps
.Increment_Last
;
499 STJ
: Subp_Entry
renames Subps
.Table
(Subps
.Last
);
502 -- Set fields of Subp_Entry for new subprogram
504 STJ
.Ent
:= Defining_Unit_Name
(Specification
(N
));
505 STJ
.Lev
:= Get_Level
(STJ
.Ent
);
507 if Nkind
(N
) = N_Subprogram_Body
then
510 STJ
.Bod
:= Parent
(Parent
(Corresponding_Body
(N
)));
512 pragma Assert
(Nkind
(STJ
.Bod
) = N_Subprogram_Body
);
515 -- Capture Uplevel_References, and then set (uses the same
516 -- field), the Subps_Index value for this subprogram.
518 STJ
.Urefs
:= Uplevel_References
(STJ
.Ent
);
519 Set_Subps_Index
(STJ
.Ent
, UI_From_Int
(Int
(Subps
.Last
)));
530 procedure Visit
is new Traverse_Proc
(Visit_Node
);
531 -- Used to traverse the body of Subp, populating the tables
533 -- Start of processing for Build_Tables
536 -- A special case, if the outer level subprogram has a separate spec
537 -- then we won't catch it in the traversal of the body. But we do
538 -- want to visit the declaration in this case!
540 if not Acts_As_Spec
(Subp_Body
) then
542 Dummy
: Traverse_Result
;
543 Decl
: constant Node_Id
:=
544 Parent
(Declaration_Node
(Corresponding_Spec
(Subp_Body
)));
545 pragma Assert
(Nkind
(Decl
) = N_Subprogram_Declaration
);
547 Dummy
:= Visit_Node
(Decl
);
551 -- Traverse the body to get the rest of the subprograms and calls
556 -- Second step is to do the transitive closure, if any subprogram has
557 -- a call to a subprogram for which Has_Uplevel_Reference is set, then
558 -- we set Has_Uplevel_Reference for the calling routine.
564 -- We use a simple minded algorithm as follows (obviously this can
565 -- be done more efficiently, using one of the standard algorithms
566 -- for efficient transitive closure computation, but this is simple
567 -- and most likely fast enough that its speed does not matter).
569 -- Repeatedly scan the list of calls. Any time we find a call from
570 -- A to B, where A does not have Has_Uplevel_Reference, and B does
571 -- have this flag set, then set the flag for A, and note that we
572 -- have made a change by setting Modified True. We repeat this until
573 -- we make a pass with no modifications.
577 Inner
: for J
in Calls
.First
.. Calls
.Last
loop
578 if not Has_Uplevel_Reference
(Calls
.Table
(J
).From
)
579 and then Has_Uplevel_Reference
(Calls
.Table
(J
).To
)
581 Set_Has_Uplevel_Reference
(Calls
.Table
(J
).From
);
586 exit Outer
when not Modified
;
590 -- Next step, create the entities for code we will insert. We do this
591 -- at the start so that all the entities are defined, regardless of the
592 -- order in which we do the code insertions.
594 Create_Entities
: for J
in Subps
.First
.. Subps
.Last
loop
596 STJ
: Subp_Entry
renames Subps
.Table
(J
);
597 Loc
: constant Source_Ptr
:= Sloc
(STJ
.Bod
);
598 ARS
: constant String := AREC_String
(STJ
.Lev
);
601 -- First we create the ARECnF entity for the additional formal
602 -- for all subprograms requiring that an activation record pointer
603 -- be passed. This is true of all subprograms that have uplevel
604 -- references, and whose enclosing subprogram also has uplevel
607 if Has_Uplevel_Reference
(STJ
.Ent
)
608 and then STJ
.Ent
/= Subp
609 and then Has_Uplevel_Reference
(Enclosing_Subprogram
(STJ
.Ent
))
612 Make_Defining_Identifier
(Loc
,
613 Chars
=> Name_Find_Str
(AREC_String
(STJ
.Lev
- 1) & "F"));
614 Set_Is_ARECnF_Entity
(STJ
.ARECnF
, True);
619 -- Now define the AREC entities for the activation record. This
620 -- is needed for any subprogram that has nested subprograms and
621 -- has uplevel references.
623 if Has_Nested_Subprogram
(STJ
.Ent
)
624 and then Has_Uplevel_Reference
(STJ
.Ent
)
627 Make_Defining_Identifier
(Loc
, Name_Find_Str
(ARS
));
629 Make_Defining_Identifier
(Loc
, Name_Find_Str
(ARS
& "T"));
631 Make_Defining_Identifier
(Loc
, Name_Find_Str
(ARS
& "PT"));
633 Make_Defining_Identifier
(Loc
, Name_Find_Str
(ARS
& "P"));
638 STJ
.ARECnPT
:= Empty
;
643 -- Define uplink component entity if inner nesting case
645 if Has_Uplevel_Reference
(STJ
.Ent
) and then STJ
.Lev
> 1 then
647 ARS1
: constant String := AREC_String
(STJ
.Lev
- 1);
650 Make_Defining_Identifier
(Loc
,
651 Chars
=> Name_Find_Str
(ARS1
& "U"));
658 end loop Create_Entities
;
660 -- Loop through subprograms
663 Addr
: constant Entity_Id
:= RTE
(RE_Address
);
666 for J
in Subps
.First
.. Subps
.Last
loop
668 STJ
: Subp_Entry
renames Subps
.Table
(J
);
671 -- First add the extra formal if needed. This applies to all
672 -- nested subprograms that require an activation record to be
673 -- passed, as indicated by ARECnF being defined.
675 if Present
(STJ
.ARECnF
) then
677 -- Here we need the extra formal. We do the expansion and
678 -- analysis of this manually, since it is fairly simple,
679 -- and it is not obvious how we can get what we want if we
680 -- try to use the normal Analyze circuit.
682 Extra_Formal
: declare
683 Encl
: constant SI_Type
:= Enclosing_Subp
(J
);
684 STJE
: Subp_Entry
renames Subps
.Table
(Encl
);
685 -- Index and Subp_Entry for enclosing routine
687 Form
: constant Entity_Id
:= STJ
.ARECnF
;
688 -- The formal to be added. Note that n here is one less
689 -- than the level of the subprogram itself (STJ.Ent).
692 -- If needed, this is the formal added to the body
694 procedure Add_Form_To_Spec
(F
: Entity_Id
; S
: Node_Id
);
695 -- S is an N_Function/Procedure_Specification node, and F
696 -- is the new entity to add to this subprogramn spec.
698 ----------------------
699 -- Add_Form_To_Spec --
700 ----------------------
702 procedure Add_Form_To_Spec
(F
: Entity_Id
; S
: Node_Id
) is
703 Sub
: constant Entity_Id
:= Defining_Unit_Name
(S
);
706 if No
(First_Entity
(Sub
)) then
707 Set_First_Entity
(Sub
, F
);
708 Set_Last_Entity
(Sub
, F
);
712 LastF
: constant Entity_Id
:= Last_Formal
(Sub
);
715 Set_Next_Entity
(F
, First_Entity
(Sub
));
716 Set_First_Entity
(Sub
, F
);
719 Set_Next_Entity
(F
, Next_Entity
(LastF
));
720 Set_Next_Entity
(LastF
, F
);
722 if Last_Entity
(Sub
) = LastF
then
723 Set_Last_Entity
(Sub
, F
);
729 if No
(Parameter_Specifications
(S
)) then
730 Set_Parameter_Specifications
(S
, Empty_List
);
733 Append_To
(Parameter_Specifications
(S
),
734 Make_Parameter_Specification
(Sloc
(F
),
735 Defining_Identifier
=> F
,
737 New_Occurrence_Of
(STJE
.ARECnPT
, Sloc
(F
))));
738 end Add_Form_To_Spec
;
740 -- Start of processing for Extra_Formal
743 -- Decorate the new formal entity
745 Set_Scope
(Form
, STJ
.Ent
);
746 Set_Ekind
(Form
, E_In_Parameter
);
747 Set_Etype
(Form
, STJE
.ARECnPT
);
748 Set_Mechanism
(Form
, By_Copy
);
749 Set_Never_Set_In_Source
(Form
, True);
750 Set_Analyzed
(Form
, True);
751 Set_Comes_From_Source
(Form
, False);
753 -- Case of only body present
755 if Acts_As_Spec
(STJ
.Bod
) then
756 Add_Form_To_Spec
(Form
, Specification
(STJ
.Bod
));
758 -- Case of separate spec
761 Formb
:= New_Entity
(Nkind
(Form
), Sloc
(Form
));
762 Copy_Node
(Form
, Formb
);
763 Add_Form_To_Spec
(Form
, Parent
(STJ
.Ent
));
764 Add_Form_To_Spec
(Formb
, Specification
(STJ
.Bod
));
769 -- Processing for subprograms that have at least one nested
770 -- subprogram, and have uplevel references.
772 if Has_Nested_Subprogram
(STJ
.Ent
)
773 and then Has_Uplevel_Reference
(STJ
.Ent
)
775 -- Local declarations for one such subprogram
778 Loc
: constant Source_Ptr
:= Sloc
(STJ
.Bod
);
784 Decl_ARECnT
: Node_Id
;
785 Decl_ARECn
: Node_Id
;
786 Decl_ARECnPT
: Node_Id
;
787 Decl_ARECnP
: Node_Id
;
788 -- Declaration nodes for the AREC entities we build
791 array (1 .. List_Length
(STJ
.Urefs
)) of Entity_Id
;
792 Num_Uplevel_Entities
: Nat
;
793 -- Uplevel_Entities (1 .. Num_Uplevel_Entities) contains
794 -- a list (with no duplicates) of the entities for this
795 -- subprogram that are referenced uplevel. The maximum
796 -- number of entries cannot exceed the total number of
797 -- uplevel references.
800 -- Populate the Uplevel_Entities array, using the flag
801 -- Uplevel_Reference_Noted to avoid duplicates.
803 Num_Uplevel_Entities
:= 0;
805 if Present
(STJ
.Urefs
) then
806 Elmt
:= First_Elmt
(STJ
.Urefs
);
807 while Present
(Elmt
) loop
808 Ent
:= Entity
(Node
(Elmt
));
810 if not Uplevel_Reference_Noted
(Ent
) then
811 Set_Uplevel_Reference_Noted
(Ent
, True);
812 Num_Uplevel_Entities
:= Num_Uplevel_Entities
+ 1;
813 Uplevel_Entities
(Num_Uplevel_Entities
) := Ent
;
821 -- Build list of component declarations for ARECnT
825 -- If we are in a subprogram that has a static link that
826 -- ias passed in (as indicated by ARECnF being deinfed),
827 -- then include ARECnU : ARECnPT := ARECnF where n is
828 -- one less than the current level and the entity ARECnPT
829 -- comes from the enclosing subprogram.
831 if Present
(STJ
.ARECnF
) then
834 renames Subps
.Table
(Enclosing_Subp
(J
));
838 Make_Component_Declaration
(Loc
,
839 Defining_Identifier
=> STJ
.ARECnU
,
840 Component_Definition
=>
841 Make_Component_Definition
(Loc
,
842 Subtype_Indication
=>
843 New_Occurrence_Of
(STJE
.ARECnPT
, Loc
)),
845 New_Occurrence_Of
(STJ
.ARECnF
, Loc
)));
849 -- Add components for uplevel referenced entities
851 for J
in 1 .. Num_Uplevel_Entities
loop
853 Make_Defining_Identifier
(Loc
,
854 Chars
=> Chars
(Uplevel_Entities
(J
)));
856 Set_Activation_Record_Component
857 (Uplevel_Entities
(J
), Comp
);
860 Make_Component_Declaration
(Loc
,
861 Defining_Identifier
=> Comp
,
862 Component_Definition
=>
863 Make_Component_Definition
(Loc
,
864 Subtype_Indication
=>
865 New_Occurrence_Of
(Addr
, Loc
))));
868 -- Now we can insert the AREC declarations into the body
870 -- type ARECnT is record .. end record;
873 Make_Full_Type_Declaration
(Loc
,
874 Defining_Identifier
=> STJ
.ARECnT
,
876 Make_Record_Definition
(Loc
,
878 Make_Component_List
(Loc
,
879 Component_Items
=> Clist
)));
881 -- ARECn : aliased ARECnT;
884 Make_Object_Declaration
(Loc
,
885 Defining_Identifier
=> STJ
.ARECn
,
886 Aliased_Present
=> True,
888 New_Occurrence_Of
(STJ
.ARECnT
, Loc
));
890 -- type ARECnPT is access all ARECnT;
893 Make_Full_Type_Declaration
(Loc
,
894 Defining_Identifier
=> STJ
.ARECnPT
,
896 Make_Access_To_Object_Definition
(Loc
,
898 Subtype_Indication
=>
899 New_Occurrence_Of
(STJ
.ARECnT
, Loc
)));
901 -- ARECnP : constant ARECnPT := ARECn'Access;
904 Make_Object_Declaration
(Loc
,
905 Defining_Identifier
=> STJ
.ARECnP
,
906 Constant_Present
=> True,
908 New_Occurrence_Of
(STJ
.ARECnPT
, Loc
),
910 Make_Attribute_Reference
(Loc
,
912 New_Occurrence_Of
(STJ
.ARECn
, Loc
),
913 Attribute_Name
=> Name_Access
));
915 Prepend_List_To
(Declarations
(STJ
.Bod
),
917 (Decl_ARECnT
, Decl_ARECn
, Decl_ARECnPT
, Decl_ARECnP
));
919 -- Analyze the newly inserted declarations. Note that we
920 -- do not need to establish the whole scope stack, since
921 -- we have already set all entity fields (so there will
922 -- be no searching of upper scopes to resolve names). But
923 -- we do set the scope of the current subprogram, so that
924 -- newly created entities go in the right entity chain.
926 -- We analyze with all checks suppressed (since we do
927 -- not expect any exceptions, and also we temporarily
928 -- turn off Unested_Subprogram_Mode to avoid trying to
929 -- mark uplevel references (not needed at this stage,
930 -- and in fact causes a bit of recursive chaos).
932 Push_Scope
(STJ
.Ent
);
933 Opt
.Unnest_Subprogram_Mode
:= False;
934 Analyze
(Decl_ARECnT
, Suppress
=> All_Checks
);
935 Analyze
(Decl_ARECn
, Suppress
=> All_Checks
);
936 Analyze
(Decl_ARECnPT
, Suppress
=> All_Checks
);
937 Analyze
(Decl_ARECnP
, Suppress
=> All_Checks
);
938 Opt
.Unnest_Subprogram_Mode
:= True;
941 -- Next step, for each uplevel referenced entity, add
942 -- assignment operations to set the comoponent in the
943 -- activation record.
945 for J
in 1 .. Num_Uplevel_Entities
loop
947 Ent
: constant Entity_Id
:= Uplevel_Entities
(J
);
948 Loc
: constant Source_Ptr
:= Sloc
(Ent
);
949 Dec
: constant Node_Id
:= Declaration_Node
(Ent
);
954 -- For parameters, we insert the assignment right
955 -- after the declaration of ARECnP. For all other
956 -- entities, we insert the assignment immediately
957 -- after the declaration of the entity.
959 -- Note: we don't need to mark the entity as being
960 -- aliased, because the address attribute will mark
961 -- it as Address_Taken, and that is good enough.
963 if Is_Formal
(Ent
) then
969 -- Build and insert the assignment:
973 Make_Assignment_Statement
(Loc
,
975 Make_Selected_Component
(Loc
,
977 New_Occurrence_Of
(STJ
.ARECn
, Loc
),
979 Make_Identifier
(Loc
, Chars
(Ent
))),
982 Make_Attribute_Reference
(Loc
,
984 New_Occurrence_Of
(Ent
, Loc
),
985 Attribute_Name
=> Name_Address
));
987 Insert_After
(Ins
, Asn
);
989 -- Analyze the assignment statement. We do not need
990 -- to establish the relevant scope stack entries
991 -- here, because we have already set the correct
992 -- entity references, so no name resolution is
993 -- required, and no new entities are created, so
994 -- we don't even need to set the current scope.
996 -- We analyze with all checks suppressed (since
997 -- we do not expect any exceptions, and also we
998 -- temporarily turn off Unested_Subprogram_Mode
999 -- to avoid trying to mark uplevel references (not
1000 -- needed at this stage, and in fact causes a bit
1001 -- of recursive chaos).
1003 Opt
.Unnest_Subprogram_Mode
:= False;
1004 Analyze
(Asn
, Suppress
=> All_Checks
);
1005 Opt
.Unnest_Subprogram_Mode
:= True;
1014 -- Next step, process uplevel references. This has to be done in a
1015 -- separate pass, after completing the processing in Sub_Loop because we
1016 -- need all the AREC declarations generated, inserted, and analyzed so
1017 -- that the uplevel references can be successfully analyzed.
1019 Uplev_Refs
: for J
in Subps
.First
.. Subps
.Last
loop
1021 STJ
: Subp_Entry
renames Subps
.Table
(J
);
1024 -- We are only interested in entries which have uplevel references
1025 -- to deal with, as indicated by the Urefs list being present
1027 if Present
(STJ
.Urefs
) then
1029 -- Process uplevel references for one subprogram
1035 -- Loop through uplevel references
1037 Elmt
:= First_Elmt
(STJ
.Urefs
);
1038 while Present
(Elmt
) loop
1040 -- Skip if we have an explicit dereference. This means
1041 -- that we already did the expansion. There can be
1042 -- duplicates in ths STJ.Urefs list.
1044 if Nkind
(Node
(Elmt
)) = N_Explicit_Dereference
then
1048 -- Otherwise, rewrite this reference
1051 Ref
: constant Node_Id
:= Node
(Elmt
);
1052 -- The uplevel reference itself
1054 Loc
: constant Source_Ptr
:= Sloc
(Ref
);
1055 -- Source location for the reference
1057 Ent
: constant Entity_Id
:= Entity
(Ref
);
1058 -- The referenced entity
1060 Typ
: constant Entity_Id
:= Etype
(Ent
);
1061 -- The type of the referenced entity
1063 Rsub
: constant Entity_Id
:=
1064 Node
(Next_Elmt
(Elmt
));
1065 -- The enclosing subprogram for the reference
1067 RSX
: constant SI_Type
:= Subp_Index
(Rsub
);
1068 -- Subp_Index for enclosing subprogram for ref
1070 STJR
: Subp_Entry
renames Subps
.Table
(RSX
);
1071 -- Subp_Entry for enclosing subprogram for ref
1073 Tnn
: constant Entity_Id
:=
1075 (Loc
, 'T', Related_Node
=> Ref
);
1076 -- Local pointer type for reference
1083 -- Push the current scope, so that the pointer type
1084 -- Tnn, and any subsidiary entities resulting from
1085 -- the analysis of the rewritten reference, go in the
1086 -- right entity chain.
1088 Push_Scope
(STJR
.Ent
);
1090 -- First insert declaration for pointer type
1092 -- type Tnn is access all typ;
1095 Make_Full_Type_Declaration
(Loc
,
1096 Defining_Identifier
=> Tnn
,
1098 Make_Access_To_Object_Definition
(Loc
,
1099 All_Present
=> True,
1100 Subtype_Indication
=>
1101 New_Occurrence_Of
(Typ
, Loc
))));
1103 -- Now we need to rewrite the reference. We have a
1104 -- reference is from level STJE.Lev to level STJ.Lev.
1105 -- The general form of the rewritten reference for
1108 -- Tnn!(ARECaF.ARECbU.ARECcU.ARECdU....ARECm.X).all
1110 -- where a,b,c,d .. m =
1111 -- STJR.Lev - 1, STJ.Lev - 2, .. STJ.Lev
1113 pragma Assert
(STJR
.Lev
> STJ
.Lev
);
1115 -- Compute the prefix of X. Here are examples to make
1116 -- things clear (with parens to show groupings, the
1117 -- prefix is everything except the .X at the end).
1119 -- level 2 to level 1
1123 -- level 3 to level 1
1125 -- (AREC2F.AREC1U).X
1127 -- level 4 to level 1
1129 -- ((AREC3F.AREC2U).AREC1U).X
1131 -- level 6 to level 2
1133 -- (((AREC5F.AREC4U).AREC3U).AREC2U).X
1135 Pfx
:= New_Occurrence_Of
(STJR
.ARECnF
, Loc
);
1137 for L
in STJ
.Lev
.. STJR
.Lev
- 2 loop
1138 SI
:= Enclosing_Subp
(SI
);
1140 Make_Selected_Component
(Loc
,
1144 (Subps
.Table
(SI
).ARECnU
, Loc
));
1147 -- Get activation record component (must exist)
1149 Comp
:= Activation_Record_Component
(Ent
);
1150 pragma Assert
(Present
(Comp
));
1152 -- Do the replacement
1155 Make_Explicit_Dereference
(Loc
,
1157 Unchecked_Convert_To
(Tnn
,
1158 Make_Selected_Component
(Loc
,
1161 New_Occurrence_Of
(Comp
, Loc
)))));
1163 -- Analyze and resolve the new expression. We do not
1164 -- need to establish the relevant scope stack entries
1165 -- here, because we have already set all the correct
1166 -- entity references, so no name resolution is needed.
1167 -- We have already set the current scope, so that any
1168 -- new entities created will be in the right scope.
1170 -- We analyze with all checks suppressed (since we do
1171 -- not expect any exceptions, and also we temporarily
1172 -- turn off Unested_Subprogram_Mode to avoid trying to
1173 -- mark uplevel references (not needed at this stage,
1174 -- and in fact causes a bit of recursive chaos).
1176 Opt
.Unnest_Subprogram_Mode
:= False;
1177 Analyze_And_Resolve
(Ref
, Typ
, Suppress
=> All_Checks
);
1178 Opt
.Unnest_Subprogram_Mode
:= True;
1189 end loop Uplev_Refs
;
1191 -- Finally, loop through all calls adding extra actual for the
1192 -- activation record where it is required.
1194 Adjust_Calls
: for J
in Calls
.First
.. Calls
.Last
loop
1196 -- Process a single call, we are only interested in a call to a
1197 -- subprogram that actually needs a pointer to an activation record,
1198 -- as indicated by the ARECnF entity being set. This excludes the
1199 -- top level subprogram, and any subprogram not having uplevel refs.
1201 Adjust_One_Call
: declare
1202 CTJ
: Call_Entry
renames Calls
.Table
(J
);
1203 STF
: Subp_Entry
renames Subps
.Table
(Subp_Index
(CTJ
.From
));
1204 STT
: Subp_Entry
renames Subps
.Table
(Subp_Index
(CTJ
.To
));
1206 Loc
: constant Source_Ptr
:= Sloc
(CTJ
.N
);
1214 if Present
(STT
.ARECnF
) then
1216 -- CTJ.N is a call to a subprogram which may require
1217 -- a pointer to an activation record. The subprogram
1218 -- containing the call is CTJ.From and the subprogram being
1219 -- called is CTJ.To, so we have a call from level STF.Lev to
1222 -- There are three possibilities:
1224 -- For a call to the same level, we just pass the activation
1225 -- record passed to the calling subprogram.
1227 if STF
.Lev
= STT
.Lev
then
1228 Extra
:= New_Occurrence_Of
(STF
.ARECnF
, Loc
);
1230 -- For a call that goes down a level, we pass a pointer
1231 -- to the activation record constructed wtihin the caller
1232 -- (which may be the outer level subprogram, but also may
1233 -- be a more deeply nested caller).
1235 elsif STT
.Lev
= STF
.Lev
+ 1 then
1236 Extra
:= New_Occurrence_Of
(STF
.ARECnP
, Loc
);
1238 -- Otherwise we must have an upcall (STT.Lev < STF.LEV),
1239 -- since it is not possible to do a downcall of more than
1242 -- For a call from level STF.Lev to level STT.Lev, we
1243 -- have to find the activation record needed by the
1244 -- callee. This is as follows:
1246 -- ARECaF.ARECbU.ARECcU....ARECm
1248 -- where a,b,c .. m =
1249 -- STF.Lev - 1, STF.Lev - 2, STF.Lev - 3 .. STT.Lev
1252 pragma Assert
(STT
.Lev
< STF
.Lev
);
1254 Extra
:= New_Occurrence_Of
(STF
.ARECnF
, Loc
);
1255 SubX
:= Subp_Index
(CTJ
.From
);
1256 for K
in reverse STT
.Lev
.. STF
.Lev
- 1 loop
1257 SubX
:= Enclosing_Subp
(SubX
);
1259 Make_Selected_Component
(Loc
,
1263 (Subps
.Table
(SubX
).ARECnU
, Loc
));
1267 -- Extra is the additional parameter to be added. Build a
1268 -- parameter association that we can append to the actuals.
1271 Make_Parameter_Association
(Loc
,
1273 New_Occurrence_Of
(STT
.ARECnF
, Loc
),
1274 Explicit_Actual_Parameter
=> Extra
);
1276 if No
(Parameter_Associations
(CTJ
.N
)) then
1277 Set_Parameter_Associations
(CTJ
.N
, Empty_List
);
1280 Append
(ExtraP
, Parameter_Associations
(CTJ
.N
));
1282 -- We need to deal with the actual parameter chain as well.
1283 -- The newly added parameter is always the last actual.
1285 Act
:= First_Named_Actual
(CTJ
.N
);
1288 Set_First_Named_Actual
(CTJ
.N
, Extra
);
1290 -- Here we must follow the chain and append the new entry
1299 PAN
:= Parent
(Act
);
1300 pragma Assert
(Nkind
(PAN
) = N_Parameter_Association
);
1301 NNA
:= Next_Named_Actual
(PAN
);
1304 Set_Next_Named_Actual
(PAN
, Extra
);
1313 -- Analyze and resolve the new actual. We do not need to
1314 -- establish the relevant scope stack entries here, because
1315 -- we have already set all the correct entity references, so
1316 -- no name resolution is needed.
1318 -- We analyze with all checks suppressed (since we do not
1319 -- expect any exceptions, and also we temporarily turn off
1320 -- Unested_Subprogram_Mode to avoid trying to mark uplevel
1321 -- references (not needed at this stage, and in fact causes
1322 -- a bit of recursive chaos).
1324 Opt
.Unnest_Subprogram_Mode
:= False;
1326 (Extra
, Etype
(STT
.ARECnF
), Suppress
=> All_Checks
);
1327 Opt
.Unnest_Subprogram_Mode
:= True;
1329 end Adjust_One_Call
;
1330 end loop Adjust_Calls
;
1333 end Unnest_Subprogram
;