File : inline.ads


   1 ------------------------------------------------------------------------------
   2 --                                                                          --
   3 --                         GNAT COMPILER COMPONENTS                         --
   4 --                                                                          --
   5 --                               I N L I N E                                --
   6 --                                                                          --
   7 --                                 S p e c                                  --
   8 --                                                                          --
   9 --          Copyright (C) 1992-2015, Free Software Foundation, Inc.         --
  10 --                                                                          --
  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.          --
  20 --                                                                          --
  21 -- GNAT was originally developed  by the GNAT team at  New York University. --
  22 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
  23 --                                                                          --
  24 ------------------------------------------------------------------------------
  25 
  26 --  This module handles four kinds of inlining activity:
  27 
  28 --  a) Instantiation of generic bodies. This is done unconditionally, after
  29 --  analysis and expansion of the main unit.
  30 
  31 --  b) Compilation of unit bodies that contain the bodies of inlined sub-
  32 --  programs. This is done only if inlining is enabled (-gnatn). Full inlining
  33 --  requires that a) and b) be mutually recursive, because each step may
  34 --  generate another generic expansion and further inlined calls.
  35 
  36 --  c) Front-end inlining for Inline_Always subprograms. This is primarily an
  37 --  expansion activity that is performed for performance reasons, and when the
  38 --  target does not use the GCC back end.
  39 
  40 --  d) Front-end inlining for GNATprove, to perform source transformations
  41 --  to simplify formal verification. The machinery used is the same as for
  42 --  Inline_Always subprograms, but there are fewer restrictions on the source
  43 --  of subprograms.
  44 
  45 with Alloc;
  46 with Opt;    use Opt;
  47 with Sem;    use Sem;
  48 with Table;
  49 with Types;  use Types;
  50 with Warnsw; use Warnsw;
  51 
  52 package Inline is
  53 
  54    --------------------------------
  55    -- Generic Body Instantiation --
  56    --------------------------------
  57 
  58    --  The bodies of generic instantiations are built after semantic analysis
  59    --  of the main unit is complete. Generic instantiations are saved in a
  60    --  global data structure, and the bodies constructed by means of a separate
  61    --  analysis and expansion step.
  62 
  63    --  See full description in body of Sem_Ch12 for more details
  64 
  65    type Pending_Body_Info is record
  66       Inst_Node : Node_Id;
  67       --  Node for instantiation that requires the body
  68 
  69       Act_Decl : Node_Id;
  70       --  Declaration for package or subprogram spec for instantiation
  71 
  72       Expander_Status : Boolean;
  73       --  If the body is instantiated only for semantic checking, expansion
  74       --  must be inhibited.
  75 
  76       Current_Sem_Unit : Unit_Number_Type;
  77       --  The semantic unit within which the instantiation is found. Must be
  78       --  restored when compiling the body, to insure that internal entities
  79       --  use the same counter and are unique over spec and body.
  80 
  81       Scope_Suppress           : Suppress_Record;
  82       Local_Suppress_Stack_Top : Suppress_Stack_Entry_Ptr;
  83       --  Save suppress information at the point of instantiation. Used to
  84       --  properly inherit check status active at this point (see RM 11.5
  85       --  (7.2/2), AI95-00224-01):
  86       --
  87       --    "If a checking pragma applies to a generic instantiation, then the
  88       --    checking pragma also applies to the instance. If a checking pragma
  89       --    applies to a call to a subprogram that has a pragma Inline applied
  90       --    to it, then the checking pragma also applies to the inlined
  91       --    subprogram body".
  92       --
  93       --  This means we have to capture this information from the current scope
  94       --  at the point of instantiation.
  95 
  96       Version : Ada_Version_Type;
  97       --  The body must be compiled with the same language version as the
  98       --  spec. The version may be set by a configuration pragma in a separate
  99       --  file or in the current file, and may differ from body to body.
 100 
 101       Version_Pragma : Node_Id;
 102       --  This is linked with the Version value
 103 
 104       Warnings : Warning_Record;
 105       --  Capture values of warning flags
 106 
 107       SPARK_Mode        : SPARK_Mode_Type;
 108       SPARK_Mode_Pragma : Node_Id;
 109       --  SPARK_Mode for an instance is the one applicable at the point of
 110       --  instantiation. SPARK_Mode_Pragma is the related active pragma.
 111    end record;
 112 
 113    package Pending_Instantiations is new Table.Table (
 114      Table_Component_Type => Pending_Body_Info,
 115      Table_Index_Type     => Int,
 116      Table_Low_Bound      => 0,
 117      Table_Initial        => Alloc.Pending_Instantiations_Initial,
 118      Table_Increment      => Alloc.Pending_Instantiations_Increment,
 119      Table_Name           => "Pending_Instantiations");
 120 
 121    --  The following table records subprograms and packages for which
 122    --  generation of subprogram descriptors must be delayed.
 123 
 124    package Pending_Descriptor is new Table.Table (
 125      Table_Component_Type => Entity_Id,
 126      Table_Index_Type     => Int,
 127      Table_Low_Bound      => 0,
 128      Table_Initial        => Alloc.Pending_Instantiations_Initial,
 129      Table_Increment      => Alloc.Pending_Instantiations_Increment,
 130      Table_Name           => "Pending_Descriptor");
 131 
 132    --  The following should be initialized in an init call in Frontend, we
 133    --  have thoughts of making the frontend reusable in future ???
 134 
 135    -----------------
 136    -- Subprograms --
 137    -----------------
 138 
 139    procedure Initialize;
 140    --  Initialize internal tables
 141 
 142    procedure Lock;
 143    --  Lock internal tables before calling backend
 144 
 145    procedure Instantiate_Bodies;
 146    --  This procedure is called after semantic analysis is complete, to
 147    --  instantiate the bodies of generic instantiations that appear in the
 148    --  compilation unit.
 149 
 150    procedure Add_Inlined_Body (E : Entity_Id; N : Node_Id);
 151    --  E is an inlined subprogram appearing in a call, either explicitly or in
 152    --  a discriminant check for which gigi builds a call or an at-end handler.
 153    --  Add E's enclosing unit to Inlined_Bodies so that E can be subsequently
 154    --  retrieved and analyzed. N is the node giving rise to the call to E.
 155 
 156    procedure Analyze_Inlined_Bodies;
 157    --  At end of compilation, analyze the bodies of all units that contain
 158    --  inlined subprograms that are actually called.
 159 
 160    procedure Build_Body_To_Inline (N : Node_Id; Spec_Id : Entity_Id);
 161    --  If a subprogram has pragma Inline and inlining is active, use generic
 162    --  machinery to build an unexpanded body for the subprogram. This body is
 163    --  subsequently used for inline expansions at call sites. If subprogram can
 164    --  be inlined (depending on size and nature of local declarations) the
 165    --  template body is created. Otherwise subprogram body is treated normally
 166    --  and calls are not inlined in the frontend. If proper warnings are
 167    --  enabled and the subprogram contains a construct that cannot be inlined,
 168    --  the problematic construct is flagged accordingly.
 169 
 170    function Can_Be_Inlined_In_GNATprove_Mode
 171      (Spec_Id : Entity_Id;
 172       Body_Id : Entity_Id) return Boolean;
 173    --  Returns True if the subprogram identified by Spec_Id and Body_Id can
 174    --  be inlined in GNATprove mode. One but not both of Spec_Id and Body_Id
 175    --  can be Empty. Body_Id is Empty when doing a partial check on a call
 176    --  to a subprogram whose body has not been seen yet, to know whether this
 177    --  subprogram could possibly be inlined. GNATprove relies on this to adapt
 178    --  its treatment of the subprogram.
 179 
 180    procedure Cannot_Inline
 181      (Msg        : String;
 182       N          : Node_Id;
 183       Subp       : Entity_Id;
 184       Is_Serious : Boolean := False);
 185    --  This procedure is called if the node N, an instance of a call to
 186    --  subprogram Subp, cannot be inlined. Msg is the message to be issued,
 187    --  which ends with ? (it does not end with ?p?, this routine takes care of
 188    --  the need to change ? to ?p?). The behavior of this routine depends on
 189    --  the value of Back_End_Inlining:
 190    --
 191    --    * If Back_End_Inlining is not set (ie. legacy frontend inlining model)
 192    --      then if Subp has a pragma Always_Inlined, then an error message is
 193    --      issued (by removing the last character of Msg). If Subp is not
 194    --      Always_Inlined, then a warning is issued if the flag Ineffective_
 195    --      Inline_Warnings is set, adding ?p to the msg, and if not, the call
 196    --      has no effect.
 197    --
 198    --    * If Back_End_Inlining is set then:
 199    --      - If Is_Serious is true, then an error is reported (by removing the
 200    --        last character of Msg);
 201    --
 202    --      - otherwise:
 203    --
 204    --        * Compiling without optimizations if Subp has a pragma
 205    --          Always_Inlined, then an error message is issued; if Subp is
 206    --          not Always_Inlined, then a warning is issued if the flag
 207    --          Ineffective_Inline_Warnings is set (adding p?), and if not,
 208    --          the call has no effect.
 209    --
 210    --        * Compiling with optimizations then a warning is issued if the
 211    --          flag Ineffective_Inline_Warnings is set (adding p?); otherwise
 212    --          no effect since inlining may be performed by the backend.
 213 
 214    procedure Check_And_Split_Unconstrained_Function
 215      (N       : Node_Id;
 216       Spec_Id : Entity_Id;
 217       Body_Id : Entity_Id);
 218    --  Spec_Id and Body_Id are the entities of the specification and body of
 219    --  the subprogram body N. If N can be inlined by the frontend (supported
 220    --  cases documented in Check_Body_To_Inline) then build the body-to-inline
 221    --  associated with N and attach it to the declaration node of Spec_Id.
 222 
 223    procedure Check_Package_Body_For_Inlining (N : Node_Id; P : Entity_Id);
 224    --  If front-end inlining is enabled and a package declaration contains
 225    --  inlined subprograms, load and compile the package body to collect the
 226    --  bodies of these subprograms, so they are available to inline calls.
 227    --  N is the compilation unit for the package.
 228 
 229    procedure Expand_Inlined_Call
 230     (N         : Node_Id;
 231      Subp      : Entity_Id;
 232      Orig_Subp : Entity_Id);
 233    --  If called subprogram can be inlined by the front-end, retrieve the
 234    --  analyzed body, replace formals with actuals and expand call in place.
 235    --  Generate thunks for actuals that are expressions, and insert the
 236    --  corresponding constant declarations before the call. If the original
 237    --  call is to a derived operation, the return type is the one of the
 238    --  derived operation, but the body is that of the original, so return
 239    --  expressions in the body must be converted to the desired type (which
 240    --  is simply not noted in the tree without inline expansion).
 241 
 242    function Has_Excluded_Declaration
 243      (Subp  : Entity_Id;
 244       Decls : List_Id) return Boolean;
 245    --  Check a list of declarations, Decls, that make the inlining of Subp not
 246    --  worthwhile
 247 
 248    function Has_Excluded_Statement
 249      (Subp  : Entity_Id;
 250       Stats : List_Id) return Boolean;
 251    --  Check a list of statements, Stats, that make inlining of Subp not
 252    --  worthwhile, including any tasking statement, nested at any level.
 253 
 254    procedure List_Inlining_Info;
 255    --  Generate listing of calls inlined by the frontend plus listing of
 256    --  calls to inline subprograms passed to the backend.
 257 
 258    procedure Remove_Dead_Instance (N : Node_Id);
 259    --  If an instantiation appears in unreachable code, delete the pending
 260    --  body instance.
 261 
 262 end Inline;