1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1992-2001 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 2, 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 COPYING. If not, write --
19 -- to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, --
20 -- MA 02111-1307, USA. --
22 -- GNAT was originally developed by the GNAT team at New York University. --
23 -- Extensive contributions were provided by Ada Core Technologies Inc. --
25 ------------------------------------------------------------------------------
27 with Atree; use Atree;
28 with Einfo; use Einfo;
29 with Elists; use Elists;
30 with Errout; use Errout;
31 with Exp_Ch7; use Exp_Ch7;
32 with Exp_Ch11; use Exp_Ch11;
33 with Exp_Tss; use Exp_Tss;
34 with Fname; use Fname;
35 with Fname.UF; use Fname.UF;
37 with Nlists; use Nlists;
39 with Sem_Ch8; use Sem_Ch8;
40 with Sem_Ch10; use Sem_Ch10;
41 with Sem_Ch12; use Sem_Ch12;
42 with Sem_Util; use Sem_Util;
43 with Sinfo; use Sinfo;
44 with Snames; use Snames;
45 with Stand; use Stand;
46 with Uname; use Uname;
48 package body Inline is
54 -- Inlined functions are actually placed in line by the backend if the
55 -- corresponding bodies are available (i.e. compiled). Whenever we find
56 -- a call to an inlined subprogram, we add the name of the enclosing
57 -- compilation unit to a worklist. After all compilation, and after
58 -- expansion of generic bodies, we traverse the list of pending bodies
59 -- and compile them as well.
61 package Inlined_Bodies is new Table.Table (
62 Table_Component_Type => Entity_Id,
63 Table_Index_Type => Int,
65 Table_Initial => Alloc.Inlined_Bodies_Initial,
66 Table_Increment => Alloc.Inlined_Bodies_Increment,
67 Table_Name => "Inlined_Bodies");
69 -----------------------
70 -- Inline Processing --
71 -----------------------
73 -- For each call to an inlined subprogram, we make entries in a table
74 -- that stores caller and callee, and indicates a prerequisite from
75 -- one to the other. We also record the compilation unit that contains
76 -- the callee. After analyzing the bodies of all such compilation units,
77 -- we produce a list of subprograms in topological order, for use by the
78 -- back-end. If P2 is a prerequisite of P1, then P1 calls P2, and for
79 -- proper inlining the back-end must analyze the body of P2 before that of
80 -- P1. The code below guarantees that the transitive closure of inlined
81 -- subprograms called from the main compilation unit is made available to
82 -- the code generator.
84 Last_Inlined : Entity_Id := Empty;
86 -- For each entry in the table we keep a list of successors in topological
87 -- order, i.e. callers of the current subprogram.
89 type Subp_Index is new Nat;
90 No_Subp : constant Subp_Index := 0;
92 -- The subprogram entities are hashed into the Inlined table.
94 Num_Hash_Headers : constant := 512;
96 Hash_Headers : array (Subp_Index range 0 .. Num_Hash_Headers - 1)
99 type Succ_Index is new Nat;
100 No_Succ : constant Succ_Index := 0;
102 type Succ_Info is record
107 -- The following table stores list elements for the successor lists.
108 -- These lists cannot be chained directly through entries in the Inlined
109 -- table, because a given subprogram can appear in several such lists.
111 package Successors is new Table.Table (
112 Table_Component_Type => Succ_Info,
113 Table_Index_Type => Succ_Index,
114 Table_Low_Bound => 1,
115 Table_Initial => Alloc.Successors_Initial,
116 Table_Increment => Alloc.Successors_Increment,
117 Table_Name => "Successors");
119 type Subp_Info is record
120 Name : Entity_Id := Empty;
121 First_Succ : Succ_Index := No_Succ;
122 Count : Integer := 0;
123 Listed : Boolean := False;
124 Main_Call : Boolean := False;
125 Next : Subp_Index := No_Subp;
126 Next_Nopred : Subp_Index := No_Subp;
129 package Inlined is new Table.Table (
130 Table_Component_Type => Subp_Info,
131 Table_Index_Type => Subp_Index,
132 Table_Low_Bound => 1,
133 Table_Initial => Alloc.Inlined_Initial,
134 Table_Increment => Alloc.Inlined_Increment,
135 Table_Name => "Inlined");
137 -----------------------
138 -- Local Subprograms --
139 -----------------------
141 function Scope_In_Main_Unit (Scop : Entity_Id) return Boolean;
142 -- Return True if Scop is in the main unit or its spec, or in a
143 -- parent of the main unit if it is a child unit.
145 procedure Add_Call (Called : Entity_Id; Caller : Entity_Id := Empty);
146 -- Make two entries in Inlined table, for an inlined subprogram being
147 -- called, and for the inlined subprogram that contains the call. If
148 -- the call is in the main compilation unit, Caller is Empty.
150 function Add_Subp (E : Entity_Id) return Subp_Index;
151 -- Make entry in Inlined table for subprogram E, or return table index
152 -- that already holds E.
154 function Has_Initialized_Type (E : Entity_Id) return Boolean;
155 -- If a candidate for inlining contains type declarations for types with
156 -- non-trivial initialization procedures, they are not worth inlining.
158 function Is_Nested (E : Entity_Id) return Boolean;
159 -- If the function is nested inside some other function, it will
160 -- always be compiled if that function is, so don't add it to the
161 -- inline list. We cannot compile a nested function outside the
162 -- scope of the containing function anyway. This is also the case if
163 -- the function is defined in a task body or within an entry (for
164 -- example, an initialization procedure).
166 procedure Add_Inlined_Subprogram (Index : Subp_Index);
167 -- Add subprogram to Inlined List once all of its predecessors have been
168 -- placed on the list. Decrement the count of all its successors, and
169 -- add them to list (recursively) if count drops to zero.
171 ------------------------------
172 -- Deferred Cleanup Actions --
173 ------------------------------
175 -- The cleanup actions for scopes that contain instantiations is delayed
176 -- until after expansion of those instantiations, because they may
177 -- contain finalizable objects or tasks that affect the cleanup code.
178 -- A scope that contains instantiations only needs to be finalized once,
179 -- even if it contains more than one instance. We keep a list of scopes
180 -- that must still be finalized, and call cleanup_actions after all the
181 -- instantiations have been completed.
185 procedure Add_Scope_To_Clean (Inst : Entity_Id);
186 -- Build set of scopes on which cleanup actions must be performed.
188 procedure Cleanup_Scopes;
189 -- Complete cleanup actions on scopes that need it.
195 procedure Add_Call (Called : Entity_Id; Caller : Entity_Id := Empty) is
196 P1 : Subp_Index := Add_Subp (Called);
201 if Present (Caller) then
202 P2 := Add_Subp (Caller);
204 -- Add P2 to the list of successors of P1, if not already there.
205 -- Note that P2 may contain more than one call to P1, and only
206 -- one needs to be recorded.
208 J := Inlined.Table (P1).First_Succ;
210 while J /= No_Succ loop
212 if Successors.Table (J).Subp = P2 then
216 J := Successors.Table (J).Next;
219 -- On exit, make a successor entry for P2.
221 Successors.Increment_Last;
222 Successors.Table (Successors.Last).Subp := P2;
223 Successors.Table (Successors.Last).Next :=
224 Inlined.Table (P1).First_Succ;
225 Inlined.Table (P1).First_Succ := Successors.Last;
227 Inlined.Table (P2).Count := Inlined.Table (P2).Count + 1;
230 Inlined.Table (P1).Main_Call := True;
234 ----------------------
235 -- Add_Inlined_Body --
236 ----------------------
238 procedure Add_Inlined_Body (E : Entity_Id) is
242 function Must_Inline return Boolean;
243 -- Inlining is only done if the call statement N is in the main unit,
244 -- or within the body of another inlined subprogram.
246 function Must_Inline return Boolean is
247 Scop : Entity_Id := Current_Scope;
251 -- Check if call is in main unit.
253 while Scope (Scop) /= Standard_Standard
254 and then not Is_Child_Unit (Scop)
256 Scop := Scope (Scop);
259 Comp := Parent (Scop);
261 while Nkind (Comp) /= N_Compilation_Unit loop
262 Comp := Parent (Comp);
265 if (Comp = Cunit (Main_Unit)
266 or else Comp = Library_Unit (Cunit (Main_Unit)))
272 -- Call is not in main unit. See if it's in some inlined
275 Scop := Current_Scope;
276 while Scope (Scop) /= Standard_Standard
277 and then not Is_Child_Unit (Scop)
279 if Is_Overloadable (Scop)
280 and then Is_Inlined (Scop)
286 Scop := Scope (Scop);
293 -- Start of processing for Add_Inlined_Body
296 -- Find unit containing E, and add to list of inlined bodies if needed.
297 -- If the body is already present, no need to load any other unit. This
298 -- is the case for an initialization procedure, which appears in the
299 -- package declaration that contains the type. It is also the case if
300 -- the body has already been analyzed. Finally, if the unit enclosing
301 -- E is an instance, the instance body will be analyzed in any case,
302 -- and there is no need to add the enclosing unit (whose body might not
305 -- Library-level functions must be handled specially, because there is
306 -- no enclosing package to retrieve. In this case, it is the body of
307 -- the function that will have to be loaded.
309 if not Is_Abstract (E) and then not Is_Nested (E)
310 and then Convention (E) /= Convention_Protected
315 and then Ekind (Pack) = E_Package
318 Comp_Unit := Parent (Pack);
320 if Pack = Standard_Standard then
322 -- Library-level inlined function. Add function iself to
323 -- list of needed units.
325 Inlined_Bodies.Increment_Last;
326 Inlined_Bodies.Table (Inlined_Bodies.Last) := E;
328 elsif Is_Generic_Instance (Pack) then
331 elsif not Is_Inlined (Pack)
332 and then not Has_Completion (E)
333 and then not Scope_In_Main_Unit (Pack)
335 Set_Is_Inlined (Pack);
336 Inlined_Bodies.Increment_Last;
337 Inlined_Bodies.Table (Inlined_Bodies.Last) := Pack;
341 end Add_Inlined_Body;
343 ----------------------------
344 -- Add_Inlined_Subprogram --
345 ----------------------------
347 procedure Add_Inlined_Subprogram (Index : Subp_Index) is
348 E : constant Entity_Id := Inlined.Table (Index).Name;
353 -- Insert the current subprogram in the list of inlined subprograms
355 if not Scope_In_Main_Unit (E)
356 and then Is_Inlined (E)
357 and then not Is_Nested (E)
358 and then not Has_Initialized_Type (E)
360 if No (Last_Inlined) then
361 Set_First_Inlined_Subprogram (Cunit (Main_Unit), E);
363 Set_Next_Inlined_Subprogram (Last_Inlined, E);
369 Inlined.Table (Index).Listed := True;
370 Succ := Inlined.Table (Index).First_Succ;
372 while Succ /= No_Succ loop
373 Subp := Successors.Table (Succ).Subp;
374 Inlined.Table (Subp).Count := Inlined.Table (Subp).Count - 1;
376 if Inlined.Table (Subp).Count = 0 then
377 Add_Inlined_Subprogram (Subp);
380 Succ := Successors.Table (Succ).Next;
382 end Add_Inlined_Subprogram;
384 ------------------------
385 -- Add_Scope_To_Clean --
386 ------------------------
388 procedure Add_Scope_To_Clean (Inst : Entity_Id) is
390 Scop : Entity_Id := Enclosing_Dynamic_Scope (Inst);
393 -- If the instance appears in a library-level package declaration,
394 -- all finalization is global, and nothing needs doing here.
396 if Scop = Standard_Standard then
400 Elmt := First_Elmt (To_Clean);
402 while Present (Elmt) loop
404 if Node (Elmt) = Scop then
408 Elmt := Next_Elmt (Elmt);
411 Append_Elmt (Scop, To_Clean);
412 end Add_Scope_To_Clean;
418 function Add_Subp (E : Entity_Id) return Subp_Index is
419 Index : Subp_Index := Subp_Index (E) mod Num_Hash_Headers;
423 -- Initialize entry in Inlined table.
425 procedure New_Entry is
427 Inlined.Increment_Last;
428 Inlined.Table (Inlined.Last).Name := E;
429 Inlined.Table (Inlined.Last).First_Succ := No_Succ;
430 Inlined.Table (Inlined.Last).Count := 0;
431 Inlined.Table (Inlined.Last).Listed := False;
432 Inlined.Table (Inlined.Last).Main_Call := False;
433 Inlined.Table (Inlined.Last).Next := No_Subp;
434 Inlined.Table (Inlined.Last).Next_Nopred := No_Subp;
437 -- Start of processing for Add_Subp
440 if Hash_Headers (Index) = No_Subp then
442 Hash_Headers (Index) := Inlined.Last;
446 J := Hash_Headers (Index);
448 while J /= No_Subp loop
450 if Inlined.Table (J).Name = E then
454 J := Inlined.Table (J).Next;
458 -- On exit, subprogram was not found. Enter in table. Index is
459 -- the current last entry on the hash chain.
462 Inlined.Table (Index).Next := Inlined.Last;
467 ----------------------------
468 -- Analyze_Inlined_Bodies --
469 ----------------------------
471 procedure Analyze_Inlined_Bodies is
478 Analyzing_Inlined_Bodies := False;
480 if Serious_Errors_Detected = 0 then
481 New_Scope (Standard_Standard);
484 while J <= Inlined_Bodies.Last
485 and then Serious_Errors_Detected = 0
487 Pack := Inlined_Bodies.Table (J);
490 and then Scope (Pack) /= Standard_Standard
491 and then not Is_Child_Unit (Pack)
493 Pack := Scope (Pack);
496 Comp_Unit := Parent (Pack);
498 while Present (Comp_Unit)
499 and then Nkind (Comp_Unit) /= N_Compilation_Unit
501 Comp_Unit := Parent (Comp_Unit);
504 -- Load the body, unless it the main unit, or is an instance
505 -- whose body has already been analyzed.
507 if Present (Comp_Unit)
508 and then Comp_Unit /= Cunit (Main_Unit)
509 and then Body_Required (Comp_Unit)
510 and then (Nkind (Unit (Comp_Unit)) /= N_Package_Declaration
511 or else No (Corresponding_Body (Unit (Comp_Unit))))
514 Bname : constant Unit_Name_Type :=
515 Get_Body_Name (Get_Unit_Name (Unit (Comp_Unit)));
520 if not Is_Loaded (Bname) then
521 Load_Needed_Body (Comp_Unit, OK);
524 Error_Msg_Unit_1 := Bname;
526 ("one or more inlined subprograms accessed in $!",
529 Get_File_Name (Bname, Subunit => False);
530 Error_Msg_N ("\but file{ was not found!", Comp_Unit);
531 raise Unrecoverable_Error;
540 -- The analysis of required bodies may have produced additional
541 -- generic instantiations. To obtain further inlining, we perform
542 -- another round of generic body instantiations. Establishing a
543 -- fully recursive loop between inlining and generic instantiations
544 -- is unlikely to yield more than this one additional pass.
548 -- The list of inlined subprograms is an overestimate, because
549 -- it includes inlined functions called from functions that are
550 -- compiled as part of an inlined package, but are not themselves
551 -- called. An accurate computation of just those subprograms that
552 -- are needed requires that we perform a transitive closure over
553 -- the call graph, starting from calls in the main program. Here
554 -- we do one step of the inverse transitive closure, and reset
555 -- the Is_Called flag on subprograms all of whose callers are not.
557 for Index in Inlined.First .. Inlined.Last loop
558 S := Inlined.Table (Index).First_Succ;
561 and then not Inlined.Table (Index).Main_Call
563 Set_Is_Called (Inlined.Table (Index).Name, False);
565 while S /= No_Succ loop
568 (Inlined.Table (Successors.Table (S).Subp).Name)
569 or else Inlined.Table (Successors.Table (S).Subp).Main_Call
571 Set_Is_Called (Inlined.Table (Index).Name);
575 S := Successors.Table (S).Next;
580 -- Now that the units are compiled, chain the subprograms within
581 -- that are called and inlined. Produce list of inlined subprograms
582 -- sorted in topological order. Start with all subprograms that
583 -- have no prerequisites, i.e. inlined subprograms that do not call
584 -- other inlined subprograms.
586 for Index in Inlined.First .. Inlined.Last loop
588 if Is_Called (Inlined.Table (Index).Name)
589 and then Inlined.Table (Index).Count = 0
590 and then not Inlined.Table (Index).Listed
592 Add_Inlined_Subprogram (Index);
596 -- Because Add_Inlined_Subprogram treats recursively nodes that have
597 -- no prerequisites left, at the end of the loop all subprograms
598 -- must have been listed. If there are any unlisted subprograms
599 -- left, there must be some recursive chains that cannot be inlined.
601 for Index in Inlined.First .. Inlined.Last loop
602 if Is_Called (Inlined.Table (Index).Name)
603 and then Inlined.Table (Index).Count /= 0
604 and then not Is_Predefined_File_Name
606 (Get_Source_Unit (Inlined.Table (Index).Name)))
609 ("& cannot be inlined?", Inlined.Table (Index).Name);
610 -- A warning on the first one might be sufficient.
616 end Analyze_Inlined_Bodies;
618 --------------------------------
619 -- Check_Body_For_Inlining --
620 --------------------------------
622 procedure Check_Body_For_Inlining (N : Node_Id; P : Entity_Id) is
623 Bname : Unit_Name_Type;
628 if Is_Compilation_Unit (P)
629 and then not Is_Generic_Instance (P)
631 Bname := Get_Body_Name (Get_Unit_Name (Unit (N)));
632 E := First_Entity (P);
634 while Present (E) loop
635 if Has_Pragma_Inline (E) then
636 if not Is_Loaded (Bname) then
637 Load_Needed_Body (N, OK);
640 and then Ineffective_Inline_Warnings
642 Error_Msg_Unit_1 := Bname;
644 ("unable to inline subprograms defined in $?", P);
645 Error_Msg_N ("\body not found?", P);
656 end Check_Body_For_Inlining;
662 procedure Cleanup_Scopes is
668 Elmt := First_Elmt (To_Clean);
670 while Present (Elmt) loop
673 if Ekind (Scop) = E_Entry then
674 Scop := Protected_Body_Subprogram (Scop);
677 if Ekind (Scop) = E_Block then
678 Decl := Parent (Block_Node (Scop));
681 Decl := Unit_Declaration_Node (Scop);
683 if Nkind (Decl) = N_Subprogram_Declaration
684 or else Nkind (Decl) = N_Task_Type_Declaration
685 or else Nkind (Decl) = N_Subprogram_Body_Stub
687 Decl := Unit_Declaration_Node (Corresponding_Body (Decl));
692 Expand_Cleanup_Actions (Decl);
695 Elmt := Next_Elmt (Elmt);
699 --------------------------
700 -- Has_Initialized_Type --
701 --------------------------
703 function Has_Initialized_Type (E : Entity_Id) return Boolean is
704 E_Body : constant Node_Id := Get_Subprogram_Body (E);
708 if No (E_Body) then -- imported subprogram
712 Decl := First (Declarations (E_Body));
714 while Present (Decl) loop
716 if Nkind (Decl) = N_Full_Type_Declaration
717 and then Present (Init_Proc (Defining_Identifier (Decl)))
727 end Has_Initialized_Type;
733 procedure Initialize is
735 Analyzing_Inlined_Bodies := False;
736 Pending_Descriptor.Init;
737 Pending_Instantiations.Init;
742 for J in Hash_Headers'Range loop
743 Hash_Headers (J) := No_Subp;
747 ------------------------
748 -- Instantiate_Bodies --
749 ------------------------
751 -- Generic bodies contain all the non-local references, so an
752 -- instantiation does not need any more context than Standard
753 -- itself, even if the instantiation appears in an inner scope.
754 -- Generic associations have verified that the contract model is
755 -- satisfied, so that any error that may occur in the analysis of
756 -- the body is an internal error.
758 procedure Instantiate_Bodies is
760 Info : Pending_Body_Info;
763 if Serious_Errors_Detected = 0 then
765 Expander_Active := (Operating_Mode = Opt.Generate_Code);
766 New_Scope (Standard_Standard);
767 To_Clean := New_Elmt_List;
769 if Is_Generic_Unit (Cunit_Entity (Main_Unit)) then
773 -- A body instantiation may generate additional instantiations, so
774 -- the following loop must scan to the end of a possibly expanding
775 -- set (that's why we can't simply use a FOR loop here).
779 while J <= Pending_Instantiations.Last
780 and then Serious_Errors_Detected = 0
783 Info := Pending_Instantiations.Table (J);
785 -- If the instantiation node is absent, it has been removed
786 -- as part of unreachable code.
788 if No (Info.Inst_Node) then
791 elsif Nkind (Info. Act_Decl) = N_Package_Declaration then
792 Instantiate_Package_Body (Info);
793 Add_Scope_To_Clean (Defining_Entity (Info.Act_Decl));
796 Instantiate_Subprogram_Body (Info);
802 -- Reset the table of instantiations. Additional instantiations
803 -- may be added through inlining, when additional bodies are
806 Pending_Instantiations.Init;
808 -- We can now complete the cleanup actions of scopes that contain
809 -- pending instantiations (skipped for generic units, since we
810 -- never need any cleanups in generic units).
811 -- pending instantiations.
814 and then not Is_Generic_Unit (Main_Unit_Entity)
818 -- Also generate subprogram descriptors that were delayed
820 for J in Pending_Descriptor.First .. Pending_Descriptor.Last loop
822 Ent : constant Entity_Id := Pending_Descriptor.Table (J);
825 if Is_Subprogram (Ent) then
826 Generate_Subprogram_Descriptor_For_Subprogram
827 (Get_Subprogram_Body (Ent), Ent);
829 elsif Ekind (Ent) = E_Package then
830 Generate_Subprogram_Descriptor_For_Package
831 (Parent (Declaration_Node (Ent)), Ent);
833 elsif Ekind (Ent) = E_Package_Body then
834 Generate_Subprogram_Descriptor_For_Package
835 (Declaration_Node (Ent), Ent);
840 elsif Is_Generic_Unit (Cunit_Entity (Main_Unit)) then
846 end Instantiate_Bodies;
852 function Is_Nested (E : Entity_Id) return Boolean is
853 Scop : Entity_Id := Scope (E);
856 while Scop /= Standard_Standard loop
857 if Ekind (Scop) in Subprogram_Kind then
860 elsif Ekind (Scop) = E_Task_Type
861 or else Ekind (Scop) = E_Entry
862 or else Ekind (Scop) = E_Entry_Family then
866 Scop := Scope (Scop);
878 Pending_Instantiations.Locked := True;
879 Inlined_Bodies.Locked := True;
880 Successors.Locked := True;
881 Inlined.Locked := True;
882 Pending_Instantiations.Release;
883 Inlined_Bodies.Release;
888 --------------------------
889 -- Remove_Dead_Instance --
890 --------------------------
892 procedure Remove_Dead_Instance (N : Node_Id) is
898 while J <= Pending_Instantiations.Last loop
900 if Pending_Instantiations.Table (J).Inst_Node = N then
901 Pending_Instantiations.Table (J).Inst_Node := Empty;
907 end Remove_Dead_Instance;
909 ------------------------
910 -- Scope_In_Main_Unit --
911 ------------------------
913 function Scope_In_Main_Unit (Scop : Entity_Id) return Boolean is
915 S : Entity_Id := Scop;
916 Ent : Entity_Id := Cunit_Entity (Main_Unit);
919 -- The scope may be within the main unit, or it may be an ancestor
920 -- of the main unit, if the main unit is a child unit. In both cases
921 -- it makes no sense to process the body before the main unit. In
922 -- the second case, this may lead to circularities if a parent body
923 -- depends on a child spec, and we are analyzing the child.
925 while Scope (S) /= Standard_Standard
926 and then not Is_Child_Unit (S)
934 and then Nkind (Comp) /= N_Compilation_Unit
936 Comp := Parent (Comp);
939 if Is_Child_Unit (Ent) then
942 and then Is_Child_Unit (Ent)
944 if Scope (Ent) = S then
953 Comp = Cunit (Main_Unit)
954 or else Comp = Library_Unit (Cunit (Main_Unit));
955 end Scope_In_Main_Unit;