home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek Gadgets 1
/
ADE-1.bin
/
ade-dist
/
gnat-2.06-src.tgz
/
tar.out
/
fsf
/
gnat
/
ada
/
exp_intr.adb
< prev
next >
Wrap
Text File
|
1996-09-28
|
9KB
|
229 lines
------------------------------------------------------------------------------
-- --
-- GNAT COMPILER COMPONENTS --
-- --
-- E X P _ I N T R --
-- --
-- B o d y --
-- --
-- $Revision: 1.17 $ --
-- --
-- Copyright (c) 1992,1993,1994,1995 NYU, All Rights Reserved --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
-- ware Foundation; either version 2, or (at your option) any later ver- --
-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
-- for more details. You should have received a copy of the GNU General --
-- Public License distributed with GNAT; see file COPYING. If not, write --
-- to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. --
-- --
------------------------------------------------------------------------------
with Atree; use Atree;
with Einfo; use Einfo;
with Exp_Ch7; use Exp_Ch7;
with Exp_Fixd; use Exp_Fixd;
with Exp_Util; use Exp_Util;
with Nmake; use Nmake;
with Nlists; use Nlists;
with Rtsfind; use Rtsfind;
with Sem; use Sem;
with Sem_Util; use Sem_Util;
with Sinfo; use Sinfo;
with Snames; use Snames;
with Stand; use Stand;
with Tbuild; use Tbuild;
package body Exp_Intr is
-----------------------
-- Local Subprograms --
-----------------------
procedure Expand_Shift (N : Node_Id; E : Entity_Id; K : Node_Kind);
-- Expand an intrinsic shift operation, N and E are from the call to
-- Expand_Instrinsic_Call (call node and subprogram spec entity) and
-- K is the kind for the shift node
procedure Expand_Unc_Conversion (N : Node_Id; E : Entity_Id);
-- Expand a call to an instantiation of Unchecked_Convertion into a node
-- N_Unchecked_Type_Conversion.
procedure Expand_Unc_Deallocation (N : Node_Id; E : Entity_Id);
-- Expand a call to an instantiation of Unchecked_Deallocation into a node
-- N_Free_Statement and appropriate context.
----------------------------
-- Expand_Instrinsic_Call --
----------------------------
procedure Expand_Intrinsic_Call (N : Node_Id; E : Entity_Id) is
Nam : Name_Id;
begin
-- If the intrinsic subprogram is generic, gets its original name.
if Present (Parent (E))
and then Present (Generic_Parent (Parent (E)))
then
Nam := Chars (Generic_Parent (Parent (E)));
else
Nam := Chars (E);
end if;
if Nam = Name_Divide then
Expand_Decimal_Divide_Call (N);
elsif Nam = Name_Rotate_Left then
Expand_Shift (N, E, N_Op_Rotate_Left);
elsif Nam = Name_Rotate_Right then
Expand_Shift (N, E, N_Op_Rotate_Right);
elsif Nam = Name_Shift_Left then
Expand_Shift (N, E, N_Op_Shift_Left);
elsif Nam = Name_Shift_Right then
Expand_Shift (N, E, N_Op_Shift_Right);
elsif Nam = Name_Shift_Right_Arithmetic then
Expand_Shift (N, E, N_Op_Shift_Right_Arithmetic);
elsif Nam = Name_Unchecked_Conversion then
Expand_Unc_Conversion (N, E);
elsif Nam = Name_Unchecked_Deallocation then
Expand_Unc_Deallocation (N, E);
else
-- If the entity is a renaming, expand the call to the original
-- operation (which must be intrinsic).
pragma Assert (Present (Alias (E)));
Expand_Intrinsic_Call (N, Alias (E));
end if;
end Expand_Intrinsic_Call;
------------------
-- Expand_Shift --
------------------
-- This procedure is used to convert a call to a shift function to the
-- corresponding operator node. This conversion is not done by the usual
-- circuit for converting calls to operator functions (e.g. "+"(1,2)) to
-- operator nodes, because shifts are not predefined operators.
-- As a result, whenever a shift is used in the source program, it will
-- remain as a call until converted by this routine to the operator node
-- form which Gigi is expecting to see.
-- Note: it is possible for the expander to generate shift operator nodes
-- directly, which will be analyzed in the normal manner by calling Analyze
-- and Resolve. Such shift operator nodes will not be seen by Expand_Shift.
procedure Expand_Shift (N : Node_Id; E : Entity_Id; K : Node_Kind) is
Loc : constant Source_Ptr := Sloc (N);
Typ : constant Entity_Id := Etype (N);
Left : constant Node_Id := First_Actual (N);
Right : constant Node_Id := Next_Actual (Left);
Snode : Node_Id;
begin
Snode := New_Node (K, Loc);
Set_Left_Opnd (Snode, Relocate_Node (Left));
Set_Right_Opnd (Snode, Relocate_Node (Right));
Set_Chars (Snode, Chars (E));
Set_Etype (Snode, Base_Type (Typ));
Set_Entity (Snode, E);
-- Do the replacement. Note that we don't call Analyze and Resolve
-- on this node, because it already got analyzed and resolved when
-- it was a function call!
Replace_Substitute_Tree (N, Snode);
Set_Analyzed (N);
end Expand_Shift;
---------------------------
-- Expand_Unc_Conversion --
---------------------------
procedure Expand_Unc_Conversion (N : Node_Id; E : Entity_Id) is
Loc : constant Source_Ptr := Sloc (N);
begin
Replace_Substitute_Tree (N,
Make_Unchecked_Type_Conversion (Loc,
Subtype_Mark => New_Occurrence_Of (Etype (E), Loc),
Expression => Relocate_Node (First_Actual (N))));
Set_Etype (N, Etype (E));
Set_Analyzed (N);
end Expand_Unc_Conversion;
-----------------------------
-- Expand_Unc_Deallocation --
-----------------------------
-- Generate the following Code :
-- if Arg /= null then
--
-- <Finalize_Call> (Arg.all); -- for controlled types
-- Free (Arg);
-- Arg := Null;
-- end if;
procedure Expand_Unc_Deallocation (N : Node_Id; E : Entity_Id) is
use Multi_Use;
Loc : constant Source_Ptr := Sloc (N);
Arg : constant Node_Id := First_Actual (N);
Typ : constant Entity_Id := Etype (Arg);
Stmts : constant List_Id := New_List;
Desig_T : constant Entity_Id := Designated_Type (Typ);
E_Arg : Exp_Id;
Free_Node : Node_Id;
Exp : Node_Id;
begin
Multi_Use.New_Exp_Id (Arg, N, E_Arg);
if Controlled_Type (Desig_T) then
Append_List_To (Stmts,
Make_Final_Call (
Ref =>
Make_Explicit_Dereference (Loc, Multi_Use.New_Ref (E_Arg)),
Typ => Desig_T,
Flist_Ref => Find_Final_List (Typ),
With_Detach => New_Reference_To (Standard_True, Loc)));
end if;
Free_Node :=
Make_Free_Statement (Loc,
Expression => Multi_Use.New_Ref (E_Arg));
Set_Storage_Pool (Free_Node, Associated_Storage_Pool (Etype (Arg)));
if Present (Storage_Pool (Free_Node)) then
Set_Procedure_To_Call (Free_Node,
Find_Prim_Op (Etype (Storage_Pool (Free_Node)), Name_Deallocate));
end if;
Append_To (Stmts, Free_Node);
Append_To (Stmts,
Make_Assignment_Statement (Loc,
Name => Multi_Use.New_Ref (E_Arg),
Expression => Make_Null (Loc)));
Replace_Substitute_Tree (N,
Make_If_Statement (Loc,
Condition =>
Make_Op_Ne (Loc,
Left_Opnd => Multi_Use.New_Ref (E_Arg),
Right_Opnd => Make_Null (Loc)),
Then_Statements => Stmts));
Analyze (N);
end Expand_Unc_Deallocation;
end Exp_Intr;