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
/
sem_intr.adb
< prev
next >
Wrap
Text File
|
1996-09-28
|
8KB
|
234 lines
------------------------------------------------------------------------------
-- --
-- GNAT COMPILER COMPONENTS --
-- --
-- S E M _ I N T R --
-- --
-- B o d y --
-- --
-- $Revision: 1.8 $ --
-- --
-- Copyright (c) 1992,1993,1994 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. --
-- --
------------------------------------------------------------------------------
-- Processing for intrinsic subprogram declarations
with Atree; use Atree;
with Einfo; use Einfo;
with Errout; use Errout;
with Namet; use Namet;
with Sem_Ch13; use Sem_Ch13;
with Sem_Util; use Sem_Util;
with Sinfo; use Sinfo;
with Snames; use Snames;
with Stand; use Stand;
with Uintp; use Uintp;
package body Sem_Intr is
-----------------------
-- Local Subprograms --
-----------------------
procedure Check_Divide (E : Entity_Id; N : Node_Id);
-- Check intrinsic Divide subprogram. There must be four arguments,
-- and all four arguments must be decimal types. The first two
-- arguments must be mode IN, and the last two must be mode OUT.
procedure Check_Shift (E : Entity_Id; N : Node_Id);
-- Check intrinsic shift subprogram, the two arguments are the same
-- as for Check_Intrinsic_Subprogram (i.e. the entity of the subprogram
-- declaration, and the node for the pragma argument, used for messages)
procedure Errint (Msg : String; S : Node_Id; N : Node_Id);
-- Post error message for bad intrinsic, the message itself is posted
-- on the appropriate spec node and another message is placed on the
-- pragma itself, referring to the spec. S is the node in the spec on
-- which the message is to be placed, and N is the pragma argument node.
------------------
-- Check_Divide --
------------------
procedure Check_Divide (E : Entity_Id; N : Node_Id) is
Arg : Node_Id;
Nargs : Nat;
begin
if Ekind (E) /= E_Procedure
and then Ekind (E) /= E_Generic_Procedure
then
Errint ("intrinsic divide subprogram must be procedure", E, N);
return;
end if;
Arg := First_Formal (E);
Nargs := 0;
while Present (Arg) loop
Nargs := Nargs + 1;
if not Is_Decimal_Fixed_Point_Type (Etype (Arg)) then
Errint ("intrinsic divide argument must be decimal type", Arg, N);
return;
end if;
if (Nargs <= 2 and then Ekind (Arg) /= E_In_Parameter)
or else (Nargs > 2 and then Ekind (Arg) /= E_Out_Parameter)
then
Errint ("intrinsic divide argument has wrong mode", Arg, N);
end if;
Arg := Next_Formal (Arg);
end loop;
if Nargs /= 4 then
Errint ("wrong number of arguments for intrinsic divide", E, N);
end if;
-- All tests have passed, divide procedure can be marked intrinsic
Set_Is_Intrinsic_Subprogram (E);
end Check_Divide;
--------------------------------
-- Check_Intrinsic_Subprogram --
--------------------------------
procedure Check_Intrinsic_Subprogram (E : Entity_Id; N : Node_Id) is
Spec : constant Node_Id := Specification (Get_Declaration_Node (E));
Nam : Name_Id;
begin
if Present (Spec)
and then Present (Generic_Parent (Spec))
then
Nam := Chars (Generic_Parent (Spec));
else
Nam := Chars (E);
end if;
-- Simply ignore cases where name is an operator name
Get_Name_String (Nam);
if Name_Buffer (1) = 'O' then
return;
-- Shift cases
elsif Nam = Name_Rotate_Left
or else Nam = Name_Rotate_Right
or else Nam = Name_Shift_Left
or else Nam = Name_Shift_Right
or else Nam = Name_Shift_Right_Arithmetic
then
Check_Shift (E, N);
-- Unchecked conversion and deallocation, no further processing needed
elsif Nam = Name_Unchecked_Conversion
and then Ekind (E) = E_Generic_Function
then
null;
elsif Nam = Name_Unchecked_Deallocation then
null;
-- Case of Divide routine in package Decimal
elsif Nam = Name_Divide then
Check_Divide (E, N);
-- For now, no other intrinsic subprograms are recognized
else
Errint ("unrecognized intrinsic subprogram", E, N);
end if;
end Check_Intrinsic_Subprogram;
-----------------
-- Check_Shift --
-----------------
procedure Check_Shift (E : Entity_Id; N : Node_Id) is
Arg1 : Node_Id;
Arg2 : Node_Id;
Size : Nat;
begin
if Ekind (E) /= E_Function
and then Ekind (E) /= E_Generic_Function
then
Errint ("intrinsic shift subprogram must be a function", E, N);
return;
end if;
Arg1 := First_Formal (E);
if Present (Arg1) then
Arg2 := Next_Formal (Arg1);
else
Arg2 := Empty;
end if;
if Arg1 = Empty or else Arg2 = Empty then
Errint ("intrinsic shift function must have two arguments", E, N);
return;
end if;
if not Is_Integer_Type (Etype (Arg1)) then
Errint ("first argument to shift must be integer type", Arg1, N);
return;
end if;
if Etype (Arg2) /= Standard_Natural then
Errint ("second argument to shift must be type Natural", Arg2, N);
return;
end if;
Size := UI_To_Int (Esize (Etype (Arg1)));
if Size /= 8
and then Size /= 16
and then Size /= 32
and then Size /= 64
then
Errint
("first argument for shift must have size 8, 16, 32 or 64",
Parameter_Type (Arg1), N);
return;
elsif Etype (Arg1) /= Etype (E) then
Errint
("return type of shift must match first argument", E, N);
return;
end if;
-- All tests have passed, shift function can be marked intrinsic
Set_Is_Intrinsic_Subprogram (E);
end Check_Shift;
------------
-- Errint --
------------
procedure Errint (Msg : String; S : Node_Id; N : Node_Id) is
begin
Error_Msg_N (Msg, S);
Error_Msg_N ("incorrect intrinsic subprogram, see spec", N);
end Errint;
end Sem_Intr;