Inst : Entity_Id;
Inst_Decl : Node_Id;
- Inst_Node : Node_Id;
Level : Inline_Level_Type;
-- Start of processing for Add_Inlined_Body
and then Is_Generic_Instance (Inst)
and then not Is_Called (Inst)
then
- -- Do not add a pending instantiation if the body exits
- -- already, or if the instance is a compilation unit, or
- -- the instance node is missing.
-
Inst_Decl := Unit_Declaration_Node (Inst);
+
+ -- Do not inline the instance if the body already exists,
+ -- or if the instance is a compilation unit, or else if
+ -- the instance node is simply missing.
+
if Present (Corresponding_Body (Inst_Decl))
or else Nkind (Parent (Inst_Decl)) = N_Compilation_Unit
or else No (Next (Inst_Decl))
then
Set_Is_Called (Inst);
-
else
- -- If the inlined call itself appears within an instance,
- -- ensure that the enclosing instance body is available.
- -- This is necessary because Sem_Ch12.Might_Inline_Subp
- -- does not recurse into nested instantiations.
-
- if not Is_Inlined (Inst) and then In_Instance then
- Set_Is_Inlined (Inst);
-
- -- The instantiation node usually follows the package
- -- declaration for the instance. If the generic unit
- -- has aspect specifications, they are transformed
- -- into pragmas in the instance, and the instance node
- -- appears after them.
-
- Inst_Node := Next (Inst_Decl);
-
- while Nkind (Inst_Node) /= N_Package_Instantiation loop
- Inst_Node := Next (Inst_Node);
- end loop;
-
- Add_Pending_Instantiation (Inst_Node, Inst_Decl);
- end if;
-
Add_Inlined_Instance (Inst);
end if;
end if;
end if;
- -- If the unit containing E is an instance, then the instance body
- -- will be analyzed in any case, see Sem_Ch12.Might_Inline_Subp.
+ -- If the unit containing E is an instance, nothing more to do
if Is_Generic_Instance (Pack) then
null;
-- circularity is detected, and used to abandon compilation after the
-- messages have been posted.
+ Circularity_Detected : Boolean := False;
+ -- It should really be reset upon encountering a new main unit, but in
+ -- practice we do not use multiple main units so this is not critical.
+
-----------------------------------------
-- Implementation of Generic Contracts --
-----------------------------------------
-- Instantiate_Subprogram_Contract
- Circularity_Detected : Boolean := False;
- -- This should really be reset on encountering a new main unit, but in
- -- practice we are not using multiple main units so it is not critical.
-
--------------------------------------------------
-- Formal packages and partial parameterization --
--------------------------------------------------
-- the generic package, and a set of declarations that map the actuals
-- into local renamings, just as we do for bona fide instantiations. For
-- defaulted parameters and formals with a box, we copy directly the
- -- declarations of the formal into this local package. The result is a
- -- a package whose visible declarations may include generic formals. This
+ -- declarations of the formals into this local package. The result is a
+ -- package whose visible declarations may include generic formals. This
-- package is only used for type checking and visibility analysis, and
- -- never reaches the back-end, so it can freely violate the placement
+ -- never reaches the back end, so it can freely violate the placement
-- rules for generic formal declarations.
-- The list of declarations (renamings and copies of formals) is built
-- by Analyze_Associations, just as for regular instantiations.
-- At the point of instantiation, conformance checking must be applied only
- -- to those parameters that were specified in the formal. We perform this
+ -- to those parameters that were specified in the formals. We perform this
-- checking by creating another internal instantiation, this one including
-- only the renamings and the formals (the rest of the package spec is not
-- relevant to conformance checking). We can then traverse two lists: the
-- list of actuals in the instance that corresponds to the formal package,
-- and the list of actuals produced for this bogus instantiation. We apply
- -- the conformance rules to those actuals that are not defaulted (i.e.
+ -- the conformance rules to those actuals that are not defaulted, i.e.
-- which still appear as generic formals.
-- When we compile an instance body we must make the right parameters
-- Only relevant when back-end inlining is not enabled.
function Might_Inline_Subp (Gen_Unit : Entity_Id) return Boolean;
- -- If inlining is active and the generic contains inlined subprograms,
- -- we either instantiate the body when front-end inlining is enabled,
- -- or we add a pending instantiation when back-end inlining is enabled.
- -- In the former case, this may cause superfluous instantiations, but
- -- in either case we need to perform the instantiation of the body in
- -- the context of the instance and not in that of the point of inlining.
+ -- Return True if inlining is active and Gen_Unit contains inlined
+ -- subprograms. In this case, we may either instantiate the body when
+ -- front-end inlining is enabled, or add a pending instantiation when
+ -- back-end inlining is enabled. In the former case, this may cause
+ -- superfluous instantiations, but in either case we need to perform
+ -- the instantiation of the body in the context of the instance and
+ -- not in that of the point of inlining.
+
+ function Needs_Body_Instantiated (Gen_Unit : Entity_Id) return Boolean;
+ -- Return True if Gen_Unit needs to have its body instantiated in the
+ -- context of N. This in particular excludes generic contexts.
-----------------------
-- Might_Inline_Subp --
return False;
end Might_Inline_Subp;
+ -------------------------------
+ -- Needs_Body_Instantiated --
+ -------------------------------
+
+ function Needs_Body_Instantiated (Gen_Unit : Entity_Id) return Boolean is
+ begin
+ -- No need to instantiate bodies in generic units
+
+ if Is_Generic_Unit (Cunit_Entity (Main_Unit)) then
+ return False;
+ end if;
+
+ -- If the instantiation is in the main unit, then the body is needed
+
+ if Is_In_Main_Unit (N) then
+ return True;
+ end if;
+
+ -- If not, then again no need to instantiate bodies in generic units
+
+ if Is_Generic_Unit (Cunit_Entity (Get_Code_Unit (N))) then
+ return False;
+ end if;
+
+ -- Here we have a special handling for back-end inlining: if the
+ -- instantiation is not a compilation unit, then we want to have
+ -- its body instantiated. The reason is that Might_Inline_Subp
+ -- does not catch all the cases (since it does not recurse into
+ -- nested packages) so this avoids the need to patch things up
+ -- at a later stage. Moreover the instantiations that are not
+ -- compilation units are only performed on demand when back-end
+ -- inlining is enabled, so this causes very little extra work.
+
+ if Nkind (Parent (N)) /= N_Compilation_Unit
+ and then Inline_Processing_Required
+ and then Back_End_Inlining
+ then
+ return True;
+ end if;
+
+ -- We want to have the bodies instantiated in non-main units if
+ -- they might contribute inlined subprograms.
+
+ return Might_Inline_Subp (Gen_Unit);
+ end Needs_Body_Instantiated;
+
-- Local declarations
Gen_Id : constant Node_Id := Name (N);
end if;
-- Save the instantiation node for a subsequent instantiation of the
- -- body if there is one and the main unit is not generic, and either
- -- we are generating code for this main unit, or the instantiation
- -- contains inlined subprograms and is not done in a generic unit.
+ -- body if there is one and it needs to be instantiated here.
-- We instantiate the body only if we are generating code, or if we
-- are generating cross-reference information, or if we are building
(Unit_Requires_Body (Gen_Unit)
or else Enclosing_Body_Present
or else Present (Corresponding_Body (Gen_Decl)))
- and then not Is_Generic_Unit (Cunit_Entity (Main_Unit))
- and then (Is_In_Main_Unit (N)
- or else (Might_Inline_Subp (Gen_Unit)
- and then
- not Is_Generic_Unit
- (Cunit_Entity (Get_Code_Unit (N)))))
+ and then Needs_Body_Instantiated (Gen_Unit)
and then not Is_Actual_Pack
and then not Inline_Now
and then (Operating_Mode = Generate_Code